MPP 是瑞芯微提供的硬件级视频编解码方案,走的是底层硬件加速,CPU 几乎不参与。对于需要在板子上做视频采集、编码、转码、推流的场景,MPP 是绑不开的一环。
重要前提: RK182X 本身是一颗协处理器,没有内置 VPU。本文提到的 8K/4K 编解码能力是 Host SoC(比如 RK3588)上 VPU 的参考规格。MPP 在 RK182X 上的实际编解码能力取决于你搭配的主控 SoC 的 VPU 硬件,具体看主控的 TRM。
一、整体架构框图
先把 MPP 的分层结构看清楚:
┌─────────────────────────────────────────┐
│ 用户应用程序 │
├─────────────────────────────────────────┤
│ MPP API(C 接口) │
├──────────┬──────────┬───────────────────┤
│ VPU 编码 │ VPU 解码 │ RGA / ISP │
├──────────┴──────────┴───────────────────┤
│ 硬件驱动(内核层) │
├─────────────────────────────────────────┤
│ 硬件 IP(VPU / RGA) │
└─────────────────────────────────────────┘
上层是你的应用代码,中间是 MPP 的 C API 封装,底层直接调硬件 IP。整条链路 CPU 开销极低,这才是 MPP 的核心价值。
二、支持的编解码格式(Host SoC 参考规格)
| 方向 | 格式 | 最大分辨率 |
|---|---|---|
| 编码 | H.264 | 8K@30fps |
| 编码 | H.265 | 8K@30fps |
| 解码 | H.264 | 8K@30fps |
| 解码 | H.265 | 8K@60fps |
| 解码 | VP9 | 8K@60fps |
| 解码 | AV1 | 4K@60fps |
再次提醒: 上面是 Host SoC(如 RK3588)VPU 的参考规格,实际能力以你的主控 SoC 硬件为准。
三、环境验证
拿到板子后,先确认 MPP 开发环境是否齐全。
3.1 检查头文件
ls /usr/include/rockchip/
正常会看到一堆头文件:mpp_buffer.h、mpp_frame.h、mpp_packet.h、rk_mpi.h、rk_venc_cfg.h、vpu_api.h 等等,这些都是 MPP 编程需要的。
3.2 检查库文件
ls /usr/lib/aarch64-linux-gnu/librockchip_mpp.so* -l
正常输出:
lrwxrwxrwx 1 root root 20 May 20 2021 /usr/lib/aarch64-linux-gnu/librockchip_mpp.so -> librockchip_mpp.so.1
-rw-r--r-- 1 root root 2444776 May 20 2021 /usr/lib/aarch64-linux-gnu/librockchip_mpp.so.0
lrwxrwxrwx 1 root root 20 May 20 2021 /usr/lib/aarch64-linux-gnu/librockchip_mpp.so.1 -> librockchip_mpp.so.0
库文件在就有,编码链接时 -lrockchip_mpp 就能找到。
3.3 FFmpeg
which ffmpeg && ffmpeg -version | head -1
输出:
/usr/bin/ffmpeg
ffmpeg version 4.4.2-0ubuntu0.22.04.1 Copyright (c) 2000-2021 the FFmpeg developers
3.4 检查 RKMPP 硬件编码器
ffmpeg -encoders 2>/dev/null | grep -i rkmpp
实测输出:空,什么都没有。
原因是 Debian 12 apt 安装的 ffmpeg 编译时没有 --enable-rkmpp,所以 h264_rkmpp、hevc_rkmpp 这些硬件编码器根本不存在。
要用 RKMPP 硬件编解码,只有两条路:
- 自己编译瑞芯微定制的 ffmpeg(源码在 github.com/airockchip,buildroot 也有提供)
- 直接用 MPP C API 或者
mpp_enc/mpp_dec工具
3.5 检查视频设备
ls /dev/video*
会看到 video0 ~ video19 共 20 个常规节点,另外还有三个专用节点:
/dev/video-dec0— MPP 硬件解码专用/dev/video-enc0— MPP 硬件编码专用/dev/video-camera0— 摄像头节点
四、MPP 编码实战(C API)
以下代码在板子上针对 librockchip-mpp 编译通过、运行正常(实测运行时版本 520ab553,2025-12-16,作者 Herman Chen):
#include <stdio.h>
#include <rockchip/mpp_buffer.h>
#include <rockchip/mpp_frame.h>
#include <rockchip/mpp_packet.h>
#include <rockchip/rk_mpi.h>
#include <rockchip/rk_mpi_cmd.h> /* MPP_ENC_SET_CFG 等控制命令 */
#include <rockchip/rk_venc_cfg.h> /* mpp_enc_cfg_* 编码配置 API */
int main(void)
{
MPP_RET ret;
MppCtx ctx = NULL;
MppApi *mpi = NULL;
// 创建 MPP 上下文
ret = mpp_create(&ctx, &mpi);
if (ret) return ret;
// 初始化:指定方向和编码类型
ret = mpp_init(ctx, MPP_CTX_ENC, MPP_VIDEO_CodingAVC);
if (ret) return ret;
// 配置编码参数
MppEncCfg cfg = NULL;
mpp_enc_cfg_init(&cfg);
mpp_enc_cfg_set_s32(cfg, "prep:width", 1920);
mpp_enc_cfg_set_s32(cfg, "prep:height", 1080);
mpp_enc_cfg_set_s32(cfg, "rc:bps_target", 4000000);
mpp_enc_cfg_set_s32(cfg, "rc:fps_in", 30);
// 配置必须通过 mpi->control 下发
ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg);
if (ret) return ret;
// 编码循环
MppFrame frame = NULL;
MppPacket packet = NULL;
mpp_frame_init(&frame);
// 填充帧数据(width/height/hor_stride/buf/fd/pts)
ret = mpi->encode(ctx, frame, &packet);
// 处理编码输出(length/pts/data)
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame);
// 销毁
mpp_destroy(ctx);
mpp_enc_cfg_deinit(cfg);
return MPP_OK;
}
4.1 关键 API 要点
这几个坑我都踩过,标清楚:
| API | 说明 |
|---|---|
MppCtx ctx + MppApi *mpi |
mpp_create 必须返回 MppApi**;后续 control、encode 调用都通过 mpi-> |
mpp_init(ctx, MPP_CTX_ENC, MppCodingType) |
第三个参数类型是 MppCodingType(如 MPP_VIDEO_CodingAVC),不是 MppEncCodecId |
mpi->control(ctx, MPP_ENC_SET_CFG, cfg) |
没有顶层的 mpp_enc_set_cfg() 函数,配置必须通过 mpi->control 下发 |
mpi->encode(ctx, frame, &packet) |
没有顶层的 mpp_encode() 函数,编码函数是 MppApi 的成员 |
#include <rockchip/mpp_packet.h> |
必须包含,否则 packet 相关操作编译不过 |
4.2 实测输出
跑最小化验证程序的实际输出:
mpp[6401]: mpp_info: mpp version: 520ab553 author: Herman Chen 2025-12-16 fix[sys_cfg]: Fix decoder sys_cfg crash
[OK] mpp_create, ctx=0x559dc44e80 mpi=0x7fb64b38b8
[OK] mpp_init(MPP_CTX_ENC, MPP_VIDEO_CodingAVC)
[MPP version] mpi->version=0x00000000 (major=0 minor=0)
[control probe] MPP_ENC_GET_HDR_SYNC ret=0
[OK] mpp_destroy, exit
关于版本号: 实际的 MPP 版本看 mpp_info 日志输出(这里是 520ab553,2025-12-16)。mpi->version 实测为 0,这是个未使用的字段,不是版本号,别被误导。
五、MPP 与 FFmpeg 集成
瑞芯微提供了一套定制的 FFmpeg,通过 h264_rkmpp / hevc_rkmpp 编码器调用 MPP 硬件加速。
实测警告: 以下命令在板子自带的 Debian 12 apt ffmpeg(5.1.9,无 --enable-rkmpp)上跑不通——h264_rkmpp 编码器不存在。
# 硬件编码(需要定制版 FFmpeg)
ffmpeg -f v4l2 -i /dev/video0 -c:v h264_rkmpp -b:v 4M output.mp4
# 硬件解码(需要定制版 FFmpeg)
ffmpeg -c:v h264_rkmpp -i input.mp4 -f null -
# 列出可用的硬件编码器
ffmpeg -encoders | grep rkmpp
要用硬件编解码,必须先编译安装瑞芯微定制版 FFmpeg(源码在 github.com/airockchip,buildroot 里也有)。或者直接用 MPP C API / mpp_enc / mpp_dec 命令行工具替代。
六、关键环境变量
从库文件里提取出来的调试变量:
strings /usr/lib/aarch64-linux-gnu/librockchip_mpp.so.1 2>/dev/null | grep -E "^mpp_(debug|buffer|rt|enc|dec)_debug" | head -10
输出:
mpp_enc_debug
mpp_dec_debug
mpp_buffer_debug
mpp_rt_debug
| 变量 | 用途 |
|---|---|
mpp_debug |
调试日志级别(info / debug / warn / error / verbose),运行时覆盖 mpp_set_log_level() |
mpp_buffer_debug |
buffer 子模块调试日志 |
mpp_rt_debug |
runtime 子模块调试日志 |
mpp_enc_debug |
编码器子模块调试日志 |
mpp_dec_debug |
解码器子模块调试日志 |
排查编解码问题时,设一下 export mpp_debug=debug 能看到详细的内部日志,很管用。
有遇到其他问题的欢迎评论区交流。