Commit 4df5e0bec9 for aom
commit 4df5e0bec98a220bbe28b9addf344ceeecd4bddb
Author: Deepa K G <deepa.kg@ittiam.com>
Date: Mon Mar 23 19:18:41 2026 +0530
Extend sf 'prune_comp_ref_frames' to speed 3
The speed feature 'prune_comp_ref_frames' is extended to speed 3
conservatively by disallowing pruning of important reference frame
pairs decided based on the relative distance to the current frame
and base_qindex.
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 0.7 0.0215 0.0230 0.0252 0.0369 0.0308
STATS_CHANGED for speed=3
Change-Id: I07476268df9c7075826ea956e7d9c2a8f07a11db
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 7f824a94bf..54ef94fb71 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1721,11 +1721,14 @@ static int compare_score_data_asc(const void *a, const void *b) {
// Determines whether a given reference frame is "good" based on temporal
// distance and base_qindex. The "good" reference frames are not allowed to be
-// pruned by the speed feature "prune_single_ref" frame at block level.
-static inline void setup_keep_single_ref_frame_mask(AV1_COMP *cpi) {
+// pruned by the speed feature "prune_single_ref" and "prune_comp_ref_frames"
+// at block level.
+static inline void setup_keep_ref_frame_mask(AV1_COMP *cpi) {
const int prune_single_ref = cpi->sf.inter_sf.prune_single_ref;
+ const int prune_comp_ref_frames = cpi->sf.inter_sf.prune_comp_ref_frames;
const AV1_COMMON *const cm = &cpi->common;
cpi->keep_single_ref_frame_mask = 0;
+ cpi->keep_comp_ref_frame_mask = 0;
if (frame_is_intra_only(cm)) return;
RefScoreData ref_score_data[INTER_REFS_PER_FRAME];
@@ -1758,13 +1761,35 @@ static inline void setup_keep_single_ref_frame_mask(AV1_COMP *cpi) {
// prune_single_ref = 1 => The best 5 reference frames are not pruned.
// prune_single_ref = 2 => The best 3 reference frames are not pruned.
// prune_single_ref = 3, 4 => All the 7 references are allowed to be pruned.
- static const int num_frames_to_keep_lookup[5] = { INTER_REFS_PER_FRAME, 5, 3,
- 0, 0 };
- const int num_frames_to_keep = num_frames_to_keep_lookup[prune_single_ref];
- for (int i = 0; i < num_frames_to_keep; ++i) {
+ static const int num_single_ref_to_keep_lookup[5] = { INTER_REFS_PER_FRAME, 5,
+ 3, 0, 0 };
+ assert(prune_single_ref >= 0 && prune_single_ref <= 4);
+ const int num_single_ref_to_keep =
+ num_single_ref_to_keep_lookup[prune_single_ref];
+ for (int i = 0; i < num_single_ref_to_keep; ++i) {
const int idx = ref_score_data[i].index;
cpi->keep_single_ref_frame_mask |= 1 << idx;
}
+
+ // Decide the number of reference frame pairs for which pruning via the speed
+ // feature "prune_comp_ref_frames" is disallowed.
+ // prune_comp_ref_frames = 0 => None of the allowed reference frame pairs
+ // are pruned.
+ // prune_comp_ref_frames = 1 => The best 3 reference frame pairs are not
+ // allowed to be pruned, i.e, reference frame
+ // pairs with rank (1, 2), (1, 3), (2, 3) are
+ // not pruned.
+ // prune_comp_ref_frames = 2, 3 => All the reference frame pairs are allowed
+ // to be pruned.
+ static const int num_comp_ref_to_keep_lookup[4] = { INTER_REFS_PER_FRAME, 3,
+ 0, 0 };
+ assert(prune_comp_ref_frames >= 0 && prune_comp_ref_frames <= 3);
+ const int num_comp_ref_to_keep =
+ num_comp_ref_to_keep_lookup[prune_comp_ref_frames];
+ for (int i = 0; i < num_comp_ref_to_keep; ++i) {
+ const int idx = ref_score_data[i].index;
+ cpi->keep_comp_ref_frame_mask |= 1 << idx;
+ }
}
static inline void setup_prune_ref_frame_mask(AV1_COMP *cpi) {
@@ -2336,7 +2361,7 @@ static inline void encode_frame_internal(AV1_COMP *cpi) {
setup_prune_ref_frame_mask(cpi);
// Disable certain reference frame pruning based on temporal distance and
// quality of that reference frame.
- setup_keep_single_ref_frame_mask(cpi);
+ setup_keep_ref_frame_mask(cpi);
x->txfm_search_info.txb_split_count = 0;
#if CONFIG_SPEED_STATS
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index b4e25d4c23..ec95323d63 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -3329,12 +3329,19 @@ typedef struct AV1_COMP {
int prune_ref_frame_mask;
/*!
- * Mark the reference frames which are important (based on the temporal
+ * Mark the single reference frames which are important (based on the temporal
* distance and quality) to prevent pruning the reference frame at block
* level.
*/
int keep_single_ref_frame_mask;
+ /*!
+ * Mark the compound reference frames which are important (based on the
+ * temporal distance and quality) to prevent pruning the reference frame pair
+ * at block level.
+ */
+ int keep_comp_ref_frame_mask;
+
/*!
* Loop Restoration context.
*/
diff --git a/av1/encoder/rdopt.h b/av1/encoder/rdopt.h
index dcdf3d29aa..90eb31543e 100644
--- a/av1/encoder/rdopt.h
+++ b/av1/encoder/rdopt.h
@@ -291,11 +291,18 @@ static inline int prune_ref_by_selective_ref_frame(
int closest_ref_frames = has_closest_ref_frames(
ref_frame, cpi->ref_frame_dist_info.nearest_past_ref,
cpi->ref_frame_dist_info.nearest_future_ref);
- if (closest_ref_frames == 0) {
+ const int ref_idx0 = ref_frame[0] - LAST_FRAME;
+ const int ref_idx1 = ref_frame[1] - LAST_FRAME;
+ const int keep_comp_ref_pair_mask =
+ (cpi->keep_comp_ref_frame_mask & (1 << ref_idx0)) &&
+ (cpi->keep_comp_ref_frame_mask & (1 << ref_idx1));
+
+ // Don't prune references frame pairs which are important or closest.
+ if (!(keep_comp_ref_pair_mask || closest_ref_frames)) {
// Prune reference frames which are not the closest to the current frame.
- if (sf->inter_sf.prune_comp_ref_frames >= 2) {
+ if (sf->inter_sf.prune_comp_ref_frames >= 3) {
return 1;
- } else if (sf->inter_sf.prune_comp_ref_frames == 1) {
+ } else if (sf->inter_sf.prune_comp_ref_frames >= 1) {
// Prune reference frames with non minimum pred_mv_sad.
if (has_best_pred_mv_sad(ref_frame, x) == 0) return 1;
}
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 53983af4b4..3f00173288 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -929,6 +929,12 @@ static void set_good_speed_feature_framesize_dependent(
sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL2;
}
+ if (is_480p_or_lesser) {
+ sf->inter_sf.prune_comp_ref_frames = 0;
+ } else {
+ sf->inter_sf.prune_comp_ref_frames = 1;
+ }
+
sf->inter_sf.disable_interintra_wedge_var_thresh = UINT_MAX;
}
@@ -954,9 +960,9 @@ static void set_good_speed_feature_framesize_dependent(
if (is_480p_or_lesser) sf->inter_sf.skip_newmv_in_drl = 3;
if (is_720p_or_larger) {
- sf->inter_sf.prune_comp_ref_frames = 1;
+ sf->inter_sf.prune_comp_ref_frames = 2;
} else if (is_480p_or_larger) {
- sf->inter_sf.prune_comp_ref_frames = is_boosted_arf2_bwd_type ? 0 : 1;
+ sf->inter_sf.prune_comp_ref_frames = is_boosted_arf2_bwd_type ? 0 : 2;
}
if (is_720p_or_larger)
@@ -978,7 +984,7 @@ static void set_good_speed_feature_framesize_dependent(
if (is_720p_or_larger) sf->hl_sf.recode_tolerance = 40;
sf->inter_sf.skip_newmv_in_drl = 4;
- sf->inter_sf.prune_comp_ref_frames = 1;
+ sf->inter_sf.prune_comp_ref_frames = 2;
sf->mv_sf.skip_fullpel_search_using_startmv_refmv = boosted ? 0 : 1;
if (!is_720p_or_larger) {
@@ -1012,7 +1018,7 @@ static void set_good_speed_feature_framesize_dependent(
if (speed >= 6) {
sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = 4;
sf->inter_sf.prune_nearmv_using_neighbors = PRUNE_NEARMV_LEVEL3;
- sf->inter_sf.prune_comp_ref_frames = 2;
+ sf->inter_sf.prune_comp_ref_frames = 3;
sf->inter_sf.prune_nearest_near_mv_using_refmv_weight =
(boosted || allow_screen_content_tools) ? 0 : 1;
sf->mv_sf.skip_fullpel_search_using_startmv_refmv = boosted ? 0 : 2;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 8bb6a0d7d3..1af82a89e8 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1030,12 +1030,15 @@ typedef struct INTER_MODE_SPEED_FEATURES {
// Prune compound reference frames
// 0 no pruning
- // 1 prune compound references which do not satisfy the two conditions:
+ // 1 prune based on temporal distance and pred_mv_sad. However, disallow
+ // pruning of important reference frame pairs decided based on temporal
+ // distance and quality.
+ // 2 prune compound references which do not satisfy the two conditions:
// a) The references are at a nearest distance from the current frame in
// both past and future direction.
// b) The references have minimum pred_mv_sad in both past and future
// direction.
- // 2 prune compound references except the one with nearest distance from the
+ // 3 prune compound references except the one with nearest distance from the
// current frame in both past and future direction.
int prune_comp_ref_frames;