Reduce reference MV search
The VP9 style reference MV search(find_mv_refs_idx) exists in AV1,
and gather reference MVs in mv_ref_list, which is used to set
nearestmv and nearmv.
This patch switches the ref_mv search order, first call
setup_ref_mv_list() to find same reference frame MVs. If >= 2 MVs are
found, no more search is needed. Otherwise, we add MVs with different
reference frames. The purpose of doing this is to speed up the decoder.
Since we depends on setup_ref_mv_list() to find same reference frame
MVs, this change does change the bitstream. But, it wouldn't affect the
quality.
Borg test result:
avg_psnr ovr_psnr ssim
lowres: -0.013 -0.016 -0.047
Change-Id: I219b9ca097b8fa90335d5b00f6edd639886f414d
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index 63ae567..3ccccfe 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -986,11 +986,11 @@
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list, int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data,
- int16_t *mode_context, int_mv zeromv) {
+ int16_t *mode_context, int_mv zeromv,
+ uint8_t refmv_count) {
const int *ref_sign_bias = cm->ref_frame_sign_bias;
const int sb_mi_size = mi_size_wide[cm->sb_size];
- int i, refmv_count = 0;
- int different_ref_found = 0;
+ int i;
int context_counter = 0;
#if CONFIG_MFMV
@@ -1092,44 +1092,10 @@
#endif // CONFIG_INTRABC
// Keep counts for entropy encoding.
context_counter += mode_2_counter[candidate->mode];
- different_ref_found = 1;
-
- if (candidate->ref_frame[0] == ref_frame)
- ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col),
- refmv_count, mv_ref_list, bw, bh, xd, Done);
- else if (candidate->ref_frame[1] == ref_frame)
- ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col),
- refmv_count, mv_ref_list, bw, bh, xd, Done);
}
}
- // Check the rest of the neighbors in much the same way
- // as before except we don't need to keep track of sub blocks or
- // mode counts.
- for (; i < MVREF_NEIGHBOURS; ++i) {
- const POSITION *const mv_ref = &mv_ref_search[i];
- if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
- const MB_MODE_INFO *const candidate =
- !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
- ? NULL
- : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
- if (candidate == NULL) continue;
-#if CONFIG_INTRABC
- if (ref_frame == INTRA_FRAME && !is_intrabc_block(candidate)) continue;
-#endif // CONFIG_INTRABC
- if ((mi_row & (sb_mi_size - 1)) + mv_ref->row >= sb_mi_size ||
- (mi_col & (sb_mi_size - 1)) + mv_ref->col >= sb_mi_size)
- continue;
- different_ref_found = 1;
-
- if (candidate->ref_frame[0] == ref_frame)
- ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
- Done);
- else if (candidate->ref_frame[1] == ref_frame)
- ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
- Done);
- }
- }
+ if (refmv_count >= MAX_MV_REF_CANDIDATES) goto Done;
// TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
// on windows platform. The sync here is unncessary if use_perv_frame_mvs
@@ -1162,9 +1128,9 @@
// Since we couldn't find 2 mvs from the same reference frame
// go back through the neighbors and find motion vectors from
// different reference frames.
- if (different_ref_found
+ if (
#if CONFIG_INTRABC
- && ref_frame != INTRA_FRAME
+ ref_frame != INTRA_FRAME
#endif // CONFIG_INTRABC
) {
for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
@@ -1256,15 +1222,15 @@
zeromv[0].as_int = zeromv[1].as_int = 0;
}
- if (ref_frame <= ALTREF_FRAME)
- find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, mi_row, mi_col, sync,
- data, compound_mode_context, zeromv[0]);
-
setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
#if USE_CUR_GM_REFMV
zeromv,
#endif // USE_CUR_GM_REFMV
mi_row, mi_col, mode_context);
+
+ if (ref_frame <= ALTREF_FRAME)
+ find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, mi_row, mi_col, sync,
+ data, compound_mode_context, zeromv[0], *ref_mv_count);
}
void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,