一、NDK编译新版本FFmpeg
编译FFmpeg的版本:4.4.6、5.1.6、6.1.2、7.0.2
脚本下载地址 :ffmpeg_build
编译环境:
- 系统:
Ubuntu 20.04
- 编译工具:
sudo apt install build-essential nasm yasm make cmake automake autoconf libtool diffutils pkg-config git unzip
- 编译器是:
llvm
项目的clang
编译器
1.1 目录结构
bash
./
├── build_android.sh # 主构建脚本
├── config_scripts # 配置脚本目录
│ ├── fdk-aac-config-android.sh # fdk-aac配置脚本
│ ├── ffmpeg-config-android.sh # FFmpeg配置脚本
│ └── x264-config-android.sh # x264配置脚本
├── deps # 依赖库源码目录
│ ├── fdk-aac # fdk-aac的源码
│ └── x264 # x264源码
├── download_ffmpeg_deps.sh # 依赖下载脚本
├── ffmpeg # FFmpeg源码目录
│ ├── ffmpeg-4.4.6 # FFmpeg 4.4.6源码
│ ├── ffmpeg-4.4.6.tar.xz # FFmpeg 4.4.6压缩包
│ ├── ffmpeg-5.1.6 # FFmpeg 5.1.6源码
│ ├── ffmpeg-5.1.6.tar.xz # FFmpeg 5.1.6压缩包
│ ├── ffmpeg-6.1.2 # FFmpeg 6.1.2源码
│ ├── ffmpeg-6.1.2.tar.xz # FFmpeg 6.1.2压缩包
│ ├── ffmpeg-7.0.2 # FFmpeg 7.0.2源码
│ └── ffmpeg-7.0.2.tar.xz # FFmpeg 7.0.2压缩包
├── ndk # Android NDK目录
│ ├── android-ndk-r21e # NDK r21e解压目录
│ ├── android-ndk-r21e-linux-x86_64.zip # NDK r21e压缩包
│ ├── android-ndk-r24 # NDK r24解压目录
│ └── android-ndk-r24-linux-x86_64.zip # NDK r24压缩包
└── output # 编译输出目录
├── 4.4.6 # FFmpeg 4.4.6输出
├── 5.1.6 # FFmpeg 5.1.6输出
├── 6.1.2 # FFmpeg 6.1.2输出
├── 7.0.2 # FFmpeg 7.0.2输出
└── deps # 依赖库输出目录
说明:
- 上面是最终目录结构
- deps、ffmpeg、ndk目录是执行
download_ffmpeg_deps.sh
脚本后才有的。 - output 是编译后产生的。
1.2 脚本使用
设置终端代理(方便下载NDK和源码)
bash
export http_proxy="http://127.0.0.1:10809"
export https_proxy="http://127.0.0.1:10809"
下载NDK和源代码:
bash
# 下载:NDK(r21e、r24)、ffmpeg(4.4.6、5.1.6、6.1.2、7.0.2)、依赖(fdk-aac、x264)
./download_ffmpeg_deps.sh
修改build_android.sh
中的参数:
编译:
bash
# 先编译x264和fdk-aac,再编译ffmpeg
./build_android.sh all
# 只编译x264库
./build_android.sh x264
# 只编译fdk-aac库
./build_android.sh fdk-aac
1.3 库的位置
bash
output/ # 编译输出目录
├── 4.4.6 # 4.4.6ffmpeg的库目录
│ ├── arm64-v8a # arm64-v8a架构
│ └── armeabi-v7a # armeabi-v7a架构
├── 5.1.6
│ ├── arm64-v8a
│ └── armeabi-v7a
├── 6.1.2
│ ├── arm64-v8a
│ └── armeabi-v7a
├── 7.0.2
│ ├── arm64-v8a
│ └── armeabi-v7a
└── deps # 依赖输出目录
├── arm64-v8a
└── armeabi-v7a
1.4 脚本内容与说明
脚本目录结构:
bash
./
├── build_android.sh # 2.编译控制脚本
├── config_scripts
│ ├── fdk-aac-config-android.sh # 4.fdk-aac编译脚本
│ ├── ffmpeg-config-android.sh # 5.ffmpeg编译脚本
│ └── x264-config-android.sh # 3.x264编译脚本
└── download_ffmpeg_deps.sh # 1.下载NDK和源码,并解压
(1)download_ffmpeg_deps.sh
bash
#!/bin/bash
# 基础目录设置
BASE_DIR=$(pwd)
NDK_DIR="$BASE_DIR/ndk"
FFMPEG_DIR="$BASE_DIR/ffmpeg"
DEPS_DIR="$BASE_DIR/deps"
CONFIG_SCRIPTS_DIR="$BASE_DIR/config_scripts"
# 创建目录结构
mkdir -p "$NDK_DIR" "$FFMPEG_DIR" "$DEPS_DIR"/{fdk-aac,x264} "$CONFIG_SCRIPTS_DIR"
# 下载函数
download_file() {
local url="$1" output="$2"
if [ ! -f "$output" ]; then
echo "Downloading $url to $output"
wget --no-check-certificate -q --show-progress "$url" -O "$output" || {
echo "Error: Failed to download $url"
exit 1
}
else
echo "File $output already exists, skipping download"
fi
}
# 下载NDK
download_ndk() {
local ndk_versions=("r21e" "r24")
local ndk_urls=(
"https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip"
"https://dl.google.com/android/repository/android-ndk-r24-linux.zip"
)
for i in "${!ndk_versions[@]}"; do
local version="${ndk_versions[i]}" url="${ndk_urls[i]}"
local output="$NDK_DIR/android-ndk-${version}-linux-x86_64.zip"
download_file "$url" "$output"
# 解压NDK
if [ -f "$output" ] && [ ! -d "$NDK_DIR/android-ndk-$version" ]; then
echo "Extracting $output"
unzip -q "$output" -d "$NDK_DIR"
mv "$NDK_DIR/android-ndk-$version" "$NDK_DIR/android-ndk-$version" 2>/dev/null || true
fi
done
}
# 下载FFmpeg
download_ffmpeg() {
local versions=("4.4.6" "5.1.6" "6.1.2" "7.0.2")
for version in "${versions[@]}"; do
local tarball="ffmpeg-$version.tar.xz"
local url="https://ffmpeg.org/releases/$tarball"
local output="$FFMPEG_DIR/$tarball"
download_file "$url" "$output"
# 解压FFmpeg
if [ -f "$output" ] && [ ! -d "$FFMPEG_DIR/ffmpeg-$version" ]; then
echo "Extracting $output"
tar -xf "$output" -C "$FFMPEG_DIR"
fi
done
}
# 下载依赖库
download_deps() {
# fdk-aac
if [ ! -d "$DEPS_DIR/fdk-aac/.git" ]; then
git clone --depth 1 https://github.com/mstorsjo/fdk-aac "$DEPS_DIR/fdk-aac"
else
echo "Updating fdk-aac"
cd "$DEPS_DIR/fdk-aac" && git pull
fi
# x264
if [ ! -d "$DEPS_DIR/x264/.git" ]; then
git clone --depth 1 https://code.videolan.org/videolan/x264.git "$DEPS_DIR/x264"
else
echo "Updating x264"
cd "$DEPS_DIR/x264" && git pull
fi
}
# 主函数
main() {
echo "Starting FFmpeg build environment setup"
download_ndk
download_ffmpeg
download_deps
echo "Setup completed successfully!"
}
main
说明:
- 创建基本目录结构(ndk、ffmpeg、deps/fdk-aac、deps/x264、config_scripts)
- 下载r21e和r24两个版本的NDK,并解压。
- 下载4.4.6、5.1.6、6.1.2、7.0.2版本的FFmpeg,并解压
- 下载fdk-aac和x264源码
(2)build_android.sh
bash
#!/bin/bash
# Compilation threads
THREAD_NUM=8
# NDK installation path
# NDK_HOME=$(pwd)/ndk/android-ndk-r21e
NDK_HOME=$(pwd)/ndk/android-ndk-r24
# Android Platform API (21+ for arm64-v8a)
ANDROID_API=21
# ABI type: armeabi-v7a or arm64-v8a
ARCH_ABI=armeabi-v7a
# FFmpeg version 4.4.6, 5.1.6, 6.1.2, 7.0.2
FFMPEG_VERSION=7.0.2
# 配置脚本目录
CONFIG_SCRIPTS_DIR=$(pwd)/config_scripts
# 输出目录设置
BASE_OUTPUT_DIR=$(pwd)/output
DEPS_OUTPUT_DIR="${BASE_OUTPUT_DIR}/deps/${ARCH_ABI}"
FFMPEG_OUTPUT_DIR="${BASE_OUTPUT_DIR}/${FFMPEG_VERSION}/${ARCH_ABI}"
export THREAD_NUM NDK_HOME ANDROID_API ARCH_ABI FFMPEG_VERSION
export BASE_OUTPUT_DIR DEPS_OUTPUT_DIR FFMPEG_OUTPUT_DIR CONFIG_SCRIPTS_DIR
print_helpmsg(){
echo "Usage: source $0 [option] [ffmpeg_version]"
echo "Options:"
printf "\tall: rebuild all libraries (x264, fdk-aac, ffmpeg)\n"
printf "\tx264: rebuild x264\n"
printf "\tfdk-aac: rebuild libfdk-aac\n"
printf "\tffmpeg: rebuild ffmpeg\n"
printf "\thelp: print this message\n"
echo "FFmpeg versions: 4.4.6, 5.1.6, 6.1.2, 7.0.2"
echo "Example: source $0 all 6.1.2"
}
build_x264(){
cd deps/x264
echo "Building x264 for ${ARCH_ABI}..."
DEPS_OUTPUT_DIR="${DEPS_OUTPUT_DIR}" \
${CONFIG_SCRIPTS_DIR}/x264-config-android.sh || exit $?
cd -
}
build_fdk-aac(){
cd deps/fdk-aac
echo "Building fdk-aac for ${ARCH_ABI}..."
DEPS_OUTPUT_DIR="${DEPS_OUTPUT_DIR}" \
${CONFIG_SCRIPTS_DIR}/fdk-aac-config-android.sh || exit $?
cd -
}
build_ffmpeg(){
cd "ffmpeg/ffmpeg-${FFMPEG_VERSION}"
echo "Building FFmpeg ${FFMPEG_VERSION} for ${ARCH_ABI}..."
FFMPEG_OUTPUT_DIR="${FFMPEG_OUTPUT_DIR}" \
DEPS_OUTPUT_DIR="${DEPS_OUTPUT_DIR}" \
${CONFIG_SCRIPTS_DIR}/ffmpeg-config-android.sh "$1" || exit $?
cd -
}
build(){
local ffmpeg_ver=${2:-${FFMPEG_VERSION}}
if [[ ! "4.4.6 5.1.6 6.1.2 7.0.2" =~ "${ffmpeg_ver}" ]]; then
echo "Invalid FFmpeg version: ${ffmpeg_ver}. Supported: 4.4.6, 5.1.6, 6.1.2, 7.0.2"
exit 1
fi
export FFMPEG_VERSION=${ffmpeg_ver}
# 更新输出目录
export FFMPEG_OUTPUT_DIR="${BASE_OUTPUT_DIR}/${FFMPEG_VERSION}/${ARCH_ABI}"
export DEPS_OUTPUT_DIR="${BASE_OUTPUT_DIR}/deps/${ARCH_ABI}"
# 确保输出目录存在
mkdir -p "${FFMPEG_OUTPUT_DIR}" "${DEPS_OUTPUT_DIR}"
case "$1" in
"all")
build_x264 && build_fdk-aac && build_ffmpeg 2
;;
"x264")
build_x264
;;
"fdk-aac")
build_fdk-aac
;;
"ffmpeg")
build_ffmpeg 2
;;
"help")
print_helpmsg
exit 0
;;
"")
build_x264 && build_fdk-aac && build_ffmpeg 2
;;
*)
echo "Invalid option: $1"
print_helpmsg
exit 1
;;
esac
echo "Build completed for FFmpeg ${FFMPEG_VERSION} (${ARCH_ABI})"
echo "Output directory: ${FFMPEG_OUTPUT_DIR}"
}
build "$@"
说明:
- 编译的主脚本。
- 控制编译x264、fdk-aac、ffmpeg。
- 控制编译线程、NDK版本、Android的API、架构ARM7\ARM8、ffmpeg版本。
(3)ffmpeg-config-android.sh
bash
#!/bin/bash
if [ ! $# == 1 ]; then
echo "Usage: $0 [0|1|2]"
exit 1
fi
# 使用环境变量中的输出目录
PREFIX="${FFMPEG_OUTPUT_DIR}"
# Toolchain setup
TOOLCHAIN=${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=${TOOLCHAIN}/sysroot
# 确保输出目录存在
mkdir -p ${PREFIX}/lib
mkdir -p ${PREFIX}/include
# ABI configuration
case ${ARCH_ABI} in
armeabi-v7a)
TARGET=armv7a-linux-androideabi
CFLAGS="-march=armv7-a -mfpu=neon -D__ARM_ARCH_7A__ -O3 -fPIC -DANDROID"
LDFLAGS=""
TARGET_ARCH_OPTION="--arch=arm --enable-neon"
;;
arm64-v8a)
TARGET=aarch64-linux-android
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -fPIC -DANDROID"
LDFLAGS=""
TARGET_ARCH_OPTION="--arch=aarch64"
;;
*)
echo "Unsupported ABI: ${ARCH_ABI}"
exit 1
;;
esac
# 编译器路径设置
CC="${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang"
CXX="${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang++"
AR="${TOOLCHAIN}/bin/llvm-ar"
RANLIB="${TOOLCHAIN}/bin/llvm-ranlib"
STRIP="${TOOLCHAIN}/bin/llvm-strip"
# 导出环境变量
export CC CXX AR RANLIB STRIP
export CFLAGS LDFLAGS
echo "=================================================================="
echo "FFmpeg Version: ${FFMPEG_VERSION}"
echo "Output Directory: ${PREFIX}"
echo "CC=${CC}"
echo "CXX=${CXX}"
echo "AR=${AR}"
echo "RANLIB=${RANLIB}"
echo "STRIP=${STRIP}"
echo "CFLAGS=${CFLAGS}"
echo "LDFLAGS=${LDFLAGS}"
echo "PREFIX=${PREFIX}"
echo "=================================================================="
# Common configure options
COMMON_CONFIG="\
--prefix=${PREFIX} \
--enable-cross-compile \
--sysroot=${SYSROOT} \
--target-os=android \
${TARGET_ARCH_OPTION} \
--disable-everything \
--disable-programs \
--enable-pic \
--enable-gpl \
--enable-nonfree \
--enable-decoder=aac,aac_latm,h264 \
--enable-demuxer=aac,asf,ffmetadata,h264,mp3 \
--enable-muxer=adts,h264,mp4,pcm_s16le \
--enable-parser=aac,aac_latm,h264 \
--enable-protocol=file \
--disable-zlib \
--disable-debug \
--cc=${CC} \
--cxx=${CXX} \
--ar=${AR} \
--strip=${STRIP} \
--ranlib=${RANLIB}"
# Version-specific options
case ${FFMPEG_VERSION} in
"4.4.6")
EXTRA_CONFIG="--disable-vulkan --disable-mediacodec"
;;
"5.1.6"|"6.1.2"|"7.0.2")
EXTRA_CONFIG="--enable-jni --enable-mediacodec"
;;
esac
# 使用环境变量中的依赖库目录
export PKG_CONFIG_PATH="${DEPS_OUTPUT_DIR}/lib/pkgconfig"
case $1 in
"2")
echo "********support x264,fdk-aac encoder******"
./configure ${COMMON_CONFIG} \
--enable-libx264 \
--enable-libfdk-aac \
--enable-encoder=aac,libfdk_aac,libx264 \
--extra-cflags="-I${DEPS_OUTPUT_DIR}/include" \
--extra-ldflags="-L${DEPS_OUTPUT_DIR}/lib" \
${EXTRA_CONFIG} || exit $?
;;
"1")
echo "*******support h264,aac encoder******"
./configure ${COMMON_CONFIG} \
--enable-libx264 \
--enable-encoder=aac,libx264 \
--extra-cflags="-I${DEPS_OUTPUT_DIR}/include" \
--extra-ldflags="-L${DEPS_OUTPUT_DIR}/lib" \
${EXTRA_CONFIG} || exit $?
;;
"0")
echo "******no encoder support********"
./configure ${COMMON_CONFIG} \
--extra-cflags="-I${DEPS_OUTPUT_DIR}/include" \
--extra-ldflags="-L${DEPS_OUTPUT_DIR}/lib" \
${EXTRA_CONFIG} || exit $?
;;
*)
echo "Invalid parameter: $1"
exit 1
;;
esac
# 编译前清理
rm -f compat/strtod.o compat/strtod.d compat/msvcrt/snprintf.o compat/msvcrt/snprintf.d
make clean
make -j$THREAD_NUM
# 安装
make install
说明:
- 核心配置选项
--disable-everything
# 禁用所有组件--enable-decoder=aac,aac_latm,h264
# 按需启用解码器--enable-demuxer=aac,asf,ffmetadata,h264,mp3
# 启用解封装器--enable-muxer=adts,h264,mp4,pcm_s16le
# 启用封装器
- 版本特定配置
- 4.4.6:禁用 Vulkan 和 MediaCodec
- 5.1.6+:启用 JNI 和 MediaCodec
(4)x264-config-android.sh
bash
#!/bin/bash
# 使用环境变量中的输出目录
PREFIX="${DEPS_OUTPUT_DIR}"
# Toolchain setup
TOOLCHAIN=${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=${TOOLCHAIN}/sysroot
# Common compiler tools
CC=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang
CXX=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang++
AR=${TOOLCHAIN}/bin/llvm-ar
RANLIB=${TOOLCHAIN}/bin/llvm-ranlib
STRIP=${TOOLCHAIN}/bin/llvm-strip
# ABI configuration
case ${ARCH_ABI} in
armeabi-v7a)
TARGET=armv7a-linux-androideabi
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -fPIC -DANDROID"
LDFLAGS="-march=armv7-a"
;;
arm64-v8a)
TARGET=aarch64-linux-android
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -fPIC -DANDROID"
LDFLAGS="-march=armv8-a"
;;
*)
echo "Unsupported ABI: ${ARCH_ABI}"
exit 1
;;
esac
# Update CC and CXX with the correct TARGET
CC=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang
CXX=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang++
# 关键修复:禁用 strip 操作并添加数学库链接
export STRIP=true
LDFLAGS="${LDFLAGS} -lm"
export CC CXX AR RANLIB CFLAGS LDFLAGS
# Configure x264
./configure \
--prefix=${PREFIX} \
--disable-opencl \
--disable-cli \
--enable-pic \
--enable-static \
--host=${TARGET} \
--sysroot=${SYSROOT} \
--extra-cflags="${CFLAGS}" \
--extra-ldflags="${LDFLAGS}" || exit $?
# 编译并安装
make clean
make -j$THREAD_NUM
make install
说明:
- 关键修复:
export STRIP=true
# 禁用 strip 操作,防止兼容性问题 - 配置选项
--enable-static --disable-cli
# 仅构建静态库,禁用命令行工具--enable-pic
# 位置无关代码(PIC)
(5)fdk-aac-config-android.sh
bash
#!/bin/bash
# 使用环境变量中的输出目录
PREFIX="${DEPS_OUTPUT_DIR}"
# Toolchain setup
TOOLCHAIN=${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=${TOOLCHAIN}/sysroot
# Common compiler tools
CC=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang
CXX=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang++
AR=${TOOLCHAIN}/bin/llvm-ar
RANLIB=${TOOLCHAIN}/bin/llvm-ranlib
STRIP=${TOOLCHAIN}/bin/llvm-strip
# ABI configuration
case ${ARCH_ABI} in
armeabi-v7a)
TARGET=armv7a-linux-androideabi
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -fPIC -DANDROID"
LDFLAGS="-march=armv7-a"
;;
arm64-v8a)
TARGET=aarch64-linux-android
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -fPIC -DANDROID"
LDFLAGS="-march=armv8-a"
;;
*)
echo "Unsupported ABI: ${ARCH_ABI}"
exit 1
;;
esac
# Update CC and CXX with the correct TARGET
CC=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang
CXX=${TOOLCHAIN}/bin/${TARGET}${ANDROID_API}-clang++
# 关键修复: 添加log库链接
LDFLAGS="${LDFLAGS} -llog"
export CC CXX AR RANLIB STRIP CFLAGS LDFLAGS
# 关键修复: 创建符号链接解决头文件路径问题
mkdir -p ${PWD}/log
ln -sf ${SYSROOT}/usr/include/android/log.h ${PWD}/log/log.h
# 关键修复: 添加当前目录到头文件搜索路径
export CFLAGS="${CFLAGS} -I${PWD}"
# Configure fdk-aac
autoreconf -i
./configure \
--prefix=${PREFIX} \
--host=${TARGET} \
--with-sysroot=${SYSROOT} \
--enable-static \
--disable-shared || exit $?
# 编译并安装
make clean
make -j$THREAD_NUM
make install
说明:
- 构建准备:
autoreconf -i
# 生成配置脚本 - 关键修复
LDFLAGS="${LDFLAGS} -llog"
# 添加 Android log 库ln -sf ${SYSROOT}/usr/include/android/log.h ${PWD}/log/log.h
# 解决头文件路径问题export CFLAGS="${CFLAGS} -I${PWD}"
# 添加当前目录到搜索路径
二、NDK编译旧版本FFmpeg
编译FFmpeg的版本:3.2.2
脚本下载地址 :ffmpeg-android-master.tar.gz
编译环境:
- 系统:
Ubuntu 20.04
- 编译工具:
sudo apt install build-essential nasm yasm make cmake automake autoconf libtool diffutils pkg-config git unzip
- 编译器是:
gnu
项目的gcc
编译器
2.1 目录结构
bash
./
├── ndk # NDK
│ ├── android-ndk-r13b
│ └── android-ndk-r21e
├── ffmpeg # ffmpeg 源码目录(3.2.2版本)
│ ├── ...
│ └── config-android.sh # ffmpeg配置脚本
├── libfdk-aac # fdk-aac 源码目录
│ ├── ...
│ └── config-android.sh # fdk-aac 配置脚本
├── x264 # x264 源码目录
│ ├── ...
│ └── config-android.sh # x264 配置脚本
├── build_android.sh # 编译控制脚本
└── output # 编译输出目录
├── armeabi-v7a
└── arm64-v8a
2.2 脚本使用
下载NDK并放在ndk目录:
修改build_android.sh
参数:
编译:
bash
# 先编译x264和fdk-aac,再编译ffmpeg
./build_android.sh all
# 只编译x264库
./build_android.sh x264
# 只编译fdk-aac库
./build_android.sh fdk-aac
2.3 脚本内容
(1)build_android.sh
bash
#!/bin/bash
# !!!编译线程数
THREAD_NUM=8
# !!!NDK的安装位置
NDK_ROOT_PATH=$(pwd)/ndk/android-ndk-r21e
# !!!Android Platform API (只有大于等于21,才能编译arm64-v8a)
ANDROID_API=21
# !!!ABI类型: armeabi-v7a arm64-v8a
ARCH_ABI=arm64-v8a
export THREAD_NUM NDK_ROOT_PATH ANDROID_API ARCH_ABI
print_helpmsg(){
echo "usage:source set-env.sh [option]"
echo "option is:"
printf "\t all: rebuild all opensource library and interface files(GGCodec*.c)\n"
printf "\t x264: rebuild x264 and interface files\n"
printf "\t libfdk-aac: rebuild libfdk-aac and interface files\n"
printf "\t ffmpeg: rebuild ffmpeg and interface files\n"
printf "\t help: print this message\n\n"
}
build_x264(){
cd x264 && ./config-android.sh && cd ..
}
build_libfdk-aac(){
cd libfdk-aac && ./config-android.sh && cd ..
}
build_ffmpeg(){
cd ffmpeg && ./config-android.sh $1 && cd ..
}
build(){
if test "$1" = "all"; then
build_x264 && build_libfdk-aac && build_ffmpeg 2
elif test "$1" = "x264"; then
#build_x264 && build_ffmpeg 2
build_x264
elif test "$1" = "libfdk-aac"; then
#build_libfdk-aac && build_ffmpeg 2
build_libfdk-aac
elif test "$1" = "ffmpeg"; then
build_ffmpeg 2
elif test "$1" = "help"; then
print_helpmsg && eixt 0
elif test "$1" = ""; then
build_x264 && build_libfdk-aac && build_ffmpeg 2
else
printf "no option, just rebuild interface files\n\n" && print_helpmsg
fi
build "$@"
(2)ffmpeg/config-android.sh
bash
#!/bin/bash
if [ ! $# == 1 ] ; then
echo "Usage: $0 [0|1|2]"
exit
fi
# 检测 NDK 版本
NDK_VERSION=$(grep -oP "Pkg.Revision\s*=\s*\K.*" $NDK_ROOT_PATH/source.properties)
echo "Detected NDK version: $NDK_VERSION"
# 提取主版本号
MAJOR_VERSION=$(echo $NDK_VERSION | cut -d '.' -f 1)
# 判断是 NDK13 还是 NDK21
if [[ $MAJOR_VERSION -le 13 ]]; then
echo "Using NDK13 (GCC)"
TOOLCHAIN=$NDK_ROOT_PATH/toolchains
SYSROOT=$NDK_ROOT_PATH/platforms/android-$ANDROID_API/arch-arm
if [ $ARCH_ABI == "arm64-v8a" ]; then
SYSROOT=$NDK_ROOT_PATH/platforms/android-$ANDROID_API/arch-arm64
fi
elif [[ $MAJOR_VERSION -ge 21 ]]; then
echo "Using NDK21 (Clang)"
TOOLCHAIN=$NDK_ROOT_PATH/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=$TOOLCHAIN/sysroot
else
echo "Unsupported NDK version: $NDK_VERSION"
echo "Only NDK <= 13 (GCC) or NDK >= 21 (Clang) are supported."
exit 1
fi
# 选择 ABI
TARGET_ARCH_OPTION="--arch=arm"
case $ARCH_ABI in
armeabi-v7a)
if [[ $MAJOR_VERSION -le 13 ]]; then
TARGET=arm-linux-androideabi
TOOLCHAIN_BIN=$TOOLCHAIN/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin
CC="$TOOLCHAIN_BIN/$TARGET-gcc --sysroot=$SYSROOT"
CXX="$TOOLCHAIN_BIN/$TARGET-g++ --sysroot=$SYSROOT"
AR=$TOOLCHAIN_BIN/$TARGET-ar
RANLIB=$TOOLCHAIN_BIN/$TARGET-ranlib
STRIP=$TOOLCHAIN_BIN/$TARGET-strip
else
TARGET=armv7a-linux-androideabi
CC=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang
CXX=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang++
AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar
RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip
fi
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -DANDROID"
LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8"
TARGET_ARCH_OPTION="--arch=arm --cpu=armv7-a --enable-neon"
;;
arm64-v8a)
if [[ $MAJOR_VERSION -le 13 ]]; then
TARGET=aarch64-linux-android
TOOLCHAIN_BIN=$TOOLCHAIN/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin
CC="$TOOLCHAIN_BIN/$TARGET-gcc --sysroot=$SYSROOT"
CXX="$TOOLCHAIN_BIN/$TARGET-g++ --sysroot=$SYSROOT"
AR=$TOOLCHAIN_BIN/$TARGET-ar
RANLIB=$TOOLCHAIN_BIN/$TARGET-ranlib
STRIP=$TOOLCHAIN_BIN/$TARGET-strip
else
TARGET=aarch64-linux-android
CC=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang
CXX=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang++
AR=$TOOLCHAIN/bin/$TARGET-ar
RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
STRIP=$TOOLCHAIN/bin/$TARGET-strip
fi
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -DANDROID"
LDFLAGS="-march=armv8-a -Wl,-dynamic-linker=/system/bin/linker"
TARGET_ARCH_OPTION="--arch=aarch64"
;;
*)
echo "Unsupported ABI: $ARCH_ABI"
exit 1
;;
esac
export CC CXX AR RANLIB STRIP CFLAGS LDFLAGS
PREFIX=${PWD}/../output/${ARCH_ABI}
echo "=================================================================="
echo "CC="$CC
echo "CXX="$CXX
echo "AR="$AR
echo "RANLIB="$RANLIB
echo "STRIP="$STRIP
echo "CFLAGS="$CFLAGS
echo "LDFLAGS="$LDFLAGS
echo "PREFIX="$PREFIX
echo "=================================================================="
# 注意新版的NDK对none汇编支持不是很好,用--disable-neon禁用(最好更新ffmpeg源码)
if [ $1 == "2" ] ; then
echo "********support X264,fdk-aac encoder******"
./configure \
--prefix=$PREFIX \
--enable-cross-compile \
--sysroot=${SYSROOT} \
--target-os=android \
${TARGET_ARCH_OPTION} \
--disable-everything \
--disable-programs \
--disable-neon \
--enable-pic \
--enable-memalign-hack \
--enable-gpl \
--enable-libx264 \
--enable-nonfree \
--enable-libfdk-aac \
--enable-encoder=aac,libfdk_aac \
--enable-encoder=aac,libx264 \
--enable-decoder=aac,aac_latm,h264 \
--enable-demuxer=aac,asf,ffmetadata,h264,mp3 \
--enable-muxer=adts,h264,mp4,pcm_s16le \
--enable-parser=aac,aac_latm,h264 \
--enable-protocol=file \
--disable-zlib \
--disable-debug \
--cc=$CC \
--cxx=$CXX \
--ar=$AR \
--strip=$STRIP \
--ranlib=$RANLIB \
--extra-cflags="-DANDROID -I${PREFIX}/include $CFLAGS" \
--extra-ldflags="-L${PREFIX}/lib -lx264 -lfdk-aac -Wl,-dynamic-linker=/system/bin/linker -lm -llog -lc $LDFLAGS"
elif [ $1 == "1" ] ; then
echo "*******support h264,mp4,aacplus encoder[deprecated]********"
./configure \
--prefix=$PREFIX \
--enable-cross-compile \
--target-os=android \
--sysroot=$SYSROOT \
${TARGET_ARCH_OPTION} \
--disable-everything \
--disable-programs \
--disable-neon \
--enable-pic \
--enable-memalign-hack \
--enable-gpl \
--enable-libx264 \
--enable-nonfree \
--enable-encoder=aac \
--enable-decoder=aac,aac_latm,h264 \
--enable-demuxer=aac,asf,ffmetadata,h264,latm \
--enable-muxer=adts,h264,mp4,pcm_s16le \
--enable-parser=aac,aac_latm,h264 \
--disable-zlib \
--disable-debug \
--cc=$CC \
--cxx=$CXX \
--ar=$AR \
--strip=$STRIP \
--ranlib=$RANLIB \
--extra-cflags="-DANDROID -I${PREFIX}/include $CFLAGS" \
--extra-ldflags="-L${PREFIX}/lib -lx264 -dynamic-linker=/system/bin/linker -lm -llog -lc $LDFLAGS"
elif [ $1 == "0" ] ; then
echo "******no support encoder********"
./configure \
--prefix=$PREFIX \
${TARGET_ARCH_OPTION} \
--target-os=android \
--enable-cross-compile \
--sysroot=$SYSROOT \
--disable-everything \
--disable-programs \
--disable-neon \
--enable-memalign-hack \
--enable-pic \
--enable-gpl \
--enable-nonfree \
--enable-decoder=aac,aac_latm,h264 \
--enable-demuxer=aac,asf,ffmetadata,h264,latm \
--enable-muxer=adts,h264,mp4,pcm_s16le \
--enable-parser=aac,aac_latm,h264 \
--disable-zlib \
--disable-debug \
--cc=$CC \
--cxx=$CXX \
--ar=$AR \
--strip=$STRIP \
--ranlib=$RANLIB \
--extra-cflags="-DANDROID -I${PREFIX}/include $CFLAGS" \
--extra-ldflags="-L${PREFIX}/lib -dynamic-linker=/system/bin/linker -lm -llog -lc $LDFLAGS"
else
echo "********* check input para. *******"
exit
fi
#make clean and disclean can't delete the bellow 4 files,so delete them manual
rm -f compat/strtod.o compat/strtod.d compat/msvcrt/snprintf.o compat/msvcrt/snprintf.d
make clean
make -j$THREAD_NUM
#编译的静态库(.a)放在$PREFIX/lib目录下,模块对外头文件存放在$PREFIX/lib目录下
make install
(3)fdk-aac/config-android.sh
bash
#!/bin/bash
# 检测 NDK 版本
NDK_VERSION=$(grep -oP "Pkg.Revision\s*=\s*\K.*" $NDK_ROOT_PATH/source.properties)
echo "Detected NDK version: $NDK_VERSION"
# 提取主版本号
MAJOR_VERSION=$(echo $NDK_VERSION | cut -d '.' -f 1)
# 判断是 NDK13 还是 NDK21
if [[ $MAJOR_VERSION -le 13 ]]; then
echo "Using NDK13 (GCC)"
TOOLCHAIN=$NDK_ROOT_PATH/toolchains
SYSROOT=$NDK_ROOT_PATH/platforms/android-$ANDROID_API/arch-arm
if [ $ARCH_ABI == "arm64-v8a" ]; then
SYSROOT=$NDK_ROOT_PATH/platforms/android-$ANDROID_API/arch-arm64
fi
elif [[ $MAJOR_VERSION -ge 21 ]]; then
echo "Using NDK21 (Clang)"
TOOLCHAIN=$NDK_ROOT_PATH/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=$TOOLCHAIN/sysroot
else
echo "Unsupported NDK version: $NDK_VERSION"
echo "Only NDK <= 13 (GCC) or NDK >= 21 (Clang) are supported."
exit 1
fi
# 选择 ABI
case $ARCH_ABI in
armeabi-v7a)
if [[ $MAJOR_VERSION -le 13 ]]; then
TARGET=arm-linux-androideabi
TOOLCHAIN_BIN=$TOOLCHAIN/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin
CC="$TOOLCHAIN_BIN/$TARGET-gcc --sysroot=$SYSROOT"
CXX="$TOOLCHAIN_BIN/$TARGET-g++ --sysroot=$SYSROOT"
AR=$TOOLCHAIN_BIN/$TARGET-ar
RANLIB=$TOOLCHAIN_BIN/$TARGET-ranlib
STRIP=$TOOLCHAIN_BIN/$TARGET-strip
else
TARGET=armv7a-linux-androideabi
CC=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang
CXX=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang++
AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar
RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip
fi
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -DANDROID"
LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8"
;;
arm64-v8a)
if [[ $MAJOR_VERSION -le 13 ]]; then
TARGET=aarch64-linux-android
TOOLCHAIN_BIN=$TOOLCHAIN/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin
CC="$TOOLCHAIN_BIN/$TARGET-gcc --sysroot=$SYSROOT"
CXX="$TOOLCHAIN_BIN/$TARGET-g++ --sysroot=$SYSROOT"
AR=$TOOLCHAIN_BIN/$TARGET-ar
RANLIB=$TOOLCHAIN_BIN/$TARGET-ranlib
STRIP=$TOOLCHAIN_BIN/$TARGET-strip
else
TARGET=aarch64-linux-android
CC=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang
CXX=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang++
AR=$TOOLCHAIN/bin/$TARGET-ar
RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
STRIP=$TOOLCHAIN/bin/$TARGET-strip
fi
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -DANDROID"
LDFLAGS="-march=armv8-a -Wl,-dynamic-linker=/system/bin/linker"
;;
*)
echo "Unsupported ABI: $ARCH_ABI"
exit 1
;;
esac
export CC CXX AR RANLIB STRIP CFLAGS LDFLAGS
# 配置 x264
./configure \
--prefix=${PWD}/../output/${ARCH_ABI} \
--host=$TARGET \
--with-sysroot=$SYSROOT \
--enable-static=yes \
--enable-shared=no
if test $? -ne 0;then
exit $?
fi
# 编译并安装
make clean
make -j$THREAD_NUM
make install
(4)x264/config-android.sh
bash
#!/bin/bash
# 检测 NDK 版本
NDK_VERSION=$(grep -oP "Pkg.Revision\s*=\s*\K.*" $NDK_ROOT_PATH/source.properties)
echo "Detected NDK version: $NDK_VERSION"
# 提取主版本号
MAJOR_VERSION=$(echo $NDK_VERSION | cut -d '.' -f 1)
# 判断是 NDK13 还是 NDK21
if [[ $MAJOR_VERSION -le 13 ]]; then
echo "Using NDK13 (GCC)"
TOOLCHAIN=$NDK_ROOT_PATH/toolchains
SYSROOT=$NDK_ROOT_PATH/platforms/android-$ANDROID_API/arch-arm
if [ $ARCH_ABI == "arm64-v8a" ]; then
SYSROOT=$NDK_ROOT_PATH/platforms/android-$ANDROID_API/arch-arm64
fi
elif [[ $MAJOR_VERSION -ge 21 ]]; then
echo "Using NDK21 (Clang)"
TOOLCHAIN=$NDK_ROOT_PATH/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=$TOOLCHAIN/sysroot
else
echo "Unsupported NDK version: $NDK_VERSION"
echo "Only NDK <= 13 (GCC) or NDK >= 21 (Clang) are supported."
exit 1
fi
# 选择 ABI
case $ARCH_ABI in
armeabi-v7a)
if [[ $MAJOR_VERSION -le 13 ]]; then
TARGET=arm-linux-androideabi
TOOLCHAIN_BIN=$TOOLCHAIN/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin
CC="$TOOLCHAIN_BIN/$TARGET-gcc --sysroot=$SYSROOT"
CXX="$TOOLCHAIN_BIN/$TARGET-g++ --sysroot=$SYSROOT"
AR=$TOOLCHAIN_BIN/$TARGET-ar
RANLIB=$TOOLCHAIN_BIN/$TARGET-ranlib
STRIP=$TOOLCHAIN_BIN/$TARGET-strip
else
TARGET=armv7a-linux-androideabi
CC=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang
CXX=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang++
AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar
RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip
fi
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -DANDROID"
LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8"
;;
arm64-v8a)
if [[ $MAJOR_VERSION -le 13 ]]; then
TARGET=aarch64-linux-android
TOOLCHAIN_BIN=$TOOLCHAIN/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin
CC="$TOOLCHAIN_BIN/$TARGET-gcc --sysroot=$SYSROOT"
CXX="$TOOLCHAIN_BIN/$TARGET-g++ --sysroot=$SYSROOT"
AR=$TOOLCHAIN_BIN/$TARGET-ar
RANLIB=$TOOLCHAIN_BIN/$TARGET-ranlib
STRIP=$TOOLCHAIN_BIN/$TARGET-strip
else
TARGET=aarch64-linux-android
CC=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang
CXX=$TOOLCHAIN/bin/$TARGET$ANDROID_API-clang++
AR=$TOOLCHAIN/bin/$TARGET-ar
RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
STRIP=$TOOLCHAIN/bin/$TARGET-strip
fi
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -DANDROID"
LDFLAGS="-march=armv8-a -Wl,-dynamic-linker=/system/bin/linker"
;;
*)
echo "Unsupported ABI: $ARCH_ABI"
exit 1
;;
esac
export CC CXX AR RANLIB STRIP CFLAGS LDFLAGS
# 配置 x264
./configure \
--prefix=${PWD}/../output/${ARCH_ABI} \
--disable-opencl \
--disable-cli \
--enable-pic \
--enable-static \
--host=$TARGET \
--sysroot=$SYSROOT \
--extra-cflags="$CFLAGS" \
--extra-ldflags="$LDFLAGS"
if test $? -ne 0;then
exit $?
fi
# 编译并安装
make clean
make -j$THREAD_NUM
make install
三、ffmpeg-android-maker
项目地址: ffmpeg-android-maker (变种将多个so合并一个so:ffmpeg-android-build)
下载NDK :these obsolete versions of the NDK
3.1 项目使用
(1)安装依赖
bash
sudo apt install -y meson nasm ninja-build autoconf libtool unzip cmake git pkg-config curl
(2)下载NDK和ffmpeg-android-maker
下载NDK并解压: android-ndk-r21e
下载ffmpeg-android-maker:
bash
git clone https://github.com/Javernaut/ffmpeg-android-maker.git
(3)使用
bash
# SDK路径(必须),由于项目没有使用到,这里随便填一个。
export ANDROID_SDK_HOME=$(pwd)
# NDK位置(必须)
export ANDROID_NDK_HOME=/home/ubuntu/android-ndk-r24
# 编译
./ffmpeg-android-maker.sh x264 -android=21 -abis=arm,arm64
库的位置
output/
├── include
│ ├── arm64-v8a
│ └── armeabi-v7a
└── lib
├── arm64-v8a
└── armeabi-v7a
(4)存在问题
编译x264时提示:
bash
bin/llvm-strip: error: 'common/arm/cpu-a.o': not stripping symbol 'cpu_enable_armv7_counter' because it is named in a relocation
说明:用llvm-strip尝试剥离符号时失败,这些符号在重定位中被引用。不影响编译
3.2 常见参数
(1)ABI
使用格式 :--target-abis=xxx
或 -abis=xxx
ABI值:
- x86
- x86_64
- armeabi-v7a 或 arm
- arm64-v8a 或 arm64
举例:
./ffmpeg-android-maker.sh -abis=arm,arm64
./ffmpeg-android-maker.sh --target-abis=armeabi-v7a,x86
./ffmpeg-android-maker.sh -abis=armeabi-v7a,arm64-v8a,x86,x86_64
./ffmpeg-android-maker.sh
# 默认是编译上面4种ABI
(2)Android API版本
使用格式 :--android-api-level=x
或 -android=x
举例:
./ffmpeg-android-maker.sh -android=19
./ffmpeg-android-maker.sh --android-api-level=24
注意:64 位 ABI(arm64-v8a 和 x86_64)的最小值为 21(因为 Android 5 是第一个支持 64 位的 ABI)。
(3)Binutils 类型
Binutils 的值:
gnu
默认值llvm
举例:
./ffmpeg-android-maker.sh -binutils=llvm
# 使用llvm./ffmpeg-android-maker.sh
# 使用gnu
注意:从 NDK r18 版本开始,Android NDK 正式停止对 GNU 工具链(GCC)的支持,并全面转向 Clang 作为默认编译器。
(4)支持的外部库
库名称 | 启用标志 | GPL | 备注 |
---|---|---|---|
libaom | --enable-libaom 或 -aom | No | 该库的编码器需要 Android API 至少 18 才能编译(-android=18)。解码器可使用 -android=16 构建。 |
libbluray | --enable-libbluray 或 -bluray | No | |
libdav1d | --enable-libdav1d 或 -dav1d | No | 使用 Meson 构建系统。某些版本的 Meson 可能无法构建该库,0.52.1 和 0.53.2 版本正常。需要 nasm >= 2.14 和 ninja >= 1.9。如果安装必要软件有问题,可查看 Docker 支持页面。 |
libfreetype | --enable-libfreetype 或 -freetype | No | |
libfribidi | --enable-libfribidi 或 -fribidi | No | |
libmp3lame | --enable-libmp3lame 或 -mp3lame 或 -lame | No | |
libopus | --enable-libopus 或 -opus | No | |
libspeex | --enable-libspeex 或 -speex | No | |
libtwolame | --enable-libtwolame 或 -twolame | No | 当前不依赖 libsndfile。 |
libvpx | --enable-libvpx 或 -vpx | No | FFmpeg 本身支持 VP8 和 VP9 解码器,优先级高于 libvpx_vp8 和 libvpx_vp9。如果不需要原生 VP8 和 VP9,可通过 --disable-decoder=vp8 和 --disable-decoder=vp9 禁用。使用 LLVM 编译时需要 -android=21。 |
libwavpack | --enable-libwavpack 或 -wavpack | No | |
libwebp | --enable-libwebp 或 -webp | No | |
libx264 | --enable-libx264 或 -x264 | Yes | 启用该库会导致 FFmpeg 的输出二进制文件和共享库遵循 GPL 2 许可证。 |
libx265 | --enable-libx265 或 -x265 | Yes | H.265/HEVC 视频编码器。启用该库会导致 FFmpeg 的输出二进制文件和共享库遵循 GPL 2 许可证。(备注基于常见 FFmpeg 配置推测) |
libxml2 | --enable-libxml2 或 -xml2 | No | 用于解析和处理 XML 文件的库。(备注基于常见 FFmpeg 配置推测) |
mbedtls | --enable-mbedtls 或 -mbedtls | No | 提供加密和 SSL/TLS 功能的轻量级加密库。(备注基于常见 FFmpeg 配置推测) |
标志 | 含义 |
---|---|
--enable-all-free 或 -all-free | 启用所有支持的免费库,这些库不会更改结果二进制文件的许可证,保持 LGPL 2.1。 |
--enable-all-gpl 或 -all-gpl | 启用所有支持的库,这些库会将结果二进制文件的许可证更改为 GPL 2 或更高版本。 |
举例:
- 启用x264:
../ffmpeg-android-maker.sh -x264
- 详细看:
scripts/parse-arguments.sh
脚本
(5) 指定ffmpeg版本
三种方式指定版本:
- Git 标签
- 获取tag:ffmpeg.git / tags
./ffmpeg-android-maker.sh --source-git-tag=n4.1.4
- Git 分支
- 获取tag:ffmpeg.git / heads
./ffmpeg-android-maker.sh --source-git-branch=release/4.2
- 特定版本的 Tar 存档
- 获取版本号:ffmpeg.org
./ffmpeg-android-maker.sh --source-tar=4.2
四、NDK编译参数说明
4.1 NDK与sysroot
- 旧版本NDK的sysroot在:platforms/android-$(android_api)
- arch-arm
- arch-arm64
- 新版本NDK的sysroot在:toolchains/llvm/prebuilt/linux-x86_64/sysroot
4.2 不同版本NDK的编译器
NDK 版本 | GCC 支持 | Clang 支持 | 关键变更 |
---|---|---|---|
≤ r13 | ✅ 默认 | ⚠️ 可选 | 引入 Clang 作为替代方案 |
r14 - r17 | ⚠️ 保留(废弃状态) | ✅ 推荐 | GCC 标记为废弃,建议迁移至 Clang |
≥ r18 | ❌ 完全移除 | ✅ 唯一编译器 | 强制使用 Clang |
4.3 ABI与Android API关系
arm64-v8a是Android API 21开始引入的特性,所以API低于21的 都只能编译armeabi-v7a
4.4 ABI与target_host
编译器类型 | 架构 | target_host | 编译器名称 | toolchains路径 |
---|---|---|---|---|
gcc | armeabi-v7a | arm-linux-androideabi | arm-linux-androideabi-gcc arm-linux-androideabi-g++ arm-linux-androideabi-ar arm-linux-androideabi-ranlib arm-linux-androideabi-strip | toolchains/arm-linux-androideabi-4.9 |
gcc | arm64-v8a | aarch64-linux-android | aarch64-linux-android-gcc aarch64-linux-android-g++ aarch64-linux-android-ar aarch64-linux-android-ranlib aarch64-linux-android-strip | toolchains/aarch64-linux-android-4.9 |
clang | armeabi-v7a | armv7a-linux-androideabi | armv7a-linux-androideabi21-clang armv7a-linux-androideabi21-clang++ arm-linux-androideabi-ar arm-linux-androideabi-ranlib arm-linux-androideabi-strip | toolchains/llvm/prebuilt/linux-x86_64/bin |
clang | arm64-v8a | aarch64-linux-android | aarch64-linux-android21-clang aarch64-linux-android21-clang++ aarch64-linux-android-ar aarch64-linux-android-ranlib aarch64-linux-android-strip | toolchains/llvm/prebuilt/linux-x86_64/bin |
注意:上面的21是Android的API版本
4.5 ABI与CFLAGS、LDFLAGS
ABI
- armeabi-v7a
- CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -DANDROID"
- LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8"
- arm64-v8a
- CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -DANDROID"
- LDFLAGS="-march=armv8-a"
参数解析:
bash
armeabi-v7a
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7A__ -O3 -DANDROID"
LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8"
CFLAGS
-O3:这是 GCC/Clang 的优化级别选项,-O3 表示最高级别的优化。
-DANDROID:这是一个预处理器宏定义,用于在代码中标识 Android 平台。
-march=armv7-a:指定目标架构为 ARMv7-A。
-mfloat-abi=softfp:使用软浮点 ABI(与硬件浮点兼容)。
-mfpu=neon:启用 NEON 指令集(SIMD 加速)。
-D__ARM_ARCH_7A__:定义 ARMv7-A 架构宏。
LDFLAGS
-march=armv7-a:确保链接器使用 ARMv7-A 架构。
-Wl,--fix-cortex-a8:修复 Cortex-A8 处理器的某些硬件 bug。
arm64-v8a
CFLAGS="-march=armv8-a -D__ARM_ARCH_8A__ -O3 -DANDROID"
LDFLAGS="-march=armv8-a"
CFLAGS
-march=armv8-a:指定目标架构为 ARMv8-A。
-D__ARM_ARCH_8A__:定义 ARMv8-A 架构宏。
LDFLAGS
-march=armv8-a:确保链接器使用 ARMv8-A 架构。