Commit 5329a2bf authored by Yue Chen's avatar Yue Chen

Restrict the number of neighbors in obmc mode

Enable obmc mode only when there are <= 2 left neighbors and <=2
above neighbors. Also disable it when there is no overlappable
neighbors.

Gain in AWCY test: 1.60%, was 1.64% when there is no restriction

Change-Id: I2d82ef4fb4daa9b0843ac8844f99b9f412c4f379
parent 641b7a8e
......@@ -353,6 +353,9 @@ typedef struct {
INTERINTER_COMPOUND_DATA interinter_compound_data;
#endif // CONFIG_EXT_INTER
MOTION_MODE motion_mode;
#if CONFIG_MOTION_VAR
int overlappable_neighbors[2];
#endif // CONFIG_MOTION_VAR
int_mv mv[2];
int_mv pred_mv[2];
#if CONFIG_REF_MV
......@@ -1036,6 +1039,18 @@ static INLINE int is_motion_variation_allowed_bsize(BLOCK_SIZE bsize) {
return (bsize >= BLOCK_8X8);
}
#if CONFIG_MOTION_VAR
static INLINE int check_num_overlappable_neighbors(const MB_MODE_INFO *mbmi) {
if (mbmi->overlappable_neighbors[0] == 0 &&
mbmi->overlappable_neighbors[1] == 0)
return 0;
if (mbmi->overlappable_neighbors[0] > 2 ||
mbmi->overlappable_neighbors[1] > 2)
return 0;
return 1;
}
#endif
static INLINE MOTION_MODE motion_mode_allowed(const MB_MODE_INFO *mbmi) {
#if CONFIG_EXT_INTER
if (is_motion_variation_allowed_bsize(mbmi->sb_type) &&
......@@ -1044,6 +1059,9 @@ static INLINE MOTION_MODE motion_mode_allowed(const MB_MODE_INFO *mbmi) {
if (is_motion_variation_allowed_bsize(mbmi->sb_type) &&
is_inter_mode(mbmi->mode)) {
#endif // CONFIG_EXT_INTER
#if CONFIG_MOTION_VAR
if (!check_num_overlappable_neighbors(mbmi)) return SIMPLE_TRANSLATION;
#endif
#if CONFIG_WARPED_MOTION
if (!has_second_ref(mbmi) && mbmi->num_proj_ref[0] >= 3)
return WARPED_CAUSAL;
......
......@@ -1545,6 +1545,52 @@ const uint8_t *av1_get_obmc_mask_flipped(int length) {
}
#endif // CONFIG_NCOBMC
void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd,
int mi_row, int mi_col) {
int i, mi_step;
xd->mi[0]->mbmi.overlappable_neighbors[0] = 0;
xd->mi[0]->mbmi.overlappable_neighbors[1] = 0;
if (xd->up_available) {
for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
int mi_row_offset = -1;
int mi_col_offset = i;
MODE_INFO *above_mi =
xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
MB_MODE_INFO *above_mbmi = &above_mi->mbmi;
mi_step = AOMMIN(xd->n8_w, mi_size_wide[above_mbmi->sb_type]);
if (is_neighbor_overlappable(above_mbmi)) {
xd->mi[0]->mbmi.overlappable_neighbors[0]++;
if (!CONFIG_CB4X4 && (above_mbmi->sb_type == BLOCK_4X4 ||
above_mbmi->sb_type == BLOCK_4X8))
xd->mi[0]->mbmi.overlappable_neighbors[0]++;
}
}
}
if (xd->left_available) {
for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
int mi_row_offset = i;
int mi_col_offset = -1;
MODE_INFO *left_mi =
xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
MB_MODE_INFO *left_mbmi = &left_mi->mbmi;
mi_step = AOMMIN(xd->n8_h, mi_size_high[left_mbmi->sb_type]);
if (is_neighbor_overlappable(left_mbmi)) {
xd->mi[0]->mbmi.overlappable_neighbors[1]++;
if (!CONFIG_CB4X4 && (left_mbmi->sb_type == BLOCK_4X4 ||
left_mbmi->sb_type == BLOCK_8X4))
xd->mi[0]->mbmi.overlappable_neighbors[1]++;
}
}
}
}
// This function combines motion compensated predictions that is generated by
// top/left neighboring blocks' inter predictors with the regular inter
// prediction. We assume the original prediction (bmc) is stored in
......
......@@ -541,6 +541,8 @@ static INLINE int av1_is_interp_needed(const MACROBLOCKD *const xd) {
#if CONFIG_MOTION_VAR
const uint8_t *av1_get_obmc_mask(int length);
void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd,
int mi_row, int mi_col);
void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
int mi_row, int mi_col,
uint8_t *above[MAX_MB_PLANE],
......
......@@ -1960,6 +1960,9 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
if (mbmi->sb_type >= BLOCK_8X8 && !has_second_ref(mbmi))
mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
#endif // CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR
av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
#endif
#if CONFIG_SUPERTX
if (!supertx_enabled) {
......
......@@ -9649,19 +9649,22 @@ void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data,
#endif // CONFIG_REF_MV
#if CONFIG_MOTION_VAR
av1_build_prediction_by_above_preds(cm, xd, mi_row, mi_col,
opt_args.above_pred_buf, dst_width1,
dst_height1, opt_args.above_pred_stride);
av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col,
opt_args.left_pred_buf, dst_width2,
dst_height2, opt_args.left_pred_stride);
av1_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
x->mask_buf = mask2d_buf;
x->wsrc_buf = weighted_src_buf;
calc_target_weighted_pred(
cm, x, xd, mi_row, mi_col, opt_args.above_pred_buf[0],
opt_args.above_pred_stride[0], opt_args.left_pred_buf[0],
opt_args.left_pred_stride[0]);
av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
if (check_num_overlappable_neighbors(mbmi)) {
av1_build_prediction_by_above_preds(
cm, xd, mi_row, mi_col, opt_args.above_pred_buf, dst_width1,
dst_height1, opt_args.above_pred_stride);
av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col,
opt_args.left_pred_buf, dst_width2,
dst_height2, opt_args.left_pred_stride);
av1_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
x->mask_buf = mask2d_buf;
x->wsrc_buf = weighted_src_buf;
calc_target_weighted_pred(
cm, x, xd, mi_row, mi_col, opt_args.above_pred_buf[0],
opt_args.above_pred_stride[0], opt_args.left_pred_buf[0],
opt_args.left_pred_stride[0]);
}
#endif // CONFIG_MOTION_VAR
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment