准备工作

在开始正式的编译工作之前,需要准备好一下几个工具:

Yasm

Yasm是一个完全重写的MASM汇编器,编译FFmpeg时,需要借助Yasm生成二进制数据。[1]
如果还未安装Yasm,可以通过一下命令进行安装:

brew install yasm

NDK

Android NDK是一套工具集,可以使Android应用能够使用C和C++代码,编译FFmpeg时,需要借助NDK来实现交叉编译。我用的NDK版本是android-ndk-r20b[2]

编译步骤

1.下载FFmpeg源码

通过git直接拉取源码:

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

我拉取下来的源码工程的最新tag是n4.5-dev

2.修改配置文件

在不修改FFmpeg默认配置的情况下,编译出来的动态库文件的文件名会存在一个问题,即文件名中.so后面还会跟上一串版本号,如:libavcodec.so.x.y.z,其中还x.y.z是一串版本号,这在Android平台中是不能被正常识别的,因此需要修改配置文件相关部分的代码,以保证编译出来的动态库文件的文件名是以.so结尾的。
FFmpeg源码根目录下有一个configure文件,打开后找到以下代码:

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)'

3.编写编译脚本

接下来需要编写编译FFmpeg的shell脚本。
我们在FFmpeg源码根目录下创建一个脚本文件,文件名随意,例如我这里的文件名为build_android.sh,脚本内容如下[3]

#!/bin/bash
make clean
set -e
archbit=64

if [ $archbit -eq 64 ];then
echo "build for 64bit"
ARCH=aarch64
CPU=armv8-a
API=21
PLATFORM=aarch64
ANDROID=android
CFLAGS=""
LDFLAGS=""

else
echo "build for 32bit"
ARCH=arm
CPU=armv7-a
API=16
PLATFORM=armv7a
ANDROID=androideabi
CFLAGS="-mfloat-abi=softfp -march=$CPU"
LDFLAGS="-Wl,--fix-cortex-a8"
fi

export NDK=/Users/xiaoyu/Library/Android/sdk/ndk/android-ndk-r20b
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin
export SYSROOT=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
export CROSS_PREFIX=$TOOLCHAIN/$ARCH-linux-$ANDROID-
export CC=$TOOLCHAIN/$PLATFORM-linux-$ANDROID$API-clang
export CXX=$TOOLCHAIN/$PLATFORM-linux-$ANDROID$API-clang++
export PREFIX=$(pwd)/android/$CPU

function build_android {
    ./configure \
    --prefix=$PREFIX \
    --cross-prefix=$CROSS_PREFIX \
    --target-os=android \
    --arch=$ARCH \
    --cpu=$CPU \
    --cc=$CC \
    --cxx=$CXX \
    --nm=$TOOLCHAIN/$ARCH-linux-$ANDROID-nm \
    --strip=$TOOLCHAIN/$ARCH-linux-$ANDROID-strip \
    --enable-cross-compile \
    --sysroot=$SYSROOT \
    --extra-cflags="$CFLAGS" \
    --extra-ldflags="$LDFLAGS" \
    --extra-ldexeflags=-pie \
    --enable-runtime-cpudetect \
    --disable-static \
    --enable-shared \
    --disable-ffprobe \
    --disable-ffplay \
    --disable-ffmpeg \
    --disable-debug \
    --disable-doc \
    --enable-avfilter \
    --enable-decoders \
    $ADDITIONAL_CONFIGURE_FLAG

    make
    make install
}
build_android

脚本内容中的export NDK=/Users/xiaoyu/Library/Android/sdk/ndk/android-ndk-r20b指明了NDK的路径,须替换为自己的NDK路径。

4.执行编译

保存build_android.sh文件的内容后,在终端访问FFmpeg源码根目录执行如下命令进行编译:

./build_android.sh

编译开始后,在终端会不断输出编译信息,截取一段编译信息如下:
image.png
编译时间较长,大概二十分钟左右,可以趁这段时间干点别的事情。

5.编译完成

编译完成后,FFmpeg源码目录下多了一个android目录,android目录下包含了FFmpeg各模块的动态库文件以及需要include的头文件。
image.png

常见问题

1.编译后找不到libpostproc模块

需在编译脚本中增以下配置项:

--enable-postproc \
--enable-gpl \

参考资料


  1. yasm ↩︎

  2. Android NDK ↩︎

  3. FFmpegAndroid(https://github.com/xufuji456/FFmpegAndroid) ↩︎

Q.E.D.


学而时习之,不亦说乎? 有朋自远方来,不亦乐乎?