☰
RK3568 SDK中Rockit编译与测试实战:从环境搭建到设备树配置
2026/10/3 1:34:04 网站建设 项目流程

如果你是从应用开发转过来做RK3568,第一次面对Rockit,很容易被它搞懵。我最初拿到板卡SDK时,以为Rockit就是某个静态库,找到头文件链接完就能用。真到自己动手编译才发现,这玩意背后牵扯到mpp、rga、rkaiq一整套底层库,设备树、sensor驱动、IQ文件稍有不对,编译能过、测试大概率也挂在运行阶段。这套东西最大的问题不是难,而是资料分散,官方文档和实际代码版本经常对不上,你必须在板子上反复试错才能把链路捋顺。

这篇文章把我实际编译测试RK3568 SDK中Rockit的过程完整记录下来,包括环境准备、两种编译方式、部署验证,以及测试时必然要碰到的设备树、sensor和显示配置问题。如果你正准备在RK3568上做摄像头采集、视频编码、RTSP推流或者AI视觉这类开发,这篇内容能帮你少走很多弯路。

1. Rockit在RK3568 SDK中的定位与依赖关系

1.1 Rockit不是单一个库,而是一整套媒体中间件

先纠正一个最常见误解:Rockit不是一个可以直接拿过来链接的库,它在RK3568上是一整套以C/C++接口为主的多媒体处理中间件。你可以把它理解为"业务应用和内核驱动之间的翻译官"——摄像头采集、ISP处理、视频编解码、显示输出这些底层能力,Rockit都用统一API封装起来,你在应用层只需要调用rk_mpi_xxx系列接口就能完成一个典型的"采集-编码-推流"流水线。

这里有个很重要的概念:Rockit在SDK里其实分成几个层次,远不止一个librockit.so。典型包含:

  • media模块:负责数据流打通、buffer管理、通道绑定;
  • apilib模块:对外暴露的API层,也就是你开发时真正调用的部分;
  • modules模块:接到底层硬件能力,比如ISP、VENC、VDEC、RGA、VO这些子模块。

编译Rockit时,这几个模块会分别生成对应库文件,再通过头文件和链接关系合成一个整体。所以你在SDK目录里会看到external/rockit下面还有多层子目录,这不是代码乱,而是模块化设计的必然结果。

1.2 编译Rockit前必须先满足的依赖矩阵

Rockit本身不依赖太多第三方库,但它依赖一套同源的底层组件,这些组件在SDK里同样需要编译或者已经预编译好。我在实际编译前吃过亏:直接进到external/rockit目录想单独编,结果librkaiq的版本和内核ISP驱动对不上,编译过去了,跑sample时一启动就崩。编译前必须确认下面几项:

依赖组件在SDK中的位置作用不匹配时的典型现象
rockchip_mppexternal/mpp视频编解码底层VENC/VDEC初始化失败或输出码流花屏
librgaexternal/rga图像缩放、格式转换IMG_GE_RGA调用报错,图像输出黑屏
librkaiqexternal/aiq摄像头ISP图像质量调优Camera采集画面全黑或颜色严重偏色
drm/drm-utilsexternal/drm_utils显示输出相关VO绑定失败,HDMI/BT1120无输出

这些组件在Rockchip的SDK中都有对应版本管理文件,通常用manifest来锁定版本。编译前务必要确认你拉的SDK是一整套完整的,而不是从GitHub上单独clone的Rockit源码——单独clone的Rockit没有配套编译脚本,而且跟板子上的mpp、rkaiq版本经常不匹配。

1.3 SDK拿到手后先确认索引和版本

接触任何Rockchip SDK,我建议第一件事不是急着编译,而是先花十分钟确认代码版本和目录完整性。RK3568的SDK一般在根目录下会有.repo目录,内部记录了各个子仓库的manifest版本。执行:

cd SDK_ROOT .repo/repo/repo forall -c 'echo $REPO_PROJECT && git log --oneline -1'

这条命令会把所有子仓库的路径和当前commit列出来。重点看external/rockit、external/mpp、external/aiq的commit时间是否大致同步。如果Rockit是一个月前的,mpp是三个月前的,那编译十有八九要出问题。不要信任任何"单独更新某个库"的说法,Rockit对mpp/rkaiq的接口依赖极强,版本必须一起升或一起降。

顺便说一句,external/rockit目录里通常没有.git目录的完整历史,它通过.repo管理,所以git log是无法执行的。用repo forall统一查最靠谱。

2. 交叉编译环境:先把工具链和路径排清楚

2.1 工具链选择:buildroot工具链永远是首选

编译RK3568的Rockit,说到底是交叉编译。市面上有几种工具链:Linaro的aarch64-linux-gnu-、ARM官方工具链、还有Rockchip SDK内置的buildroot工具链。我的建议非常明确:用SDK内置buildroot生成的工具链,别用外面随便下的。

为什么?RK3568的SDK完整发布包含buildroot源码包,在buildroot/output或prebuilt目录里可以找到配套工具链。这套工具链是跟SDK里的rootfs、glibc版本严格匹配的。如果你用Linaro的独立工具链编译Rockit,编译一般能过,但拷到板子上运行时会报GLIBC_2.34 not found之类的错——因为工具链使用的glibc比板子rootfs里的新,动态链接器根本无法识别。

在EVM板较新的SDK版本中,工具链路径通常长这样:

SDK_ROOT/prebuilt/gcc/linux-x86/aarch64/gcc-arm-10.3-linux-gnu/bin

不同版本有差异,找一下带aarch64-linux-gnu-gcc的目录就行。确认方法也简单:

aarch64-linux-gnu-gcc -v

看输出里是不是带--with-sysroot,如果带且指向buildroot目录,就是官方配套工具链,可以用。

2.2 一套可复用的环境变量配置

交叉编译最烦人的就是环境变量。每次打开新终端都要重新设置一堆变量,设置错了又浪费时间排查。我建议把下面这段写成一个setenv_rk3568.sh,放在你的项目目录里,source一次搞定:

export SDK_ROOT=/home/user/rk3568_sdk export TOOLCHAIN_PATH=$SDK_ROOT/prebuilt/gcc/linux-x86/aarch64/gcc-arm-10.3-linux-gnu/bin export PATH=$TOOLCHAIN_PATH:$PATH export CROSS_COMPILE=aarch64-linux-gnu- export CC=${CROSS_COMPILE}gcc export CXX=${CROSS_COMPILE}g++ export AR=${CROSS_COMPILE}ar export LD=${CROSS_COMPILE}ld export STRIP=${CROSS_COMPILE}strip export SYSROOT=$SDK_ROOT/buildroot/output/rockchip_rk3568/host/aarch64-buildroot-linux-gnu/sysroot

这里SYSROOT是关键。Rockit编译时会通过--sysroot=$SYSROOT去查找头文件和标准库,如果你不设置,CMake会默认用编译器的内置路径,最终可能把PC上的/usr/include里乱七八糟的头文件拉进来,导致的错误千奇百怪。这个变量我在几次项目里都吃过亏,单独拎出来强调一下。

2.3 同时装多套工具链会让CMake选错编译器

很多工程师机器上同时装了arm-2019、aarch64-linux-gnu-10.3、Android NDK等多套工具链。CMake选编译器时,如果检测不到你明确指定的路径,就会按PATH顺序去找第一个aarch64-linux-gnu-gcc。这会导致一种非常隐蔽的问题:编译能通过,但生成的Rockit库在板子上就是跑不起来,而且报错跟工具链完全不搭边,比如Illegal instruction。

避免方法是在CMake配置时显式指定工具链文件,不要依赖PATH。Rockit源码目录里一般自带toolchain/linux_arm64.cmake或类似文件,里面会把CMAKE_C_COMPILER和CMAKE_SYSROOT写死。如果SDK版本里没有,就自己写一个,内容核心是:

set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER /home/user/rk3568_sdk/prebuilt/gcc/linux-x86/aarch64/gcc-arm-10.3-linux-gnu/bin/aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER /home/user/rk3568_sdk/prebuilt/gcc/linux-x86/aarch64/gcc-arm-10.3-linux-gnu/bin/aarch64-linux-gnu-g++) set(CMAKE_SYSROOT /home/user/rk3568_sdk/buildroot/output/rockchip_rk3568/host/aarch64-buildroot-linux-gnu/sysroot)

用绝对路径写死,CMake就不会有歧义。这一步省下来的排查时间,比写这个文件的时间多十倍。

3. 编译Rockit的两种方式与完整操作

3.1 方式一:在buildroot里集成编译,省心且可靠

如果你手里是一整套RK3568 SDK,最推荐的编译方式是直接在buildroot里集成。因为Rockit是作为buildroot的一个package存在的,buildroot会帮你处理依赖关系,先编译mpp、rga、aiq,再编rockit,最后自动部署到rootfs的target目录。整个过程的顺序和依赖,官方都已经验证过,踩坑概率最低。

具体操作步骤:

cd SDK_ROOT source build/envsetup.sh lunch rk3568_evb8m-userdebug cd buildroot make rockit -j$(nproc)

这里lunch后面的product配置要看具体的板子型号,EVM板通常是rk3568_evb8m、rk3568_evb1之类,不确定就执行lunch不带参数,看看列表里有哪些。编译完成后,make rockit会自动把生成的库和可执行文件install到buildroot/output/rockchip_rk3568/target/usr/lib和target/usr/bin。

还有一个技巧:如果只改了Rockit源码,重新make rockit不会整包重新编译,buildroot会识别到变更自动增量编译,非常快。我第一次全量编译Rockit大约用了10分钟,二次增量编译往往不到1分钟。

3.2 方式二:手动cmake交叉编译,适合单独维护Rockit

有些场景你不想动整个buildroot,比如只做Rockit开发、不想重新做rootfs打包,那就手动cmake编译。进到external/rockit目录,一般会有一个build.sh或CMakeLists.txt,标准流程是:

cd external/rockit rm -rf build mkdir build && cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain/linux_arm64.cmake make -j8

如果编译报错找不到rk_mpi_mb.h这类头文件,多半是CMake没找到rockit的依赖头文件路径,需要手动加参数,比如:

cmake .. \ -DCMAKE_TOOLCHAIN_FILE=../toolchain/linux_arm64.cmake \ -DRKAIQ_DIR=$SDK_ROOT/external/aiq \ -DMPP_DIR=$SDK_ROOT/external/mpp \ -DRGA_DIR=$SDK_ROOT/external/rga

具体变量名不同SDK版本有差异,你进去看一眼CMakeLists.txt里定义了哪些-D选项再填就行。手动编译最大的好处是你可以在源码里加日志,随时做定制化修改,但代价是要自己管理依赖库的路径,版本对不上就各种诡异报错。我的建议是:第一个工程周期用方式一,确保环境完全正确后再切到方式二做二次开发。

3.3 编译产物到底有哪些

编译完成后,在Rockit的build输出目录里主要会看到这几类文件:

  • librkaiq.so、librkaiq_3a.so:ISP相关的,摄像头图像质量靠它;
  • librk_mpi.so:Rockit对外核心API库;
  • librga.so:图像加速库,有时候这个不跟Rockit一起编,而是由RGA单独提供;
  • librockit_*.so:各模块的内部实现库;
  • sample_*:一系列测试可执行文件,名字一般是sample_venc、sample_vdec、sample_camera、sample_vo等。

拿到这些产物后,手动部署时要按依赖关系拷,建议直接用buildroot的make rockit装一次然后从target目录里拷贝,这样不会漏库。我见过有人手动把librk_mpi.so拷到板子上,结果漏了librkaiq.so,sample一启动就报symbol lookup error,花了大半天才查出来。

4. 部署到板子并让sample真正跑起来

4.1 部署前必须确认的运行目录与权限

编译产物有了,下一步是部署到板子。这里要先搞清楚RK3568 SDK的rootfs目录约定——Rockit的sample和配置不是随便放的,它有一套默认路径逻辑。常见约定是:

  • 库文件放/usr/lib;
  • 可执行程序放/usr/bin或/oem/usr/bin;
  • IQ文件(ISP调优参数)放/etc/iqfiles或/oem/usr/etc/iqfiles;
  • 配置文件放/etc/rockit或/oem/usr/etc/rockit。

部署我一般用两种方式:一是直接把编译产物的整个目录打包,传到板子上解压覆盖;二是挂载NFS,把开发机编译目录当板子的运行时目录,改代码后直接运行,省去反复拷贝。NFS方式对调试效率提升非常明显,前提是板子能正常上网且没有开启防火墙限制。

不管哪种方式,记得给可执行文件加执行权限:

chmod +x /usr/bin/sample_venc

4.2 拿sample_venc做第一个冒烟测试

部署完成后,不要一上来就跑复杂的多路绑定程序,先用最简单的sample_venc(视频编码)做冒烟测试。这个sample的职责很单纯:从摄像头采集图像,经过Rockit处理后编码成H.264/H.265码流,输出到文件。它能跑通,说明Rockit库、mpp、采集链路基本没有问题。

在板子上执行:

cd /oem/usr/bin export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH ./sample_venc -w 1920 -h 1080 -t 7 -o /tmp/test.h264

参数含义大致是:-w宽度;-h高度;-t编码类型,7通常对应H.264;-o输出文件。不同SDK版本的sample参数不完全一样,执行时不带参数会打印usage,先看一眼确认。

运行时观察几个关键日志:

  • 是否正常打开视频设备open /dev/video0 success;
  • 是否成功创建AI通道和VENC通道;
  • 最后结束时是否输出encode frame count = xxx。

如果编码过程中有ERROR级别日志,先别乱改代码,把dmesg | grep -i isp和dmesg | grep -i mpp的输出拉出来看内核侧有什么信息。Rockit的问题定位要遵循"先内核后应用"的顺序,内核驱动报错不解决,应用层改再多都没用。

4.3 怎么判断测试真的通过了

很多人看sample跑起来没报错就以为测试通过,这是不对的。我做测试至少验证三层:

第一层是进程退出码,sample正常结束时shell返回码应该是0,如果非0说明某个通道没有正常关闭;

第二层是输出文件的完整性,用下面的命令在板子上查看码流信息:

ffprobe /tmp/test.h264

如果ffprobe能识别出H.264码流且分辨率跟你设置的一致,说明编码链路通畅;如果提示could not find codec parameters,哪怕sample日志说成功了,实际编码也是异常的,常见原因是buffer分配大小不对或者帧率设置太低导致输出码流不完整。

第三层是实际回放,把/tmp/test.h264拉到电脑上用VLC或者ffplay播放,肉眼确认画面不是全黑、不是花屏。这一步能暴露ISP出的原始图是否正常,因为很多情况下编码器没毛病,纯是sensor或ISP配置不对导致输入就是黑帧。

5. 测试时避不开的周边配置:设备树、sensor与显示链路

5.1 摄像头不出图,七成问题不在Rockit而在设备树

测试sample_venc时最常碰到的就是摄像头不出图。我在RK3568上调试过OV5695这颗sensor,最大的教训是:Rockit跑不起来摄像头,先怀疑设备树,再怀疑IQ文件,最后才怀疑代码逻辑。

RK3568的设备树中,sensor节点一般在kernel/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi这类文件里定义。以OV5695为例,需要在设备树中检查几个节点:

  • I2C总线地址是否正确,OV5695一般挂在I2C几上,地址是0x36;
  • 时钟频率clock-frequency是否配置了,sensor的MCLK一般要求24MHz;
  • reset和powerdown引脚的GPIO号是否正确,对应IO口的pinctrl配置是否冲突;
  • 数据lane数是否与实际硬件连接一致,4 lane摄像头接成2 lane,图像不是出不来就是花屏。

调试时在板子上用i2cdetect -y 0(根据实际I2C总线号替换0)看一眼sensor地址是否存在。如果探测不到,设备树I2C或供电就有问题,跟Rockit半毛钱关系没有;如果能探测到但就是不出图,再查reset GPIO和reset时序。这个排查顺序能帮你省掉至少半天无头苍蝇式debug。

另外,Rockit运行时需要加载sensor对应的IQ文件。OV5695的IQ文件一般是ov5695_0.json,或者针对定制板卡可能是ov5695_custom_0.json。这个文件名必须和rkaiq初始化时传入参数对应,很多定制板的问题就出在这里:把EVM板的IQ文件直接拷到定制板上,sensor的镜头模组不同,IQ参数不匹配,画面亮度、色彩完全不对。

5.2 BT1120输出配置对测试结果的影响

测试完摄像头采集,很多人会接着测显示输出,这时容易碰到BT1120。RK3568支持通过VOP把视频数据以BT1120格式输出给外部芯片或设备。这个功能本身不复杂,但配置项分散在设备树和Rockit的VO模块参数里,任何一个对不上,输出就是花屏或者无信号。

设备树侧需要确认vopb或vopl节点的route配置是否使能了对应的接口。如果用的是BT1120,通常还会配套一个bt1120节点,里面设置像素格式、时钟极性、数据位宽。我记得调试时遇到过VOP本身输出正常,但BT1120的时钟极性接反,外部采集设备看到的画面边缘有严重重影,改设备树的pinctrl-0配置(更换带反相时钟的引脚组)后就好了。

Rockit侧则要确认VO通道的像素格式和视频层的配合。BR3568的VOP层对BT1120的输出格式有要求,一般需要设置成YUV422格式,并保证buffer alignment。跑sample_vo(显示输出)时如果黑屏,先不要怀疑Rockit代码,派一个实时的纯色输出测试,比如用modetest或weston --idle-time=0这个工具集里给出的一张纯色画面,如果外部设备能显示纯色,说明硬件链路没问题,再把Rockit接上去。硬件链路不通就去改设备树和驱动,不要浪费时间去调API参数。

5.3 常见异常日志与定位对照表

编译测试中会遇到各种报错,很多是可以一眼定位的。我把这些年踩过的、结合社区里高频出现的Rockit异常场景整理成了一张对照表,方便你快速判断方向:

现场症状常见原因优先排查路径
启动报GLIBC_2.34 not found交叉工具链版本比RootFS新换回SDK buildroot自带工具链重编
跑sample报symbol lookup error板子上的rockit相关库与你编译版本不一致把编译产的so全部更新,不要只更新主库
摄像头节点open /dev/video0 failed设备树sensor节点没生效查i2cdetect、复位GPIO、驱动dmesg
有码流文件但ffprobe不识别buffer或帧率配置导致码流不完整检查VENC参数、采集帧率设置
图像全黑初始化参数不对,配置装载失败查IQ文件路径和日志中的aiq initialization
图像花屏偏色sensor的配置与硬件不匹配检查I2C地址/时钟/数据lane配置
显示输出无信号设备树route或BT1120配置有冲突用modetest确认硬件链路再查Rockit

这张表不是我拍脑袋列的,每一条都在实际调试中遇到过,尤其是第一个glibc版本问题,在初学者群里几乎每周都有人问,根源就是没用SDK配套工具链。

6. 多次编译测试后的几个实操结论

6.1 编译时间与资源占用实测

先给大家一个参考数据,方便安排项目节奏。在配置为8核CPU、32G内存的开发机上,buildroot增量编译Rockit(只改rockit一个包)大约需要30到60秒;如果同时修改了metadata,全量重编可能要10到20分钟。手动cmake编rockit单模块,第一次全量编译大约需要5到10分钟,之后增量编译非常快。整体编译不算很耗时,真正耗时的是运行期的debug,尤其是摄像头和显示链路的问题。

板子资源也提一嘴:RK3568是4核Cortex-A55,跑单路1080P编码sample时CPU占用大约20%到30%,跑双路编码会高一些。如果你在开发机上打开了几十个Chrome页面,同时再编译Rockit,编译速度会明显下降,建议做编译时把浏览器关掉,这个细节虽然土,但很实际。

6.2 哪些改动值得重编Rockit,哪些不值得

Rockit的编译并不是改一行代码就得从头编一次,这里有个成本意识问题。我在项目里总结了一个原则:

不值得重编Rockit的场景:只改应用层逻辑、只调整sensor的IQ参数、只调整设备树的引脚配置。IQ参数和sensor配置都是运行时加载的,Rockit库本身不需要重新编译,重启板子重新加载配置文件即可。设备树改完要重新编译内核或dtb,但也没必要重编Rockit。

值得重编Rockit的场景:改动了rk_mpi_*API的内部逻辑;调整了Rockit模块间的消息交互机制;跨版本升级SDK时同步Rockit和mpp。这些情况下不重编的话,运行时会因为API接口不匹配出现各种不可预期行为。

这个区分能帮你高效利用时间。我第一次做Rockit开发时只要改了一点配置就想着重编整个SDK,经常一个下午全耗在编译上了,改了思路之后,只花10分钟就能完成"改配置-重启板子-跑测试"的循环。

6.3 一套我建议的联调流程

最后分享一下我现在每到一个RK3568新板卡时都会走的联调流程,这套流程基本保证一天内能把Rockit编译测试链路打通:

第一步,确认SDK完整性和版本同步,用repo forall检查各仓库commit时间。

第二步,清理buildroot的cache并编译一次最小系统,确认基础rootfs没问题。

第三步,用buildroot方式编译并部署Rockit,所有库、sample、IQ配置文件统一部署。

第四步,运行sample_venc做冒烟测试,验证完整链路。

第五步,测试特定sensor(比如OV5695)的采集,此时重点检查设备树、复位、I2C等硬件配置。

第六步,测试显示输出,验证BT1120或HDMI链路。

第七步,接入具体应用场景,做AI推理、推流或录制等业务开发。

这套流程从零到跑通基本不会卡住太久,即使中间遇到问题,也能通过流程定位到具体环节,不会在一堆相互纠缠的因素里打转。按照这个顺序走,Rockit编译测试这事儿基本就是个体力活,而非纯粹的debug战争。

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

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

立即咨询