我写了一篇有关使用 NDK 编译 Android 的 FFmpeg 的文章,尽管它是中文并且使用起来太多了,但每天都有成千上万的访问。

在这里,您将逐步了解如何使用最新的 git 存储库和最新的 Android NDK 版本构建 FFmpeg,并保证能够正常工作。

有 FFmpeg (Got FFmpeg)

首先,您需要使用 git 来获取 FFmpeg 代码,如果您没有 git 或不想使用 git,则可以从 http://ffmpeg.org 获取 FFmpeg。

git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
git checkout 5e99df019a850e9ffa96d73e72b8a47a93a61de8

配置 NDK (Configure NDK)

在本教程中,我们不使用传统的 Android.mk 文件来构建 FFmpeg,而是尝试使用 Android NDK 独立工具链。要初始化工具链,请发出以下命令:

export ANDROID_NDK=/path/to/your/android/ndk/root
export TOOLCHAIN=/tmp/ffmpeg
export SYSROOT=$TOOLCHAIN/sysroot/
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh \
    --platform=android-14 \
    --install-dir=$TOOLCHAIN

此时,我们可以使用位于 $TOOLCHAIN 的 Android 独立工具链来构建 FFmpeg。有关 Android 独立工具链的更多详细信息,请参见 Android NDK 的文档。

配置 FFmpeg (Configure FFmpeg)

现在我们已经准备好为 FFmpeg 做传统的 Linux 风格的 ./configure 工作了,一旦前两个准备工作都准备好了,就很容易做到。

稍作休息:直接在终端窗口中编写 bash 脚本很烦人,因此,在这一点上,我将创建一个包含以下内容的 bash 文件:

export PATH=$TOOLCHAIN/bin:$PATH
export CC=arm-linux-androideabi-gcc
export LD=arm-linux-androideabi-ld
export AR=arm-linux-androideabi-ar

CFLAGS="-O3 -Wall -mthumb -pipe -fpic -fasm \
  -finline-limit=300 -ffast-math \
  -fstrict-aliasing -Werror=strict-aliasing \
  -fmodulo-sched -fmodulo-sched-allow-regmoves \
  -Wno-psabi -Wa,--noexecstack \
  -D__ARM_ARCH_5__ -D__ARM_ARCH_5E__ \
  -D__ARM_ARCH_5T__ -D__ARM_ARCH_5TE__ \
  -DANDROID -DNDEBUG"

EXTRA_CFLAGS="-march=armv7-a -mfpu=neon \
              -mfloat-abi=softfp -mvectorize-with-neon-quad"

EXTRA_LDFLAGS="-Wl,--fix-cortex-a8"

FFMPEG_FLAGS="--prefix=/tmp/ffmpeg/build \
  --target-os=linux \
  --arch=arm \
  --enable-cross-compile \
  --cross-prefix=arm-linux-androideabi- \
  --enable-shared \
  --disable-symver \
  --disable-doc \
  --disable-ffplay \
  --disable-ffmpeg \
  --disable-ffprobe \
  --disable-ffserver \
  --disable-avdevice \
  --disable-avfilter \
  --disable-encoders \
  --disable-muxers \
  --disable-filters \
  --disable-devices \
  --disable-everything \
  --enable-protocols \
  --enable-parsers \
  --enable-demuxers \
  --disable-demuxer=sbg \
  --enable-decoders \
  --enable-bsfs \
  --enable-network \
  --enable-swscale \
  --enable-asm \
  --enable-version3"

./configure $FFMPEG_FLAGS \
  --extra-cflags="$CFLAGS $EXTRA_CFLAGS" \
  --extra-ldflags="$EXTRA_LDFLAGS"

很简单,对吧?我们只定义一些变量并启用或禁用某些 FFmpeg 组件。还包括一些 GCC 优化,可以从 man gcc 或在线文档 http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html 中找到详细信息。

构建并剥离 FFmpeg (Build and strip FFmpeg)

If you succeed to configure FFmpeg for Android, it’s time to make, issue commands below:

make -j4
make install

If everything is OK, we can get libavcodec.so, libavformat.so, etc in the prefix directory. If you wanna combine them to one libffmpeg.so, run:

rm libavcodec/inverse.o
$CC -lm -lz -shared --sysroot=$SYSROOT -Wl,--no-undefined \
    -Wl,-z,noexecstack $EXTRA_LDFLAGS \
    libavutil/*.o libavutil/arm/*.o \
    libavcodec/*.o libavcodec/arm/*.o \
    libavformat/*.o libswresample/*.o \
    libswscale/*.o -o libffmpeg.so

After testing with your build, you may want to strip unused information to shrink the libffmpeg.so library size:

arm-linux-androideabi-strip --strip-unneeded libffmpeg.so

For those who wanna the full code, please go to https://github.com/cedricfung/FFmpeg-Android.

Conclusion

It’s easier to port Linux library to Android since Android standalone toolchain was available, I’ve managed to compile many other libraries in my Android project.

In the later tutorials, I will share how to build a video player with FFmpeg from the ground, step by step too. Stay tuned!