sample_venc解读(hi3516dv300)

本文深入探讨海思sample中的venc代码,详细介绍H.265与H.264编码过程,涵盖编码参数配置、编码启动及流保存流程。通过实际案例,解析编码器与VPSS模块交互细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要讲海思sample里的venc代码,介绍自己的心得体会。

/******************************************************************************
* function    : main()
* Description : video venc sample
******************************************************************************/
#ifdef __HuaweiLite__
    int app_main(int argc, char *argv[])
#else
    int main(int argc, char *argv[])
#endif
{
    HI_S32 s32Ret;
    HI_U32 u32Index;

    if (argc < 2 || argc > 2)
    {
        SAMPLE_VENC_Usage(argv[0]);
        return HI_FAILURE;
    }

    if (!strncmp(argv[1], "-h", 2))
    {
        SAMPLE_VENC_Usage(argv[0]);
        return HI_SUCCESS;
    }

    u32Index = atoi(argv[1]);

#ifndef __HuaweiLite__
    signal(SIGINT, SAMPLE_VENC_HandleSig);
    signal(SIGTERM, SAMPLE_VENC_HandleSig);
#endif

    switch (u32Index)
    {
        case 0:
            s32Ret = SAMPLE_VENC_H265_H264();
            break;
        case 1:
            s32Ret = SAMPLE_VENC_LOW_DELAY();
            break;
        case 2:
            s32Ret = SAMPLE_VENC_Qpmap();
            break;
        case 3:
            s32Ret = SAMPLE_VENC_IntraRefresh();
            break;
        case 4:
            s32Ret = SAMPLE_VENC_ROIBG();
            break;
        case 5:
            s32Ret = SAMPLE_VENC_DeBreathEffect();
            break;
        case 6:
            s32Ret = SAMPLE_VENC_SVC_H264();
            break;
        case 7:
            s32Ret = SAMPLE_VENC_MJPEG_JPEG();
            break;
        default:
            printf("the index is invaild!\n");
            SAMPLE_VENC_Usage(argv[0]);
            return HI_FAILURE;
    }

    if (HI_SUCCESS == s32Ret)
    { printf("program exit normally!\n"); }
    else
    { printf("program exit abnormally!\n"); }

#ifdef __HuaweiLite__
    return s32Ret;
#else
    exit(s32Ret);
#endif
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

sample_venc的main函数里有七种编码函数,以第一个SAMPLE_VENC_H265_H264()为例,介绍venc的过程。

main 
    SAMPLE_VENC_Usage(/*sample的用法*/)
    switch(u32Index)
        SAMPLE_VENC_H265_H264()//编码H264,265
            SAMPLE_COMM_SYS_GetPicSize()//获得通道图片大小
            SAMPLE_COMM_VI_GetSensorInfo()//
            SAMPLE_VENC_CheckSensor()
            SAMPLE_VENC_ModifyResolution()//if Hifailure run this
                SAMPLE_COMM_VI_GetSizeBySensor()//Get enSize by diffrent sensor
                SAMPLE_COMM_SYS_GetPicSize()// get picture size(w*h), according enPicSize
            SAMPLE_VENC_VI_Init()
                SAMPLE_VENC_SYS_Init()
                    memset(&stVbConf, 0, sizeof(VB_CONFIG_S))//缓存池内存清0
                    SAMPLE_COMM_VI_GetSizeBySensor()//从sensor类型得到图像数据是1080p,720p之类
                    SAMPLE_COMM_SYS_GetPicSize()// 从1080P,720p得到图像的宽与高
                    COMMON_GetPicBufferSize()//计算缓存块大小
                    if(0 == u32SupplementConfig)
                        SAMPLE_COMM_SYS_Init() 
                            HI_MPI_SYS_Exit()//去初始化
                            HI_MPI_VB_Exit();//VB去初始化
                            HI_MPI_VB_SetConfig()//VB set
                            HI_MPI_VB_Init();//VB init
                            HI_MPI_SYS_Init();//mpp init
                        SAMPLE_COMM_SYS_InitWithVbSupplement()
                            HI_MPI_SYS_Exit()//去初始化
                            HI_MPI_VB_Exit();//VB去初始化
                            HI_MPI_VB_SetConfig()
                            HI_MPI_VB_SetSupplementConfig()//设置VB内存的附加信息
                            HI_MPI_VB_Init()
                            HI_MPI_SYS_Init();
            SAMPLE_VENC_VPSS_Init()
                SAMPLE_COMM_VI_GetSizeBySensor()//从sensor类型得到图像数据是1080p,720p之类
                SAMPLE_COMM_SYS_GetPicSize()// 从1080P,720p得到图像的宽与高
                SAMPLE_COMM_VPSS_Start()//
                    HI_MPI_VPSS_CreateGrp()
                    HI_MPI_VPSS_SetChnAttr()
                    HI_MPI_VPSS_StartGrp()
            SAMPLE_COMM_VI_Bind_VPSS()//可直接调用,海思good
                HI_MPI_SYS_Bind()

            //start stream venc
            SAMPLE_VENC_GetRcMode()//get cbr etc
            SAMPLE_VENC_GetGopMode()//get NORMALP etc
            SAMPLE_COMM_VENC_GetGopAttr()//配置GOP if failure goto EXIT_VI_VPSS_UNBIND

            /***encode h.265 **/
            SAMPLE_COMM_VENC_Start()//if failure goto EXIT_VI_VPSS_UNBIND
                SAMPLE_COMM_VENC_Creat()
                    SAMPLE_COMM_SYS_GetPicSize()
                    SAMPLE_COMM_VI_GetSensorInfo()//获取sensor数据,配置chn,dev等
                    SAMPLE_COMM_VI_GetFrameRateBySensor()//get information from sensor and control framerate
                    HI_MPI_VENC_CreateChn()
                    SAMPLE_COMM_VENC_CloseReEncode()
            SAMPLE_COMM_VPSS_Bind_VENC()//if failure goto EXIT_VENC_H265_STOP

            /***encode h.264 **/
            SAMPLE_COMM_VENC_Start()//if failure goto EXIT_VI_VPSS_UNBIND
            SAMPLE_COMM_VPSS_Bind_VENC()//if failure goto EXIT_VENC_H264_STOP

            //stream save process
            SAMPLE_COMM_VENC_StartGetStream()
                pthread_create(&gs_VencPid, 0, SAMPLE_COMM_VENC_GetVencStreamProc, (HI_VOID*)&gs_stPara);//创建线程
                   SAMPLE_COMM_VENC_GetVencStreamProc()//this has 5 steps and if failure goto EXIT_VENC_H264_UnBind

                SAMPLE_COMM_VENC_StopGetStream()//exit
            EXIT_VENC_H264_UnBind:
                SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[1],VencChn[1]);
            EXIT_VENC_H264_STOP:
                SAMPLE_COMM_VENC_Stop(VencChn[1]);
            EXIT_VENC_H265_UnBind:
                SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[0],VencChn[0]);
            EXIT_VENC_H265_STOP:
                SAMPLE_COMM_VENC_Stop(VencChn[0]);
            EXIT_VI_VPSS_UNBIND:
                SAMPLE_COMM_VI_UnBind_VPSS(ViPipe,ViChn,VpssGrp);
            EXIT_VPSS_STOP:
                SAMPLE_COMM_VPSS_Stop(VpssGrp,abChnEnable);
            EXIT_VI_STOP:
                SAMPLE_COMM_VI_StopVi(&stViConfig);
                SAMPLE_COMM_SYS_Exit();

        SAMPLE_VENC_LOW_DELAY()//
        SAMPLE_VENC_Qpmap()
        SAMPLE_VENC_IntraRefresh()
        SAMPLE_VENC_ROIBG()
        SAMPLE_VENC_DeBreathEffect()
        SAMPLE_VENC_SVC_H264()
        SAMPLE_VENC_MJPEG_JPEG()
        SAMPLE_VENC_Usage()

上面的图片是我对SAMPLE_VENC_H265_H264()做的图解,缩进代表子函数被上一级调用,并附有少量注释。

/******************************************************************************
* function: H.265e + H264e@720P, H.265 Channel resolution adaptable with sensor
******************************************************************************/
HI_S32 SAMPLE_VENC_H265_H264(void)
{
    HI_S32 i;
    HI_S32 s32Ret;
    SIZE_S          stSize[2];
    PIC_SIZE_E      enSize[2]     = {PIC_3840x2160, PIC_720P};
    HI_S32          s32ChnNum     = 2;
    VENC_CHN        VencChn[2]    = {0,1};
    HI_U32          u32Profile[2] = {0,0};
    PAYLOAD_TYPE_E  enPayLoad[2]  = {PT_H265, PT_H264};
    VENC_GOP_MODE_E enGopMode;
    VENC_GOP_ATTR_S stGopAttr;
    SAMPLE_RC_E     enRcMode;
    HI_BOOL         bRcnRefShareBuf = HI_TRUE;

    VI_DEV          ViDev        = 0;
    VI_PIPE         ViPipe       = 0;
    VI_CHN          ViChn        = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    VPSS_GRP        VpssGrp        = 0;
    VPSS_CHN        VpssChn[2]     = {0,1};
    HI_BOOL         abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {1,1,0};

    HI_U32 u32SupplementConfig = HI_FALSE;

    for(i=0; i<s32ChnNum; i++)
    {
        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize[i], &stSize[i]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
            return s32Ret;
        }
    }

    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
    if(SAMPLE_SNS_TYPE_BUTT == stViConfig.astViInfo[0].stSnsInfo.enSnsType)
    {
        SAMPLE_PRT("Not set SENSOR%d_TYPE !\n",0);
        return HI_FAILURE;
    }

    s32Ret = SAMPLE_VENC_CheckSensor(stViConfig.astViInfo[0].stSnsInfo.enSnsType,stSize[0]);
    if(s32Ret != HI_SUCCESS)
    {
        s32Ret = SAMPLE_VENC_ModifyResolution(stViConfig.astViInfo[0].stSnsInfo.enSnsType,&enSize[0],&stSize[0]);
        if(s32Ret != HI_SUCCESS)
        {
            return HI_FAILURE;
        }
    }

    stViConfig.s32WorkingViNum       = 1;
    stViConfig.astViInfo[0].stDevInfo.ViDev     = ViDev;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[0] = ViPipe;
    stViConfig.astViInfo[0].stChnInfo.ViChn     = ViChn;
    stViConfig.astViInfo[0].stChnInfo.enDynamicRange = DYNAMIC_RANGE_SDR8;
    stViConfig.astViInfo[0].stChnInfo.enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

    s32Ret = SAMPLE_VENC_VI_Init(&stViConfig, HI_FALSE,u32SupplementConfig);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("Init VI err for %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = SAMPLE_VENC_VPSS_Init(VpssGrp,abChnEnable,DYNAMIC_RANGE_SDR8,PIXEL_FORMAT_YVU_SEMIPLANAR_420,stSize,stViConfig.astViInfo[0].stSnsInfo.enSnsType);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Init VPSS err for %#x!\n", s32Ret);
        goto EXIT_VI_STOP;
    }

    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("VI Bind VPSS err for %#x!\n", s32Ret);
        goto EXIT_VPSS_STOP;
    }

   /******************************************
    start stream venc
    ******************************************/

    enRcMode = SAMPLE_VENC_GetRcMode();

    enGopMode = SAMPLE_VENC_GetGopMode();
    s32Ret = SAMPLE_COMM_VENC_GetGopAttr(enGopMode,&stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc Get GopAttr for %#x!\n", s32Ret);
        goto EXIT_VI_VPSS_UNBIND;
    }

   /***encode h.265 **/
    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[0], enPayLoad[0],enSize[0], enRcMode,u32Profile[0],bRcnRefShareBuf,&stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
        goto EXIT_VI_VPSS_UNBIND;
    }

    s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn[0],VencChn[0]);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc Get GopAttr failed for %#x!\n", s32Ret);
        goto EXIT_VENC_H265_STOP;
    }

    /***encode h.264 **/
    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[1], enPayLoad[1], enSize[1], enRcMode,u32Profile[1],bRcnRefShareBuf,&stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
        goto EXIT_VENC_H265_UnBind;
    }

    s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn[1],VencChn[1]);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc bind Vpss failed for %#x!\n", s32Ret);
        goto EXIT_VENC_H264_STOP;
    }

    /******************************************
     stream save process
    ******************************************/
    s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn,s32ChnNum);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Start Venc failed!\n");
        goto EXIT_VENC_H264_UnBind;
    }

    printf("please press twice ENTER to exit this sample\n");
    getchar();
    getchar();

    /******************************************
     exit process
    ******************************************/
    SAMPLE_COMM_VENC_StopGetStream();

EXIT_VENC_H264_UnBind:
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[1],VencChn[1]);
EXIT_VENC_H264_STOP:
    SAMPLE_COMM_VENC_Stop(VencChn[1]);
EXIT_VENC_H265_UnBind:
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[0],VencChn[0]);
EXIT_VENC_H265_STOP:
    SAMPLE_COMM_VENC_Stop(VencChn[0]);
EXIT_VI_VPSS_UNBIND:
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe,ViChn,VpssGrp);
EXIT_VPSS_STOP:
    SAMPLE_COMM_VPSS_Stop(VpssGrp,abChnEnable);
EXIT_VI_STOP:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
    SAMPLE_COMM_SYS_Exit();

    return s32Ret;
}

本来想写详细解释的,可是太多了,不想搞了。

有一点很奇怪,如果我拔插sd卡,sample_venc运行失败,reboot也不行,需要重新上电,我有拔插时用了mount、umount命令,有哥们说可能函数有关于sd卡的部分。

接下来看看音频是咋整的,弄个程序记录一段时间的音视频,有结果再分享给大家。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值