☰
RK3568平台Rockit多媒体库编译实战:从环境准备到运行测试
2026/10/3 6:51:40 网站建设 项目流程

刚拿到一块 RK3568 的开发板,要把 Rockit 这套多媒体库编译起来跑一轮测试,记录一下整个过程的思路、步骤和踩过的坑。搜热点时看到很多人也在碰 RK3568 的 OV5695 调试、BT.1120 输出、设备树修改之类的问题,这些其实都绕不开 Rockit 周边这套工具链。这篇文章就按我实际操作的顺序来写,从环境准备到编译执行,再到运行测试用例,最后把典型报错整理成速查表,希望对正在折腾 RK3568 的同行有帮助。

Rockit 的定位要搞清楚。它是瑞芯微面向多媒体和视觉应用的一套用户态库,把 ISP 图像处理、视频编解码、RGA 加速这些底层能力封装成相对统一的 C/C++ 接口。在 RK3568 上做摄像头采集、视频推流、AI 前处理,基本都会碰到它。编译 Rockit 本身不难,难的是把交叉编译环境、系统依赖、设备树配置、Sensor 驱动这些周边因素理顺。这篇文章主要适合两类人:一是刚接触 RK3568、准备跑通 Rockit SDK 做视频开发的新手,二是已经在用 Rockit、但编译或运行阶段卡住的工程师。

1. 在动手之前:先梳理 Rockit 在 RK3568 上的组成

Rockit 并不是一个孤立的库文件,它更像是一套多媒体中间件,依赖底层 MPP(Media Process Platform)、RGA、DPP、AIQ(ISP 调试)等组件。在编译之前,先把这些概念理清楚,后面排查问题会省很多时间。

1.1 Rockit 的模块划分

RK3568 的 Rockit 框架大致分成四块:

  • VI(Video Input):从 MIPI CSI、BT.1120、LVDS 等接口采集图像数据,经过 ISP 处理后输出给内存或直接送显。RK3568 的 ISP 支持 8M 像素,OV5695 这类 500 万 Sensor 是很常见的搭配。
  • VENC/VDEC:硬件编码和解码,支持 H.264、H.265、JPEG。这部分底层走的是 MPP,MPP 编译不过的话 Rockit 编码功能基本全废。
  • RGA(Raster Graphic Acceleration):负责图像缩放、裁剪、格式转换、旋转等操作。Rockit 的 AI 前处理大量依赖 RGA,如果 rga 头文件版本不对,编译 Rockit 时会报一堆函数未定义。
  • AIQ(Camera 3A):自动曝光、自动白平衡、自动对焦的算法库。这个库通常由瑞芯微以闭源二进制形式提供,编译 Rockit 时需要链接相关 .a 文件。

如果你在编译过程中发现某个模块始终有问题,建议先确认整个 SDK 的版本是否匹配。Rockit 代码迭代很快,不同版本的 MPP、RGA 头文件可能不兼容,混用版本是最常见的编译失败原因。

1.2 编译方式的选择

Rockit 在 RK3568 上有两种典型编译方式:

  1. 在 SDK 源码树内编译:瑞芯微发布的完整 SDK 中,Rockit 位于external/rockit/,与 MPP、RGA、Camera 驱动等一起构建。这种方式最省心,因为依赖关系由构建系统统一处理。
  2. 独立下载 Rockit 源码交叉编译:只拿到rockit目录,或者从 GitHub 拉取源码,然后用交叉编译器单独编译。这种方式更灵活,但需要自己手动指定依赖库和头文件路径。

大部分情况下我建议直接用 SDK 内的整体构建,但如果只是验证一个模块,独立编译会更快。下面以独立编译为主线,因为它能把依赖关系暴露得更清楚,也更容易定位问题。

2. 环境准备:交叉编译工具链与 SDK 目录结构

编译 Rockit 之前,先把交叉编译环境搭好。RK3568 是 ARMv8 架构的 64 位平台,常见工具链是aarch64-linux-gnu-系列。可以使用瑞芯微 SDK 自带的工具链,也可以使用系统的gcc-aarch64-linux-gnu。

2.1 安装交叉编译工具链

我用的是 Ubuntu 22.04,直接安装系统包方便一些:

sudo apt update sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

验证工具链是否可用:

aarch64-linux-gnu-gcc --version

如果开发板使用的是 Buildroot 或 Yocto 环境,则需要使用对应 SDK 中提供的工具链路径,通常类似:

export CROSS_COMPILE=/path/to/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-

有一点需要留意:工具链版本不要过于陈旧。Rockit 新版本代码用到了 C++14 甚至 C++17 的特性,老工具链可能遇到语法报错,这类报错往往非常锻炼耐心。

2.2 确认 SDK 目录结构

独立编译时,建议把依赖库的源码或头文件提前准备好。一次比较典型的目录布局如下:

rk3568_sdk/ ├── external/ │ ├── rockit/ │ │ ├── include/ │ │ ├── src/ │ │ └── sample/ │ ├── mpp/ │ ├── rga/ │ └── camera_engine/ │ └── include/ ├── kernel/ ├── u-boot/ └── buildroot/

Rockit 的源码目录在瑞芯微 SDK 中通常是external/rockit,依赖的头文件在external/camera_engine/include、external/mpp/include、external/rga/include等位置。编译时可以通过-I参数把这些路径加进来,也可以通过环境变量统一设置,后面会详细说明。

2.3 安装必要的宿主工具

虽然最终产物是 ARM 平台的可执行文件,但编译过程中可能用到cmake、make、pkg-config、python3等工具,这些属于宿主机的构建工具,也需要提前装好:

sudo apt install cmake make pkg-config python3

如果是老一点的 SDK,可能还会用到android-tools相关的工具去打包或刷机,但编译 Rockit 本身用不到,这里就不展开了。

3. Rockit 编译流程:一条命令背后的逻辑

Rockit 提供了build.sh或在CMakeLists.txt中预设好的交叉编译工具链文件。实际操作时,我会先看一遍README和CMakeLists.txt开头的注释,确认默认参数和输出路径。

3.1 查看编译脚本入口

以 SDK 内的 Rockit 源码为例,进入目录后第一件事是查看文件结构:

cd external/rockit ls -la cat README.md

通常可以看到build.sh或者CMakeLists.txt。如果有build.sh,先打开它,看里面的关键变量:

#!/bin/bash export ARCH=arm64 export CROSS_COMPILE=aarch64-linux-gnu- export PATH=$PATH:/path/to/toolchain/bin cmake -DCMAKE_C_COMPILER=${CROSS_COMPILE}gcc \ -DCMAKE_CXX_COMPILER=${CROSS_COMPILE}g++ \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ ${ROCKIT_ROOT_DIR} make -j$(nproc)

有些版本的脚本还会引用RK_PLATFORM、RK_CHIP等变量,用来控制 BOARD 相关配置。比如:

export RK_CHIP=3568 export RK_PLATFORM=linux

这些变量会影响目标平台的 sysroot 路径和特定头文件选择。如果你的板子不是瑞芯微标准 SDK,需要检查这些路径是否指向实际存在的目录。

3.2 一个可参考的交叉编译命令

在没有现成脚本的情况下,我整理了一套可直接执行的步骤:

export ROCKIT_ROOT=$(pwd) export MPP_ROOT=/path/to/external/mpp export RGA_ROOT=/path/to/external/rga export CAMERA_ENGINE_ROOT=/path/to/external/camera_engine mkdir -p build && cd build cmake .. \ -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \ -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ -DCMAKE_BUILD_TYPE=Release \ -DROCKIT_PLATFORM=RK3568 \ -DROCKIT_HAL_PATH=$CAMERA_ENGINE_ROOT \ -DROCKIT_MPP_PATH=$MPP_ROOT \ -DROCKIT_RGA_PATH=$RGA_ROOT

然后再执行:

make -j$(nproc)

如果顺利,会在build/目录下生成librockit.so和对应的头文件复制目录,示例程序可能生成在build/samples/下面。

3.3 编译选项说明

上面几个关键编译选项的解释:

  • ROCKIT_PLATFORM: 告诉库代码目标芯片型号,影响部分硬件相关宏定义。比如 RK3568 的 ISP 支持、编解码规格都会与 RK3588 有差异。
  • ROCKIT_HAL_PATH: 指向 camera_engine 的根目录,用于编译调用 ISP 相关接口。如果没有指定,可能出现rk_aiq.h找不到的报错。
  • ROCKIT_MPP_PATH: 指向 MPP 解码器库路径,缺失时会报mpp_*.h相关错误。
  • ROCKIT_RGA_PATH: 指向 RGA 加速库路径,缺失时会报rga.h相关错误。

这里有个经验:宁可把依赖头文件目录多传几个,也不要一开始就追求精简。Rockit 源码里对私有头文件的引用比对外 API 多得多,漏一个目录都会让编译中途中断,而报错位置往往离真正的缺失头文件很遥远。

4. 运行测试用例:编译成功只是第一步

编译生成库只是热身,真正能体现问题是运行测试程序。Rockit 自带的一堆sample程序是快速验证功能的最短路径。

4.1 找到合适的 sample 程序

在 Rockit 源码中,示例程序一般位于sample/目录,常见的有:

  • sample_vi_venc: 从 VI 采集视频,编码为 H.264,保存为文件或通过 RTSP 推流
  • sample_venc: 纯编码,可以直接把 YUV 文件编码为 H.264/H.265
  • sample_vdec: 解码测试,读入码流文件输出 YUV
  • sample_vi: 仅图像采集,输出原始图像或经过 ISP 处理的图像
  • sample_camera: 配合 AIQ 使用的摄像头采集程序

我先跑sample_venc和sample_vi,因为这两个对传感器和显示环境的依赖最少,最容易验证基础链路。

编译这些 sample 前,需要确认 CMake 中的BUILD_SAMPLE宏是否打开。有的 SDK 默认不编译 sample,需要手动开启。在 cmake 命令行追加:

-DBUILD_SAMPLE=ON

如果样列代码里还引用了live555等库,需要先交叉编译它们。瑞芯微 SDK 里通常会捆绑三方库源码,位置可能在external/下,将其一并编译或者链接静态库即可。

4.2 使用 sample_venc 快速验证编码链路

以sample_venc为例,典型用法是把 YUV 文件编码成 H.264:

./sample_venc -w 1920 -h 1080 -f 3 -t 7 -b 4000000 -i input.yuv -o output.h264 -n 300 -s 30

参数含义大致是:

  • -w/-h: 输入宽度和高度
  • -f: 输入像素格式,比如 3 表示 NV12
  • -t: 编码类型,比如 7 表示 H.264,8 表示 H.265
  • -b: 码率
  • -n: 编码帧数
  • -s: 帧率

如果输入 YUV 文件格式或参数不匹配,程序可能会直接退出,或者在编码中途出现花屏。所以测试时最好先准备一段已知正确的 NV12 文件,或者用工具从解码器转出来。

4.3 使用 sample_vi_venc 验证摄像头链路

有摄像头时,跑sample_vi_venc能一次验证 Sensor 配置、ISP 通路、编码通路。一个典型命令:

./sample_vi_venc --aiq=1 --sensor=ov5695 --width=1920 --height=1080 --format=NV12 --venc=h264 --rate=30 --bitrate=8000000 --output=/tmp/test.h264

运行日志中关注三点:

  1. Sensor 是否注册成功:日志里会打印 sensor 名称和对应的 I2C 地址
  2. ISP 通路是否正常:如果 AIQ 初始化失败,通常会打印rkaiq相关错误
  3. 编码码率是否接近设定值:如果码率异常偏差大,可能是 MPP 配置异常

如果日志中出现fail to open device /dev/video0一类错误,不要先怀疑 Rockit,先检查板卡设备节点:

ls /dev/video* ls /dev/media*

常见情况是驱动没加载或者设备树里摄像头节点没配好。这里提醒一个我之前踩过的坑:RK3568 某些 SDK 默认把video0分配给 ISP,video1分配给 VIPP,不同内核版本命名可能不同,Rockit 并不是直接打开/dev/videoX的,它的路由是通过 media-controller 框架完成的,所以如果 media 设备拓扑不对,即使/dev/videoX存在,依然无法采到数据。

4.4 把编译好的库与测试程序部署到板端

把交叉编译得到的.so、可执行程序和依赖库一起拷贝到开发板。这里建议使用 NFS 挂载或者 ADB push:

adb push build/librockit.so /usr/lib/ adb push build/samples/sample_vi_venc /userdata/ adb push build/samples/input.yuv /userdata/

然后通过串口或 SSH 进入板子,设置动态库路径:

export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH

运行前可以用ldd检查是否缺少依赖库:

ldd ./sample_vi_venc

如果输出中出现not found,需要把对应的.so一并推到板子上。常见的缺失库包括:

  • librockit.so
  • librkaiq.so
  • librga.so
  • libmpp_enc.so或libmpp_dec.so
  • libdrm.so
  • libion.so

其中libion.so特别值得注意。Rockit 早期版本依赖 ION 内存分配器,但新内核上 ION 已经被 DMA-BUF Heap 替代,某些 SDK 里可能已经没有/dev/ion节点,导致运行时初始化失败。如果你的 Rockit 版本比较老,遇到open /dev/ion failed这种报错,要么把内核 ION 驱动配置打开,要么换用新版本 Rockit 和 MPP。

运行测试前也别忘了检查权限。Rockit 涉及DRM、RGA、ION等设备节点,如果直接 root 运行当然没问题,但如果是普通用户,很可能会因为权限不足打不开设备。最简单的办法是先用 root 跑一遍,确认链路正常后再去完善权限配置。

5. 编译和运行阶段的典型报错与排查方案

这部分是我觉得最实用的一节。整理一下我在 RK3568 上编译 Rockit 时遇到的几个高频问题,附上根因分析和解决办法。

5.1 头文件找不到:rk_aiq.h、mpp_enc.h、rga.h

编译报错示例:

fatal error: rk_aiq.h: No such file or directory

根因通常是依赖路径没有加到编译搜索路径中。Rockit 的头文件分布在多个模块里,比如 AIQ 的头文件在camera_engine/include,MPP 的头文件在mpp/inc,RGA 的在rga/include。最简单的办法是用-I把这三个路径都加上:

cmake -DCMAKE_C_FLAGS="-I/path/camera_engine/include -I/path/mpp/inc -I/path/rga/include"

另外,Rockit 自己的 include 目录中还有个rk_type.h定义基础类型,如果报错定位到rk_type.h,检查一下是不是 SDK 目录结构被改动过,导致相对路径失效。

5.2 链接阶段找不到库:cannot find -lrockit

出现这种情况,多半是因为编译依赖顺序不对或者库路径不对。Rockit 的库本身是最终产物,但如果 sample 程序链接时指定了-lrockit,而librockit.so还没生成,或者没有指定-L路径,就会出现这个报错。

解决方式是先编译生成librockit.so,再编译 sample。或者在 CMakeLists 中调整 target 顺序。如果确认librockit.so存在但仍然报错,用find看一下实际文件名,确认是不是没有软链接或版本号后缀导致-lrockit无法匹配。

5.3 运行时缺少链接库:symbol lookup error

./sample_vi: symbol lookup error: /usr/lib/librockit.so: undefined symbol: RK_MPI_VENC_CreateChn

这个报错很典型,通常是板子上的librockit.so与 MPP 版本不匹配。比如板子的系统里已经有一个libmpp_enc.so,你新编译的 Rockit 依赖的却是另一版本的 MPP 接口。这种情况下,先把板子上旧的 MPP 库、旧 Rockit 库备份后移走,再放入新编译的库,然后用ldd重新确认依赖关系。

5.4 设备节点不通:open /dev/video0 失败

很多人在这一步被卡住,以为是 Rockit 编译问题,实际上大部分是设备树和驱动问题。排查顺序:

  1. 确定内核有没有编译进 ISP、MIPI DPHY、Sensor 驱动
  2. 查看设备树中 Camera 节点是否使能
  3. 检查/dev/mediaX和/dev/videoX是否存在
  4. 用media-ctl打印当前 media 拓扑,确认数据流路由与 Rockit 期望一致

比如 OV5695 这类 Sensor,通常需要 endpoing 里的 reg 值对应正确,如果 reg 错误,驱动解析时无法匹配到正确的虚拟通道。而且不同内核版本对数据通道的描述方式可能不同,有的用>open /dev/ion failed allocate ion memory failed

RK3568 的内核版本通常已经切换到 DMA-BUF Heap,Rockit 如果仍然走 ION 接口,就需要修改 Rockit 源码或者开启内核的旧 ION 兼容。检查内核配置:

cat /sys/kernel/debug/dri/0/summary ls /dev/dma_heap

如果/dev/dma_heap存在,说明系统使用的是 DMA-BUF Heap。这种情况下,需要确认你的 Rockit 版本是否支持USE_DMA_HEAP。有的 SDK 会有编译宏:

-DROCKIT_USE_DMA_HEAP=ON

如果没有这个宏,可以尝试升级 MPP 和 Rockit 到较新版本,或者给内核加上 ION 兼容支持。但我的建议是优先升级用户态库,因为改内核增加旧框架支持,后续可能会引入新的不稳定因素。

5.6 编译速度慢

搜热点时发现不少人在搜“编译慢”,确实在 RK3568 SDK 里,如果没有使用 ccache,全量编译 Rockit 和相关模块会非常依赖 CPU。如果只是单独编译 Rockit,代码量不算大,十几分钟到半小时内能完成。但如果你是从整个 SDK 开始构建,建议开启 ccache:

sudo apt install ccache export USE_CCACHE=1 export CCACHE_DIR=/path/to/.ccache

在 cmake 构建时可以设置:

-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache

二次编译会快非常多。如果是在多核机器上编译,直接用-j$(nproc)即可;但如果内存不大,-j太高可能会导致 OOM,建议 16G 内存以下用-j4或-j8。

5.7 常见报错速查表

报错信息可能原因解决方向
rk_aiq.h: No such file or directorycamera_engine 头文件路径未加入添加-I指向camera_engine/include
mpp_enc.h: No such file or directoryMPP 头文件路径未加入添加-I指向mpp/inc
undefined reference to RK_MPI_*链接顺序或库缺失调整链接顺序、确认librockit.so
error: ‘V4L2_PIX_FMT_NV12’ undeclared内核头文件版本过旧或未包含 v4l2 头文件安装/更新 linux-libc-dev,或添加对应 include 路径
open /dev/ion failed内存分配器不匹配开启内核 ION 兼容或切换 Rockit DMA_HEAP 编译选项
/dev/video0 open failed设备树或驱动问题检查 media 拓扑、设备树节点、Sensor 驱动
Segmentation fault多为库版本混用或内存配置异常ldd检查库依赖、替换旧 MPP/Rockit 库
No space left on device板端存储不足或 tmp 分区过小清理板端空间,或调整/tmp大小

6. 编译完成之后的扩展玩法:BT.1120 输出和多路 Sensor 采集

一旦 Rockit 编译通过并且基础测试正常,可以尝试的场景就多了。热点中有人提到“配置 bt1120 输出”和“调试 ov5695”,这两个我都试过一点,简单说一下在 Rockit 框架下的入口。

RGB/BT.1120 输出这类需求,通常发生在需要把视频送出去显示的场景。Rockit 中对应的模块是 VO(Video Output),或者使用 RGA 旋转缩放后再接显示通路。在 RK3568 上,BT.1120 输出能力取决于芯片 Video Port 的接口定义。实际调试时,首先要确认设备树中的 VOP 节点、显示接口、时钟配置都正确,其次在 Rockit 中创建 VO 通道时,需要把输出分辨率、像素格式、时序参数配成 BT.1120 对应的模式。这个过程比编译复杂得多,很多参数需要芯片手册和显示设备的规格表对照填。

OV5695 调试则主要落在 Camera 接入侧。在 Rockit 框架下,先确认设备树中 OV5695 的 I2C 地址、reset GPIO、power GPIO、MIPI data lanes 等配置与 Sensor 硬件连接一致。然后在camera_engine配置文件中加入 OV5695 的 sensor 名称和对应的初始化序列。接着编译进 AIQ 的 sensor 库,Rockit 初始化时才能正确加载。如果图像颜色不对,多半是白平衡增益没生效;如果预览黑屏,大概率是数据通路没通,而不是算法问题。

这两类扩展方向都需要在“编译 Rockit”之外多花数倍时间,但这也是 RK3568 平台好玩的地方。一套 SDKS 基础打牢之后,很多上层功能都是接口配置和参数调试的事。

7. 编译成功后我还会做的一组常规验证

为了让后续开发少踩坑,库编译成功后我一般会按顺序跑这组验证:

  1. 用sample_venc编码一段固定 YUV 数据,确认 MPP 编解码链路正常
  2. 用sample_vdec解码刚才的 H.264 数据,确认闭环一致
  3. 接上摄像头后跑sample_vi,确认采集链路正常
  4. 再跑sample_vi_venc做采集+编码全流程
  5. 启用 RGA 测试,验证图像缩放格式转换是否满足后续 AI 前处理需求

这组验证能够把 Rockit 依赖的各个核心子系统快速摸底一遍。如果其中某一步失败,重点排查对应子系统而不是 Rockit 本身。比如第 2 步解码失败,问题通常在 MPP,而不是 Rockit 框架层。

另外建议在板端测试时打开 Rockit 的调试日志。Rockit 支持通过环境变量控制日志级别,例如:

export RK_LOG_LEVEL=1

这样运行时会输出更多内部调用细节,定位问题会直观很多。具体变量名在不同版本可能略有差异,可以在源码中搜索log_level或rk_log.

回到开头说的那台板子,我最后把编译好的 Rockit 库和 sample 程序打到文件系统镜像里,重启验证了一遍自动加载和开机自启的流程。期间遇到的一次问题是,启动脚本先加载了旧版 MPP 库,导致 Rockit 初始化报版本不匹配。解决方法是把脚本里的LD_LIBRARY_PATH显式指向新库目录,并把旧库目录从路径中移走。

实际测试中还有个小技巧值得分享:调试 Rockit 时,不要只盯日志里的错误码。Rockit 很多错误码对应的是底层驱动或 MPP 模块的返回值,光看数字很难定位。比较实用的做法是先在板端用v4l2-ctl直接测一遍摄像头是否出图,再用mpi_enc_test这类 MPP 自带测试工具验证编解码,最后回到 Rockit 层组合调试。这样一层层往上查,每一步的基础都确认过,问题范围会迅速缩小。

这次编译测试花了一天左右,主要时间都耗在依赖库版本对齐和摄像头设备树的排查上。如果只编译 Rockit 而不跑 sample,那真的只是“编译”而已,没有太大参考价值。我建议每个拿到 RK3568 板子的人,尽量把编译、部署、运行这条完整链路都走通一遍,后续做任何上层功能,心里都有底。

最后再补充一个小习惯:Rockit 编译产物建议保留完整的编译日志,万一后续换了 SDK 版本或者改了依赖路径,能够快速 diff 出差异点。把这些日志和修改过的 CMake 参数统一放在一个文档里,下次遇到问题翻一翻,往往能省下不少重复排查的时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询