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 进行以上步骤

相关推荐
vocal2 小时前
【我的安卓第一课】Android 多线程与异步通信机制(1)
android
顾林海2 小时前
ViewModel 销毁时机详解
android·面试·android jetpack
恋猫de小郭4 小时前
Google I/O Extended :2025 Flutter 的现状与未来
android·前端·flutter
@Ryan Ding4 小时前
MySQL主从复制与读写分离概述
android·mysql·adb
移动开发者1号5 小时前
Android 同步屏障(SyncBarrier)深度解析与应用实战
android·kotlin
移动开发者1号5 小时前
深入协程调试:协程调试工具与实战
android·kotlin
雨白13 小时前
Jetpack系列(三):Room数据库——从增删改查到数据库平滑升级
android·android jetpack
花王江不语16 小时前
android studio 配置硬件加速 haxm
android·ide·android studio
江太翁18 小时前
mediapipe流水线分析 三
android·mediapipe
与火星的孩子对话19 小时前
Unity进阶课程【六】Android、ios、Pad 终端设备打包局域网IP调试、USB调试、性能检测、控制台打印日志等、C#
android·unity·ios·c#·ip