编译ffmpeg支持av1格式

编译ffmpeg支持av1格式

NDK版本:android-ndk-r21e
ffmpeg版本:5.1.8
av1版本:1.2.1

1、先手动编译av1库,下面是脚本

!/bin/bash

set -e
set -x

====================== 全局配置 ======================

COMPILE_DIR=/home/linrendi/Desktop/Compile/av1
NDK=/home/linrendi/Desktop/Compile/android-ndk-r21e
DAV1D_VERSION=1.2.1
DAV1D_SRC={COMPILE_DIR}/dav1d-{DAV1D_VERSION}
LLVM_TOOLCHAIN={NDK}/toolchains/llvm/prebuilt/linux-x86_64 GCC_TOOLCHAIN_32={NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
GCC_TOOLCHAIN_64=${NDK}/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64

====================== 下载解压源码 ======================

cd {COMPILE_DIR} if [ ! -f "dav1d-{DAV1D_VERSION}.tar.bz2" ]; then
wget --no-check-certificate https://code.videolan.org/videolan/dav1d/-/archive/{DAV1D_VERSION}/dav1d-{DAV1D_VERSION}.tar.bz2
fi
if [ ! -d {DAV1D_SRC} ]; then tar -xjvf dav1d-{DAV1D_VERSION}.tar.bz2
fi
cd ${DAV1D_SRC}

====================== 编译函数 ======================

build_dav1d() {
local ARCH=1 # armv7a / aarch64 local TARGET=2 # armv7a-linux-androideabi / aarch64-linux-android
local API=3 # 21(32位)/ 21(64位) local INSTALL_DIR={COMPILE_DIR}/dav1d_{ARCH} local GCC_TOOLCHAIN=4

echo -e "\n========== 编译 ${ARCH} 架构 libdav1d =========="
# 清理旧编译目录
rm -rf build

# 配置环境变量
export CC=${LLVM_TOOLCHAIN}/bin/${TARGET}${API}-clang
export CXX=${LLVM_TOOLCHAIN}/bin/${TARGET}${API}-clang++
export AR=${LLVM_TOOLCHAIN}/bin/llvm-ar
export LD=${GCC_TOOLCHAIN}/bin/${TARGET%-linux*}-ld
export STRIP=${LLVM_TOOLCHAIN}/bin/llvm-strip
export PKG_CONFIG_LIBDIR=${INSTALL_DIR}/lib/pkgconfig

# 验证工具
if [ ! -f "${CC}" ]; then
    echo "错误:Clang不存在!路径:${CC}"
    exit 1
fi

# 配置meson
meson setup build \
    --cross-file <(echo -e "[binaries]\ncc = '${CC}'\ncxx = '${CXX}'\nar = '${AR}'\nld = '${LD}'\nstrip = '${STRIP}'\n[host_machine]\nsystem = 'android'\ncpu_family = '${ARCH%v7a}'\ncpu = '${ARCH}'\nendian = 'little'") \
    --prefix=${INSTALL_DIR} \
    --libdir=lib \
    --buildtype=release \
    --default-library=static \
    -Denable_asm=false \
    -Denable_tools=false \
    -Denable_tests=false

# 编译安装
ninja -C build install -j4

# 验证结果
if [ ! -f "${INSTALL_DIR}/lib/libdav1d.a" ]; then
    echo "错误:${ARCH} 架构 libdav1d.a 编译失败!"
    exit 1
fi
echo "✅ ${ARCH} 架构 libdav1d 编译完成:${INSTALL_DIR}/lib/libdav1d.a"

}

====================== 执行编译 ======================

编译32位(armeabi-v7a)

build_dav1d "armv7a" "armv7a-linux-androideabi" 21 ${GCC_TOOLCHAIN_32}

编译64位(arm64-v8a)

build_dav1d "aarch64" "aarch64-linux-android" 21 ${GCC_TOOLCHAIN_64}

echo -e "\n🎉 所有架构 libdav1d 编译完成!"
echo "32位路径:{COMPILE_DIR}/dav1d_armv7a" echo "64位路径:{COMPILE_DIR}/dav1d_aarch64"

2、下载ffmpeg 5.1.8版本,ndk21e版本,并解压,进入ffmpeg 5.1.8文件夹,将编译好的av1库引用到ffmpeg配置文件里面


1.png

3、在ffmpeg 5.1.8文件夹里面创建下面脚本,执行

!/bin/bash

set -e

===================== 核心配置(根据实际路径修改)=====================

NDK=/home/linrendi/Desktop/Compile/android-ndk-r21e
ROOT_PREFIX=/home/linrendi/Desktop/ffmpeg_android
ANDROID_API=23
JOBS=4

FFMPEG_DIR=$(pwd)

16KB 对齐常量(Android 强制要求)

ALIGNMENT=16384

===================== 架构编译函数 =====================

build_ffmpeg() {
local ARCH=1 local CPU=2
local TARGET=3 local CLANG_TARGET=4
local SYSROOT=5 local CFLAGS=6
local LDFLAGS=7 local PREFIX={ROOT_PREFIX}/${ARCH}

local DAV1D_PATH=/home/linrendi/Desktop/Compile/av1/dav1d_${ARCH}

# ===================== 前置验证 =====================
if [ ! -f "${DAV1D_PATH}/lib/libdav1d.a" ] || [ ! -d "${DAV1D_PATH}/include/dav1d" ]; then
    echo -e "\033[31m【致命错误】64位libdav1d不完整!\033[0m"
    echo "检查:1. ${DAV1D_PATH}/lib/libdav1d.a  2. ${DAV1D_PATH}/include/dav1d/dav1d.h"
    exit 1
fi

mkdir -p ${PREFIX}
echo "===== 开始编译 ${ARCH} 架构 ====="
make clean || true

# 提取架构名(arm/arm64)
local ARCH_NAME=$(echo ${ARCH} | cut -d'-' -f1)

# 配置 FFmpeg(适配FFmpeg 5.1.8:移除无效BSF,保留核心解码功能)
./configure \
    --prefix=${PREFIX} \
    --target-os=android \
    --disable-doc \
    --cross-prefix=${TOOLCHAIN}/bin/${TARGET}- \
    --arch=${ARCH_NAME} \
    --cpu=${CPU} \
    --disable-asm \
    --sysroot=${SYSROOT} \
    --extra-cflags="${CFLAGS} -I${DAV1D_PATH}/include -DDAV1D_API_VERSION=1 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security -Werror=format-security" \
    --extra-ldflags="${LDFLAGS} -L${DAV1D_PATH}/lib -ldav1d -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,max-page-size=${ALIGNMENT} -Wl,-z,common-page-size=${ALIGNMENT}" \
    --cc=${TOOLCHAIN}/bin/${CLANG_TARGET}${ANDROID_API}-clang \
    --cxx=${TOOLCHAIN}/bin/${CLANG_TARGET}${ANDROID_API}-clang++ \
    --nm=${TOOLCHAIN}/bin/${TARGET}-nm \
    --disable-shared \
    --enable-static \
    --enable-small \
    --disable-debug \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-symver \
    --enable-neon \
    --enable-pthreads \
    --disable-devices \
    --disable-encoders \
    --enable-decoder=av1,av1_mediacodec \
    --enable-hwaccel=av1_mediacodec \
    --enable-parser=av1 \
    --enable-libdav1d \
    --enable-decoder=hevc,hevc_mediacodec \
    --enable-hwaccel=hevc_mediacodec \
    --enable-hwaccels --enable-jni --enable-mediacodec \
    --enable-parser=hevc \
    --enable-encoder=aac \
    --enable-jni \
    --enable-mediacodec \
    --enable-encoder=aac \
    --enable-decoder=h264_mediacodec \
    --enable-hwaccel=h264_mediacodec \
    --enable-encoder=mjpeg \
    --enable-encoder=ljpeg \
    --enable-encoder=jpeg2000 \
    --enable-encoder=jpegls \
    --enable-muxer=mp4 \
    --enable-muxer=mjpeg \
    --enable-encoder=ljpeg --enable-encoder=jpeg2000 --enable-encoder=jpegls \
    --enable-runtime-cpudetect \
    --extra-libs="-lm -lz -ldl -llog -latomic" \
    --disable-vulkan \
    --disable-bzlib \
    --disable-openssl \
    --disable-postproc \
    --disable-programs \
    --disable-hardcoded-tables

if [ $? -ne 0 ]; then
    echo "${ARCH} 配置失败,查看 ffbuild/config.log 了解详情"
    exit 1
fi

# 编译
make -j${JOBS}
if [ $? -ne 0 ]; then
    echo "${ARCH} 编译失败"
    exit 1
fi

# 安装静态库
make install
if [ $? -ne 0 ]; then
    echo "${ARCH} 安装失败"
    exit 1
fi

# 链接动态库(单行命令,无换行)
echo "===== 开始链接 ${ARCH} 动态库 ====="
if [ "${ARCH}" = "armeabi-v7a" ]; then
    ${TOOLCHAIN}/bin/${CLANG_TARGET}${ANDROID_API}-clang -fPIE -pie -shared -nostdlib -Bsymbolic --sysroot=${SYSROOT} -march=${CPU} -o ${PREFIX}/libffmpeg.so -Wl,--whole-archive -Wl,-z,max-page-size=${ALIGNMENT} -Wl,-z,common-page-size=${ALIGNMENT} ${DAV1D_PATH}/lib/libdav1d.a libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a libavdevice/libavdevice.a -Wl,--no-whole-archive -lm -lz -ldl -llog -latomic -lgcc -lc -lm -lstdc++ -Wl,--fix-cortex-a8
else
    ${TOOLCHAIN}/bin/${CLANG_TARGET}${ANDROID_API}-clang -fPIE -pie -shared -nostdlib -Bsymbolic --sysroot=${SYSROOT} -march=${CPU} -o ${PREFIX}/libffmpeg.so -Wl,--whole-archive -Wl,-z,max-page-size=${ALIGNMENT} -Wl,-z,common-page-size=${ALIGNMENT} ${DAV1D_PATH}/lib/libdav1d.a libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a libavdevice/libavdevice.a -Wl,--no-whole-archive -lm -lz -ldl -llog -latomic -lgcc -lc -lm -lstdc++
fi

if [ $? -ne 0 ]; then
    echo "${ARCH} 链接失败"
    exit 1
fi

# ===================== 验证 =====================
echo -e "\n========================================"
echo -e "\033[32m64位编译完成!AV1功能验证\033[0m"
echo -e "========================================"

# 验证1:AV1核心符号
echo -e "\n【验证1】AV1解码符号:"
AV1_SYMBOLS=("av1_decode_frame" "ff_av1_decoder" "dav1d_decode")
for sym in "${AV1_SYMBOLS[@]}"; do
    if ${TOOLCHAIN}/bin/llvm-objdump -t ${PREFIX}/libffmpeg.so | grep -q "$sym"; then
    echo -e "  ✅ $sym"
    else
    echo -e "  ❌ $sym"
    fi
done

# 验证2:16KB对齐(关键)
echo -e "\n【验证2】16KB内存对齐:"
ALIGN_CHECK=$(${TOOLCHAIN}/bin/llvm-readelf -l ${PREFIX}/libffmpeg.so | grep "Align" | head -n1 | awk '{print $NF}')
if [ "${ALIGN_CHECK}" = "${ALIGNMENT}" ] || [ "${ALIGN_CHECK}" = "16384" ]; then
   echo -e "  ✅ 已满足Android 16KB对齐要求(当前对齐:${ALIGN_CHECK}字节)"
else
   echo -e "  ❌ 未满足16KB对齐!当前对齐:${ALIGN_CHECK}字节(需16384)"
fi

# 优化so库
${TOOLCHAIN}/bin/${TARGET}-strip ${PREFIX}/libffmpeg.so
make clean
echo "===== ${ARCH} 编译完成!输出路径:${PREFIX} ====="

}

===================== 工具链基础配置 =====================

TOOLCHAIN={NDK}/toolchains/llvm/prebuilt/linux-x86_64 SYSROOT={TOOLCHAIN}/sysroot

===================== 编译32位(armeabi-v7a)=====================

ARCH=armeabi-v7a
CPU=armv7-a
TARGET=arm-linux-androideabi
CLANG_TARGET=armv7a-linux-androideabi
CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -mthumb -O3 -DANDROID -D__ANDROID_API__={ANDROID_API}" LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8" build_ffmpeg{ARCH} {CPU}{TARGET} {CLANG_TARGET}{SYSROOT} "{CFLAGS}" "{LDFLAGS}"

===================== 编译64位(arm64-v8a)=====================

ARCH=arm64-v8a
CPU=armv8-a
TARGET=aarch64-linux-android
CLANG_TARGET=aarch64-linux-android
CFLAGS="-march=armv8-a -O3 -DANDROID -D__ANDROID_API__={ANDROID_API}" LDFLAGS="-march=armv8-a" build_ffmpeg{ARCH} {CPU}{TARGET} {CLANG_TARGET}{SYSROOT} "{CFLAGS}" "{LDFLAGS}"

echo "===== 所有架构编译完成!根输出路径:{ROOT_PREFIX} =====" echo "32位输出:{ROOT_PREFIX}/armeabi-v7a"
echo "64位输出:${ROOT_PREFIX}/arm64-v8a"
echo "✅ 已支持(FFmpeg 5.1.8 兼容版):"
echo " - AV1 软解(av1)+ 硬解(av1_mediacodec)"
echo " - H.265/HEVC 软解(hevc)+ 硬解(hevc_mediacodec)"
echo " - H.264 硬解(h264_mediacodec)"

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容