Luckfox RV1106开发板实战:手把手教你用ffmpeg播放240x240视频(附环境变量配置)
Luckfox RV1106开发板实战:手把手教你用ffmpeg播放240x240视频(附环境变量配置)
最近在折腾Luckfox RV1106这块开发板,想用它来驱动一块240x240的小屏幕播放视频。这听起来是个简单的任务,不就是把视频文件解码然后显示出来嘛?但真正上手才发现,在嵌入式Linux环境下,从交叉编译ffmpeg到处理开发板特有的权限和环境变量,每一步都可能藏着“坑”。这篇文章,我就把自己从环境搭建到成功播放视频的完整流程,以及中间遇到的各种问题和解法,毫无保留地分享出来。无论你是刚接触Luckfox RV1106的嵌入式开发者,还是想在资源受限的设备上实现多媒体功能的爱好者,这篇实战指南应该都能帮你少走些弯路。
1. 环境准备与ffmpeg交叉编译
在PC上编译一个程序和在嵌入式开发板上编译,完全是两码事。RV1106采用的是ARM架构的处理器,这意味着我们无法直接在开发板上编译复杂的软件,必须在x86_64的宿主机(比如你的Ubuntu虚拟机)上,使用专门的交叉编译工具链,生成能在ARM板上运行的可执行文件。这个过程,就是我们常说的“交叉编译”。
1.1 获取并配置交叉编译工具链
Luckfox官方SDK里已经为我们准备好了现成的工具链。通常,它位于SDK目录的 tools/linux/toolchain/ 路径下。你需要先确认这个路径,并把它加入到系统的环境变量中,这样后续编译时才能被自动调用。
打开你的终端,执行以下命令来临时添加工具链到PATH(假设你的SDK解压在家目录下):
export PATH=$PATH:~/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin
为了验证工具链是否生效,可以尝试查询其版本:
arm-rockchip830-linux-uclibcgnueabihf-gcc --version
如果正确输出了gcc版本信息,说明工具链已经就绪。我建议将这个环境变量写入你的 ~/.bashrc 文件,避免每次打开终端都要重新设置。
1.2 下载与编译ffmpeg源码
ffmpeg版本众多,为了稳定性和兼容性,我选择了经典的 ffmpeg-3.4.8 版本。这个版本在嵌入式领域被广泛验证过,依赖相对清晰。
首先,下载并解压源码:
wget http://www.ffmpeg.org/releases/ffmpeg-3.4.8.tar.gz
tar -zxvf ffmpeg-3.4.8.tar.gz
cd ffmpeg-3.4.8
接下来就是关键的配置环节。直接运行 ./configure 会为目标宿主机(也就是你的Ubuntu)编译,我们需要通过参数告诉它,我们要为ARM架构的Linux进行交叉编译。
这里有一个经典的错误你可能马上会遇到:
yasm/nasm not found or too old. Use --disable-yasm for a crippled build.
yasm 是一个汇编编译器,ffmpeg用它来编译一些高度优化的汇编代码(比如SIMD指令),以提升编解码性能。在宿主机上,我们可以选择安装yasm,或者直接禁用汇编优化(--disable-yasm)。但对于交叉编译,情况更特殊:我们编译的是在ARM上运行的ffmpeg,而yasm编译的是x86的汇编代码,这对ARM目标机无用。因此,最直接的做法是在交叉编译配置中直接禁用yasm。
基于此,我的完整配置命令如下:
./configure \
--enable-cross-compile \ # 启用交叉编译
--arch=arm \ # 目标架构为ARM
--target-os=linux \ # 目标操作系统为Linux
--cross-prefix=arm-rockchip830-linux-uclibcgnueabihf- \ # 交叉工具链前缀
--disable-yasm \ # 禁用x86汇编优化,对ARM目标必须
--enable-shared \ # 生成动态链接库
--prefix=/usr/lib/ffmpeg \ # 指定安装目录(相对目标板根目录)
--disable-static \ # 可选:禁用静态库,减小体积
--disable-programs \ # 可选:不编译ffplay, ffprobe等程序,如果你只需要库
--disable-doc # 可选:禁用文档生成
注意:
--cross-prefix参数的值就是你的交叉编译工具链的前缀。它告诉配置脚本,使用arm-rockchip830-linux-uclibcgnueabihf-gcc而不是默认的gcc进行编译。
配置成功后,执行编译和安装:
make -j$(nproc) # 使用多核编译加速
make install DESTDIR=$(pwd)/_install # 安装到当前目录的_install子目录
这里使用 DESTDIR 是关键技巧。--prefix=/usr/lib/ffmpeg 定义了文件在目标板文件系统中的最终位置。而 DESTDIR=$(pwd)/_install 则指定了在宿主机上的临时安装目录。编译生成的所有文件(可执行文件、库、头文件)都会被放置到 ./_install/usr/lib/ffmpeg/ 目录下。这样,我们就能方便地将整个 _install 目录打包,传输到开发板。
编译完成后,检查 _install 目录,你应该能看到类似这样的结构:
_install/
└── usr
└── lib
└── ffmpeg
├── bin
│ └── ffmpeg # 我们需要的可执行文件
└── lib
├── libavcodec.so.57
├── libavformat.so.57
├── libavutil.so.55
└── ... # 其他ffmpeg动态库
2. 向开发板部署ffmpeg
编译产物有了,下一步就是把它放到RV1106开发板上运行。这里涉及到文件传输和权限管理两个核心问题。
2.1 文件传输与存储路径选择
RV1106开发板通常通过SD卡或网络(如NFS、SCP)与宿主机交换数据。对于像ffmpeg这样包含可执行文件和多个库的“软件包”,我推荐两种方式:
- SD卡/U盘挂载:最直接的方式。将
_install目录下的所有内容拷贝到存储设备的某个文件夹(例如ffmpeg_package),然后将存储设备插入开发板并挂载。这种方式独立于开发板的根文件系统,不会对其造成任何修改,非常安全。 - SCP网络传输:如果开发板已经联网,可以使用
scp命令直接将文件传输到板子的某个目录,比如/tmp或/home下。这要求开发板已开启SSH服务。
假设我们使用SD卡,在宿主机上将其格式化为FAT32或ext4,并挂载到 /mnt/sdcard。然后将编译好的文件复制过去:
cp -r _install/usr/lib/ffmpeg/* /mnt/sdcard/ffmpeg/
在开发板上,我们需要挂载这个SD卡:
# 在RV1106开发板的终端上操作
mkdir -p /mnt/sdcard
mount /dev/mmcblk0p1 /mnt/sdcard # 设备节点可能不同,请用 `ls /dev/mmc*` 确认
cd /mnt/sdcard/ffmpeg
ls -l
你应该能看到 bin 和 lib 目录。
2.2 解决执行权限问题
一个容易被忽略但至关重要的问题是:从SD卡或U盘这类非系统分区直接运行可执行文件,可能会因为文件系统权限属性(如noexec)或SELinux/AppArmor(虽然RV1106上不常见)而导致失败。
提示:如果你直接运行
/mnt/sdcard/ffmpeg/bin/ffmpeg报错 “Permission denied” 或无法执行,很可能就是权限问题。
最稳妥的解决方案是,将必要的可执行文件复制到开发板本地的系统路径,例如 /usr/bin 或 /usr/local/bin。这些路径默认就具有执行权限。
# 在RV1106开发板上操作
cp /mnt/sdcard/ffmpeg/bin/ffmpeg /usr/bin/
chmod +x /usr/bin/ffmpeg # 确保添加执行权限
现在,你可以在终端任何位置直接输入 ffmpeg 命令了。
3. 配置运行时环境变量
ffmpeg的可执行文件放好了,但它运行时还需要找到对应的动态链接库(.so文件)。这些库文件我们放在了 /mnt/sdcard/ffmpeg/lib/。系统默认的库搜索路径(如 /lib, /usr/lib)里没有它们,所以直接运行 ffmpeg 会报错:
error while loading shared libraries: libavcodec.so.57: cannot open shared object file: No such file or directory
这就需要配置 LD_LIBRARY_PATH 环境变量。这个变量告诉系统的动态链接器,除了默认路径,还要去哪些额外的目录寻找共享库。
3.1 临时设置与验证
在开发板的终端中,可以临时设置:
export LD_LIBRARY_PATH=/mnt/sdcard/ffmpeg/lib:$LD_LIBRARY_PATH
然后,立刻测试ffmpeg是否能正常运行:
ffmpeg -version
如果正确输出了ffmpeg的版本信息和编译配置,恭喜你,环境配置成功了!这种临时设置只对当前终端会话有效。
3.2 永久环境变量配置
为了让ffmpeg在每次开机或任何终端中都能使用,我们需要永久设置 LD_LIBRARY_PATH。有几种常见方法:
方法一:修改用户配置文件(推荐用于个人开发)
编辑开发板上当前用户的 ~/.bashrc 文件(如果使用bash):
echo 'export LD_LIBRARY_PATH=/mnt/sdcard/ffmpeg/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc # 使配置立即生效
方法二:创建全局配置文件
如果希望所有用户都能使用,可以在 /etc/profile.d/ 目录下创建一个脚本文件:
echo 'export LD_LIBRARY_PATH=/mnt/sdcard/ffmpeg/lib:$LD_LIBRARY_PATH' > /etc/profile.d/ffmpeg.sh
chmod +x /etc/profile.d/ffmpeg.sh
重启或重新登录后,环境变量就会自动生效。
方法三:将库文件复制到系统路径
更彻底的方法是,把ffmpeg的库文件也复制到系统的标准库目录,比如 /usr/lib:
cp /mnt/sdcard/ffmpeg/lib/*.so* /usr/lib/
ldconfig # 更新系统的库缓存
这样做之后,就完全不需要设置 LD_LIBRARY_PATH 了。但要注意,这可能会覆盖系统原有的同名库(虽然概率很低),且会占用开发板自身存储空间。
下表对比了这几种部署和配置方式的优缺点:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| SD卡存储 + 临时LD_LIBRARY_PATH | 不占用板载存储,干净隔离 | 每次新开终端需重新设置,依赖外置存储 | 快速测试、原型验证 |
| SD卡存储 + 永久LD_LIBRARY_PATH | 使用方便,不占用板载存储 | 系统启动依赖外置存储挂载 | 长期使用且存储卡常驻的项目 |
| 复制到系统目录 (/usr/bin, /usr/lib) | 使用最方便,无需额外配置 | 占用板载存储,可能(极低风险)影响系统 | 产品化部署、存储空间充足的板子 |
4. 播放240x240分辨率视频实战
环境终于搭好了,现在来点实际的——播放视频。我们的目标是一块240x240的RGB接口小屏幕,在Linux系统中通常对应一个帧缓冲(Framebuffer)设备,比如 /dev/fb0。
4.1 准备测试视频与ffmpeg命令解析
首先,准备一个视频文件(比如 test.mp4),并将其放到开发板可访问的位置,例如SD卡的根目录 /mnt/sdcard/。
播放视频的核心ffmpeg命令如下:
ffmpeg -i /mnt/sdcard/test.mp4 -r 30 -vf scale=240:240 -pix_fmt rgb565le -f fbdev /dev/fb0
我们来拆解这个命令的每个参数:
-i /mnt/sdcard/test.mp4:指定输入视频文件。-r 30:设置输出帧率为30帧/秒。你可以根据视频原帧率和性能调整。-vf scale=240:240:这是视频滤镜(video filter)参数,scale滤镜将视频缩放到指定的分辨率。240:240 正是我们屏幕的目标分辨率。ffmpeg会智能地进行缩放,保持宽高比或强制拉伸(可添加force_original_aspect_ratio等参数微调)。-pix_fmt rgb565le:设置输出像素格式为 RGB565 Little Endian。这是嵌入式显示屏非常常用的一种16位色彩格式(R:5位, G:6位, B:5位)。务必确认你的屏幕控制器支持的格式,常见的还有rgb24(24位真彩色)、bgr565le等。格式不对会导致花屏或颜色错误。-f fbdev:指定输出格式为 framebuffer device,即Linux帧缓冲设备。/dev/fb0:指定具体的帧缓冲设备节点。如果你的屏幕连接在别的FB设备上,请相应修改。
4.2 高级参数调优与问题排查
直接运行上述命令可能成功,也可能遇到性能或显示问题。下面是一些调优技巧和排查思路:
1. 降低解码负载: RV1106的CPU和算力有限,解码高分辨率、高码率的视频可能吃力。可以尝试:
- 降低输出帧率:
-r改为 15 或 10。 - 跳过解码:如果视频是H.264等格式,RV1106的硬件解码器可能支持。但通过ffmpeg命令行直接调用硬解通常需要特定配置(如
-c:v h264_rkmpp),这涉及到更复杂的ffmpeg编译选项和MPP(Media Process Platform)库的集成,是另一个深水区。初期建议先用软解测试流程。
2. 精确控制缩放:
scale=240:240 可能会使视频变形。如果你想保持原视频比例,并在四周填充黑边,可以使用:
-vf "scale=240:240:force_original_aspect_ratio=decrease,pad=240:240:(ow-iw)/2:(oh-ih)/2"
这个滤镜链先按比例缩放到能放入240x240的最大尺寸,然后用pad滤镜在四周填充黑色至目标尺寸。
3. 检查帧缓冲设备:
确保你有权限访问 /dev/fb0,并且它确实对应你的屏幕。可以尝试用简单的命令测试FB设备:
cat /dev/urandom > /dev/fb0
如果屏幕出现随机雪花点,说明FB设备基本工作正常。注意:执行此命令后屏幕会花,可能需要重启恢复。
4. 性能监控: 在播放视频时,可以通过另一个终端查看系统负载:
top
观察CPU使用率。如果 ffmpeg 进程的CPU占用率持续接近100%,说明软解压力很大。
4.3 编写一个简单的播放脚本
为了方便测试,我们可以将命令、环境变量设置和必要的检查写成一个Shell脚本 play_video.sh:
#!/bin/sh
# 播放脚本示例
# 1. 设置库路径(根据你的实际部署方式调整)
export LD_LIBRARY_PATH=/mnt/sdcard/ffmpeg/lib:$LD_LIBRARY_PATH
# 2. 定义变量
VIDEO_FILE="/mnt/sdcard/test.mp4"
FB_DEVICE="/dev/fb0"
TARGET_RES="240:240"
FRAME_RATE="15"
PIXEL_FORMAT="rgb565le"
# 3. 检查文件是否存在
if [ ! -f "$VIDEO_FILE" ]; then
echo "错误:视频文件 $VIDEO_FILE 不存在!"
exit 1
fi
# 4. 检查fb设备是否存在
if [ ! -c "$FB_DEVICE" ]; then
echo "错误:帧缓冲设备 $FB_DEVICE 不存在!"
exit 1
fi
# 5. 打印信息并开始播放
echo "开始播放 $VIDEO_FILE -> $FB_DEVICE (${TARGET_RES}, ${PIXEL_FORMAT} @ ${FRAME_RATE}fps)"
echo "按 Ctrl+C 停止播放。"
# 6. 执行ffmpeg命令
ffmpeg -i "$VIDEO_FILE" -r "$FRAME_RATE" -vf "scale=$TARGET_RES" -pix_fmt "$PIXEL_FORMAT" -f fbdev "$FB_DEVICE"
# 7. 播放结束后的提示
echo "播放结束。"
将脚本保存到开发板,赋予执行权限 chmod +x play_video.sh,然后运行即可。这个脚本增加了基本的健壮性检查,比直接输入长命令更可靠。
5. 常见问题与深度优化方向
走到这一步,你应该已经能在屏幕上看到跳动的画面了。但实际项目中,我们可能还会遇到一些“怪现象”,或者有更高的要求。
问题一:播放卡顿,CPU占用高 这是嵌入式视频播放最常见的问题。
- 第一步:确认是否使用了硬件解码。正如前文所述,软解(CPU解码) 在RV1106上播放稍高分辨率的视频会非常吃力。真正的性能提升来自于启用 硬解,这需要:
- ffmpeg编译时开启Rockchip MPP(Media Process Platform)支持。这通常意味着在
./configure时需要额外参数,并且SDK中必须提供MPP库的头文件和链接库。 - 播放命令中使用特定的解码器,如
-c:v h264_rkmpp。
- ffmpeg编译时开启Rockchip MPP(Media Process Platform)支持。这通常意味着在
- 第二步:降低视频源规格。如果暂时无法搞定硬解,那就从源头下手,在PC上先用工具将视频转码为低分辨率(如240p)、低码率、低帧率的格式,再放到板子上播放。
问题二:颜色显示异常(偏色、反色)
这几乎可以肯定是 -pix_fmt 参数设置错误。
- 确认屏幕数据格式:仔细阅读屏幕驱动芯片(如ILI9341、ST7789等)的数据手册,看它期望的16位或18位数据格式是 RGB565 还是 BGR565,是 Little Endian 还是 Big Endian。
rgb565le和bgr565be显示出来的红蓝色调会是反的。 - 尝试其他格式:如果RGB565系列都不对,可以尝试24位格式,如
rgb24或bgr24。当然,这需要屏幕驱动和FB驱动支持。
问题三:画面位置偏移或只有部分显示
这可能与帧缓冲的内存映射有关。有些FB驱动要求写入的数据与屏幕的物理分辨率和色深严格匹配。你可以尝试使用 fbset 命令查看和设置FB参数:
fbset
查看 geometry 和 rgba 设置是否与你的命令输出匹配。在ffmpeg命令中,确保 -vf scale 的分辨率与FB设备报告的分辨率一致。
深度优化方向:绕过ffmpeg,直接使用MPP库 对于追求极致性能和低延迟的应用(如视频门铃、流媒体客户端),最终方案往往是剥离ffmpeg。ffmpeg作为一个庞大的通用框架,在嵌入式场景下有一定开销。Rockchip提供了直接的 MPP (Media Process Platform) 编程接口,允许开发者用C/C++直接调用VPU(视频处理单元)进行硬解码,然后将解码后的图像数据通过DRM(Direct Rendering Manager)或自定义方式送显。这条路学习曲线陡峭,但能带来最大的控制权和效率。
整个流程走下来,从交叉编译的配置陷阱,到开发板上的权限和环境变量“玄学”,再到播放命令的参数调校,每一步都需要耐心和细致的排查。嵌入式开发就是这样,理论上的简单流程,总会因为具体硬件和环境的差异变得复杂。但每解决一个问题,你对系统的理解就加深一层。我最初在RV1106上折腾ffmpeg播放时,光是颜色不对就排查了两天,最后发现是屏幕规格书上一个不起眼的注释——它要求的是BGR顺序。希望我的这些经验,能帮你把这两天的调试时间缩短到两小时。
更多推荐


所有评论(0)