Android 编译FFmpeg4.3.1并集成x264

编译前的准备

Ubuntu 20.04.6 LTS

Android NDK r21e(21.2.6472646)需要准备Linux版本和Windows版本

FFmpeg-4.3.1

x264

编译过程及脚本

主要流程:先编译好准备的第三方库,生成相应的动态库文件,最后在编译FFmpeg时关联起来。在实际应用中可能还需要编译不同的ABI才能在不同的设备上使用,本文FFmpeg以编译arm64-v8a为例。

存储目录结构

Shell 复制代码
home
 ├── ffmpeg_build
 │    └── out
 │        └── arm64-v8a
 └── ffmpeg_sources
     ├── ffmpeg-4.3.1
     ├── ndk
     ├── x264 
     └── other_libs # 存储第三方库编译的动态库文件
         └── x264

编译第三方库

x264

Shell 复制代码
#!/bin/bash
set -e

NDK=# 实际ndk路径
X264_SRC=# 实际X264源码路径
INSTALL_BASE=# 实际存储第三方库编译的动态库文件路径

API=21
ABIS=("armeabi-v7a" "arm64-v8a" "x86" "x86_64")

TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64

for ABI in "${ABIS[@]}"; do
    echo "============================="
    echo " 正在构建 ABI: $ABI"
    echo "============================="

    case $ABI in
        armeabi-v7a)
            TARGET=armv7a-linux-androideabi
            ARCH=arm
            CROSS_PREFIX=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
            CC=$TOOLCHAIN/bin/armv7a-linux-androideabi${API}-clang
            ;;
        arm64-v8a)
            TARGET=aarch64-linux-android
            ARCH=arm64
            CROSS_PREFIX=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-
            CC=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang
            ;;
        x86)
            TARGET=i686-linux-android
            ARCH=x86
            CROSS_PREFIX=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android-
            CC=$TOOLCHAIN/bin/i686-linux-android${API}-clang
            ;;
        x86_64)
            TARGET=x86_64-linux-android
            ARCH=x86_64
            CROSS_PREFIX=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-
            CC=$TOOLCHAIN/bin/x86_64-linux-android${API}-clang
            ;;
        *)
            echo " Unsupported ABI: $ABI"
            exit 1
            ;;
    esac

    BUILD_DIR=$X264_SRC/build/$ABI
    INSTALL_DIR=$INSTALL_BASE/$ABI/x264
    mkdir -p "$BUILD_DIR" "$INSTALL_DIR"

    rm -rf "$BUILD_DIR"/*
    cd "$BUILD_DIR"

    echo " 配置 x264 for $ABI"

    # 设置 sysroot 为 llvm 自带的 sysroot,兼容新 NDK
    SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot

    # 设置环境变量,指定交叉编译器和 sysroot
    export CC=$CC
    export CFLAGS="--sysroot=$SYSROOT"
    export LDFLAGS="--sysroot=$SYSROOT"

    $X264_SRC/configure \
        --prefix="$INSTALL_DIR" \
        --host=$TARGET \
        --enable-shared \
        --disable-cli \
        --enable-pic \
        --disable-asm \
        --sysroot="$SYSROOT"

    echo " 编译 x264 动态库"
    make -j$(nproc)
    make install

    echo " 静态库完成: $INSTALL_DIR/lib/libx264.a"
    echo
done

echo " 所有 ABI 构建完成,输出在: $INSTALL_BASE/<abi>/x264"

随后切换到FFmpeg目录下,新建以下脚本

Shell 复制代码
#!/bin/bash

set -e

NDK=/home/puffy/sang/ffmpeg_sources/ndk/21.2.6472646/android-ndk-r21e
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
API=21
ARCH=arm64-v8a
CPU=armv8-a
PLATFORM=aarch64-linux-android
PREFIX=/home/puffy/sang/ffmpeg_build/out/$ARCH
X264_PATH=/home/puffy/sang/ffmpeg_sources/other_libs/$ARCH/x264

export CC=$TOOLCHAIN/bin/${PLATFORM}${API}-clang
export CXX=$TOOLCHAIN/bin/${PLATFORM}${API}-clang++
export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld
export NM=$TOOLCHAIN/bin/aarch64-linux-android-nm
export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip

export PKG_CONFIG_PATH=$X264_PATH/lib/pkgconfig

./configure \
    --prefix=$PREFIX \
    --target-os=android \
    --arch=aarch64 \
    --cpu=$CPU \
    --enable-cross-compile \
    --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \
    --cc=$CC \
    --cxx=$CXX \
    --sysroot=$TOOLCHAIN/sysroot \
    --enable-gpl \
    --enable-libx264 \
    --enable-shared \
    --disable-static \
    --disable-doc \
    --disable-programs \
    --disable-symver \
    --extra-cflags="-I$X264_PATH/include -march=$CPU" \
    --extra-ldflags="-L$X264_PATH/lib"

make -j$(nproc)
make install

#  拷贝 libx264.so
X264_SO=$X264_PATH/lib/libx264.so
DEST_SO_DIR=$PREFIX/lib

if [ -f "$X264_SO" ]; then
    echo " 拷贝 libx264.so 到 FFmpeg 输出目录:$DEST_SO_DIR"
    cp -v "$X264_SO" "$DEST_SO_DIR/"
else
    echo " 未找到 libx264.so,请确认 x264 已正确编译:$X264_SO"
    exit 1
fi

#  拷贝 include 头文件
X264_INCLUDE_DIR=$X264_PATH/include
DEST_INCLUDE_DIR=$PREFIX/include/x264

if [ -d "$X264_INCLUDE_DIR" ]; then
    echo " 拷贝 x264 include 头文件到:$DEST_INCLUDE_DIR"
    mkdir -p "$DEST_INCLUDE_DIR"
    cp -v "$X264_INCLUDE_DIR"/*.h "$DEST_INCLUDE_DIR/"
else
    echo " 未找到 x264 include 目录,请确认路径:$X264_INCLUDE_DIR"
    exit 1
fi


echo " 编译完成,所有文件已就绪"

如果需要编译其他ABI或别的第三方库可参看github

编译成功后可在输出文件得到以下内容

在新建Native C++ 项目后,将ndk配置为和之前在Linux编译的ndk版本一致,新建jniLibs/arm64-v8a,lib文件下的so文件拷贝到此处

include下的文件拷贝到cpp/ffmpeg/include下

随后在CMakeList引入FFmpeg

txt 复制代码
# 支持gnu++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
set(CMAKE_BUILD_TYPE Debug)

# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/ffmpeg)

# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir}/include)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath=$ORIGIN") #注意:告诉 CMake 不要使用 .so 的 SONAME

# 3. 添加ffmpeg相关的so库
add_library(avutil
        SHARED
        IMPORTED)
set_target_properties(avutil
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavutil.so)

add_library(swresample
        SHARED
        IMPORTED)
set_target_properties(swresample
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswresample.so)

add_library(avcodec
        SHARED
        IMPORTED)
set_target_properties(avcodec
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavcodec.so)

add_library(avfilter
        SHARED
        IMPORTED)
set_target_properties(avfilter
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavfilter.so)

add_library(swscale
        SHARED
        IMPORTED)
set_target_properties(swscale
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswscale.so)

add_library(avformat
        SHARED
        IMPORTED)
set_target_properties(avformat
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavformat.so)

add_library(avdevice
        SHARED
        IMPORTED)
set_target_properties(avdevice
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavdevice.so)

add_library(postproc
        SHARED
        IMPORTED)
set_target_properties(postproc
        PROPERTIES
        IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libpostproc.so
)

add_library(x264 SHARED IMPORTED)
set_target_properties(x264
        PROPERTIES
        IMPORTED_LOCATION ${ffmpeg_lib_dir}/libx264.so
        IMPORTED_NO_SONAME TRUE
        #注意
        #未设置 IMPORTED_NO_SONAME
        #如果第三方库是外部提供的 .so 文件(例如手动编译的 libx264.so),而你又不希望 CMake 写入 .so 的完整路径(而是仅写成 libx264.so),你应该显式关闭 SONAME:
)

# 查找代码中使用到的系统库
find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# 配置目标so库编译信息
add_library( # Sets the name of the library.
        native-lib


        SHARED

)

target_link_libraries(
        native-lib
        -landroid

        # 打开opensl es支持
        OpenSLES
        -lEGL
        -lGLESv2

        postproc

        avutil
        swresample
        avcodec
        avfilter
        swscale
        avformat
        avdevice
        x264
        ${log-lib}
)

后续

如果因为配置原因无法安装虚拟机,也可以在Windows环境下配置msys2 进行以上步骤

相关推荐
liang_jy10 分钟前
Android 事件分发机制(二)—— 点击事件透传
android·面试·源码
圆号本昊3 小时前
Flutter Android Live2D 2026 实战:模型加载 + 集成渲染 + 显示全流程 + 10 个核心坑( OpenGL )
android·flutter·live2d
冬奇Lab4 小时前
ANR实战分析:一次audioserver死锁引发的系统级故障排查
android·性能优化·debug
冬奇Lab4 小时前
Android车机卡顿案例剖析:从Binder耗尽到单例缺失的深度排查
android·性能优化·debug
ZHANG13HAO5 小时前
调用脚本实现 App 自动升级(无需无感、允许进程中断)
android
圆号本昊5 小时前
【2025最新】Flutter 加载显示 Live2D 角色,实战与踩坑全链路分享
android·flutter
小曹要微笑6 小时前
MySQL的TRIM函数
android·数据库·mysql
mrsyf7 小时前
Android Studio Otter 2(2025.2.2版本)安装和Gradle配置
android·ide·android studio
DB虚空行者7 小时前
MySQL恢复之Binlog格式详解
android·数据库·mysql