关于DM368的H264视频编码过程(下)

关于DM368的H264视频编码过程(下) Tony 2023-06-30 10:11:29 834

上篇:关于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;
    }
}

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

五、后记

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

喵~!

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
Tony
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
Tony
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区