文章目录
1.项目介绍
板子:正点原子RK3588开发板
SDK:正点原子官方提供,正点原子RK3588开发板 — 正点原子资料下载中心 1.0.0 文档
交叉工具编译链:gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu
编程语言:c/c++
cmake: 3.22.1
os:ubuntu22.04(wsl2)
本项目是在PC上搭建交叉编译环境进行编译最后将程序部署在板子端,功能为:应用层使用ffmpeg+rkmpp插件对h.264格式的mp4进行硬解码,然后将得到的AV_PIX_FMT_DRM_PRIME格式帧使用DRM框架进行渲染显示。
题外话,市面上流行的共有三套方案:
(1)ffmpeg使用CPU进行软解,占用cpu资源高,但是稳定;
(2)ffmpeg进行解封装,然后使用瑞芯微提供的mpp框架进行硬解码;
(3)ffmpeg+rkmpp硬解码。
其实2跟3的原理是差不多,只是3把官方的mpp杂糅进了ffmpeg里面。经过实测下来方案三在稳定性上更胜一筹,并且使用流程和ffmpeg一致,基本没有再学习成本。
2.项目文件架构介绍
├───3rd :使用的第三模块,包括mpp、DRM、ffmpeg、x264、opencv、
├───install/ :交叉编译生成的头文件和库
├───source/ :第三模块的源代码
├───example :参考代码,大部分是单独模块的实现和测试
├──drm-howto/ :DRM的原子操作示例
├──drm-test/ :DRM的测试
├─── drm_atomic_ctrc.c :最简单的DRM 原子操作,不使用plane,使单颜色铺满屏幕
├─── drm_atomic_plane.c:使用plane的DRM原子操作,使单颜色铺满屏幕
├─── drm_atomic_jpg.c:使用opencv和plane显示一张jpg图片到屏幕上
├─── drm_test.c : 不使用原子操作,用最原始的方式(已过时)使用DRM框架显示彩色方块
├──ffmpeg_player/ :ffmpeg+sdl2实现最简单的播放视频,想了解使用ffmpeg流程的可以查阅
├───source:项目的DRM显示和ffmpeg解码渲染源代码,也是最关键的代码
├───drmDisplay.cpp:DRM相关的操作和对象
├───drmDisplay.h
├───ffmpegPlayer.cpp:ffmpeg相关的操作和对象
├───ffmpegPlayer.h
├───toolchain:交叉编译工具链放置地点
├───main.cpp:程序的入口函数
...
3.使用说明
由于gitee对个人用户git-lfs有限制不能上传大文件,所以交叉编译工具链无法上传,不过大家的板子不一样,SDK不一样,使用的编译链也不一样,就算上传了用处也不大hhh。所以程序要运用到各自的板子上的话要重新配置交叉编译工具链,使用你们的交叉工具链重新编译对应模块,再编译链接成可执行程序。
(1) 拉取源码
git clone https://gitee.com/freecry039/ffmpeg_rkmpp_drm.git
cd ./ffmpeg_rkmpp_drm
(2) 更新子模块,获取第三方官方库
git submodule update --init --recursive
(3) 重新编译第三方库:
参考第四章节的内容
(4) 创建build目录编译生成对应的执行文件
mkdir ./build
cd build
cmake ..
make -j36
(5)在项目根目录下会出现bin目录,里面会生成main.exe执行程序,/path/to/ffmpeg-rkmpp-drm/bin/main/.exe,将其使用u盘或者frp等拉取到板子上运行即可。
4.交叉编译介绍
嵌入式系统通常由具有特殊硬件架构的处理器(如ARM、MIPS等)组成,而这些处理器的架构和常见的桌面计算机(如x86、x64)有所不同。为了在嵌入式设备上运行程序,我们需要将程序从PC上编译成适用于嵌入式目标平台的代码。这个过程就叫做交叉编译。
其实可以简单这样理解,你必须使用你编译sdk时使用的交叉编译工具链去编译目标程序,目标程序才能正常跑在板子上。
4.1 查找对应的交叉编译工具链
厂商一般会提供对应的sdk给用户去编译烧录进板子,那么他们肯定会提供对应的交叉编译工具链的,以正点原子rk3588为例,在官方提供的说明文档中介绍了交叉编译工具链就在prebuilts文件夹下面。
在找到对应的交叉编译工具链之后直接复制整个交叉编译工具链到项目目录下的toolchain文件夹下面,正点原子的目录如下:
cp -rf /path/to/toolchain /path/to/ffmpeg_rkmpp_drm/toolchian
然后声明交叉编译工具链的环境变量
export PATH=/path/to/ffmpeg_rkmpp_drm/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH
如果声明成功的话在终端输入交叉编译的前缀然后按TAB键会出现提示
然后执行会有相对于输出
aarch64-none-linux-gnu-gcc -v
4.2 交叉编译对应模块
如果不是和本项目一样的环境,那么需要重新编译不同模块。先把项目下对应已经编译好的模块删掉,在项目根目录下执行以下命令
rm -rf ./3rd/install/mpp/* ./3rd/install/ffmpeg/* ./3rd/install/libdrm/* ./3rd/install/opencv/* ./3rd/install/x264/*
因为ffmpeg的交叉编译依赖其他模块,所以要先编译完其它四个模块最后再编译ffmpeg
4.2.1 交叉编译libdrm
进入到libdrm的源码之中
cd ./3rd/source/libdrm-2.4.123/
创建build文件夹
mkdir ./build
创建cross_file.txt文件,用于配置 meson
交叉编译 libdrm
库。这些配置文件指定了交叉编译所需的工具链、目标平台(嵌入式平台)和构建平台(开发平台)的信息。
touch ./cross_file.txt
打开cross_file.txt文件填上以下内容,如果是不同的交叉编译工具链记得把[binaries]下面的对应选项更换成你们的编译链名称,其他照抄即可
[binaries]
c = 'aarch64-none-linux-gnu-gcc'
cpp = 'aarch64-none-linux-gnu-g++'
ar = 'aarch64-none-linux-gnu-ar'
strip = 'aarch64-none-linux-gnu-strip'
[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv8'
endian = 'little'
[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
[project options]
install-test-programs = 'true'
进入之前创建好的build目录下使用 meson
构建系统来配置并构建一个项目
cd ./build
meson --prefix=$(pwd)/../../../install/libdrm/ --cross-file=../cross_file.txt -D exynos=enabled
–prefix 选项指定了项目构建后的安装路径。这里使用了 $(pwd),它是一个 shell 命令,表示当前工作目录的路径(即你运行命令时所在的目录),命令让它指向了ffmpeg_rkmpp_drm/3rd/install/libdrm/
–cross-file 选项告诉 Meson 使用指定的交叉编译配置文件进行构建。…/cross_file.txt 是一个相对路径,指向当前目录的上一级目录中的 cross_file.txt 文件
-D是配置是否编译对应功能的,可加可不加
执行ninja命令进行编译和安装
ninja && ninja install
命令执行完后发现已经生成对应的头文件和库
也可以使用file命令查看一下对应的.so文件的架构来确认是否交叉编译成功
file libdrm.so.123.0*
4.2.2 交叉编译mpp
本项目使用的是https://github.com/rockchip-linux/mpp仓库,在编译时使用的日志编号是aaa4c8e9(当时最新),也是项目的子模块里面链接的分支,使用git submodule update --init --recursive
可以拉取。
进入到mpp的源码之中
cd ./3rd/source/mpp/
进入对应的build文件夹
cd ./build/linux/aarch64/
按照自己的环境修改make-Makefiles.bash文件,主要是下面标注的两个选项,第一个为交叉编译链的名称,第二个为交叉编译链的路径
修改arm.linux.cross.cmake文件,也是修改为对应的交叉工具链,下面是运行平台,rk3588的话就写aarch64即可
修改完毕后直接执行脚本</