Skip chroma RD evaluation of interpolation filter search
This patch introduces the speed feature 'skip_model_rd_uv' to skip
the RD evaluation of chroma planes during the interpolation filter
search. The chroma predictors are built later using the best
interpolation filter selected by the luma RD. This speed feature is
enabled for speed >= 3.
Encoder performance results averaged over all resolutions are as
follows:
Instruction Count BD-Rate Loss(%)
cpu Reduction(%) avg.psnr ovr.psnr ssim vmaf vmaf_neg
3 2.260 -0.0128 -0.0099 -0.0090 0.0010 -0.0064
4 0.957 0.0010 -0.0010 0.0003 -0.0214 -0.0330
5 -0.076 -0.0000 0.0042 -0.0079 -0.0103 -0.0140
6 -0.203 -0.0089 -0.0153 -0.0000 -0.0261 -0.0147
STATS_CHANGED for speed >= 3
Change-Id: I354d04a9f4cd4f37288dbcebf1ae3784ee5a9d38
diff --git a/av1/common/filter.h b/av1/common/filter.h
index fb85ab2..13d2902 100644
--- a/av1/common/filter.h
+++ b/av1/common/filter.h
@@ -52,7 +52,8 @@
enum {
INTERP_EVAL_LUMA_EVAL_CHROMA = 0,
INTERP_SKIP_LUMA_EVAL_CHROMA,
- INTERP_EVAL_INVALID,
+ INTERP_EVAL_LUMA_SKIP_CHROMA, // Valid only when skip_model_rd_uv speed
+ // feature is enabled
INTERP_SKIP_LUMA_SKIP_CHROMA,
} UENUM1BYTE(INTERP_EVAL_PLANE);
diff --git a/av1/encoder/interp_search.c b/av1/encoder/interp_search.c
index 994c78b..3ecd4a4 100644
--- a/av1/encoder/interp_search.c
+++ b/av1/encoder/interp_search.c
@@ -188,7 +188,6 @@
(void)tile_data;
- assert(skip_pred != 2);
assert((rd_stats_luma->rate >= 0) && (rd_stats->rate >= 0));
assert((rd_stats_luma->dist >= 0) && (rd_stats->dist >= 0));
assert((rd_stats_luma->sse >= 0) && (rd_stats->sse >= 0));
@@ -208,11 +207,16 @@
(skip_pred == interp_search_flags->default_interp_skip_flags)
? INTERP_SKIP_LUMA_SKIP_CHROMA
: skip_pred;
+ assert(IMPLIES(tmp_skip_pred == INTERP_EVAL_LUMA_SKIP_CHROMA,
+ cpi->sf.interp_sf.skip_model_rd_uv));
- switch (tmp_skip_pred) {
- case INTERP_EVAL_LUMA_EVAL_CHROMA:
- // skip_pred = 0: Evaluate both luma and chroma.
- // Luma MC
+ if (tmp_skip_pred == INTERP_SKIP_LUMA_SKIP_CHROMA) {
+ // Both luma and chroma evaluation is skipped
+ this_rd_stats = *rd_stats;
+ } else {
+ // Evaluate Luma
+ if (tmp_skip_pred == INTERP_EVAL_LUMA_EVAL_CHROMA ||
+ tmp_skip_pred == INTERP_EVAL_LUMA_SKIP_CHROMA) {
interp_model_rd_eval(x, cpi, bsize, orig_dst, AOM_PLANE_Y, AOM_PLANE_Y,
&this_rd_stats_luma, 0);
this_rd_stats = this_rd_stats_luma;
@@ -222,10 +226,11 @@
INT64_MAX);
PrintPredictionUnitStats(cpi, tile_data, x, &rd_stats_y, bsize);
#endif // CONFIG_COLLECT_RD_STATS == 3
- AOM_FALLTHROUGH_INTENDED;
- case INTERP_SKIP_LUMA_EVAL_CHROMA:
- // skip_pred = 1: skip luma evaluation (retain previous best luma stats)
- // and do chroma evaluation.
+ }
+
+ // Evaluate Chroma
+ if (tmp_skip_pred == INTERP_EVAL_LUMA_EVAL_CHROMA ||
+ tmp_skip_pred == INTERP_SKIP_LUMA_EVAL_CHROMA) {
for (int plane = 1; plane < num_planes; ++plane) {
int64_t tmp_rd =
RDCOST(x->rdmult, tmp_rs + this_rd_stats.rate, this_rd_stats.dist);
@@ -236,14 +241,9 @@
interp_model_rd_eval(x, cpi, bsize, orig_dst, plane, plane,
&this_rd_stats, 0);
}
- break;
- case INTERP_SKIP_LUMA_SKIP_CHROMA:
- // both luma and chroma evaluation is skipped
- this_rd_stats = *rd_stats;
- break;
- case INTERP_EVAL_INVALID:
- default: assert(0); return 0;
+ }
}
+
int64_t tmp_rd =
RDCOST(x->rdmult, tmp_rs + this_rd_stats.rate, this_rd_stats.dist);
@@ -625,6 +625,13 @@
assert(mbmi->comp_group_idx == 1);
if (*skip_hor == 0 && *skip_ver == 1) *skip_ver = 0;
}
+
+ // Configure flags to skip chroma RD evaluation when skip_model_rd_uv is
+ // enabled
+ if (cpi->sf.interp_sf.skip_model_rd_uv) {
+ *skip_hor |= INTERP_EVAL_LUMA_SKIP_CHROMA;
+ *skip_ver |= INTERP_EVAL_LUMA_SKIP_CHROMA;
+ }
}
/*!\brief AV1 interpolation filter search
@@ -649,7 +656,7 @@
* \param[in,out] switchable_rate The rate associated with using a SWITCHABLE
* filter mode.
* \param[in,out] skip_build_pred Indicates whether or not to build the inter
- * predictor. If this is 0, the inter predictor
+ * predictor. If this is 3, the inter predictor
* has already been built and thus we can avoid
* repeating computation.
* \param[in] args HandleInterModeArgs struct holding
@@ -677,6 +684,7 @@
MB_MODE_INFO *const mbmi = xd->mi[0];
const int need_search = av1_is_interp_needed(xd);
const int ref_frame = xd->mi[0]->ref_frame[0];
+ const int skip_model_rd_uv = cpi->sf.interp_sf.skip_model_rd_uv;
RD_STATS rd_stats_luma, rd_stats;
// Initialization of rd_stats structures with default values
@@ -694,7 +702,7 @@
*rd = args->interp_filter_stats[match_found_idx].rd;
x->pred_sse[ref_frame] =
args->interp_filter_stats[match_found_idx].pred_sse;
- *skip_build_pred = 0;
+ *skip_build_pred = INTERP_EVAL_LUMA_EVAL_CHROMA;
return 0;
}
@@ -716,11 +724,13 @@
PrintPredictionUnitStats(cpi, tile_data, x, &rd_stats_y, bsize);
#endif // CONFIG_COLLECT_RD_STATS == 3
// Chroma MC
- if (num_planes > 1) {
+ if (num_planes > 1 && !skip_model_rd_uv) {
interp_model_rd_eval(x, cpi, bsize, orig_dst, AOM_PLANE_U, AOM_PLANE_V,
&rd_stats, *skip_build_pred);
}
- *skip_build_pred = 1;
+ *skip_build_pred = num_planes > 1 && skip_model_rd_uv
+ ? INTERP_SKIP_LUMA_EVAL_CHROMA
+ : INTERP_SKIP_LUMA_SKIP_CHROMA;
av1_merge_rd_stats(&rd_stats, &rd_stats_luma);
@@ -757,7 +767,8 @@
// Setting 0th flag corresonds to skipping luma MC and setting 1st bt
// corresponds to skipping chroma MC skip_flag=0 corresponds to "Don't skip
// luma and chroma MC" Skip flag=1 corresponds to "Skip Luma MC only"
- // Skip_flag=2 is not a valid case
+ // Skip_flag=2 corresponds to "Skip chroma MC only". This is valid only when
+ // skip_model_rd_uv speed feature is enabled
// skip_flag=3 corresponds to "Skip both luma and chroma MC"
int skip_hor = interp_search_flags->default_interp_skip_flags;
int skip_ver = interp_search_flags->default_interp_skip_flags;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index f099bf4..3ebbd10 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -2689,10 +2689,9 @@
* to skip the transform search if the computed
* skip RD for the current mode is not better
* than the best skip_rd so far.
- * \param[in,out] skip_build_pred Indicates whether or not to build the inter
- * predictor. If this is 0, the inter predictor
- * has already been built and thus we can avoid
- * repeating computation.
+ * \param[out] skip_build_pred Indicates whether or not to build the inter
+ * predictor during/after interpolation
+ * filter search.
* \return Returns 1 if this mode is worse than one already seen and 0 if it is
* a viable candidate.
*/
@@ -2746,7 +2745,7 @@
av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
AOM_PLANE_U, num_planes - 1);
}
- *skip_build_pred = 1;
+ *skip_build_pred = INTERP_SKIP_LUMA_SKIP_CHROMA;
}
return 0;
}
@@ -3274,7 +3273,9 @@
}
}
- int skip_build_pred = 0;
+ // Flag to indicate whether to skip av1_enc_build_inter_predictor() after
+ // interpolation filter search
+ int skip_build_pred = INTERP_EVAL_LUMA_EVAL_CHROMA;
const int mi_row = xd->mi_row;
const int mi_col = xd->mi_col;
@@ -3334,12 +3335,19 @@
}
rd_stats->rate += compmode_interinter_cost;
- if (skip_build_pred != 1) {
+ if (skip_build_pred != INTERP_SKIP_LUMA_SKIP_CHROMA) {
+ // Chroma plane of COMPOUND_DIFFWTD mode shares the segment mask of luma
+ // which is stored in xd->seg_mask. Hence, the predictor is populated for
+ // all planes. This should avoid usage of incorrect segment mask when the
+ // call is made only for chroma.
+ const int skip_luma_plane =
+ skip_build_pred == INTERP_SKIP_LUMA_EVAL_CHROMA &&
+ mbmi->interinter_comp.type != COMPOUND_DIFFWTD;
+ const int start_plane = skip_luma_plane ? AOM_PLANE_U : AOM_PLANE_Y;
// Build this inter predictor if it has not been previously built
- av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize, 0,
- av1_num_planes(cm) - 1);
+ av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize,
+ start_plane, num_planes - 1);
}
-
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, motion_mode_rd_time);
#endif
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index ac031e2..4bab891 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1319,6 +1319,7 @@
sf->inter_sf.prune_single_ref = 2;
sf->interp_sf.adaptive_interp_filter_search = 2;
+ sf->interp_sf.skip_model_rd_uv = 1;
// TODO(chiyotsai@google.com): the thresholds chosen for intra hog are
// inherited directly from luma hog with some minor tweaking. Eventually we
@@ -2416,6 +2417,7 @@
interp_sf->use_interp_filter = 0;
interp_sf->skip_interp_filter_search = 0;
interp_sf->use_more_sharp_interp = 0;
+ interp_sf->skip_model_rd_uv = 0;
}
static inline void init_intra_sf(INTRA_MODE_SPEED_FEATURES *intra_sf) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 05db0a9..342049e 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1279,6 +1279,10 @@
// Bias towards sharp filter
int use_more_sharp_interp;
+
+ // Skip model RD evaluation of chroma planes during interpolation filter
+ // search.
+ int skip_model_rd_uv;
} INTERP_FILTER_SPEED_FEATURES;
typedef struct INTRA_MODE_SPEED_FEATURES {