Hi3518E官方录像例程源码流程分析(五)

源码地址 + 文档资料 – 提取码: chmr

本专栏分析的是mpp\venc\sample\sample_venc.c

Venc理论部分

在这里插入图片描述
VENC 模块由编码通道子模块(VENC)和编码协议子模块(H.264/H.265/JPEG/MJPEG)组成。

通道支持接收 YUV 格式图像输入,支持格式为 Semi-planar YUV 4:2:0 或 Semi-planar YUV 4:2:2,其中 H.264/H.265 只支持 Semi-planar YUV 4:2:0,JPEG/MJPEG 支持 Semi-planar YUV 4:2:0 或 Semi-planar YUV 4:2:2。另外,Hi3518EV200 能够支持单分量输入(只存在 Y 分量)。通道模块接收外部原始图像数据,而不关心图像数据是来自哪个外部模块。

通道接收到图像之后,比较图像尺寸和编码通道尺寸:

  • 如果输入图像比编码通道尺寸大,VENC 将按照编码通道尺寸大小,调用 VGS 对源图像进行缩小,然后对缩小之后的图像进行编码。
  • 如果输入图像比编码通道尺寸小,VENC 丢弃源图像。VENC 不支持放大输入图像编码。
  • 如果输入图像与编码通道尺寸相当,VENC 直接接受源图像,进行编码。

在这里插入图片描述

编码通道作为基本容器,保存编码通道的多种用户设置和管理编码通道的多种内部资源。编码通道完成图像转化为码流的功能,具体由码率控制器和编码器协同完成。这里的编码器指的是狭义上的编码器,只完成编码功能。码率控制器提供了对编码参数的控制和调整,从而对输出码率进行控制。

阶段五 开始视频流编码

	if(s32ChnNum >= 1)
	{
		VpssGrp = 0;
	    VpssChn = 0;
	    VencChn = 0;//bind VencChn0 to VpssChn0
	    s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad[0],\
	                                   gs_enNorm, enSize[0], enRcMode,u32Profile);
	    if (HI_SUCCESS != s32Ret)
	    {
	        SAMPLE_PRT("Start Venc failed!\n");
	        goto END_VENC_1080P_CLASSIC_5;
	    }
				 //bind VencChn0 to VpssChn0
	    s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);
	    if (HI_SUCCESS != s32Ret)
	    {
	        SAMPLE_PRT("Start Venc failed!\n");
	        goto END_VENC_1080P_CLASSIC_5;
	    }
	}

SAMPLE_COMM_VENC_Start()

s32Ret = SAMPLE_COMM_SYS_GetPicSize(enNorm, enSize, &stPicSize);

首先是前面出现过很多次的GetPicSize,就不再哆嗦了

创造Venc channal

首先命中enType的H264

        case PT_H264:
        {
            stH264Attr.u32MaxPicWidth = stPicSize.u32Width;
            stH264Attr.u32MaxPicHeight = stPicSize.u32Height;
            stH264Attr.u32PicWidth = stPicSize.u32Width;/*the picture width*/
            stH264Attr.u32PicHeight = stPicSize.u32Height;/*the picture height*/
            stH264Attr.u32BufSize  = stPicSize.u32Width * stPicSize.u32Height;/*stream buffer size*/
            stH264Attr.u32Profile  = u32Profile;/*0: baseline; 1:MP; 2:HP;  3:svc_t */
            stH264Attr.bByFrame = HI_TRUE;/*get stream mode is slice mode or frame mode?*/
			stH264Attr.u32BFrameNum = 0;/* 0: not support B frame; >=1: number of B frames */
			stH264Attr.u32RefNum = 1;/* 0: default; number of refrence frame*/
			memcpy(&stVencChnAttr.stVeAttr.stAttrH264e, &stH264Attr, sizeof(VENC_ATTR_H264_S));

            if(SAMPLE_RC_CBR == enRcMode)
            {
                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
                stH264Cbr.u32Gop            = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264Cbr.u32StatTime       = 1; /* stream rate statics time(s) */
                stH264Cbr.u32SrcFrmRate      = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;/* input (vi) frame rate */
                stH264Cbr.fr32DstFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;/* target frame rate */
				
				switch (enSize)
                {
                  case PIC_QCIF:
                       stH264Cbr.u32BitRate = 256; /* average bit rate */
                       break;
                  case PIC_QVGA:    /* 320 * 240 */
                  case PIC_CIF: 

                	   stH264Cbr.u32BitRate = 512;
                       break;

                  case PIC_D1:
                  case PIC_VGA:	   /* 640 * 480 */
                	   stH264Cbr.u32BitRate = 1024*2;
                       break;
                  case PIC_HD720:   /* 1280 * 720 */
                	   stH264Cbr.u32BitRate = 1024*2;
                	   break;
                  case PIC_HD1080:  /* 1920 * 1080 */
                  	   stH264Cbr.u32BitRate = 1024*4;
                	   break;
                  case PIC_5M:  /* 2592 * 1944 */
                  	   stH264Cbr.u32BitRate = 1024*8;
                	   break;                       
                  default :
                       stH264Cbr.u32BitRate = 1024*4;
                       break;
                }
                
                stH264Cbr.u32FluctuateLevel = 0; /* average bit rate */
                memcpy(&stVencChnAttr.stRcAttr.stAttrH264Cbr, &stH264Cbr, sizeof(VENC_ATTR_H264_CBR_S));
            }
            else if (SAMPLE_RC_FIXQP == enRcMode) 
            {
                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264FIXQP;
                stH264FixQp.u32Gop = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264FixQp.u32SrcFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264FixQp.fr32DstFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264FixQp.u32IQp = 20;
                stH264FixQp.u32PQp = 23;
                memcpy(&stVencChnAttr.stRcAttr.stAttrH264FixQp, &stH264FixQp,sizeof(VENC_ATTR_H264_FIXQP_S));
            }
            else if (SAMPLE_RC_VBR == enRcMode) 
            {
                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR;
                stH264Vbr.u32Gop = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264Vbr.u32StatTime = 1;
                stH264Vbr.u32SrcFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264Vbr.fr32DstFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
                stH264Vbr.u32MinQp = 10;
                stH264Vbr.u32MaxQp = 40;
                switch (enSize)
                {

                  case PIC_HD720:   /* 1280 * 720 */
                	   stH264Vbr.u32MaxBitRate = 1024*3;
                	   break;
                  default :
                       stH264Vbr.u32MaxBitRate = 1024*4;
                       break;
                }
                memcpy(&stVencChnAttr.stRcAttr.stAttrH264Vbr, &stH264Vbr, sizeof(VENC_ATTR_H264_VBR_S));
            }
            else
            {
                return HI_FAILURE;
            }
        }
        break;

首先是这两步

stH264Attr.u32MaxPicWidth  = stPicSize.u32Width;
stH264Attr.u32MaxPicHeight = stPicSize.u32Height;
stH264Attr.u32PicWidth     = stPicSize.u32Width;/*the picture width*/
stH264Attr.u32PicHeight    = stPicSize.u32Height;/*the picture height*/

通过上面资料可知

  • 如果输入图像比编码通道尺寸大,VENC 将按照编码通道尺寸大小,调用 VGS 对源图像进行缩小,然后对缩小之后的图像进行编码。
  • 如果输入图像比编码通道尺寸小,VENC 丢弃源图像。VENC 不支持放大输入图像编码。
  • 如果输入图像与编码通道尺寸相当,VENC 直接接受源图像,进行编码。

所以这里直接把图像尺寸大小给到编码通道,这样既不会丢弃源图像,也不会对图像进行缩小

码率控制

CBR

CBR(Constant Bit Rate)固定比特率。即在码率统计时间内保证编码码率平稳。码率稳定主要由两个量来评估,这两个量都可以由用户在创建编码通道时指定。

  • 码率统计时间 u32StatTime
    单位为秒(s),码率统计时间越长,每帧图像的码率波动对于码率调节的影响越弱,码率的调节会更缓慢,图像质量的波动会更轻微;码率统计时间越短,每帧图像的码率波动对于码率调节的影响越强,图像码率的调节会更灵敏,图像质量的波动会更剧烈。

  • 行级码率控制调节幅度 u32RowQpDelta
    行级码率控制调节幅度是一帧内行级调节的最大范围,其中行级以宏块行为单位。调节幅度越大,允许行级调整的 QP 范围越大,码率越平稳。对于图像复杂度分布不均匀的场景,行级码率控制调节幅度设置过大会带来图像质量不均匀。

stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
stH264Cbr.u32Gop                = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264Cbr.u32StatTime           = 1; /* stream rate statics time(s) */
stH264Cbr.u32SrcFrmRate         = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;/* input (vi) frame rate */
stH264Cbr.fr32DstFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;/* target frame rate */
case PIC_HD720:   /* 1280 * 720 */
   stH264Cbr.u32BitRate = 1024*2;

FIXQP

Fix Qp 固定 Qp 值。在码率统计时间内,编码图像所有宏块 Qp 值相同,采用用户设定
的图像 Qp 值,I 帧和 P 帧的 QP 值可以分别设置。

stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264FIXQP;
stH264FixQp.u32Gop = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264FixQp.u32SrcFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264FixQp.fr32DstFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264FixQp.u32IQp = 20;
stH264FixQp.u32PQp = 23;

VBR

VBR(Variable Bit Rate)可变比特率,即允许在码率统计时间内编码码率波动,从而保证编码图像质量平稳。以 H.264 编码为例,VENC 模块提供用户可设置 MaxQp,MinQp,MaxBitrate 和 ChangePos。MaxQp,MinQp 用于控制图像的质量范围, MaxBitrate 用于钳位码率统计时间内的最大编码码率,ChangePos 用于控制开始调整Qp 的码率基准线。当编码码率大于 MaxBitrateChangePos 时,图像 qp 会逐步向MaxQp 调整,如果图像 QP 达到 MaxQp,QP 会被钳位到最大值,MaxBitrate 的钳位效果失效,编码码率有可能会超出 MaxBitrate。当编码码率小于 MaxBitrateChangePos时,图像 QP 会逐步向 MinQp 调整,如果图像 QP 达到 MinQp,此时编码的码率已经达到最大值,而且图像质量最好。

stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR;
stH264Vbr.u32Gop = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264Vbr.u32StatTime = 1;
stH264Vbr.u32SrcFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264Vbr.fr32DstFrmRate = (VIDEO_ENCODING_MODE_PAL== enNorm)?25:30;
stH264Vbr.u32MinQp = 10;
stH264Vbr.u32MaxQp = 40;

HI_MPI_VENC_CreateChn

通过上面设置好的参数创建Venc通道

HI_MPI_VENC_StartRecvPic

开始接收Venc图像

SAMPLE_COMM_VENC_BindVpss 绑定VPsschn0 到Vencchn0

VPsschn2 到Vencchn02的部分在if(s32ChnNum >= 2)

    HI_S32 s32Ret = HI_SUCCESS;
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;

    stSrcChn.enModId = HI_ID_VPSS;
    stSrcChn.s32DevId = VpssGrp;
    stSrcChn.s32ChnId = VpssChn;

    stDestChn.enModId = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = VeChn;

    s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

HI_MPI_SYS_Bind()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值