AV1 重叠块运动补偿OBMC原理
- 对于一个帧间编码块,重叠块运动补偿 OBMC 被允许当下面条件都满足时:
- 当前块是单一预测
- 宽或高是大于或等于 8 采样
- 至少有一个相邻块是帧间预测
- 当 OBMC 被应用在当前块时,首先,使用当前块分配的运动矢量生成初始的帧间预测样本,然后,将当前块的帧间预测样本与基于上方和左侧块的运动矢量生成的帧间预测样本混合,以生成最终的预测样本。基于当前块的大小,限制了邻近运动矢量的最大数量,每个上方和左侧块最多可以有4个运动矢量参与当前块的OBMC过程。
- 在下图中展示了一个相邻块处理顺序的例子,其中每个块中标记的值表示当前块和相邻块运动矢量的处理顺序。具体来说,首先应用当前块的运动矢量来生成帧间预测样本 P0(x,y)。然后,应用块 1 的运动矢量来生成预测样本 p1(x,y)。之后,在块 0 和块 1 之间的重叠区域,预测样本是 p0(x,y) 和 p1(x,y) 的加权平均值。块1和块0的重叠区域在下图中以灰色标记。以相同的方式进一步应用并混合块 2、3、4 的运动矢量。
- 通过这种方式,OBMC技术平滑了块边缘,减少了块效应,特别是在快速运动或复杂场景中,可以提高预测的准确性和视频质量。
libaom 相关源码分析
- 开关控制:unsigned int disable_obmc;在头文件 aom_encoder.h 中 cfg_options 结构体中声明控制变量;
- 函数控制逻辑关系:
- 运动模式:SIMPLE_TRANSLATION、OBMC_CAUSAL、WARPED_CAUSAL。
- motion_mode_allowed 函数
- 用于确定在视频编码过程中是否允许使用特定的运动模式。这个函数考虑了多种条件来决定是否允许使用简单的平移运动(SIMPLE_TRANSLATION)、重叠块运动补偿(OBMC_CAUSAL)或扭曲运动补偿(WARPED_CAUSAL);
- 调用check_num_overlappable_neighbors 函数判断如果当前宏块(MB_MODE_INFO)没有足够的可重叠邻居块,则只允许使用简单的平移运动。
- 如果当前帧不强制使用整数运动矢量,则检查全局运动参数;如果当前宏块使用全局运动矢量,则只允许使用简单的平移运动。
- 检查当前宏块的大小是否允许运动变化、检查当前模式是否为帧间模式,并且是否有第二个参考帧(不是内部帧)、检查复合模式是否允许运动变化;
- 如果当前宏块至少有一个投影参考,并且允许扭曲运动,并且当前帧不强制使用整数运动矢量,并且参考尺度因子没有被缩放,则允许使用扭曲运动补偿。
- 否则,如果满足运动变化的条件,但不允许扭曲运动,或者不满足扭曲运动的其他条件,则允许使用重叠块运动补偿。
- 上述条件不满足,返回简单的平移运动。
static INLINE MOTION_MODE
motion_mode_allowed(const WarpedMotionParams *gm_params, const MACROBLOCKD *xd,const MB_MODE_INFO *mbmi, int allow_warped_motion) {if (!check_num_overlappable_neighbors(mbmi)) return SIMPLE_TRANSLATION;if (xd->cur_frame_force_integer_mv == 0) {const TransformationType gm_type = gm_params[mbmi->ref_frame[0]].wmtype;if (is_global_mv_block(mbmi, gm_type)) return SIMPLE_TRANSLATION;}if (is_motion_variation_allowed_bsize(mbmi->bsize) &&is_inter_mode(mbmi->mode) && mbmi->ref_frame[1] != INTRA_FRAME &&is_motion_variation_allowed_compound(mbmi)) {assert(!has_second_ref(mbmi));if (mbmi->num_proj_ref >= 1 && allow_warped_motion &&!xd->cur_frame_force_integer_mv &&!av1_is_scaled(xd->block_ref_scale_factors[0])) {return WARPED_CAUSAL;}return OBMC_CAUSAL;}return SIMPLE_TRANSLATION;
}
6. obmc_diamond_search_sad 函数
● 该函数通过在参考帧中搜索最佳匹配块来最小化SAD值,同时考虑了OBMC掩码和运动矢量成本。通过递减搜索步长和遍历搜索站点,这个函数能够找到最佳的运动矢量,以提高视频编码的效率和质量。
static int obmc_diamond_search_sad(const FULLPEL_MOTION_SEARCH_PARAMS *ms_params, FULLPEL_MV start_mv,FULLPEL_MV *best_mv, int search_step, int *num00) {const aom_variance_fn_ptr_t *fn_ptr = ms_params->vfp;const search_site_config *cfg = ms_params->search_sites;const MV_COST_PARAMS *mv_cost_params = &ms_params->mv_cost_params;const MSBuffers *ms_buffers = &ms_params->ms_buffers;const int32_t *wsrc = ms_buffers->wsrc;const int32_t *mask = ms_buffers->obmc_mask;const struct buf_2d *const ref_buf = ms_buffers->ref;const int tot_steps = cfg->num_search_steps