编译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={DAV1D_VERSION}
LLVM_TOOLCHAIN={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 {DAV1D_VERSION}.tar.bz2" ]; then
wget --no-check-certificate https://code.videolan.org/videolan/dav1d/-/archive/{DAV1D_VERSION}.tar.bz2
fi
if [ ! -d {DAV1D_VERSION}.tar.bz2
fi
cd ${DAV1D_SRC}
====================== 编译函数 ======================
build_dav1d() {
local ARCH=2 # armv7a-linux-androideabi / aarch64-linux-android
local API={COMPILE_DIR}/dav1d_
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_aarch64"
2、下载ffmpeg 5.1.8版本,ndk21e版本,并解压,进入ffmpeg 5.1.8文件夹,将编译好的av1库引用到ffmpeg配置文件里面

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=2
local TARGET=4
local SYSROOT=6
local LDFLAGS={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={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__={ARCH}
{TARGET}
{SYSROOT} "
{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__={ARCH}
{TARGET}
{SYSROOT} "
{LDFLAGS}"
echo "===== 所有架构编译完成!根输出路径:{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)"