首先列出本次编译所需要的环境和源码版本:
- 编译环境:VMware-15.5.6 + ubuntu-20.04.2.0
- 编译工具:android-ndk-r22b
- FFmpeg源码:ffmpeg-4.1.6
1. 搭建编译环境
1.1 安装Ubuntu
在Windows10电脑安装VMware,创建新的虚拟机Ubuntu,到官网下载需要版本安装即可,安装完成后执行以下命令:
apt-get update
apt-get install yasm
apt-get install pkg-config
-
apt-get install make
如果安装失败,解决办法根据提示,加sudo,如:sudo apt-get install make
1.2 下载ndk
在/home下新建ffm文件夹,将ndk下载到 /home/ffm/目录下:
wget https://dl.google.com/android/repository/android-ndk-r22b-linux-x86_64.zip
下载完成后解压:
unzip android-ndk-r22b-linux-x86_64.zip
1.3 下载FFmpeg
将FFmpeg下载到 /home/ffm/目录下:
wget http://www.ffmpeg.org/releases/ffmpeg-4.1.6.tar.gz
下载完成后解压:
tar -zxvf ffmpeg-4.1.6.tar.gz
2. 编译FFmpeg
在开始编译FFmpeg之前,先简单介绍下交叉编译。引自百度百科的定义:交叉编译是在一个平台上生成另一个平台上的可执行代码,这里即是在Linux平台编译出Android平台可以使用的FFmpeg so库。
对于C/C++的编译,通常有两个工具 GCC 和 CLANG 。
- GCC,是一个老牌的编译工具,不仅可以编译C/C++,也可以编译Java,Object-C,Go等语言。
- CLANG,则是一个效率更高的C/C++编译工具,并且兼容GCC,Google在很早以前就开始建议使用clang进行编译,并且在ndk17以后,把GCC移除了,全面推行使用 CLANG 。
2.1 新建配置编译脚本
在ffmpeg-4.1.6源码根目录下新建脚本build.sh:vim build.sh
输入完成后,出现如下界面:
然后按下英文字母i, 底部就会出现INSERT, 表示当前可以输入文本信息,脚本内容如下:
#!/bin/bash
# 目标Android版本
API=21
ARCH=arm
CPU=armv7-a
#so库输出目录
PREFIX=$(pwd)/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/home/root1/ffm/android-ndk-r22b
# 编译环境
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
# 编译工具链路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
OPTIMIZE_CFLAGS="-DBIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
configure()
{
./configure \
--prefix=$PREFIX \
--enable-cross-compile \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--sysroot=$SYSROOT \
--cc=$TOOLCHAIN/armv7a-linux-androideabi$API-clang \
--cxx=$TOOLCHAIN/armv7a-linux-androideabi$API-clang++ \
--cross-prefix=$TOOLCHAIN/arm-linux-androideabi- \
--disable-encoders \
--disable-decoders \
--enable-decoder=h264 \
--enable-decoder=h264_mediacodec \
--enable-decoder=mp3 \
--enable-decoder=aac \
--disable-muxers \
--disable-demuxers \
--enable-demuxer=flv \
--enable-demuxer=sdp \
--enable-demuxer=rtsp \
--disable-filters \
--disable-parsers \
--enable-parser=aac \
--enable-parser=h264 \
--disable-bsfs \
--enable-bsf=aac_adtstoasc \
--enable-bsf=h264_mp4toannexb \
--disable-protocols \
--enable-protocol=file \
--enable-protocol=http \
--enable-protocol=rtmp \
--disable-libsrt \
--enable-neon \
--enable-hwaccels \
--enable-shared \
--enable-jni \
--enable-mediacodec \
--disable-static \
--disable-doc \
--enable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--enable-avdevice \
--disable-doc \
--disable-symver \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
}
build()
{
configure
make clean
make
make install
}
build
编辑完成后按Esc键退出编辑模式,输入:wq保存退出,可以看到根目录下多了build.sh文件。
重点关注几个选项:
- arch 选择机器架构
- cpu 选择最低的cpu
-
target-os 设置目标系统
在旧版本的 FFmpeg 中,对Android平台的支持并不是很完善,并没有android
这个target,所以在一些比较老的文章中都会提到,编译Android平台的so库,需要对 configure 做以下修改,否则会按照 linux 标准的方式输出so库,其命名方式和Android的so不一样,Android是无法加载的。
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)'
但是在新版本(至少从4.0
开始)的FFmpeg中,这个问题已经被解决了,FFmpeg加入了android
这个 target,不再需要手动去修改,建议大家尽量使用较新的版本。
-
sysroot 用于配置交叉编译环境的
根路径
,编译的时候会默认从这个路径下去寻找usr/include
和usr/lib
这两个路径,进而找到相关的头文件和库文件。
注意:这里的路径一定要写对,ndk路径,包括不同ndk版本下面的头文件和库文件位置可能有所不同,如果找不到就会编译失败。
关于ndk的路径,这里有个坑,本来设置/home/ffm/android-ndk-r22b
,一直提示找不到,编译失败,真实路径是/home/root1/ffm/android-ndk-r22b
。大家可以右键查看ndk文件夹属性,即可看到真实路径,如下图所示:
cross-prefix 交叉编译工具的前缀
cc 指定使用何种C编译器(默认gcc)
cxx 指定使用何种C编译器(默认g++)
FFmpeg 默认的编译工具是gcc
,ndk老版本中,使用的也是gcc
编译,所以只要设置cross-prefix即可,要保证能找到gcc文件,比如ndk14中配置如下
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
...
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
对应的编译工具如下
ndk17
以后,改用clang
编译,需要设置cc和cxx选项,比如本例的ndk22。
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
...
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--cc=$TOOLCHAIN/armv7a-linux-androideabi$API-clang \
--cxx=$TOOLCHAIN/armv7a-linux-androideabi$API-clang++ \
对应的编译工具如下
可以根据自己的需求对脚本进行修改
查看所有编译配置选项:
./configure --help
查看支持的解码器:
./configure --list-decoders
查看支持的编码器:
./configure --list-encoders
查看支持的硬件加速:
./configure --list-hwaccels
2.2 启动编译
赋予脚本执行权限:chmod +x build.sh
执行脚本开始编译:./build.sh
等待编译完成,将会在源码根目录下的android/armv7-a/lib/下找到我们需要的.so文件了。