1 海思媒体处理平台架构
海思媒体处理平台的主要内部处理流程如图下所示,主要分为视频输入( VI)、视频处理( VPSS)、视频编码( VENC)、视频解码( VDEC)、视频输出(VO)、视频侦测分析(VDA)、音频输入(AI)、音频输出(AO)、音频编码( AENC)、音频解码( ADEC)、
区域管理( REGION)等模块。主要的处理流程介绍如下:
图1-1 海思媒体处理平台内部处理流程图
- VI 模块捕获视频图像,可对其做剪切、缩放等处理,并输出多路不同分辨率的图像数据。
- 解码模块对编码后的视频码流进行解码,并将解析后的图像数据送 VPSS 进行图像处理或直接送 VO 显示。可对 H264/MPEG4/MPEG2 格式的视频码流进行解码。
- VPSS 模块接收 VI 和解码模块发送过来的图像,可对图像进行去噪、图像增强、
- 锐化等处理,并实现同源输出多路不同分辨率的图像数据用于编码、预览或抓拍。
- 编码模块接收 VI 捕获并经 VPSS 处理后输出的图像数据,可叠加用户通过 Region模块设置的 OSD(信息叠加) 图像,然后按不同协议进行编码并输出相应码流。
- VDA 模块接收 VI 的输出图像,并进行移动侦测和遮挡侦测,最后输出侦测分析结果。
- VO 模块接收 VPSS 处理后的输出图像,可进行播放控制等处理,最后按用户配置的输出协议输出给外围视频设备。
- AI 模块捕获音频数据,然后 AENC 模块支持按多种音频协议对其进行编码,最后输出音频码流。
- 用户从网络或外围存储设备获取的音频码流可直接送给 ADEC 模块, ADEC 支持解码多种不同的音频格式码流,解码后数据送给 AO 模块即可播放声音。
2 海思Hi3518E视频缓存池
2.1 什么是视频缓冲池
- 视频的本质是多帧图片,图片的本质是RGB或rawRGB数据,要占用一段连续内存
- 视频的裁剪、缩放、修正处理等各种操作,本质上就是对内存中的数据进行运算
- 视频缓存池(VB, video buffer)就是一段很大,又被合理划分和管理的内存,里面又N个缓冲块,每个缓冲块大小相同,用来做视频数据的暂存和运算场地
- 公共视频缓存池的公共2字,可以理解为全局变量,也就是各个模块都能访问的一段内存
- 看似视频缓存块在各个模块之间流转,实际上并没有内存复制,而是指针在传递
- 视频缓存池的内存由MPP来维护,我们在系统启动时就把整个SDRAM分成了2部分(共64M内存,32M用于操作系统,32M用于mpp):系统部分(由linux kernel来维护管理)和mpp部分(由mpp系统来维护管理)
- 缓存池需要几个,每个中包含几个缓存块,每个缓存块多大,都是可以由用户程序设置好参数,然后调用MPP的相应API来向MPP申请分配的。
2.2 相关的数据结构和API
VB_CONF_S
【说明】
定义视频缓存池属性结构体。
【定义】
typedef struct hiVB_CONF_S
{
HI_U32 u32MaxPoolCnt; /* max count of pools, (0,VB_MAX_POOLS] */
Struct hiVB_CPOOL_S
{
HI_U32 u32BlkSize;
HI_U32 u32BlkCnt;
HI_CHAR acMmzName[MAX_MMZ_NAME_LEN];
}astCommPool[VB_MAX_COMM_POOLS];
} VB_CONF_S;
【成员】
成员名称 | 描述 |
u32MaxPoolCnt | 整个系统中可容纳的缓存池个数。 取值范围: (0, VB_MAX_POOLS(MPP自身定义的最大的上限))。 静态属性。 目前,固定取值 VB_MAX_POOLS。 |
astCommPool | 公共缓存池属性结构体,成员包括公共缓存池中每个缓存块的大小(以 byte 为单位)和缓存块的个数及此缓存池在所在的MMZ 的名字。静态属性。 |
【注意事项】
公共缓存池中每个缓存块的大小应根据当前图像像素格式以及图像是否压缩而有所不
同。详见如表 2-2 所示。
表2-2
像素格式 | 是否压缩 | |
压缩 | 非压缩 | |
PIXEL_FORMAT_YUV_SEMIPLANAR_420 | (宽+压缩头 stride) * 高 * 1.5 | 宽* 高 * 1.5 |
PIXEL_FORMAT_YUV_SEMIPLANAR_422 | (宽+压缩头 stride) * 高 * 2 | 宽* 高 * 2 |
PIXEL_FORMAT_YUV_400 | 宽+压缩头 stride) * 高 | 宽* 高 |
如表 2-2 所示,压缩指 256byte 段式压缩(目前仅支持此压缩模式)。另外,要求宽 16对齐,高 2 对齐。压缩头 stride 为 16。压缩时,图像压缩头大小可以直接调用宏定义VB_PIC_HEADER_SIZE 得到,图像总大小可以直接调用宏定义 VB_PIC_BLK_SIZE得到,这两个宏定义皆位于 hi_define.h 头文件中。
HI_MPI_VB_SetConf
【描述】
设置 MPP 视频缓存池属性。
【语法】
HI_S32 HI_MPI_VB_SetConf (const VB_CONF_S *pstVbConf);
【参数】
参数名称 | 描述 | 输入输出 |
pstVbConf | 视频缓存池属性指针。 静态属性 | 输入 |
【返回值】
返回值 | 描述 |
0 | 成功 |
非0 | 失败,返回值见 错误码 |
【需求】
- 头文件: hi_comm_vb.h、 mpi_vb.h
- 库文件: libmpi.a
示例代码:
HI_S32 s32ret;
VB_CONF_S struVbConf;
MPP_SYS_CONF_S struSysConf;
memset(&struVbConf,0,sizeof(VB_CONF_S));
struVbConf.u32MaxPoolCnt = 64;
struVbConf.astCommPool[0].u32BlkSize = 1920*1088*2;
struVbConf.astCommPool[0].u32BlkCnt = 15;
memset(struVbConf.astCommPool[0].acMmzName,0,sizeof(struVbConf.astCommPool[0].acMmzName));
s32ret = HI_MPI_VB_SetConf(&struVbConf);
if (HI_SUCCESS != s32ret)
{
return s32ret;
}
s32ret = HI_MPI_VB_Init();
if (HI_SUCCESS != s32ret)
{
return s32ret;
}
struSysConf.u32AlignWidth = 16;
/* set config of mpp system*/
s32ret = HI_MPI_SYS_SetConf(&struSysConf);
if (HI_SUCCESS != s32ret)
{
printf("Set mpp sys config failed!\n");
return s32ret;
}
/* init system*/
s32ret = HI_MPI_SYS_Init();
if (HI_SUCCESS != s32ret)
{
printf("Mpi init failed!\n");
return s32ret;
}
/* ...... */
/* exit system*/
s32ret = HI_MPI_SYS_Exit();
if (HI_SUCCESS != s32ret)
{
printf("Mpi exit failed!\n");
return s32ret;
}
s32ret = HI_MPI_VB_Exit();
if (HI_SUCCESS != s32ret)
{
return s32ret;
}
【注意】
- 只能在系统(mpp)处于未初始化的状态下,才可以设置缓存池属性,否则会返回失败。
- video buf 根据不同的应用场景需要不同的配置。配置规则参见 图2-2 “典型的公共视频缓存池数据流图”
- 公共缓存池中每个缓存块的大小应根据当前图像像素格式以及图像是否压缩而有所不同。具体分配大小请参考 VB_CONF_S 结构体中的描述。
HI_MPI_VB_Init
【描述】
初始化 MPP 视频缓存池。
【语法】
HI_S32 HI_MPI_VB_Init (HI_VOID);
【参数】
无。
【返回值】
返回值 | 描述 |
0 | 成功。 |
非 0 | 失败,其值参见错误码。 |
【需求】
- 头文件: hi_comm_vb.h、 mpi_vb.h
- 库文件: libmpi.a
【注意】
- 必须先调用 HI_MPI_VB_SetConf 配置缓存池属性,再初始化缓存池,否则会失败。
- 可反复初始化,不返回失败。
下面是官方手册对视频缓存池的描述:
视频缓存池主要向媒体业务提供大块物理内存管理功能,负责内存的分配和回收,充分发挥内存缓存池的作用,让物理内存资源在各个媒体处理模块中合理使用。一组大小相同、物理地址连续的缓存块组成一个视频缓存池。视频输入通道需要使用公共视频缓存池。所有的视频输入通道都可以从公共视频缓存池中获取视频缓存块用于保存采集的图像(如图 2-1 中所示从公共视频缓存池 A 中获取视频缓存块 Bm)。由于视频输入通道不提供创建和销毁公共视频缓存池功能,因此,在系统初始化之前,必须为视频输入通道配置公共视频缓存池。根据业务的不同,公共缓存池的数量、缓存块的大小和数量不同。 图 2-1 中所示缓存块的生存期是指经过 VPSS 通道传给后续模块的情形( 图 2-1 实线路径)。如果该缓存块完全没有经过 VPSS 通道传给其他模块,则将在 VPSS 模块处理后被放回公共缓存池( 图 2-1 虚线
路径)。
图2-2 典型的公共视频缓存池数据流图