通过Hi3536sdk中Hi3536_SDK_V2.0.7.0/mpp_master/sample/vo的例程修改而来的视频叠加简单例程。
例程实现了打开16个窗口,通过按键输入,控制每个窗口以规定的大小、位置叠加起来。
效果如下:
主要功能函数代码如下(注释行为关键部分):
HI_S32 SAMPLE_VO_Virtual_HD0(HI_VOID)
{HI_S32 s32Ret &#61; HI_SUCCESS; VB_CONF_S stVbConf; HI_U32 u32BlkSize;VDEC_CHN VdChn &#61; 1;PAYLOAD_TYPE_E enType; SIZE_S stSize; HI_S32 s32VpssGrpCnt &#61; 6, s32VpssChnCnt &#61; 1; HI_S32 i,x,y;HI_U32 u32WndNum;VPSS_GRP_ATTR_S stGrpAttr; VPSS_CHN_MODE_S stVpssChnMode;VENC_CHN VeJpegChn &#61; 0;VO_DEV VoDev; VO_LAYER VoLayer;VO_PUB_ATTR_S stVoPubAttr; SAMPLE_VO_MODE_E enVoMode;VO_VIDEO_LAYER_ATTR_S stLayerAttr;HI_CHAR ch;VDEC_CHN_ATTR_S stVdecChnAttr[VDEC_MAX_CHN_NUM];VdecThreadParam stVdecSend[VDEC_MAX_CHN_NUM]; pthread_t VdecThread[2 * VDEC_MAX_CHN_NUM];/******************************************step 1: init variable ******************************************/ memset(&stVbConf,0,sizeof(VB_CONF_S)); u32BlkSize &#61; SAMPLE_COMM_SYS_CalcPicVbBlkSize(VIDEO_ENCODING_MODE_PAL,\PIC_HD1080, SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);stVbConf.u32MaxPoolCnt &#61; 128;stVbConf.astCommPool[0].u32BlkSize &#61; u32BlkSize;stVbConf.astCommPool[0].u32BlkCnt &#61; 20;s32Ret &#61; SAMPLE_COMM_SYS_GetPicSize(VIDEO_ENCODING_MODE_PAL, PIC_HD1080, &stSize);if (HI_SUCCESS !&#61;s32Ret){SAMPLE_PRT("get picture size failed!\n");return HI_FAILURE;}if (704 &#61;&#61; stSize.u32Width){stSize.u32Width &#61; 720;}else if (352 &#61;&#61; stSize.u32Width){stSize.u32Width &#61; 360;}else if (176 &#61;&#61; stSize.u32Width){stSize.u32Width &#61; 180;}/******************************************step 2: mpp system init. ******************************************/s32Ret &#61; SAMPLE_COMM_SYS_Init(&stVbConf);if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("system init failed with %d!\n", s32Ret);goto END_VIRTUAL_1;}/******************************************step 3: start vdec ******************************************/ enType &#61; PT_H264;memset(&stVbConf,0,sizeof(VB_CONF_S)); SAMPLE_COMM_VDEC_ModCommPoolConf(&stVbConf, enType, &stSize, VdChn); s32Ret &#61; SAMPLE_COMM_VDEC_InitModCommVb(&stVbConf);if(s32Ret !&#61; HI_SUCCESS){ SAMPLE_PRT("init mod common vb fail for %#x!\n", s32Ret);goto END_VIRTUAL_1;}/**************create vdec chn****************************/ SAMPLE_COMM_VDEC_ChnAttr(VdChn, &stVdecChnAttr[0], enType, &stSize);s32Ret &#61; SAMPLE_COMM_VDEC_Start(VdChn, &stVdecChnAttr[0]); if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("Start Vdec failed!\n");goto END_VIRTUAL_2;} /**************send stream****************************/SAMPLE_COMM_VDEC_ThreadParam(VdChn, &stVdecSend[0], &stVdecChnAttr[0], "1080P.h264"); SAMPLE_COMM_VDEC_StartSendStream(VdChn, &stVdecSend[0], &VdecThread[0]);/******************************************step 4: start vpss with vdec bind vpss ******************************************/stGrpAttr.u32MaxW &#61; stSize.u32Width;stGrpAttr.u32MaxH &#61; stSize.u32Height;stGrpAttr.bIeEn &#61; HI_FALSE;stGrpAttr.bNrEn &#61; HI_TRUE;stGrpAttr.bHistEn &#61; HI_FALSE;stGrpAttr.enDieMode &#61; VPSS_DIE_MODE_NODIE;stGrpAttr.enPixFmt &#61; SAMPLE_PIXEL_FORMAT;stGrpAttr.bDciEn &#61; HI_FALSE;stGrpAttr.bEsEn &#61; HI_TRUE;s32Ret &#61; SAMPLE_COMM_VPSS_Start(s32VpssGrpCnt, &stSize, s32VpssChnCnt, &stGrpAttr);if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("Start Vpss failed!\n");goto END_VIRTUAL_3;}for(i&#61;0; i<1; i&#43;&#43;){s32Ret &#61; HI_MPI_VPSS_GetChnMode(i, 0, &stVpssChnMode);if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("HI_MPI_VPSS_SetChnMode failed with %x\n",s32Ret);goto END_VIRTUAL_3;}stVpssChnMode.bDouble &#61; HI_FALSE;stVpssChnMode.enChnMode &#61; VPSS_CHN_MODE_USER;stVpssChnMode.enPixelFormat &#61; PIXEL_FORMAT_YUV_SEMIPLANAR_420;stVpssChnMode.u32Width &#61; 1920;stVpssChnMode.u32Height &#61; 1080;stVpssChnMode.enCompressMode &#61; COMPRESS_MODE_NONE; s32Ret &#61; HI_MPI_VPSS_SetChnMode(i, 0, &stVpssChnMode);if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("HI_MPI_VPSS_SetChnMode failed with %x\n",s32Ret);goto END_VIRTUAL_3;}}for(i &#61; 0;i < VdChn; i&#43;&#43;){s32Ret &#61; SAMPLE_COMM_VDEC_BindVpss(i,i);if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("SAMPLE_COMM_VDEC_BindVpss failed!\n");goto END_VIRTUAL_4;}}/***************************************************step 5: start VIRT0 with 4 windows and bind to VENC***************************************************/ /**************start Dev****************************/VoDev &#61; SAMPLE_VO_DEV_VIRT0; stVoPubAttr.enIntfSync &#61; VO_OUTPUT_1080P30;stVoPubAttr.enIntfType &#61; VO_INTF_HDMI;stVoPubAttr.u32BgColor &#61; 0x0;s32Ret &#61; SAMPLE_COMM_VO_StartDev(VoDev, &stVoPubAttr); if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("SAMPLE_COMM_VO_StartDev failed!\n");goto END_VIRTUAL_4;}/**************start Layer****************************/VoLayer &#61; SAMPLE_VO_LAYER_VIRT0;stLayerAttr.bClusterMode &#61; HI_FALSE;stLayerAttr.bDoubleFrame &#61; HI_FALSE;stLayerAttr.enPixFormat &#61; SAMPLE_PIXEL_FORMAT; s32Ret &#61; SAMPLE_COMM_VO_GetWH(stVoPubAttr.enIntfSync, \&stLayerAttr.stDispRect.u32Width, &stLayerAttr.stDispRect.u32Height, &stLayerAttr.u32DispFrmRt);if (s32Ret !&#61; HI_SUCCESS){SAMPLE_PRT("failed with %#x!\n", s32Ret);goto END_VIRTUAL_5;}stLayerAttr.stImageSize.u32Width &#61; stLayerAttr.stDispRect.u32Width;stLayerAttr.stImageSize.u32Height &#61; stLayerAttr.stDispRect.u32Height;HI_MPI_VO_SetVideoLayerPartitionMode(VoLayer,VO_PART_MODE_SINGLE);s32Ret &#61; SAMPLE_COMM_VO_StartLayer(VoLayer, &stLayerAttr); if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("SAMPLE_COMM_VO_StartLayer failed!\n");goto END_VIRTUAL_5;} /**************start Chn****************************/ enVoMode &#61; VO_MODE_16MUX; //16个窗口s32Ret &#61; SAMPLE_COMM_VO_StartChn(VoLayer,enVoMode); if (s32Ret !&#61; HI_SUCCESS){SAMPLE_PRT("failed with %#x!\n", s32Ret);goto END_VIRTUAL_6;} /**************vo bind to vpss****************************/u32WndNum &#61; 16; //16个窗口for(i &#61; 0;i < u32WndNum;i&#43;&#43;){s32Ret &#61; SAMPLE_COMM_VO_BindVpss(VoLayer, i, 0, VPSS_CHN0);if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("SAMPLE_COMM_VO_BindVpss failed!\n");goto END_VIRTUAL_6;} }sleep(1);/******************************************step 6: start jpege snap.*****************************************/VoDev &#61; SAMPLE_VO_DEV_DHD0;VoLayer &#61; SAMPLE_VO_LAYER_VHD0;enVoMode &#61; VO_MODE_1MUX; //单分屏
#ifdef HI_FPGAstVoPubAttr.enIntfSync &#61; VO_OUTPUT_1080P30;stVoPubAttr.enIntfType &#61; VO_INTF_VGA;
#elsestVoPubAttr.enIntfSync &#61; VO_OUTPUT_3840x2160_30;stVoPubAttr.enIntfType &#61; VO_INTF_HDMI;
#endif stVoPubAttr.u32BgColor &#61; 0x0;s32Ret &#61; SAMPLE_COMM_VO_StartDev(VoDev, &stVoPubAttr); if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("SAMPLE_COMM_VO_StartDev failed!\n");goto END_VIRTUAL_4;}
#ifndef HI_FPGAif (HI_SUCCESS !&#61; SAMPLE_COMM_VO_HdmiStart(stVoPubAttr.enIntfSync)){SAMPLE_PRT("Start SAMPLE_COMM_VO_HdmiStart failed!\n");goto END_VIRTUAL_5;}
#endif/**************start Layer****************************/ stLayerAttr.bClusterMode &#61; HI_FALSE;stLayerAttr.bDoubleFrame &#61; HI_FALSE;stLayerAttr.enPixFormat &#61; SAMPLE_PIXEL_FORMAT; s32Ret &#61; SAMPLE_COMM_VO_GetWH(stVoPubAttr.enIntfSync, \&stLayerAttr.stDispRect.u32Width, &stLayerAttr.stDispRect.u32Height, &stLayerAttr.u32DispFrmRt);if (s32Ret !&#61; HI_SUCCESS){SAMPLE_PRT("failed with %#x!\n", s32Ret);goto END_VIRTUAL_5;}stLayerAttr.stImageSize.u32Width &#61; stLayerAttr.stDispRect.u32Width;stLayerAttr.stImageSize.u32Height &#61; stLayerAttr.stDispRect.u32Height;s32Ret &#61; SAMPLE_COMM_VO_StartLayer(VoLayer, &stLayerAttr); if (HI_SUCCESS !&#61; s32Ret){SAMPLE_PRT("SAMPLE_COMM_VO_StartLayer failed!\n");goto END_VIRTUAL_6;} /**************start Chn****************************/ s32Ret &#61; SAMPLE_COMM_VO_StartChn(VoLayer,enVoMode); if (s32Ret !&#61; HI_SUCCESS){SAMPLE_PRT("failed with %#x!\n", s32Ret);goto END_VIRTUAL_6;} SAMPLE_COMM_Vpss_BindVO(SAMPLE_VO_LAYER_VIRT0,0,4,0);/**************vo bind to vpss****************************/s32Ret &#61; SAMPLE_COMM_VO_BindVpss(VoLayer, 0, 4, 0);s32Ret &#61; SAMPLE_COMM_VO_BindVpss(VoLayer, 6, 5, 0);i &#61; 0;while(1){printf("\tpress &#39;q&#39; to exit this sample.\n");printf("\tpress &#39;s&#39; to snap one picture\n");ch &#61; getchar();if (10 &#61;&#61; ch){continue;}getchar(); if (&#39;q&#39; &#61;&#61; ch){break;}else if(&#39;s&#39; &#61;&#61; ch){if(i > 15) //0~15&#xff0c;16个窗口goto END_VIRTUAL_1;x &#61; 200&#43;i*20; //通过X轴坐标定位窗口位置SAMPLE_COMM_VO_SetChn(SAMPLE_VO_LAYER_VIRT0,i,x,x);i&#43;&#43;;usleep(10);}else{SAMPLE_PRT("the input is invaild! please try again.\n");continue;}}/******************************************step 9: exit process******************************************/
END_VIRTUAL_7: SAMPLE_COMM_VO_SnapStop(VeJpegChn);END_VIRTUAL_6:VoLayer &#61; SAMPLE_VO_LAYER_VIRT0;enVoMode &#61; VO_MODE_4MUX; SAMPLE_COMM_VO_StopChn(VoLayer,enVoMode); SAMPLE_COMM_VO_StopLayer(VoLayer);u32WndNum &#61; 4; for(i &#61; 0;i < u32WndNum;i&#43;&#43;){SAMPLE_COMM_VO_UnBindVpss(VoLayer,i,i,VPSS_CHN0);}END_VIRTUAL_5: VoDev &#61; SAMPLE_VO_DEV_VIRT0; SAMPLE_COMM_VO_StopDev(VoDev); END_VIRTUAL_4: for(i &#61; 0;i < VdChn;i&#43;&#43;){SAMPLE_COMM_VDEC_UnBindVpss(i,i);}END_VIRTUAL_3: SAMPLE_COMM_VPSS_Stop(s32VpssGrpCnt, VPSS_MAX_CHN_NUM);END_VIRTUAL_2:SAMPLE_COMM_VDEC_Stop(VdChn); SAMPLE_COMM_VDEC_StopSendStream(VdChn, &stVdecSend[0], &VdecThread[0]);END_VIRTUAL_1:SAMPLE_COMM_SYS_Exit();return s32Ret;
}
完整代码与编译生成文件&#xff1a;https://download.csdn.net/download/weixin_43793181/19037437