FFmpeg开发 Windows环境集成AV1解码器libaom完整指南
概览流程
环境准备 → aom库安装 → FFmpeg编译 → AV1支持 → 验证测试 → 开发集成
环境准备
安装MSYS2环境
# 1. 下载并安装MSYS2
# 访问 https://www.msys2.org/ 下载安装包
# 安装完成后运行 MSYS2 UCRT64
# 2. 更新系统包
pacman -Syu
pacman -Su
# 3. 安装编译工具链
pacman -S mingw-w64-ucrt-x86_64-toolchain
pacman -S mingw-w64-ucrt-x86_64-pkg-config
pacman -S make
pacman -S mingw-w64-ucrt-x86_64-yasm
pacman -S mingw-w64-ucrt-x86_64-nasm
pacman -S git
pacman -S mingw-w64-ucrt-x86_64-cmake
pacman -S mingw-w64-ucrt-x86_64-python
创建工作目录
# 在MSYS2环境中创建目录
mkdir -p /c/ffmpeg_dev/{sources,build,output}
cd /c/ffmpeg_dev
aom库安装
方法一:使用MSYS2包管理器安装
# 安装aom开发包
pacman -S mingw-w64-ucrt-x86_64-aom
# 验证安装
pacman -Q mingw-w64-ucrt-x86_64-aom
方法二:手动编译aom库
# 下载aom源码
cd /c/ffmpeg_dev/sources
# 克隆aom源码(官方GitHub仓库)
git clone https://aomedia.googlesource.com/aom
cd aom
# 创建构建目录
mkdir -p build
cd build
# 配置CMake
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/c/ffmpeg_dev/build/aom \
-DBUILD_SHARED_LIBS=OFF \
-DENABLE_EXAMPLES=OFF \
-DENABLE_TESTS=OFF \
-DENABLE_TOOLS=OFF \
-DCMAKE_TOOLCHAIN_FILE=/ucrt64/share/cmake/toolchain-x86_64-w64-mingw32.cmake
# 编译和安装
make -j$(nproc)
make install
# 检查生成的文件
ls -la /c/ffmpeg_dev/build/aom/
方法三:使用预编译的aom库
# 如果有预编译的aom库文件,直接复制到指定目录
mkdir -p /c/ffmpeg_dev/build/aom/{include,lib}
# 复制头文件和库文件(示例路径)
# cp /path/to/aom/include/*.h /c/ffmpeg_dev/build/aom/include/
# cp /path/to/aom/lib/*.lib /c/ffmpeg_dev/build/aom/lib/
# cp /path/to/aom/lib/*.dll /c/ffmpeg_dev/build/aom/lib/
FFmpeg源码编译
下载FFmpeg源码
# 进入源码目录
cd /c/ffmpeg_dev/sources
# 克隆FFmpeg源码
if [ ! -d "ffmpeg" ]; then
git clone https://git.ffmpeg.org/ffmpeg.git
fi
cd ffmpeg
配置FFmpeg(启用libaom支持)
# 配置FFmpeg编译选项
./configure \
--prefix=/c/ffmpeg_dev/output \
--enable-shared \
--enable-static \
--enable-gpl \
--enable-nonfree \
--enable-version3 \
--enable-runtime-cpudetect \
--enable-postproc \
--enable-avfilter \
--enable-pthreads \
--enable-network \
--enable-libaom \
--enable-encoder=libaom_av1 \
--enable-decoder=libaom_av1,av1 \
--enable-parser=av1 \
--enable-demuxer=ivf,matroska,mp4 \
--enable-muxer=ivf,matroska \
--enable-protocol=file,http,https \
--arch=x86_64 \
--target-os=mingw32 \
--cross-prefix=x86_64-w64-mingw32- \
--extra-cflags="-I/c/ffmpeg_dev/build/aom/include -I/ucrt64/include" \
--extra-ldflags="-L/c/ffmpeg_dev/build/aom/lib -L/ucrt64/lib" \
--extra-libs="-laom -lpthread -lm"
编译和安装
# 清理之前的构建
make clean
# 并行编译
make -j$(nproc)
# 安装到指定目录
make install
使用vcpkg编译(推荐方法)
安装vcpkg
# 在Windows命令提示符中执行
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
bootstrap-vcpkg.bat
使用vcpkg安装FFmpeg
# 安装带有libaom支持的FFmpeg
vcpkg install ffmpeg[core,aom]:x64-windows
# 或者安装更多功能
vcpkg install ffmpeg[core,aom,x264,x265]:x64-windows
集成到Visual Studio
# 集成到系统
vcpkg integrate install
完整构建脚本
# 创建完整构建脚本
cat > build_ffmpeg_windows_aom.sh << 'EOF'
#!/bin/bash
# 设置环境变量
WORK_DIR=/c/ffmpeg_dev
SOURCES_DIR=$WORK_DIR/sources
BUILD_DIR=$WORK_DIR/build
OUTPUT_DIR=$WORK_DIR/output
# 创建目录结构
mkdir -p $SOURCES_DIR $BUILD_DIR $OUTPUT_DIR
echo "开始FFmpeg libaom集成编译..."
# 安装依赖包
echo "安装依赖库..."
pacman -Syu --noconfirm
pacman -S --noconfirm \
mingw-w64-ucrt-x86_64-toolchain \
mingw-w64-ucrt-x86_64-pkg-config \
make \
mingw-w64-ucrt-x86_64-yasm \
mingw-w64-ucrt-x86_64-nasm \
git \
mingw-w64-ucrt-x86_64-cmake \
mingw-w64-ucrt-x86_64-aom
# 检查aom是否已安装
if ! pacman -Q mingw-w64-ucrt-x86_64-aom >/dev/null 2>&1; then
echo "手动编译aom库..."
cd $SOURCES_DIR
if [ ! -d "aom" ]; then
git clone https://aomedia.googlesource.com/aom
fi
cd aom
mkdir -p build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$BUILD_DIR/aom \
-DBUILD_SHARED_LIBS=OFF \
-DENABLE_EXAMPLES=OFF \
-DENABLE_TESTS=OFF \
-DENABLE_TOOLS=OFF \
-DCMAKE_TOOLCHAIN_FILE=/ucrt64/share/cmake/toolchain-x86_64-w64-mingw32.cmake
make -j$(nproc)
make install
fi
# 下载FFmpeg源码
cd $SOURCES_DIR
if [ ! -d "ffmpeg" ]; then
git clone https://git.ffmpeg.org/ffmpeg.git
fi
cd ffmpeg
# 配置FFmpeg
echo "配置FFmpeg..."
./configure \
--prefix=$OUTPUT_DIR \
--enable-shared \
--enable-static \
--enable-gpl \
--enable-nonfree \
--enable-version3 \
--enable-runtime-cpudetect \
--enable-postproc \
--enable-avfilter \
--enable-pthreads \
--enable-network \
--enable-libaom \
--enable-encoder=libaom_av1 \
--enable-decoder=libaom_av1,av1,h264,hevc \
--enable-parser=av1,h264,hevc \
--enable-demuxer=ivf,matroska,mp4,mov,h264,hevc \
--enable-muxer=ivf,matroska,mp4 \
--enable-protocol=file,http,https,rtmp \
--arch=x86_64 \
--target-os=mingw32 \
--cross-prefix=x86_64-w64-mingw32-
# 编译和安装
echo "编译FFmpeg..."
make clean
make -j$(nproc)
make install
echo "FFmpeg编译完成!"
echo "输出目录: $OUTPUT_DIR"
echo "可执行文件: $OUTPUT_DIR/bin/ffmpeg.exe"
EOF
chmod +x build_ffmpeg_windows_aom.sh
验证安装
功能验证脚本
# 创建验证脚本
cat > verify_ffmpeg_aom.sh << 'EOF'
#!/bin/bash
OUTPUT_DIR=/c/ffmpeg_dev/output
FFMPEG_EXE=$OUTPUT_DIR/bin/ffmpeg.exe
echo "验证FFmpeg libaom功能支持"
# 检查FFmpeg是否可执行
if [ ! -f "$FFMPEG_EXE" ]; then
echo "错误: FFmpeg未找到"
exit 1
fi
echo "FFmpeg可执行文件存在"
# 检查aom支持
echo "检查aom支持..."
$FFMPEG_EXE -encoders | grep aom > /dev/null && echo "✓ aom编码器支持正常" || echo "✗ aom编码器支持异常"
$FFMPEG_EXE -decoders | grep aom > /dev/null && echo "✓ aom解码器支持正常" || echo "✗ aom解码器支持异常"
$FFMPEG_EXE -decoders | grep -i av1 > /dev/null && echo "✓ AV1解码器支持正常" || echo "✗ AV1解码器支持异常"
# 显示版本信息
echo "FFmpeg版本信息:"
$FFMPEG_EXE -version | head -5
# 显示编译配置
echo "aom编译配置:"
$FFMPEG_EXE -buildconf | grep -i aom
# 显示支持的编解码器
echo "aom相关编解码器:"
$FFMPEG_EXE -encoders | grep aom
$FFMPEG_EXE -decoders | grep aom
echo "验证完成"
EOF
chmod +x verify_ffmpeg_aom.sh
测试aom功能
# aom编码测试
test_aom_encoding() {
echo "测试aom编码功能..."
# 创建测试视频
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-f lavfi -i testsrc=duration=5:size=1280x720:rate=30 \
-c:v libaom-av1 -cpu-used 8 -b:v 1000k \
-f ivf test_aom.ivf
if [ -f "test_aom.ivf" ]; then
echo "aom编码测试成功"
ls -lh test_aom.ivf
rm test_aom.ivf
else
echo "aom编码测试失败"
fi
}
# aom解码测试
test_aom_decoding() {
echo "测试aom解码功能..."
# 创建测试文件
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-f lavfi -i testsrc=duration=3:size=1280x720:rate=25 \
-c:v libaom-av1 -cpu-used 8 -b:v 800k \
-f ivf test_decode.ivf
if [ -f "test_decode.ivf" ]; then
# 解码测试
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-i test_decode.ivf \
-f null -
if [ $? -eq 0 ]; then
echo "aom解码测试成功"
else
echo "aom解码测试失败"
fi
rm test_decode.ivf
else
echo "aom解码测试文件创建失败"
fi
}
# aom兼容性测试
test_aom_compatibility() {
echo "测试aom兼容性..."
# 创建不同CPU使用率的测试文件
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-f lavfi -i testsrc=duration=3:size=1920x1080:rate=25 \
-c:v libaom-av1 -cpu-used 5 -b:v 2000k \
-f ivf test_cpu5.ivf
/c/ffmpeg_dev/output/bin/ffmpeg.exe \
-f lavfi -i testsrc=duration=3:size=1920x1080:rate=25 \
-c:v libaom-av1 -cpu-used 9 -b:v 2000k \
-f ivf test_cpu9.ivf
if [ -f "test_cpu5.ivf" ] && [ -f "test_cpu9.ivf" ]; then
echo "不同CPU使用率测试文件创建成功"
ls -lh test_cpu*.ivf
rm test_cpu5.ivf test_cpu9.ivf
else
echo "测试文件创建失败"
fi
}
Visual Studio开发集成
项目配置
// 在Visual Studio项目属性中设置:
// 包含目录:
// C:\vcpkg\installed\x64-windows\include
// 或
// C:\ffmpeg_dev\output\include
// C:\msys64\ucrt64\include
// 库目录:
// C:\vcpkg\installed\x64-windows\lib
// 或
// C:\ffmpeg_dev\output\lib
// C:\msys64\ucrt64\lib
// 附加依赖项:
// avformat.lib
// avcodec.lib
// avutil.lib
// swscale.lib
// swresample.lib
// avfilter.lib
// aom.lib
CMake配置
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(FFmpegAOMTest)
set(CMAKE_CXX_STANDARD 17)
# 如果使用vcpkg
# set(FFMPEG_ROOT "C:/vcpkg/installed/x64-windows")
# 如果使用自编译版本
set(FFMPEG_ROOT "C:/ffmpeg_dev/output")
set(MSYS2_ROOT "C:/msys64/ucrt64")
# 包含目录
include_directories(
${FFMPEG_ROOT}/include
${MSYS2_ROOT}/include
)
# 库目录
link_directories(
${FFMPEG_ROOT}/lib
${MSYS2_ROOT}/lib
)
# 源文件
add_executable(${PROJECT_NAME} main.cpp)
# 链接库
target_link_libraries(${PROJECT_NAME}
avformat
avcodec
avutil
swscale
swresample
avfilter
aom
)
# 复制DLL文件到输出目录
file(GLOB FFMPEG_DLLS "${FFMPEG_ROOT}/bin/*.dll")
file(GLOB MSYS2_DLLS "${MSYS2_ROOT}/bin/*.dll")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${FFMPEG_DLLS}
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${MSYS2_DLLS}
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
aom处理示例代码
// aom_example.cpp - aom处理示例
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/opt.h>
}
#include <iostream>
#include <string>
class AOMProcessor {
private:
AVFormatContext* format_ctx;
AVCodecContext* codec_ctx;
const AVCodec* codec;
public:
AOMProcessor() : format_ctx(nullptr), codec_ctx(nullptr), codec(nullptr) {
// 初始化网络
avformat_network_init();
}
~AOMProcessor() {
cleanup();
avformat_network_deinit();
}
bool checkAOMSupport() {
std::cout << "检查aom支持..." << std::endl;
// 检查aom编码器
const AVCodec* aom_encoder = avcodec_find_encoder_by_name("libaom-av1");
if (aom_encoder) {
std::cout << "aom AV1编码器: " << aom_encoder->name << std::endl;
} else {
std::cout << "aom AV1编码器不可用" << std::endl;
}
// 检查aom解码器
const AVCodec* aom_decoder = avcodec_find_decoder_by_name("libaom-av1");
if (aom_decoder) {
std::cout << "aom AV1解码器: " << aom_decoder->name << std::endl;
} else {
std::cout << "aom AV1解码器不可用" << std::endl;
}
// 检查内置AV1解码器
const AVCodec* av1_decoder = avcodec_find_decoder(AV_CODEC_ID_AV1);
if (av1_decoder) {
std::cout << "内置AV1解码器: " << av1_decoder->name << std::endl;
} else {
std::cout << "内置AV1解码器不可用" << std::endl;
}
// 检查AV1解析器
void* parser_opaque = nullptr;
const AVCodecParser* parser = nullptr;
bool av1_parser_found = false;
while ((parser = av_parser_iterate(&parser_opaque))) {
if (parser->codec_ids[0] == AV_CODEC_ID_AV1) {
std::cout << "AV1解析器: " << avcodec_get_name(parser->codec_ids[0]) << std::endl;
av1_parser_found = true;
break;
}
}
if (!av1_parser_found) {
std::cout << "AV1解析器不可用" << std::endl;
}
return (aom_encoder != nullptr || aom_decoder != nullptr || av1_decoder != nullptr);
}
bool encodeToAOM(const std::string& output_file) {
std::cout << "编码到aom AV1格式: " << output_file << std::endl;
// 分配输出格式上下文
AVFormatContext* ofmt_ctx = nullptr;
avformat_alloc_output_context2(&ofmt_ctx, NULL, "ivf", output_file.c_str());
if (!ofmt_ctx) {
std::cerr << "无法创建输出格式上下文" << std::endl;
return false;
}
// 查找aom编码器
const AVCodec* encoder = avcodec_find_encoder_by_name("libaom-av1");
if (!encoder) {
std::cerr << "找不到aom编码器" << std::endl;
avformat_free_context(ofmt_ctx);
return false;
}
// 创建视频流
AVStream* video_stream = avformat_new_stream(ofmt_ctx, encoder);
if (!video_stream) {
std::cerr << "无法创建视频流" << std::endl;
avformat_free_context(ofmt_ctx);
return false;
}
// 分配编码器上下文
AVCodecContext* enc_ctx = avcodec_alloc_context3(encoder);
if (!enc_ctx) {
std::cerr << "无法分配编码器上下文" << std::endl;
avformat_free_context(ofmt_ctx);
return false;
}
// 设置编码参数
enc_ctx->width = 1920;
enc_ctx->height = 1080;
enc_ctx->time_base = (AVRational){1, 30};
enc_ctx->framerate = (AVRational){30, 1};
enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
enc_ctx->bit_rate = 2000000; // 2Mbps
// 设置aom特定选项
av_opt_set(enc_ctx->priv_data, "cpu-used", "8", 0); // CPU使用率
av_opt_set(enc_ctx->priv_data, "threads", "0", 0); // 自动线程数
av_opt_set(enc_ctx->priv_data, "lag-in-frames", "0", 0); // 无延迟模式
av_opt_set(enc_ctx->priv_data, "error-resilient", "0", 0); // 错误恢复
// 打开编码器
int ret = avcodec_open2(enc_ctx, encoder, NULL);
if (ret < 0) {
std::cerr << "无法打开编码器" << std::endl;
avcodec_free_context(&enc_ctx);
avformat_free_context(ofmt_ctx);
return false;
}
// 复制参数到流
ret = avcodec_parameters_from_context(video_stream->codecpar, enc_ctx);
if (ret < 0) {
std::cerr << "无法复制编解码器参数" << std::endl;
avcodec_close(enc_ctx);
avcodec_free_context(&enc_ctx);
avformat_free_context(ofmt_ctx);
return false;
}
// 写入文件头
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, output_file.c_str(), AVIO_FLAG_WRITE);
if (ret < 0) {
std::cerr << "无法打开输出文件" << std::endl;
avcodec_close(enc_ctx);
avcodec_free_context(&enc_ctx);
avformat_free_context(ofmt_ctx);
return false;
}
}
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
std::cerr << "无法写入文件头" << std::endl;
avcodec_close(enc_ctx);
avcodec_free_context(&enc_ctx);
avformat_free_context(ofmt_ctx);
return false;
}
std::cout << "aom编码器初始化成功" << std::endl;
// 清理资源
avcodec_close(enc_ctx);
avcodec_free_context(&enc_ctx);
avformat_free_context(ofmt_ctx);
return true;
}
bool openAOMFile(const std::string& filename) {
std::cout << "打开AOM AV1文件: " << filename << std::endl;
// 打开输入文件
int ret = avformat_open_input(&format_ctx, filename.c_str(), nullptr, nullptr);
if (ret < 0) {
char err_buf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, err_buf, sizeof(err_buf));
std::cerr << "无法打开文件: " << filename << ", 错误: " << err_buf << std::endl;
return false;
}
// 获取流信息
ret = avformat_find_stream_info(format_ctx, nullptr);
if (ret < 0) {
std::cerr << "无法获取流信息" << std::endl;
return false;
}
// 查找视频流
int video_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
if (video_stream_index < 0) {
std::cerr << "未找到视频流" << std::endl;
return false;
}
// 获取解码器
AVStream* video_stream = format_ctx->streams[video_stream_index];
AVCodecParameters* codecpar = video_stream->codecpar;
// 优先使用aom解码器
codec = avcodec_find_decoder_by_name("libaom-av1");
if (!codec) {
codec = avcodec_find_decoder(codecpar->codec_id);
}
if (!codec) {
std::cerr << "未找到解码器" << std::endl;
return false;
}
// 创建解码器上下文
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
std::cerr << "无法分配解码器上下文" << std::endl;
return false;
}
// 复制参数到解码器上下文
ret = avcodec_parameters_to_context(codec_ctx, codecpar);
if (ret < 0) {
std::cerr << "无法复制编解码器参数" << std::endl;
return false;
}
// 打开解码器
ret = avcodec_open2(codec_ctx, codec, nullptr);
if (ret < 0) {
std::cerr << "无法打开解码器" << std::endl;
return false;
}
std::cout << "成功打开AOM AV1文件" << std::endl;
return true;
}
void printVideoInfo() {
if (!codec_ctx) return;
std::cout << "视频信息:" << std::endl;
std::cout << " 编解码器: " << codec->name << std::endl;
std::cout << " 分辨率: " << codec_ctx->width << "x" << codec_ctx->height << std::endl;
std::cout << " 像素格式: " << av_get_pix_fmt_name(codec_ctx->pix_fmt) << std::endl;
if (codec_ctx->framerate.den != 0) {
std::cout << " 帧率: " << av_q2d(codec_ctx->framerate) << " fps" << std::endl;
}
std::cout << " 比特率: " << (codec_ctx->bit_rate > 0 ? codec_ctx->bit_rate / 1000 : 0) << " kbps" << std::endl;
}
void cleanup() {
if (codec_ctx) {
avcodec_free_context(&codec_ctx);
codec_ctx = nullptr;
}
if (format_ctx) {
avformat_close_input(&format_ctx);
format_ctx = nullptr;
}
if (codec) {
codec = nullptr;
}
}
};
int main() {
std::cout << "FFmpeg aom处理示例" << std::endl;
AOMProcessor processor;
// 检查aom支持
if (!processor.checkAOMSupport()) {
std::cout << "aom支持检查失败" << std::endl;
return -1;
}
// 测试编码功能
if (processor.encodeToAOM("test_output.ivf")) {
std::cout << "aom编码测试成功" << std::endl;
} else {
std::cout << "aom编码测试失败" << std::endl;
}
std::cout << "aom支持测试完成" << std::endl;
return 0;
}
aom使用示例
命令行示例
# aom编码(使用libaom-av1)
ffmpeg.exe -i input.mp4 -c:v libaom-av1 -b:v 2M -cpu-used 8 output.av1
# aom编码(更多选项)
ffmpeg.exe -i input.mp4 -c:v libaom-av1 \
-cpu-used 6 -crf 30 -b:v 2000k \
-threads 0 -row-mt 1 \
-lag-in-frames 0 \
output.av1
# aom解码
ffmpeg.exe -i input.av1 -c:v libaom-av1 -f null -
# aom文件信息查看
ffmpeg.exe -i input.av1 -f null -
# aom转码
ffmpeg.exe -i input.av1 -c:v libx264 output.mp4
# aom流媒体传输
ffmpeg.exe -f lavfi -i testsrc=duration=30:size=1280x720:rate=30 \
-c:v libaom-av1 -cpu-used 8 -b:v 2000k \
-f ivf "udp://127.0.0.1:1234"
aom参数说明
# aom编码参数:
# -cpu-used 范围:0-8 (0=最慢最高质量, 8=最快最低质量)
# -crf 范围:0-63 (恒定质量模式)
# -b:v 比特率控制
# -threads 线程数 (0=自动)
# -row-mt 行多线程 (0/1)
# -tile-columns 瓦片列数 (0-6)
# -tile-rows 瓦片行数 (0-2)
# -lag-in-frames 延迟帧数 (0-25)
# -error-resilient 错误恢复 (0/1)
# -aq-mode 自适应量化模式 (0-4)
# -frame-parallel 帧并行 (0/1)
环境变量配置
# 在Windows系统环境变量中添加:
# 系统PATH变量添加:
C:\ffmpeg_dev\output\bin
C:\msys64\ucrt64\bin
# 或如果使用vcpkg:
C:\vcpkg\installed\x64-windows\bin
# 创建批处理文件设置环境
@echo off
set PATH=C:\ffmpeg_dev\output\bin;C:\msys64\ucrt64\bin;%PATH%
set FFmpeg_HOME=C:\ffmpeg_dev\output
echo 环境变量已设置
常见问题解决
1. aom库缺失
# 检查aom库是否存在
ls /c/ffmpeg_dev/build/aom/lib/
ls /ucrt64/lib/ | grep aom
# 如果使用MSYS2包,检查安装
pacman -Q mingw-w64-ucrt-x86_64-aom
2. 编译时链接错误
# 检查库文件
file /ucrt64/lib/libaom.a
file /ucrt64/lib/libaom.dll.a
# 确保包含正确的库
# -laom
3. 运行时DLL错误
# 复制必要的DLL文件
copy C:\ffmpeg_dev\output\bin\*.dll .\
copy C:\msys64\ucrt64\bin\*.dll .\
copy C:\msys64\ucrt64\bin\libaom-*.dll .\
4. 编码器不可用
# 检查FFmpeg编译配置
/c/ffmpeg_dev/output/bin/ffmpeg.exe -buildconf | grep -i aom
/c/ffmpeg_dev/output/bin/ffmpeg.exe -encoders | grep aom
# 如果显示disable,则需要重新编译
5. 性能问题
# aom性能优化
# 调整cpu-used参数平衡质量和速度
# 启用多线程:-threads 0
# 启用行多线程:-row-mt 1
# 设置合适的瓦片参数
性能优化建议
编译优化选项
# 性能优化编译配置
./configure \
--prefix=/c/ffmpeg_dev/output \
--enable-shared \
--enable-static \
--enable-optimizations \
--disable-debug \
--enable-stripping \
--enable-small \
--extra-cflags="-O3 -ffast-math -march=native" \
--extra-ldflags="-s" \
--enable-libaom \
# 其他配置选项
aom编码参数优化
# FFmpeg aom优化参数
ffmpeg.exe -i input.mp4 \
-c:v libaom-av1 \
-cpu-used 7 \
-crf 32 \
-b:v 2000k \
-threads 0 \
-row-mt 1 \
-tile-columns 2 \
-tile-rows 1 \
output.av1
硬件加速支持
# 检查硬件加速支持
ffmpeg.exe -hwaccels | grep -i av1
# 如果支持硬件解码
ffmpeg.exe -hwaccel cuda -c:v av1_cuvid -i input.av1 output.mp4
aom技术特性
aom优势
# aom的主要优势:
# 1. 标准符合性:官方AV1编码器
# 2. 高压缩效率:优秀的压缩性能
# 3. 灵活配置:丰富的编码参数
# 4. 免版税:完全开源
# 5. 活跃开发:AOMedia持续维护
# 6. 跨平台:支持多种操作系统
aom与其他编码器对比
# aom vs 其他编码器:
# 压缩效率:aom ≈ rav1e > SVT-AV1
# 编码速度:SVT-AV1 > rav1e > aom
# 标准符合性:aom > 其他
# 配置灵活性:aom > rav1e > SVT-AV1
# 开发活跃度:aom > rav1e > SVT-AV1
aom应用场景
# 适用场景:
# 1. 高质量视频编码
# 2. 标准符合性要求高的场景
# 3. 开源项目
# 4. 需要精细控制的编码
# 5. 研究和开发用途
CPU使用率参考表
# aom CPU使用率参考:
# cpu-used 0-2: 最高质量,极慢速度
# cpu-used 3-4: 高质量,慢速
# cpu-used 5-6: 中等质量,中等速度
# cpu-used 7: 平衡质量,较快(推荐)
# cpu-used 8: 低质量,快速
# 建议使用:
# 实时编码:cpu-used 7-8
# 批量处理:cpu-used 5-7
# 最高质量:cpu-used 2-4
# 平衡性能:cpu-used 6-7
测试用例
// test_aom.cpp - aom测试用例
#include "aom_example.h"
#include <cassert>
#include <filesystem>
void testAOMSupport() {
AOMProcessor processor;
// 测试aom支持检查
bool result = processor.checkAOMSupport();
assert(result == true); // 应该至少支持某种aom编码/解码
std::cout << "aom支持测试通过!" << std::endl;
}
void testEncoding() {
AOMProcessor processor;
// 测试编码功能
bool result = processor.encodeToAOM("test_output.ivf");
assert(result == true);
// 检查输出文件是否存在
assert(std::filesystem::exists("test_output.ivf") == true);
// 清理测试文件
if (std::filesystem::exists("test_output.ivf")) {
std::filesystem::remove("test_output.ivf");
}
std::cout << "编码测试通过!" << std::endl;
}
void testDecoding() {
AOMProcessor processor;
// 创建测试文件
system("/c/ffmpeg_dev/output/bin/ffmpeg.exe -f lavfi -i testsrc=duration=3:size=1280x720:rate=25 -c:v libaom-av1 -cpu-used 8 -b:v 800k -f ivf test_decode.ivf");
// 测试解码功能
if (std::filesystem::exists("test_decode.ivf")) {
bool result = processor.openAOMFile("test_decode.ivf");
assert(result == true);
processor.printVideoInfo();
// 清理测试文件
std::filesystem::remove("test_decode.ivf");
std::cout << "解码测试通过!" << std::endl;
}
}
void testPerformance() {
AOMProcessor processor;
// 性能测试
auto start_time = std::chrono::high_resolution_clock::now();
// 进行编码操作
processor.encodeToAOM("perf_test.ivf");
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
std::cout << "性能测试完成,耗时: " << duration.count() << " ms" << std::endl;
// 清理测试文件
if (std::filesystem::exists("perf_test.ivf")) {
std::filesystem::remove("perf_test.ivf");
}
}
int main() {
testAOMSupport();
testEncoding();
testDecoding();
testPerformance();
std::cout << "所有测试通过!" << std::endl;
return 0;
}
完成这些配置后,你就可以在Windows环境下使用带有完整libaom AV1编码器/解码器支持的FFmpeg进行开发了。推荐使用vcpkg方法,因为它最简单且维护性最好。