Restrict # of neighbors in obmc blending

Only blend with the first N neighbors at each side. If the size of
one dimenstion is 8/16/32/64, the max # of neighbors to overlap
with is 1/2/3/4.
Previously we disable obmc mode if there are too many neighbors.

Change of performance in AWCY, compared to disabling obmc if
at any side there are more than 2 overlappable neighbors.
HL improved by 0.02%
LL improved by 0.09%

Change-Id: I93d9a65c6c4aabf0b4a4946e2253d3e2ef21a662
This commit is contained in:
Yue Chen 2017-03-15 18:07:04 -07:00
Родитель dfad2b1579
Коммит 1bd42be68f
3 изменённых файлов: 73 добавлений и 23 удалений

Просмотреть файл

@ -1083,14 +1083,12 @@ static INLINE int is_motion_variation_allowed_bsize(BLOCK_SIZE bsize) {
}
#if CONFIG_MOTION_VAR
// input: log2 of length, 0(4), 1(8), ...
static const int max_neighbor_obmc[6] = { 0, 1, 2, 3, 4, 4 };
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;
return !(mbmi->overlappable_neighbors[0] == 0 &&
mbmi->overlappable_neighbors[1] == 0);
}
#endif

Просмотреть файл

@ -1664,9 +1664,10 @@ void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd,
mi_step = AOMMIN(xd->n8_w, mi_size_wide[above_mbmi->sb_type]);
if (is_neighbor_overlappable(above_mbmi)) {
const BLOCK_SIZE a_bsize = above_mbmi->sb_type;
xd->mi[0]->mbmi.overlappable_neighbors[0]++;
if (!CONFIG_CB4X4 && (above_mbmi->sb_type == BLOCK_4X4 ||
above_mbmi->sb_type == BLOCK_4X8))
if (!CONFIG_CB4X4 && (a_bsize == BLOCK_4X4 || a_bsize == BLOCK_4X8))
xd->mi[0]->mbmi.overlappable_neighbors[0]++;
}
}
@ -1684,9 +1685,10 @@ void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd,
mi_step = AOMMIN(xd->n8_h, mi_size_high[left_mbmi->sb_type]);
if (is_neighbor_overlappable(left_mbmi)) {
const BLOCK_SIZE l_bsize = left_mbmi->sb_type;
xd->mi[0]->mbmi.overlappable_neighbors[1]++;
if (!CONFIG_CB4X4 && (left_mbmi->sb_type == BLOCK_4X4 ||
left_mbmi->sb_type == BLOCK_8X4))
if (!CONFIG_CB4X4 && (l_bsize == BLOCK_4X4 || l_bsize == BLOCK_8X4))
xd->mi[0]->mbmi.overlappable_neighbors[1]++;
}
}
@ -1714,6 +1716,8 @@ void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
const int overlap = num_4x4_blocks_high_lookup[bsize] * 2;
const int miw = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
const int mi_row_offset = -1;
const int neighbor_limit = max_neighbor_obmc[b_width_log2_lookup[bsize]];
int neighbor_count = 0;
assert(miw > 0);
@ -1722,9 +1726,15 @@ void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
const int mi_col_offset = i;
const MB_MODE_INFO *const above_mbmi =
&xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]->mbmi;
const int mi_step = AOMMIN(xd->n8_w, mi_size_wide[above_mbmi->sb_type]);
const BLOCK_SIZE a_bsize = above_mbmi->sb_type;
const int mi_step = AOMMIN(xd->n8_w, mi_size_wide[a_bsize]);
if (is_neighbor_overlappable(above_mbmi)) {
if (!CONFIG_CB4X4 && (a_bsize == BLOCK_4X4 || a_bsize == BLOCK_4X8))
neighbor_count += 2;
else
neighbor_count++;
if (neighbor_count > neighbor_limit) break;
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
const struct macroblockd_plane *pd = &xd->plane[plane];
const int bw = (mi_step * MI_SIZE) >> pd->subsampling_x;
@ -1755,6 +1765,8 @@ void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
const int overlap = num_4x4_blocks_wide_lookup[bsize] * 2;
const int mih = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
const int mi_col_offset = -1;
const int neighbor_limit = max_neighbor_obmc[b_height_log2_lookup[bsize]];
int neighbor_count = 0;
assert(mih > 0);
@ -1763,9 +1775,15 @@ void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
const int mi_row_offset = i;
const MB_MODE_INFO *const left_mbmi =
&xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]->mbmi;
const int mi_step = AOMMIN(xd->n8_h, mi_size_high[left_mbmi->sb_type]);
const BLOCK_SIZE l_bsize = left_mbmi->sb_type;
const int mi_step = AOMMIN(xd->n8_h, mi_size_high[l_bsize]);
if (is_neighbor_overlappable(left_mbmi)) {
if (!CONFIG_CB4X4 && (l_bsize == BLOCK_4X4 || l_bsize == BLOCK_8X4))
neighbor_count += 2;
else
neighbor_count++;
if (neighbor_count > neighbor_limit) break;
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
const struct macroblockd_plane *pd = &xd->plane[plane];
const int bw = overlap >> pd->subsampling_x;
@ -1817,6 +1835,8 @@ void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
int i, j, mi_step, ref;
const int ilimit = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
int mb_to_right_edge_base = xd->mb_to_right_edge;
const int neighbor_limit = max_neighbor_obmc[b_width_log2_lookup[bsize]];
int neighbor_count = 0;
if (mi_row <= tile->mi_row_start) return;
@ -1827,14 +1847,21 @@ void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
int mi_x, mi_y, bw, bh;
MODE_INFO *above_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
MB_MODE_INFO *above_mbmi = &above_mi->mbmi;
const BLOCK_SIZE a_bsize = above_mbmi->sb_type;
#if CONFIG_EXT_INTER
MB_MODE_INFO backup_mbmi;
#endif // CONFIG_EXT_INTER
mi_step = AOMMIN(xd->n8_w, mi_size_wide[above_mbmi->sb_type]);
mi_step = AOMMIN(xd->n8_w, mi_size_wide[a_bsize]);
if (!is_neighbor_overlappable(above_mbmi)) continue;
if (!CONFIG_CB4X4 && (a_bsize == BLOCK_4X4 || a_bsize == BLOCK_4X8))
neighbor_count += 2;
else
neighbor_count++;
if (neighbor_count > neighbor_limit) break;
#if CONFIG_EXT_INTER
backup_mbmi = *above_mbmi;
modify_neighbor_predictor_for_obmc(above_mbmi);
@ -1870,8 +1897,8 @@ void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
bh = AOMMAX((num_4x4_blocks_high_lookup[bsize] * 2) >> pd->subsampling_y,
4);
if (above_mbmi->sb_type < BLOCK_8X8 && !CONFIG_CB4X4) {
const PARTITION_TYPE bp = BLOCK_8X8 - above_mbmi->sb_type;
if (a_bsize < BLOCK_8X8 && !CONFIG_CB4X4) {
const PARTITION_TYPE bp = BLOCK_8X8 - a_bsize;
const int have_vsplit = bp != PARTITION_HORZ;
const int have_hsplit = bp != PARTITION_VERT;
const int num_4x4_w = 2 >> !have_vsplit;
@ -1945,6 +1972,8 @@ void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
int i, j, mi_step, ref;
const int ilimit = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
int mb_to_bottom_edge_base = xd->mb_to_bottom_edge;
const int neighbor_limit = max_neighbor_obmc[b_height_log2_lookup[bsize]];
int neighbor_count = 0;
if (mi_col == 0 || (mi_col - 1 < tile->mi_col_start)) return;
@ -1955,14 +1984,21 @@ void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
int mi_x, mi_y, bw, bh;
MODE_INFO *left_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
MB_MODE_INFO *left_mbmi = &left_mi->mbmi;
const BLOCK_SIZE l_bsize = left_mbmi->sb_type;
#if CONFIG_EXT_INTER
MB_MODE_INFO backup_mbmi;
#endif // CONFIG_EXT_INTER
mi_step = AOMMIN(xd->n8_h, mi_size_high[left_mbmi->sb_type]);
mi_step = AOMMIN(xd->n8_h, mi_size_high[l_bsize]);
if (!is_neighbor_overlappable(left_mbmi)) continue;
if (!CONFIG_CB4X4 && (l_bsize == BLOCK_4X4 || l_bsize == BLOCK_8X4))
neighbor_count += 2;
else
neighbor_count++;
if (neighbor_count > neighbor_limit) break;
#if CONFIG_EXT_INTER
backup_mbmi = *left_mbmi;
modify_neighbor_predictor_for_obmc(left_mbmi);
@ -1998,8 +2034,8 @@ void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
4);
bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y;
if (left_mbmi->sb_type < BLOCK_8X8 && !CONFIG_CB4X4) {
const PARTITION_TYPE bp = BLOCK_8X8 - left_mbmi->sb_type;
if (l_bsize < BLOCK_8X8 && !CONFIG_CB4X4) {
const PARTITION_TYPE bp = BLOCK_8X8 - l_bsize;
const int have_vsplit = bp != PARTITION_HORZ;
const int have_hsplit = bp != PARTITION_VERT;
const int num_4x4_w = 2 >> !have_vsplit;

Просмотреть файл

@ -12477,6 +12477,8 @@ static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
const int miw = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
const int mi_row_offset = -1;
const uint8_t *const mask1d = av1_get_obmc_mask(overlap);
const int neighbor_limit = max_neighbor_obmc[b_width_log2_lookup[bsize]];
int neighbor_count = 0;
assert(miw > 0);
@ -12485,11 +12487,17 @@ static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
const int mi_col_offset = i;
const MB_MODE_INFO *const above_mbmi =
&xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]->mbmi;
const int mi_step =
AOMMIN(xd->n8_w, num_8x8_blocks_wide_lookup[above_mbmi->sb_type]);
const BLOCK_SIZE a_bsize = above_mbmi->sb_type;
const int mi_step = AOMMIN(xd->n8_w, num_8x8_blocks_wide_lookup[a_bsize]);
const int neighbor_bw = mi_step * MI_SIZE;
if (is_neighbor_overlappable(above_mbmi)) {
if (!CONFIG_CB4X4 && (a_bsize == BLOCK_4X4 || a_bsize == BLOCK_4X8))
neighbor_count += 2;
else
neighbor_count++;
if (neighbor_count > neighbor_limit) break;
const int tmp_stride = above_stride;
int32_t *wsrc = wsrc_buf + (i * MI_SIZE);
int32_t *mask = mask_buf + (i * MI_SIZE);
@ -12543,6 +12551,8 @@ static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
const int mih = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
const int mi_col_offset = -1;
const uint8_t *const mask1d = av1_get_obmc_mask(overlap);
const int neighbor_limit = max_neighbor_obmc[b_height_log2_lookup[bsize]];
int neighbor_count = 0;
assert(mih > 0);
@ -12551,11 +12561,17 @@ static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
const int mi_row_offset = i;
const MB_MODE_INFO *const left_mbmi =
&xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]->mbmi;
const int mi_step =
AOMMIN(xd->n8_h, num_8x8_blocks_high_lookup[left_mbmi->sb_type]);
const BLOCK_SIZE l_bsize = left_mbmi->sb_type;
const int mi_step = AOMMIN(xd->n8_h, num_8x8_blocks_high_lookup[l_bsize]);
const int neighbor_bh = mi_step * MI_SIZE;
if (is_neighbor_overlappable(left_mbmi)) {
if (!CONFIG_CB4X4 && (l_bsize == BLOCK_4X4 || l_bsize == BLOCK_8X4))
neighbor_count += 2;
else
neighbor_count++;
if (neighbor_count > neighbor_limit) break;
const int tmp_stride = left_stride;
int32_t *wsrc = wsrc_buf + (i * MI_SIZE * wsrc_stride);
int32_t *mask = mask_buf + (i * MI_SIZE * mask_stride);