Rk1828 mpp 多媒体框架

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.hmpp_frame.hmpp_packet.hrk_mpi.hrk_venc_cfg.hvpu_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_rkmpphevc_rkmpp 这些硬件编码器根本不存在。

要用 RKMPP 硬件编解码,只有两条路:

  1. 自己编译瑞芯微定制的 ffmpeg(源码在 github.com/airockchip,buildroot 也有提供)
  2. 直接用 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**;后续 controlencode 调用都通过 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 能看到详细的内部日志,很管用。


有遇到其他问题的欢迎评论区交流。