Skip to main content

H264解码视频播放

以开发板PD_X2600E_VAST_V2.0为例说明

一 基础配置

以x2600e_vast_v20_nand_5.10_defconfig配置为例

1.1 LCD

添加外设屏幕及背光配置

1

lcd供电采用设备电源管理"GPIO-POWER0",因为触摸屏供电也用到这个io,防止io被重复申请

2

背光默认采用gpio控制

3

1.2 fb配置

默认采用多fb叠加直通输出

4

fb配置建议fb0,强制最底层,解码播放缓冲帧数为0就行,节省内存,若后续要添加ui,增加fb1叠加,配置1帧

5

1.3 解码播放demo

建议使用直通模式,demo默认解码显示在fb0,源码位于libhardware2/src/cmds/h264_direct_decode_main.c

6

解码依赖的分包

10

可以解析h264 文件,查看参考帧数,辅助计算解码器需要的最小内存

7

1.4 h264解码驱动

进入kernel目录,配置h264解码驱动

bhu@bhu-PC:~/work/kernel/kernel$ make menuconfig

11

二 内存分配

2.1 rmem

说明:rmem的内存由libhardware2的rmem相关接口进行调用申请, 主要提供给一些需要申请大内存的驱动或场景使用,本文主要是lcd驱动

配置方法:位于bootloader/uboot-x2000/boards.cfg中配置, 在所用uboot配置的options里加上RMEM_MB=XXX

以x2600e_vast_v20_nand_5.10_defconfig配置为例

bhu@bhu-PC:~/work/build$ grep -nr "uboot" configs/x2600e_vast_v20_nand_5.10_defconfig 
3:APP_uboot_toolchain_dir=../tools/toolchains/mips-gcc720-glibc229
4:APP_uboot_dir=../bootloader/uboot-x2000
5:APP_uboot_config=x2600e_base_xImage_sfc_nand //uboot配置
bhu@bhu-PC:~/work/build$ grep -nr "x2600e_base_xImage_sfc_nand" ../bootloader/uboot-x2000/boards.cfg //uboot配置的rmem
798:x2600e_base_xImage_sfc_nand mips xburst2 x2600_base ingenic x2600 x2600_base:SPL_SFC_NAND,MTD_SFCNAND,SPL_OS_BOOT,SPL_PARAMS_FIXER,X2600E_DDR,RMEM_MB=16,LPJ="11476992"

iconfig配置:需要选中两个,第一个是驱动的选项,第二个是驱动对应的调用

8

9

查看:烧录进入板子后可通过cat /proc/cmdline查看配置的rmem

计算方法:以下是lcd需要内存,实际使用应该尽量往高一点计算

lcd为720p的屏幕, 并且fb只配置一层, 然后为0个buffer时

(720 ×1280 × 4) × 0 = 0 (lcd的内存是按ARGB的32位申请的,因此需要乘4)

计算方法:解码720p的视频,需要预留2帧NV12 缓存

frame_size = 1280 × 720 × 3 / 2 × 2= 2764800

2.2 reserved_memory

说明:reserved_memory是kernel里配置的, 由设备树上分配的一项预留内存, 通常用于内核里驱动的内存使用

不同于RMEM, 该段内存主要用于给h264解码内存使用, h264解码是一个相对独立且内存消耗较大的驱动

单独用此功能分配内存可以更好的管理内存分配, 并且避免在使用内存较频繁之后产生内存碎片, 申请不到编解码所需要的连续内存导致错误

配置方法:位于kernel/kernel/module_drivers/dts/对应的dts文件, 通过增加下述字段使用

dts文件查询, 以x2600e_vast_v20_nand_5.10_defconfig为例

bhu@bhu-PC:~/work/build$ grep -nr "kernel" configs/x2600e_vast_v20_nand_5.10_defconfig 
6:APP_kernel_dir=../kernel/kernel
7:APP_kernel_config=x2600_vast_module_base_linux_sfc_nand_defconfig //kernel配置
9:# APP_kernel_dtb is not set
bhu@bhu-PC:~/work/build$ grep -nr "dts" ../kernel/kernel/arch/mips/configs/x2600_vast_module_base_linux_sfc_nand_defconfig
257:CONFIG_DT_X2600_MODULE_BASE_DTS_FILE="x2600_vast_module_base.dts" //dts文件

解码内存计算说明


reserved-memory 大小说明:(需要的最小值)

例如:1080p, 参考帧为(ref_frame_count)4 帧,没有 B 帧的视频解码,需要预留的内存大小:
dec_mem:
frame_size = 1920 * 1088 * 3 / 2 = 3133440; //h264解码宽高需要16位对齐,所以1080按1088计算
mb_size = (1920 / 16) * (1088 / 16) * 136 = 1109760 //固定计算公式
dec_mem = (ref_frame_count + 1) * (frame_size + mb_size) + 其他结构体 + 码流缓存 //其他结构体固定大小,码流缓存按最大1MB计算
= (4 + 1) * 4243200 + 360448 + 1048576
= 21.5M
同理算出720p需要内存为 = 10.3M
ps:
1.计算出来的内存为极限值,并且只对于h264解码,需要多预留
2.此为使用libhardware2 接口内存计算方式,若使用ffmpeg以ffmpeg实际使用为准
3.要想降低使用内存,则需要h264编码只采用 1 帧参考帧,这样1080p只需要 9.4M
4.ref_frame_count 可以使用 cmd_h264_parse 命令查看

dts 文件解码内存添加

/ {
compatible = "ingenic,x2600";
/*chosen {
bootargs = "console=ttyS0,115200 mem=128M@0x0ip=off init=/linuxrc ubi.mtd=2 root=ubi0:rootfs ubi.mtd=3 rootfstype=ubifs rw flashtype=nand";
};*/

reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges =<>;

/*
reserved_mem@0x5000000: 对应预留内存地址起始位置为0x5000000
reg = <0x05000000 0x2000000>: 分别对应起始位置为0x05000000, 大小为0x2000000
配置的凭据以此芯片x2600为例, 内存总大小为128M, 即总大小为0x8000000
x2600通用对应的uboot配置里设置了RMEM_MB=16, 因此总地址的后16M会被RMEM占用, 则剩余内存大小为0x7000000
由此当我们分配32M预留内存给reserved_memory时, 起始地址则为0x7000000-0x2000000 = 0x5000000, 大小为0x2000000
如果需要改变此区域大小, 需要同时修改起始地址和大小(reserved_mem@0x5000000 和 reg = <0x05000000 0x2000000> 的地址需要一起修改)
需要用到该地址申请内存的驱动, 需要加上 memory-region=<&reserved_memory>; 详细参考下面 felix 等的用法
*/
reserved_memory: reserved_mem@0x5000000{
compatible = "shared-dma-pool";
reg = <0x05000000 0x2000000>;
};
};
}

/* 加上 memory-region=<&reserved_memory>; 表示会用上方设置的预留内存地址和大小作为内存申请 */
&felix {
status = "okay";
memory-region=<&reserved_memory>;
};

三 验证

整体编译

bhu@bhu-PC:~/work/build$ make x2600e_vast_v20_nand_5.10_defconfig
bhu@bhu-PC:~/work/build$ make
# cmd_h264_parse /usr/data/720p.h264 
/usr/data/720p.h264 : max_w[1280] max_h[720] max_fps[23] max_ref_frame_count[3] //解析h264码流最大参考帧数
# cmd_h264_direct_decode file=/usr/data/720p.h264 w=1280 h=720
[ 913.106275] max available: 33554432 //解码器内存剩余大小打印
[ 913.106527] min available: 33325056
[ 913.106854] min available: 33193984
[ 913.107136] h264_decode_init done!
[ 913.107392] Create instance [0]@fa0f5c11 m2m_ctx=be9345e8
[ 913.107757] 13300000.felix vcodec [0]
[ 913.108030] tmp_w 1280 tmp_h 720, w 1280 h 720
[ 913.108340] tmp_w 1280 tmp_h 720, w 1280 h 720
[ 913.110749] min available: 32698368
[ 913.111014] min available: 32235520
[ 913.111260] min available: 31313920
[ 913.111502] min available: 30851072
[ 913.136529] min available: 30818304
[ 913.136795] min available: 30355456
[ 913.137038] min available: 29433856
[ 913.137281] min available: 28971008
[ 913.153224] min available: 28938240
[ 913.153489] min available: 28475392
[ 913.153733] min available: 27553792
[ 913.153975] min available: 27090944
[ 913.203963] min available: 27058176
[ 913.204231] min available: 26595328
[ 913.204476] min available: 25673728
[ 913.204719] min available: 25210880

[ 919.088868] [0] vcodec release
[ 919.089135] total_alloc_cnt: 1413, total_alloc_size: 661127808, total_free_size:661127808, total_free_cnt:1413
[ 919.089804] max alloc size = 8343552
[ 919.105280] step3 D-PHY PLL unlocked warning (This log can be ignored)