Skip full-pel search based on start mv of prior ref_mv_idx
This CL adds a speed feature to skip full pixel search based on
the start mv of NEWMV mode evaluated prior to current ref_mv_idx.
This SF is enabled for speed 6.
Instruction Count BD-Rate Loss(%)
cpu Reduction(%) avg.psnr ovr.psnr ssim
6 0.966 0.1043 0.1049 0.1251
STATS_CHANGED
Change-Id: I160a928d9b4c9a07a5c6867cd816e4f3b98b75a8
diff --git a/av1/encoder/interp_search.h b/av1/encoder/interp_search.h
index e25d44d..8eba483 100644
--- a/av1/encoder/interp_search.h
+++ b/av1/encoder/interp_search.h
@@ -119,6 +119,17 @@
* as a previous search.
*/
INTERPOLATION_FILTER_STATS interp_filter_stats[MAX_INTERP_FILTER_STATS];
+
+ /*!
+ * Stack to store full pixel search start mv of NEWMV mode.
+ */
+ FULLPEL_MV start_mv_stack[(MAX_REF_MV_SEARCH - 1) * 2];
+
+ /*!
+ * Count of mvs in start mv stack.
+ */
+ int start_mv_cnt;
+
/*!
* Index of the last set of saved stats in the interp_filter_stats array.
*/
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index f95092e..cad4e62 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -24,7 +24,7 @@
#define RIGHT_SHIFT_MV(x) (((x) + 3 + ((x) >= 0)) >> 3)
typedef struct {
- FULLPEL_MV fmv;
+ int_mv fmv;
int weight;
} cand_mv_t;
@@ -90,8 +90,10 @@
GET_MV_RAWPEL(mv.as_mv.col) };
int unique = 1;
for (int m = 0; m < *cand_count; m++) {
- if (RIGHT_SHIFT_MV(fmv.row) == RIGHT_SHIFT_MV(cand[m].fmv.row) &&
- RIGHT_SHIFT_MV(fmv.col) == RIGHT_SHIFT_MV(cand[m].fmv.col)) {
+ if (RIGHT_SHIFT_MV(fmv.row) ==
+ RIGHT_SHIFT_MV(cand[m].fmv.as_fullmv.row) &&
+ RIGHT_SHIFT_MV(fmv.col) ==
+ RIGHT_SHIFT_MV(cand[m].fmv.as_fullmv.col)) {
unique = 0;
cand[m].weight++;
break;
@@ -99,7 +101,7 @@
}
if (unique) {
- cand[*cand_count].fmv = fmv;
+ cand[*cand_count].fmv.as_fullmv = fmv;
cand[*cand_count].weight = 1;
(*cand_count)++;
}
@@ -168,9 +170,9 @@
start_mv = get_fullmv_from_mv(&ref_mv);
// cand stores start_mv and all possible MVs in a SB.
- cand_mv_t cand[MAX_TPL_BLK_IN_SB * MAX_TPL_BLK_IN_SB + 1] = { { { 0, 0 },
- 0 } };
- cand[0].fmv = start_mv;
+ cand_mv_t cand[MAX_TPL_BLK_IN_SB * MAX_TPL_BLK_IN_SB + 1];
+ av1_zero(cand);
+ cand[0].fmv.as_fullmv = start_mv;
int cnt = 1;
int total_weight = 0;
@@ -179,6 +181,41 @@
get_mv_candidate_from_tpl(cpi, x, bsize, ref, cand, &cnt, &total_weight);
}
+ const int cand_cnt = AOMMIN(2, cnt);
+ // TODO(any): Test the speed feature for OBMC_CAUSAL mode.
+ if (cpi->sf.mv_sf.skip_fullpel_search_using_startmv &&
+ mbmi->motion_mode == SIMPLE_TRANSLATION) {
+ const int stack_size = args->start_mv_cnt;
+ for (int cand_idx = 0; cand_idx < cand_cnt; cand_idx++) {
+ int_mv *fmv_cand = &cand[cand_idx].fmv;
+ int skip_cand_mv = 0;
+
+ // Check difference between mvs in the stack and candidate mv.
+ for (int stack_idx = 0; stack_idx < stack_size; stack_idx++) {
+ FULLPEL_MV *fmv_stack = &args->start_mv_stack[stack_idx];
+ const int row = abs(fmv_stack->row - fmv_cand->as_fullmv.row);
+ const int col = abs(fmv_stack->col - fmv_cand->as_fullmv.col);
+
+ if (row <= 1 && col <= 1) {
+ skip_cand_mv = 1;
+ break;
+ }
+ }
+ if (skip_cand_mv) {
+ // Mark the candidate mv as invalid so that motion search gets skipped.
+ cand[cand_idx].fmv.as_int = INVALID_MV;
+ } else {
+ // Store start mv candidate of full-pel search in the mv stack (except
+ // last ref_mv_idx).
+ if (mbmi->ref_mv_idx != MAX_REF_MV_SEARCH - 1) {
+ args->start_mv_stack[args->start_mv_cnt] = fmv_cand->as_fullmv;
+ args->start_mv_cnt++;
+ assert(args->start_mv_cnt <= (MAX_REF_MV_SEARCH - 1) * 2);
+ }
+ }
+ }
+ }
+
// Further reduce the search range.
if (search_range < INT_MAX) {
const search_site_config *search_site_cfg =
@@ -211,13 +248,16 @@
case SIMPLE_TRANSLATION: {
// Perform a search with the top 2 candidates
int sum_weight = 0;
- for (int m = 0; m < AOMMIN(2, cnt); m++) {
- FULLPEL_MV smv = cand[m].fmv;
+ for (int m = 0; m < cand_cnt; m++) {
+ int_mv smv = cand[m].fmv;
FULLPEL_MV this_best_mv, this_second_best_mv;
- int thissme = av1_full_pixel_search(
- smv, &full_ms_params, step_param, cond_cost_list(cpi, cost_list),
- &this_best_mv, &this_second_best_mv);
+ if (smv.as_int == INVALID_MV) continue;
+
+ int thissme =
+ av1_full_pixel_search(smv.as_fullmv, &full_ms_params, step_param,
+ cond_cost_list(cpi, cost_list), &this_best_mv,
+ &this_second_best_mv);
if (thissme < bestsme) {
bestsme = thissme;
@@ -235,6 +275,7 @@
break;
default: assert(0 && "Invalid motion mode!\n");
}
+ if (best_mv->as_int == INVALID_MV) return;
if (scaled_ref_frame) {
// Swap back the original buffers for subpel motion search.
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 110ddfa..bdfd2de 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -2821,6 +2821,7 @@
save_mv[i][0].as_int = INVALID_MV;
save_mv[i][1].as_int = INVALID_MV;
}
+ args->start_mv_cnt = 0;
// Main loop of this function. This will iterate over all of the ref mvs
// in the dynamic reference list and do the following:
@@ -5686,6 +5687,8 @@
0,
interintra_modes,
{ { { 0 }, { { 0 } }, { 0 }, 0, 0, 0, 0 } },
+ { { 0, 0 } },
+ 0,
0,
-1,
-1,
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 1add4f3..5c9f1b2 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1197,6 +1197,7 @@
sf->mv_sf.simple_motion_subpel_force_stop = FULL_PEL;
sf->mv_sf.use_bsize_dependent_search_method = 1;
+ sf->mv_sf.skip_fullpel_search_using_startmv = boosted ? 0 : 1;
sf->tpl_sf.gop_length_decision_method = 3;
sf->tpl_sf.disable_filtered_key_tpl = 1;
@@ -1685,6 +1686,7 @@
mv_sf->use_downsampled_sad = 0;
mv_sf->disable_extensive_joint_motion_search = 0;
mv_sf->disable_second_mv = 0;
+ mv_sf->skip_fullpel_search_using_startmv = 0;
}
static AOM_INLINE void init_inter_sf(INTER_MODE_SPEED_FEATURES *inter_sf) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index f46a8d8..e10b91e 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -762,6 +762,9 @@
// 1: use var as the metric
// 2: disable second MV
int disable_second_mv;
+
+ // Skips full pixel search based on start mv of prior ref_mv_idx.
+ int skip_fullpel_search_using_startmv;
} MV_SPEED_FEATURES;
typedef struct INTER_MODE_SPEED_FEATURES {