海思(MPP)媒体处理软件平台(3.1)—–VDEC流程分析

step1:配置VB视频缓存池,初始化MPP系统

1.配置VB视频缓存池

(1)初始化MPP视频缓存池:HI_MPI_VB_Init(HI_VOID)

必须先调用 HI_MPI_VB_SetConf 配置缓存池属性,再初始化缓存池,否则会失败。

(2)设置缓存池属性 HI_S32 HI_MPI_VB_SetConf (const VB_CONF_S *pstVbConf);

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

【定义】

【注释】
对于缓存块u32BlkSize大小怎么定义,还没有弄明白;(由一帧图像大小决定,跟具体的编码格式有关系)
视频池中缓存块的个数u32BlkCnt定义,还没弄明白; (上述大小的缓存块一共有多少个)

2.初始化MPP系统

【描述】

初始化 MPP 系统。除了音频的编解码通道外,所有的音频输入输出、视频输入输出、
视频编码、视频叠加区域、视频侦测分析等都会被初始化。

【语法】

HI_S32 HI_MPI_SYS_Init(HI_VOID);

【参数】

【注意】

  • 必须先调用 HI_MPI_SYS_SetConf 配置 MPP 系统后才能初始化,否则初始化会失
    败。
  • 由于 MPP 系统的正常运行依赖于缓存池,因此必须先调用 HI_MPI_VB_Init 初始化缓存池,再初始化 MPP 系统。
  • 如果多次初始化,仍会返回成功,但实际上系统不会对 MPP 的运行状态有任何影响。
  • 只要有一个进程进行初始化即可,不需要所有的进程都做系统初始化的操作

【举例】

请参见 HI_MPI_SYS_SetConf 的举例。

【理解】

第一步主要目的是初始化MPP系统,但是由资料可知,MPP系统正常运行依赖于缓存池, 必须先初始化缓存池(参考1.配置VB视频缓存池),在初始化MPP系统前需要配置一些参数和初始化有一定的流程,且必须严格按照流程配置。
1)初始化MPP系统前必须先调用HI_MPI_SYS_SetConf 配置 MPP 系统;
找到HI_MPI_SYS_SetConf 说明:

【语法】

HI_S32 HI_MPI_SYS_SetConf(const MPP_SYS_CONF_S *pstSysConf);

【参数】

pstSysConf:系统控制参数指针。静态属性(指只能在系统未初始化、未启用设备或通道时,才能设置的属性)。

需要先定义u32AlignWidth值(整个系统中使用图像的 stride 字节对齐数。取值范围:[1, 1024],一般选择 16 字节对齐。静态属性。)。

【流程】

以上可知 STEP1 的目的是初始化HIMPP 系统,mpp系统依赖于视频池,所以需要先初始化视频池,初始化视频池需要定义视频缓存池属性,就需要先配置缓存池属性结构体,然后开始准备mpp系统初始化;初始化mpp系统前需要先配置系统控制参数;由资料了解到,
必须先调用 HI_MPI_SYS_Exit 去初始化 MPP 系统,再去初始化缓存池(HI_MPI_VB_Exit),否则返回失败。
必须先调用 HI_MPI_VB_ExitModCommPool 去初始化已经创建的模块公共视频缓存池,再去初始化缓存池,否则返回失败。

1,配置视频缓存池结构体;
2,HI_MPI_SYS_Exit ,去初始化mpp系统;
3,HI_MPI_VB_ExitModCommPool ,退出已经建好的公共视频缓存池;
4,HI_MPI_VB_DestroyPool,销毁视频缓存池;
5,HI_MPI_VB_Exit,去初始化缓存池;
6,HI_MPI_VB_SetConf,设置视频缓存池属性;
7,HI_MPI_VB_Init,初始化视频缓存池属性
8,HI_MPI_SYS_SetConf,配置系统控制参数;
9,HI_MPI_SYS_Init,初始化mpp系统;

step2:init mod common VB

设置通用缓冲区的公共缓冲池属性。其实这一步操作是和setp3配置VDEC做基础的,说白了也就是为解码模块开辟一条道路,关于这条路怎么开,开多大,下面会介绍:

1.公共视频缓存池mod common VB(下面流程属于倒推,由结果往前推)

  • 由于视频输入通道不提供创建和销毁公共视频缓存池功能,因此,在系统初始化之前(step1中HI_MPI_VB_ExitModCommPool 退出和HI_MPI_VB_DestroyPool销毁公共缓存池),必须为视频输入通道配置公共视频缓存池(step2中配置参数);
  • 无论是使用解码Module VB方式还是使用User VB方式都需要先创建专属于VDEC模块的VB池,且要保证VB块的大小和个数满足当前解码通道所需图像BUFF的大小和个数;
  • 不同协议解码需要的VB块大小不同,具体计算方法可参见下面的 VB_PIC_BLK_SIZE 定义;
  • VDEC使用的缓存池和step1中定义的缓存池不一样,这里定义的是VDEC专属的缓存池,该 VB 池只允许 VDEC 获取VB 块,其它模块只能使用不能获取;

在下面功能进行前,需要先确定几个参数,因为会影响后面模式设置(以本方案为例):

  • 解码帧存分配方式:g_s32VBSource = 0; ModuleVB 池方式
  • VB_UID_VDEC//定义视频缓冲池的模块 ID
  • PT_H264 //解码协议类型
  • stSize.u32Width = HD_WIDTH;//1920
  • stSize.u32Height = HD_HEIGHT;//1080
  • u32VdCnt = 1 //
    关于视频缓存池的介绍参考上文【海思(MPP)媒体处理软件平台(2)—–视频缓存池】link

(1)初始化模块公共视频缓存池

【语法】

HI_S32 HI_MPI_VB_InitModCommPool(VB_UID_E enVbUid);

【参数】

enVbUid 使用模块公共视频缓冲池的模块 ID。

【注意】

  • 当前公共视频缓冲池仅适用于 VDEC 模块。
  • 必须先调用 HI_MPI_VB_Init 进行公共视频缓冲池初始化。
  • 必须先调用 HI_MPI_VB_SetModPoolConf 配置缓存池属性,再初始化缓存池,否则会失败。
  • 可反复初始化,不返回失败。
  • VDEC 模块公共池仅在解码帧存分配方式使用模块公共 VB 池时才需要创建,即VDEC 的模块参数 VBSource 配置为 0 时。如果 VDEC 的模块参数 VBSource 配置为 1,则不需要创建 VDEC 模块公共 VB 池

(2)设置模块公共视频缓存池属性,HI_MPI_VB_SetModPoolConf

【语法】

HI_S32 HI_MPI_VB_SetModPoolConf(VB_UID_E enVbUid, const VB_CONF_S*pstVbConf)

【参数】

enVbUid:使用模块公共视频缓冲池的模块 ID。
pstVbConf:模块公共视频缓存池属性指针。静态属性。

【注意】

在使用之前需要先退出模块公共缓存池:

(3)配置VDEC 的模块 VB 池结构体

pstModVbConf->u32MaxPoolCnt = 2;//最大缓存池
使用VB_PIC_BLK_SIZE(pstSize->u32Width, pstSize->u32Height, enType, PicSize);//计算出缓存块大小PicSize
pstModVbConf->astCommPool[0].u32BlkSize = PicSize;
pstModVbConf->astCommPool[0].u32BlkCnt = 5*s32ChnNum; //

【注意】

  • 如果需要解码的 H264 和 MPEG4 码流有 B 帧,或者需要解码的 H265 码流支持时域运动矢量预测(sps_temporal_mvp_enabled_flag =1),如果要正常解码,则还需要为其分配输出每一帧 Pmv 信息的 VB 块,该 VB 块的大小比图像 VB 块小很多,所需个数为 RefFrameNum+1,具体大小计算可参见下面的VB_PMV_BLK_SIZE 定义,否则会导致解码出现花屏等错误
  • 如果 H.264/MPEG4 解码不需要解码 B 帧,或者 H.265 解码不需要解码支持时域运动矢量预测(sps_temporal_mvp_enabled_flag = 1)的码流,则创建通道时可设置此通道不支持时域运动矢量预测(bTemporalMvpEnable 设置为 0),此种情况不输
    出 Pmv 信息,可以不用创建 Pmv VB 池,节省 MMZ 内存。

step3:start VDEC配置解码器,创建解码通道,使能加收解码流。

如果说step2是为第step做基础,那么step3就应该开始配置VDEC解码器了

1.配置解码器

(1)定义视频解码通道属性结构体

VDEC_CHN_ATTR_S

【定义】

【例程】

这里每个通道都要配置

【描述】

  • 码流缓存的大小。
    取值范围:帧模式解码且使用码流 Buffer 省内存模式时,大于等于 32KB;其它情况大于等于解码通道大小(宽 x 高)的 3/4 倍,即 420 图像大小的一半(宽 x 高 x3/2×1/2),以 byte 为单位。推荐值:一幅 YUV420 解码图像大小。即:宽 x 高 x1.5。最大值不能超过 2 x 8192 x 8192 byte。
  • u32RefFrameNum参考帧的数目。取值范围:[0, 16],以帧为单位。参考帧的数目决定解码时需要的参考帧个数,会较大的影响内存 VB 块占用,根据实际情况设置合适的值。
    海思自编码流:推荐设为 2。
    其他监控码流:推荐设为 5。
    测试码流:推荐设为 16。
  • enMode码流发送方式。支持按帧或者按流发送码流。
    VIDEO_MODE_FRAME //流式发送
    VIDEO_MODE_FRAME //按帧发送
  • bTemporalMvpEnable 是否支持时域运动矢量预测
    如果 H.264/MPEG4 解码不需要解码 B 帧,或者 H.265 解码不需要解码支持时域运动矢量预测(sps_temporal_mvp_enabled_flag = 1)的码流,则配置bTemporalMvpEnable 为 0,否则配置为 1;如果支持协议切换,创建通道时 bTemporalMvpEnable 需要配置为 1。当配置为 0 时,可不分配输出 Pmv 信息的 VB 块,节省MMZ 内存。
  • 帧码流解码只解 I 帧时可以把参考帧设置为 0 以节省帧存。
  • 场码流解码只解 I 场时必须把参考帧设置为 1 才能解码,把参考帧设置为 0 解不出图像。

2.创建解码通道

码流发送方式 enMode 可在接口 HI_MPI_VDEC_CreateChn 中设置。两种发送方式都须保证每次调用发送接口发送的码流大小不超过通道属性中设置的 buffer 大小。

(1)HI_MPI_VDEC_CreateChn 创建视频解码通道

【语法】

HI_S32 HI_MPI_VDEC_CreateChn(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S*pstAttr)

【参数】

VdChn:视频解码通道 。取值范围:[0, VDEC_MAX_CHN_NUM)。
pstAttr:解码通道属性指针。

【说明】

解码帧存分配方式
解码 ModuleVB 池:创建解码通道时不分配图像 Buffer,而是由用户调用相应
的 MPI 接口创建专属于解码模块的 ModuleVB 池,该 VB 池只允许 VDEC 获取
VB 块,其它模块只能使用不能获取。支持协议切换时,用户需要预先分配
PMV VB 内存。
解码 PrivateVB 池:创建解码通道时由 VDEC 创建私有 VB 池作为该通道的图
像 Buffer,用户可以在创建通道前调用接口 HI_MPI_VDEC_SetChnVBCnt 来设
置通道私有 VB 池的 VB 个数,默认个数为 5。支持协议切换时,系统默认分
配 PMV VB 内存。
解码 UserVB 池:创建解码通道时不分配图像 Buffer,而是由用户调用接口
HI_MPI_VB_CreatePool 创建一个视频缓存 VB 池,再通过调用接口
HI_MPI_VDEC_AttachVbPool 把某个解码通道绑定到固定的视频缓存 VB 池
中。支持协议切换时,用户需要预先分配 PMV VB 内存。

由于我们使用的是ModuleVB 方式,我们在SETP2中已经创建解码通道了,这里就不用再配置了。

step4: start VPSS

配置VPSS参数,VPSS模块接收VDEC解码后的图像并对流进行处理,如裁剪、降噪等,解码实例从简单应用出发,仅仅按默认的方式配置VPSS。

【基本概念】

在芯片中VPSS可能只有一个或两个,然后我们多个模块要用vpss就得去复用这个vpss,那么我们就申请一个VPSS ,这样就好像有很多vpss,实际上我们用的都是同一个硬件,这里申请的vpss 就是GROUP,海思中有一个很重要的思想就是复用的思想。
还有就是channel,这里每个VPSS GROUP可以有很多路输出,而且每个channel的输出实现的功能不一样,但是每个group仅可以和一个输入源进行绑定。
简单来说,group是针对发送者来说的,比如vi/vdec等,数据发送者把数据发到vpss的某个group中,整个vpss模块有N多个group。
每个vpss group又有N个channel,这些channel是对于后续数据接受者来说的。
总的来说一个数据源,比如vi,可以吧数据送到多个接收者,比如channel0送到vo,channel1到VENC,可以认为是一个一分多,而这些数据通道的建立可以通过“绑定”来实现。

  • GROP:
    VPSS 对用户提供组(GROUP)的概念。最大可用数为 256 个,各 GROUP 分时复用 VPSS 硬件。每个 VPSS GROUP 包含多个通道,通道数目视方案实现有所不同,具体描述请参见 CHANNEL。

【功能描述】

HI_S32 HI_MPI_VO_SetPubAttr(VO_DEV VoDev, const VO_PUB_ATTR_S*pstPubAttr);

VoDev:视频输出设备 。
pstPubAttr:视频输出设备公共属性结构体指针。静态属性。

3.启用视频输出设备,HI_MPI_VO_Enable

HI_S32 HI_MPI_VO_Enable (VO_DEV VoDev);

4.配置HDMI 参数

(1)定义 HDMI 视频制式

(2)初始化 HDMI,HI_MPI_HDMI_Init

HI_MPI_HDMI_Init();

(3)HDMI 回调函数结构体

g_stHdmiArgs.enHdmi = HI_HDMI_ID_0;
g_stCallbackFunc.pfnHdmiEventCallback = HDMI_EventCallBack;
g_stCallbackFunc.pPrivateData = &g_stHdmiArgs;

(4)打开 HDMI。

HI_MPI_HDMI_Open(HI_HDMI_ID_0);

(5)注册事件回调函数

HI_MPI_HDMI_RegCallbackFunc(HI_HDMI_ID_0, &g_stCallbackFunc);

(6)获取 HDMI 属性

HI_MPI_HDMI_GetAttr(HI_HDMI_ID_0, &stAttr);
设置属性:

(7)设置 HDMI 属性

HI_MPI_HDMI_SetAttr(HI_HDMI_ID_0, &stAttr);

4.配置视频层参数

step6: VDEC bind VPSS,绑定VDEC与VPSS

HI_MPI_SYS_Bind(&stSrcChn, &stDestChn)

step7: VPSS bind VO,

HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);

step8: send stream to VDEC

推送视频流数据,这一步需要文件读写配合使用。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年4月6日
下一篇 2020年4月6日

相关推荐