Hi3518EV200进行H264编码时对VENC的基本设置

〇、文档说明

本文性质为个人学习笔记。
由于项目需要,基于Hi3518EV200平台进行H264编码,在此过程中涉及到对VENC的控制和理解,记录以备忘。
另外,如果您在学习hi3518编码h264的过程中有疑惑,希望我的博文可以帮到您:
1.Hi3518EV200实现H264视频采集的源码及流程详解(不依赖SAMPLE库)
2.从零开始进行Hi3518_SDK安装、环境搭建和Linux内核编译,并生成可供烧写的uImage
期待如今的我和未来的你,一起进步!

一、VENC(Video Encoder,视频编码模块)

VENC的相关内容,无论是网上还是手册中都已经介绍的非常详细了,但是对于一个学习的人而言,应当考虑的是如何将这些东西转化为自己的理解,而理解的最好过程就是用自己的语言讲出来。
VENC的学习,先从了解它的作用开始。下文描述、举例、现象等均在Hi3518EV200平台进行,MPP[Hi3518EV200_MPP_V1.0.4.0 B050 Release]
视频流从sensor到输出是这样的:
VI(sensor-ISP-ViDev0-Chn[0]/Ext_Chn[1-16])–VPSS(Group-Chn[(在线)0/(离线)0-31]/Ext_Chn[4-11])–VENC(Chn[0-15],Payload[H264/H265/JPEG],RC[CBR/VBR/AVBR/FIXQP])–输出
上面这个流程涵盖了几乎所有基本配置内容,其中通道数的限制都是基于手册查找。VENC在整个编码过程中可以干的事情有:关于通道有效荷载的编码协议选择、编码码率控制。我们所有针对VENC的设置都是围绕这两方面进行。

二、VENC设置步骤

VENC部分需要完成的设置一共有三项:
1.1选择要编码的编码方式,照着该编码方式配置相应结构体;
1.2按照所选择的编码方式的不同,配置与其对应的码流控制参数结构体;
2.按照上述的配置创建VENC通道;
3.启动通道的图像接收并绑定前级模块。

    VENC_CHN VencChn=0;                 //选择VENC通道号——0
    PAYLOAD_TYPE_E enPayLoad=PT_H264;   //选择编码方式——H264,更换编码要同时更换后面的设置参数
    VENC_CHN_ATTR_S stVencChnAttr;      //VENC通道属性参数结构体
    VENC_ATTR_H264_S stH264Attr;        //H264属性参数结构体
    VENC_ATTR_H264_CBR_S stH264Cbr;     //H264-CBR码率控制参数结构体
    SIZE_S stPicSize;                   //图像尺寸信息变量
    stPicSize.u32Width=1920;            //设置图像宽度
    stPicSize.u32Height=1080;           //设置图像高度
    HI_U32 u32Profile=0;                //0: baseline; 1:MP; 2:HP;3:Svc_t

    //--1--创建VENC通道
    stVencChnAttr.stVeAttr.enType=enPayLoad;
    if(enPayLoad==PT_H264)//在编码为H264的时候执行,换编码方式在此处
    {
        stH264Attr.u32MaxPicWidth=stPicSize.u32Width;  //设置最大图像宽度
        stH264Attr.u32MaxPicHeight=stPicSize.u32Height;//设置最大图像高度
        stH264Attr.u32PicWidth=stPicSize.u32Width;     //设置图像宽度
        stH264Attr.u32PicHeight=stPicSize.u32Height;   //设置图像高度
        stH264Attr.u32BufSize=stPicSize.u32Width * stPicSize.u32Height;//流缓冲器大小
        stH264Attr.u32Profile=u32Profile;              /*0: baseline; 1:MP; 2:HP;  3:svc_t */
        stH264Attr.bByFrame=HI_TRUE;                   //获取流模式是切片模式还是帧模式?
        stH264Attr.u32BFrameNum=0;                     //0: 不支持B帧; >=1:B帧的数量
        stH264Attr.u32RefNum=1;                        //0: 默认; >=0:参考帧数量
        memcpy(&stVencChnAttr.stVeAttr.stAttrH264e, &stH264Attr, sizeof(VENC_ATTR_H264_S));
        //选择编码码率控制方式——CBR
        {
            stVencChnAttr.stRcAttr.enRcMode=VENC_RC_MODE_H264CBR;
            stH264Cbr.u32Gop         =30;//图像组:I帧间间隔
            stH264Cbr.u32StatTime    =1; //码率统计时间
            stH264Cbr.u32SrcFrmRate  =30;//输入(VI)帧率
            stH264Cbr.fr32DstFrmRate =30;//输出帧率
            //下面的定义需要根据传感器分辨率修改
            stH264Cbr.u32BitRate=1024*2;
            stH264Cbr.u32FluctuateLevel=0;//平均比特率
            memcpy(&stVencChnAttr.stRcAttr.stAttrH264Cbr, &stH264Cbr, sizeof(VENC_ATTR_H264_CBR_S));
        }
    }
    s32Ret=HI_MPI_VENC_CreateChn(VencChn, &stVencChnAttr);//创建VENC通道
    
    //--2--启动接收VENC图像
    s32Ret=HI_MPI_VENC_StartRecvPic(VencChn);
    
    //--3--绑定VPSS和VENC
    MPP_CHN_S stSrcChn;  //源通道设备参数结构体
    MPP_CHN_S stDestChn; //目的通道设备参数结构体
    stSrcChn.enModId=HI_ID_VPSS;
    stSrcChn.s32DevId=0; //选择VPSS组号——0
    stSrcChn.s32ChnId=0; //选择VPSS通道号——0
    stDestChn.enModId=HI_ID_VENC;
    stDestChn.s32DevId=0;
    stDestChn.s32ChnId=0;//选择VENC通道号——0
    s32Ret=HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);//绑定源通道和目的通道

三、相关设置项说明

1.VENC的图像缩放

参考《HiMPP IPC V2.0 媒体处理软件开发参考》(下文称“手册”)521页,通道接收到图像之后,比较图像尺寸和编码通道尺寸:如果输入图像比编码通道尺寸大,VENC将按照编码通道尺寸大小,调用VGS对源图像进行缩小,然后对缩小之后的图像进行编码。如果输入图像比编码通道尺寸小,VENC丢弃源图像。VENC不支持放大输入图像编码。如果输入图像与编码通道尺寸相当,VENC直接接受源图像,进行编码。
也就是说,VENC模块只支持原比例编码或者缩小,但不支持放大,如果设置的编码宽高大于输入图像的宽高,则会产生错误
VENC输出的图像宽高在stH264Attr.u32PicWidth和stH264Attr.u32PicHeight两个变量进行设置。
对于编码器宽高取值的限制在手册535页:
编码器属性最大宽高,通道宽高必须满足如下约束:
− MaxPicWidth∈[MIN_WIDTH, MAX_WIDTH]
− MaxPicHeight∈[MIN_HEIGHT, MAX_HEIGHT]
− PicWidth∈[MIN_WIDTH, MAX_WIDTH]
− PicHeight∈[MIN_HEIGHT, MAX_HEIGHT]
− 最大宽高,通道宽高必须是MIN_ALIGN的整数倍。
其中MIN_WIDTH,MAX_WIDTH,MIN_HEIGHT,MAX_HEIGHT,MIN_ALIGN分别表示编码通道支持的最小宽度,最大宽度,最小高度,最大高度,最小对齐单元(像素)。
芯片相关编码通道差异
另外,在手册774也中对宽高的属性也做了说明:
编码器属性中除通道宽高(u32PicWidth和u32PicHeight)外都是静态属性,一旦创建编码通道成功,静态属性不支持被修改,除非该通道被销毁,重新创建。
这说明在通道建立成功后,可以在程序运行过程中动态地修改编码宽、高

2.VENC帧率控制

VENC作为编码的模块,自然有能力决定编码产生的帧率大小,对帧率的设置在码率参数结构体中进行:
stH264Cbr.u32SrcFrmRate表示从前级模块(VI或VPSS)传来的视频图像的帧率,一般我们在设置VPSS模块的时候不开启它的帧率控制,例如芯片SAMPLE例程库中进行的那样,此时从VPSS模块传来的图像帧率就是VI模块输出的图像帧率。
VI模块的帧率设置分为两部分,一是sensor向ISP注册时传入的帧率参数,这个帧率是sensor支持的帧率,是不一定能任意修改的;二是VI物理通道设置的帧率控制,这个在SAMPLE库中也没有进行设置。所以我们不妨也按照这种方法进行,即对帧率的修改放在VENC模块上。
此时传给VENC模块的源帧率就是sensor支持得到的最大值,假设是30fps,我们只需要设置目的帧率stH264Cbr.fr32DstFrmRate变量即可完成帧率控制。
但是实际的情况要是都这么简单就好了。
按照手册951页的说法,我给翻译翻译,就是说VENC的帧率控制分为两种情况,分别为“增帧”或者“减帧/不控制”。
在增帧模式下,要设置的是u32SrcFrmRate成员,假设前级传来的帧率是30fps,我想要60fps,那就应该设置u32SrcFrmRate=60,fr32DstFrmRate=60;
在减帧或者不控制的情况下,源帧率要设置成产生时间参考的实际帧率,此时要区分在线模式或者离线模式,关于离线模式和在线模式的说明可以参考手册32页。这里如果我们在VI/VPSS前级模块没有进行任何帧率控制,那么u32SrcFrmRate就是VI的帧率(sensor帧率)。目的帧率fr32DstFrmRate的设置分为两种,一是目标帧率为整数,此时fr32DstFrmRate设置为整数即可,例如25帧(每秒25帧);二是目标帧率为分数,例如每两秒25帧(每秒25/2帧),则fr32DstFrmRate=(2<<16)+25。

3.GOP设置

声明: 本节参考了https://blog.csdn.net/xiaoyida11/article/details/52852398
GOP设置由u32Gop成员确定,其目的是定义视频编码帧中的I帧间间隔,如果设置编码码流帧配置模式为多包模式(参考手册527页),那么可以发现,I帧会分为4个小包,其中第四包为数据包。下图为设置GOP为30时的编码流情况:
gop=30rc(gop=30)
u32Gop成员即决定了I帧和I帧之间间隔包计数。顺便提一嘴,B帧的编码有前文程序中的stH264Attr.u32BFrameNum变量确定,参考例程,已经给关了。
如果希望I帧出现在每秒编码帧的首包,则应该将u32Gop设置为目的帧率。下图为设置u32Gop=fr32DstFrmRate=10的编码输出情况。
gop=10
暂时从项目中总结的就是这么多,以上。

四、阅读注意

1.在本记录中为了简便起见,删除了所有对函数返回值s32Ret的判断,在实际程序中应该对相应执行失败的函数做适当处理。
2.本文仅为个人学习记录,如直接套用或者言语不明造成经济损失等后果作者不承担责任,如需转载,请注明原作者及出处。
————2020-1-2 @燕卫博————

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值