😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍海思视频缓存池🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰: 2024-08-12 23:03:45

本文未经允许,不得转发!!!


在这里插入图片描述
在这里插入图片描述

🎄一、概述

海思芯片的一个主要功能就是处理音视频,而处理音视频(特别是视频)时需要大量的内存暂存或运算视频帧。海思芯片又将物理内存分成两部分:OS内存、MMZ内存。这些专门用来处理视频的内存,在海思MPP中被称为 视频缓存池 。本文就根据自己的理解介绍海思MPP的视频缓存池。

关于OS内存、MMZ内存不了解的,可以参考这篇文章:【海思SS626 | 内存管理】海思芯片的OS内存、MMZ内存设置

视频缓冲池(VB,Video Buffer):就是一段很大、又被合理划分和管理的内存,这段内存是从 MMZ内存 中分配的,专门用来做视频数据的暂存和运算场地。 视频缓存池由海思MPP系统管理,用户可以通过调用海思MPP的相关 API 函数来管理视频缓存池。视频缓存池主要有以下四类:

  • 公共视频缓存池(Common VB);
  • 模块视频缓存池(Module VB);
  • 私有视频缓存池(Private VB);
  • 用户视频缓存池(User VB);

操作VB的相关API函数如下:
在这里插入图片描述


在这里插入图片描述

🎄二、公共视频缓存池(Common VB)

公共视频缓存池,是各个模块都能访问的一段内存。

下面内容引用自 SS626ReleaseDoc\zh\01.software\board\MPP\MPP 媒体处理软件 V5.0 开发参考.pdf 2.3.1 小节

  • 视频缓存池主要向媒体业务提供大块物理内存管理功能,负责内存的分配和回收,充分发挥内存缓存池的作用,让物理内存资源在各个媒体处理模块中合理使用。
  • 一组大小相同、物理地址连续的缓存块组成一个视频缓存池。必须在系统初始化之前配置公共视频缓存池。根据业务的不同,公共缓存池的数量、缓存块的大小和数量不同。
  • 所有的视频输入通道都可以从公共视频缓存池中获取视频缓存块用于保存采集的图像。

下图典型的公共视频缓存池数据流图:

  • VI 从公共视频缓存池 B 中获取视频缓存块 Bm,缓存块 Bm 经 VI 发送给 VPSS,输入缓存块 Bm 经过 VPSS 处理之后被释放回公共视频缓存池。
  • 假设 VPSS 通道的工作模式是 USER,则 VPSS 通道 0 从公共视频缓存池 B 中获取缓存块 Bi 作为输出图像缓存 buffer 发送给 VENC,Bi 经 VENC 编码完之后释放回公共视频缓存池;VPSS 通道 1 从公共视频缓存池 B 中获取缓存块 Bk 作为输出图像缓存 buffer 发送给 VO,,Bk 经 VO 显示完之后释放回公共视频缓存池。
  • 看起来是缓存块在各个模块中流转,实际上只是传递视频缓存块的指针,这样可以避免大量的内存复制。

在这里插入图片描述

设置的公共缓存池,MPP系统也会去获取,并不是只有调用 get_blk 才会获取。

下面是分配公共视频缓存池的例子:

// 01_sys_vb
// aarch64-mix410-linux-gcc 01_sys_vb.c -I hi_sdk/SS626V100_SDK_V2.0.1.0/include/ -L hi_sdk/SS626V100_SDK_V2.0.1.0/lib/ \
-lsecurec -lpthread -ldl -lm -lmpi -ldnvqe -lupvqe -lVoiceEngine -o sys_vb

#include "hi_common_sys.h"
#include "hi_common_vb.h"

#include "hi_mpi_vb.h"
#include "hi_mpi_sys.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* vb init & MPI system init */
hi_s32 sample_comm_sys_init(const hi_vb_cfg *vb_cfg)
{
    hi_s32 ret;

    hi_mpi_sys_exit();
    hi_mpi_vb_exit();

    if (vb_cfg == HI_NULL) {
        printf("input parameter is null, it is invalid!\n");
        return HI_FAILURE;
    }

    ret = hi_mpi_vb_set_cfg(vb_cfg);
    if (ret != HI_SUCCESS) {
        printf("hi_mpi_vb_set_conf failed!\n");
        return HI_FAILURE;
    }

    ret = hi_mpi_vb_init();
    if (ret != HI_SUCCESS) {
        printf("hi_mpi_vb_init failed!\n");
        return HI_FAILURE;
    }

    ret = hi_mpi_sys_init();
    if (ret != HI_SUCCESS) {
        printf("hi_mpi_sys_init failed!\n");
        hi_mpi_vb_exit();
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

/* vb exit & MPI system exit */
hi_void sample_comm_sys_exit(hi_void)
{
    hi_mpi_sys_exit();
    hi_mpi_vb_exit_mod_common_pool(HI_VB_UID_VDEC);
    hi_mpi_vb_exit_mod_common_pool(HI_VB_UID_VDEC_ADAPT);
    hi_mpi_vb_exit();
    return;
}

int main()
{
	hi_vb_cfg vb_conf = {0};
	vb_conf.max_pool_cnt = 1;/* 1 pool cnt */
    vb_conf.common_pool[0].blk_cnt = 11;
    vb_conf.common_pool[0].blk_size = 1920*1080*1.5;
	sample_comm_sys_init(&vb_conf);
	
	int count = 0;
	while(count++ < 20)
		sleep(1);
	
	sample_comm_sys_exit();
	return 0;
}

运行后可以使用cat /proc/umap/vb查看分配的视频缓存池,如下图:
在这里插入图片描述


在这里插入图片描述

🎄三、模块视频缓存池(Module VB)

模块视频缓存池是特定的模块才会使用。SS626的模块视频缓冲池仅适用于VDEC模块,解码帧存分配方式可通过接口ss_mpi_vdec_set_mod_param的参数vb_src来设置。HI_VB_SRC_MOD表示设置为模块视频缓存池。

解码ModuleVB池:创建解码通道时不分配图像Buffer,而是由用户调用相应的MPI接口创建专属于解码模块的ModuleVB池,该VB池只允许VDEC获取VB块,其它模块只能使用不能获取。

对于SS626V100,不同的解码通道部署模式使用的模块VB池不同:部署模式为OT_VDEC_DEPLOYMENT_MODE0的通道,模块vb使用uid为OT_VB_UID_VDEC的ModuleVB池;部署模式为OT_VDEC_DEPLOYMENT_MODE0的通道,模块vb使用uid为OT_VB_UID_VDEC_ADAPT的ModuleVB池。

使用解码ModuleVB池方式时要在创建解码通道之前要先创建专属于VDEC的模块VB池,使用解码UserVB方式时也要先创建用于解码的视频缓存VB池,且要保证VB块的大小和个数满足当前解码通道所需图像Buffer的大小和个数。

H264、 H265、MPEG4解码每个解码通道所需VB个数至少为参考帧+显示帧+1, JPEG/MJPEG解码每个解码通道所需VB个数至少为显示帧+1。不同协议解码所需的图像VB块大小不同,具体计算方法可参见ot_buffer.h里面的函数ot_vdec_get_pic_buf_size

模块视频缓存池的使用:

  • 必须先调用 ss_mpi_vb_init 进行公共视频缓冲池初始化。
  • 必须先调用 ss_mpi_vb_set_mod_pool_cfg 配置缓存池属性,再初始化缓存池,否则会失败。
  • VDEC模块公共池仅在解码帧存分配方式使用模块公共VB池时才需要创建。

模块视频缓存池相关的api函数:

td_s32 ss_mpi_vb_init_mod_common_pool(ot_vb_uid vb_uid);
td_s32 ss_mpi_vb_exit_mod_common_pool(ot_vb_uid vb_uid);
td_s32 ss_mpi_vb_set_mod_pool_cfg(ot_vb_uid vb_uid, const ot_vb_cfg *vb_cfg);
td_s32 ss_mpi_vb_get_mod_pool_cfg(ot_vb_uid vb_uid, ot_vb_cfg *vb_cfg);

在这里插入图片描述

🎄四、私有视频缓存池(Private VB)

海思 SS626 的 编码帧存、解码帧存 都可以设置成私有视频缓存池(Private VB)。私有视频缓存池一般由MPP系统内部创建并使用的,没有相关的api接口函数。

编码PrivateVB池方式:

可以调用 ss_mpi_venc_set_mod_param 接口将模块参数设置为OT_VB_SRC_PRIVATE表示使用编码PrivateVB池方式。

创建编码通道时由VENC创建私有VB池作为该通道的参考帧和重构帧buffer。使用PrivateVB方式时每个编码通道之间没有关联,单独销毁某个通道对其它通道无影响,使用灵活。

解码PrivateVB池:
可以调用 ss_mpi_vdec_set_mod_param 的将模块参数参数vb_src设置为OT_VB_SRC_PRIVATE表示使用解码PrivateVB池方式。

创建解码通道时由VDEC创建私有VB池作为该通道的图像Buffer,用户可以在创建通道接口ss_mpi_vdec_create_chn中设置私有VB池的个数frame_buf_cnt和VB块的大小frame_buf_size。

如果解码帧存分配方式使用的是解码PrivateVB池,则用户需要根据解码码流配置解码所需的帧存VB大小frame_buf_size和个数frame_buf_cnt,以及存放tmv信息的VB大小tmv_buf_size,解码器内部按此配置创建相应的私有VB池。


在这里插入图片描述

🎄五、用户视频缓存池(User VB)

如果使用UserVB方式,需要先创建VB池,再把n个通道绑定到对应的VB池中。通道个
数大于2的情况,使用UserVB可以减少内存消耗,需要的帧存个数请参考多通道使用
的情况;通道数为1或2的情况,也不会增加内存消耗,此时需要的帧存个数可以参考
单通道使用的情况。

在这里插入图片描述

🎄六、

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考:
《MPP 媒体处理软件 V5.0 开发参考.pdf》
什么是视频缓存池
https://blog.csdn.net/weixin_42031299/article/details/129477605

Logo

海思 HiSpark 开发者社区是上海海思为开发者搭建的内容和交流平台,依托完备芯片解决方案、专业开发环境、开源/开放的软件资源与社区技术内容,构建完整服务生态开发者的闭环体系。

更多推荐