从官方例程深度学习海思SDK及API(2)

一、海思MPP功能模块和视频缓存池

1、MPP功能模块

(1)找到MPP手册(这个手册是我们本季文章学习的重点)

Hi3518E V200R001C01SPC030\01.software\board\document_cn\HiMPP IPC V2.0 媒体处理软件开发参考.pdf
在这里插入图片描述
(2)详见系统概述1.3部分,开头的内容自己也需要去看。

  海思媒体处理平台的主要内部处理流程如下图,主要分为视频输入( VI)、视频处理( VPSS)、视频编码( VENC)、视频解码( VDEC)、视频输出(VO)、视频侦测分析(VDA)、音频输入(AI)、音频输出(AO)、音频编码( AENC)、音频解码( ADEC)、区域管理( REGION)等模块。
在这里插入图片描述

	VI 模块捕获视频图像,可对其做剪切、缩放等处理,并输出多路不同分辨率的图
像数据。补充了解:双码流采用一路高码率的码流用于本地高清存储,例如1080P和720P,
一路低码率的码流用于网络传输,同时兼顾本地存储和远程网络传输。
	三码流指三种码率。三码流采用一路高码率的码流用于本地高清存储,例如h.264\D1
编码,一路低码率的码流用于网络传输,例如D1/CIF编码,另一路超低码流用于3G\网络传
输,手机观看,例如QCIF,,同时兼顾本地存储和远程网络传输。三码流能实现本地传输和
远程传输三种不同的带宽码流需要,本地传输采用高码流可以获得更高的高清录像存储,远
程传输采用较低的码流以适应CDMA/ADSL等各种网络而获得更高的图像流畅度。

	解码模块对编码后的视频码流进行解码,并将解析后的图像数据送 VPSS 进行图
像处理或直接送 VO 显示。可对 H264/MPEG4/MPEG2 格式的视频码流进行解
码。

	VPSS 模块接收 VI 和解码模块发送过来的图像,可对图像进行去噪、图像增强、
锐化等处理,并实现同源输出多路不同分辨率的图像数据用于编码、预览或抓
拍。

	编码模块接收 VI 捕获并经 VPSS 处理后输出的图像数据,可叠加用户通过 Region
模块设置的 OSD 图像,然后按不同协议进行编码并输出相应码流。

	VDA 模块接收 VI 的输出图像,并进行移动侦测和遮挡侦测,最后输出侦测分析
结果。

	VO 模块接收 VPSS 处理后的输出图像,可进行播放控制等处理,最后按用户配置
的输出协议输出给外围视频设备。
	
	AI 模块捕获音频数据,然后 AENC 模块支持按多种音频协议对其进行编码,最后
输出音频码流。
	
	用户从网络或外围存储设备获取的音频码流可直接送给 ADEC 模块, ADEC 支持
解码多种不同的音频格式码流,解码后数据送给 AO 模块即可播放声音。

2、sample中SAMPLE_VENC_1080P_CLASSIC函数

mpp/sample/venc/sample_venc.c

typedef int                     HI_S32;
#define HI_VOID                 void
HI_S32 SAMPLE_VENC_1080P_CLASSIC(HI_VOID)//列举函数中的部分内容进行讲解
{
	//变量名前的en表示这是一个枚举类型的变量
    PAYLOAD_TYPE_E enPayLoad[3]= {PT_H264, PT_H264,PT_H264};//视频
    PIC_SIZE_E enSize[3] = {PIC_HD1080, PIC_VGA,PIC_QVGA};#视频分辨率

	变量名末尾的_S表示这是一个结构体类型的变量
    VB_CONF_S stVbConf;
    SAMPLE_VI_CONFIG_S stViConfig = {0};
   //......
}

(1)PAYLOAD_TYPE_E
在这里插入图片描述

typedef enum
{
    PT_PCMU          = 0,
    PT_1016          = 1,
    PT_G721          = 2,
    PT_GSM           = 3,
    PT_G723          = 4,
    PT_DVI4_8K       = 5,
    PT_DVI4_16K      = 6,
    PT_LPC           = 7,
    PT_PCMA          = 8,
    PT_G722          = 9,
    PT_S16BE_STEREO  = 10,
    PT_S16BE_MONO    = 11,
    PT_QCELP         = 12,
    PT_CN            = 13,
    PT_MPEGAUDIO     = 14,
    PT_G728          = 15,
    PT_DVI4_3        = 16,
    PT_DVI4_4        = 17,
    PT_G729          = 18,
    PT_G711A         = 19,
    PT_G711U         = 20,
    PT_G726          = 21,
    PT_G729A         = 22,
    PT_LPCM          = 23,
    PT_CelB          = 25,
    PT_JPEG          = 26,
    PT_CUSM          = 27,
    PT_NV            = 28,
    PT_PICW          = 29,
    PT_CPV           = 30,
    PT_H261          = 31,
    PT_MPEGVIDEO     = 32,
    PT_MPEG2TS       = 33,
    PT_H263          = 34,
    PT_SPEG          = 35,
    PT_MPEG2VIDEO    = 36,
    PT_AAC           = 37,
    PT_WMA9STD       = 38,
    PT_HEAAC         = 39,
    PT_PCM_VOICE     = 40,
    PT_PCM_AUDIO     = 41,
    PT_AACLC         = 42,
    PT_MP3           = 43,
    PT_ADPCMA        = 49,
    PT_AEC           = 50,
    PT_X_LD          = 95,
    PT_H264          = 96,
    PT_D_GSM_HR      = 200,
    PT_D_GSM_EFR     = 201,
    PT_D_L8          = 202,
    PT_D_RED         = 203,
    PT_D_VDVI        = 204,
    PT_D_BT656       = 220,
    PT_D_H263_1998   = 221,
    PT_D_MP1S        = 222,
    PT_D_MP2P        = 223,
    PT_D_BMPEG       = 224,
    PT_MP4VIDEO      = 230,
    PT_MP4AUDIO      = 237,
    PT_VC1           = 238,
    PT_JVC_ASF       = 255,
    PT_D_AVI         = 256,
    PT_DIVX3		 = 257,
    PT_AVS			 = 258,
    PT_REAL8		 = 259,
    PT_REAL9		 = 260,
    PT_VP6			 = 261,
    PT_VP6F			 = 262,
    PT_VP6A			 = 263,
    PT_SORENSON	 	 = 264,
    PT_H265          = 265,
    PT_MAX           = 266,
    /* add by hisilicon */
    PT_AMR           = 1001,
    PT_MJPEG         = 1002,
    PT_AMRWB         = 1003,
    PT_BUTT
} PAYLOAD_TYPE_E;

(2)PIC_SIZE_E:图片的分辨率大小的枚举类型

typedef enum hiPIC_SIZE_E
{
    PIC_QCIF = 0,
    PIC_CIF,
    PIC_2CIF,
    PIC_HD1,
    PIC_D1,
    PIC_960H,

    PIC_QVGA,    /* 320 * 240 */
    PIC_VGA,     /* 640 * 480 */
    PIC_XGA,     /* 1024 * 768 */
    PIC_SXGA,    /* 1400 * 1050 */
    PIC_UXGA,    /* 1600 * 1200 */
    PIC_QXGA,    /* 2048 * 1536 */

    PIC_WVGA,    /* 854 * 480 */
    PIC_WSXGA,   /* 1680 * 1050 */
    PIC_WUXGA,   /* 1920 * 1200 */
    PIC_WQXGA,   /* 2560 * 1600 */

    PIC_HD720,   /* 1280 * 720 */
    PIC_HD1080,  /* 1920 * 1080 */
    PIC_2304x1296, /* 3M:2304 * 1296 */
    PIC_2592x1520, /* 4M:2592 * 1520 */
    PIC_5M,        /* 2592 * 1944 */
    PIC_UHD4K,     /* 3840 * 2160 */
    PIC_12M,       /* 4000 * 3000 */

    PIC_BUTT
} PIC_SIZE_E;

(3)VB_CONF_S
VB_CONF_S:定义视频缓存池属性结构体

二、视频缓存池

1、什么是视频缓冲池

(1)视频的本质是多帧图片,图片的本质是RGB或rawRGB数据,要占用一段连续内存

(2)视频的裁剪、缩放、修正处理等各种操作,本质上就是对内存中的数据进行运算

(3)视频缓存池(VB, video buffer)就是一段很大,又被合理划分和管理的内存,用来做视频数据的暂存和运算场地

4)公共视频缓存池的公共2字,可以理解为全局变量,也就是各个模块都能访问的一段内存

(5)看似视频缓存块在各个模块之间流转,实际上并没有内存复制,而是指针在传递

(6)视频缓存池的内存由MPP来维护,我们在系统启动时就把整个SDRAM分成了2部分:系统部分(由linux kernel来维护管理)和mpp部分(由mpp系统来维护管理)

(7)缓存池需要几个,每个中包含几个缓存块,每个缓存块多大,都是可以由用户程序设置好参数,然后调用MPP的相应API来向MPP申请分配的。

	视频缓存池主要向媒体业务提供大块物理内存管理功能,负责内存的分配和回收,充
分发挥内存缓存池的作用,让物理内存资源在各个媒体处理模块中合理使用。一组大小相同
、物理地址连续的缓存块组成一个视频缓存池。

	视频输入通道需要使用公共视频缓存池。所有的视频输入通道都可以从公共视频缓存
池中获取视频缓存块用于保存采集的图像(如图中所示从公共视频缓存池 A 中获取视频缓
存块 Bm)。由于视频输入通道不提供创建和销毁公共视频缓存池功能,因此,在系统初始
化之前,必须为视频输入通道配置公共视频缓存池。根据业务的不同,公共缓存池的数量、
缓存块的大小和数量不同。 

	图中所示缓存块的生存期是指经过 VPSS 通道传给后续模块的情形( 图实线路径)。如果该缓存块完全没有经过 VPSS 通道传给其他模块,则将在 VPSS 模块处理后被放回公共缓存池( 图虚线路径

在这里插入图片描述

2、相关的数据结构和API

(1)VB_CONF_S:定义一个视频缓存池变量

#define MAX_MMZ_NAME_LEN             16

#define VB_MAX_POOLS 256
#define VB_MAX_COMM_POOLS 16
#define VB_MAX_MOD_COMM_POOLS 16

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;

(2)HI_MPI_VB_SetConf:对视频缓存池的属性进行填充,进行参数设置

HI_S32 HI_MPI_VB_SetConf (const VB_CONF_S *pstVbConf);
参数描述:pstVbConf 视频缓存池属性指针。静态属性。输入
返回值:返回0表示成功,非0表示失败
头文件: hi_comm_vb.h、 mpi_vb.h
库文件: libmpi.a

注意:
	只能在系统处于未初始化的状态下,才可以设置缓存池属性,否则会返回失败。video buf
根据不同的应用场景需要不同的配置。
	公共缓存池中每个缓存块的大小应根据当前图像像素格式以及图像是否压缩而有所不同。具
体分配大小请参考 VB_CONF_S 结构体中的描述。

(3)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 配置缓存池属性,再初始化缓存池,否则会失败。
	可反复初始化,不返回失败。
示例代码:
HI_S32 s32ret;
VB_CONF_S stVbConf;

memset(&stVbConf,0,sizeof(VB_CONF_S));

stVbConf.u32MaxPoolCnt = 128;
stVbConf.astCommPool[0].u32BlkSize = 768*576*2;
stVbConf.astCommPool[0].u32BlkCnt = 20;
stVbConf.astCommPool[1].u32BlkSize = 384*288*2;
stVbConf.astCommPool[1].u32BlkCnt = 40;

s32ret = HI_MPI_VB_SetConf(&stVbConf);
if (HI_SUCCESS != s32ret)
{
	printf("set vb err:0x%x\n", s32ret);
	return s32ret;
}

s32ret = HI_MPI_VB_Init();
if (HI_SUCCESS != s32ret)
{
printf("init vb err:0x%x\n", s32ret);
return s32ret;
}

(void)HI_MPI_VB_Exit();//去初始化 MPP 视频缓存池,与HI_MPI_VB_Init相对立,进行清楚工作

三、程序流程分析和MPP初始化详解

1、整个main流程分析

int main(int argc, char *argv[])
	s32Ret = SAMPLE_VENC_1080P_CLASSIC();
		step  1: init sys variable
			SAMPLE_COMM_VI_GetSizeBySensor(&enSize[0]);	
			填充VB_CONF_S 的变量
		step 2: mpp system init
			s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
		step 3: start vi dev & chn to capture	
		step 4: start vpss and vi bind vpss(启动vpss并将vpss和vi绑定)
		step 5: start stream venc(编码)
		step 6: stream venc process -- get stream, then save it to file.(处理码流)
		step 7: exit process 
	
	if (HI_SUCCESS == s32Ret)
        printf("program exit normally!\n");
    else
        printf("program exit abnormally!\n");
    exit(s32Ret);

2、MPP系统初始化详解(参考SAMPLE_VENC_1080P_CLASSIC函数)

(1)什么是MPP系统

  海思提供的媒体处理软件平台(Media Process Platform,简称 MPP),可支持应用软件快速开发。该平台对应用软件屏蔽了芯片相关的复杂的底层处理,并对应用软件直接提供MPI( MPP Programe Interface)接口完成相应功能。该平台支持应用软件快速开发以下功能:输入视频捕获、 H.265/H.264/MJPEG/JPEG/MPEG4 编码、 H.264/MPEG4/MPEG2解码、视频输出显示、视频图像前处理(包括去噪、增强、锐化、 Deinterlace)、编码码流叠加 OSD、视频侦测分析、智能分析、音频捕获及输出、音频编解码等功能。

  一般而言sensor的分辨率是要高于视频的分辨率,留有余量的,因为镜头和sensor安装位置的原因,不能百分百的保证sensor的像素点都能采集到有效信息。

step  1: init sys variable 
    memset(&stVbConf,0,sizeof(VB_CONF_S));
	SAMPLE_COMM_VI_GetSizeBySensor(&enSize[0]);
    if (PIC_HD720 == enSize[0])//一个主码流,两个子码流,画面内容相同,但格式、
    {						   //大小不同
        enSize[1] = PIC_VGA;			
		enSize[2] = PIC_QVGA;
		s32ChnNum = 3;	//通道数为3
	}	
HI_S32 SAMPLE_COMM_VI_GetSizeBySensor(PIC_SIZE_E *penSize)
{
    HI_S32 s32Ret = HI_SUCCESS;
    SAMPLE_VI_MODE_E enMode = SENSOR_TYPE;//SENSOR_TYPE是Makefile.param文件中定义传给程序的

    if (!penSize)
    {
        return HI_FAILURE;
    }

//APTINA :公司名
//
AR0130 :传感器的型号
//DC     :接口
//720P   :分辨率
//30FPS  :帧率
    switch (enMode)
    {
        case APTINA_AR0130_DC_720P_30FPS://我们的开发板装的是这个
        case APTINA_9M034_DC_720P_30FPS:
        case SONY_IMX222_DC_720P_30FPS:
        case OMNIVISION_OV9712_DC_720P_30FPS:
        case OMNIVISION_OV9732_DC_720P_30FPS:
        case OMNIVISION_OV9750_MIPI_720P_30FPS:
        case OMNIVISION_OV9752_MIPI_720P_30FPS:
            *penSize = PIC_HD720;
            break;
        case APTINA_AR0230_HISPI_1080P_30FPS:
        case SONY_IMX222_DC_1080P_30FPS:
        case PANASONIC_MN34222_MIPI_1080P_30FPS:
        case OMNIVISION_OV2718_MIPI_1080P_25FPS:
            *penSize = PIC_HD1080;
            break;

        default:
            printf("not support this sensor\n");
            break;
    }

    return s32Ret;
}
	u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,\
	      enSize[0], SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);
	SAMPLE_SYS_ALIGN_WIDTH:用于对齐,向上取整      
	
	HI_U32 SAMPLE_COMM_SYS_CalcPicVbBlkSize(VIDEO_NORM_E enNorm, PIC_SIZE_E enPicSize, PIXEL_FORMAT_E enPixFmt, HI_U32 u32AlignWidth)
		s32Ret = SAMPLE_COMM_SYS_GetPicSize(enNorm, enPicSize, &stSize);	

(2)MPP系统初始化尤其注意API调用的顺序

step 2: mpp system init. 
	s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf); 
		HI_MPI_SYS_Exit();
    	HI_MPI_VB_Exit();
    	s32Ret = HI_MPI_VB_SetConf(pstVbConf);
    	s32Ret = HI_MPI_VB_Init();
    	s32Ret = HI_MPI_SYS_SetConf(&stSysConf);
    	s32Ret = HI_MPI_SYS_Init();

3、几个比较重要的宏

(1)CEILING_2_POWER宏的作用

#define CEILING_2_POWER(x,a)     ( ((x) + ((a) - 1) ) & ( ~((a) - 1) ) )

void t_c()
{
    printf("xxx:%d\n",CEILING_2_POWER(44, 16));
}

xxxx:48
返回:参数2的倍数,且该倍数是最小的大于参数1

注:本资料大部分由朱老师物联网大讲堂课程笔记整理而来、参考了华为海思SDK中提供的开发手册,并且引用了部分他人博客的内容,如有侵权,联系删除!水平有限,如有错误,欢迎各位在评论区交流。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嵌同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值