? ? ?ffmpeg 在移动平台上应用十分广泛,其在音视频编解码,封装多媒体文件格式,rtsp http rtmp协议相关的音视频推流拉流具有强大的可用性。这里将自己平时为Android平台编译ffmpeg的用到的脚本分享出来,方便大家参考。本文编译是在MAC电脑上完成的,当然Linux系统也可以。
? ?ffmpeg 编译根据github上 WritingMinds/ffmpeg-android编译脚本,进行了修改,添加arm64-v8a平台的编译,解决链接是出现的ELF格式不对错误,解决高版本的ndk工具编译导致的链接错误。本文采用ffmpeg的版本3.0进行编译成静态库,方便以后跟jni一起打包成动态库,如果需要编译成动态库,只需要将 ffmpeg_build.sh 中 --disable-shared 编译选项 改为?--enable-shared即可。注意:与JNI其它代码一起封装成动态库是 链接ffmpeg静态库的顺序也很重要,如果出现顺序不对可能导致链接不成功。
? ?编译脚本分为4个sh文件android_build.sh settings.sh abi_settings.sh ffmpeg_build.sh。在进行ffmpeg编译时只需要运行./android_build.sh 即可完成arm64-v8a armeabi-v7a编译
android_build.sh?
#!/bin/bash
# 执行编译时,运行./android_build.sh即可
# 首先执行 settings.sh 脚本 完成基础环境配置
. settings.sh
BASEDIR=$(pwd)
TOOLCHAIN_PREFIX=${BASEDIR}/toolchain-android
# Applying required patches
patch -p0 -N --dry-run --silent -f fontconfig/src/fcxml.c < android_donot_use_lconv.patch 1>/dev/null
if [ $? -eq 0 ]; then
patch -p0 -f fontconfig/src/fcxml.c < android_donot_use_lconv.patch
fi
# 根据settings.sh 定义需要平台的cpu类型进行分别编译
for i in "${SUPPORTED_ARCHITECTURES[@]}"
do
rm -rf ${TOOLCHAIN_PREFIX}
# $1 = architecture
# $2 = base directory
# $3 = pass 1 if you want to export default compiler environment variables
#./x264_build.sh $i $BASEDIR 0 || exit 1
#./libpng_build.sh $i $BASEDIR 1 || exit 1
#./freetype_build.sh $i $BASEDIR 1 || exit 1
#./expat_build.sh $i $BASEDIR 1 || exit 1
#./fribidi_build.sh $i $BASEDIR 1 || exit 1
#./fontconfig_build.sh $i $BASEDIR 1 || exit 1
#./libass_build.sh $i $BASEDIR 1 || exit 1
#./lame_build.sh $i $BASEDIR 1 || exit 1
./ffmpeg_build.sh $i $BASEDIR 0 || exit 1
done
rm -rf ${TOOLCHAIN_PREFIX}
settings.sh
#!/bin/bash
# 定义Android NDK目录 测试使用的NDK版本为17
ANDROID_NDK=/Users/who/Library/Android/ndk-bundle
# 需要的eabi类型,一般有arm32位和 arm64位即可满足大部分的需求
SUPPORTED_ARCHITECTURES=(arm64-v8a armeabi-v7a)
#SUPPORTED_ARCHITECTURES=(arm64-v8a armeabi-v7a armeabi-v7a-neon x86)
ANDROID_NDK_ROOT_PATH=${ANDROID_NDK}
if [[ -z "$ANDROID_NDK_ROOT_PATH" ]]; then
echo "You need to set ANDROID_NDK environment variable, please check instructions"
exit
fi
# 定义支持的Android版本,此处最小支持到21,即Android5.0
ANDROID_API_VERSION=21
NDK_TOOLCHAIN_ABI_VERSION=4.9
NUMBER_OF_CORES=$(nproc)
HOST_UNAME=$(uname -m)
TARGET_OS=android
# 此处定义编译选项,在原文基础上添加-D__ANDROID_API__=21,解决在高版本的NDK编译过程中出现链接错误的问题
CFLAGS='-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all -D__ANDROID_API__=21'
LDFLAGS='-Wl,-z,relro -Wl,-z,now -pie'
FFMPEG_PKG_CONFIG="$(pwd)/ffmpeg-pkg-config"
? ?abi_settings.sh
#!/bin/bash
. settings.sh
BASEDIR=$2
case $1 in
armeabi-v7a)
NDK_ABI='arm'
NDK_TOOLCHAIN_ABI='arm-linux-androideabi'
NDK_CROSS_PREFIX="${NDK_TOOLCHAIN_ABI}"
;;
armeabi-v7a-neon)
NDK_ABI='arm'
NDK_TOOLCHAIN_ABI='arm-linux-androideabi'
NDK_CROSS_PREFIX="${NDK_TOOLCHAIN_ABI}"
CFLAGS="${CFLAGS} -mfpu=neon"
;;
arm64-v8a)
NDK_ABI='arm64'
NDK_TOOLCHAIN_ABI='aarch64-linux-android'
NDK_CROSS_PREFIX="${NDK_TOOLCHAIN_ABI}"
;;
x86)
NDK_ABI='x86'
NDK_TOOLCHAIN_ABI='x86'
NDK_CROSS_PREFIX="i686-linux-android"
CFLAGS="$CFLAGS -march=i686"
;;
esac
TOOLCHAIN_PREFIX=${BASEDIR}/toolchain-android
if [ ! -d "$TOOLCHAIN_PREFIX" ]; then
${ANDROID_NDK_ROOT_PATH}/build/tools/make-standalone-toolchain.sh --toolchain=${NDK_TOOLCHAIN_ABI}-${NDK_TOOLCHAIN_ABI_VERSION} --platform=android-${ANDROID_API_VERSION} --install-dir=${TOOLCHAIN_PREFIX}
fi
CROSS_PREFIX=${TOOLCHAIN_PREFIX}/bin/${NDK_CROSS_PREFIX}-
NDK_SYSROOT=${TOOLCHAIN_PREFIX}/sysroot
ffmpeg_build.sh
#!/bin/bash
. abi_settings.sh $1 $2 $3
pushd ffmpeg
# 添加这两行 删除stdtod.d stdtod.o这两个文件,否则导致链接错误
rm -rf compat/strtod.d
rm -rf compat/strtod.o
# 在原有基础上添加 arm64-v8a 平台
case $1 in
armeabi-v7a | armeabi-v7a-neon)
CPU='cortex-a8'
;;
arm64-v8a)
CPU='armv8-a'
;;
x86)
CPU='i686'
;;
esac
make clean
./configure \n--target-os="$TARGET_OS" \n--cross-prefix="$CROSS_PREFIX" \n--arch="$NDK_ABI" \n--cpu="$CPU" \n--enable-runtime-cpudetect \n--sysroot="$NDK_SYSROOT" \n--enable-pic \n--enable-pthreads \n--disable-debug \n--enable-version3 \n--enable-hardcoded-tables \n--disable-ffplay \n--disable-ffprobe \n--disable-ffserver \n--disable-ffmpeg \n--enable-gpl \n--enable-yasm \n--disable-doc \n--disable-shared \n--enable-static \n--pkg-config="${2}/ffmpeg-pkg-config" \n--prefix="${2}/build/${1}" \n--extra-cflags="-I${TOOLCHAIN_PREFIX}/include $CFLAGS" \n--extra-ldflags="-L${TOOLCHAIN_PREFIX}/lib $LDFLAGS" \n--extra-cxxflags="$CXX_FLAGS" || exit 1
make -j4 && make install || exit 1
popd
?