Linux 环境下交叉编译 Android 的 FFmpeg 库的完整指南

在 Linux 环境下交叉编译 Android 的 FFmpeg 库的完整指南:

环境准备

1. 安装 Android NDK

# 方法一:使用 Android Studio SDK Manager
# Tools -> SDK Manager -> SDK Tools -> NDK (Side by side)

# 方法二:命令行安装
sdkmanager "ndk;25.1.8937393"

# 方法三:直接下载
wget https://dl.google.com/android/repository/android-ndk-r25c-linux.zip
unzip android-ndk-r25c-linux.zip
export ANDROID_NDK_HOME=/path/to/android-ndk-r25c

2. 安装必要工具

# Ubuntu/Debian
sudo apt update
sudo apt install -y \
    build-essential \
    autoconf \
    automake \
    libtool \
    pkg-config \
    yasm \
    nasm \
    git \
    wget \
    make

# 创建工作目录
mkdir -p ~/android_ffmpeg/{sources,build,output}
cd ~/android_ffmpeg

编译依赖库

1. 编译 LAME 库

# 下载 LAME
cd ~/android_ffmpeg/sources
wget http://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
tar -xzf lame-3.100.tar.gz
cd lame-3.100

# 创建构建脚本
cat > build_android.sh << 'EOF'
#!/bin/bash

NDK_ROOT=$ANDROID_NDK_HOME
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
PLATFORM=$TOOLCHAIN/sysroot

function build_lame() {
    API=$1
    ARCH=$2
    CPU=$3
    PREFIX=$4
    
    ./configure \
        --prefix=$PREFIX \
        --host=$CPU-linux-android$API \
        --disable-shared \
        --enable-static \
        --disable-frontend \
        CC=$TOOLCHAIN/bin/$CPU-linux-android$API-clang \
        CXX=$TOOLCHAIN/bin/$CPU-linux-android$API-clang++ \
        AR=$TOOLCHAIN/bin/llvm-ar \
        AS=$TOOLCHAIN/bin/$CPU-linux-android$API-as \
        LD=$TOOLCHAIN/bin/$CPU-linux-android$API-ld \
        RANLIB=$TOOLCHAIN/bin/llvm-ranlib \
        STRIP=$TOOLCHAIN/bin/$CPU-linux-android$API-strip \
        CFLAGS="-fPIC" \
        LDFLAGS="-fPIC"
    
    make clean
    make -j$(nproc)
    make install
}

# 构建不同架构
build_lame 21 armv7a armv7a-linux-androideabi ~/android_ffmpeg/build/lame/armv7a
build_lame 21 aarch64 aarch64-linux-android ~/android_ffmpeg/build/lame/aarch64
build_lame 21 x86 i686-linux-android ~/android_ffmpeg/build/lame/x86
build_lame 21 x86_64 x86_64-linux-android ~/android_ffmpeg/build/lame/x86_64
EOF

chmod +x build_android.sh
./build_android.sh

2. 编译其他依赖库(可选)

# Ogg 库
cd ~/android_ffmpeg/sources
wget https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.5.tar.gz
tar -xzf libogg-1.3.5.tar.gz
cd libogg-1.3.5

# Vorbis 库
cd ~/android_ffmpeg/sources
wget https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.7.tar.gz
tar -xzf libvorbis-1.3.7.tar.gz
cd libvorbis-1.3.7

编译 FFmpeg

1. 下载 FFmpeg 源码

cd ~/android_ffmpeg/sources
git clone https://git.ffmpeg.org/ffmpeg.git
cd ffmpeg

2. 创建交叉编译脚本

cat > build_android_ffmpeg.sh << 'EOF'
#!/bin/bash

NDK_ROOT=$ANDROID_NDK_HOME
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
PLATFORM=$TOOLCHAIN/sysroot

COMMON_CONFIGURE_FLAGS="
    --enable-cross-compile \
    --target-os=android \
    --disable-shared \
    --enable-static \
    --disable-programs \
    --disable-doc \
    --disable-htmlpages \
    --disable-manpages \
    --disable-podpages \
    --disable-txtpages \
    --disable-network \
    --disable-everything \
    --enable-encoder=libmp3lame \
    --enable-decoder=mp3*,pcm* \
    --enable-muxer=mp3,wav \
    --enable-demuxer=mp3,wav \
    --enable-parser=mpegaudio \
    --enable-filter=aresample \
    --enable-protocol=file \
    --enable-swresample \
    --enable-avutil \
    --enable-avcodec \
    --enable-avformat \
    --enable-small \
    --enable-neon \
    --enable-thumb \
    --pkg-config-flags=--static \
    --extra-cflags="-fPIC" \
    --extra-ldflags="-fPIC" \
    --extra-libs="-lm -lz"
"

function build_ffmpeg() {
    API=$1
    ARCH=$2
    CPU=$3
    PREFIX=$4
    ADDI_CFLAGS=$5
    
    # 创建临时构建目录
    rm -rf build_$ARCH
    mkdir -p build_$ARCH
    cd build_$ARCH
    
    # 配置
    ../configure \
        --prefix=$PREFIX \
        --arch=$ARCH \
        --cpu=$CPU \
        --cc=$TOOLCHAIN/bin/$CPU-linux-android$API-clang \
        --cxx=$TOOLCHAIN/bin/$CPU-linux-android$API-clang++ \
        --cross-prefix=$TOOLCHAIN/bin/$CPU-linux-android$API- \
        --nm=$TOOLCHAIN/bin/llvm-nm \
        --strip=$TOOLCHAIN/bin/$CPU-linux-android$API-strip \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="-L$PREFIX/lib" \
        --enable-libmp3lame \
        --extra-cflags="-I$PREFIX/include" \
        $COMMON_CONFIGURE_FLAGS
    
    # 编译
    make clean
    make -j$(nproc)
    make install
    
    cd ..
}

# 构建不同架构
build_ffmpeg 21 armv7a armv7a-linux-androideabi ~/android_ffmpeg/build/lame/armv7a "-march=armv7-a -mfloat-abi=softfp -mfpu=neon"
build_ffmpeg 21 aarch64 aarch64-linux-android ~/android_ffmpeg/build/lame/aarch64 "-march=armv8-a"
build_ffmpeg 21 x86 i686-linux-android ~/android_ffmpeg/build/lame/x86 "-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
build_ffmpeg 21 x86_64 x86_64-linux-android ~/android_ffmpeg/build/lame/x86_64 "-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
EOF

chmod +x build_android_ffmpeg.sh

3. 简化版本的编译脚本

cat > build_simple.sh << 'EOF'
#!/bin/bash

NDK_ROOT=$ANDROID_NDK_HOME
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64

# 构建函数
build_arch() {
    local API=$1
    local ARCH=$2
    local CPU=$3
    local HOST=$4
    local EXTRA_CFLAGS=$5
    local OUTPUT_DIR=~/android_ffmpeg/output/$ARCH
    
    echo "Building for $ARCH..."
    
    # 清理
    rm -rf build_$ARCH
    mkdir -p build_$ARCH
    
    cd ffmpeg
    
    # 配置
    ./configure \
        --prefix=$OUTPUT_DIR \
        --enable-cross-compile \
        --target-os=android \
        --arch=$ARCH \
        --cpu=$CPU \
        --cc=$TOOLCHAIN/bin/$HOST$API-clang \
        --cxx=$TOOLCHAIN/bin/$HOST$API-clang++ \
        --cross-prefix=$TOOLCHAIN/bin/$HOST$API- \
        --nm=$TOOLCHAIN/bin/llvm-nm \
        --ar=$TOOLCHAIN/bin/llvm-ar \
        --as=$TOOLCHAIN/bin/$HOST$API-as \
        --strip=$TOOLCHAIN/bin/$HOST$API-strip \
        --extra-cflags="-fPIC -DANDROID -D__ANDROID_API__=$API $EXTRA_CFLAGS" \
        --extra-ldflags="-fPIC" \
        --enable-shared \
        --disable-static \
        --disable-programs \
        --disable-doc \
        --disable-htmlpages \
        --disable-manpages \
        --disable-podpages \
        --disable-txtpages \
        --disable-network \
        --enable-libmp3lame \
        --extra-cflags="-I~/android_ffmpeg/build/lame/$ARCH/include" \
        --extra-ldflags="-L~/android_ffmpeg/build/lame/$ARCH/lib" \
        --enable-encoder=libmp3lame,pcm_s16le \
        --enable-decoder=mp3,pcm_s16le \
        --enable-muxer=mp3,wav \
        --enable-demuxer=mp3,wav \
        --enable-parser=mpegaudio \
        --enable-filter=aresample \
        --enable-protocol=file \
        --enable-swresample \
        --enable-avutil \
        --enable-avcodec \
        --enable-avformat \
        --enable-small
    
    # 编译和安装
    make clean
    make -j$(nproc)
    make install
    
    cd ..
}

# 构建所有架构
mkdir -p ~/android_ffmpeg/output

build_arch 21 arm armv7a-linux-androideabi armv7a-linux-androideabi "-march=armv7-a -mfloat-abi=softfp -mfpu=neon"
build_arch 21 aarch64 aarch64-linux-android aarch64-linux-android "-march=armv8-a"
build_arch 21 x86 i686-linux-android i686-linux-android "-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
build_arch 21 x86_64 x86_64-linux-android x86_64-linux-android "-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
EOF

chmod +x build_simple.sh

创建统一的构建脚本

cat > build_android_all.sh << 'EOF'
#!/bin/bash

# 设置环境变量
export ANDROID_NDK_HOME=${ANDROID_NDK_HOME:-/opt/android-ndk-r25c}
NDK_ROOT=$ANDROID_NDK_HOME
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64

# 创建目录
WORK_DIR=~/android_ffmpeg
mkdir -p $WORK_DIR/{sources,build,output}
cd $WORK_DIR/sources

# 下载源码(如果需要)
if [ ! -d "ffmpeg" ]; then
    git clone https://git.ffmpeg.org/ffmpeg.git
fi

if [ ! -d "lame-3.100" ]; then
    wget -c http://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
    tar -xzf lame-3.100.tar.gz
fi

# 架构配置
declare -A ARCH_CONFIGS=(
    ["armv7a"]="arm armv7a-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=neon"
    ["aarch64"]="aarch64 aarch64-linux-android -march=armv8-a"
    ["x86"]="x86 i686-linux-android -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
    ["x86_64"]="x86_64 x86_64-linux-android -march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
)

# 构建 LAME
build_lame() {
    local API=$1
    local ARCH=$2
    local CPU=$3
    local PREFIX=$WORK_DIR/build/lame/$ARCH
    
    echo "Building LAME for $ARCH..."
    
    cd $WORK_DIR/sources/lame-3.100
    make clean
    
    ./configure \
        --prefix=$PREFIX \
        --host=$CPU-linux-android$API \
        --disable-shared \
        --enable-static \
        --disable-frontend \
        CC=$TOOLCHAIN/bin/$CPU-linux-android$API-clang \
        CXX=$TOOLCHAIN/bin/$CPU-linux-android$API-clang++ \
        AR=$TOOLCHAIN/bin/llvm-ar \
        AS=$TOOLCHAIN/bin/$CPU-linux-android$API-as \
        LD=$TOOLCHAIN/bin/$CPU-linux-android$API-ld \
        RANLIB=$TOOLCHAIN/bin/llvm-ranlib \
        STRIP=$TOOLCHAIN/bin/$CPU-linux-android$API-strip \
        CFLAGS="-fPIC" \
        LDFLAGS="-fPIC"
    
    make -j$(nproc)
    make install
}

# 构建 FFmpeg
build_ffmpeg() {
    local API=$1
    local ARCH=$2
    local CPU=$3
    local HOST=$4
    local EXTRA_CFLAGS=$5
    local OUTPUT_DIR=$WORK_DIR/output/$ARCH
    
    echo "Building FFmpeg for $ARCH..."
    
    cd $WORK_DIR/sources/ffmpeg
    
    # 清理
    make clean
    
    # 配置
    ./configure \
        --prefix=$OUTPUT_DIR \
        --enable-cross-compile \
        --target-os=android \
        --arch=$ARCH \
        --cpu=$CPU \
        --cc=$TOOLCHAIN/bin/$HOST$API-clang \
        --cxx=$TOOLCHAIN/bin/$HOST$API-clang++ \
        --cross-prefix=$TOOLCHAIN/bin/$HOST$API- \
        --nm=$TOOLCHAIN/bin/llvm-nm \
        --ar=$TOOLCHAIN/bin/llvm-ar \
        --as=$TOOLCHAIN/bin/$HOST$API-as \
        --strip=$TOOLCHAIN/bin/$HOST$API-strip \
        --extra-cflags="-fPIC -DANDROID -D__ANDROID_API__=$API $EXTRA_CFLAGS" \
        --extra-ldflags="-fPIC -L$WORK_DIR/build/lame/$ARCH/lib" \
        --extra-cxxflags="-fPIC" \
        --enable-shared \
        --disable-static \
        --disable-programs \
        --disable-doc \
        --disable-htmlpages \
        --disable-manpages \
        --disable-podpages \
        --disable-txtpages \
        --disable-network \
        --enable-libmp3lame \
        --extra-cflags="-I$WORK_DIR/build/lame/$ARCH/include" \
        --enable-encoder=libmp3lame,pcm_s16le \
        --enable-decoder=mp3,pcm_s16le \
        --enable-muxer=mp3,wav \
        --enable-demuxer=mp3,wav \
        --enable-parser=mpegaudio \
        --enable-filter=aresample \
        --enable-protocol=file \
        --enable-swresample \
        --enable-avutil \
        --enable-avcodec \
        --enable-avformat \
        --enable-small \
        --enable-jni \
        --enable-mediacodec
    
    # 编译和安装
    make -j$(nproc)
    make install
}

# 主构建过程
API_LEVEL=21

# 为每个架构构建 LAME 和 FFmpeg
for ARCH in "${!ARCH_CONFIGS[@]}"; do
    CONFIG=(${ARCH_CONFIGS[$ARCH]})
    ARCH_NAME=${CONFIG[0]}
    CPU=${CONFIG[1]}
    CFLAGS=${CONFIG[2]}
    HOST=$CPU
    
    echo "=== Building for $ARCH ==="
    
    # 构建 LAME
    build_lame $API_LEVEL $ARCH_NAME $CPU
    
    # 构建 FFmpeg
    build_ffmpeg $API_LEVEL $ARCH_NAME $CPU $HOST "$CFLAGS"
done

echo "=== Build completed ==="
echo "Output files are in: $WORK_DIR/output/"
EOF

chmod +x build_android_all.sh

创建 CMakeLists.txt 用于 Android 项目

# CMakeLists.txt for Android FFmpeg
cmake_minimum_required(VERSION 3.18.1)

project("ffmpeg_android")

# 设置架构
set(FFMPEG_ARCH ${ANDROID_ABI})

# FFmpeg 路径
set(FFMPEG_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/${FFMPEG_ARCH})

# 包含目录
include_directories(
    ${FFMPEG_ROOT}/include
)

# 库目录
link_directories(
    ${FFMPEG_ROOT}/lib
)

# 添加库
add_library(
    ffmpeg_android
    SHARED
    ffmpeg_jni.cpp
)

# 链接 FFmpeg 库
target_link_libraries(
    ffmpeg_android
    avformat
    avcodec
    avutil
    swresample
    swscale
    postproc
    avfilter
    mp3lame
    log
    android
)

创建 JNI 接口示例

// ffmpeg_jni.cpp
#include <jni.h>
#include <android/log.h>

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libswresample/swresample.h>
}

#define LOG_TAG "FFmpegAndroid"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

extern "C"
JNIEXPORT jstring JNICALL
Java_com_yourpackage_FFmpegHelper_getFFmpegVersion(JNIEnv *env, jobject thiz) {
    const char* version = av_version_info();
    LOGI("FFmpeg Version: %s", version);
    return env->NewStringUTF(version);
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_yourpackage_FFmpegHelper_initFFmpeg(JNIEnv *env, jobject thiz) {
    avformat_network_init();
    LOGI("FFmpeg initialized");
    return JNI_TRUE;
}

验证构建结果

# 检查生成的文件
ls -la ~/android_ffmpeg/output/*/lib/
ls -la ~/android_ffmpeg/output/*/include/

# 检查库的架构
file ~/android_ffmpeg/output/armv7a/lib/*.so

打包脚本

cat > package_ffmpeg.sh << 'EOF'
#!/bin/bash

WORK_DIR=~/android_ffmpeg
OUTPUT_DIR=$WORK_DIR/output
PACKAGE_DIR=$WORK_DIR/package

# 创建包目录
rm -rf $PACKAGE_DIR
mkdir -p $PACKAGE_DIR/include
mkdir -p $PACKAGE_DIR/libs/{armeabi-v7a,arm64-v8a,x86,x86_64}

# 复制头文件(从任意架构复制,因为头文件是通用的)
cp -r $OUTPUT_DIR/armv7a/include/* $PACKAGE_DIR/include/

# 复制库文件
cp $OUTPUT_DIR/armv7a/lib/*.so $PACKAGE_DIR/libs/armeabi-v7a/
cp $OUTPUT_DIR/aarch64/lib/*.so $PACKAGE_DIR/libs/arm64-v8a/
cp $OUTPUT_DIR/x86/lib/*.so $PACKAGE_DIR/libs/x86/
cp $OUTPUT_DIR/x86_64/lib/*.so $PACKAGE_DIR/libs/x86_64/

# 创建 zip 包
cd $PACKAGE_DIR
zip -r ffmpeg_android.zip include libs

echo "Package created: $PACKAGE_DIR/ffmpeg_android.zip"
EOF

chmod +x package_ffmpeg.sh
./package_ffmpeg.sh

使用说明

1. 设置环境变量

export ANDROID_NDK_HOME=/path/to/your/ndk
export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH

2. 执行构建

cd ~/android_ffmpeg
./build_android_all.sh

3. 在 Android 项目中使用

将生成的库文件复制到 Android 项目的 src/main/jniLibs/ 目录下对应的架构文件夹中。

完成这些步骤后,你就有了可以在 Android 项目中使用的 FFmpeg 库,支持 MP3 LAME 编解码器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值