RK平台从零编译FFmpeg:启用rkmpp硬解完整指南
发布时间:2026/10/21 9:54:44 锦皓数字建站

在RK3588、RK3568这类RK平台的板子上捣鼓音视频几乎绕不开FFmpeg。但我发现很多朋友第一步就直接apt install ffmpeg装完以为万事大吉结果一拉4K HEVC的流就卡成PPT或者多路RTSP同时解码时CPU直接飙到100%。问题基本都出在同一个地方发行版预编译的FFmpeg没有打开Rockchip的rkmpp硬解通道。这篇文章就记录一下我最近在RK平台从零编译FFmpeg的完整过程包括板端直编和交叉编译怎么选、依赖库怎么备、configure参数怎么给、编完怎么验证硬解真的生效以及我踩过的几个让人抓狂的坑。先说一下结论只要你想在RK设备上做正经的实时代码转换、多路解码或者边缘推理前的视频预处理自己编译带rkmpp的FFmpeg基本是绕不过去的一步。这个工作本身不复杂但牵扯到mpp库、libdrm、工具链、内核设备节点几层东西哪一环没对上都会出幺蛾子。我尽量把关键点都讲透附带可以直接复制的命令。1. RK平台为什么非要自己编FFmpeg1.1 预编译包缺的不只是一个开关很多发行版里的FFmpeg编译时压根没有检测到Rockchip的MPP库。你可以试一下在板子上跑ffmpeg -hwaccels大概率输出里只有vdpau、vaapi这些x86上常见的东西ARM板上一个都没有。更别提ffmpeg -decoders | grep rkmpp这个命令正常情况下什么都查不到。这时候就算你强行在命令行里写-hwaccel rkmpp -c:v hevc_rkmppFFmpeg也会直接甩你一句Unknown decoder hevc_rkmpp原因就是编译时没有开启对应的decoder和hwaccel。ARM平台不是不用硬解是压根没把硬解能力编进二进制里。另一个容易被忽略的问题是版本。很多板卡自带的Ubuntu/Debian源里FFmpeg版本停留在老旧的4.x甚至3.x。老版本对RK新一代VPU的支持很残缺比如RK3588上的VP9解码、H.265 4K 60fps硬解在老版本上要么不支持要么有严重的兼容Bug。与其去官方源等更新不如自己编一份干净的。1.2 两条路线板端直编 vs 交叉编译在RK平台上编译FFmpeg通常有两种做法对比项板端直接编译主机交叉编译适用场景板子性能够、改配置频率低板子性能弱、批量出固件、需要反复调参速度慢取决于板子CPU快但前期要配工具链和sysroot编译依赖板端包管理器装依赖简单依赖库也要交叉编译稍麻烦产物控制直接装进系统路径可以精确控制安装目录便于打包踩坑难度较低出错直观较高环境变量和pkg-config问题多如果板子是RK3588这种8核A76A55的机器内存8G以上直接在板子上编也完全可以接受。我第一次编大概花了不到二十分钟。但如果你用的是RK3308这种弱鸡或者要做量产镜像还是老老实实用交叉编译。我个人比较习惯的流程是开发调试阶段在板端直编快速验证功能确认方案没问题后再到主机上交叉编译出一份干净的可发布版本。这样兼顾了调试效率和最终交付质量。2. 编译环境的搭建与依赖整理2.1 工具链版本怎么选板端直编的话工具链就是板子自带的gcc一般不用操心。唯一要注意的是老版本rootfs里的gcc可能比较旧编FFmpeg 6.x以上的版本时偶发语法兼容问题如果碰到诡异报错优先考虑升级gcc。交叉编译的话主机上装一个通用的aarch64工具链就行sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu binutils-aarch64-linux-gnu我建议用系统包管理器里的工具链而不是自己从Linaro下载。原因很简单系统包管理的工具链和你主机上的其它工具pkg-config、autoconf配合更顺畅版本也不会太激进。曾经有朋友图新鲜下了个非常新的工具链结果编译时头文件里多了几个新定义反而不兼容老内核的根文件系统折腾了半天。如果你要编的是带NEON优化的ARMv7版本比如RK3288的32位系统工具链则换成arm-linux-gnueabihf-前缀编译参数里把--arch改成armv7-a。现在绝大多数新板子都是64位下面我以aarch64为例。2.2 依赖库清单FFmpeg的rkmpp硬解核心依赖是下面几样rockchip-mppRockchip媒体处理平台库。硬解、硬编的底层API全在这里面FFmpeg通过rkmpp模块调用它。libdrm显示直接渲染管理器。Rockchip的硬解帧不落地直接放到DRM的buffer里后续可以零拷贝送到显示控制器也方便和DRM的其它模块配合。yasm/nasm汇编器FFmpeg编译x86优化代码时需要。ARM平台上其实用不到x86asm但有些老版本configure还没完全理顺装上一个可以避免莫名其妙的报错。pkg-config、make、cmake构建基础工具。mpp库我直接用GitHub上游的git clone https://github.com/rockchip-linux/mpp.git cd mpp mkdir build cd build cmake .. -DCMAKE_INSTALL_PREFIX/opt/rk-mpp -DCMAKE_BUILD_TYPERelease make -j$(nproc) make installlibdrm同样git clone https://github.com/rockchip-linux/libdrm.git cd libdrm sudo apt install autoconf libtool pkg-config ./autogen.sh --prefix/opt/rk-drm --hostaarch64-linux-gnu make -j$(nproc) make install注意交叉编译时--hostaarch64-linux-gnu必须给对否则默认会按x86编译装到板子上直接运行不了。2.3 环境变量pkg-config和sysroot的坑无论板端直编还是交叉编译FFmpeg的configure脚本寻找依赖库时靠的全是pkg-config。如果你把mpp和libdrm装到了自定义目录必须让pkg-config能找到它们export PKG_CONFIG_PATH/opt/rk-mpp/lib/pkgconfig:/opt/rk-drm/lib/pkgconfig交叉编译时还有一个更隐蔽的坑如果libdrm和mpp的.pc文件里写死了prefix/usr/local默认值而你的sysroot里并没有这些库pkg-config报出来的路径会指向主机上的/usr/local。这时要用export PKG_CONFIG_SYSROOT_DIR/path/to/sysroot export PKG_CONFIG_LIBDIR/opt/rk-drm/lib/pkgconfig:/opt/rk-mpp/lib/pkgconfigPKG_CONFIG_LIBDIR要指向sysroot内实际的.pc文件路径PKG_CONFIG_SYSROOT_DIR负责把路径整体重定向到目标文件系统。这个配置不弄对configure阶段要么报找不到库要么找到了x86的库导致链接报错。我在这上面至少浪费过两个小时所以建议你在交叉编译前用下面这条命令先确认一下pkg-config --exists libdrm echo OK || echo MISSING确认完再进configure能省掉一轮排查。3. 核心configure配置逐项解析3.1 rkmpp到底对应哪些开关FFmpeg对Rockchip硬解的支持集中在几个配置项上--enable-rkmpp主开关启用Rockchip MPP封装层。--enable-libdrm启用DRM帧缓冲管理。--enable-hwaccelh264_rkmpp/hevc_rkmpp/vp8_rkmpp/vp9_rkmpp/mpeg2_rkmpp分别打开对应编码格式的硬解加速。--enable-version3启用某些协议/库的第三方许可证mpp模块用得上。--enable-cross-compile交叉编译时必须加。如果你只是想解码上面这些足够了。如果要硬编码RK3588/3576这些新平台的VEU单元还支持H.264/H.265编码对应的是h264_rkmpp和hevc_rkmpp的编码器部分。编码这块后面我单独说。3.2 一条可以落地的configure命令板端直编依赖都装好后按下面这个配置来cd ffmpeg-src ./configure \ --prefix/usr/local/ffmpeg \ --enable-shared \ --disable-static \ --enable-rkmpp \ --enable-libdrm \ --enable-version3 \ --enable-nonfree \ --enable-hwaccelh264_rkmpp \ --enable-hwaccelhevc_rkmpp \ --enable-hwaccelvp8_rkmpp \ --enable-hwaccelvp9_rkmpp \ --enable-hwaccelmpeg2_rkmpp \ --enable-encoderh264_rkmpp \ --enable-encoderhevc_rkmpp \ --disable-x86asm make -j$(nproc) make install交叉编译时configure命令改成./configure \ --prefix/usr/local/ffmpeg \ --archaarch64 \ --target-oslinux \ --cross-prefixaarch64-linux-gnu- \ --enable-cross-compile \ --enable-rkmpp \ --enable-libdrm \ --enable-version3 \ --enable-nonfree \ --enable-hwaccelh264_rkmpp \ --enable-hwaccelhevc_rkmpp \ --enable-hwaccelvp8_rkmpp \ --enable-hwaccelvp9_rkmpp \ --enable-hwaccelmpeg2_rkmpp \ --enable-encoderh264_rkmpp \ --enable-encoderhevc_rkmpp \ --enable-shared \ --disable-static \ --disable-x86asm \ --extra-cflags-I/opt/rk-drm/include -I/opt/rk-mpp/include \ --extra-ldflags-L/opt/rk-drm/lib -L/opt/rk-mpp/lib -Wl,-rpath-link这里--enable-nonfree要不要加取决于你编译的组件里是否包含特殊协议。如果只是纯硬解解码可以直接去掉不干扰mpp链路但如果想安心加上不会影响编译通过。3.3 configure阶段常见的检查点跑完configure强烈建议回头看一眼输出信息特别是这几行... h264_rkmpp yes ... hevc_rkmpp yes ... rkmpp yes ... libdrm yes只要上面出现任何一个no就不要往下make了先回头查依赖。有一次我configure时看到rkmpp no排查半天发现是PKG_CONFIG_PATH没写对把mpp.pc的路径指成了libdrm的路径。这种低级错误花十分钟确认环境变量绝对值得。另外交叉编译时如果提示ERROR: libdrm not found大概率不是真的没装而是pkg-config里PKG_CONFIG_LIBDIR或PKG_CONFIG_SYSROOT_DIR的问题。如果提示和汇编器相关nasm/yasm not found or version too old就sudo apt install nasm yasm装上然后加--disable-x86asm就算了ARM平台不依赖这个。4. 编译、安装与板上硬解验证4.1 板端直编的编译过程与提速技巧板子上执行make -j$(nproc)FFmpeg本体编译量不小。RK3588这种机器还好十几分钟能跑完如果是RK3568大概要半个多小时。如果板子内存只有4G直接-j8编FFmpeg很容易OOM我建议make -j2或者手动加swap。我试过在4G内存的老板子上创建一个2G的swap文件编译速度提升明显sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile编译过程中如果CPU温度上升太快注意散热我遇到过编译到一半温度过高导致整机重启的情况。这种重跑一遍非常折磨人建议编译时用htop盯一下温度。4.2 交叉编译产物部署到板子交叉编译完成后把产物放到板子上。比较简单的做法是整个目录打包带过去cd /usr/local tar czf ffmpeg-rk.tar.gz ffmpeg/在板子上解压到对应路径tar xzf ffmpeg-rk.tar.gz -C /usr/local然后通知动态链接器找到新库echo /usr/local/ffmpeg/lib /etc/ld.so.conf.d/ffmpeg-rk.conf ldconfig这里有个需要注意的点如果你在主机上编译时用了-Wl,-rpath-link板子上运行还要确保librkmpp.so、libdrm.so也在库路径里。mpp的动态库一般装到/usr/local/lib或者你自己指定的目录在板子上同样要加到ld.so.conf。否则运行时会报error while loading shared libraries: librkmpp.so: cannot open shared object file4.3 怎么判断硬解真的生效了装好后第一件事确认FFmpeg能看到我们编进去的模块ffmpeg -hwaccels ffmpeg -decoders | grep rkmpp ffmpeg -encoders | grep rkmpp正常情况下会看到h264_rkmpp、hevc_rkmpp、vp8_rkmpp、vp9_rkmpp等解码器名称以及h264_rkmpp、hevc_rkmpp编码器。接下来拿一个真实的HEVC文件或者RTSP流去测ffmpeg -hwaccel rkmpp -c:v hevc_rkmpp -i input.hevc -f null -如果输出正常并且CPU占用率明显低于软解软解1080P HEVC可能占用2-3个核心硬解基本压在10%以下说明硬解链路已经通了。有显示输出的板子还可以直接投到DRM平面ffmpeg -hwaccel rkmpp -c:v hevc_rkmpp -i input.hevc -f framebuffer -pixel_format bgra -s 1920x1080 /dev/fb0能看到画面基本就稳了。这一步我建议还是做一下因为有些板子的DRM/内核配置有问题FFmpeg即使解码成功显示链路上还会出错。5. 常见故障排查实录5.1 configure通过编译却报mpp符号未定义我遇到过一种情况configure阶段一切正常但make时编译器报undefined reference to mpp_create这是典型的新老版本混用问题。要么是FFmpeg版本太老用的是旧的mpp API要么是mpp库版本太新把老接口废弃了。我建议FFmpeg直接用最新release分支6.x、7.x。mpp源码用release tag不要追master。如果板卡厂商给了BSP SDK优先用SDK里配套的mpp版本比GitHub上游更匹配内核驱动。内核里的mpp驱动和用户态的mpp库是一套系统两边版本差太远轻则功能不全重则直接运行崩溃。很多问题不是编译错误而是运行时报错排查起来更费劲。5.2 运行时提示找不到设备节点解码器编出来了但运行时提示mpp_mem_setup failed /dev/mpp_service: No such file or directory这说明内核驱动没有加载或者设备节点没创建。老内核RK3399、RK3288时代通常有/dev/mpp_service节点新内核RK3568、RK3588的5.10已经切换到V4L2的m2m节点FFmpeg的rkmpp模块会自动适配。如果节点不存在ls /dev/dri/renderD* /dev/mpp_service /dev/video* 2/dev/null看到什么都没有就去查内核配置和DTS确认VPU在设备树里使能了。同时确认板子上的media用户组自己是否有权限访问sudo usermod -aG video $USER有些运行在docker里的场景还要额外传--device/dev/mpp_service和--device/dev/dri否则容器里面同样找不到节点。5.3 CMA内存不足导致解码失败硬解需要连续物理内存RK平台用CMA来预留。跑大分辨率或多路并发时如果出现mpp_create_frame failed或者画面花花绿绿、一闪一闪先查CMAcat /proc/meminfo | grep CmaCmaFree如果只剩几十MB4K 60fps硬解很容易失败。此时有两条路一是改内核cmdline增大CMA预留例如video_mem64M或者修改内核配置里的CONFIG_CMA_SIZE_MBYTES重新编内核二是减少并发路数分批处理。真实项目中我推荐先用指令限制解码帧数做低负载测试确认CMA不是瓶颈后再逐步加压。5.4 解码格式用不了有些格式虽然硬件支持但在FFmpeg里没有对应的rkmpp解码器。比如老的MPEG2、VC1很多新板卡的VPU已经不支持了这时FFmpeg会自动回退到软解。如果你在命令行里强制用-c:v mpeg2_rkmpp会直接报错说没这个解码器。这属于正常现象不是编译问题。另外部分老版本FFmpeg对VP8/VP9的rkmpp支持是后来加的如果你用的是4.2之前的老版本装上也可能不识别。建议统一用新版本。5.5 视频画面时间和实际对不上排查到这一步通常硬解已经正常了。你会发现FFmpeg输出的时间戳偶尔跳变。原因多半是输入流的B帧处理顺序和mpp解帧顺序不一致。我的经验是ffmpeg -fflags genpts -hwaccel rkmpp -c:v hevc_rkmpp -i input.hevc -f null -加上genpts强制生成完整时间戳能缓解大部分跳变问题。如果是直播流还建议加上-use_wallclock_as_timestamps 1实测下来RTSP拉流的时间戳稳定很多。最后说一个我这几次操作下来最大的体会编译FFmpeg本身不复杂真正折磨人的永远是库和内核、工具链和rootfs之间的版本匹配。把所有依赖版本锁定在同一个时候点按顺序从mpp、libdrm、FFmpeg依次编译大部分坑都能提前避开。另外强烈建议在板子上保留一套编译好的mpp静态库和头文件后续编GStreamer插件、OpenCV或者其它音视频库时都能直接复用。这个小习惯能省下不少重复劳动。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。