瑞芯微开发笔记 · MPP 篇(三)编译和运行

1. 编译概述

test/CMakeLists.txt 由项目根的 CMake 引入,受顶层 BUILD_TEST 选项控制:

option(BUILD_TEST "Build all the test programs" OFF)

每个测试又有自己的细粒度开关:MPI_DEC_TESTMPI_ENC_TESTMPI_RC2_TESTVPU_API_TEST 等(由 add_mpp_test() 宏自动生成,规则是 test_name 大写)。

1.1 Linux 板端编译(aarch64 / arm)

项目自带交叉编译脚本:

option(BUILD_TEST "Build all t# 在 PC 上交叉编译 aarch64 板子
cd build/linux/aarch64
./make-Makefiles.bash         # 这个脚本会调 cmake,并默认 BUILD_TEST=ON
make -j8
​
# 产物在 build/linux/aarch64/test/
ls -la build/linux/aarch64/test/
# mpp_info_test  mpi_dec_test  mpi_enc_test  ...he test programs" OFF)

如果需要修改交叉编译工具可以直接修改./mpp/build/linux/aarch64/arm.linux.cross.cmake文件或者设置TOOLCHAIN的环境变量实现,如下图:

图片[1]-瑞芯微开发笔记 · MPP 篇(三)编译和运行-天煜博客

板端编译同理(如果板子算力够):

cd build/linux/x86_64
./make-Makefiles.bash
make -j$(nproc)

编译后的输出文件在./mpp/build/linux/aarch64/mpp./mpp/build/linux/aarch64/test两个目录下:

图片[2]-瑞芯微开发笔记 · MPP 篇(三)编译和运行-天煜博客

如果后续使用静态库或者动态库编写程序直接使用./mpp/inc下的头文件即可。

1.2 Android 板编译

cd build/android/aarch64
./make-Android.bash       # 需要先 source build/android/env_setup.sh 设置 NDK 路径

1.3 编译输出选项

如果只想编某一个 test,传 -D<TEST>=ON 给 cmake:

cmake .. -DBUILD_TEST=OFF -DMPI_DEC_TEST=ON -DMPI_ENC_TEST=ON

或者 BUILD_TEST=ON 后再单独关掉某些 case。

1.4 ASan(地址消毒)

vpu_api_test 支持 -DASAN_CHECK=ON,链接 libasan 检查内存错误(其它 test 默认未启用,可类似添加)。

2. 运行前的环境准备

2.1 板上前置条件

  • 内核已加载 mpp 驱动模块(视芯片不同:mpp_service.ko / rkvdec.ko / rkvenc.ko
  • 设备节点存在:/dev/mpp_service/dev/iep/dev/rga
  • libmpp.so 已部署到 /usr/lib/LD_LIBRARY_PATH
  • 板上能访问输入码流文件

检查驱动状态:

dmesg | grep -i mpp
ls -la /dev/mpp* /dev/iep* /dev/rga*

2.2 LD_LIBRARY_PATH

如果库没装在标准路径:

export LD_LIBRARY_PATH=/path/to/libs:$LD_LIBRARY_PATH

2.3 部分 MPP 行为开关(环境变量)

变量作用
mpp_show_history=1mpp_info_test 打印历史 commit
MPP_SYSLOG_NAME=foo日志 syslog tag
MPP_VERBOSE=1增加日志级别
dbrh_en=1mpi_rc2_test 启用 debreath
dbrh_s=16debreath 强度
fbc_dec_en=1mpi_rc2_test 解码端开 FBC
fast_en=1mpi_rc2_test 解码端 fast mode

这些既可以 export 设到 OS 环境,也可以代码里 mpp_env_set_u32 设到进程内。

3. 通用命令行参数

mpi_dec_*_testmpi_enc_*_test 的命令行被 utils/mpi_dec_utils.c / utils/mpi_enc_utils.c 集中解析,参数模式高度一致。

3.1 解码测试(MpiDecTestCmd)参数

最常用:

参数含义
-i <file>输入码流文件-i test.h264
-o <file>输出 YUV/RGB 文件(可选)-o out.yuv
-w <int>流的宽(部分 codec 可省,靠 SPS)-w 1920
-h <int>流的高-h 1080
-t <int>编码类型-t 7 (7=H.264)
-f <int>输出像素格式(仅 JPEG 用)-f 0
-n <int>帧数限制:>0 解 N 帧停;0 解到 EOS;<0 无限循环-n 100
-bm <int>buffer mode:0=half_int,1=internal,2=external-bm 0
-help列出所有参数

-t 取值(来自 MppCodingType):

类型
7AVC / H.264
8MPEG-4
9H.263
10VP8
11MJPEG
12VP9
16777220HEVC / H.265
16777221AVS
16777222AVS2
16777223AV1

实际值以 inc/rk_type.hMppCodingType 枚举为准。

3.2 编码测试(MpiEncTestArgs)参数

最常用:

参数含义
-i <file>输入 YUV 文件-i in_1080p.yuv
-o <file>输出码流-o out.h264
-w <int>视频宽-w 1920
-h <int>视频高-h 1080
-hstride <int>输入行 stride(不传则按 align 算)
-vstride <int>输入纵 stride
-f <int>输入像素格式(YUV420SP=0x100002 等)
-t <int>输出编码类型-t 7
-rc <int>码控模式:0=VBR,1=CBR,2=FIXQP,3=AVBR,4=SMTRC-rc 1
-bps <int>目标码率(bits/s)-bps 4000000
-fps <int>帧率-fps 30
-gop <int>GOP 长度-gop 60
-qp <int>FIXQP 模式下的 QP 值-qp 26
-n <int>帧数限制(语义同解码)-n 300
-loop <int>输入文件循环次数-loop 5
-nthreads <int>并发实例数-nthreads 4
-cfg <json>加载 JSON 配置-cfg cfg/enc/base_h264_1920x1080.json
-osd启用 OSD 测试图案
-roi启用 ROI 测试
-help列出所有参数

4. 实战:常用命令行示例

4.1 解码 H.264 → YUV

# 文件名包含分辨率 hint,比如 myvid_1920x1080.h264,部分 utils 解析能从中读出 w/h
./mpi_dec_test -i ~/Videos/car.h264  -t 7 -o car_1920x1080.yuv
# 或显式指定宽高
./mpi_dec_test -i ~/Videos/car.h264 -t 7 -w 1920 -h 1080 -o car_1920x1080.yuv

输出 YUV 是 NV12(YUV420SP)格式,stride 按硬件对齐(通常 16 / 64)。如要查看:

ffplay -f rawvideo -pixel_format nv12 -video_size 1920x1088 car_1920x1080.yuv
# 注意是 1088(ver_stride),不是 1080

第一次运行时候没使用sudo权限,程序报错,重新使用sudo之后正常运行:

topeet@topeet:~/work/mpp/build/linux/aarch64/test$ ./mpi_dec_test -i ~/Videos/car.h264  -t 7 -o car_1920x1080.yuv
mpp[332039]: mpp_platform: client 4 driver is not ready!
mpp[332039]: mpi_dec_utils: input file /home/topeet/Videos/car.h264 size 25071599
mpp[332039]: mpi_dec_utils: cmd parse result:
mpp[332039]: mpi_dec_utils: input  file name: /home/topeet/Videos/car.h264
mpp[332039]: mpi_dec_utils: output file name: car_1920x1080.yuv
mpp[332039]: mpi_dec_utils: width      :    0
mpp[332039]: mpi_dec_utils: height     :    0
mpp[332039]: mpi_dec_utils: type       :    7
mpp[332039]: mpi_dec_utils: max frames :    0
mpp[332039]: mpi_dec_test: mpi_dec_test start
mpp[332039]: mpp_info: mpp version: 1375813c author: Herman Chen   2026-05-29 docs: Update 1.0.12 CHANGELOG.md
mpp[332039]: mpi_dec_test: 0x559ec73280 mpi_dec_test decoder test start w 0 h 0 type 7
mpp[332039]: mpp_dma_heap: os_allocator_dma_heap_open open dma heap type 0 system failed!
mpp[332039]: mpp_buffer: MppBufferService get_group failed to get allocater with mode 0 type 20001
mpp[332039]: mpp_buffer: mpp_buffer_group_limit_config input invalid group (nil)
mpp[332039]: mpp_dma_heap: os_allocator_dma_heap_open open dma heap type 0 system-uncached failed!
mpp[332039]: mpp_buffer: MppBufferService get_group failed to get allocater with mode 0 type 1
mpp[332039]: mpp_hal: hal_impl_init mpp_buffer_group_get_internal failed. ret: -1
mpp[332039]: mpp_hal: mpp_hal_init soc rockchip,rk3588-evb7-v11 rockchip,rk3588 hal h264d_vdpu34x init failed ret -1
mpp[332039]: mpp_dec: mpp_dec_init could not init hal
mpp[332039]: mpp: error found on mpp initialization
mpp[332039]: mpi_dec_test: 0x559ec73280 mpp_init failed
mpp[332039]: mpi_dec_test: test failed ret -1
mpp[332039]: mpp_mem_pool: put_pool pool mpp_packet       found 1 used buffer size  328 at mpp_packet_srv_deinit
topeet@topeet:~/work/mpp/build/linux/aarch64/test$ sudo ./mpi_dec_test -i ~/Videos/car.h264  -t 7 -o car_1920x1080.y
uv
mpp[332566]: mpp_platform: client 4 driver is not ready!
mpp[332566]: mpi_dec_utils: input file /home/topeet/Videos/car.h264 size 25071599
mpp[332566]: mpi_dec_utils: cmd parse result:
mpp[332566]: mpi_dec_utils: input  file name: /home/topeet/Videos/car.h264
mpp[332566]: mpi_dec_utils: output file name: car_1920x1080.yuv
mpp[332566]: mpi_dec_utils: width      :    0
mpp[332566]: mpi_dec_utils: height     :    0
mpp[332566]: mpi_dec_utils: type       :    7
mpp[332566]: mpi_dec_utils: max frames :    0
mpp[332566]: mpi_dec_test: mpi_dec_test start
mpp[332566]: mpp_info: mpp version: 1375813c author: Herman Chen   2026-05-29 docs: Update 1.0.12 CHANGELOG.md
mpp[332566]: mpi_dec_test: 0x559a56a280 mpi_dec_test decoder test start w 0 h 0 type 7
mpp[332566]: mpi_dec_test: 0x559a56a280 decode_get_frame get info changed found
mpp[332566]: mpi_dec_test: 0x559a56a280 decoder require buffer w:h [1920:1080] stride [1920:1088] buf_size 4177920
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 0
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 1
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 2
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 3
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 4
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 5
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 6
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 7
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 8
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 9
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 10
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 11
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 12
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 13
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 14
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 15
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 16
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 17
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 18
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 19
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 20
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 21
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 22
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 23
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 24
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 25
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 26
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 27
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 28
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 29
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 30
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 31
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 32
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 33
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 34
mpp[332566]: mpi_dec_test: 0x559a56a280 decode get frame 35
图片[3]-瑞芯微开发笔记 · MPP 篇(三)编译和运行-天煜博客

使用YUV播放器查看解码后的YUV文件:

图片[4]-瑞芯微开发笔记 · MPP 篇(三)编译和运行-天煜博客

4.2 解码 H.265

./mpi_dec_test -i ~/Videos/imagenet.h265  -t 16777220 -o imagenet.yuv

###########################日志如下#########################################
topeet@topeet:~/work/mpp/build/linux/aarch64/test$ sudo ./mpi_dec_test -i ~/Videos/imagenet.h265  -t 16777220 -o imagenet.yuv
mpp[356932]: mpp_platform: client 4 driver is not ready!
mpp[356932]: mpi_dec_utils: input file /home/topeet/Videos/imagenet.h265 size 2640231
mpp[356932]: mpi_dec_utils: cmd parse result:
mpp[356932]: mpi_dec_utils: input  file name: /home/topeet/Videos/imagenet.h265
mpp[356932]: mpi_dec_utils: output file name: imagenet.yuv
mpp[356932]: mpi_dec_utils: width      :    0
mpp[356932]: mpi_dec_utils: height     :    0
mpp[356932]: mpi_dec_utils: type       : 16777220
mpp[356932]: mpi_dec_utils: max frames :    0
mpp[356932]: mpi_dec_test: mpi_dec_test start
mpp[356932]: mpp_info: mpp version: 1375813c author: Herman Chen   2026-05-29 docs: Update 1.0.12 CHANGELOG.md
mpp[356932]: mpi_dec_test: 0x5591eee280 mpi_dec_test decoder test start w 0 h 0 type 16777220
mpp[356932]: mpi_dec_test: 0x5591eee280 decode_get_frame get info changed found
mpp[356932]: mpi_dec_test: 0x5591eee280 decoder require buffer w:h [1920:1080] stride [1920:1080] buf_size 3732480
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 0
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 1
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 2
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 3
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 4
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 5
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 6
mpp[356932]: mpi_dec_test: 0x5591eee280 decode get frame 7

4.3 解码 JPEG

# 单个 JPEG
./mpi_dec_test -i pic.jpg -t 11 -w 1920 -h 1080 -o pic.yuv
​
# 设输出格式为 RGB888
./mpi_dec_test -i pic.jpg -t 11 -w 1920 -h 1080 -o pic.rgb -f <RGB888 值>

JPEG 走 advanced 路径,每个文件一帧。

4.4 限制帧数(验证用)

# 只解前 30 帧
./mpi_dec_test -i myvid.h264 -t 7 -n 30 -o first30.yuv
​
# 死循环跑(压测、按回车停)
./mpi_dec_test -i myvid.h264 -t 7 -n -1

4.5 多线程解码

# 输入输出分线程,对长流压测
./mpi_dec_mt_test -i myvid.h264 -t 7 -n 0    # -n 0 表示跑到 EOS
​
# 多实例并发,4 路 1080p
./mpi_dec_multi_test -i myvid.h264 -t 7 -nthreads 4 -n 300

4.6 编码 YUV → H.264(CBR 4Mbps)

./mpi_enc_test -i in_1920x1080.yuv -w 1920 -h 1080 -t 7 -rc 1 -bps 4000000 -fps 30 -gop 60 -o out.h264

YUV 输入默认 NV12(YUV420SP)。换格式用 -f

# YUV420P(I420)
./mpi_enc_test -i in.yuv -w 1920 -h 1080 -t 7 -f 0x00000000 -rc 1 -bps 4000000 -o out.h264

格式枚举值见 inc/rk_type.hMppFrameFormat

4.7 编码 + JSON 配置

./mpi_enc_test -cfg cfg/enc/base_h264_1920x1080.json \
               -cfg cfg/enc/func_roi.json \
               -i in.yuv -o out.h264

4.8 编码多实例

./mpi_enc_test -i in.yuv -w 1920 -h 1080 -t 7 -rc 1 -bps 4000000 \
               -nthreads 4 -o out.h264
# 会生成 out.h264.0、out.h264.1、out.h264.2、out.h264.3

4.9 转码(解码后再编码)

./mpi_rc2_test -i src.h264 -t 7 -w 1920 -h 1080 \
               -rc 1 -bps 4000000 -gop 60 \
               -o reenc.h264 -n 100 \
               -psnr 1 -ssim 1

-psnr 1 -ssim 1 让程序对每帧做”再次解码 → 与原帧比对”算质量指标,跑得很慢但能给你一个客观分数。

4.10 旧 VPU API(不推荐新代码用)

./vpu_api_test -i src.h264 -t dec -coding 7 -w 1920 -h 1080 -o out.yuv
./vpu_api_test -i src.yuv -t enc -coding 7 -w 1920 -h 1080 -o out.h264 -vframes 100

5. 性能与质量评估

5.1 fps 与延迟

每个测试结尾都会打印类似:

decode 100 frames time 1234 ms delay 18 ms fps 81.05

含义:

  • time:从第一次 put_packet 到最后一帧 get_frame 的总耗时(μs,打印时除以 1000)
  • delay:从首次成功 put_packet 到首次 get_frame 的时间(μs / 1000)—— 首帧延迟
  • fps:帧率 = frame_count × 1e6 / time(μs)

5.2 内存峰值

mpi_dec_test / mpi_dec_nt_test 收尾会打:

test success max memory 12.34 MB

这是 mpp_buffer_group_usage() 在循环里采样到的峰值。注意只统计了输出 frame group,编码端 packet buffer、内部码流缓存不计入。

5.3 CRC 校验(回归用)

mpi_dec_test 支持 -slt <file>(self test),把每帧的 CRC 写入文件,用于和”标准答案”比对:

./mpi_dec_test -i src.h264 -t 7 -slt src.crc
diff src.crc /path/to/golden.crc

参考 utils/mpi_dec_utils.ccmd->file_slt 的赋值逻辑。

5.4 编码 PSNR

编码测试每帧能从 meta 读出 KEY_ENC_SSE(残差平方和),程序里转成 PSNR:

psnr = 3.01029996 * (psnr_const - log2(sse));

只在 cmd->psnr_en 时计算(命令行未必直接暴露,可能要 -psnr 1 或读 cfg)。

6. 调试 tips

6.1 看不到日志

确认 stdout 没被重定向。MPP 默认走 mpp_log → printf。如要 syslog:

export MPP_SYSLOG_NAME=test
./mpi_dec_test ...
journalctl -t test

6.2 解码器一直 ERR_TIMEOUT

可能:

  • 输入文件不是真的 H.264(检查 first 4 bytes 起始码 00 00 00 01
  • -t 类型对不上
  • split_parse 关了但你的 packet 不是按帧切的
  • 硬件被另一个进程占用

6.3 解出来的帧花屏 / 黑屏

可能:

  • hor_stride / ver_stride 用错了(必须用 frame 的 stride,不是 width/height)
  • err_info / discard 标志没看:RK_U32 err = mpp_frame_get_errinfo(frame);
    RK_U32 dis = mpp_frame_get_discard(frame);
    if (err || dis) printf(“bad frame %x/%x\n”, err, dis);

6.4 编码出来播不了

可能:

  • 没写 SPS/PPS 头(mpi_enc_test 是写了的,看 MPP_ENC_GET_HDR_SYNC
  • 文件中混了 pkt_eos 标志包(这种包的 length 通常为 0,要过滤)
  • bitrate 设太低导致丢帧

7. 常见快捷组合

# 跑通流水线(基础冒烟)
./mpp_info_test
./mpi_dec_test -i sample.h264 -t 7 -n 10
​
# 解码性能基线
./mpi_dec_test -i sample.h264 -t 7 -n 0
​
# 多路解码极限测试
for n in 1 2 4 8; do
    ./mpi_dec_multi_test -i sample.h264 -t 7 -nthreads $n -n 300
done
​
# 编码 + 检查质量
./mpi_rc2_test -i src.yuv -w 1920 -h 1080 -t 7 -rc 1 -bps 4000000 -n 100 -psnr 1 -ssim 1

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容