3.1 Android NDK交叉编译FFmpeg

一、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 目录结构

 ./
├── 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和源码)

export http_proxy="http://127.0.0.1:10809"
export https_proxy="http://127.0.0.1:10809"

下载NDK和源代码:

# 下载: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中的参数:
在这里插入图片描述

编译:

# 先编译x264和fdk-aac,再编译ffmpeg
./build_android.sh all

# 只编译x264库
./build_android.sh x264

# 只编译fdk-aac库
./build_android.sh fdk-aac

1.3 库的位置

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 脚本内容与说明

脚本目录结构:

./
├── 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

#!/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

#!/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

#!/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

#!/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

#!/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 目录结构

./
├── 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参数:
在这里插入图片描述

编译:

# 先编译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

#!/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

#!/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

#!/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

#!/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)

下载NDKthese obsolete versions of the NDK

3.1 项目使用

(1)安装依赖

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:

git clone https://github.com/Javernaut/ffmpeg-android-maker.git

(3)使用

# 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时提示:

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 或 -aomNo该库的编码器需要 Android API 至少 18 才能编译(-android=18)。解码器可使用 -android=16 构建。
libbluray–enable-libbluray 或 -blurayNo
libdav1d–enable-libdav1d 或 -dav1dNo使用 Meson 构建系统。某些版本的 Meson 可能无法构建该库,0.52.1 和 0.53.2 版本正常。需要 nasm >= 2.14 和 ninja >= 1.9。如果安装必要软件有问题,可查看 Docker 支持页面。
libfreetype–enable-libfreetype 或 -freetypeNo
libfribidi–enable-libfribidi 或 -fribidiNo
libmp3lame–enable-libmp3lame 或 -mp3lame 或 -lameNo
libopus–enable-libopus 或 -opusNo
libspeex–enable-libspeex 或 -speexNo
libtwolame–enable-libtwolame 或 -twolameNo当前不依赖 libsndfile。
libvpx–enable-libvpx 或 -vpxNoFFmpeg 本身支持 VP8 和 VP9 解码器,优先级高于 libvpx_vp8 和 libvpx_vp9。如果不需要原生 VP8 和 VP9,可通过 --disable-decoder=vp8 和 --disable-decoder=vp9 禁用。使用 LLVM 编译时需要 -android=21。
libwavpack–enable-libwavpack 或 -wavpackNo
libwebp–enable-libwebp 或 -webpNo
libx264–enable-libx264 或 -x264Yes启用该库会导致 FFmpeg 的输出二进制文件和共享库遵循 GPL 2 许可证。
libx265–enable-libx265 或 -x265YesH.265/HEVC 视频编码器。启用该库会导致 FFmpeg 的输出二进制文件和共享库遵循 GPL 2 许可证。(备注基于常见 FFmpeg 配置推测)
libxml2–enable-libxml2 或 -xml2No用于解析和处理 XML 文件的库。(备注基于常见 FFmpeg 配置推测)
mbedtls–enable-mbedtls 或 -mbedtlsNo提供加密和 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 标签
  • Git 分支
  • 特定版本的 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路径
gccarmeabi-v7aarm-linux-androideabiarm-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
gccarm64-v8aaarch64-linux-androidaarch64-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
clangarmeabi-v7aarmv7a-linux-androideabiarmv7a-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
clangarm64-v8aaarch64-linux-androidaarch64-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”

参数解析:

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 架构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值