V821 多媒体内存优化指南
前言
编写目的
本文档旨在介绍多媒体内存优化的常规优化措施和特定场景下优化措施,用于指导编码产品多媒体内存优化。
常规优化措施包括:
- 使用在线编码
- 调整分辨率
- 增大 LBC 压缩倍数
- 调整 VBV buffer 缓存时长
特定场景优化措施包括:
- 离线编码时 VIPP 配置 2 个 buffer
- TDM 配置单 buffer 模式
- VE 编码参考帧 buffer 和重建帧 buffer 复用
读者对象
本文档(本指南)主要适用于以下人员:
-
技术支持工程师
-
软件开发工程师
适用范围
适用产品列表
:::
| 产品名称 | 内核版本 |
|---|---|
| V821 | Linux-5.4 |
文档约定
标志说明
注意
- 提醒操作中应注意的事项 。不当的操作可能会损坏器件,影响可靠性、降低性能等。
:::
备注
为准确理解文中指令、正确实施操作而提供的补充或强调信息。
:::
提示
一些容易忽视的小功能、技巧。了解这些功能或技巧能帮助解决特定问题或者节省操作时间。
:::
相关术语介绍
- CSI(Camera Serial Interface):相机串行接口,DVP(Digital Video Port)数字视频端口
- MIPI(Mobile Industry Processor Interface):MIPI 联盟(TI、ST、ARM、Nokia)定义的移动行业处理器接口,如 MIPI CSI-2(Camera)、MIPI DSI(Display)
- TDM(Time Division Multiplexing):帧级分时复用控制器
- TDM RX(receive):帧级分时复用控制器的接收端
- TDM TX(transmit):帧级分时复用控制器的发送端
- ISP(Image Signal Processing):图像信号处理器
- VIPP(Video Input Processor):视频输入处理器
- VE/VENC(Video Encoder):视频编码器
- MPP(Media Process Platform):媒体处理平台
- ORL(Object Rectangle Label):物体矩形框标注
- LBC(Lossy Block Compression):有损块压缩
- LBD(Lossy Block Decompression):有损块解压缩
- ISP D3D:ISP 3D降噪
- hblank:行消隐,当扫描点到达图像右侧边缘时,扫描点快速返回左侧,重新开始在第1行的起点下面进行第2行扫描,行与行之间的返回过程称为行消隐
- vblank:场消隐,扫描点扫描完一帧后,要从图像的右下角返回到图像的左上角,开始新一帧的扫描,会有一段间隔时间,这个时间间隔是场消隐
- VBV buffer(Video Buffering Verifier):视频缓冲验证器,用于控制编码码流的缓冲大小
- WDR(Wide Dynamic Range):宽动态范围,一种提高图像亮暗区域细节的技术
- 在线编码(Online Encoding):VIPP 与 VE 硬件通过共享 buffer 直接传输数据的编码模式,无需经过应用层传递
- 离线编码(Offline Encoding):VIPP 与 VE 之间的数据传递需经过应用层 MPP 的编码模式,需配置更多 buffer
- buffer:缓冲区,用于临时存储视频帧数据的内存空间
了解了上述术语后,下面介绍多媒体内存优化的整体情况。
多媒体内存优化概述
对于小内存(比如:64MB、128MB)方案,内存资源少,为保证能同时开启更多功能,需要进行内存优化。
内存优化主要包含以下几个方面:
- 系统内存优化
- 多媒体内存优化
- 应用内存优化
本文主要介绍多媒体内存优化,涉及 TDM(帧级分时复用控制器)、ISP(图像信号处理器)、VIPP(视频输入处理器)、VENC(视频编码器)等模块。
本文档主要分场景介绍编码产品多媒体内存优化的几种措施和预期结果。在介绍多媒体内存优化措施前,先分别介绍单 MIPI sensor 和双 MIPI sensor 两个典型场景下的编码通路情况。
-
单 MIPI sensor 场景下,编码通路框图如下图所示。

该场景下,只有一路 sensor,无需使用 TDM 帧级分时复用控制器。
数据流程:MIPI sensor 采集的图像经过 ISP 处理(ISP 处理需用 ISP D3D buffer),处理后通过硬件传输给 VIPP。根据用户配置,VIPP 对输入的图像进行 CROP(裁剪)、SR(缩放)、ORL(物体矩形框标注)等处理,处理后写入 DMA buffer。VE 的 ENCPP(编码前处理)读取图像视频帧数据,根据用户配置进行 SR(缩放)、Sharp(锐化)、Overlay(叠加 OSD)、Thumb(缩略图)等处理,处理后送给 VEncoder 编码器进行编码。编码器在编码过程中需用到 VE 参考帧/重建帧 buffer。
LBC(有损块压缩)压缩:由于图像数据量大,为节省带宽,需用到 LBC 压缩和解压缩处理。
- ISP D3D(3D 降噪)处理时往 DDR 写读数据前后分别进行 LBC 压缩和 LBD(有损块解压缩)解压缩
- VIPP 往 DMA buffer 写读数据前后分别进行 LBC 压缩和 LBD 解压缩
- VE 编码往参考帧 buffer 写读数据前后分别进行 LBC 压缩和 LBD 解压缩
其中,ISP D3D 默认配置 LBC1.5X,暂不支持用户配置;VIPP 的 LBC 压缩支持用户配置,可配置不同的压缩比(LBC1.0X、LBC1.5X、LBC2.0X 和 LBC2.5X);VE 编码参考帧的 LBC 压缩支持用户配置,可配置不同的压缩比(NO_LOSSY、LBC1.5X、LBC2.0X 和 LBC2.5X)。
该场景下编码通路中可优化的 buffer:VE 参考帧/重建帧 buffer。
-
双 MIPI sensor 场景下,编码通路框图如下图所示。

该场景下,有 2 路 sensor,需使用 TDM 帧级分时复用控制器。
数据流程:与单 MIPI sensor 场景不同的是,由于只有一个 ISP 硬件,2 路 MIPI sensor 采集的图像在送给 ISP 处理前,需要经过 TDM 帧级分时复用控制器进行处理。
TDM:帧级分时复用控制器,用来辅助 ISP 做分时处理。其中,RX 用来接收对应 sensor 的数据,有多个 RX;TX 用来判断把哪个 RX 的数据发给 ISP 处理。
该场景下编码通路中可优化的 buffer:TDM buffer、VIPP DMA buffer 和 VE 参考帧/重建帧 buffer。
V821平台上关于多媒体硬件模块使用到的内存都通过内存池来申请,所以在V821平台上查看系统使用的多媒体内存通过内存池相关节点获取。获取内存情况信息命令如下:
cat /sys/kernel/debug/size_pool/layout
打印出的信息如下:
size_pool memory layout(+: free, -*/#: busy, unit: 4KB):
...
pool area start:0x82000000 end:0x83400000
pool area Total:20MB Free:20480KB ~= 20MB
| 节点信息 | 说明 |
|---|---|
| pool area start | 内存池起始地址 |
| pool area end | 内存池截至位置 |
| pool area Total | 内存池总大小 |
| pool Free | 内存池空闲大小 |
了解了多媒体内存优化的背景和基本通路后,下面详细介绍具体的优化措施。
多媒体内存优化措施
常规优化措施
多媒体内存大小与编码通路上在线/离线编码、分辨率、码率、帧率、LBC压缩倍数、VBV buffer等配置有关,当多媒体内存占用大时,可 先评估这些参数是否可调节。
另外这里也描述一下系统的一些内存优化措施。
系统裁剪
系统裁剪可以参考《Tina Linux 系统裁剪开发指南》操作,v821 quick_config也提供了一份内存优化配置“memory_optimization”,这个主要是对内核进行裁剪。
配置详情可以查看该文件:device/config/chips/v821/configs/default/quick_config.json
配置方法:
sdk 执行 quick_config,勾选上“memory_optimization”,然后重新sourc 和lunch操作,编译sdk即可。
确认功能生效方法:
可以对比裁剪前后的系统 free内存。
root@(none):/# echo 3 > /proc/sys/vm/drop_caches
root@(none):/# cat /proc/meminfo
内核内存压缩zram
配置方法:
内核配置make kernel_menuconfig 打开:
CONFIG_ZSMALLOC
CONFIG_ZRAM
CONFIG_ZRAM_WRITEBACK
openwrt配置 make menuconfig 打开:
CONFIG_PACKAGE_zram-swap
编译sdk并烧录固件,板子启动后,需要手动配置zram的磁盘大小,以及打开swap,
比如设置12M大小为交换空间,并打开zram:
root@(none):/# echo 12M > /sys/block/zram0/disksize
root@(none):/# mkswap /dev/zram0
root@(none):/# swapon /dev/zram0
如果当前使用的sdk 版本是 v821 TINA 1.3sdk, 以及打上了 GeneralPatch1补丁,那么有quick_config直接配置zram以及打开zram,无需执行上面的操作,只需执行quick_config, 并勾选 “enable_zram”,重新编译sdk并烧录固件即可。
注意事项
内存压缩技术 zram 会对不常用的内存进行压缩处理,需要使用时再解压,可以增加当前系统可用内存,减缓系统内存压力。但是这过程会增加cpu开销,另外打开zram 本身也有一定的 内存开销,所以cpu负载很高,但是内存充裕的场景,不建议打开这个功能。
确认功能生效方法:
板端执行 free 指令,如下,可以看到Swap total为前面设置的12M 大小,used即已经使用的空间,free就是剩余的空间。
root@(none):/# free
total used free shared buff/cache available
Mem: 33584 16528 4980 0 12076 14224
Swap: 12284 256 12028
视频编码
使用在线编码
对于小内存方案,建议优先选择在线编码。在线编码支持配置单buffer和双buffer两种模式。单buffer模式下,其他路离线编码至少配置 4个buffer,否则会因调度问题出现丢帧。双buffer模式下,其他路离线编码可最低配置3个buffer。
离线编码,则可参考特殊场景下优化措施三,优化编码内存。
调整分辨率
VIPP采集的分辨率和编码输出分辨率的大小直接影响到多媒体内存的分配。在其他条件不变的情况下,分辨率越大,消耗的内存越多。
YUV(一种颜色编码方法,非压缩格式)格式图像占用的 buffer 大小计算公式为:宽 × 高 × 1.5。
增大LBC压缩倍数
-
ISP D3D默认配置LBC1.5X,暂不支持用户配置。
-
VIPP 的 LBC 压缩支持用户配置 ,可配置 LBC1.0X、LBC1.5X、LBC2.0X 和 LBC2.5X。为节省内存,推荐配置 LBC2.5X。
// MPP 配置接口
VI_ATTR_S mViAttr;
// 设置像素格式为 LBC 2.5X 压缩
mViAttr.format.pixelformat = map_PIXEL_FORMAT_E_to_V4L2_PIX_FMT(MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X);
AW_MPI_VI_SetVippAttr(mVipp, &mViAttr);
VENC_CHN_ATTR_S mVEncChnAttr;
// 设置编码通道像素格式为 LBC 2.5X
mVEncChnAttr.VeAttr.PixelFormat = MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X;
AW_MPI_VENC_CreateChn(mVEncChn, &mVEncChnAttr);
// RT-MEDIA 配置接口
VideoInputConfig config;
config.pixelformat = RT_PIXEL_LBC_25X; // 设置为 LBC 2.5X
AWVideoInput_Configure(channelId, &config); -
VE 编码参考帧的 LBC 压缩支持用户配置,可配置 NO_LOSSY、LBC1.5X、LBC2.0X 和 LBC2.5X。VE 编码参考帧 LBC 压缩倍数增大时,可能对编码效果有影响,需考虑取舍。推荐配置 LBC1.5X(若不配置,默认是 LBC1.5X)。
// MPP 配置接口
VENC_CHN_ATTR_S mVEncChnAttr;
// 设置编码参考帧 LBC 模式为 1.5X
mVEncChnAttr.VeAttr.mVeRefFrameLbcMode = VENC_REF_FRAME_LBC_MODE_1_5X;
AW_MPI_VENC_CreateChn(mVEncChn, &mVEncChnAttr);
// RT-MEDIA 配置接口
RTeVeLbcMode rec_lbc_mode = RT_LBC_MODE_1_5X; // 设置为 LBC 1.5X
AWVideoInput_SetRecRefLbcMode(channelId, rec_lbc_mode);
调整 VBV buffer 缓存时长
编码目标帧率、编码码率和 VBV buffer 缓存时长会影响 VBV buffer 大小,具体可参考以下公式。
VBV buffer 缓存时长可根据应用实际情况调整,推荐配置 4 秒,如果应用对编码输出码流有缓存,可适当缩短这个缓存时间。
VBV buffer阈值计算公式:vbvBufferThresh = BitRate/8/FrameRate*15
其中,
- FrameRate为编码目标帧率,单位:fps
- 8为bit与byte的转换
- 15为经验值
VBV buffer计算公式:vbvBufferSize = BitRate/8*4 + vbvBufferThresh
其中,
- BitRate为编码码率,单位:bps
- 8为bit与byte的转换
- 4为VBV buffer缓存时长,单位:s
设置接口(以 H264 为例):
ERRORTYPE AW_MPI_VENC_CreateChn(VENC_CHN VeChn, const VENC_CHN_ATTR_S *pAttr);
// 参数 pAttr 的 vbvBuffer 相关设置:
pAttr->VeAttr.AttrH264e.BufSize = vbvBufferSize; // 设置 VBV buffer 大小
pAttr->VeAttr.AttrH264e.mThreshSize = vbvBufferThresh; // 设置 VBV buffer 阈值
视频解码
配置接口:ERRORTYPE AW_MPI_VDEC_CreateChn(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S *pAttr)
-
vbvSize: 在视频解码过程中,vbvSize是存储编码码流的buffer。视频解码驱动的默认的vbvSize会很大,所以低内存方案需自己配置 一个较小的合适的数值。配置视频解码驱动的vbvBufferSize的数值需1024对齐。
pAttr->mBufSize = vbvSize; -
frame number: 视频解码驱动根据视频文件的编码参考帧数量决定初始解码帧数量,用户不可配。考虑解码兼容性以及视频显示需要占 用额外的1帧,允许用户在初始解码帧数量的基础上增加更多的解码帧。有2种方式:
-
配置cedarx.conf中的配置项,mpi_vdec组件运行时读取配置文件的解码帧数量的配置,设置给视频解码库。
# picture num for modules
pic_4list_num = 3V821平台中JPEG视频解码驱动中解码默认会申请一个解码帧,设置pic_4list_num可以让视频解码驱动再额外申请解码帧数。默认 pic_4list_num参数为3,也就是会申请4个解码帧。如只使用JPEG解码驱动解码单帧JPEG图片,那么可以设置pic_4list_num参数为0,这 时候就只会申请一个解码帧,减少了内存的使用。但是这个配置是对所有解码格式和解码场景都生效,所以不建议修改这里。用户可以用 方式2单独对某个解码通道设置。
-
在
ERRORTYPE AW_MPI_VDEC_CreateChn(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S *pAttr);的参数pAttr中配置。pAttr->bEnableExtraFrameNum:为TRUE表示使用用户自定义的额外帧数量,忽略cedarx.conf的配置。
pAttr->mExtraFrameNum:额外增加的解码帧数量,最小为0。jpeg解码场景下,考虑到jpeg图片的解码只需一帧,为使用尽可能少的内存解码大分辨率的jpeg图片,用户可以使用方式2,设置额外帧 数量为0。
-
音频编码
配置接口:ERRORTYPE AW_MPI_AENC_CreateChn(AENC_CHN AeChn, const AENC_CHN_ATTR_S *pAttr)
-
输入pcmBufferSize: 存储待编码的PCM数据,默认64KB。低内存方案可以配置更小的数值。
pAttr->AeAttr.mInBufSize = pcmBufferSize; -
输出的编码帧的数量OutBufCnt: 存储编码的音频帧的数量,数值越大,缓冲越多。默认16。
pAttr->AeAttr.mOutBufCnt = nOutBufCnt;
音频解码
配置接口:ERRORTYPE AW_MPI_ADEC_CreateChn(ADEC_CHN ADecChn, const ADEC_CHN_ATTR_S *pAttr)
-
输入absBufferSize: 存储待解码音频数据,默认896KB。低内存方案可以配置更小的数值。
pAttr->mInBufSize = absBufferSize; -
输出PCMBufferSize: 存储解码后的PCM音频数据,默认128KB。低内存方案可以配置更小的数值。
pAttr->mOutBufSize = PCMBufferSize;
特定场景下优化措施
对于离线编码或者双mipi sensor使用场景,多媒体内存优化措施主要有以下几个:
-
措施一:离线编码时VIPP 配置2个buffer
在线编码和离线编码:在线编码模式下,VIPP0 与VE 硬件通过共享buffer 传输数据,这些在linux内核驱动层已完成,无需经过MPP(多媒体中间件)传递。离线编码模式下,VIPP 与VE 之间的数据传递需经过应用层MPP。在线编码支持单buffer 和双buffer 两种模式。离线编码一般至少需配置3个buffer,否则会因还帧不及时出现丢帧。
VIPP 的online mode 和offline mode:VIPP online mode 是在线模式,该模式下VIPP 无需将数据写到DDR 再回读;VIPP offline mode 是离线模式,该模式下VIPP 需将数据写到DDR 再回读,同时TDM 会消耗两个buffer,而且增大带宽。
离线编码,VIPP offline mode 下,VIPP 可配置2个buffer。
-
措施二:TDM 配置单buffer模式
利用vblank(场消隐) 错开TDM 写入buffer 的时机,可以将TDM 配置成单buffer。当vblank 大于20% 时,硬件时序上可以把控,保证buffer 不会发生覆盖。因此,TDM 配置单buffer模式,要求vblank 大于20%。由于不是所有sensor 的vblank 都能满足大于20% 的要求,所以TDM 默认是配置2个buffer。
大部分sensor 可通过调整寄存器配置,保证vblank 满足大于20% 要求。这样,TDM 可配置单buffer模式,双目场景TDM每路单独使用1个BUFF。
-
措施三:VE 编码参考帧buffer 和重建帧buffer 复用
内存优化前,参考帧与重建帧的转换所需要用到的是至少两个以上的 buffer,前一帧的参考帧在使用完之后,转换为下一帧的重建帧使用的 buffer;而前一帧的重建帧,则作为下一帧的参考帧进行使用。缺点是会占用较多的内存。
内存优化后,VE 编码参考帧buffer 和重建帧buffer 可复用一个。当参考帧读取完的空间,则由重建帧进行写入,这样就可以节约到每一路编码只需要使用一个buffer。
重编码:编码器编码一帧后,若不满足用户要求(I帧大小和P帧大小),根据设置调整编码参数后,需要重新将这一帧送入编码再编码一次,直到满足要求或者达到预设重编次数后停止编码这一帧,继续编码下一帧。
重编码与编码内存优化冲突:开启编码内存优化后,编码过程中参考帧buffer 会被重建帧写入,参考帧数据被破坏。若开启重编码,则无法再次读取当前帧的参考帧数据。
在开启重编码的情况下,VE 编码参考帧buffer 和重建帧buffer 可复用一个。
-
措施四:TDM 配置单buffer交替模式 此模式基于措施二方案进一步优化,达到双目场景TDM共用1个BUFF,具体原理和注意点,参考 措施四-TDM-onebuf交替模式内存优化说明
使用前的配置
为方便检查多媒体内存优化策略的约束条件,以及验证修改是否有效,需先打开以下配置项:
- Tina SDK 配置
make menuconfig,搜索以下配置并打开
KERNEL_DEBUG_FS
KERNEL_PROC_PAGE_MONITOR
- 内核配置
make kernel_menuconfig,搜索以下配置并打开
DEBUG_FS
SUNXI_MPP
CONFIG_VIN_LOG
措施一:离线编码时VIPP 配置2个buffer
约束条件:
只支持在VIPP offline mode 下使用;VIPP online mode 下时序不满足,不能使用。
检查是否满足约束条件方法:
打开配置,通过vi调试节点确认。
make menuconfig,打开 KERNEL_DEBUG_FS
make kernel_menuconfig,打开 DEBUG_FS、SUNXI_MPP 和 CONFIG_VIN_LOG
在串口输入 cat /sys/kernel/debug/mpp/vi 获取vi的调试信息。
确认对应vi设备的调试信息,比如:vipp0 对应vi0。
vi0:
bkuf => cnt: 3 size: 1384448 rest: 3, work_mode: online
其中,work_mode 为 offline,可确认当前VIPP是 offline 模式。
这里bkbuf实际上是指VIPP DMA buffer。
配置方法:
默认关闭,通过 make kernel_menuconfig 修改内核配置打开 CONFIG_FRAMEDONE_TWO_BUFFER 。
需要注意的是,这样修改后,所有的VIPP 都会配置成2个buffer。
确认功能生效方法:
打开配置,通过vi调试节点确认。
make menuconfig,打开 KERNEL_DEBUG_FS
make kernel_menuconfig,打开 DEBUG_FS、SUNXI_MPP 和 CONFIG_VIN_LOG
在串口输入 cat /sys/kernel/debug/mpp/vi 获取vi的调试信息。
确认对应vi设备的调试信息,比如:vipp0 对应vi0。
vi0:
bkuf => cnt: 2 size: 1384448 rest: 1, work_mode: offline
其中,cnt: 2 是指bkbuf个数为2,表示该功能已打开。
这里bkbuf实际上是指VIPP DMA buffer。
措施二:TDM 配置单buffer模式
约束条件:
单mipi sensor 场景不开TDM,对其无效;仅用于双mipi sensor 场景,且需要vblank大于20%
检查是否满足约束条件方法:
通过以下计算公式判断是否满足vblank大于20%的条件。
计算公式:vts - height <= height * 20%
其中,vts是指帧长,height是指sensor的原图高度。
如果不满足,需要修改sensor的寄存器配置。
注意事项:
开启tdm one buffer debug时,如果vblank不满足大于20%的话,vin会有打印提示:[VIN_WARN]use tdm one buffer must ensure sensor vblank >= 20%
配置方法:
默认关闭,通过 make kernel_menuconfig 修改内核配置打开 CONFIG_TDM_ONE_BUFFER 。
确认功能生效方法:
打开配置,通过vi调试节点确认。
make menuconfig,打开 KERNEL_DEBUG_FS
make kernel_menuconfig,打开 DEBUG_FS、SUNXI_MPP 和 CONFIG_VIN_LOG
在串口输入 cat /sys/kernel/debug/mpp/vi 获取vi的调试信息。
确认对应vi设备的调试信息,比如:vipp0 对应vi0。
vi0:
tdmbuf => cnt: 1 size: 1155072, cmp_ratio: 0
其中,cnt: 1 是指tdmbuf个数为1,表示该功能已打开。
措施三:VE 编码参考帧buffer 和重建帧buffer 复用
约束条件:
不能与超大帧重编码同时打开。
检查是否满足约束条件方法:
- 配置超大帧重编码的MPP 接口
VENC_SUPERFRAME_CFG_S mSuperFrmParam;
memset(&mSuperFrmParam, 0, sizeof(VENC_SUPERFRAME_CFG_S));
mSuperFrmParam.enSuperFrmMode = SUPERFRM_REENCODE;
mSuperFrmParam.MaxRencodeTimes = 1;
mSuperFrmParam.MaxP2IFrameBitsRatio = 0.33;
mSuperFrmParam.SuperIFrmBitsThr = 200*1024*8; // 200 KB
mSuperFrmParam.SuperPFrmBitsThr = mSuperFrmParam.SuperIFrmBitsThr / 3;
AW_MPI_VENC_SetSuperFrameCfg(mVEncChn, &mSuperFrmParam);
若配置冲突,MPP有提示错误打印:
fatal error! Exception Case: VeRecRefBufReduce enable and SUPERFRM_REENCODE can not be used at the same time.
- 配置重编码的RT-MEDIA 接口:
RTVencSuperFrameConfig mSuperConfig;
memset(&mSuperConfig, 0, sizeof(RTVencSuperFrameConfig));
mSuperConfig.eSuperFrameMode = RT_VENC_SUPERFRAME_REENCODE;
mSuperConfig.nMaxRencodeTimes = 1;
mSuperConfig.nMaxP2IFrameBitsRatio = 0.33;
mSuperConfig.nMaxIFrameBits = 200*1024*8; // 200 KB
mSuperConfig.nMaxPFrameBits = mSuperConfig.nMaxIFrameBits / 3;
AWVideoInput_SetSuperFrameParam(channel_id, &mSuperConfig);
mSuperFrmParam.enSuperFrmMode = SUPERFRM_NONE 或 SUPERFRM_DISCARD;表示不开启超大帧重编码。
配置方法:
-
配置编码内存优化的 MPP 接口
默认关闭。当关闭超大帧重编码功能时,可通过接口 AW_MPI_VENC_CreateChn 配置打开”VE 编码参考帧 buffer 和重建帧 buffer 复用”功能:
VENC_CHN_ATTR_S mVEncChnAttr;
// 开启参考帧和重建帧 buffer 复用功能
mVencChnAttr.VeAttr.mVeRecRefBufReduceEnable = 1;
AW_MPI_VENC_CreateChn(VeChn, &mVencChnAttr);
- 配置编码内存优化的 RT-MEDIA 接口
VideoInputConfig config;
// 开启参考帧和重建帧内存复用
config.breduce_refrecmem = MAIN_CHANNEL_REDUCE_REFREC_MEM;
AWVideoInput_Configure(channelId, &config);
确认功能生效方法:
打开配置,通过ve_base调试节点确认。
make menuconfig,打开 KERNEL_DEBUG_FS
make kernel_menuconfig,打开 DEBUG_FS、SUNXI_MPP
在串口输入 cat /sys/kernel/debug/mpp/ve_base 获取ve的调试信息。
确认对应ve通道的调试信息,比如:vechn0 对应Ch[0]。
**********Ch[0] H264 F0 BaseInfo Start**********
Ref(Byte): LBC1.5X, Reduce:1, Lbc:61440+1314816, Qsub:6144+118784
**********Ch[0] H264 F0 BaseInfo End**********
其中,Reduce节点信息代表是否开启参考帧buffer与重建帧buffer复用功能,0代表未开启,1代表开启。
注意事项说明
开启参考帧和重建帧buffer复用之后,如果编码过程出现overwrite,参考帧已经损坏,则不能再编P帧,编码会强制出I帧。
原因为重建帧写了buffer一部分,被异常中断丢帧,相当于一个buffer里面夹杂两帧的内容,如果继续使用它做参考,编码P帧,会出现画面断层。
措施四:TDM 配置单buffer交替模式
约束条件:
单mipi sensor 场景不开TDM,对其无效;仅用于双mipi sensor 场景,且需要vblank大于50%
检查是否满足约束条件方法:
通过以下计算公式判断是否满足vblank大于50%的条件。
计算公式:vts - height <= height * 50%
其中,vts是指帧长,height是指sensor的原图高度。
如果不满足,需要修改sensor的寄存器配置。
注意事项:
开启tdm one buffer debug时,如果vblank不满足大于50%的话,vin会有打印提示:[VIN_WARN]use tdm one buffer must ensure sensor vblank >= 50%
确认功能生效方法:
具体原理和注意点,参考 措施四-TDM-onebuf交替模式内存优化说明
以下提供典型场景的实测优化数据供参考。
典型场景多媒体内存优化数据
单mipi sensor 场景
场景描述
规格:
分辨率:1280x720
像素格式:lbc2.5x
帧率:20fps
码率:1Mbps
编码参考帧压缩:lbc1.5x
编码格式:h.265
编码方式:离线编码
VI buffer个数:3
VBV缓存时间:4s
可采用的优化措施
措施三:VE 编码参考帧buffer 和重建帧buffer 复用
措施一、二不适用说明:
单mipi sensor 场景下,VIPP 的work mode 配置的是online mode,故措施一不适用。
单mipi sensor 场景下,不使用TDM 模块,故措施二。
优化前后多媒体内存对比
| 优化措施 | 内存优化收益 |
|---|---|
| VE编码参考帧buffer和重建帧buffer复用 | 0.54MB |
测试前:
系统内存池空闲大小:20.480MB

测试时:
不开多媒体内存优化措施
系统内存占用:8.288MB = 20.480MB - 12.192MB

采用多媒体内存优化措施三
- 措施三:VE 编码参考帧buffer 和重建帧buffer 复用
多媒体内存占用:7.748MB = 20.480MB - 12.732MB
措施三内存收益:0.54MB = 12.732MB - 12.192MB

双mipi sensor 场景
场景描述
Sensor0 这路规格:
分辨率:1280x720
像素格式:lbc2.5x
帧率:20fps
码率:1Mbps
编码参考帧压缩:lbc1.5x
TDM压缩倍数:3.5x
D3D压缩倍数:1.5x
编码格式:h.264
编码方式:离线编码
VI buffer个数:3(内存优化措施一会有调整)
VBV缓存时间:4s
Sensor1 这路规格:
分辨率:1280x720
像素格式:lbc2.5x
帧率:20fps
码率:1Mbps
编码参考帧压缩:lbc1.5x
TDM压缩倍数:1x
D3D压缩倍数:1.5x
编码格式:h.264
编码方式:离线编码
VI buffer个数:3(内存优化措施一会有调整)
VBV缓存时间:4s
可采用的优化措施
措施一:离线编码时VIPP 配置2个buffer
措施二:TDM 配置单buffer模式
措施三:VE 编码参考帧buffer 和重建帧buffer 复用
措施四:TDM 配置单buffer交替模式
优化前后多媒体内存对比
| 优化措施 | 内存优化收益 |
|---|---|
| 离线编码时VIPP 配置2个buffer | 0.564MB |
| TDM 配置单buffer模式 | 2.184MB |
| VE 编码参考帧buffer 和重建帧buffer复用 | 1.152MB |
| TDM 配置单buffer交替模式 | (TDM 配置单buffer模式/2)MB |
ramparser 内存工具获取的内存信息
测试前:
系统内存池空闲大小:25.208MB

测试时:
不开多媒体内存优化措施
多媒体内存占用:16.348MB = 25.208MB - 8.860MB



采用多媒体内存优化措施一
- 措施一:离线编码时VIPP 配置2个buffer
多媒体内存占用:15.784MB = 25.208MB - 9.424MB
措施一内存收益:0.564MB = 16.348MB - 15.784MB



采用多媒体内存优化措施一和措施二
- 措施一:离线编码时VIPP 配置2个buffer
- 措施二:TDM 配置单buffer模式
多媒体内存占用:13.6MB = 25.208MB - 11.608MB
措施二内存收益:2.184MB = 15.784MB - 13.6M



采用多媒体内存优化措施一、措施二和措施三
- 措施一:离线编码时VIPP 配置2个buffer
- 措施二:TDM 配置单buffer模式
- 措施三:VE 编码参考帧buffer 和重建帧buffer 复用
多媒体内存占用:12.448MB = 25.208MB - 12.760MB
措施三内存收益:1.152MB = 13.6MB - 12.448MB



附录
单mipi sensor 场景测试demo和配置
测试demo:sample_OnlineVenc
路径:
tina\external\eyesee-mpp\middleware\sun8iw21\sample\sample_OnlineVenc\
配置和编译方法:
配置
make menuconfig
Location:
-> Allwinner
-> eyesee-mpp
-> eyesee-mpp-middleware
-> select mpp sample (mpp_sample [=y])
[*] mpp sample OnlineVenc
编译
cleanmpp && mkmpp
单mipi测试配置一
配置文件:sample_OnlineVenc.conf,需参考单mipi sensor 测试场景的规格参数修改,且只保留1路编码。
########### paramter (ref to tulip_cedarx.conf)############
[parameter]
main_isp = 0
main_vipp = 0
main_src_width = 1280
main_src_height = 720
main_pixel_format = "aw_lbc_2_5x" #nv21,nv12,yu12,yv12;aw_lbc_2_5x,aw_lbc_2_0x,aw_lbc_1_5x,aw_lbc_1_0x
main_wdr_enable = 0
main_vi_buf_num = 3
main_src_frame_rate = 20 #fps
main_viChn = 0 #-1:disale main stream
main_venc_chn = 0 #-1:disale main stream
main_encode_type = "H.264"
main_encode_width = 1280 #1280x720->720p, 1920x1080->1080p, 2304x1296->3M, 2560×1440->2k, 3840x2160->4k, 7680x4320->8k
main_encode_height = 720
main_encode_frame_rate = 20 #fps
main_encode_bitrate = 1048576 #5M:5242880, 2M:2097152, 1.5M:1572864, 1M:1048576
main_file_path = "/mnt/extsd/mainStream.raw" #if no path is specified, it will not be saved.
main_online_en = 0
main_online_share_buf_num = 2
main_encpp_enable = 1
main_vi_sync_ctrl_enable = 0
sub_isp = 0
sub_vipp = 4
sub_src_width = 640
sub_src_height = 360
sub_pixel_format = "aw_lbc_2_0x" #nv21,nv12,yu12,yv12;aw_lbc_2_5x,aw_lbc_2_0x,aw_lbc_1_5x,aw_lbc_1_0x
sub_wdr_enable = 0
sub_vi_buf_num = 3
sub_src_frame_rate = 20 #fps
sub_vipp_crop_en = 0
sub_vipp_crop_rect_x = 0
sub_vipp_crop_rect_y = 0
sub_vipp_crop_rect_w = 1888
sub_vipp_crop_rect_h = 1072
sub_viChn = -1 #-1:disale sub stream
sub_venc_chn = -1 #-1:disale sub stream
sub_encode_type = "H.264"
sub_encode_width = 640 #1280x720->720p, 1920x1080->1080p, 2560×1440->2k, 3840x2160->4k, 7680x4320->8k
sub_encode_height = 360
sub_encode_frame_rate = 20 #fps
sub_encode_bitrate = 256000 #5M:5242880, 2M:2097152, 1M:1048576, 0.5M:512000
sub_file_path = "/mnt/extsd/subStream.raw" #if no path is specified, it will not be saved.
sub_encpp_enable = 1
sub_lapse_viChn = -1 #-1:disale sub lapse stream
sub_lapse_venc_chn = -1 #-1:disale sub lapse stream
sub_lapse_encode_type = "H.264"
sub_lapse_encode_width = 640 #1280x720->720p, 1920x1080->1080p, 2560×1440->2k, 3840x2160->4k, 7680x4320->8k
sub_lapse_encode_height = 360
sub_lapse_encode_frame_rate = 20 #fps
sub_lapse_encode_bitrate = 256000 #5M:5242880, 2M:2097152, 1M:1048576, 0.5M:512000
sub_lapse_file_path = "/mnt/extsd/subLapseStream.raw" #if no path is specified, it will not be saved.
sub_lapse_time = 1000000 #unit:us
sub_lapse_encpp_enable = 1
isp_ve_linkage_enable = 1
isp_ve_linkage_stream_channel = 0 #0:main stream, 1:sub stream, 2:sub lapse stream
wb_yuv_enable = 0
wb_yuv_buf_num = 1
wb_yuv_start_index = 0
wb_yuv_total_cnt = 10
wb_yuv_stream_channel = 0 #0:main stream, 1:sub stream, 2:sub lapse stream
wb_yuv_file_path = "/mnt/extsd/wb_yuv.yuv"
test_duration = 60 #unit:s
单mipi测试配置二
########### paramter (ref to tulip_cedarx.conf)############
[parameter]
main_isp = 0
main_vipp = 0
main_src_width = 1280
main_src_height = 720
main_pixel_format = "aw_lbc_2_5x" #nv21,nv12,yu12,yv12;aw_lbc_2_5x,aw_lbc_2_0x,aw_lbc_1_5x,aw_lbc_1_0x
main_wdr_enable = 1
main_vi_buf_num = 3
main_src_frame_rate = 20 #fps
main_viChn = 0 #-1:disale main stream
main_venc_chn = 0 #-1:disale main stream
main_encode_type = "H.264"
main_encode_width = 1280 #1280x720->720p, 1920x1080->1080p, 2304x1296->3M, 2560×1440->2k, 3840x2160->4k, 7680x4320->8k
main_encode_height = 720
main_encode_frame_rate = 20 #fps
main_encode_bitrate = 1048576 #5M:5242880, 2M:2097152, 1.5M:1572864, 1M:1048576
main_file_path = "/mnt/extsd/mainStream.raw" #if no path is specified, it will not be saved.
main_online_en = 0
main_online_share_buf_num = 2
main_encpp_enable = 1
main_vi_sync_ctrl_enable = 0
sub_isp = 0
sub_vipp = 4
sub_src_width = 640
sub_src_height = 360
sub_pixel_format = "aw_lbc_2_0x" #nv21,nv12,yu12,yv12;aw_lbc_2_5x,aw_lbc_2_0x,aw_lbc_1_5x,aw_lbc_1_0x
sub_wdr_enable = 0
sub_vi_buf_num = 3
sub_src_frame_rate = 20 #fps
sub_vipp_crop_en = 0
sub_vipp_crop_rect_x = 0
sub_vipp_crop_rect_y = 0
sub_vipp_crop_rect_w = 1888
sub_vipp_crop_rect_h = 1072
sub_viChn = -1 #-1:disale sub stream
sub_venc_chn = -1 #-1:disale sub stream
sub_encode_type = "H.264"
sub_encode_width = 640 #1280x720->720p, 1920x1080->1080p, 2560×1440->2k, 3840x2160->4k, 7680x4320->8k
sub_encode_height = 360
sub_encode_frame_rate = 20 #fps
sub_encode_bitrate = 256000 #5M:5242880, 2M:2097152, 1M:1048576, 0.5M:512000
sub_file_path = "/mnt/extsd/subStream.raw" #if no path is specified, it will not be saved.
sub_encpp_enable = 1
sub_lapse_viChn = -1 #-1:disale sub lapse stream
sub_lapse_venc_chn = -1 #-1:disale sub lapse stream
sub_lapse_encode_type = "H.264"
sub_lapse_encode_width = 640 #1280x720->720p, 1920x1080->1080p, 2560×1440->2k, 3840x2160->4k, 7680x4320->8k
sub_lapse_encode_height = 360
sub_lapse_encode_frame_rate = 20 #fps
sub_lapse_encode_bitrate = 256000 #5M:5242880, 2M:2097152, 1M:1048576, 0.5M:512000
sub_lapse_file_path = "/mnt/extsd/subLapseStream.raw" #if no path is specified, it will not be saved.
sub_lapse_time = 1000000 #unit:us
sub_lapse_encpp_enable = 1
isp_ve_linkage_enable = 1
isp_ve_linkage_stream_channel = 0 #0:main stream, 1:sub stream, 2:sub lapse stream
wb_yuv_enable = 0
wb_yuv_buf_num = 1
wb_yuv_start_index = 0
wb_yuv_total_cnt = 10
wb_yuv_stream_channel = 0 #0:main stream, 1:sub stream, 2:sub lapse stream
wb_yuv_file_path = "/mnt/extsd/wb_yuv.yuv"
test_duration = 60 #unit:s
双mipi sensor 场景测试demo和配置
测试demo:sample_OnlineVenc
路径、配置和编译方法,请参考单mipi sensor 场景中的描述。