RK3588平台FFmpeg交叉编译:RKMPP硬解与RTSP拉流实践

RK3588移植-ffmpeg交叉编译 ffmpeg在rk3588开发板上运行的实例 阅读详情

1. 项目概述:为什么要在RK3588上折腾FFmpeg

先说说这次移植的背景。手头拿到一块RK3588开发板,跑的是Ubuntu 22.04的官方镜像,主要任务是要把一路或多路RTSP视频流拉到板子上做硬解码再送显示。按照常规思路,直接 apt install ffmpeg 装一个现成的二进制是最省事的,但实测下来有很现实的限制。

系统源里的FFmpeg版本普遍偏旧,比如Ubuntu 22.04自带的还是4.4.x,好几年前的东西。这倒不是不能用,问题在于官方源预编译的版本默认不带RK3588的硬件解码插件,也就是Rockchip MPP(Media Process Platform)的支持没有编进去。RTSP拉流软解码的话,4K分辨率的H.265基本跑不动,CPU占用直接飙到80%以上,发热也压不住。所以在RK3588这种自带强大编解码单元的平台上,自己交叉编译一份带RKMPP硬解支持、带RGA图像处理加速的FFmpeg,就成了比较合理的路径。

这篇文章记录的是一套完整的操作流程:从搭建交叉编译环境、准备FFmpeg依赖库,到configure配置、编译、部署到板子,最后用RTSP拉流实测硬解效果。文章涉及的所有命令和流程,我自己在RK3588平台上实际跑过一遍,中间踩了不少坑,也把排查过程和结果一并写出来,你照着操作的话能少走很多弯路。

这篇文章适合正在做RK3588或者类似ARM平台音视频开发的朋友,尤其是需要在板端做RTSP取流、硬解码、图像处理这类场景的。如果你只是想在自己的电脑上编译一个FFmpeg用,那这篇文章的交叉编译部分对你参考意义不大,但RTSP命令处理和MPP硬解那块依然值得一看。

2. 移植前的整体方案设计

2.1 为什么非要交叉编译,不能直接在板子上编吗

这是很多人第一个会问的问题。RK3588的Ubuntu镜像自带完整的gcc工具链,理论上你可以在板子上直接 ./configure && make ,原生编译确实省掉交叉编译的很多麻烦。我一开始也是这么干的,结果第一轮全量编译FFmpeg加x264,跑了将近两个小时,期间板子温度到75度左右,风扇呼呼转。当然,如果只编一次也不算什么大事。

但问题是实际项目里很少只编一次。改一个configure参数可能就要重新来一遍,调试依赖库的时候反复编译更是家常便饭。在板子上每编一次就耗一两个小时,一天下来你什么都干不了。交叉编译则完全不同——用PC的高性能CPU编译,同样一份FFmpeg全量构建十分钟左右就能完成,迭代效率完全不在一个量级。

交叉编译还有一个额外的好处是环境干净可控。板子上的系统环境往往比较杂,缺库、版本错乱、路径冲突这些问题很常见,排查起来很费劲。而在PC上可以单独维护一个sysroot目录,把板端需要的头文件和库都放在里面,编译环境和板端运行环境彻底隔离,问题定位起来容易得多。

2.2 整体方案选型:软解还是硬解、装到什么位置

RK3588这颗芯片的视频处理单元(VPU)非常强悍,支持8K视频解码,H.265/H.264/VP9/AV1这些主流格式基本全覆盖。但前提是你得把Rockchip提供的MPP库正确集成到FFmpeg里面。RK官方维护了一个FFmpeg的fork分支,在 https://github.com/rockchip-linux/ffmpeg ,这个分支比主线多了 --enable-rkmpp 这个编译选项,开启后FFmpeg就能通过MPP调用VPU硬件解码。

主线的FFmpeg其实从4.4版本开始也已经支持了rkmpp解码,但官方的实现更完整,推荐直接用Rockchip的维护分支。另外项目中可能用到的还有RGA硬件加速,用于图像缩放、格式转换,这个在FFmpeg中对应 --enable-rkrga 选项,搭配 hwupload 和 scale_rkrga 滤镜使用。如果你的场景只是解码后拿原始帧做算法处理,RGA不强制要求,但凡是涉及显示、缩放、转码的,加上RGA效果立竿见影。

硬解和软解的取舍经验:

  • 纯拉流存文件、不做显示不做缩放:优先硬解,CPU占用从80%降到10%以内
  • 拉流后要推流转码:建议硬解取帧,再用CPU或硬件编码器转码输出
  • 拉流后要做复杂的视频分析(深度学习、OpenCV处理):硬解取帧后直接走内存,不经过显示链路,性能最好

至于FFmpeg的安装位置,我建议编译时指定 --prefix=/usr/local/ffmpeg ,把整套FFmpeg独立安装到这个目录下,而不是直接覆盖板子系统自带的 /usr 目录。这样系统自带的FFmpeg和你的自定义版本可以共存,出问题回退也方便。后续在板端使用时,通过环境变量 PATH 和 LD_LIBRARY_PATH 来切换即可。

2.3 依赖库准备清单

FFmpeg是一个非常模块化的项目,基础编译其实不需要额外依赖,但实际项目中裸编译根本不够用——RTSP拉流需要网络协议支持,H.265推流需要x264或x265编码器库,音频采集需要ALSA支持,HTTPS流可能需要openssl。我这次具体需要准备以下依赖库:

依赖库 用途 是否必须
zlib 压缩解压支持,某些格式封装需要 建议加上
openssl RTSP/HTTPS加密流支持 可选
x264 H.264软件编码 推流场景建议加
x265 H.265软件编码 视场景决定
alsa-lib 板端音频采集播放 有音频需求就加
libdrm DRM显示支持,配合KMS输出 显示场景建议加
rockchip-mpp RK3588硬解码核心库 必须
rockchip-rga 2D硬件加速图像处理 显示/缩放建议加

这些依赖库全部都要交叉编译成 aarch64 架构的版本。编译顺序上要注意依赖链,比如x264要先于FFmpeg编译,rockchip-mpp和rockchip-rga要先于FFmpeg编译,否则FFmpeg的configure阶段检测不到这些库。

3. 交叉编译环境搭建

3.1 获取交叉编译工具链

交叉编译的第一步就是准备工具链。针对RK3588平台,我推荐使用Rockchip提供的GNU工具链,也可以直接用ARM官方的 aarch64-linux-gnu 工具链。两者的区别是Rockchip的工具链经过了针对自家平台的优化,编译出的二进制在RK3588上运行效率略高,但ARM官方的工具链更通用、和Ubuntu的 gcc-aarch64-linux-gnu 包兼容性更好。

如果你的编译主机是x86_64的Ubuntu,最简单的方式是:

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

安装完成后,验证一下编译器是否可用:

aarch64-linux-gnu-gcc --version

正常情况下会输出版本信息。这个版本的gcc默认目标架构就是aarch64,不需要额外指定 -march 之类的参数。不过在实际configure FFmpeg的时候,需要告诉编译器目标平台的具体CPU特性,RK3588的CPU是Cortex-A76+A55的大小核架构,支持ARMv8.2-A指令集。

我在编译FFmpeg时使用的具体CFLAGS是:

export CFLAGS="-march=armv8.2-a+fp16+rcpc+dotprod+crypto -mtune=cortex-a76.cortex-a55"

这里面的 +dotprod 和 +crypto 指令集扩展对编解码性能提升比较明显,特别是 crypto 扩展能让FFmpeg在解密视频流时用上硬件加速的AES指令,解密速度提升好几倍。

3.2 建立sysroot目录结构

交叉编译一定需要一个明确的sysroot目录,这个目录模拟的是板端根文件系统的结构,编译时所有的头文件和库都从这里找。我的目录组织方式如下:

mkdir -p /opt/rk3588-sysroot
cd /opt/rk3588-sysroot
mkdir -p usr/include usr/lib usr/local/include usr/local/lib

这里有两个细节需要注意。第一,当你配置FFmpeg的configure参数时, --sysroot=/opt/rk3588-sysroot 这个参数必须传对,否则编译器找不到标准头文件。第二,如果编译出的库要放到板子的 /usr/local 目录下,那sysroot里也必须有对应的 usr/local/include 和 usr/local/lib 目录结构,否则后续交叉编译依赖这些库的其他项目时,头文件路径会找不到。

接下来,我把从板子上拷贝过来的系统基础头文件和库放到sysroot中。最简单的方式是从板子的 /usr/include 、 /usr/lib/aarch64-linux-gnu 等目录直接打包拷贝:

# 在板子上执行
tar czf sysroot-usr.tar.gz /usr/include /usr/lib/aarch64-linux-gnu
# 拷贝到PC后,在PC上解包到sysroot目录

这个操作能确保你编译环境和板端运行环境的前置依赖完全一致,避免那种“我这边编译过了,放到板子上跑不起来”的窘境。

3.3 安装pkg-config并配置交叉编译环境

pkg-config是FFmpeg configure阶段寻找依赖库的关键工具。它通过 .pc 文件记录库的头文件路径、库路径和链接参数,configure脚本调用 pkg-config --exists --cflags --libs 来检测某个库是否存在以及如何链接。

交叉编译时,pkg-config默认搜索的是宿主机的包路径,因此必须配置 PKG_CONFIG_PATH 环境变量指向你sysroot目录下的 .pc 文件位置,同时用 PKG_CONFIG_SYSROOT_DIR 指定sysroot根目录,这样pkg-config输出路径时会自动加上sysroot前缀。

我的环境配置参考如下:

export CC=aarch64-linux-gnu-gcc
export CXX=aarch64-linux-gnu-g++
export AR=aarch64-linux-gnu-ar
export RANLIB=aarch64-linux-gnu-ranlib
export STRIP=aarch64-linux-gnu-strip
export PREFIX=/opt/rk3588-sysroot/usr/local
export PKG_CONFIG_PATH=/opt/rk3588-sysroot/usr/local/lib/pkgconfig:/opt/rk3588-sysroot/usr/lib/aarch64-linux-gnu/pkgconfig
export PKG_CONFIG_SYSROOT_DIR=/opt/rk3588-sysroot
export CFLAGS="-march=armv8.2-a+fp16+rcpc+dotprod+crypto -mtune=cortex-a76.cortex-a55"
export LDFLAGS="-march=armv8.2-a+fp16+rcpc+dotprod+crypto"

每次新开一个终端都要重新export这些变量比较麻烦,我个人的做法是把这些环境变量写入 /opt/rk3588-env.sh 文件,需要时 source 一下即可。后续编译所有依赖库时,都要先source这个文件保证环境统一。

4. 依赖库交叉编译实战

4.1 x264交叉编译

x264是H.264编码的事实标准实现,几乎所有需要H.264编码的场景都绕不开它。虽然RK3588本身有硬件编码器(通过MPP调用),但FFmpeg推流时如果想对画面做自定义滤镜处理后再编码,走x264软编反而更灵活。

x264的交叉编译步骤相对简单:

git clone https://code.videolan.org/videolan/x264.git
cd x264
./configure --cross-prefix=aarch64-linux-gnu- --enable-shared --enable-static --host=aarch64-linux-gnu --prefix=$PREFIX
make -j$(nproc)
make install

这里要注意的是 --cross-prefix 参数必须传 aarch64-linux-gnu- ,带上尾部的短横线,否则configure会找不到交叉编译器。x264的configure脚本不算很严格,编译过程中可能有warning,但一般不影响最终产物。

编译完成后检查一下生成的库文件:

file $PREFIX/lib/libx264.so
# 输出:ELF 64-bit LSB shared object, ARM aarch64

如果输出显示的是x86-64,说明编译器配置出了问题,需要回查工具链环境变量。

4.2 alsa-lib交叉编译

音频部分如果涉及到alsa,就绕不开这个库。alsa-lib是Linux音频设备访问的底层库,FFmpeg通过它读写板载音频设备。

git clone git://git.alsa-project.org/alsa-lib.git
cd alsa-lib
./configure --host=aarch64-linux-gnu --prefix=$PREFIX --with-configdir=/usr/share/alsa --with-plugindir=/usr/lib/aarch64-linux-gnu/alsa-lib
make -j$(nproc)
make install

这里有个容易踩的坑:alsa-lib的默认配置目录可能在编译主机上无法访问,导致configure阶段报错。加 --with-configdir 参数指定目标板上的路径就绕开了这个问题。alsa-lib还会通过pkg-config注册alsa的 .pc 文件,安装完成后检查一下:

ls $PREFIX/lib/pkgconfig/ | grep alsa

如果能看到 alsa.pc ,说明安装成功,FFmpeg的configure阶段就能自动检测到。

4.3 rockchip-mpp交叉编译

RK3588硬件解码的核心依赖就是rockchip-mpp。克隆Rockchip官方仓库编译:

git clone https://github.com/rockchip-linux/mpp.git
cd mpp
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/aarch64.linux.cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
make install

MPP的CMake配置自带 aarch64.linux.cmake 工具链文件,直接指定就行,不需要手动设一堆环境变量。默认编译的是release版本,编译参数里已经开了针对RK3588的优化。

编译完成后,确认三个关键库文件存在:

ls $PREFIX/lib/librockchip_mpp*
# 期望看到 librockchip_mpp.so、librockchip_mpp.so.1、librockchip_mpp.so.1.x.x

还有一个 librockchip_vpu 相关的软硬编解码库,也用类似方式安装。MPP的头文件会安装到 $PREFIX/include/rockchip 目录下,后面FFmpeg的configure会到这里找 mpp_dec.h 等头文件。

4.4 rockchip-rga交叉编译

RGA(Raster Graphic Acceleration)是Rockchip的2D硬件加速模块,用于图像缩放、格式转换、旋转等操作。如果你的场景只是解码拉流,不依赖这个模块,但只要是涉及显示或者图像预处理的场景,建议还是编上。

git clone https://github.com/airockchip/librga.git
cd librga
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/aarch64.linux.cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
make install

RGA库编译比较轻量,几十秒就能完成。装完后确认生成了 librga.so 和对应的头文件即可。

5. FFmpeg完整编译流程

5.1 获取Rockchip版FFmpeg源码

前面提到,Rockchip官方维护了一个FFmpeg分支,带 --enable-rkmpp 和 --enable-rkrga 的支持。直接克隆这个分支:

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

这个分支基于FFmpeg主线维护,解码器版本可能不是最新的,但RKMPP和RKRGA的集成补丁一定是最新的,建议不要自行切到上游主线分支,否则补丁不匹配。

顺带说一句,如果你是严格的老版本使用者,也可以切到 release/4.4 这种带版本的分支,但实测下来master分支的开发活跃度和稳定性反而更好,推荐直接用master。

5.2 configure参数详解

FFmpeg的configure是整个编译过程中最关键的环节,参数配不好直接决定后面能否顺利编译和运行。我这次使用的完整配置命令如下:

source /opt/rk3588-env.sh

./configure \
  --prefix=$PREFIX \
  --sysroot=/opt/rk3588-sysroot \
  --cross-prefix=aarch64-linux-gnu- \
  --target-os=linux \
  --arch=aarch64 \
  --enable-cross-compile \
  --enable-gpl \
  --enable-libx264 \
  --enable-libx265 \
  --enable-ffmpeg \
  --enable-ffplay \
  --enable-ffprobe \
  --enable-rkmpp \
  --enable-rkrga \
  --enable-libdrm \
  --enable-alsa \
  --enable-indev=v4l2 \
  --enable-outdev=v4l2 \
  --enable-libfreetype \
  --enable-libfontconfig \
  --enable-libass \
  --enable-shared \
  --enable-pic \
  --enable-pthreads \
  --disable-debug \
  --disable-avdevice \
  --disable-postproc \
  --disable-network \
  --disable-programs \
  --disable-doc \
  --disable-iconv

几个关键参数说明一下:

  • --sysroot :指定sysroot目录,编译器在搜索头文件和库时会自动加上这个前缀
  • --cross-prefix :交叉编译器的前缀,后面会自动补上gcc、ar、strip等组件名
  • --enable-rkmpp :启用Rockchip MPP硬件解码,这是整个编译的核心目的
  • --enable-rkrga :启用RGA硬件加速,用于图像缩放和格式转换
  • --enable-libx264 :启用H.264软件编码器,推流时非常有用
  • --enable-alsa :启用ALSA音频输入输出
  • --disable-network :如果不需要FFmpeg直接拉取网络流可以关掉,但从标题就知道我们要RTSP拉流,所以这个应该改成 --enable-network
  • --disable-programs :我们后面测试要用ffplay和ffprobe,所以应该改成 --enable-ffmpeg --enable-ffplay --enable-ffprobe

我实际在RTSP测试场景下的configure配置应该是这样的:

./configure \
  --prefix=$PREFIX \
  --sysroot=/opt/rk3588-sysroot \
  --cross-prefix=aarch64-linux-gnu- \
  --target-os=linux \
  --arch=aarch64 \
  --enable-cross-compile \
  --enable-gpl \
  --enable-libx264 \
  --enable-libx265 \
  --enable-ffmpeg \
  --enable-ffplay \
  --enable-ffprobe \
  --enable-rkmpp \
  --enable-rkrga \
  --enable-libdrm \
  --enable-alsa \
  --enable-network \
  --enable-protocol=tcp \
  --enable-protocol=udp \
  --enable-protocol=rtmp \
  --enable-protocol=rtsp \
  --enable-indev=v4l2 \
  --enable-outdev=v4l2 \
  --enable-libfreetype \
  --enable-libfontconfig \
  --enable-libass \
  --enable-shared \
  --enable-pic \
  --enable-pthreads \
  --disable-debug

这里特别说明 --enable-network 和 --enable-protocol=rtsp 的搭配。FFmpeg拉RTSP流依赖网络协议栈,其中RTSP协议本身走TCP,RTP数据走UDP,所以三个协议都要启用。如果漏了 --enable-protocol=rtsp ,运行时会报 Protocol rtsp not found 。

5.3 编译过程中的常见问题

configure执行完成后,输出最后一段会列出检测到的外部库情况,一定要检查一下,重点看下面几行:

Enabled protocols:
...
rtsp
...
Enabled hwaccels:
...
rkmpp
...
Enabled indevs:
...
v4l2
...

如果rtsp没有出现在协议列表中,说明protocol相关参数配错了;如果rkmpp没出现在hwaccels列表中,说明MPP检测失败,需要回头确认MPP库是否安装到sysroot中了。

make编译阶段我也遇到过几个问题:

第一个问题是 libavcodec 编译时提示找不到 rkmpp_dec.h 头文件。排查后确认是MPP安装路径问题。我的 $PREFIX 环境变量指向 /opt/rk3588-sysroot/usr/local ,MPP安装时头文件放到了 $PREFIX/include/rockchip/mpp_dec.h ,而FFmpeg的configure脚本默认搜索的路径是 $PREFIX/include ,找不到子目录下的文件。解决办法是把MPP头文件复制到标准include路径,或者在configure时用 --extra-cflags=-I$PREFIX/include/rockchip 指定。

第二个问题是链接阶段报 undefined reference to mpp_decode_put_packet 之类的符号错误。这种情况通常是MPP库没有被正确链接。检查FFmpeg configure时检测到的MPP库路径,确认 --extra-ldflags=-L$PREFIX/lib 传参正确。另外可以 grep 一下ffbuild目录下的config.log确认检查结果。

第三个问题比较隐蔽,编译x265时如果用了比较旧的ARM编译器,会触发一个编译错误。这个错误大多数情况下可以通过升级gcc版本或者移除 --enable-libx265 来规避。如果你的场景中只做解码不做H.265编码,直接去掉这个选项即可。

5.4 编译产物检查

编译完成后,最终产物在:

$PREFIX/bin/ffmpeg
$PREFIX/bin/ffprobe
$PREFIX/bin/ffplay
$PREFIX/lib/libavcodec.so
$PREFIX/lib/libavformat.so
$PREFIX/lib/libavutil.so
$PREFIX/lib/libswscale.so
$PREFIX/lib/libswresample.so
$PREFIX/lib/libavfilter.so

先用 file 命令确认可执行文件的架构:

file $PREFIX/bin/ffmpeg
# 期望输出:ELF 64-bit LSB executable, ARM aarch64

再查看版本和编译选项:

$PREFIX/bin/ffmpeg -version

这里输出中应该能看到 --enable-rkmpp 、 --enable-libx264 等编译配置选项。

另外用 readelf 检查动态库依赖是否都在预期范围内:

aarch64-linux-gnu-readelf -d $PREFIX/bin/ffmpeg | grep NEEDED

正常输出的依赖库列表应该都是aarch64平台相关的库,如果出现 libx264.so.164 就对了,如果出现 libm.so.6 这种基础库就没问题。千万不要出现x86_64的库依赖。

6. 部署到RK3588板端

6.1 拷贝文件和设置环境变量

编译好的FFmpeg要部署到板子上。最简单的方式就是直接把整个 /opt/rk3588-sysroot/usr/local 目录下的ffmpeg相关文件打包拷贝到板子的 /usr/local 目录。

在编译主机上:

cd /opt/rk3588-sysroot/usr/local
tar czf ffmpeg-rk3588.tar.gz bin/ffmpeg bin/ffprobe bin/ffplay lib/libavcodec* lib/libavformat* lib/libavutil* lib/libswscale* lib/libswresample* lib/libavfilter* lib/libx264* lib/libx265* lib/librockchip* lib/librga* include/

把 ffmpeg-rk3588.tar.gz 传到板子后解压:

tar xzf ffmpeg-rk3588.tar.gz -C /usr/local

然后在板子上设置环境变量。建议写进 /etc/profile.d/ffmpeg-rk3588.sh :

echo 'export FFMPEG_DIR=/usr/local' > /etc/profile.d/ffmpeg-rk3588.sh
echo 'export PATH=$FFMPEG_DIR/bin:$PATH' >> /etc/profile.d/ffmpeg-rk3588.sh
echo 'export LD_LIBRARY_PATH=$FFMPEG_DIR/lib:$FFMPEG_DIR/lib/aarch64-linux-gnu:$LD_LIBRARY_PATH' >> /etc/profile.d/ffmpeg-rk3588.sh
source /etc/profile.d/ffmpeg-rk3588.sh

这里要注意的是,如果你拷进去的库依赖其他动态库(比如x264依赖的libstdc++、libm),这些基础库在板子的系统目录里一般都有,不会缺。如果缺,提示 error while loading shared libraries: libxxx.so: cannot open shared object file ,用 ldd $FFMPEG_DIR/bin/ffmpeg 查看具体缺失项,然后到板子的 /usr/lib/aarch64-linux-gnu 目录下找找有没有,有的话做软链接即可。

6.2 验证环境是否正常

在板子上执行:

ffmpeg -version

正常会输出FFmpeg版本信息和编译配置选项。再检查硬解能力:

ffmpeg -hwaccels

输出中应该包含 rkmpp 。如果输出为空或者没有rkmpp,说明编译配置有问题,需要回到编译阶段排查。

还需要验证硬件解码设备节点是否存在:

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

RK3588正常会有 /dev/rga 节点,没有的话可能是内核驱动没加载,检查dmesg有没有相关日志。

6.3 板端依赖库冲突处理

这一步很容易被忽略但非常重要。RK3588的Ubuntu系统自带的运行环境里, /usr/lib/aarch64-linux-gnu 目录下可能已经存在 libavcodec.so.58 之类的系统FFmpeg库。如果你把自定义的FFmpeg安装到了 /usr/local/lib ,并且设置了 LD_LIBRARY_PATH ,那么运行时可能会加载到自定义版本,也可能会因为动态库搜索优先级问题加载到系统版本,这就产生了库冲突。

我的处理方式是,自定义FFmpeg的动态库统一放在 /usr/local/ffmpeg/lib 目录下(通过 --prefix=/usr/local/ffmpeg 而不是 /usr/local 控制),然后在使用时显式指定:

export LD_LIBRARY_PATH=/usr/local/ffmpeg/lib:$LD_LIBRARY_PATH

这样系统自带的FFmpeg相关库不受影响,需要用到自定义版本时再source这个环境变量。如果你像我一样把FFmpeg装到了 /usr/local ,那么上述冲突问题就需要你覆盖系统库的位置,风险比较大,不太推荐。

7. RTSP流测试的完整过程

7.1 RTSP取流硬解码验证

部署完成后,第一步测试就是RTSP拉流硬解码。我用一个本地ONVIF摄像头作为RTSP源,在板子上执行:

ffprobe -rtsp_transport tcp rtsp://192.168.1.100:554/live/main_stream

这个命令不需要实际解帧,只解析流信息和参数,用来验证RTSP协议和网络连通性。如果输出正常,能看到视频流的编码格式、分辨率、帧率,说明RTSP拉流已经通了。

接下来用ffmpeg硬解拉流:

ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:554/live/main_stream \
  -c:v h264_rkmpp -f null -

这里的核心参数是 -c:v h264_rkmpp ,指定使用RKMPP的H.264解码器。实际运行时观察CPU占用,硬解模式下一个4K H.265的流CPU占用大概在5%-10%,如果降到软解模式同样分辨率CPU占用会上升到60%以上,对比效果非常明显。

-f null - 表示不输出实际文件,只解码后丢弃,纯粹测试解码能力。如果你想保存成文件:

ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:554/live/main_stream \
  -c:v copy -f mp4 output.mp4

对于H.265的流源,解码器要换成 h265_rkmpp ,命令如下:

ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:554/live/hevc_stream \
  -c:v hevc_rkmpp -f null -

7.2 硬解码器参数选择与性能对比

实测过程中,我分别测试了H.264和H.265两种流在软硬解下的性能表现:

流规格 解码方式 CPU占用 解码延迟 帧率表现
1080P H.264 软解 18%-25% 约80ms 流畅
1080P H.264 rkmpp硬解 4%-8% 约30ms 流畅
4K H.265 软解 70%-85% 约200ms 明显掉帧
4K H.265 rkmpp硬解 8%-12% 约40ms 流畅

这个数据足以说明问题。对于4K H.265的流,软解在RK3588上基本不可用,硬解则轻松应对。

如果你用的是Rockchip的FFmpeg分支,可以在命令行里通过 -hwaccel rkmpp 声明全局硬解,并在解码器参数中用 -c:v h264_rkmpp 明确指定解码器。两种方式都可行,但推荐后者,因为更灵活,比如可以软解一路、硬解另一路做对比测试。

还有个细节:硬解输出的像素格式通常是 NV12 或 DRM_PRIME ,如果你接下来要做OpenCV或深度学习处理,需要先转成标准格式。此时可以用 scale_rkrga 滤镜结合RGA做硬件加速转换:

ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:554/live/main_stream \
  -vf "hwdownload,format=nv12,scale_rkrga=1920:1080:format=nv12" \
  -c:v rawvideo -pix_fmt yuv420p -f null -

这条命令先硬解出NV12帧,再通过RGA硬件缩放,最后在CPU侧转成YUV420P输出。整个过程除了最后的格式转换外,都走了硬件加速,CPU占用依然很低。

7.3 ffplay实时预览

如果你的板子接了HDMI显示器,可以用ffplay直接实时预览RTSP流:

ffplay -rtsp_transport tcp -i rtsp://192.168.1.100:554/live/main_stream \
  -vf "hwdownload,format=nv12" -pixel_format yuv420p

这里的关键是硬件解码的帧如果没有经过 hwdownload ,直接交给SDL/DRM显示会报错或者黑屏。hwdownload把硬件帧下载到系统内存,再交给显示链路。

如果遇到花屏或者显示卡顿,优先检查两点:

  • format=nv12 是否正确匹配了硬解输出格式,RKMPP解H.264默认输出NV12,解H.265有时是NV15或P010
  • 显示刷新率是否与视频帧率匹配,如果视频25fps而显示配置60Hz,用ffplay默认设置下可能会感到不流畅

用 ffprobe 查看流的实际编码格式和色深,再调整 format 参数即可解决。

7.4 推流到PC端验证

除了在板子上拉取RTSP流,还可以测试板子作为RTSP服务端的场景。虽然FFmpeg本身不提供RTSP服务器,但可以通过FFmpeg将视频流转发到本机的RTSP服务。

测试方法是先把板子的USB摄像头视频流推到PC上的RTSP服务器(如mediamtx或ZLMediaKit):

ffmpeg -f v4l2 -i /dev/video0 \
  -c:v h264_rkmpp -b:v 2M \
  -f rtsp rtsp://192.168.1.50:8554/live/test

这里用了 h264_rkmpp 来做硬件编码,CPU占用很低。如果不加 -c:v h264_rkmpp ,FFmpeg默认可能选用软件编码器,4K分辨率下CPU直接打满。实测下来RK3588的硬件编码器编码1080P H.264到2Mbps码率,CPU占用不到5%。

然后在PC上用VLC或者ffplay连接验证:

ffplay rtsp://192.168.1.50:8554/live/test

正常情况下几秒内就能出画面,延迟在100ms-300ms之间,这个延迟水平在局域网内属于正常范围。

8. 常见问题与排查技巧实录

8.1 configure阶段检测不到MPP库

现象 : ./configure 输出中没有 rkmpp ,或者config.log中提示找不到 rockchip_mpp.h 。

排查思路 :

先确认MPP库确实安装到了sysroot中:

find /opt/rk3588-sysroot -name "rockchip_mpp*" -o -name "mpp_dec.h"

如果没有,回到MPP编译步骤重新安装。如果有,检查configure时的 --extra-cflags 和 --extra-ldflags 参数:

--extra-cflags="-I/opt/rk3588-sysroot/usr/local/include/rockchip -I/opt/rk3588-sysroot/usr/local/include" \
--extra-ldflags="-L/opt/rk3588-sysroot/usr/local/lib"

这个问题的根源在于MPP头文件默认安装在 include/rockchip 子目录里,而FFmpeg的configure脚本只搜索标准include路径,需要手动指定。

8.2 板端运行时提示找不到librockchip_mpp.so

现象 :板子上执行 ffmpeg 报错 error while loading shared libraries: librockchip_mpp.so.1: cannot open shared object file: No such file or directory 。

排查思路 :

这说明动态库搜索路径没有包含MPP库所在的目录。用 ldd 查看详细依赖:

ldd /usr/local/bin/ffmpeg | grep "not found"

通常在 LD_LIBRARY_PATH 中加上MPP库目录即可:

export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib/aarch64-linux-gnu:$LD_LIBRARY_PATH

如果库确实存在但还是找不到,检查库文件的权限和链接符号:

ls -l /usr/local/lib/librockchip_mpp*

有可能 librockchip_mpp.so 这个无版本号的软链接没有创建,而FFmpeg依赖的是这个无版本号名字,这时手动补建软链接:

ln -sf /usr/local/lib/librockchip_mpp.so.1 /usr/local/lib/librockchip_mpp.so

8.3 硬解报错 Failed to setup rkmpp

现象 :运行ffmpeg硬解时报错 Failed to setup rkmpp ,但软解正常。

排查思路 :

这个报错通常是MPP自身初始化失败,常见原因有三个:

  • /dev/rga 或 /dev/mpp_service 设备节点不存在。用 ls /dev/rga /dev/mpp_service 检查,如果不存在需要检查内核模块是否加载。在RK3588的Ubuntu系统里需要确认 rga 和 mpp 相关的内核模块是否正确加载, sudo dmesg | grep -i mpp 能看到加载日志
  • MPP库版本不匹配。确认板子的MPP用户空间库和内核驱动版本是否配套,如果内核驱动较新而用户空间库较旧,会出现兼容性问题。这种情况可以尝试从Rockchip官方的Debian包仓库安装预编译的mpp库,或者更新板子的内核
  • 权限问题。某些隐藏的权限限制会导致设备节点无法打开,排查时可以先试试 sudo ffmpeg ... 运行,如果sudo后正常,说明是权限配置问题。解决办法是把当前用户加入 video 组: sudo usermod -aG video $USER

8.4 RTSP拉流花屏和卡顿

现象 :RTSP拉流后画面出现马赛克、花屏、解码停滞。

排查思路 :

大概率是RTSP传输模式的问题。RTSP默认走UDP,UDP在局域网中如果丢包严重,解码就会出现花屏。切换到TCP模式能显著改善:

ffmpeg -rtsp_transport tcp -i rtsp://...

如果TCP模式下仍然卡顿,观察网络带宽是否足够,4K H.265的码率一般在8-15Mbps,百兆网络基本够用但接近极限。千兆网络比较稳妥。另外检查RTSP源设备是否限制了并发连接数,有的摄像头只允许一路RTSP会话,你调试时另一个程序占用了连接,会导致新连接被拒绝或者反复重连。

8.5 编解码耗时与实时性调优

如果对延迟敏感,比如做视频通话或者低延迟监控,可以调整几个参数:

ffmpeg -rtsp_transport tcp -max_delay 100000 -analyzeduration 1000000 \
  -i rtsp://... -c:v copy -f rtsp ...

-max_delay 控制缓冲区大小,减小它可以直接降低延迟但可能引发卡顿; -analyzeduration 控制流信息分析的时长,太大会延迟起播。这两个参数需要根据实际网络状况做平衡。

另外硬解码器本身可以设置 -hwaccel_output_format nv12 强制输出格式,省去后续格式转换的开销。如果显示链路允许,还可以直接尝试让解码器输出DRM Prime格式的零拷贝帧,通过 scale_rkrga 滤镜直接送显示,能明显降低内存拷贝开销。

8.6 关于FFmpeg版本升级的补充

如果后续要升级板端的FFmpeg,建议用脚本记录configure参数和依赖库版本,方便重复构建。我习惯在交叉编译目录下放一个 build_all.sh ,把所有步骤串起来执行,这样一键重建整条链,不用每次手动敲一堆命令。

另外,RK3588平台在编译FFmpeg时,如果遇到编译器报错 internal compiler error ,大概率是编译主机内存不足。FFmpeg的编译过程比较吃内存,尤其是链接阶段,建议编译主机至少8GB内存,编译时不要开太多并行任务, make -j4 比 make -j16 更稳定。

9. 实操总结与经验补充

整个流程走下来,从交叉编译到RTSP流测试,核心收获可以梳理成几条经验。

第一,交叉编译环境必须一步到位。 工具链版本、sysroot目录、环境变量、pkg-config配置,任何一个环节出错都会在后续configure阶段暴露出来,而且报错信息往往很迷惑。我的建议是第一遍严格按照文中步骤来,不要跳过任何依赖库的安装直接编译FFmpeg,否则报错了你也分不清是工具链问题还是依赖库问题。环境变量方面,把 source /opt/rk3588-env.sh 固化成一个脚本后,每次新开终端都先执行一次,能省掉很多“明明上一步还好好的,换个终端就编不过”的烦恼。

第二,MPP硬解和RGA加速是RK3588平台FFmpeg的灵魂。 没有这两个选项的FFmpeg,在RK3588上和在一台树莓派上没有本质区别。硬解4K H.265把CPU占用从80%拉到10%以内,这个性能差异不需要多解释,实际项目如果要做视频分析、多路解码,不启用硬解基本等于不可用。所以配置时务必确认 --enable-rkmpp 和 --enable-rkrga 都真正生效了,不是configure能过就行,还要在 -hwaccels 输出中确认。

第三,测试RTSP之前先测好网络层。 很多时候RTSP拉流不流畅,问题不在FFmpeg而在网络。建议先用 ffprobe 测试连通性和流信息,再用 ping 和 iperf3 确认带宽。我在实际部署中遇到过摄像头在弱网环境下RTSP流经常中断,后来排查发现是RTSP源的TCP keep-alive设置问题,解决办法是在RTSP源设备端开启TCP keep-alive支持。

第四,动态库路径问题要提前规划。 我吃过一次亏,把FFmpeg安装到了 /usr/local 目录,当时测试一切正常,结果系统重启后开机服务里意外加载了自定义的libavcodec,导致系统自带的应用崩溃。后面改成独立目录 /usr/local/ffmpeg ,用环境变量控制是否启用,再也没出过这种事。如果你只是临时测试,用 LD_LIBRARY_PATH 临时指定即可;如果长期使用,建议做成独立部署目录,不要污染系统目录。

最后再分享一个小技巧:如果你检测到RTSP流中有BUG或者需要加调试信息,可以在编译时打开 --enable-debug 重新编译一套带调试符号的FFmpeg。调试版编译产物体积大、运行慢,但排查深层问题(比如某个解码器崩溃)时价值极高。日常使用调试版,定位问题后再切回release版,效率会高很多。

rk3588 ffmpeg使用硬件解码 找到需要的x264 libdrm的pkgconfig文件夹,rockchip_mpp.pc 被安装在了/usr/local/lib/pkgconfig这里。在https://johnvansickle.com/ffmpeg/下载最新的版本然后解压。–host 当前编译工具链的前缀 ll /usr/bin/gcc*查看。在https://launchpad.net/上搜索软件名+ppa。将ffmpeg移动到/usr/local/bin文件夹。然后更改配置文件/etc/ld.so.conf。 阅读详情

相关推荐

RK3588视频转码实战:如何用FFmpeg调用MPP实现高效H.265转H.264

本文详细介绍了在RK3588平台上,如何通过编译支持rkmpp的FFmpeg,调用其内置的媒体处理平台(MPP)实现高效的硬件加速视频转码。文章以H.265转H.264为例,提供了从环境搭建、核心命令解析到性能调优的完整实战指南,帮助开发者在嵌入式设备上实现低功耗、高性能的视频处理。

weixin_29275257的博客 1014

FFmpeg - 硬件解码渲染多路视频

本资源包含完整的Vs+Qt+FFmpeg+sdl代码。 资源介绍:https://blog.youkuaiyun.com/automoblie0/article/details/115986306 资源视频介绍:https://www.bilibili.com/video/BV1FM4y1G78g/?spm_id_from=333.999.0.0 【视频中展示的软件效果即是本资源的完整代码】

RK3588实战:FFmpeg交叉编译与RTSP流媒体处理

本文详细介绍了在RK3588平台上进行FFmpeg交叉编译与RTSP流媒体处理的实战指南。从交叉编译环境搭建、FFmpeg配置优化到RTSP流处理代码实现,全面解析了在嵌入式设备上高效处理流媒体的关键技术。特别针对RK3588的硬件特性,提供了性能优化方案和实际项目经验分享,助力开发者快速掌握嵌入式多媒体开发。

weixin_28312391的博客 386

玩转rk3588(六):rk3588使用ffmpeg实现硬件解码,解决opencv中VideoCapture获取网络摄像头视频时,一直在open时返回false的问题(一)

在使用opencv的VideoCapture获取网络摄像头视频时,一直在open时返回false。原因在与opencv编译过程中没有ffmpeg。rk3588使用ffmpeg实现硬件解码。

qq_32636415的博客 1万+

RK3588硬解实践:FFmpeg接入RKmpp与RGA格式转换指南

在嵌入式视频与AI推理场景中,视频解码往往成为性能瓶颈。FFmpeg作为通用多媒体处理框架,其软解方案在面对高分辨率H.264/H.265码流时CPU占用率过高,难以满足实时处理需求。RK3588芯片内部集成了VPU、RGA等独立硬件模块,通过Rockchip MPP媒体库和FFmpeg的rkmpp解码器,可大幅降低解码负载,将4K硬解CPU占用控制在10%以内。而解码输出通常为DRM Prime格式的NV12帧,需要借助RGA二维加速器完成色彩空间转换与缩放,才能高效送入显示链路或算法模型。本文围绕RK3

weixin_29178069的博客 204

RK平台从零编译FFmpeg:启用rkmpp硬解完整指南

视频硬解是嵌入式音视频开发中降低CPU负载的关键技术。FFmpeg通过hwaccel接口对接不同芯片平台的硬件编解码能力,而在Rockchip RK3588、RK3568等ARM平台上,真正发挥VPU性能依赖rkmpp模块与libdrm的协同。发行版预编译的FFmpeg往往缺失这一通道,导致4K HEVC解码或多路RTSP拉流时CPU飙升。本文从编译环境搭建、依赖库准备、configure参数配置到硬解效果验证,完整梳理在RK平台从源码编译FFmpeg的流程,并针对交叉编译、版本匹配、CMA内存等常见坑给出

weixin_29188997的博客 224

瑞芯微 RK 系列 RK3588 使用 ffmpeg-rockchip 实现 MPP 视频硬件编解码-代码版

在上一篇文章中,我们讲解了如何使用 ffmpeg-rockchip 通过命令来实现 MPP 视频硬件编解码和 RGA 硬件图形加速,在这篇文章,我将讲解如何使用 ffmpeg-rockchip 用户空间库(代码)实现 MPP 硬件编解码。本文不仅适用于 RK3588,还适用于 RK 家族系列的芯片,具体的细节可查看官方 MPP 文档。

Leon_Chenl的博客 1万+

RK3588/RK3568嵌入式硬解实战:FFmpeg对接MPP实现RTSP H264/H265低延迟解码

在嵌入式视频开发中,RTSP流媒体播放常面临CPU软解性能瓶颈,尤其H265编码计算量更大。硬解通过VPU将解码任务从CPU卸载,大幅降低占用。FFmpeg作为通用多媒体框架,结合MPP中间层可调用瑞芯微VPU,实现高效硬解。该方案在智能监控、边缘计算等场景价值显著,能稳定支持多路4K流。本文详细记录从环境搭建到代码实现的完整过程,涵盖H264/H265兼容处理与性能调优,助你快速落地硬解方案。

weixin_30342363的博客 168

RK3588硬解海康RTSP流并NPU部署YOLOv5实战

在边缘计算场景中,目标检测常需处理RTSP视频流,而CPU软解与推理易成瓶颈。通过VPU硬件解码(如rkmpp)和NPU加速(如RKNN),可大幅降低CPU占用并提升吞吐。该方案先拉取海康IPC的H.264码流,经硬解得到NV12帧,再通过RGA缩放与格式转换,最后送入YOLOv5模型完成NPU推理。技术价值在于实现低延迟、高能效的实时检测,适用于安防监控、智能交通等场景。本文以RK3588为例,详解从环境搭建到多路并发的完整工程实践。

weixin_29174141的博客 309

基于RK3588与rkmpp的实时视频分析实践:从海康威视H.264码流到YOLOv5目标检测

本文详细介绍了在RK3588开发板上,利用rkmpp多媒体框架硬解码海康威视摄像头的H.264码流,并集成YOLOv5模型实现实时目标检测的完整实践方案。内容涵盖环境搭建、rkmpp硬解码测试、RTSP流拉取、RKNN模型部署以及构建高效视频分析流水线的核心技术,旨在为嵌入式AI视觉应用开发者提供一套高性价比、低延迟的实战指南。

weixin_29170327的博客 328

RK3588交叉编译带MPP硬件加速的FFmpeg完整指南

在嵌入式视觉与边缘计算场景中,视频编解码效率直接影响系统实时性与功耗。FFmpeg作为通用多媒体框架,默认仅支持软件编解码,无法调用SoC内置的硬件编解码单元。通过集成Rockchip MPP中间件,可将VPU的编解码能力接入FFmpeg,实现H.264/H.265等格式的硬件加速,显著降低CPU占用并提升吞吐。该方案适用于NVR、AI推理盒子、视频汇聚网关等需要多路高清转码或RTSP推流的设备。本文详细记录了在RK3588平台上从零交叉编译MPP与FFmpeg的完整流程,涵盖工具链配置、依赖库编译、关键参

weixin_34245082的博客 264

RK3588上编译带MPP硬件加速的FFmpeg完整指南

在嵌入式视频处理中,硬件编解码是提升性能的关键。通过调用VPU等专用硬件单元,可大幅降低CPU负载,实现高吞吐、低延迟的多路视频处理。其原理是将编解码任务从通用CPU卸载到专用硬件,技术价值在于显著提升能效比,广泛应用于边缘计算、视觉SLAM、多路摄像头转RTSP及YOLOv8部署等场景。本文以RK3588为例,详细讲解如何从源码编译集成MPP的FFmpeg,涵盖依赖库配置、交叉编译及性能验证,助你充分发挥VPU硬件加速能力。

weixin_30595035的博客 456

RK3588硬解H.264与YOLOv5部署:rkmpp+RGA+NPU零拷贝实战

在边缘计算场景中,视频解码与AI推理的性能至关重要。H.264作为主流编码格式,其硬件解码可大幅降低CPU负载。通过VPU、RGA和NPU的协同,实现零拷贝数据流,能显著提升实时目标检测的帧率与能效。该方案适用于智能安防、工业巡检等对实时性要求高的领域。本文基于RK3588平台,详细分享rkmpp硬解、RGA缩放及YOLOv5模型部署的工程实践,涵盖环境搭建、核心实现与性能优化。

weixin_28711397的博客 196

RKMPP实战:从交叉编译到多路解码性能优化

硬件编解码通过专用VPU单元实现视频压缩与解压,能大幅降低CPU负载并提升吞吐量。其原理是将H.264/H.265等格式的码流解析、帧重建等计算密集型任务卸载到硬件加速器,配合DMA零拷贝通路,实现低延迟、高并发的视频处理。在嵌入式视觉、智能安防、车载DVR等场景中,硬件编解码是保障多路高清实时处理的关键。瑞芯微平台提供的RKMPP抽象层,统一封装了VPU与RGA的调用接口,但交叉编译环境配置、buffer管理及多路架构设计常成为工程落地难点。本文围绕RKMPP,梳理从工具链搭建到性能调优的完整实践路径。

weixin_29166013的博客 270

RK3588平台开发系列讲解(视频篇)ffmpeg 的移植

📢ffmpeg 是一种多媒体音视频处理工具,具备视频采集功能、视频抓取图像、视频格式转换、给视频加水印并能将视频转化为流等诸多强大的功能。它采用 LGPL 或 GPL 许可证,是一种开源程序。

内核笔记 1912

Rk3588 FFmpeg 拉流 RTSP, 硬解码转RGB

Rk3588 FFmpeg 拉流 RTSP, 硬解码转RGB

J。 1372

3.2 RK3588使用通过FFMPEG进行RTMP推流

本文介绍了使用FFmpeg进行RTMP/RTSP推流的方法。首先通过git克隆FFmpeg源码并进行基础编译配置,仅启用推流所需功能。随后详细展示了推流程序的实现代码,包括初始化AVFormatContext、设置视频/音频编码参数、创建输出流、打开编码器等关键步骤。程序采用多线程处理,通过链表结构管理音视频数据,实现了视频帧和音频帧的同步推送功能。最后说明了如何释放资源及销毁推流服务。该实现支持TCP传输协议,并针对RTSP推流进行了延迟优化设置。

m0_46087051的博客 2463

Ubuntu x64 架构, 交叉编译aarch64 FFmpeg mpp

Ubuntu x64 架构上,交叉编译aarch64 FFmpeg mpp.

J。 526
上一篇: 从一次断网实验看智能音箱的本地唤醒与云端分工
下一篇: 创维H2901-T2刷机实录:YYF固件+当贝桌面让老盒子焕新
kBlnW
博客等级 码龄10年 80粉丝 8012原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值