rtc: refactor reduce_mv_pel_precision and reduce_zeromv_mvres
* The sf reduce_mv_pel_precision is refactored into two sfs:
reduce_mv_pel_precision_highmot and
reduce_mv_pel_precision_lowcomplex.
* The sf reduce_zeromv_mvres is made a part of
reduce_mv_pel_precision_lowcomplex as level 1
This change is bit-exact.
Change-Id: I35fb604b1c31100fc29104c7129357d9e139f6f6
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index df12354..ce5d67d 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -175,9 +175,10 @@
}
static INLINE int subpel_select(AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
- int_mv *mv) {
- assert(cpi->sf.rt_sf.reduce_mv_pel_precision);
- if (cpi->sf.rt_sf.reduce_mv_pel_precision == 2) {
+ int_mv *mv, MV ref_mv, FULLPEL_MV start_mv,
+ bool fullpel_performed_well) {
+ // Reduce MV precision to halfpel for higher int MV value& frame-level motion
+ if (cpi->sf.rt_sf.reduce_mv_pel_precision_highmotion == 1) {
int mv_thresh = 4;
const int is_low_resoln =
(cpi->common.width * cpi->common.height <= 320 * 240);
@@ -188,9 +189,10 @@
if (abs(mv->as_fullmv.row) >= mv_thresh ||
abs(mv->as_fullmv.col) >= mv_thresh)
return HALF_PEL;
- } else if (cpi->sf.rt_sf.reduce_mv_pel_precision == 1) {
- // Reduce MV precision for relatively static (e.g. background), low-complex
- // large areas
+ }
+ // Reduce MV precision for relatively static (e.g. background), low-complex
+ // large areas
+ if (cpi->sf.rt_sf.reduce_mv_pel_precision_lowcomplex >= 2) {
const int qband = x->qindex >> (QINDEX_BITS - 2);
assert(qband < 4);
if (x->content_state_sb.source_sad_nonrd <= kVeryLowSad &&
@@ -200,6 +202,10 @@
else if (x->source_variance < 5000)
return HALF_PEL;
}
+ } else if (cpi->sf.rt_sf.reduce_mv_pel_precision_lowcomplex >= 1) {
+ if (fullpel_performed_well && ref_mv.row == 0 && ref_mv.col == 0 &&
+ start_mv.row == 0 && start_mv.col == 0)
+ return HALF_PEL;
}
return cpi->sf.mv_sf.subpel_force_stop;
}
@@ -296,24 +302,14 @@
SUBPEL_MOTION_SEARCH_PARAMS ms_params;
av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
cost_list);
- if (sf->rt_sf.reduce_mv_pel_precision &&
- sf->mv_sf.subpel_force_stop < HALF_PEL)
- ms_params.forced_stop = subpel_select(cpi, x, bsize, tmp_mv);
const bool fullpel_performed_well =
(bsize == BLOCK_64X64 && full_var_rd * 40 < 62267 * 7) ||
(bsize == BLOCK_32X32 && full_var_rd * 8 < 42380) ||
(bsize == BLOCK_16X16 && full_var_rd * 8 < 10127);
- if (sf->rt_sf.reduce_zeromv_mvres && ref_mv.row == 0 && ref_mv.col == 0 &&
- start_mv.row == 0 && start_mv.col == 0) {
- // If both the refmv and the fullpel results show zero mv, then there is
- // high likelihood that the current block is static. So we can try to
- // reduce the mv resolution here.
- // These thresholds are the mean var rd collected from multiple encoding
- // runs.
- if (fullpel_performed_well) {
- ms_params.forced_stop = HALF_PEL;
- }
- }
+ if (sf->rt_sf.reduce_mv_pel_precision_highmotion ||
+ sf->rt_sf.reduce_mv_pel_precision_lowcomplex)
+ ms_params.forced_stop = subpel_select(cpi, x, bsize, tmp_mv, ref_mv,
+ start_mv, fullpel_performed_well);
MV subpel_start_mv = get_mv_from_fullmv(&tmp_mv->as_fullmv);
if (sf->rt_sf.use_adaptive_subpel_search &&
@@ -402,9 +398,12 @@
SUBPEL_MOTION_SEARCH_PARAMS ms_params;
av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv, NULL);
- if (cpi->sf.rt_sf.reduce_mv_pel_precision &&
- cpi->sf.mv_sf.subpel_force_stop < HALF_PEL)
- ms_params.forced_stop = subpel_select(cpi, x, bsize, &best_mv);
+ if (cpi->sf.rt_sf.reduce_mv_pel_precision_highmotion ||
+ cpi->sf.rt_sf.reduce_mv_pel_precision_lowcomplex) {
+ FULLPEL_MV start_mv = { .row = 0, .col = 0 };
+ ms_params.forced_stop =
+ subpel_select(cpi, x, bsize, &best_mv, ref_mv, start_mv, false);
+ }
MV start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
cpi->mv_search_params.find_fractional_mv_step(
xd, cm, &ms_params, start_mv, &best_mv.as_mv, &dis,
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 64b5ee0..80457a2 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1292,7 +1292,7 @@
if (speed >= 10) {
sf->rt_sf.skip_intra_pred = 2;
sf->rt_sf.hybrid_intra_pickmode = 3;
- sf->rt_sf.reduce_zeromv_mvres = true;
+ sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 1;
}
} else {
sf->rt_sf.prune_intra_mode_based_on_mv_range = 2;
@@ -1344,14 +1344,14 @@
} else {
if (speed >= 6) sf->rt_sf.skip_newmv_mode_based_on_sse = 3;
if (speed == 7) sf->rt_sf.prefer_large_partition_blocks = 0;
- if (speed >= 7) sf->rt_sf.reduce_mv_pel_precision = 1;
+ if (speed >= 7) sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 2;
if (speed >= 9) {
sf->rt_sf.sad_based_adp_altref_lag = 1;
- sf->rt_sf.reduce_mv_pel_precision = 0;
+ sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 0;
}
if (speed >= 10) {
sf->rt_sf.sad_based_adp_altref_lag = 3;
- sf->rt_sf.reduce_mv_pel_precision = 2;
+ sf->rt_sf.reduce_mv_pel_precision_highmotion = 1;
}
}
// Setting for SVC, or when the ref_frame_config control is
@@ -1369,11 +1369,11 @@
sf->mv_sf.search_method = NSTEP;
sf->mv_sf.subpel_search_method = SUBPEL_TREE;
sf->rt_sf.fullpel_search_step_param = 6;
- sf->rt_sf.reduce_mv_pel_precision = 0;
+ sf->rt_sf.reduce_mv_pel_precision_highmotion = 0;
}
if (speed >= 8) {
sf->rt_sf.disable_cdf_update_non_reference_frame = true;
- sf->rt_sf.reduce_mv_pel_precision = 2;
+ sf->rt_sf.reduce_mv_pel_precision_highmotion = 1;
if (rtc_ref->non_reference_frame) {
sf->rt_sf.nonrd_agressive_skip = 1;
sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
@@ -1411,8 +1411,8 @@
sf->rt_sf.nonrd_prune_ref_frame_search = 3;
sf->rt_sf.var_part_split_threshold_shift = 10;
sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
- sf->rt_sf.reduce_mv_pel_precision = 2;
- sf->rt_sf.reduce_zeromv_mvres = true;
+ sf->rt_sf.reduce_mv_pel_precision_highmotion = 1;
+ sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 1;
sf->rt_sf.screen_content_cdef_filter_qindex_thresh = 20;
}
if (speed >= 10) {
@@ -1720,7 +1720,7 @@
sf->rt_sf.var_part_based_on_qidx = 0;
sf->rt_sf.frame_level_mode_cost_update = true;
sf->rt_sf.check_only_zero_zeromv_on_large_blocks = true;
- sf->rt_sf.reduce_mv_pel_precision = 0;
+ sf->rt_sf.reduce_mv_pel_precision_highmotion = 0;
sf->rt_sf.use_adaptive_subpel_search = false;
// For multi-thread use case with row_mt enabled, enable top right
// dependency wait of threads at mi level.
@@ -1737,7 +1737,7 @@
sf->rt_sf.nonrd_prune_ref_frame_search = 3;
sf->rt_sf.var_part_split_threshold_shift = 10;
sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
- sf->rt_sf.reduce_mv_pel_precision = 2;
+ sf->rt_sf.reduce_mv_pel_precision_highmotion = 1;
}
}
@@ -2049,7 +2049,8 @@
rt_sf->prune_inter_modes_with_golden_ref = 0;
rt_sf->prune_inter_modes_wrt_gf_arf_based_on_sad = 0;
rt_sf->prune_inter_modes_using_temp_var = 0;
- rt_sf->reduce_mv_pel_precision = 0;
+ rt_sf->reduce_mv_pel_precision_highmotion = 0;
+ rt_sf->reduce_mv_pel_precision_lowcomplex = 0;
rt_sf->prune_intra_mode_based_on_mv_range = 0;
rt_sf->var_part_split_threshold_shift = 7;
rt_sf->gf_refresh_based_on_qp = 0;
@@ -2062,7 +2063,6 @@
rt_sf->partition_direct_merging = 0;
rt_sf->var_part_based_on_qidx = 0;
rt_sf->tx_size_level_based_on_qstep = 0;
- rt_sf->reduce_zeromv_mvres = false;
rt_sf->vbp_prune_16x16_split_using_min_max_sub_blk_var = false;
rt_sf->prune_compoundmode_with_singlecompound_var = false;
rt_sf->frame_level_mode_cost_update = false;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 64e2b6c..4cbce7d 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1505,10 +1505,15 @@
// variance wrt LAST reference.
int prune_inter_modes_using_temp_var;
- // Reduce MV precision at block level, represents various algos (0: disabled)
- // 1: switch to halfpel, fullpel based on blk SAD, source var, bsize and qp
- // 2: switch to halfpel based on integer mv size, bsize, frame-level motion
- int reduce_mv_pel_precision;
+ // Reduce MV precision to halfpel for higher int MV value & frame-level motion
+ int reduce_mv_pel_precision_highmotion;
+
+ // Reduce MV precision for low complexity blocks
+ // 0: disabled
+ // 1: Reduce the mv resolution for zero mv if the variance is low
+ // 2: Switch to halfpel, fullpel based on low block spatial-temporal
+ // complexity.
+ int reduce_mv_pel_precision_lowcomplex;
// Prune intra mode evaluation in inter frames based on mv range.
BLOCK_SIZE prune_intra_mode_based_on_mv_range;
@@ -1556,9 +1561,6 @@
// Level of aggressiveness for obtaining tx size based on qstep
int tx_size_level_based_on_qstep;
- // Reduce the mv resolution for zero mv if the variance is low.
- bool reduce_zeromv_mvres;
-
// Avoid the partitioning of a 16x16 block in variance based partitioning
// (VBP) by making use of minimum and maximum sub-block variances.
// For allintra encode, this speed feature reduces instruction count by 5.39%