海思媒体(mmp)处理平台架构
海思媒体处理平台的主要内部处理流程如图 1-2 所示,主要分为视频输入(VI)、视频处理(VPSS)、视频编码(VENC)、视频解码(VDEC)、视频输出(VO)、视频侦测分析(VDA)、音频输入(AI)、音频输出(AO)、音频编码(AENC)、音频解码(ADEC)、区域管理(REGION)等模块。主要的处理流程介绍如下:
VI 模块捕获视频图像,可对其做剪切、缩放等处理,并输出多路不同分辨率的图像数据。解码模块对编码后的视频码流进行解码,并将解析后的图像数据送 VPSS 进行图像处理或直接送 VO 显示。可对 H264/MPEG4/MPEG2 格式的视频码流进行解码。
VPSS 模块接收 VI 和解码模块发送过来的图像,可对图像进行去噪、图像增强、锐化等处理,并实现同源输出多路不同分辨率的图像数据用于编码、预览或抓拍。
编码模块接收 VI 捕获并经 VPSS 处理后输出的图像数据,可叠加用户通过 Region模块设置的 OSD 图像,然后按不同协议进行编码并输出相应码流。
VDA 模块接收 VI 的输出图像,并进行移动侦测和遮挡侦测,最后输出侦测分析结果。
VO 模块接收 VPSS 处理后的输出图像,可进行播放控制等处理,最后按用户配置的输出协议输出给外围视频设备。
AI 模块捕获音频数据,然后 AENC 模块支持按多种音频协议对其进行编码,最后输出音频码流。
用户从网络或外围存储设备获取的音频码流可直接送给 ADEC 模块, ADEC 支持解码多种不同的音频格式码流,解码后数据送给 AO 模块即可播放声音。
下面的代码我把不会用到的代码删除了,这样更简洁,为了简介,下面我只做一路输出,只选择APTINA_AR0130_DC_720P_30FPS为视频输出格式
int main(int argc, char *argv[])
{
HI_S32 s32Ret;
signal(SIGINT, SAMPLE_VENC_HandleSig);//ctrl+c,delete
signal(SIGTERM, SAMPLE_VENC_HandleSig);//ctrl+\
/* H.264@1080p@30fps+H.265@1080p@30fps+H.264@D1@30fps */
s32Ret = SAMPLE_VENC_1080P_CLASSIC();
if (HI_SUCCESS == s32Ret)
printf("program exit normally!\n");
else
printf("program exit abnormally!\n");
exit(s32Ret);
}
SAMPLE_VENC_HandleSig:主要做系统的回收,ISP线程的退出,ISP的停止
SAMPLE_VENC_1080P_CLASSIC:H.264@1080p@30fps+H.265@1080p@30fps+H.264@D1@30fps这几种情况的处理
由于海思的应用程序启动 MPP 业务前,必须完成 MPP 系统初始化工作。同理,应用程序退出MPP 业务后,也要完成 MPP 系统去初始化工作,释放资源。
初始化工作主要为:
各个模块之间的绑定
可以参考:https://blog.csdn.net/qq_40732350/article/details/87970605
在H264_Venc()函数里先去初始化MPI系统,然后根据摄像头设置参数。我这里是AR030摄像头,其拍摄图片大小为720P,编码为H264,为了简单只输出一路。在初始化MPI系统时要计算视频缓存池VB_CONF_S的大小,然后填充VB_CONF_S结构体。填充完VB_CONF_S结构体后再用HI_MPI_VB_SetConf设置,最后初始化视频视频缓存池HI_MPI_VB_Init。这里注意的是基本上每个函数调用后都会判断返回值并作出错出理,后面很多函数也是这样处理的,这样利于程序排错
第一步:初始化视频缓冲池和系统MPP初始化
//为了简单点,编码类型就选择PT_H264,图片大小就选择PIC_HD720,通道也只用1路s32ChnNum=1
PAYLOAD_TYPE_E enPayLoad=PT_H264;//264编码
PIC_SIZE_E enSize=PIC_HD720;//摄像头拍摄图片的大小,这里只用720P
HI_S32 s32ChnNum=1;//支持一路摄像
HI_S32 s32Ret=HI_FAILURE;
/******************************************
mpp system init.
******************************************/
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
VB_CONF_S stVbConf;//缓存池参数结构体
HI_U32 u32BlkSize;//一张图片占多少字节
memset(&stVbConf,0,sizeof(VB_CONF_S));
//根据制式,图片大小,图片格式及对齐方式确定图片缓存大小
//这里用NTSC,720P,YUV420,64字节对齐
u32BlkSize=SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,enSize, PIXEL_FORMAT_YUV_SEMIPLANAR_420, \
SAMPLE_SYS_ALIGN_WIDTH);
printf("u32BlkSize=%d\n",u32BlkSize);
stVbConf.u32MaxPoolCnt = 128;//用默认值,3518默认是128
stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;//(宽+压缩头 stride) * 高 * 1.5 参考MPP手册94
stVbConf.astCommPool[0].u32BlkCnt = g_u32BlkCnt; //4个缓冲块
//设置缓冲池
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
s32Ret = HI_MPI_VB_SetConf(&stVbConf);//设置 MPP 视频缓存池属性
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VB_SetConf failed!\n");
return HI_FAILURE;
}
s32Ret = HI_MPI_VB_Init();//初始化 MPP 视频缓存池
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VB_Init failed!\n");
return HI_FAILURE;
}
//设置系统属性
MPP_SYS_CONF_S stSysConf = {0};
HI_S32 s32Ret = HI_FAILURE;
stSysConf.u32AlignWidth = SAMPLE_SYS_ALIGN_WIDTH; //64
s32Ret = HI_MPI_SYS_SetConf(&stSysConf);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_SetConf failed\n");
return HI_FAILURE;
}
s32Ret = HI_MPI_SYS_Init();
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_Init failed!\n");
return HI_FAILURE;
}