编译Android平台FFMPEG库

一、FFMPEG简介

FFmpeg即是一款音视频编解码工具,同时也是一组音视频编码开发套件,作为编码开发套件,它为开发者提供了丰富的音视频处理的调用接口。
FFmpeg提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种多彩格式转换、多种采样率转换、多种码率转换等;FFmpeg框架提供了多种丰富的插件模块,包含封装与解封装的插件、编码与解码的插件等。

引用自:https://blog.csdn.net/Mr_robot_strange/article/details/109966774

二、FFMPEG模块组成

FFmpeg框架的基本组成包含AVFormat、AVCodec、AVFilter、AVDevice、AVUtil等模块库,结构图如下:
在这里插入图片描述

2.1 AVFormat–FFmpeg的封装模块

AVFormat中实现了目前多媒体领域中的绝大多数媒体封装格式,包括封装和解封装,如MP4、FLV、KV、TS等文件封装格式,RTMP、RTSP、MMS、HLS等网络协议封装格式。FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。

2.2 AVCodec–FFmpeg的编解码模块

AVCodec中实现了目前多媒体领域绝大多数常用的编解码格式,即支持编码,也支持解码。AVCodec除了支持MPEG4、AAC、MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.264(AVC)编码,需要使用x264编码器;H.265(HEVC)编码,需要使用x264编码器;MP3(mp3lame)编码,需要使用libmp3lame编码器。如果希望增加自己的编码格式,或者硬件编解码,则需要在AVCodec中增加相应的编解码模块。

2.3 AVFilter–FFmpeg的滤镜模块

AVFilter库提供了一个通用的音频、视频、字幕等滤镜处理框架。在AVFilter中,滤镜框架可以有多个输入和多个输出。

2.4 swresample–FFmpeg的音频转换计算模块

swresample模块提供了高级别的音频重采样API。例如允许操作音频采样、音频通道布局转换与布局调整。

2.5 swscale–FFmpeg的视频图像转换计算模块

swscale模块提供了高级别的图像转换API,例如它允许进行图像缩放和像素格式转换,常见于将图像从1080p转换成720p或者480p等的缩放,或者将图像数据从YUV420p转换成YUYV,或者YUV转RGB等图像格式转换。

引用自:https://blog.csdn.net/Mr_robot_strange/article/details/109966774

三、FFMPEG编译

在开发中,需要使用到FFMPEG的解封装功能,所以要将FFMPEG的源码编译成可以供上层调用的so库,集成到android系统源码中。因此要学习和了解FFMPEG编译的相关知识。
首先,在进行FFMPEG编译之前,需要了解一些必要知识点。
如何将FFMPEG编译成so库?
FFMEPG是属于第三方代码,android平台编译第三方C/C++代码最通用的解决的方案是利用Android NDK的工具链进行交叉编译。
那么什么是交叉编译呢?
在宿主机上编译,在目标机上执行。从事嵌入式系统或者单片机朋友再熟悉不过了。所有的嵌入系统都是在PC机上编译(宿主机),在单板上执行(目标机)。也就是在一个平台上生成另一个平台上的可执行代码,再简单来说,就是在一个机器上生成一个程序,这个程序可以跑在另外一个机器上。
因为PC上的环境和手机上的运行环境是绝然不同的,所以,交叉编译最重要的是,要配置好编译过程中使用到的相关的环境,而这个环境其实就是目标机器(比如Android手机)正在运行的环境。
对于C/C++的编译,通常有两个工具 GCC 和 CLANG 。
GCC 可能大家都有听说过,这是一个老牌的编译工具,不仅可以编译C/C++,也可以编译Java,Object-C,Go等语言。
CLANG 则是一个效率更高的C/C++编译工具,并且兼容GCC,Google在很早以前就开始建议使用clang进行编译,并且在 ndk 17 以后,把 GCC 移除了,全面推行使用 CLANG 。

那么,介绍完基本的知识点之后,现在开始正式讲解FFMPEG编译的内容。

3.1 下载Android NDK

需要使Google提供的NDK,将FFMPEG源码编译成Android可以调用的so.
下载地址:https://developer.android.google.cn/ndk/downloads?hl=zh_cn
因为我是在linux环境下编译的,所以这里下载对应的软件包
在这里插入图片描述
配置NDK环境变量
将下载下来的NDK包,解压至对应的路径,然后复制相应的路径。
打开终端,输入下面的命令

vim ~/.bashrc

翻到文件的末尾,按i键进入编辑模式,输入

export NDK_HOME=刚才复制的path
export PATH=$NDK_HOME:$PATH

在这里插入图片描述
然后按ESC键退出编辑模式,输入:wq回车,保存修改内容。
退出vim后,使用命令

source ~/.bashrc

使改动生效,至此,ndk的环境变量就配置好了。

3.2 下载FFMPEG源码

下载网址:http://ffmpeg.org/download.html
在这里插入图片描述

3.3 编辑修改配置文件

下载好源码后,进入根目录,找到一个名为 congfigure 的文件,这是一个shell脚本,用于生成一些 FFmpeg 编译需要的配置文件,如下图所示。
这个文件非常重要,FFmpeg 的编译配置就是靠它完成的。 后面我们将对其中一些重要的内容进行分析,这是理解 FFmpeg 编译配置的关键。
在这里插入图片描述
旧的版本会让修改configure文件中的如下部分,是为了生成Android可以使用的so。原因如下:
Android 工程中只支持导入 .so 结尾的动态库,形如:libavcodec-57.so 。但是 FFmpeg 编译生成的动态库默认格式为 xx.so.版本号 ,形如:libavcodec.so.57 , 所以需要修改 FFmpeg 根目录下的 configure 文件,使其生成以 .so 结尾格式的动态库。修改方法为:

# 将 configure 文件中 build settings 下的:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' 
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"' 
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' 
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

#替换为:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

但在新版本上已经好像不用再这样修改了,如果编译出来的so库的后缀不符合要求的话,可以使用上面的方法修改configure文件。

除此之外,因为Google 在新版ndk把 GCC 移除了,全面推行使用 CLANG,所以我们需要把编译工具配置进行修改。修改流程如下:
1.新增 cross_prefix_clang 参数
我们可以搜索 CMDLINE_SET ,可以找到以下代码,然后新增一个命令行选项:cross_prefix_clang
在这里插入图片描述
2.修改编译工具路径设置
我们可以搜索 ar_default=“ c r o s s p r e f i x {cross_prefix} crossprefix{ar_default}” , 找到以下代码:

ar_default="${cross_prefix}${ar_default}"

cc_default="${cross_prefix}${cc_default}"

cxx_default="${cross_prefix}${cxx_default}"

nm_default="${cross_prefix}${nm_default}"

pkg_config_default="${cross_prefix}${pkg_config_default}"

将中间两行修改为:

ar_default="${cross_prefix}${ar_default}"
#------------------------------------------------
cc_default="${cross_prefix_clang}${cc_default}"
cxx_default="${cross_prefix_clang}${cxx_default}"
#------------------------------------------------
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"

引用自:https://cloud.tencent.com/developer/article/1773965

3.4 编辑编译脚本

FFmpeg 已经为我们准备好了 Makefile 可以直接用于建构,还为我们提供了 configure 程序可以调节编译的设置,configure 提供许多参数可供选择,如编译模块,目标平台、编译工具链等等,通常的做法是编写一份脚本进行设置与建构
关于configure的参数含义,可参考:https://cloud.tencent.com/developer/article/2246778?areaSource=106000.5&traceId=EmVuSa-xvaoG4O5f0IpFQ

在ffmpeg路径下,新建一个名为"build_android.sh"的脚本,编译脚本内容如下:

#!/bin/bash
set -x
# 目标Android版本
API=29
ARCH=arm64
CPU=armv8-a
TOOL_CPU_NAME=aarch64
#so库输出目录
OUTPUT=$(pwd)/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/home/gec/Documents/FFMPEG/NDK/android-ndk-r25c-linux/android-ndk-r25c
# 编译工具链路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
# 编译环境
SYSROOT=$TOOLCHAIN/sysroot

TOOL_PREFIX="$TOOLCHAIN/bin/$TOOL_CPU_NAME-linux-android"
 
CC="$TOOL_PREFIX$API-clang"
CXX="$TOOL_PREFIX$API-clang++"
OPTIMIZE_CFLAGS="-march=$CPU"
function build
{
  ./configure \
  --prefix=$OUTPUT \
  --target-os=android \
  --arch=$ARCH  \
  --cpu=$CPU \
  --disable-asm \
  --enable-neon \
  --enable-cross-compile \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --cc=$CC \
  --cxx=$CXX \
  --sysroot=$SYSROOT \
  --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
  --disable-vulkan \
  --disable-stripping

  make clean all
  # 这里是定义用几个CPU编译
  make -j8
  make install
}
build

注意,以上编译脚本内容不是一成不变的,不可以直接照抄,要根据自己的实际情况进行修改。
注意修改下面的部分。
在这里插入图片描述
如果想要确认android平台的CPU架构,可使用以下命令

adb shell getprop ro.product.cpu.abi

对于几个参数的介绍
target-os
–target-os=android:在旧版本的 FFmpeg 中,对Android平台的支持并不是很完善,并没有 android 这个target,所以在一些比较老的文章中都会提到,编译Android平台的so库,需要对 configure 做以下修改,否则会按照 linux 标准的方式输出so库,其命名方式和Android的so不一样,Android是无法加载的,就是之前说的问题。
sysroot
–sysroot=$SYSROOT: 用于配置交叉编译环境的 根路径 ,编译的时候会默认从这个路径下去寻找 usr/include usr/lib 这两个路径,进而找到相关的头文件和库文件。
r20b 版本的 NDK 系统的头文件和库文件就是在 $SYSYROOT/usr/include 和 $SYSYROOT/usr/lib 中。
基本上很多新手在编译的时候都会出现找不到各种头文件,导致编译失败。所以当编译出现找不到头文件的时候,首先要检查的就是这个路径。

3.5 运行脚本

执行下方的命令

 ./build_android.sh

如果有提示权限问题,可以加上sudo

 sudo ./build_android.sh

3.6 踩过的坑

1.如果有遇到一些没有安装相应的工具报错
可以先更新一下包列表

sudo apt update

然后检查一下是否有安装如下的编译软件

sudo apt install autoconf \
automake \
build-essential \
cmake \
git-core \
libass-dev \
libfreetype6-dev \
libgnutls28-dev \
libmp3lame-dev \
libsdl2-dev \
libtool \
libva-dev \
libvdpau-dev \
libvorbis-dev \
libxcb1-dev \
libxcb-shm0-dev \
libxcb-xfixes0-dev \
meson \
ninja-build \
pkg-config \
texinfo \
wget \
yasm \
zlib1g-dev \
libunistring-dev \
libaom-dev \
libdav1d-dev \
pkg-config

2.查看相关log
进到ffbuild找到config.log并打开,拉到最下方,可以看到以下报错详情:
在这里插入图片描述

3.遇到如下编译报错Unable to recognise the format of the input file

STRIP	install-libavdevice-shared
strip: Unable to recognise the format of the input file `/home/gec/Documents/FFMPEG/SourceCode/ffmpeg-6.0/android/armv8-a/lib/libavdevice.so'
make: *** [ffbuild/library.mak:120: install-libavdevice-shared] Error 1

在网上查找资料,遇到这种错误的原因,是因为宿主机和编译的目标所使用的strip不是同一个导致的,可以使用type strip命令查看。
在这里插入图片描述

但是没有从根本去解决问题,了解到strip是用于优化编译的,我是在脚本文件中添加了–disable-stripping解决的

参考

https://zhuanlan.zhihu.com/p/580515740
https://cloud.tencent.com/developer/article/1773965
https://blog.csdn.net/yonghuming_jesse/article/details/127244553
https://blog.csdn.net/qq_42612119/article/details/121238236
https://blog.csdn.net/fengliang191/article/details/119858225
https://blog.csdn.net/Mr_robot_strange/article/details/109966774

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Android平台编译FFmpeg,需要先安装NDK(Native Development Kit)和Android SDK(Software Development Kit)。然后,可以按照以下步骤进行编译: 1. 下载FFmpeg源代码,并解压缩。 2. 打开终端或命令行窗口,进入FFmpeg源代码目录。 3. 设置NDK路径和SYSROOT路径: ``` export NDK=/path/to/ndk export SYSROOT=$NDK/platforms/android-<platform-version>/arch-<arch>/ ``` 其中,`<platform-version>`和`<arch>`需要根据实际情况进行替换,例如: ``` export SYSROOT=$NDK/platforms/android-21/arch-arm/ ``` 4. 设置交叉编译器路径: ``` export CROSS_PREFIX=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android- ``` 其中,`darwin-x86_64`需要根据实际情况进行替换,例如: ``` export CROSS_PREFIX=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi- ``` 5. 配置FFmpeg: ``` ./configure \ --prefix=$PREFIX \ --enable-shared \ --disable-static \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-postproc \ --disable-avdevice \ --disable-swscale \ --disable-avfilter \ --disable-network \ --disable-iconv \ --disable-bsfs \ --disable-demuxers \ --disable-muxers \ --disable-indevs \ --disable-outdevs \ --arch=<arch> \ --target-os=android \ --cross-prefix=$CROSS_PREFIX \ --sysroot=$SYSROOT \ --extra-cflags="-Os -fpic -marm" \ --extra-ldflags="-shared" ``` 其中,`<arch>`需要根据实际情况进行替换,例如: ``` --arch=arm ``` 6. 编译FFmpeg: ``` make -j4 make install ``` 其中,`-j4`表示使用4个线程进行编译编译完成后,可以在`$PREFIX/lib`目录下找到编译好的FFmpeg文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值