版本 :v3.9.1 | 许可证 :BSD-2-Clause + AOM Patent License 1.0
作者 :码流怪侠 | 标签 :
AV1libaom视频编解码开源项目音视频开发
目录
- [前言:为什么要研究 libaom?](#前言:为什么要研究 libaom?)
- 项目背景与定位
- 整体架构设计
- [公共 API 层:aom/ 目录](#公共 API 层:aom/ 目录)
- [DSP 信号处理层:aom_dsp/](#DSP 信号处理层:aom_dsp/)
- [AV1 核心公共模块:av1/common/](#AV1 核心公共模块:av1/common/)
- 编码器深度解析:av1/encoder/
- 解码器分析:av1/decoder/
- [平台优化层:SIMD 加速](#平台优化层:SIMD 加速)
- 构建系统与跨平台支持
- [实际使用:编解码 API 示例](#实际使用:编解码 API 示例)
- 性能与质量对比
- 总结与展望
一、前言:为什么要研究 libaom?
自 2015 年 Alliance for Open Media(AOM)成立以来,AV1 已成为下一代视频编码标准的事实基石。Netflix 的 4K 内容、YouTube 的主流流媒体、Chrome/Firefox/Edge 的硬件解码支持......AV1 正在席卷整个视频产业。
libaom 是 AV1 的官方参考实现,意义不仅在于"能用",更在于它是编解码算法设计的权威参考。研究 libaom:
- 理解 AV1 规范:标准文本枯燥,源码更直观
- 学习工业级 C/C++ 实践:大型多平台项目、CMake 构建、SIMD 优化、多线程模型
- 掌握编解码器架构:率失真优化、码率控制、多遍编码...这些思想在 x264/x265/VP9 中同样存在
本文基于 libaom v3.9.1 (libaom-main),从目录结构出发,逐层深入每个核心模块,力求给你一份真正"读完能上手"的技术地图。
二、项目背景与定位
2.1 AV1 标准简介
AV1(AOMedia Video 1)是 AOM 联盟于 2018 年正式发布的开放、免专利费的视频编码标准,目标是替代 H.265/HEVC。与 HEVC 相比,AV1 在相同质量下平均码率降低约 30%,而且完全免版税。
AOM 创始成员包括 Google、Mozilla、Microsoft、Netflix、Intel、AMD、ARM、Nvidia 等大厂,可谓业界顶级技术联盟。
2.2 libaom 的角色
| 角色 | 说明 |
|---|---|
| AV1 参考编码器 | 算法正确性的"黄金标准",所有实现须与其对齐 |
| AV1 参考解码器 | 符合规范的基准解码实现 |
| 算法研究平台 | 包含 ML/CNN 模块、全局运动、VMAF 调优等前沿特性 |
| 实时编码支持 | REALTIME 模式支持实时视频流(RTC 场景) |
⚠️ libaom 的编码器并非 为生产环境的极限性能而生,那是 SVT-AV1、rav1e 的战场。libaom 的首要任务是算法正确性与研究灵活性。
2.3 版本历程(v3.9.1 节点)
v3.9.0 (2024-04-09) --- 功能版本
✦ Speed 11 超激进模式(比 Speed 10 快 ~30%)
✦ Arm SVE/SVE2 优化(高位深编码加速 5-9%)
✦ 全局运动估计进一步改进
✦ 新增 SVC 帧丢弃模式控制
v3.9.1 (2024-06-05) --- Bug 修复
✦ 修复 linsolve_wiener 中的缩放溢出(oss-fuzz:68195)
✦ 修复高目标数据率溢出
✦ UBSan 错误修复
三、整体架构设计
理解 libaom 的关键,是先建立"分层"的全局视图:
┌──────────────────────────────────────────────────────────────────┐
│ 应用层 │
│ apps/aomenc.c apps/aomdec.c examples/ tools/ │
├──────────────────────────────────────────────────────────────────┤
│ 公共 API 层(稳定 ABI 边界) │
│ aom/aom_codec.h aom/aomcx.h aom/aomdx.h │
│ aom/aom_encoder.h aom/aom_decoder.h aom/aom_image.h │
├─────────────────────────┬────────────────────────────────────────┤
│ 编码器核心 │ 解码器核心 │
│ av1/av1_cx_iface.c │ av1/av1_dx_iface.c │
│ av1/encoder/ (120+文件)│ av1/decoder/ (10+文件) │
├─────────────────────────┴────────────────────────────────────────┤
│ 公共编解码模块 av1/common/ (80+文件) │
│ 变换·量化·预测·滤波·熵编码·MV参考·超级块·Tile管理 │
├──────────────┬───────────────┬──────────────┬───────────────────┤
│ aom_dsp/ │ aom_scale/ │ aom_mem/ │ aom_util/ │
│ DSP/信号处理 │ 图像缩放 │ 内存管理 │ 线程/调试 │
├──────────────┴───────────────┴──────────────┴───────────────────┤
│ 平台移植层 aom_ports/ │
│ CPU 检测 (x86/ARM/PPC/RISC-V) 内存操作 计时器 ABI 支持 │
├──────────────────────────────────────────────────────────────────┤
│ SIMD 加速层 │
│ x86: SSE2 / SSSE3 / SSE4.1 / AVX2 / AVX-512 │
│ ARM: NEON / SVE / SVE2 PPC: VSX │
└──────────────────────────────────────────────────────────────────┘
第三方库: googletest libwebm libyuv fastfeat(FAST角点)
这种分层设计有几个核心优点:
- ABI 稳定性 :应用只需依赖
aom/*.h,内部实现可自由演化 - 平台无关性 :通过
aom_ports/屏蔽平台差异,RTCD 机制动态选择最优 SIMD 路径 - 编解码解耦 :编码器
av1/encoder/和解码器av1/decoder/独立,可只编译其中一个 - 可测试性 :所有核心模块均有对应
test/*.cc单元测试
四、公共 API 层:aom/ 目录
aom/ 目录是 libaom 对外暴露的唯一"界面",所有应用程序只应包含这里的头文件。
4.1 核心头文件一览
aom/
├── aom_codec.h ← 编解码器通用接口(ctx、iface、control)
├── aom_encoder.h ← 编码器接口(init、encode、get_cx_data)
├── aom_decoder.h ← 解码器接口(init、decode、get_frame)
├── aom_image.h ← 图像数据结构(格式、颜色空间)
├── aomcx.h ← 编码器控制 ID 定义(AV1E_SET_*)
└── aomdx.h ← 解码器控制 ID 定义(AV1D_GET_*)
4.2 编解码器两级接口设计
这是整个 API 层最精妙的设计------算法描述符(iface)与运行时上下文(ctx)分离:
c
// 第一级:算法描述符(静态,唯一)
extern aom_codec_iface_t *aom_codec_av1_cx(void); // 编码器算法接口
extern aom_codec_iface_t *aom_codec_av1_dx(void); // 解码器算法接口
// 第二级:运行时上下文(动态,可多实例)
typedef struct aom_codec_ctx {
const char *name; // 实现名称
aom_codec_iface_t *iface; // 指向算法描述符
aom_codec_err_t err; // 最后一次错误
const char *err_detail; // 错误详情字符串
aom_codec_flags_t init_flags; // 初始化标志
union { ... } config; // 编码器或解码器配置
aom_codec_priv_t *priv; // 不透明内部状态指针
} aom_codec_ctx_t;
priv 指针内部指向 aom_codec_alg_priv_t(实际定义在 av1_cx_iface.c),其核心字段是 AV1_COMP *cpi------这是整个编码器的"大脑"。
4.3 图像格式:aom_image.h
libaom 支持丰富的图像格式,通过位标志组合定义:
c
#define AOM_IMG_FMT_PLANAR 0x100 // 平面格式
#define AOM_IMG_FMT_UV_FLIP 0x200 // V 在 U 前(YV12)
#define AOM_IMG_FMT_HIGHBITDEPTH 0x800 // 16bit 缓冲区存储(10/12bit内容)
| 格式常量 | 采样 | 位深 | 说明 |
|---|---|---|---|
AOM_IMG_FMT_I420 |
4:2:0 | 8 | 最常见格式 |
AOM_IMG_FMT_I422 |
4:2:2 | 8 | 广播级 |
AOM_IMG_FMT_I444 |
4:4:4 | 8 | 专业制作 |
AOM_IMG_FMT_I42016 |
4:2:0 | 10/12 | HDR 主流 |
AOM_IMG_FMT_I44416 |
4:4:4 | 10/12 | 高端制作 |
AOM_IMG_FMT_NV12 |
4:2:0 | 8 | 硬件对齐(UV 交错) |
颜色空间遵循 CICP(Coding-Independent Code Points) 标准,支持 BT.709、BT.2020(HDR)、BT.601 等。
4.4 编码器控制接口(aomcx.h)
编码器的"旋钮"通过 aom_codec_control(ctx, ctrl_id, value) 调节,控制 ID 定义在 aome_enc_control_id 枚举中(范围 7~229+):
c
// 帧级标志(位掩码,传给 aom_codec_encode 的 flags 参数)
#define AOM_EFLAG_NO_REF_LAST (1 << 16) // 禁止参考 LAST 帧
#define AOM_EFLAG_NO_REF_GF (1 << 19) // 禁止参考 Golden 帧
#define AOM_EFLAG_NO_REF_ARF (1 << 20) // 禁止参考 AltRef 帧
#define AOM_EFLAG_NO_UPD_ENTROPY (1 << 26) // 禁止更新熵模型(错误恢复场景)
#define AOM_EFLAG_ERROR_RESILIENT (1 << 28) // 错误恢复模式
#define AOM_EFLAG_SET_S_FRAME (1 << 29) // 设置 S 帧(无缝切换参考帧集)
// 常用编码器控制
AV1E_SET_CPUUSED // 编码速度档位 0~9(越大越快)
AV1E_SET_TARGET_BITRATE // 目标码率(kbps)
AV1E_SET_CQ_LEVEL // CQ/CQP 模式质量等级
AV1E_SET_TILE_COLUMNS // Tile 列数(对数值)
AV1E_SET_TILE_ROWS // Tile 行数(对数值)
AV1E_SET_ENABLE_CDEF // 开关 CDEF 滤波
AV1E_SET_ENABLE_RESTORATION // 开关环路恢复滤波
AV1E_SET_SVC_PARAMS // 设置 SVC 参数
AV1E_SET_VMAF_MODEL_PATH // VMAF 质量调优模型路径
五、DSP 信号处理层:aom_dsp/
aom_dsp/ 是 libaom 的"工具箱",封装了大量底层信号处理算法,供编解码器上层调用。
5.1 模块功能分类
aom_dsp/
├── 🔢 基本运算 variance.c sad.c sse.c sum_squares.c
├── 🎯 变换 fwd_txfm.c txfm_common.h fft.c
├── 🖼️ 预测基础 intrapred.c blend_a64_*.c convolve.c
├── 📊 质量评估 psnr.c ssim.c fastssim.c vmaf.c butteraugli.c
├── 🔊 噪声处理 noise_model.c noise_util.c grain_table.c
├── 🎬 光流估计 flow_estimation/ (corner_detect/match/ransac/disflow)
├── 🧮 熵编码基础 entcode.c entdec.c entenc.c bitreader.c bitwriter.c
├── 📐 量化 quantize.c
├── 🔍 图像分析 pyramid.c fft.c
└── 💻 SIMD 优化 x86/ arm/ simd/
5.2 运行时 CPU 检测(RTCD)
这是 libaom 最精妙的工程设计之一。aom_dsp_rtcd.h 由 Perl 脚本 build/cmake/rtcd.pl 在编译时自动生成,为每个关键函数声明多个实现:
c
// 自动生成的 RTCD 调度(伪代码示意)
void (*aom_sad16x16)(const uint8_t *src, int src_stride,
const uint8_t *ref, int ref_stride);
// 运行时根据 CPUID 初始化为最优实现:
// aom_sad16x16_c --- 纯 C 实现(兜底)
// aom_sad16x16_sse2 --- SSE2 加速
// aom_sad16x16_avx2 --- AVX2 加速(最优)
程序启动时调用 aom_dsp_rtcd() 完成一次性 CPU 探测和函数指针填表,后续所有调用走最优路径,零运行时开销。
5.3 关键算法:光流估计子模块
aom_dsp/flow_estimation/ 是 AV1 全局运动估计的底层支撑:
flow_estimation/
├── corner_detect.c --- FAST 角点检测(依赖 third_party/fastfeat/)
├── corner_match.c --- 角点匹配(光流特征点对应)
├── disflow.c --- DISflow 稠密光流(Dense Inverse Search)
├── ransac.c --- RANSAC 鲁棒估计(排除离群点,拟合变换模型)
└── flow_estimation.c --- 整合:检测→匹配→RANSAC→得到全局变换参数
RANSAC 支持的模型类型:平移(Translation)、旋转缩放(Rotzoom)、仿射(Affine)、透视(Homography),对应 AV1 规范中的 Warp 变换类型。
六、AV1 核心公共模块:av1/common/
av1/common/ 是编解码器的"共享内核",包含编码器和解码器都需要用到的算法。
6.1 超级块与块划分体系
AV1 的块划分体系是其核心设计之一:
c
// enums.h 中的关键定义
#define MAX_SB_SIZE 128 // 最大超级块:128×128 像素
#define MIN_SB_SIZE 64 // 最小超级块:64×64 像素
#define MI_SIZE 4 // 最小编码单元:4×4 像素
#define MAX_MIB_SIZE 32 // 最大超级块含 32×32 个 MI 单元
AV1 支持的块大小(BLOCK_SIZE 枚举)涵盖从 4×4 到 128×128 的多种方形和矩形组合(共约 22 种),这是相比 H.264/H.265 的重要扩展。
6.2 核心功能模块
| 文件 | 功能 | 重要性 |
|---|---|---|
reconinter.c |
帧间预测重建(参考帧插值、复合预测) | ⭐⭐⭐⭐⭐ |
reconintra.c |
帧内预测重建(56 种模式) | ⭐⭐⭐⭐⭐ |
av1_inv_txfm2d.c |
逆变换(DCT/ADST/identity/DST) | ⭐⭐⭐⭐⭐ |
restoration.c |
环路恢复滤波(Wiener/SGR) | ⭐⭐⭐⭐ |
cdef.c |
CDEF 去振铃滤波 | ⭐⭐⭐⭐ |
warped_motion.c |
全局运动/Warped MC | ⭐⭐⭐⭐ |
convolve.c |
8-tap 亚像素卷积 | ⭐⭐⭐⭐⭐ |
mvref_common.c |
MV 参考候选构建(AMVP/Merge 候选列表) | ⭐⭐⭐⭐ |
cfl.c |
色度预测(Chroma from Luma, CfL) | ⭐⭐⭐ |
entropy.c |
熵编码模型(概率分布、CDFs) | ⭐⭐⭐⭐⭐ |
6.3 AV1 Profile 体系
c
enum { PROFILE_0, PROFILE_1, PROFILE_2, MAX_PROFILES };
// Profile 0: 8/10bit 4:2:0 / 4:0:0 (互联网主流)
// Profile 1: 8/10bit 4:4:4 (专业制作)
// Profile 2: 8/10bit 4:2:2 (广播级)
// 12bit 4:0:0/4:2:2/4:4:4(最高位深)
七、编码器深度解析:av1/encoder/
av1/encoder/ 是整个 libaom 最复杂的部分,拥有超过 120 个源文件。这里是 AV1 所有编码智慧的汇聚地。
7.1 编码器主控流程
整个编码器的"大脑"是 AV1_COMP 结构体(定义在 encoder.h),它聚合了编码器所有状态:
AV1_COMP(编码器全局状态)
├── AV1_COMMON cm --- AV1 公共编解码器状态
├── EncodeFrameInput enc_input --- 当前帧输入
├── EncodeFrameParams enc_params --- 当前帧参数
├── RateControlParams rc --- 码率控制参数
├── FIRSTPASS_DATA twopass --- 两遍编码统计数据
├── TPLData tpl_data --- TPL 模型数据
├── TemporalFilterCtx tf_ctx --- 时域滤波上下文
├── TileDataEnc *tile_data --- Tile 编码数据数组
├── lookahead_ctx *lookahead --- 前视缓冲区
├── GlobalMotionInfo gm_info --- 全局运动信息
├── SPEED_FEATURES sf --- 速度特性配置
├── SVC svc --- 可伸缩编码状态
└── ...(数十个字段)
编码一帧的主流程(av1/encoder/encoder.c):
aom_codec_encode() ← 应用层入口
└─ av1_receive_raw_frame() ← 推入前视缓冲区
└─ av1_get_compressed_data() ← 获取压缩数据
├─ av1_lookahead_pop() ← 从前视队列取帧
├─ 场景检测/KF 决策
├─ av1_setup_frame() ← 设置帧参数(帧类型、参考帧等)
├─ encode_frame_to_data_rate() ← 核心编码
│ ├─ av1_encode_strategy() ← 编码策略决策
│ ├─ av1_encode() ← 实际编码
│ │ ├─ av1_encode_tiles_mt() ← 多线程编码 Tile
│ │ │ └─ av1_encode_tile()
│ │ │ └─ av1_encode_sb() ← 超级块编码
│ │ │ ├─ partition_search() ← 分区搜索
│ │ │ ├─ encode_block() ← 块编码
│ │ │ └─ av1_apply_loop_filters() ← 环路滤波
│ │ └─ av1_pack_bitstream() ← 码流打包
│ └─ 码率控制更新
└─ av1_get_one_frame_buffer() ← 输出压缩帧
7.2 多遍编码框架
libaom 支持最多三遍编码 ,在质量模式(GOOD)下两遍是默认配置:
第一遍(First Pass) --- firstpass.c
目的:快速分析每帧统计特征,不产生输出码流
关键统计(FIRSTPASS_STATS):
├─ intra_error --- 帧内预测误差(衡量帧复杂度)
├─ coded_error --- LAST 参考帧的 inter 误差
├─ sr_coded_error --- Golden 帧的 inter 误差
├─ pcnt_motion --- 含运动块的比例
├─ pcnt_inter --- inter 编码更优的块比例
├─ intra_skip_pct --- 近零残差块比例(动画/屏幕内容检测信号)
└─ frame_avg_wavelet_energy --- DWT 小波平均能量
第二遍(Second Pass) --- pass2_strategy.c
目的:利用 first pass 统计数据,做最优 GOP 结构规划和 bit 分配
核心决策:
├─ KF 判定(场景切换检测)
├─ GF/ARF 间隔和层次设计
├─ 每帧比特目标分配
└─ 复杂度加权 bit 分配
第三遍(Third Pass) --- thirdpass.c(可选)
目的:以第二遍码流为参考,进一步优化 bit 分配
应用场景:超高质量编码、研究场景
7.3 前视缓冲区(Lookahead)
Lookahead 机制是 libaom 实现高质量编码的基础设施。相关代码在 lookahead.c/h:
c
// 关键参数
#define MAX_LAG_BUFFERS 48 // 最大前视帧数(质量模式下可达 48 帧)
#define MAX_LAP_BUFFERS 48 // LAP 分析阶段缓冲
#define LAP_LAG_IN_FRAMES 17 // LAP 阶段仅使用 17 帧前视
// 双 Stage 设计
enum { ENCODE_STAGE, LAP_STAGE, MAX_STAGES };
// 核心结构
struct lookahead_ctx {
int max_sz;
int write_idx;
struct read_ctx read_ctxs[MAX_STAGES]; // 各 stage 独立读取位置!
struct lookahead_entry *buf;
int push_frame_count;
};
// 每个 lookahead_entry 存储:
// - 完整的 YV12 帧数据
// - 时间戳 (ts_start / ts_end)
// - 帧级编码标志 (flags)
// - 显示顺序索引 (display_idx)
双 Stage 设计的精妙之处 :ENCODE_STAGE 和 LAP_STAGE 共享同一环形缓冲区,但各自维护独立的读取索引。LAP 阶段超前分析,Encode 阶段实际编码,两者解耦,互不干扰------这是 libaom 支持"单遍延迟 LAP"模式的关键。
7.4 GOP 结构与 AltRef 机制
AV1 的 GOP(Group of Pictures)结构是其超越 H.264/H.265 的重要创新:
典型 GOP 结构(层次化 B 帧 + AltRef):
GF/ARF(L1)
/ \
GF(L2) ARF2(L2)
/ \ / \
LF(L3) LF(L3) LF(L3) LF(L3) ← 叶子帧(Leaf Frame)
- Golden Frame (GF):跨 GOP 参考帧,定期刷新(默认间隔 16~32 帧)
- AltRef (ARF) :通过时域滤波 合成的"未来帧",仅用于参考不展示
temporal_filter.c对未来若干帧做加权融合- 极大提升了参考帧质量,降低后续帧的编码代价
- 内部 AltRef (INTNL_ARF):ARF 可嵌套,形成多层金字塔结构(最多 6 层)
- Overlay 帧:展示时替换 ARF 的实际显示帧
c
// ratectrl.h 中的帧更新类型枚举
enum {
KF_UPDATE, // 关键帧
LF_UPDATE, // 叶子帧(普通帧,B/P 帧)
GF_UPDATE, // Golden 帧
ARF_UPDATE, // AltRef 帧
OVERLAY_UPDATE, // ARF 的展示替代帧
INTNL_OVERLAY_UPDATE, // 内部 ARF 的展示替代帧
INTNL_ARF_UPDATE, // 内部 AltRef(金字塔中间层)
};
7.5 码率控制
av1/encoder/ratectrl.c 实现了多种码率控制模式:
支持的码率控制模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
| VBR (Variable Bitrate) | 可变码率,以目标码率为均值 | 流媒体点播 |
| CBR (Constant Bitrate) | 恒定码率,严格约束每帧比特数 | 实时流媒体 |
| CQ/CQP (Constrained Quality) | 固定量化参数,可选最大码率约束 | 高质量存档 |
| Q (Quality) | 固定质量(CRF 模式),不约束码率 | 离线编码 |
| Lossless | 无损编码 | 内容制作 |
核心参数
c
// 关键阈值(ratectrl.h)
#define MAX_GF_INTERVAL 32 // GF 帧最大间隔
#define MIN_GF_INTERVAL 4 // GF 帧最小间隔
#define MAX_ARF_LAYERS 6 // AltRef 最大层数
#define STATIC_KF_GROUP_THRESH 99 // 静止场景 KF 组判定阈值(%)
// 实时模式专属参数
#define FIXED_GF_INTERVAL_RT 80 // 实时模式 GF 间隔(更长)
#define DEFAULT_KF_BOOST_RT 2300 // 关键帧码率 boost 因子
#define DEFAULT_GF_BOOST_RT 2000 // Golden 帧码率 boost 因子
KF 检测算法
第一遍统计数据驱动场景切换检测:
场景切换条件:
coded_error / prev_coded_error > 阈值 (帧间误差突增)
AND
pcnt_inter < 阈值 (inter 预测效果变差)
AND
连续检测 SCENE_CUT_KEY_TEST_INTERVAL(=16) 帧确认
7.6 率失真优化(RDO)
av1/encoder/rd.c / rdopt.c 实现了 libaom 的"大脑"------率失真优化框架:
基本原理:
RD Cost = Distortion + λ ⋅ Rate \text{RD Cost} = \text{Distortion} + \lambda \cdot \text{Rate} RD Cost=Distortion+λ⋅Rate
其中:
- Distortion(失真)= SSD(Sum of Squared Differences),或 SAD 近似
- Rate(比特数)= 实际比特消耗的 bit count(或近似估计)
- λ(拉格朗日乘子)= 由当前 QP 决定,控制质量与码率的权衡
c
// rdopt.c 中的核心决策过程(简化)
for each candidate (mode, ref_frame, mv) {
// 1. 计算预测
predict_block(candidate);
// 2. 计算残差并变换
compute_residual();
forward_transform();
// 3. 量化(得到量化系数)
quantize();
// 4. 计算率失真代价
distortion = calc_distortion(); // 重建误差
rate = estimate_bits(); // 编码比特估计
rd_cost = distortion + lambda * rate;
// 5. 更新最优候选
if (rd_cost < best_rd_cost) {
best_rd_cost = rd_cost;
best_candidate = candidate;
}
}
速度与 RDO 精度的权衡 :libaom 通过 SPEED_FEATURES 控制 RDO 的"搜索范围"------高速模式下跳过大量候选(如不搜索某些参考帧、跳过变换类型搜索),以牺牲少量质量换取显著加速。
7.7 分区搜索与 CU 划分
AV1 的块划分继承了 HEVC 的 CTU/CU 概念,但扩展更为丰富:
AV1 分区类型(比 H.265 多得多):
PARTITION_NONE --- 不分区(整块编码)
PARTITION_HORZ --- 水平二分
PARTITION_VERT --- 垂直二分
PARTITION_SPLIT --- 四叉树递归分割
PARTITION_HORZ_A --- 水平 + 右侧小块(T 形)
PARTITION_HORZ_B --- 水平 + 左侧小块(T 形)
PARTITION_VERT_A --- 垂直 + 下方小块(T 形)
PARTITION_VERT_B --- 垂直 + 上方小块(T 形)
PARTITION_HORZ_4 --- 水平四分(1:2:1 比例)
PARTITION_VERT_4 --- 垂直四分(1:2:1 比例)
partition_search.c 通过递归 + RDO 在每个超级块中搜索最优分区:
av1_rd_pick_partition()
├─ 尝试 NONE 分区 → 计算 RD Cost
├─ 尝试 SPLIT 分区 → 递归四子块
├─ 尝试 HORZ/VERT 分区
├─ 尝试 T 形分区(HORZ_A/B, VERT_A/B)
└─ 选择最优 RD Cost 的分区方案
速度档位高时,partition_strategy.c 会利用机器学习模型预判分区概率,剪枝大量候选分区,大幅加速。
7.8 运动估计与补偿
运动估计(ME)是帧间编码的核心,libaom 的相关代码分布在:
| 文件 | 功能 |
|---|---|
mcomp.c |
运动搜索核心(菱形/全搜索/Hexagon 等策略) |
motion_search_facade.c |
不同编码场景的 ME 门面接口 |
global_motion.c |
全局运动估计(使用光流) |
global_motion_facade.c |
全局运动编码接口 |
AV1 运动搜索策略:
菱形搜索(DIAMONDSEARCH) --- 默认,速度快
全搜索(FULLSEARCH) --- 最优,极慢
六边形搜索(HEXSEARCH) --- 平衡
运动矢量预测(MVSEARCH) --- 基于参考 MV 的预测搜索
AV1 特有运动特性:
- 复合预测(Compound Prediction) :两个参考帧加权混合
- 距离加权(DIST_WTD_COMP)
- Diff Weighted Compound
- Segment Mask Compound
- Warped Motion(翘曲运动):基于全局运动参数的非刚体运动补偿
- OBMC(Overlapped Block Motion Compensation):重叠块运动补偿,减少块边界伪影
7.9 帧内预测
AV1 帧内预测是 H.265 的重大扩展,支持 **56 种(实际更多)**预测模式:
c
// 方向性模式(angle-based)
UENUM1BYTE(PREDICTION_MODE) {
DC_PRED, // DC 预测(均值)
V_PRED, // 垂直预测
H_PRED, // 水平预测
D45_PRED, // 45° 对角方向预测
D135_PRED, // 135° 方向预测
D113_PRED, // 113° 方向预测
D157_PRED, // 157° 方向预测
D203_PRED, // 203° 方向预测
D67_PRED, // 67° 方向预测
SMOOTH_PRED, // 平滑预测(水平+垂直加权)
SMOOTH_V_PRED, // 垂直平滑预测
SMOOTH_H_PRED, // 水平平滑预测
PAETH_PRED, // Paeth 预测(自然图像效果好)
NEARESTMV, NEARMV, GLOBALMV, NEWMV, ... // 帧间模式
};
AV1 专有帧内特性:
- Intra BC(帧内块复制) :在同一帧内引用已编码区域,专为屏幕内容/动画优化
- CfL(Chroma from Luma) :色度预测利用亮度信号,
cfl.c实现 - Palette 调色板模式 :最多 8 色索引图,
MAX_PALETTE_SIZE=8,适合简单图形
7.10 变换与量化
AV1 变换体系是对 H.265 的重要扩展:
变换类型矩阵
变换类型(二维组合):
行变换 × 列变换:
DCT_DCT --- 标准 DCT(最常用)
ADST_DCT --- 垂直 ADST + 水平 DCT
DCT_ADST --- 垂直 DCT + 水平 ADST
ADST_ADST --- 双向 ADST
FLIPADST_* --- 镜像 ADST
IDTX --- Identity 变换(跳过,适合平坦内容)
H_DCT --- 仅水平 DCT(垂直 Identity)
V_DCT --- 仅垂直 DCT(水平 Identity)
...(共 16 种二维组合)
ADST(Asymmetric Discrete Sine Transform):在块边界处更符合信号特性,减少振铃效应。
变换块大小:从 4×4 到 64×64,支持矩形变换(如 4×16、16×4)。
量化与反量化
c
// av1_quantize.c
// AV1 使用统一量化,基本步骤:
// 1. 正向变换得到变换系数 coeff[]
// 2. 除以量化步长 QStep(由 QP 查表得到)
// 3. 四舍五入得到量化系数 qcoeff[]
// 4. 记录非零系数位置(eob: end-of-block)
// AV1 量化矩阵(Quantization Matrix)
// CONFIG_QUANT_MATRIX=1 时启用,对不同频率系数施加不同权重
// 视觉感知加权:高频系数量化更粗,低频系数量化更细
7.11 熵编码
AV1 使用 ANS(Asymmetric Numeral Systems) 熵编码,而非 H.265 的 CABAC:
AV1 熵编码特点:
✦ 基于非对称数值系统(ANS/rANS)
✦ 上下文自适应(数百个概率模型)
✦ 概率以 CDF(累积分布函数)形式存储,而非单个概率值
✦ 支持无损编码模式(Identity 变换 + 零量化)
核心文件:
aom_dsp/entcode.c/h--- ANS 基础实现aom_dsp/entenc.c--- 编码器 ANSaom_dsp/entdec.c--- 解码器 ANSav1/common/entropy.c--- AV1 上下文模型av1/encoder/tokenize.c--- 系数符号化av1/encoder/bitstream.c--- OBU 码流打包
7.12 环路滤波
AV1 的环路滤波体系是三级的,每级针对不同的视觉失真:
┌──────────────────────────────────────────────────────────┐
│ 第 1 级:Deblocking Filter(去块滤波) │
│ - 消除块边界伪影 │
│ - 对每个变换块边界自适应滤波 │
│ - av1/common/av1_loopfilter.c + picklpf.c │
├──────────────────────────────────────────────────────────┤
│ 第 2 级:CDEF(Constrained Directional Enhancement) │
│ - 去振铃滤波(消除 ringing artifact) │
│ - 方向性滤波,8 种方向独立处理 │
│ - av1/common/cdef.c + av1/encoder/pickcdef.c │
├──────────────────────────────────────────────────────────┤
│ 第 3 级:Loop Restoration(环路恢复) │
│ - 精细恢复细节纹理 │
│ - 两种模式: │
│ ① Wiener 滤波(可分离 7×7 滤波器,自适应系数) │
│ ② SGR(Self-Guided Restoration,导向滤波) │
│ - av1/common/restoration.c + av1/encoder/pickrst.c │
└──────────────────────────────────────────────────────────┘
环路恢复滤波的系数每个 64×64 单元独立优化 ,pickrst.c 中通过 sparse_linear_solver.c(稀疏线性方程组求解器)找到最优 Wiener 滤波系数------这解释了为什么它效果好但编码慢。
7.13 速度特性与速度档位
speed_features.c 是 libaom "速度与质量权衡"的总控开关,有 Speed 0~11 共 12 个档位:
| 速度档位 | 模式 | 典型应用场景 |
|---|---|---|
| 0 | GOOD,极慢 | 质量研究、BD-Rate 基准测试 |
| 1~3 | GOOD,慢 | 离线高质量编码 |
| 4~6 | GOOD,平衡 | 内容制作流水线 |
| 7~9 | GOOD,快 | 批量转码 |
| 0~9 | REALTIME | 实时直播(另一套参数体系) |
| 10 | 超快 | 实时超低延迟 |
| 11 | 极限速度 | 速度 10 的基础上再快 ~30%(v3.9.0 新增) |
速度特性通过关闭/简化以下特性实现加速:
c
// speed_features.h 中的关键控制(示例)
sf.part_sf.partition_search_breakout // 提前终止分区搜索
sf.inter_sf.motion_vector_mode // 简化 MV 搜索
sf.tx_sf.tx_type_search.fast_intra_tx_type_search // 跳过大量变换类型
sf.mv_sf.search_method // 运动搜索方法降级(钻石→六边形)
sf.intra_sf.intra_pruning_with_hog // 用 HoG 特征剪枝帧内模式
sf.rd_sf.use_fast_coef_costing // 系数代价快速估计
sf.global_motion_search_type // 全局运动搜索策略降级
sf.interp_filter_search_mask // 插值滤波类型搜索范围
帧内模式搜索掩码设计:
c
// 速度越高,候选模式集合越小
INTRA_ALL = DC|V|H|D45|D135|D113|D157|D203|D67|SMOOTH|SMOOTH_V|SMOOTH_H|PAETH
INTRA_DC_H_V_SMOOTH = DC|V|H|SMOOTH // 快速模式:仅 4 种
INTRA_DC = DC_PRED // 极速模式:仅 DC
7.14 机器学习集成
libaom 是业界最早将 ML 深度融入编码器的实现之一:
ML 应用场景(encoder/ml.c / cnn.c):
1. 分区决策加速(partition_ml_models/)
→ 用轻量 CNN 预测最可能的分区类型,剪枝 RDO 搜索
2. 运动搜索指导
→ ML 模型预测运动矢量搜索的起点
3. VMAF 感知质量调优(tune_vmaf.c)
→ 以 VMAF 评分而非 PSNR 为优化目标
→ 需要 CONFIG_TUNE_VMAF=1 编译选项
4. Butteraugli 调优(tune_butteraugli.c)
→ Google 的感知质量度量,人眼视觉模型
5. 显著图引导(saliency_map.c)
→ 人眼注视区域更高质量,背景区域降质
6. 光流辅助全局运动(optical_flow.c)
→ 基于 DISflow 的稠密光流用于 Warp 参数估计
八、解码器分析:av1/decoder/
相比编码器的复杂,解码器相对简洁(约 10 个源文件),遵循严格的规范定义:
8.1 解码器核心模块
av1/decoder/
├── obu.c --- OBU(Open Bitstream Unit)解析与派发
├── decodeframe.c --- 帧解码主流程(包括参考帧管理)
├── decodemv.c --- 运动向量解码(从熵流还原 MV)
├── decodetxb.c --- 变换块系数解码
├── detokenize.c --- 系数反符号化(dequant → 重建系数)
├── decoder.c --- 解码器初始化、线程管理
├── grain_synthesis.c --- 胶片颗粒合成(Film Grain)
├── accounting.c --- 码流统计(每个 OBU 比特数统计)
└── inspection.c --- 码流检查(AOMAnalyzer 工具接口)
8.2 OBU(Open Bitstream Unit)体系
AV1 的码流单元体系------OBU 是 AV1 与 H.265 NAL Unit 的对应概念:
| OBU 类型 | 说明 |
|---|---|
OBU_SEQUENCE_HEADER |
序列头(Profile、Level、分辨率、位深) |
OBU_FRAME_HEADER |
帧头(帧类型、显示/渲染尺寸、参考帧标识) |
OBU_FRAME |
完整帧(帧头 + Tile 数据的合并形式) |
OBU_TILE_GROUP |
Tile 组数据(熵编码压缩数据) |
OBU_METADATA |
元数据(HDR信息、Film Grain 参数等) |
OBU_TILE_LIST |
Tile 列表(Light Field 应用) |
OBU_TEMPORAL_DELIMITER |
时域分隔符(访问单元边界标记) |
8.3 Film Grain(胶片颗粒合成)
这是 AV1 的特色功能------在解码端合成模拟胶片颗粒感,而无需在码流中传输实际颗粒噪声:
c
// grain_synthesis.c 核心流程
// 1. 从 OBU_METADATA 中读取 Film Grain 参数
// (ar_coeffs_y, ar_coeffs_cb, ar_coeffs_cr, scaling_shift 等)
// 2. 生成伪随机颗粒噪声(基于标准 LUT)
// 3. 自回归滤波生成有相关性的颗粒
// 4. 按亮度缩放颗粒强度(亮部颗粒细,暗部颗粒粗)
// 5. 叠加到重建图像上
// 意义:将颗粒噪声信息以 ~200 bits 的参数编码,
// 而直接编码颗粒噪声需要 MB 级别的带宽
九、平台优化层:SIMD 加速
libaom 的性能来自精心编写的 SIMD 代码,覆盖主流架构:
9.1 SIMD 覆盖范围
| 架构 | SIMD 指令集 | 关键优化函数 |
|---|---|---|
| x86/x86-64 | SSE2/SSSE3/SSE4.1 | 基础函数集,兜底 |
| x86/x86-64 | AVX2 | 主要加速路径,256-bit SIMD |
| x86/x86-64 | AVX-512 | 部分函数(需编译选项开启) |
| ARM/ARM64 | NEON | 主要移动平台优化 |
| ARM64 | SVE / SVE2 | 高端 ARM 服务器/移动(v3.9.0 重点优化) |
| PowerPC | VSX | 服务器支持 |
9.2 优化热点函数(以 SAD 为例)
c
// 以 SAD(Sum of Absolute Differences)为例,展示多级实现:
// 纯 C 实现(兜底)
unsigned int aom_sad16x16_c(const uint8_t *src, int src_stride,
const uint8_t *ref, int ref_stride) {
unsigned int sad = 0;
for (int r = 0; r < 16; r++) {
for (int c = 0; c < 16; c++)
sad += abs(src[c] - ref[c]);
src += src_stride; ref += ref_stride;
}
return sad;
}
// SSE2 实现(16 路并行)
unsigned int aom_sad16x16_sse2(...) {
// _mm_sad_epu8() 指令一次计算 16 个绝对差之和
// 一次循环处理 16 个像素 × 16 行 = 256 个像素
}
// AVX2 实现(32 路并行)
unsigned int aom_sad16x16_avx2(...) {
// 256-bit 寄存器,一次 32 像素
// 循环次数减半,显著减少分支预测开销
}
9.3 RTCD 动态分发机制详解
构建时(编译期):
rtcd.pl 脚本 → 生成 aom_dsp_rtcd.h(函数指针声明 + C 实现宏)
运行时(启动期):
aom_dsp_rtcd() →
check_cpuid() → 检测 SSE2/AVX2/AVX512 支持
↓
设置函数指针表(一次性):
aom_sad16x16 = aom_sad16x16_avx2; // 若支持 AVX2
aom_convolve8 = aom_convolve8_avx2;
...
↓
后续所有调用通过函数指针,无额外开销
十、构建系统与跨平台支持
10.1 CMake 构建体系
libaom 使用纯 CMake 构建,主要配置文件:
cmake
# CMakeLists.txt 关键配置
cmake_minimum_required(VERSION 3.9)
project(AOM C CXX)
# 库版本(libtool 体系)
set(LT_CURRENT 12) # ABI 版本
set(LT_AGE 9) # 向后兼容版本数
set(LT_REVISION 1) # 补丁版本
# 生成的 .so 版本: libaom.so.3.9.1(= SO_VERSION.LT_AGE.LT_REVISION)
10.2 支持平台矩阵
| 平台 | 架构 | 编译器 | 状态 |
|---|---|---|---|
| Linux | x86-64, ARM64, ARMv7, RISC-V | GCC 6+, Clang 7+ | ✅ |
| macOS | x86-64, Apple Silicon(ARM64) | Clang 7+ | ✅ |
| Windows | x86-64, x86 | MSVC 2019+ | ✅ |
| Windows | x86-64 | MinGW-GCC | ✅ |
| iOS | ARM64, ARMv7 | Clang | ✅ |
| Android | ARM64, ARMv7, x86 | NDK | ✅ |
| WebAssembly | --- | Emscripten | ✅ |
| PowerPC | PPC64 | GCC | ✅ |
10.3 关键构建选项
bash
# 标准构建(Release 模式,开启 SIMD)
cmake ../libaom-main -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
# 禁用 SIMD(纯 C,调试/可移植性)
cmake ../libaom-main -DAOM_TARGET_CPU=generic
# 仅构建解码器(减小体积)
cmake ../libaom-main -DCONFIG_AV1_ENCODER=0
# 开启 VMAF 质量调优
cmake ../libaom-main -DCONFIG_TUNE_VMAF=1
# 开启内部统计(质量研究)
cmake ../libaom-main -DCONFIG_INTERNAL_STATS=1
# 内存检测
cmake ../libaom-main -DSANITIZE=address
# 交叉编译 ARM64 Linux
cmake ../libaom-main \
-DCMAKE_TOOLCHAIN_FILE=../libaom-main/build/cmake/toolchains/arm64-linux-gcc.cmake
十一、实际使用:编解码 API 示例
11.1 最简单的编码器
基于 examples/simple_encoder.c 的核心逻辑:
c
#include "aom/aom_encoder.h"
#include "aom/aomcx.h"
int main() {
aom_codec_ctx_t codec;
aom_codec_enc_cfg_t cfg;
aom_image_t raw;
// 1. 获取默认配置
aom_codec_enc_config_default(aom_codec_av1_cx(), &cfg, 0);
cfg.g_w = 1280;
cfg.g_h = 720;
cfg.rc_target_bitrate = 2000; // 2 Mbps
cfg.g_usage = GOOD; // 质量模式
// 2. 初始化编码器
aom_codec_enc_init(&codec, aom_codec_av1_cx(), &cfg, 0);
// 3. 设置速度(0=最慢最好,9=最快)
aom_codec_control(&codec, AOME_SET_CPUUSED, 4);
// 4. 分配图像缓冲区
aom_img_alloc(&raw, AOM_IMG_FMT_I420, 1280, 720, 1);
while (/* 有帧 */) {
// 5. 填充 raw 数据...
// 6. 编码一帧
aom_codec_encode(&codec, &raw, pts, duration, 0 /* flags */);
// 7. 取出压缩数据
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt;
while ((pkt = aom_codec_get_cx_data(&codec, &iter)) != NULL) {
if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
// pkt->data.frame.buf ← 压缩数据
// pkt->data.frame.sz ← 压缩数据大小
// pkt->data.frame.flags ← AOM_FRAME_IS_KEY 等
}
}
}
// 8. Flush(drain 剩余帧)
aom_codec_encode(&codec, NULL, 0, 0, 0);
// ... 继续取帧 ...
aom_img_free(&raw);
aom_codec_destroy(&codec);
return 0;
}
11.2 最简单的解码器
基于 examples/simple_decoder.c 的核心逻辑:
c
#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
int main() {
aom_codec_ctx_t codec;
aom_codec_dec_cfg_t cfg = { 0, 0, 0, 1 };
cfg.threads = 4; // 使用 4 线程解码
// 1. 初始化解码器
aom_codec_dec_init(&codec, aom_codec_av1_dx(), &cfg, 0);
while (/* 有压缩数据 */) {
// 2. 解码一个数据包
aom_codec_decode(&codec, frame_data, frame_size,
NULL /* user_priv */);
// 3. 获取解码帧
aom_codec_iter_t iter = NULL;
aom_image_t *img;
while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
// img->planes[AOM_PLANE_Y] ← Y 分量数据
// img->planes[AOM_PLANE_U] ← U 分量数据
// img->planes[AOM_PLANE_V] ← V 分量数据
// img->d_w, img->d_h ← 显示宽高
// img->bit_depth ← 位深(8/10/12)
}
}
aom_codec_destroy(&codec);
return 0;
}
11.3 aomenc 命令行常用参数
bash
# 基本两遍编码(推荐,最优质量)
aomenc --codec=av1 --cpu-used=4 --end-usage=vbr \
--target-bitrate=2000 --passes=2 \
--pass=1 --fpf=stats.log -o /dev/null input.yuv
aomenc --codec=av1 --cpu-used=4 --end-usage=vbr \
--target-bitrate=2000 --passes=2 \
--pass=2 --fpf=stats.log -o output.ivf input.yuv
# 固定质量(CQ 模式)
aomenc --codec=av1 --cpu-used=4 --end-usage=q \
--cq-level=32 -o output.ivf input.yuv
# 实时直播编码(低延迟)
aomenc --codec=av1 --cpu-used=8 --end-usage=cbr \
--target-bitrate=2000 --rt --lag-in-frames=0 \
-o output.ivf input.yuv
# 高质量编码(CPU 0,最慢)
aomenc --codec=av1 --cpu-used=0 --end-usage=q \
--cq-level=24 --lag-in-frames=48 \
-o output.ivf input.yuv
十二、性能与质量对比
12.1 AV1 与 HEVC 编码效率对比(BD-Rate)
基于学术测试(YUV 4:2:0 8bit,两遍编码 Speed 4):
| 内容类型 | AV1 vs HEVC(HM) | AV1 vs x265 (slow) |
|---|---|---|
| 自然视频(PSNR) | -30% ~ -35% | -15% ~ -20% |
| 屏幕内容(SSIM) | -40% ~ -50% | -25% ~ -30% |
| 高分辨率 4K | -28% ~ -33% | -12% ~ -18% |
注:负值表示相同质量下 AV1 码率更低(即压缩效率更高)。
12.2 编码速度对比
libaom 以编码质量为主,速度弱于 SVT-AV1:
| 编码器 | 1080p Speed 4 | 1080p Speed 8 | 相对质量 |
|---|---|---|---|
| libaom | ~2 fps | ~15 fps | ⭐⭐⭐⭐⭐ |
| SVT-AV1 | ~50 fps | ~120 fps | ⭐⭐⭐⭐ |
| rav1e | ~15 fps | ~60 fps | ⭐⭐⭐⭐ |
12.3 解码性能
解码方面,libaom 的参考解码器(单线程)性能:
- 1080p@30fps:约 150 fps(x86-64 AVX2,单线程)
- 多线程解码:支持 Tile 级并行,4线程约 4× 加速
十三、总结与展望
13.1 libaom 的核心设计理念
通过对 v3.9.1 的深入分析,可以总结出 libaom 的核心设计哲学:
- 算法正确性第一:宁慢勿错,这是参考实现的天职
- 分层解耦 :API/算法/平台三层清晰分离,
aom_ports/做到了真正的平台无关 - RTCD 零开销多态:一套代码多平台最优,编译时生成,运行时一次选择
- 前视驱动的质量:最多 48 帧前视 + 多遍编码,让 bit 分配最优化
- 机器学习集成:分区决策、VMAF 调优、Butteraugli 调优,走在学术前沿
13.2 libaom 的局限性
- 编码速度慢:质量优先设计,Speed 4 下约 2fps(1080p),生产环境建议用 SVT-AV1
- 代码复杂度高:编码器超过 120 个源文件,学习曲线陡峭
- API 不够稳定 :内部结构频繁重构(但
aom/*.hABI 保持兼容)
13.3 未来方向
根据代码中的实验性功能标志(CONFIG_*),以下方向正在研发中:
- VVC/H.266 方向借鉴:更精细的分区、LFNST 等
- ML 深度集成:更多基于 TFLite 的 ML 推断路径
- 编码并行化 :帧级并行编码(
CONFIG_FPMT_TEST) - SVE2 优化:ARM SVE2 带来的进一步加速
- AV2 预研:libaom 将作为 AV2 研究的基础平台
13.4 如果你要上手 libaom
学习路线建议:
1. 从 examples/simple_encoder.c 开始 → 跑通第一个编码程序
2. 读 aom/aomcx.h → 掌握所有编码控制旋钮
3. 研究 av1/encoder/lookahead.h/c → 理解前视缓冲区机制
4. 深入 av1/encoder/firstpass.c → 掌握两遍编码的 first pass
5. 啃 av1/encoder/rd.c + rdopt.c → 理解率失真优化核心
6. 看 av1/encoder/ratectrl.c → 码率控制完整流程
7. 读 aom_dsp/flow_estimation/ → 全局运动估计实现
附录:关键文件速查表
| 你想了解的 | 对应源文件 |
|---|---|
| 编码器 API 接口 | aom/aomcx.h, av1/av1_cx_iface.c |
| 解码器 API 接口 | aom/aomdx.h, av1/av1_dx_iface.c |
| 编码器主数据结构 | av1/encoder/encoder.h |
| 前视缓冲区 | av1/encoder/lookahead.h/c |
| 第一遍分析 | av1/encoder/firstpass.c/h |
| GOP 结构/AltRef | av1/encoder/gop_structure.c, av1/encoder/pass2_strategy.c |
| 码率控制 | av1/encoder/ratectrl.c/h |
| 帧编码主流程 | av1/encoder/encodeframe.c |
| 分区搜索 | av1/encoder/partition_search.c |
| 率失真优化 | av1/encoder/rd.c, av1/encoder/rdopt.c |
| 运动估计 | av1/encoder/mcomp.c |
| 全局运动 | av1/encoder/global_motion.c, aom_dsp/flow_estimation/ |
| 帧内预测 | av1/common/reconintra.c |
| 帧间预测 | av1/common/reconinter.c |
| 变换 | av1/encoder/av1_fwd_txfm2d.c, av1/common/av1_inv_txfm2d.c |
| 量化 | av1/encoder/av1_quantize.c |
| 熵编码 | aom_dsp/entenc.c, av1/encoder/bitstream.c |
| CDEF 滤波 | av1/common/cdef.c, av1/encoder/pickcdef.c |
| 环路恢复 | av1/common/restoration.c, av1/encoder/pickrst.c |
| 速度特性 | av1/encoder/speed_features.c/h |
| OBU 解析 | av1/decoder/obu.c |
| Film Grain | av1/decoder/grain_synthesis.c |
| SIMD 加速 | aom_dsp/x86/, aom_dsp/arm/, av1/encoder/x86/, av1/encoder/arm/ |
| CPU 检测 | aom_ports/x86.h, aom_ports/arm.h |
| 构建系统 | build/cmake/aom_configure.cmake, build/cmake/rtcd.pl |
本文基于 libaom-main (v3.9.1) 源码分析,如有疏漏欢迎指正。
AV1 规范文档:https://aomediacodec.github.io/av1-spec/
libaom 官方仓库:https://aomedia.googlesource.com/aom/