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

相关推荐
泥嚎泥嚎3 小时前
【Android】给App添加启动画面——SplashScreen
android·java
全栈派森4 小时前
初见 Dart:这门新语言如何让你的 App「动」起来?
android·flutter·ios
q***98524 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb
恋猫de小郭4 小时前
Dart 3.10 发布,快来看有什么更新吧
android·前端·flutter
恋猫de小郭6 小时前
Flutter 3.38 发布,快来看看有什么更新吧
android·前端·flutter
百锦再11 小时前
第11章 泛型、trait与生命周期
android·网络·人工智能·python·golang·rust·go
会跑的兔子12 小时前
Android 16 Kotlin协程 第二部分
android·windows·kotlin
键来大师12 小时前
Android15 RK3588 修改默认不锁屏不休眠
android·java·framework·rk3588
江上清风山间明月15 小时前
Android 系统超级实用的分析调试命令
android·内存·调试·dumpsys
百锦再15 小时前
第12章 测试编写
android·java·开发语言·python·rust·go·erlang