2、开发环境搭建:交叉编译工具链安装、FFmpeg源码编译、SDL库移植
好,咱们正式开始动手了。
这一章,说白了就是搭灶台。没有锅碗瓢盆,你后面再好的菜也炒不出来。嵌入式音视频开发,最烦人的就是环境搭建。我当年刚入行时,光配交叉编译链就折腾了两天,后来发现是路径写错了……嗯,这种坑咱们今天一次性填平。
2.1 交叉编译工具链:为什么非得用这个?
你想想看,你的开发电脑是 x86 架构,但目标板子是 ARM 架构。代码在 x86 上编译出来,ARM 板子根本跑不了。交叉编译链,就是让你在 PC 上生成 ARM 可执行文件的桥梁。
我个人习惯用 Linaro 提供的 GCC 工具链,稳定且社区活跃。以 ARM Cortex-A7 为例,安装步骤其实就三步:
- 下载:从 Linaro 官网获取 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
- 解压:扔到 /opt/toolchains 目录下
- 配置环境变量:把 bin 目录加到 PATH 里
# 解压
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/toolchains/
# 配置环境变量(写到 ~/.bashrc 里)
export PATH=/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
# 验证
arm-linux-gnueabihf-gcc --version
2.2 FFmpeg 源码编译:别怕,没那么玄乎
FFmpeg 是音视频领域的瑞士军刀。但嵌入式平台不能直接用 apt-get 装,必须自己交叉编译。为什么?因为你要裁剪功能、优化尺寸、适配硬件编解码器。
我建议你下载 FFmpeg 4.4 版本,这个版本稳定且文档齐全。编译前先配好 configure 参数,核心就这几项:
| 参数 | 说明 |
|---|---|
| --cross-prefix | 指定交叉编译工具链前缀 |
| --enable-cross-compile | 开启交叉编译模式 |
| --target-os | 目标操作系统,比如 linux |
| --arch | 目标架构,比如 arm |
| --disable-xxx | 按需裁剪,减少体积 |
下面是我实际项目里用过的编译脚本,你可以直接参考:
#!/bin/bash
export PATH=/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
./configure \
--cross-prefix=arm-linux-gnueabihf- \
--enable-cross-compile \
--target-os=linux \
--arch=arm \
--disable-doc \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-network \
--disable-encoders \
--disable-muxers \
--enable-decoder=h264 \
--enable-decoder=aac \
--enable-demuxer=mov \
--enable-demuxer=flv \
--enable-protocol=file
make -j4
make install
2.3 SDL 库移植:让画面显示出来
FFmpeg 负责解码,但解码出来的数据怎么显示到屏幕上?这就轮到 SDL 出场了。SDL 是一个跨平台的多媒体库,说白了就是帮你操作 framebuffer 或 OpenGL ES。
嵌入式平台移植 SDL,重点在于配置显示后端。对于大多数 ARM Linux 板子,我们使用 fbcon(framebuffer console)驱动。
编译 SDL 2.0.20 的步骤:
# 配置
./configure \
--host=arm-linux-gnueabihf \
--prefix=/opt/sdl2_arm \
--disable-video-x11 \
--disable-video-wayland \
--enable-video-fbcon \
--enable-video-opengles
make -j4
make install
这里有个关键点:--enable-video-fbcon 必须打开。否则 SDL 找不到显示设备,你的画面就黑屏了。
🔑 核心验证方法:
编译完成后,写一个简单的测试程序:
#include <SDL2/SDL.h>
int main() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL Init failed: %s\n", SDL_GetError());
return -1;
}
SDL_Window *win = SDL_CreateWindow("test", 0, 0, 640, 480, SDL_WINDOW_FULLSCREEN);
if (!win) {
printf("Window create failed: %s\n", SDL_GetError());
return -1;
}
SDL_Delay(3000);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
交叉编译后扔到板子上跑。如果屏幕亮了3秒然后退出,说明环境搭建成功。
2.4 整合验证:让 FFmpeg 和 SDL 握手
工具链、FFmpeg、SDL 都装好了,怎么知道它们能协同工作?我习惯写一个最简单的播放器雏形:FFmpeg 解码一帧,SDL 显示一帧。
编译时链接参数要特别注意:
arm-linux-gnueabihf-gcc \
-I/opt/ffmpeg_arm/include \
-I/opt/sdl2_arm/include/SDL2 \
-L/opt/ffmpeg_arm/lib \
-L/opt/sdl2_arm/lib \
test_player.c \
-lavformat -lavcodec -lavutil -lswscale \
-lSDL2 \
-o test_player
把生成的 test_player 拷贝到板子上,运行。如果能看到画面在动,恭喜你,开发环境搭建成功了!
说实话,环境搭建这一步最磨人。但只要你按照上面的步骤来,把每个组件的编译日志都仔细看一遍,基本不会出大问题。后面章节咱们就开始真正写代码了——从打开一个视频文件,到解码、缩放、渲染,一步步把管道搭起来。
嗯,下一章见。