Skip to content

背景与定位

Rockchip 平台上有两套多媒体 API:MPPRockit。两者不是替代关系,而是分层关系——Rockit 在上层,MPP 在底层。

MPP(Media Process Platform) 2015 年开源,只做一件事:视频编解码硬件加速。API 简单,代码在 GitHub 上。

Rockit 2021 年随 RK356X/RK3588 推出,闭源,覆盖完整多媒体管线:采集、缩放、编解码、显示、音频、ISP,模块之间支持零拷贝绑定。编解码部分底层仍然调用 MPP。

简单说:只做编解码用 MPP,要做完整视频系统用 Rockit。


API 设计思路

MPP:一个上下文搞定编解码

MPP 的核心抽象是一个 MppCtx,配上函数指针操作:

c
MppCtx ctx;
MppApi *mpi;

mpp_create(&ctx, &mpi);
mpp_init(ctx, MPP_CTX_ENC, MPP_VIDEO_H264);

// 同步模式
mpi->encode(ctx, input_frame, &output_packet);

// 异步模式
mpi->encode_put_frame(ctx, frame);
mpi->encode_get_packet(ctx, &packet);

// 高级:Task 模型,适合多线程
mpi->poll(ctx, MPP_PORT_INPUT, MPP_POLL_NON_BLOCK);
mpi->dequeue(ctx, MPP_PORT_OUTPUT, &task);
mpi->enqueue(ctx, MPP_PORT_INPUT, task);

mpp_destroy(ctx);

编码和解码用同一套 API,通过 MPP_CTX_ENC/DEC 区分。它不关心数据从哪来、到哪去——你给它帧,它给你码流,仅此而已。

Rockit:模块化管线

Rockit 把系统拆成独立模块(VI/VPSS/VENC/VO 等),每个模块有独立的通道管理:

c
RK_MPI_SYS_Init();

// 创建编码通道
VENC_CHN_ATTR_S attr = {0};
attr.stVencAttr.enType = RK_VIDEO_ID_AVC;
RK_MPI_VENC_CreateChn(0, &attr);
RK_MPI_VENC_StartRecvFrame(0, NULL);

// 方式一:绑定模式(零拷贝,推荐)
MPP_CHN_S src = {RK_ID_VI, 0, 0};
MPP_CHN_S dst = {RK_ID_VENC, 0, 0};
RK_MPI_SYS_Bind(&src, &dst);
// 绑定后 VI 的帧自动流入 VENC

// 方式二:手动模式(需要中间处理时用)
VIDEO_FRAME_INFO_S frame;
RK_MPI_VI_GetChnFrame(0, 0, &frame, -1);
// ... 应用处理 ...
RK_MPI_VENC_SendFrame(0, &frame, -1);
RK_MPI_VI_ReleaseChnFrame(0, 0, &frame);

// 清理
RK_MPI_SYS_UnBind(&src, &dst);
RK_MPI_VENC_StopRecvFrame(0);
RK_MPI_VENC_DestroyChn(0);
RK_MPI_SYS_Exit();

关键区别:Rockit 的模块可以绑定,数据在内核层零拷贝流转,应用层不用搬内存。


功能覆盖

功能MPPRockit
H.264/H.265/JPEG/VP8/VP9/AV1 编解码
视频输入 (VI)
视频输出 (VO)
视频处理缩放 (VPSS)
图形叠加 (VGS/RGN)
2D 加速 (TDE)
音频输入输出/编解码
智能分析 (IVS)
畸变校正 (GDC)
视频拼接 (AVS)
模块绑定 (Bind)
ISP 图像质量 (配合 RKAIQ)

MPP 只管编解码,其余全是 Rockit 独占。


内存管理

两者都用物理连续内存(DMA 需要),但管理方式不同:

c
// MPP:MppBuffer
MppBuffer buf;
mpp_buffer_get(group, &buf, size);
void *ptr = mpp_buffer_get_ptr(buf);  // 只有虚拟地址
mpp_buffer_put(buf);

// Rockit:MB_BLK(三地址互转)
MB_BLK blk;
RK_MPI_SYS_MmzAlloc(&blk, NULL, NULL, size);
void   *vir = RK_MPI_MB_Handle2VirAddr(blk);  // 虚拟地址
RK_U64 phy = RK_MPI_MB_Handle2PhysAddr(blk);  // 物理地址
RK_S32  fd  = RK_MPI_MB_Handle2Fd(blk);       // DMA-BUF fd
RK_MPI_SYS_MmzFlushCache(blk, RK_FALSE);
RK_MPI_SYS_MmzFree(blk);

Rockit 的 MB_BLK 同时暴露虚拟地址、物理地址和 DMA-BUF fd,方便与其他子系统(如 NPU 推理)共享内存。MPP 不直接暴露物理地址和 fd,跨模块协作受限。


模块绑定机制

这是 Rockit 相比 MPP 最大的架构优势:

IPC 典型管线:
┌─────┐    ┌──────┐    ┌──────┐    ┌─────┐
│ VI  │───→│ VPSS │───→│ VENC │    │ VO  │
│采集  │    │缩放  │    │编码  │    │显示  │
└─────┘    └──────┘    └──────┘    └─────┘
   │                               ↑
   └─────────── Bind ───────────────┘

NVR 典型管线:
┌──────┐    ┌──────┐    ┌─────┐
│ VDEC │───→│ VPSS │───→│ VO  │
│解码  │    │缩放  │    │显示  │
└──────┘    └──────┘    └─────┘

绑定模式下,数据从 VI 到 VENC 完全在内核层流转,应用零拷贝。手动模式下,应用可以在 VPSS 后插入自定义处理(如 AI 推理前处理)。

MPP 没有绑定概念。用 MPP 时,数据搬运全靠应用层:V4L2 取帧 → memcpy/DMABUF → MPP 编码 → 取码流 → 写文件/推流。


架构层次

┌──────────────────────────────────────────┐
│ 应用层 (CamHal / NVR / IPC)             │
├──────────────────┬───────────────────────┤
│ Rockit (librockit.so)  │ RKAIQ (ISP)    │
│ VI / VPSS / VENC / VO │ 3A/HDR/IQ      │
│ ┌────────────────────┐ │                 │
│ │ SYS (Bind/MB/MMZ) │ │                 │
│ └────────┬───────────┘ │                 │
├──────────┼─────────────┴─────────────────┤
│ MPP (librockchip_mpp.so)                │
│ H.264/H.265/JPEG/VP8/VP9/AV1 硬件编解码 │
├──────────────────────────────────────────┤
│ Linux Kernel: V4L2 / ISP / VPU / RGA    │
├──────────────────────────────────────────┤
│ RK3588: MIPI CSI / ISP / VPU / RGA / HDMI│
└──────────────────────────────────────────┘

注意:VI 和 VO 直接走内核驱动,不经过 MPP。VPSS 和 VGS 直接操作硬件引擎,也不经过 MPP。只有编解码走 MPP。


数据结构对比

编码输入帧:

c
// MPP: MppFrame
// 包含 buffer、宽高、步长、格式、PTS/DTS、meta 等
// 通过 mpp_buffer_get_ptr() 获取数据

// Rockit: VIDEO_FRAME_INFO_S
// 包含 VIDEO_FRAME_S(宽高、格式、物理/虚拟地址、步长、PTS)
// + MB_BLK 句柄(可转物理地址和 fd)
// 统一帧结构贯穿所有模块

编码输出码流:

c
// MPP: MppPacket — 单个包,data + length + pts + flag
// Rockit: VENC_STREAM_S — 包数组,每个包有 DataType(SPS/PPS/SEI/SLICE)

Rockit 的码流结构区分了 SPS/PPS/SEI 和 Slice,方便提取参数集或拼 RTMP/RTSP 包。


编译链接

cmake
# MPP
target_include_directories(myapp PRIVATE /path/to/mpp/inc)
target_link_libraries(myapp rockchip_mpp)

# Rockit
target_include_directories(myapp PRIVATE
    /path/to/rockit/usr/include
    /path/to/rockit/usr/include/rkaiq   # ISP(需要时)
)
target_link_libraries(myapp rockit)
c
// MPP
#include "rk_mpi.h"

// Rockit
#include "rk_mpi_sys.h"
#include "rk_mpi_vi.h"
#include "rk_mpi_venc.h"

选型建议

场景推荐理由
文件转码MPP轻量,无多余依赖
摄像头采集 + 编码(IPC)RockitVI→VENC 绑定,零拷贝
多路 NVRRockit多模块协同,4/8/16 路
解码 + 显示RockitVDEC→VO 绑定
视频会议Rockit双管线:编码 + 显示并行
AI 推理前处理RockitVPSS 缩放 + DMA-BUF 共享
鱼眼畸变校正RockitGDC 模块
跨平台编解码库MPP开源,易集成

迁移映射

从 MPP 迁到 Rockit,编码侧的核心映射:

MPPRockit说明
mpp_create + mpp_init(ENC)RK_MPI_VENC_CreateChn创建编码实例
mpi->encode_put_frameRK_MPI_VENC_SendFrame送帧
mpi->encode_get_packetRK_MPI_VENC_GetStream取码流
mpp_buffer_get_ptrRK_MPI_MB_Handle2VirAddr取数据地址
mpp_destroyRK_MPI_VENC_DestroyChn销毁实例

如果当前项目只用 MPP 做编解码且运行正常,没必要迁移。需要扩展到完整管线时再切 Rockit。