2、开发环境搭建:安装交叉编译工具链、配置Android NDK或Yocto SDK,验证硬件编解码节点(/dev/video*)
好,咱们正式开始动手了。
这一章,说白了就是给你的电脑装上「翻译官」和「工具箱」。你想想看,我们写的代码是在x86电脑上,但最终要跑到ARM架构的Exynos芯片上。这中间差了十万八千里,没有交叉编译工具链,代码根本跑不起来。
2.1 交叉编译工具链——为什么非得用这个?
我刚开始接触嵌入式开发时,也犯过傻。直接在Ubuntu上用gcc编译了一个hello world,然后兴冲冲地拷贝到开发板上,结果执行时提示「无法执行二进制文件」。嗯,当时我还以为是板子坏了。
其实原因很简单:你的电脑是x86架构,Exynos是ARM架构。两种CPU的指令集完全不同。交叉编译工具链,就是让你在x86电脑上生成ARM可执行文件的桥梁。
核心概念:交叉编译工具链 = 编译器 + 链接器 + 库文件,全部针对目标架构(ARM)定制。
我个人习惯用Linaro提供的工具链,稳定且社区支持好。对于Exynos平台,我建议你下载gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf这个版本。为什么选这个?我在项目中踩过坑,太新的工具链有时会和内核驱动有兼容性问题,这个版本经过大量验证,稳得很。
安装步骤其实很简单:
- 下载工具链压缩包
- 解压到
/opt/toolchains/目录 - 配置环境变量
PATH
# 下载(以Linaro 7.5为例)
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压
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
# 验证
arm-linux-gnueabihf-gcc --version
小技巧:我个人习惯在 /opt/toolchains/ 下建一个 current 软链接,指向当前使用的工具链版本。这样切换版本时只需要改软链接,不用改环境变量。
2.2 配置Android NDK——如果你用安卓系统
如果你的Exynos平台跑的是Android系统,那事情就简单一些了。Android NDK本身就是一套完整的交叉编译环境,而且Google已经帮你把坑填得差不多了。
我曾经在一个项目里,直接用NDK编译了一个视频解码库,扔到Exynos 9820的板子上,一次就跑通了。说实话,当时我自己都有点意外。
配置步骤:
- 下载Android NDK(推荐r21e或更高版本)
- 解压到本地目录
- 使用
ndk-build或cmake工具链文件
# 下载NDK
wget https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip
unzip android-ndk-r21e-linux-x86_64.zip -d ~/android-ndk
# 使用CMake工具链文件
cmake -DCMAKE_TOOLCHAIN_FILE=~/android-ndk/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-28 \
..
注意:Exynos芯片的MFC(Multi-Format Codec)硬件编解码器,在Android下是通过HAL层暴露的。如果你直接用NDK编译的代码去操作 /dev/video* 节点,可能会遇到权限问题。我曾经被这个坑过——明明节点存在,但open()返回-1。后来发现是SELinux策略在作怪。
2.3 配置Yocto SDK——如果你用嵌入式Linux
对于嵌入式Linux场景,Yocto是主流选择。Exynos的官方BSP(Board Support Package)通常也是基于Yocto构建的。
Yocto SDK的好处是:它不光给你编译器,还给你一套完整的头文件和库文件,版本和你的目标系统完全一致。说白了,就是「你编译出来的东西,放到板子上就能跑」,不用再担心库版本不匹配的问题。
配置步骤:
- 从Yocto构建环境生成SDK
- 安装SDK到指定目录
- 运行环境设置脚本
# 在Yocto构建目录下生成SDK
bitbake core-image-minimal -c populate_sdk
# 安装SDK(生成的文件在 tmp/deploy/sdk/ 下)
./poky-glibc-x86_64-core-image-minimal-armv8a-toolchain-*.sh
# 设置环境变量
source /opt/poky/2.7/environment-setup-aarch64-poky-linux
# 验证
$CC --version
我的经验:Yocto SDK安装后,一定要运行那个 environment-setup-* 脚本。它不光设置 CC、CXX 这些变量,还会设置 PKG_CONFIG_PATH,这样你编译依赖库时,pkg-config能自动找到正确的头文件和库路径。我第一次用Yocto时没注意这个,结果编译ffmpeg时死活找不到libavcodec的头文件,折腾了一下午。
2.4 验证硬件编解码节点——/dev/video* 的秘密
好了,工具链装好了,接下来要确认你的Exynos板子上,硬件编解码器是不是活着的。
在Exynos平台上,硬件编解码器通常以V4L2(Video for Linux 2)设备节点的形式暴露。你会在 /dev/ 目录下看到 video0、video1 这样的文件。但注意,不是所有的 /dev/video* 都是编解码器——有些是摄像头,有些是M2M(Memory to Memory)设备。
怎么区分?我教你一个方法:
# 查看所有video设备
ls -l /dev/video*
# 使用v4l2-ctl查看设备能力
v4l2-ctl -d /dev/video0 --all
# 或者用media-ctl查看拓扑
media-ctl -p -d /dev/media0
对于Exynos的MFC硬件编解码器,你通常会看到类似这样的输出:
Driver name : s5p-mfc
Card name : s5p-mfc-dec
Bus info : platform:11000000.codec
Driver version : 5.10.9
Capabilities : 0x84204000
Video Memory-to-Memory
Streaming
Device Capabilities
Device Caps : 0x04204000
Video Memory-to-Memory
Streaming
看到 s5p-mfc 和 Video Memory-to-Memory 了吗?这就是我们要找的硬件编解码器。
关键点:Exynos的MFC设备通常有两个节点:一个用于解码(dec),一个用于编码(enc)。比如 /dev/video10 是解码器,/dev/video11 是编码器。具体编号因内核配置而异,但规律是一样的。
2.5 写一个简单的测试程序——验证一切就绪
光说不练假把式。我们来写一个最简单的C程序,验证交叉编译环境和硬件节点是否都正常。
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
int main() {
int fd = open("/dev/video10", O_RDWR);
if (fd < 0) {
perror("open /dev/video10 failed");
return -1;
}
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
perror("VIDIOC_QUERYCAP failed");
close(fd);
return -1;
}
printf("Driver: %s\n", cap.driver);
printf("Card: %s\n", cap.card);
printf("Bus info: %s\n", cap.bus_info);
close(fd);
return 0;
}
用交叉编译器编译:
arm-linux-gnueabihf-gcc -o test_video test_video.c
然后把 test_video 拷贝到板子上,运行。如果看到类似上面的驱动信息,恭喜你——环境搭建成功了!
避坑指南:我曾经在Exynos 5422板子上遇到一个怪事——/dev/video10 明明存在,但open()总是返回权限错误。后来发现是内核配置里把MFC的节点权限设成了600(仅root可访问)。解决方案是修改udev规则,或者用 chmod 666 /dev/video10 临时解决。嗯,这个问题在量产时一定要处理好,不然你的App会崩溃得很惨。
2.6 本章小结
这一章我们做了三件事:
- 安装了交叉编译工具链,让你的x86电脑能编译ARM代码
- 配置了Android NDK或Yocto SDK,根据你的系统选择
- 验证了
/dev/video*节点,确认硬件编解码器在线
说实话,环境搭建是最枯燥的部分,但也是最重要的。我见过太多人一上来就写编解码代码,结果发现工具链不对、节点打不开,白白浪费几天时间。所以,请务必按照本章的步骤,一步一步验证通过。
下一章,我们就要真正开始操作MFC硬件编解码器了。我会带你写第一个V4L2的编解码程序,让你亲眼看到硬件加速的效果。准备好了吗?
公众号:蓝海资料掘金营,微信deep3321