欢迎光临散文网 会员登陆 & 注册

为Raspberry Pi 64bit OS编译可硬件加速的FFmpeg(arm64)

2022-01-18 23:58 作者:28283844972_bili  | 我要投稿

》》》 Hi~ o(* ̄▽ ̄*)ブ 《《《

起因是我去年7月份在b站上偶然看到了这样一个比较有意思的树莓派教学视频:

【树莓派排坑指南】如何为你64位系统的树莓派4B编译可使用硬件编码的FFMPEG

看完之后的我大为震撼,决定多多少少都要做些什么 ( •̀ ω •́ )!因为视频中整个编译过程全部是在Raspberry Pi 4B上面完成的,又恰巧在这不久之前第一次了解到嵌入式交叉编译技术的存在,可以利用计算资源更丰富、性能更强劲的x86平台给其他架构的设备编译软件,所以就在评论区里面请教了一下有关“交叉编译树莓派64位FFmpeg”教程的问题(当时我还没有意思到,想要交叉编译出可以使用特定平台硬件编码ffmpeg需要面临的问题的严重性),视频的UP主也是很有耐心地跟我分析了交叉编译方案的难点所在:

交叉编译不现实,因为很多依赖全部都要交叉编译,太累人。在树莓派上编译的话,可以省去编译很多共享库的时间,只需要编译一个ffmpeg,而且编译硬件解码支持必须要Linux内核头文件,这些都只有官方版系统有,所以交叉编译ffmpeg是不支持硬件编解码的。想要交叉编译好的静态ffmpeg(单文件可运行)的话,可以去ffmpeg官网下载,官方有编译好的。

初生牛犊不怕虎,当时的我对交叉编译这一概念仅仅是停留在理论阶段,并没有实践经验,所以对UP主所说的这段话理解还不够深刻 (〒▽〒),后来我真的尝试去交叉编译可以硬件加速的FFmpeg,然后就没然后了。。。

在交叉编译这条路上碰了一鼻子灰之后,除了在真正的Raspberry Pi 4B平台上编译全过程以外,暂时也没有其他办法。所幸的是,我并不急需要在树莓派上使用FFmpeg,所以有一段时间也没多在意这个事情。直到几天前得到了一位大佬的回复,提供了使用QEMU模拟aarch64环境,同时利用树莓派系统镜像中的RootFS编译FFmpeg的方案,让我有了继续填坑的动力(非常感谢大佬的技术知识分享 ヾ(≧▽≦*)o ),于是在接下来的几天内,我抽空前往大佬的个人博客拜读了相关的技术文章,并完成了全过程的实践验证,这篇专栏才得以公之于众。大佬的个人博客文章链接,供大家参考阅读:https://haruto.zone/post/132

下面我会将实践过程连同遇到的一些问题和解决方案,以及个人的思考感悟分享给大家,一库走!

》》》 (。・∀・)ノ 《《《

在开始之前我先总结性的回答几个问题(权当你还没看过上面的视频和文章,建议先去看一遍视频和博客文章):

  1. 为什么要在树莓派上使用64位系统?

    答:Raspberry Pi 4B搭载了一颗4核心的64bit armv8 SoC,实践证明,在树莓派上使用64位系统的性能发挥与32位系统相比有明显提升,特别是8GB内存容量的树莓派,64位系统能充分利用内存空间。

  2. 为什么要自己编译适用于树莓派64位系统的、可硬件加速的FFmpeg?

    答:从官方64位系统源中直接下载的FFmpeg无法正常使用硬件编解码器(不知道官方现在有没有修复这个问题),会出现偏色等奇怪的问题,总之非常让人头疼,所以要自己手搓FFmpeg。

  3. 我为什么总是执着于在树莓派开发板以外的平台上编译FFmpeg?

    答:也是因为个人“洁癖”,我使用的树莓派系统是raspios-buster-arm64-lite,没有图形界面以及其他额外的软件包,一切从简,而编译FFmpeg不仅需要安装大量额外的dev软件包,还会占用“大量”的存储空间(家境贫寒,我目前在用树莓派SDCard容量仅有16GB)。另外Raspberry Pi 4B虽然在性能上较前一代有了显著提升,但综合来看还是很弱鸡,更何况编译软件是非常消耗设备资源的,所以首选是在其他性能更强劲的平台上编译。

好,答疑结束,准备手搓一个FFmpeg ( •̀ ω •́ )y

再次确认你的树莓派上目前所使用的系统发行版本和硬件架构,并准备好相对应的64位树莓派系统镜像:

树莓派系统镜像可以前往官网或者国内主流镜像站下载,以我的Raspberry Pi 4B为例,基本信息如下,所以我准备的系统镜像是2021-05-07-raspios-buster-arm64-lite.img:

发行版本与硬件架构

本次实践过程中我使用的“宿主机”环境是Ubuntu 20.04.1 LTS amd64虚拟机😂,别问,问就是家境贫寒,被迫套娃。如果条件允许的话,建议还是直接上性能强劲一点的物理机或者云服务器,除非你愿意在编译阶段等上个2~3小时,那还不如直接在树莓派上编译。。。

家境贫寒,告辞!

宿主机命令行下执行以下命令,安装相关的工具,没什么好说的:

觉得多敲几个“sudo”麻烦的话,可以在Root用户模式下执行这些命令,我个人在操作时比较谨慎,基本都是用sudo提权。

继续在宿主机中进行下一项操作,将准备好的树莓派镜像文件与loop设备绑定:

这里可能会遇到一些问题,例如我在验证上述步骤的过程中碰到了loop设备忙的情况,尝试挣扎后无果,于是换成其他的loop设备再做尝试。

loop0设备忙

如果是自己做实验的话,还是得根据自己的实际情况来,必要的时候需要灵活处理遇到的各种突发问题。

将镜像文件绑定到loop1设备上,Unix哲学:没有任何输出的结果才是好结果

想要知道宿主机上有哪些可用的loop设备,可以执行这条命令:

接下来创建两个空的文件目录,用来挂载和转存树莓派镜像文件中的RootFS;接着以只读模式将树莓派镜像中的RootFS挂载到空文件目录;这里的空目录命名并没有固定要求,待挂载的loop设备一定要根据自己的实际情况来,选择p2分区:

为什么是挂载loop设备的p2分区?给树莓派烧录过系统镜像的同学都知道,树莓派系统镜像默认有两个分区,一个是/boot分区,FAT32格式;另外一个是根分区(/),Ext4格式;p1是/boot,p2就是我们需要的RootFS。通过宿主机的资源管理器我们也可以验证上述猜想:

挂载后可以正常访问树莓派镜像中RootFS内容

将挂载目录下RootFS全部内容转存到准备好的空目录当中。比较奇怪的是,在博客文章中有以下描述:

这里必须使用mv来代替复制,如果使用cp命令会丢失文件的suid导致sudo等功能报废

我大致能理解作者的用意了,这里所说的“丢失suid导致sudo不能正常使用”,指的是在QEMU模拟树莓派环境中无法正常使用,所以在实际操作中选择了遵从原文以验证结果。那么我之所以觉得奇怪是因为当初在挂载镜像的时候选择了只读模式,mv一般是用作重命名或移动文件内容,虽然最终结果是验证通过的,但逻辑上多少有点别扭(强迫症害死人!😓)。

于是待整个实验结束后,我重新验证了cp结果,稍做调整能够保留文件原始属性,让sudo等功能正常使用,选项参数的具体含义可自行查阅:

*  2> /dev/null 是重定向错误输出信息到“设备黑洞”,忽略错误信息在屏幕上输出的意思,可选

耐心等待文件转存完毕之后,根据自己的实际情况卸载并解绑loop设备。至于本项第2条命令以及之后删除镜像文件,普通人随意,强迫症必备:

至此,在宿主机上的准备工作已全部准备完毕,可以起身去喝杯养身茶稍作休息了(正在播放 饮茶哥.mp3)

》》》 o(*^▽^*)┛ 《《《

书接上文,在正式进入QEMU模拟aarch64环境的容器之前,当然需要在宿主机上启动容器了(废话),这也是最后一条需要在宿主机中执行的操作,之后如果没有特别提醒,全部是在容器中完成。博客原文如下:

#可以使用快捷键ctrl+a+d暂时离开

#可以使用命令screen -r build重新回到控制台

screen -S build systemd-nspawn -D rpi-env --hostname=raspberrypi --user=pi

这条命令可以拆分成两段来看,前半段是screen -S build,使用多重视窗管理工具创建了一个名为build的作业视窗,文章博主使用的是远程连接到云服务器进行编译,谁也不想在编译中途因为意外断开连接而重新来过对吧?后半段才是启用容器的执行操作,虽然是进入到作业视窗之后执行的操作,但此时依旧是在宿主机环境中,只有等容器完全启用后,才算是真正意义上进入到容器模拟的环境中。如果你是远程连接或者想要在编译的同时执行其他工作的话,建议加上screen,否则可以直接执行:

具体含义不用我解释,基本都能猜到。不出意外的话出现以下内容则说明成功启用容器并进入到模拟环境中。

只是模拟出来的aarch64环境,内核实际上用的还是宿主机的,妥妥的缝合怪

按照流程接下来是更新软件源,然后获取相关的软件依赖库、工具包,不过博主开篇有提示说在执行这一步操作时国内的网络会比较糟心:

推荐在境外服务器进行编译,国内由于网络问题非常蛋疼

非常贴心的提醒,事实证明也是如此。所以有多余闲钱的话,还是租个综合性能不错的境外服务器耍耍比较好,如果跟我一样家境贫寒的话建议考虑换源。虽然这是个模拟出来的aarch64平台环境,但好歹也是用了树莓派系统的RootFS,所有的操作是依靠arm转译给宿主机内核执行的(就是这个转译效率确实挺感人的),理论上和在真实的树莓派系统环境下没多大差别。按照给树莓派换源的步骤操作就行,没多大难度。

以我实际操作为例全部替换为中国科技大学的镜像源,注意需要修改两个软件源文件,特别是raspi.list中的内容一定要修改成对应的国内镜像源(不然你会后悔的,很多树莓派专有的软件依赖包都要根据这个源获取):

遇事不决先换源

另外,中科大镜像站里面有关Debian软件源配置的帮助文档中提供了一个非常好用的工具,能够快速根据自己的发行版本生成相应的软件源配置内容:

给站长和snullp大叔点个赞!q(≧▽≦q)
一定要根据自己的发行版本来配置软件源哦!其他Linux发行版本的软件源配置也可以来试试!

换完软件源之后,正常执行更新和获取操作,等待时间的多少取决于你的网络状况(谁想要交叉编译的快过来看看!至少lib打头依赖库和工具包都需要自己交叉编译!。。。哦原来是我,那没事了):

源码编译没源码包怎么行呢?前往FFmpeg的官网下载最新的stable版本源码包;喜欢“追新”的同学可以下载snapshot版本,但不建议用于生产环境。以我的为例,下载的是代号为“Rao” FFmpeg4.4.1的稳定版本,解压tar.xz使用 -J 选项,解压tar.bz2使用 -j 选项,解压tar.gz使用 -z 选项:

进入到源码包根目录之后,就可以开始进行configure配置和编译工作了,编译选项配置如原文所示,--prefix是编译好之后软件包的安装路径,不用默认配置是方便打包;如果只是需要编译FFmpeg,继续添加 --disable-ffprobe--disable-ffplay 这两个编译选项;更多编译选项请参考 ./configure --help

因为需要arm转译执行,所以执行配置编译选项这一环节会花个3~4分钟(看你的平台性能,就算是虚拟机建议资源配置也尽量多给一点),中间不报错,最后出配置成功的结果就行。

开始编译,-j 选项要不要加?加多少?请谨慎考虑,arm转译真的很吃CPU资源:

少女祈祷中……

等待编译完成大概需要2~3小时(取决于你的平台性能),如果没其他什么事的话,建议去看一会儿番剧、一部电影或者小睡一会儿什么的。除非在编译过程意外中断,需要排查错误。。。 (╯‵□′)╯︵┻━┻

编译并安装完成后,前往你的prefix安装路径,可以先在模拟环境下测试一下编译出来的软件是否可用:

编译生成的二进制文件本体
新鲜出炉的FFmpeg在模拟环境下能够正常使用

接下来就可以退出容器模拟环境,进入宿主机操作了,从转存树莓派系统RootFS的文件目录中拷贝出编译好的安装文件,就是prefix指定的目录,打包发送到树莓派准备实战演示,可以用scp工具。啊,忘记说了,退出容器和多任务视窗直接执行exit即可

》》》 \(0^◇^0)/ 《《《

当你迫不及待地想要在树莓派上使用刚刚编译好的FFmpeg的时候,大概率会获得一个错误提示,缺少一些必要的共享库!解决方法也很简单,直接回到刚刚的RootFS把需要的共享库一个一个拷贝出来、转存到树莓派的/usr/lib/aarch64-linux-gnu/目录中

当然是先检查一下缺少哪些共享库,以我的实际情况为例,进入FFmpeg软件本体所在目录:

具体显示结果因实际情况而异!

然后在树莓派上按需获取对应的依赖库软件包,和编译的时候不同,这里我们只取所需,dev开发工具包中额外的内容都是不需要,最小化安装:

如果还缺少其他依赖库,可以自行百度(找规律,特别是共享库名称与软件包的联系,应该很容易就能总结出规律),有时候只要解决一个依赖库可以连同解决多个,apt工具很智能。

这样子依赖库的问题就解决了

下面正式进入实战,这里准备了一个时长00:01:30的视频文件test.mp4,大小为13MB左右;树莓派为GPU划分的内存大小为128MB:

首先是使用软件解码器和CPU进行软编码,用了将近1分钟的时间完成测试:

接下来是使用GPU硬件解码器与编码器进行测试,用时大约12.5秒完成,证明编译得到的FFmpeg能够利用树莓派平台的GPU硬件加速:

终于,我们通过在非树莓派平台上编译出了支持arm64系统、可硬件加速的FFmpeg,完结撒花! ヽ(。・∀・)ノ✿

番外篇

还记得我最开始说想要交叉编译一个可支持树莓派硬件加速的FFmpeg计划吗?试过,最后“有幸”获得了一件失败品! (¬_¬")

你别看它现在还能活蹦乱跳的,实际上已经凉了

当我得知要从头交叉编译各种依赖库、手动配置头文件的时候,作为初学者基本上已经放弃了,所以只尝试了交叉编译其中两个依赖库libx264libsdl2-2.0,在交叉编译过程中解决的各种蜜汁报错且不说,各种配置以及查阅文档就让人头大得不得了,实在是划不来,大家就看个乐呵吧。

--enable-small    optimize for size instead of speed
硬件加速完全不能用(苦笑)

虽然把玩树莓派只是我的业余兴趣,不过说到底还是自己的能力有限,第一次接触到交叉编译和QEMU虚拟机,所以对这方面的知识积累基本没有,本文有些地方肯定还有我个人的误解和疏漏,欢迎有懂行的大佬批评指正。

貌似我可以学习一下QEMU,因为我感觉要发现新大陆了…… (¬‿¬)


推荐观看/阅读:

参考资料:

  • https://www.bilibili.com/video/BV14U4y1V7CE

  • https://haruto.zone/post/132

  • https://holmesian.org/Raspberry-Pi-optimized-FFmpeg-with-HW-Acceleration

  • https://ffmpeg.org/

  • https://mirrors.ustc.edu.cn/help/debian.html

  • https://mirrors.ustc.edu.cn/repogen


为Raspberry Pi 64bit OS编译可硬件加速的FFmpeg(arm64)的评论 (共 条)

分享到微博请遵守国家法律