本文主要讲海思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卡的部分。
接下来看看音频是咋整的,弄个程序记录一段时间的音视频,有结果再分享给大家。