libaom
- libaom 是 AOMedia Video 1 (AV1) 视频编码格式的参考实现库,由 Alliance for Open Media (AOMedia) 开发和维护。AV1 是一个高效、开放、免专利授权的下一代视频编解码标准,设计目标是提供较高的视频压缩效率,同时适配各种分辨率、码率和平台。
- 下载:
git clone https://aomedia.googlesource.com/aom
- 以下是libaom的一些关键特点:
开放和免版税:libaom提供了一个开放源代码的编码器,任何个人和组织都可以免费使用,无需支付版税。
高效的编码:libaom旨在提供高效的视频压缩,以适应不同的网络条件和设备性能。
跨平台:libaom支持多种操作系统和平台,包括Windows、Linux和macOS。
AV1编解码器:libaom实现了AV1编解码器,这是一种基于块的视频编码格式,它使用了一系列先进的压缩技术,如CDEF(Constrained Directional Enhancement Filtering)、CIC(Compound Internal Coding)、和PAET(Probabilistic Angular Early Termination)等。
可配置性:libaom提供了多种配置选项,允许开发者根据应用需求调整编码参数。
实时编码:libaom支持实时编码,适用于直播和实时通信应用。
兼容性:libaom编码的视频可以在支持AV1解码的任何播放器或设备上播放。
社区支持:作为一个开源项目,libaom得到了活跃的社区支持,不断有新功能和改进被加入。
libaom是实现AV1视频编码标准的关键部分,它被许多视频播放器、浏览器和视频服务提供商所采用。随着AV1编解码器的成熟和普及,libaom将继续在视频编码领域发挥重要作用。
AV1 帧间Skip模式
- AV1 的帧间Skip 模式是一种压缩工具,用于提高编码效率。通过跳过某些特定块的编码过程,Skip 模式可以显著减少比特率需求,同时保持较高的视频质量。这种方法尤其适合于低运动场景或重复帧。
- Skip 模式是 AV1 编码器中不可或缺的优化工具,通过智能跳过不必要的计算和编码步骤,不仅显著提升了编码效率,还能在低比特率场景中保持良好的视觉质量。它与其他压缩技术(如 Zeromv、残差剪枝)协同工作,共同实现 AV1 在现代视频编码中的性能优势。
- Skip 模式的定义:Skip 模式的核心思想是,如果某个块的内容可以通过参考帧完全预测出来,就无需显式存储该块的数据。此时编码器可以跳过:
- 变换系数的编码。
- 残差的计算和编码。
- 运动矢量的编码(在特定情况下)。
- 当使用 Skip 模式时,解码器会直接从参考帧重建该块的内容。
- Skip 模式的优点
- 显著节省比特率:减少了不必要的信息存储,降低了编码复杂度。
- 提高编码效率:跳过某些复杂计算,如变换和残差编码,编码速度加快。
- 适用性广:在静态场景、重复帧或低运动内容中效果显著。
- Skip 模式的局限性
- 不适用于高运动块:高运动内容通常需要显式存储残差和运动矢量,Skip 模式难以触发。
- 依赖参考帧质量:如果参考帧质量较低,Skip 模式可能会导致解码器重建的块质量下降。
- 需结合其他模式优化:Skip 模式通常与 Zeromv 或 Nearestmv 模式结合使用,需要编码器智能选择。
- 帧间 Skip 模式的触发条件:在帧间预测中,Skip 模式的使用条件主要包括以下几方面:
- 残差为零:预测值和块内容完全匹配,没有残差需要编码。例如:静态背景、重复内容块。
- 无显著变换系数:预测块的变换系数接近零,可以省略变换编码。
- 运动矢量和预测运动矢量一致:如果块的运动矢量等于预测运动矢量,可以跳过运动矢量的显式编码。
- 块划分模式一致:当前块划分方式与参考帧的划分方式一致。
libaom 帧间Skip模式分析
- 流程框图:
av1_rd_pick_inter_mode_sb_seg_skip
函数源码分析
//开启SEG_LVL_SKIP时,帧间 skip 模式计算
void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
TileDataEnc *tile_data, MACROBLOCK *x,
int mi_row, int mi_col,
RD_STATS *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far) {
const AV1_COMMON *const cm = &cpi->common;
const FeatureFlags *const features = &cm->features;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = xd->mi[0];
unsigned char segment_id = mbmi->segment_id;
const int comp_pred = 0;
int i;
unsigned int ref_costs_single[REF_FRAMES];
unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
const ModeCosts *mode_costs = &x->mode_costs;
const int *comp_inter_cost =
mode_costs->comp_inter_cost[av1_get_reference_mode_context(xd)];
InterpFilter best_filter = SWITCHABLE;
int64_t this_rd = INT64_MAX;
int rate2 = 0;
const int64_t distortion2 = 0;
(void)mi_row;
(void)mi_col;
(void)tile_data;
av1_collect_neighbors_ref_counts(xd);//分析当前块的邻居块,统计它们的参考帧使用情况
//根据当前块上下文,估算编码参考帧所需要的比特数
estimate_ref_frame_costs(cm, xd, mode_costs, segment_id, ref_costs_single,
ref_costs_comp);
for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
for (i = LAST_FRAME; i < REF_FRAMES; ++i) x->pred_mv_sad[i] = INT_MAX;
rd_cost->rate = INT_MAX;
assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP));//检查是否启用了 SEG_LVL_SKIP 特性
//调色板模式与滤波模式初始化
mbmi->palette_mode_info.palette_size[0] = 0;
mbmi->palette_mode_info.palette_size[1] = 0; //禁用调色板,因为 SEG_LVL_SKIp 特性下通常不使用调色板
mbmi->filter_intra_mode_info.use_filter_intra = 0; //不使用滤波器内插
//模式和运动设置
mbmi->mode = GLOBALMV; //全局运动
mbmi->motion_mode = SIMPLE_TRANSLATION; //简单平移运动,不考虑亚像素精度和其他运动模式
mbmi->uv_mode = UV_DC_PRED;//色度使用 DC 模式
//参考帧选择
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME))
mbmi->ref_frame[0] = get_segdata(&cm->seg, segment_id, SEG_LVL_