免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

RK3588交叉编译FFmpeg:启用RKMPP与RGA硬件加速实践

RK3588交叉编译FFmpeg:启用RKMPP与RGA硬件加速实践 先交代一下背景如果你手里正好有一块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的FFmpeg1.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。它封装了MPIMedia Process Interface负责和VPU交互完成H.264、H.265、VP9、AV1等视频的硬件编解码。在ffmpeg里它表现为以_rkmpp结尾的编解码器比如h264_rkmpp、hevc_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/lostfound \ / user192.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_TYPERelease make -j$(nproc)这里解释一下-DCMAKE_INSTALL_PREFIX$SYSROOT/usr的含义编译出来的头文件和库会安装到sysroot里后续ffmpeg的configure在sysroot内搜索依赖时就能直接找到rockchip/mpp_*.h和librockchip_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.h、mpp_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.cmakeset(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.sorga.h和librga.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 \ --archaarch64 \ --target-oslinux \ --enable-cross-compile \ --cross-prefixaarch64-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-libdrmmpp依赖drm接口这个不开启ffmpeg的hwdevice初始化会失败。--sysroot指定目标板的根文件系统目录configure和后续编译都会在这个环境下搜索头文件和链接库。--cross-prefix交叉编译器的前缀ffmpeg会在后面自动拼接gcc、ld等命令。--disable-x86asmaarch64下不需要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。需要拷贝的内容包括ffmpeg和ffprobe两个可执行文件放到板子的/usr/local/binlibrockchip_mpp.so和librockchip_mpp.so.0放到/usr/local/liblibrga.so和librga.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_rkmpp、hevc_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里最常用的场景是做硬件缩放。比如把视频缩放到1280x720ffmpeg -c:v hevc_rkmpp -i input.mp4 -vf scale_rga1280: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_PATHconfigure找不到rgarga头文件路径未指定extra-cflags加-I$SYSROOT/usr/include/rgaconfigure找不到libdrmsysroot缺libdrm交叉编译最新libdrm并安装到sysrootmake时报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_PATHDecoder (codec hevc) not foundffmpeg未包含rkmpp解码器重新编译开启--enable-rkmppFailed 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版本这两处最容易被忽略。运行期如果出了诡异的问题先别急着改代码确认是不是权限、环境变量或库版本不匹配导致的。把这些基础打牢硬件加速带来的效果绝对物有所值。
返回列表