RK3588交叉编译FFmpeg:启用RKMPP与RGA硬件加速实践
2026/9/24 5:29:54 网站建设 项目流程

先交代一下背景:如果你手里正好有一块RK3588的开发板,并且想用硬件解码去处理几路视频流,那你迟早会撞上一个坎——系统预装的ffmpeg默认走的是软解和软编,CPU直接被拉满,VPU和RGA全程看戏。我最初也想着“直接apt install ffmpeg不就行了”,实测下来那个ffmpeg里既没有rkmpp也没有rga,想踩硬件加速这条路,只能自己动手编译一份。

这篇文章我会把整个流程从头到尾拆开讲:在Ubuntu 22.04主机上交叉编译一份带RKMpp和RGA硬件加速的FFmpeg,再部署到RK3588板子上跑起来。内容包括工具链安装、sysroot准备、mpp和rga两个库的编译、ffmpeg的configure与make、常见编译错误和运行时报错排查。不管你是做视频处理、AI盒子还是直播推流,这套流程基本都能直接抄作业。

1. 为什么要费劲编译一份带RKMpp和RGA的FFmpeg

1.1 系统自带ffmpeg的痛

Ubuntu 22.04的官方源里确实有ffmpeg,但它是给通用x86/ARM64服务器用的,默认不启用Rockchip硬件加速相关模块。在RK3588板子上执行:

ffmpeg -version

看“configuration”那一行,你会发现根本没有--enable-rkmpp。不带这个选项编译出来的ffmpeg,即使系统里躺着librockchip_mpp.so,它也调不动VPU。更麻烦的是RGA,它通常作为libavfilter的滤镜或hwaccel集成进ffmpeg,没有对应的编译参数支持,你敲-vf scale_rga这类命令时,只会得到No such filter的报错。

从软解到硬解,CPU占用率的差别很直观。我测试过同一段4K H.265视频,软解时RK3588的四个A76核心全部打满,温度一路飙到70多;换成rkmpp硬解后,CPU占用率直接掉到5%以下,整机功耗和发热都降了一个量级。这正是自己编译ffmpeg的最大价值所在。

1.2 RKMPP和RGA分别是什么

这里先把两个概念理清楚,因为很多新手容易混淆。

RKMPP,全称Rockchip Media Process Platform,是瑞芯微提供的媒体处理库,对应librockchip_mpp.so。它封装了MPI(Media Process Interface),负责和VPU交互,完成H.264、H.265、VP9、AV1等视频的硬件编解码。在ffmpeg里,它表现为以_rkmpp结尾的编解码器,比如h264_rkmpphevc_rkmpp

RGA,全称Rockchip Raster Graphic Acceleration,是一个2D图形加速引擎,专门做缩放、格式转换、裁剪、旋转等操作,对应librga.so。它和GPU不冲突,GPU管3D渲染,RGA管2D图形搬运。在视频后处理场景里,RGA可以把NV12帧缩放成模型输入分辨率,或者把BGRA转成YUV,速度比CPU软转快得多。

在ffmpeg的硬件加速链路里,RKMPP负责编解码,RGA负责帧的格式转换和缩放,两者配合,可以做到整条视频流水线都不经过CPU做像素级操作。说白了,一个管“解”和“编”,一个管“转”和“缩”。

1.3 编译成功后你得到了什么

自己编译一遍带来的实际收益很清晰:

  • ffmpeg命令行可以直接用-c:v h264_rkmpp指定硬件解码或编码
  • 多路视频流处理时CPU占用率大幅下降
  • 可以把scale_rga滤镜用于2D硬件加速缩放,避免CPU软缩放
  • 编译产物可移植,量产时直接打包部署即可

这套编译流程本身不复杂,但一次跑通需要对sysroot、交叉编译依赖、库版本匹配有清晰的概念。下面按步骤来。

2. 编译前准备:交叉工具链、sysroot与依赖库

2.1 安装交叉编译工具链

在Ubuntu 22.04主机上,先建一个工作目录,方便把所有源码和产物集中管理:

mkdir -p ~/rk3588_ffmpeg && cd ~/rk3588_ffmpeg

然后安装基础依赖:

sudo apt update sudo apt install -y \ build-essential \ git \ make \ cmake \ autoconf \ automake \ libtool \ pkg-config \ yasm \ nasm \ crossbuild-essential-arm64 \ libdrm-dev

这里最关键的是crossbuild-essential-arm64,它提供aarch64交叉编译器aarch64-linux-gnu-gcc。Ubuntu 22.04仓库里对应的版本一般是GCC 11,这个版本编译mpp、rga、ffmpeg都没有问题,不需要自己折腾其他工具链。

装完验证一下交叉编译器是否可用:

aarch64-linux-gnu-gcc --version

如果提示找不到命令,检查一下crossbuild-essential-arm64是否安装成功。这个包会把编译器装在/usr/bin/aarch64-linux-gnu-前缀下。

2.2 准备目标板rootfs

这一步特别容易被忽略,但偏偏卡住了不少人。编译带rkmpp的ffmpeg时,configure要检测的不只是头文件,还有动态库和依赖链。如果不准备一个目标板的rootfs放到$SYSROOT里,configure阶段会频繁出现checking for ... no这类失败。

rootfs最简单的获取方式,是把板子上正在运行的Ubuntu系统整体rsync出来。在开发板上执行:

sudo rsync -avz \ --exclude='/proc' --exclude='/sys' --exclude='/dev' \ --exclude='/tmp' --exclude='/run' --exclude='/mnt' \ --exclude='/media' --exclude='/lost+found' \ / user@192.168.x.x:/home/you/rk3588_ffmpeg/sysroot/

如果没有正在跑的板子,也可以直接下载开发板厂商发布的rootfs镜像包,解压后放到同一目录。需要确保sysroot里包含/usr/lib/aarch64-linux-gnu/目录,这是aarch64架构Ubuntu存放共享库的标准位置。

2.3 目录规划和依赖检查

把rootfs准备好之后,统一用环境变量指路:

export SYSROOT=$HOME/rk3588_ffmpeg/sysroot

每次开新终端都要重新执行这一句,或者直接写进~/.bashrc里,省得每次手敲。接下来检查一下sysroot里有没有libdrm相关文件:

ls $SYSROOT/usr/lib/aarch64-linux-gnu/ | grep drm

如果有libdrm.so和对应的头文件,说明rootfs自带了DRM支持;如果没有,后续编译mpp时会报缺少DRM依赖,需要先交叉编译一份libdrm装进sysroot。这一步不要跳过,直接复制宿主机上的libdrm是不可行的,架构不匹配会导致链接失败。

3. 编译RKMpp,注意避开这些坑

3.1 获取源码与分支选择

rkmpp的官方仓库在GitHub上,直接拉取:

cd ~/rk3588_ffmpeg git clone https://github.com/rockchip-linux/mpp.git

默认拉下来的是master分支。对RK3588来说,master分支支持已经比较完善,H.264、H.265、VP9、AV1的硬件解码都有。如果你想更保守一点,可以根据板卡BSP版本切换到对应的release tag,一般release分支经过厂商验证,稳定性更好,但代价是可能缺少新特性。我自己的做法是先用master编译测试,确认编码器、解码器都正常后再锁定版本。

3.2 CMake构建与安装

mpp使用CMake构建,官方仓库里已经提供了针对aarch64的工具链文件。直接引用即可:

cd mpp mkdir build && cd build cmake .. \ -DCMAKE_TOOLCHAIN_FILE=../cmake/aarch64.linux.cmake \ -DCMAKE_INSTALL_PREFIX=$SYSROOT/usr \ -DCMAKE_BUILD_TYPE=Release make -j$(nproc)

这里解释一下-DCMAKE_INSTALL_PREFIX=$SYSROOT/usr的含义:编译出来的头文件和库会安装到sysroot里,后续ffmpeg的configure在sysroot内搜索依赖时,就能直接找到rockchip/mpp_*.hlibrockchip_mpp.so

编译过程一般不会太慢,四核以上机器一两分钟就完成。如果报错提示找不到DRM,说明sysroot里的libdrm没有准备好。报错信息通常是:

Could NOT find DRM (missing: DRM_INCLUDE_DIRS DRM_LIBRARIES)

这时候不要硬编译,先解决libdrm问题。

3.3 libdrm依赖问题

libdrm的交叉编译比较简单,源码从freedesktop官方仓库拉取:

cd ~/rk3588_ffmpeg git clone https://gitlab.freedesktop.org/mesa/drm.git cd drm mkdir build && cd build meson setup .. \ --cross-file=交叉编译配置 \ --prefix=$SYSROOT/usr ninja ninja install

如果系统里没有meson和ninja,先安装:

sudo apt install meson ninja-build

交叉编译配置文件可以这样写:

[binaries] c = 'aarch64-linux-gnu-gcc' cpp = 'aarch64-linux-gnu-g++' ar = 'aarch64-linux-gnu-ar' strip = 'aarch64-linux-gnu-strip' pkgconfig = 'aarch64-linux-gnu-pkg-config' [host_machine] system = 'linux' cpu_family = 'aarch64' cpu = 'aarch64' endian = 'little'

安装完成后,回到mpp的build目录,重新跑一次cmake,这次基本上能顺利通过。

3.4 为什么建议保留动态库

mpp编译时有动态库和静态库两种选项,默认输出动态库librockchip_mpp.so,推荐保持这个默认值。原因有两个:一是后续如果升级mpp版本,只需要替换板子上的so文件,不用重新编译ffmpeg;二是在ffmpeg运行过程中可能会动态加载mpp的独立模块,比如mpi、vpu、rkvdec,静态链接这些模块反而容易出问题。

编译完成后执行安装:

sudo make install

检查一下关键文件是否就位:

ls $SYSROOT/usr/include/rockchip/ ls $SYSROOT/usr/lib/librockchip_mpp*

mpp.hmpp_frame.h这些头文件,以及librockchip_mpp.so,说明mpp部分已经妥了。

4. RGA库编译:性能提升的关键一环

4.1 源码获取

RGA使用rockchip-linux/linux-rga仓库:

cd ~/rk3588_ffmpeg git clone https://github.com/rockchip-linux/linux-rga.git

这个仓库比mpp小很多,核心代码集中在libs目录下,里面是对RGA硬件操作的封装。

4.2 toolchain文件与编译参数

linux-rga虽然也用CMake,但对交叉编译的支持没有mpp那么开箱即用。直接使用系统自带工具链时,可能会在find_package或者头文件搜索环节出问题。建议准备一份独立的toolchain文件。

创建一个rga_toolchain.cmake

set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) set(CMAKE_FIND_ROOT_PATH /home/you/rk3588_ffmpeg/sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

然后编译安装:

cd linux-rga mkdir build && cd build cmake .. \ -DCMAKE_TOOLCHAIN_FILE=/home/you/rk3588_ffmpeg/rga_toolchain.cmake \ -DCMAKE_INSTALL_PREFIX=$SYSROOT/usr make -j$(nproc) sudo make install

安装完成后检查:

ls $SYSROOT/usr/include/rga/ ls $SYSROOT/usr/lib/librga.so

rga.hlibrga.so都存在,说明RGA库已经进入sysroot。

4.3 版本匹配问题

RGA有个比较隐蔽的坑,就是版本匹配。板子上运行的librga版本必须和内核DRM/ION驱动的版本兼容,否则运行时会出现类似RGA_GET_VERSION的错误,或者failed to query rga version

我在调试过程中遇到过这样的情况:自己编译的新版librga放到老版本内核的板子上,调用RGA时直接报驱动版本不匹配。后来换回和板子BSP配套的librga版本,问题迎刃而解。

所以编译之前,先确认板子上的/usr/lib/librga.so是什么版本:

strings /usr/lib/librga.so | grep -i version

如果板子自带librga版本比较老,而你自己编译的版本很新,建议以板子实际跑的版本为准,或者干脆把编译好的librga推送到板子上替换,但前提是内核驱动必须兼容新版本。

4.4 RGA和ffmpeg的集成方式

在ffmpeg里,RGA不是独立编解码器,而是作为滤镜或hwaccel辅助模块存在。Rockchip维护的ffmpeg分支里,RGA主要用在scale_rga这类滤镜上。它的典型用法是把解码出来的硬件帧通过RGA做缩放和格式转换,再喂给编码器或AI推理模块。

如果你的板子上装了Rockchip的mpp和rga,并且ffmpeg编译时正确开启了RGA支持,ffmpeg -filters里能看到scale_rga。这个滤镜走的是2D加速引擎,CPU几乎不参与像素运算。

5. FFmpeg源码与configure配置要点

5.1 主线还是rockchip分支

这一步先要想清楚:你只需要标准硬编硬解,还是需要额外的RGA滤镜。

如果只是标准硬编硬解,主线FFmpeg就能满足,配置--enable-rkmpp即可。但如果你明确要用scale_rga这类RGA滤镜,或者需要Rockchip在ffmpeg里打的专用补丁,建议使用Rockchip维护的ffmpeg仓库:

git clone https://github.com/rockchip-linux/ffmpeg.git

这个仓库跟随主线更新,同时集成了Rockchip的专用补丁,对RGA的集成更完整。我自己的项目里用到RGA做画面缩放,所以直接用rockchip分支。

5.2 关键configure参数逐项说明

以下是实际可用的配置,已经经过验证:

cd ffmpeg export SYSROOT=/home/you/rk3588_ffmpeg/sysroot ./configure \ --prefix=$SYSROOT/usr \ --arch=aarch64 \ --target-os=linux \ --enable-cross-compile \ --cross-prefix=aarch64-linux-gnu- \ --sysroot=$SYSROOT \ --enable-rkmpp \ --enable-rga \ --enable-libdrm \ --enable-avcodec \ --enable-avformat \ --enable-avutil \ --enable-swscale \ --enable-avfilter \ --enable-version3 \ --disable-doc \ --disable-debug \ --disable-x86asm \ --extra-cflags="-I$SYSROOT/usr/include -I$SYSROOT/usr/include/rga" \ --extra-ldflags="-L$SYSROOT/usr/lib -L$SYSROOT/usr/lib/aarch64-linux-gnu"

逐个拆解这些参数的含义:

  • --enable-rkmpp:启用RK MPP硬件编解码支持,这是整个编译的核心开关。
  • --enable-rga:启用RGA滤镜和加速支持,前提是sysroot里能找到rga头文件。
  • --enable-libdrm:mpp依赖drm接口,这个不开启,ffmpeg的hwdevice初始化会失败。
  • --sysroot:指定目标板的根文件系统目录,configure和后续编译都会在这个环境下搜索头文件和链接库。
  • --cross-prefix:交叉编译器的前缀,ffmpeg会在后面自动拼接gccld等命令。
  • --disable-x86asm:aarch64下不需要x86汇编加速,不加这个选项可能会在编译时引入x86汇编指令导致失败。
  • --extra-cflags--extra-ldflags:手动指定额外的头文件和库搜索路径。-I$SYSROOT/usr/include/rga这行很关键,很多人的RGA检测失败就是因为这里没加。

5.3 常见的configure报错与解法

实际编译中遇到过几类典型报错,这里把处理和原因一起说。

第一类,ERROR: rkmpp not found。说明sysroot里没有mpp头文件或库,或者pkg-config的搜索路径没指到sysroot。可以通过设置环境变量解决:

export PKG_CONFIG_PATH=$SYSROOT/usr/lib/pkgconfig:$SYSROOT/usr/lib/aarch64-linux-gnu/pkgconfig

然后重新跑configure。

第二类,ERROR: rga not found。说明librga头文件没找到。检查$SYSROOT/usr/include/rga/rga.h是否存在,并把--extra-cflags里的-I$SYSROOT/usr/include/rga保留好。

第三类,ERROR: libdrm not found。说明sysroot里缺少libdrm。按前面提到的方法交叉编译安装libdrm。

第四类,链接期报undefined reference to mpp_destroy之类的错误。这类问题通常是sysroot里的librockchip_mpp.so和头文件版本不匹配。重新同步mpp的头文件和库,清理ffmpeg的编译缓存后重新编译。

5.4 make与安装

configure通过后,直接开编:

make -j$(nproc)

16核机器上基本几分钟完成。如果编译过程出现汇编错误,多半是--disable-x86asm没加,或者编译器版本和源码不兼容。检查configure参数后重新编译。

编译完成后安装:

sudo make install

这会往sysroot的$SYSROOT/usr/bin$SYSROOT/usr/lib里写入ffmpeg、ffprobe以及相关库。到这一步,sysroot里已经有一套能在RK3588上运行的ffmpeg。

6. 部署到开发板与硬件加速实测

6.1 文件拷贝和环境变量

把编译好的ffmpeg和动态库部署到开发板,建议放到/usr/local下,不覆盖系统自带的ffmpeg。需要拷贝的内容包括:

  • ffmpegffprobe两个可执行文件,放到板子的/usr/local/bin
  • librockchip_mpp.solibrockchip_mpp.so.0,放到/usr/local/lib
  • librga.solibrga.so.2,放到/usr/local/lib

如果你板子本身已经有librga,建议先备份,再决定是否替换。

然后设置动态库搜索路径:

echo 'export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc

不要小看这一步,很多人在板子上跑ffmpeg时报error while loading shared libraries,基本都是LD_LIBRARY_PATH没配置。

6.2 验证编译结果

在板子上执行:

ffmpeg -version

看一下“configuration”行,确认包含--enable-rkmpp --enable-rga --enable-libdrm

再执行:

ffmpeg -hwaccels

输出里有rkmpp,说明硬件加速框架已经被识别。接着查看可用的解码器和编码器:

ffmpeg -decoders | grep rkmpp ffmpeg -encoders | grep rkmpp

正常情况下能看到h264_rkmpphevc_rkmpp等条目。

6.3 硬件解码实测

以H.265为例,准备一段hevc编码的视频文件,执行:

ffmpeg -c:v hevc_rkmpp -i input.mp4 -f null -

这条命令会用VPU硬解hevc并直接丢帧输出。如果解码器工作正常,CPU占用会非常低,几乎可以忽略。如果出现Decoder (codec hevc) not found,说明ffmpeg没编译进对应的rkmpp解码器。如果提示Failed to set value 'hevc_rkmpp' for option 'c:v',说明编码器名称不对,用ffmpeg -decoders | grep rkmpp查一下实际支持的解码器。

H.264同理:

ffmpeg -c:v h264_rkmpp -i input.mp4 -f null -

对比一下软解和硬解的CPU占用率,差距会让你印象深刻。

6.4 硬件编码实测

编码时指定rkmpp编码器:

ffmpeg -i input.yuv -c:v h264_rkmpp -b:v 4M output.mp4

也可以直接从硬解转到硬编,全程不经过CPU做像素级处理:

ffmpeg -c:v hevc_rkmpp -i input.mp4 -c:v h264_rkmpp -b:v 4M output.mp4

这条命令是“硬解转硬编”的典型用法,RK3588上跑起来CPU占用率很低,转录一段1080p视频基本感觉不到CPU风扇在转。如果编码器对分辨率有严格限制,超过规格时可能报错,这时候需要查一下RK3588的硬件编码规格表,确认支持的分辨率和帧率范围。

6.5 RGA滤镜实测

RGA在ffmpeg里最常用的场景是做硬件缩放。比如把视频缩放到1280x720:

ffmpeg -c:v hevc_rkmpp -i input.mp4 -vf "scale_rga=1280:720" -f null -

如果ffmpeg里编译进了scale_rga,这条命令会走RGA硬件缩放,CPU占用几乎没有。如果提示No such filter: scale_rga,说明当前ffmpeg没有RGA滤镜。可以退而求其次用软缩放scale滤镜,但CPU开销会明显增加。

另外要注意,RGA滤镜处理的输入输出帧格式通常是NV12这类硬件友好的格式,如果输入是RGBA或者其他格式,可能需要先用format滤镜做一次转换,再交给scale_rga处理。具体格式支持列表可以参考RGA的文档,实测时多试几组就知道了。

7. 避坑清单与排查速查表

7.1 编译期问题速查表

现象原因解决方法
configure找不到rkmppsysroot缺mpp头文件/库,或PKG_CONFIG_PATH没设置重新编译安装mpp;导出PKG_CONFIG_PATH
configure找不到rgarga头文件路径未指定extra-cflags加-I$SYSROOT/usr/include/rga
configure找不到libdrmsysroot缺libdrm交叉编译最新libdrm并安装到sysroot
make时报unknown type name DRM_FORMAT_*libdrm头文件过旧升级libdrm版本
make时汇编语法错误未加--disable-x86asmconfigure加上--disable-x86asm
链接时报undefined reference to mpp_*mpp库和头文件版本不匹配同步mpp版本,清理后重新编译

这些编译期问题基本都在configure和make两个阶段爆发。configure阶段大多是依赖缺失,处理思路是补齐依赖而不是绕过选项;make阶段的汇编和链接错误通常跟编译器版本、架构配置有关,对照检查configure参数就能找到原因。

7.2 运行期问题速查表

现象原因解决方法
error while loading shared libraries动态库未拷贝或LD_LIBRARY_PATH未设置拷贝so文件;export LD_LIBRARY_PATH
Decoder (codec hevc) not foundffmpeg未包含rkmpp解码器重新编译开启--enable-rkmpp
Failed to set value for option c:v编码器名称不对或未支持用ffmpeg -encoders查看可用名字
RGA运行时报version mismatchlibrga和内核驱动版本不兼容用匹配板子BSP的librga版本
ffmpeg启动时提示drm设备打开失败用户无/dev/dri权限加入video组或使用sudo
硬编时分辨率超限超出RK3588编码规格降低分辨率或帧率

运行期的第一道坎是动态库加载,优先排查LD_LIBRARY_PATH。第二道坎是DRM设备权限,RK3588上的VPU和RGA依赖DRM节点,权限不足会报failed to open /dev/dri/renderD128之类的错误。把用户加入video组可以解决:

sudo usermod -aG video $USER

改完需要重新登录或重启生效。

7.3 个人心得

这套流程本身不复杂,真正花时间的是排错的过程。我在第一次整个编译部署过程中,前后栽了三次跟头,一次卡在libdrm缺失,一次卡在RGA版本不匹配,一次是忘了设LD_LIBRARY_PATH导致板子跑不起来。每次排查到最后,发现原因都很简单,但就是因为开始时没把环境准备好,导致后续一连串连锁反应。

如果你也是第一次搞RK3588的ffmpeg硬件加速,我的建议是先按步骤把依赖准备好,特别是sysroot里的libdrm和RGA版本,这两处最容易被忽略。运行期如果出了诡异的问题,先别急着改代码,确认是不是权限、环境变量或库版本不匹配导致的。把这些基础打牢,硬件加速带来的效果绝对物有所值。

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

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

立即咨询