从零开始理解DM368的H264视频编码过程(下)

四、一些需要注意的问题和提示

色彩空间

在capture捕获线程中有一项设置叫色彩空间,colorspace 变量。色彩空间的定义在Dmai中的 ColorSpace.h 文件中:

/**
  * @brief Color formats.
  */
typedef enum {
    ColorSpace_NOTSET = -1,

    /**
      * @brief YUV 420 semi planar corresponding to V4L2_PIX_FMT_NV12 in v4l2.
      *        This format consists of two planes: one with the Y component
      *        and one with the CbCr components interleaved (hence semi).
      *        See the LSP documentation for a thorough description of this
      *        format.
      */
    ColorSpace_YUV420PSEMI = 0,

    /**
      * @brief YUV 422 semi planar corresponding to V4L2_PIX_FMT_YUV422UVP. This
      *        format was added to v4l2 by TI because the dm6467 VDCE and VPSS
      *        peripherals use this format. The format consists of two planes:
      *        one with the Y component and one with the CbCr components
      *        interleaved (hence semi) See the LSP VDCE documentation for a
      *        thorough description of this format.
      */
    ColorSpace_YUV422PSEMI,

    /** @brief YUV 422 interleaved corresponding to V4L2_PIX_FMT_UYVY in v4l2 */
    ColorSpace_UYVY,
    
    /** @brief RGB 888 packed corresponding to V4L2_PIX_FMT_RGB24 in v4l2 */
    ColorSpace_RGB888,

    /** @brief RGB 565 packed corresponding to V4L2_PIX_FMT_RGB565 in v4l2 */
    ColorSpace_RGB565,

    /**
      * @brief 2 bits per pixel. This is the format used by the VDCE for the
      *        bitmap while blending and is documented in the VDCE peripheral
      *        guide.
      */
    ColorSpace_2BIT,
    
    /**
      * @brief YUV 420 planar. The format consists of three planes:
      *        one with the Y component, one Cb, and one Cr component.
      */
    ColorSpace_YUV420P,
    
    /**
      * @brief YUV 422 planar. The format consists of three planes:
      *        one with the Y component, one Cb, and one Cr component.
      */
    ColorSpace_YUV422P,

    /**
      * @brief YUV 444 planar. The format consists of three planes:
      *        one with the Y component, one Cb, and one Cr component.
      */
    ColorSpace_YUV444P,
    
    /**
      * @brief Gray Scale. The format consist of single Luma plane
      *        ignoring the color plane components.      
      *             
      */
    ColorSpace_GRAY,

    ColorSpace_COUNT
} ColorSpace_Type;

支持的视频编码格式

在视频编码线程中支持的视频编码格式枚举变量在 VideoStd.h 文件中定义:

/** @brief Video standards */
typedef enum {
    VideoStd_AUTO = 0,      /**< Automatically select standard (if supported) */
    VideoStd_CIF,           /**< CIF @ 30 frames per second */
    VideoStd_SIF_NTSC,      /**< SIF @ 30 frames per second */
    VideoStd_SIF_PAL,       /**< SIF @ 25 frames per second */
    VideoStd_VGA,           /**< VGA (640x480) @ 60 frames per second */
    VideoStd_D1_NTSC,       /**< D1 NTSC @ 30 frames per second */
    VideoStd_D1_PAL,        /**< D1 PAL @ 25 frames per second */
    VideoStd_480P,          /**< D1 Progressive NTSC @ 60 frames per second */
    VideoStd_576P,          /**< D1 Progressive PAL @ 50 frames per second */
    VideoStd_720P_60,       /**< 720P @ 60 frames per second */
    VideoStd_720P_50,       /**< 720P @ 50 frames per second */
    VideoStd_720P_30,       /**< 720P @ 30 frames per second */
    VideoStd_1080I_30,      /**< 1080I @ 30 frames per second */
    VideoStd_1080I_25,      /**< 1080I @ 25 frames per second */
    VideoStd_1080P_30,      /**< 1080P @ 30 frames per second */
    VideoStd_1080P_25,      /**< 1080P @ 25 frames per second */
    VideoStd_1080P_24,      /**< 1080P @ 24 frames per second */
    VideoStd_QVGA,          /**< QVGA @ 30 frames per second */
    VideoStd_1080P_60,      /**< 1080P @ 60 frames per second */
    VideoStd_1080P_50,      /**< 1080P @ 50 frames per second */    
    VideoStd_1080I_60,      /**< 1080I @ 60 frames per second */    
    VideoStd_COUNT
} VideoStd_Type;

支持的视频输入源

支持的输入源枚举变量在 Capture.h 文件中定义:

/**
 * @brief       Video capture inputs.
 */
typedef enum {
    /** @brief S-Video video input */
    Capture_Input_SVIDEO = 0,

    /** @brief Composite video input */
    Capture_Input_COMPOSITE,

    /** @brief Component video input */
    Capture_Input_COMPONENT,

    /** @brief Camera/Imager card video input 
      * @remarks only applicable on DM368
      */
    Capture_Input_CAMERA,

    Capture_Input_COUNT
} Capture_Input;

Camera的更换

Dmai(达芬奇多媒体应用程序接口)中是调用V4L2库从系统中的video设备获取图像的。这一步可以在 Capture.c 文件中的 Capture_detectVideoStd 函数中得到证实:

/******************************************************************************
 * Capture_detectVideoStd
 ******************************************************************************/
Int Capture_detectVideoStd(Capture_Handle hCapture, VideoStd_Type *videoStdPtr,
                           Capture_Attrs *attrs)
{
    Int                failCount  =  0;
    Int                firstInput;
    Int                queryInput;
    struct v4l2_input  v4l2Input;
    v4l2_std_id        std;
    Int                input;
    Int                fd;
    Int                ret;

    assert(videoStdPtr);
    assert(attrs);

    /*
     * Initialize variables outside of variable declarations to suppress
     * "unused variable" warnings for platforms that don't use them.
     */
    Dmai_clear(v4l2Input);
    queryInput =  0;
    firstInput = -1;

    if (attrs->videoStd < 0 || attrs->videoStd > VideoStd_COUNT) {
        Dmai_err1("Invalid capture standard given (%d)\n", attrs->videoStd);
        return Dmai_EINVAL;
    }

    if (hCapture) {
        fd = hCapture->fd;
    }
    else {
        fd = open(attrs->captureDevice, O_RDWR, 0);

        if (fd == -1) {
            Dmai_err2("Cannot open %s (%s)\n", attrs->captureDevice,
                                               strerror(errno));
            return Dmai_EFAIL;
        }
    }

    if (attrs->decoderIdx < 0) {
        v4l2Input.type = V4L2_INPUT_TYPE_CAMERA;
        v4l2Input.index = 0;
        do {
            if (ioctl(fd, VIDIOC_ENUMINPUT, &v4l2Input) != 0) {
                Dmai_err2("%s input not found (%s)\n",
                          captureInputString[attrs->videoInput], strerror(errno));
                return Dmai_EFAIL;
            }
            v4l2Input.index++;        
        } while (strcmp((Char *) v4l2Input.name,
                            captureInputString[attrs->videoInput]) != 0);
        input = --v4l2Input.index;

        Dmai_dbg1("%s input selected\n", v4l2Input.name);

    } else {
        input = attrs->decoderIdx;
    }

    if (ioctl(fd, VIDIOC_S_INPUT, &input) == -1) {
        Dmai_err2("Failed to set video input to %d (%s)\n", 
            input, strerror(errno));
        return Dmai_EFAIL;
    }

    if (ioctl(fd, VIDIOC_G_INPUT, &queryInput) == -1) {
        Dmai_err0("Failed to retrieve video input setting\n");
        return Dmai_EFAIL;
    }

    if (input != queryInput) {
        Dmai_dbg2("Attempted to set video input to %d, but it still has a"
                  "setting of %d\n", input, queryInput);
        return Dmai_EFAIL;
    }

    if (attrs->videoStd != VideoStd_AUTO) {
        /* Force video standard */
        std = stds[attrs->videoStd];
    } else {
        Dmai_dbg0("Checking video standard\n");

        /* It might take a few tries to detect the signal */
        do {
            ret = ioctl(fd, VIDIOC_QUERYSTD, &std);

            if (ret == -1 && errno == EAGAIN) {
                usleep(1);
                failCount++;
            }
        } while (ret == -1 && errno == EAGAIN && failCount < NUM_IOCTL_RETRIES);

        if (ret == -1) {
            Dmai_err1("VIDIOC_QUERYSTD failed on %s. Video input connected?\n",
                      attrs->captureDevice);
            return Dmai_EFAIL;
        }
    }

    if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {
        Dmai_err2("VIDIOC_S_STD failed on %s (%s)\n",
                  attrs->captureDevice, strerror(errno));
        return Dmai_EFAIL;
    }

    if (!hCapture) {
        close(fd);
    }

    if (std & V4L2_STD_NTSC) {
       *videoStdPtr = VideoStd_D1_NTSC;
    }
    else if (std & V4L2_STD_PAL) {
        *videoStdPtr = VideoStd_D1_PAL;
    }
    else if (std & V4L2_STD_525P_60) {
        *videoStdPtr = VideoStd_480P;
    }
    else if (std & V4L2_STD_625P_50) {
        *videoStdPtr = VideoStd_576P;
    }
    else if (std == V4L2_STD_720P_60) {
       *videoStdPtr = VideoStd_720P_60;
    }
    else if (std == V4L2_STD_720P_50) {
        *videoStdPtr = VideoStd_720P_50;
    }
#if 0
    else if (std == V4L2_STD_720P_30) {
        *videoStdPtr = VideoStd_720P_30;
    }
#endif
    else if (std == V4L2_STD_1080I_60) {
        *videoStdPtr = VideoStd_1080I_30;
    }
    else if (std == V4L2_STD_1080I_50) {
        *videoStdPtr = VideoStd_1080I_25;
    }
#if 0    
    else if (std == V4L2_STD_1080P_30) {
        *videoStdPtr = VideoStd_1080P_30;
    }
    else if (std == V4L2_STD_1080P_25) {
        *videoStdPtr = VideoStd_1080P_25;
    }
    else if (std == V4L2_STD_1080P_24) {
        *videoStdPtr = VideoStd_1080P_24;
    }
#endif
    else if (std == V4L2_STD_1080P_60) {
        *videoStdPtr = VideoStd_1080P_60;
    }
    else if (std == V4L2_STD_1080P_50) {
        *videoStdPtr = VideoStd_1080P_50;
    }        
    else {
        Dmai_err1("Unknown video standard on capture device %s\n",
                  attrs->captureDevice);
        return Dmai_EFAIL; 
    }

    attrs->videoStd = *videoStdPtr;
    Dmai_dbg2("Capture input set to %s:%d\n",
              captureInputString[attrs->videoInput], *videoStdPtr);

    return Dmai_EOK;
}

emmmm,函数有点长哈,总之,更换摄像头需要在linux内核中添加对新sensor的支持,且驱动要在V4L2框架下编写。不知道V4L2的请自行bing一下(因为我写累了)。

在DVSDK4_02_00_06中的Linux内核是2.6.32.17版本的,该内核支持的sensor非常有限,可以在 ./linux-2.6.32.17/drivers/media/video/ 中查看。

IDR帧

Dmai中,它比较皮,要是不设置,是不会产生IDR帧的。

在例程中,video线程处理部分,有这样的函数:

unsigned char idr_trigger = 0;//IDR帧触发变量
//IDR帧触发(这个判断在video的while中轮询)
		if(idr_trigger)
		{
				ForceIDR(hVe1, &dynParams, 1);
				idr_trigger=0;
		}

//修改产生IDR的设置
void ForceIDR(Venc1_Handle hVe1, VIDENC1_DynamicParams *dynParams, unsigned int idr)
{
	Int mystatus;
	VIDENC1_Status tEncStatus;
	VIDENC1_Handle enghandle = Venc1_getVisaHandle(hVe1);
	tEncStatus.size = sizeof(VIDENC1_Status);
	tEncStatus.data.buf = NULL;
	if(0 == idr)
	{
		dynParams->forceFrame = IVIDEO_NA_FRAME;
	}
	else
	{	
		dynParams->forceFrame = IVIDEO_IDR_FRAME;
	}
	mystatus = VIDENC1_control(enghandle, XDM_SETPARAMS, dynParams, &tEncStatus);
	if(mystatus != VIDENC1_EOK) 
	{
    	VIDENC1_delete(enghandle);
    	return;
	}
}

什么?没看到?那跟我没关系嗷。

五、后记

本人才疏学浅,千万别喷,谢谢,给你卖个萌嗷:

喵~!

————2020-2-8@燕卫博————

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值