Commit 9440aeedd0 for aom

commit 9440aeedd097343b763dfe1c75af72c99f4a3175
Author: Ranjit Kumar Tulabandu <ranjit.tulabandu@ittiam.com>
Date:   Thu Oct 15 20:08:28 2026 +0530

    Prune interintra search using top smooth interintra RD

    This CL tracks the top N estimated RD Costs for smooth
    interintra mode per coding unit. If the current estimated
    RD cost of smooth interintra mode exceeds the Nth-best cost,
    interintra mode is skipped. The speed feature
    skip_interintra_using_top_smooth_rd_lvl configures N=2 for
    speed 1 and N=1 for speed 2.

    Encoder performance results averaged over all resolutions are
    as follows:
       Instruction Count          BD-Rate Loss(%)
    cpu   Reduction(%)   avg.psnr  ssim    vmaf   vmaf_neg  uvq_1p5
     1        4.162       0.0686  0.0924  0.044    0.0492   0.2235
     2        2.752       0.0511  0.0589  0.0144   0.06     0.6322

    STATS_CHANGED for speed = 1,2

    Change-Id: Iddc646028e011068a9f48aa5cf46cd040e9bcb3c

diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index a9327150ff..16862d408f 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -879,6 +879,9 @@ typedef struct SetOffsetsLoc {
 //! Maximum number of estimated RD Cost records for compound average.
 #define TOP_COMP_AVG_EST_RD_COUNT 5

+//! Maximum number of estimated RD Cost records for smooth interintra.
+#define TOP_SMOOTH_INTERINTRA_RD_COUNT 2
+
 /*! \brief Encoder's parameters related to the current coding block.
  *
  * This struct contains most of the information the encoder needs to encode the
@@ -1439,6 +1442,9 @@ typedef struct macroblock {
   /*!\brief Array of best estimated RD Costs of compound average. */
   int64_t top_comp_avg_est_rd[TOP_COMP_AVG_EST_RD_COUNT];

+  /*!\brief Array of best estimated RD Costs of smooth interintra. */
+  int64_t top_smooth_interintra_rd[TOP_SMOOTH_INTERINTRA_RD_COUNT];
+
 #if CONFIG_PARTITION_SEARCH_ORDER
   /*!\brief Pointer to RD_STATS structure to be used in
    * av1_rd_partition_search().
diff --git a/av1/encoder/compound_type.c b/av1/encoder/compound_type.c
index 3bfe78f468..569cfa95c4 100644
--- a/av1/encoder/compound_type.c
+++ b/av1/encoder/compound_type.c
@@ -29,6 +29,11 @@ typedef int64_t (*pick_interinter_mask_type)(
 // speed feature.
 static const int num_comp_mode_skip_cand[3] = { 5, 4, 2 };

+// Look-up table for the number of top smooth interintra estimated RD Costs that
+// should be considered based on skip_interintra_using_top_smooth_rd_lvl
+// speed feature.
+static const int num_interintra_skip_cand[2] = { 2, 1 };
+
 // Checks if characteristics of search match
 static inline int is_comp_rd_match(const AV1_COMP *const cpi,
                                    const MACROBLOCK *const x,
@@ -602,12 +607,6 @@ static int handle_smooth_inter_intra_mode(
   }
   *best_rd = rd;
   *best_mode_rate = rmode;
-  // Return early if best rd not good enough
-  if (ref_best_rd < INT64_MAX &&
-      (*best_rd >> INTER_INTRA_RD_THRESH_SHIFT) * INTER_INTRA_RD_THRESH_SCALE >
-          ref_best_rd) {
-    return IGNORE_MODE;
-  }
   return 0;
 }

@@ -757,6 +756,24 @@ static inline void push_comp_avg_est_rd(
   }
 }

+// Store the estimated smooth interintra RD Cost in the sorted top-N array.
+static inline void push_smooth_interintra_rd(
+    int64_t *top_smooth_interintra_rd, int64_t tmp_rd,
+    int skip_interintra_using_top_smooth_rd_lvl) {
+  if (!skip_interintra_using_top_smooth_rd_lvl) return;
+
+  // Insert the RD Cost in sorted order.
+  for (int i = 0; i < TOP_SMOOTH_INTERINTRA_RD_COUNT; ++i) {
+    if (tmp_rd < top_smooth_interintra_rd[i]) {
+      for (int j = TOP_SMOOTH_INTERINTRA_RD_COUNT - 1; j > i; --j) {
+        top_smooth_interintra_rd[j] = top_smooth_interintra_rd[j - 1];
+      }
+      top_smooth_interintra_rd[i] = tmp_rd;
+      break;
+    }
+  }
+}
+
 // Avoid further evaluation of compound modes based on top estimated RD Costs of
 // compound average.
 static inline bool prune_comp_eval_using_comp_avg_est_rd(
@@ -779,6 +796,22 @@ static inline bool prune_comp_eval_using_comp_avg_est_rd(
   return false;
 }

+static inline bool prune_interintra_using_smooth_rd(
+    const int64_t *top_smooth_interintra_rd, int64_t tmp_rd,
+    int skip_interintra_using_top_smooth_rd_lvl) {
+  if (!skip_interintra_using_top_smooth_rd_lvl) return false;
+
+  const int num_top_cand =
+      num_interintra_skip_cand[skip_interintra_using_top_smooth_rd_lvl - 1];
+
+  // Do not prune if there is no valid top RD Cost for comparison.
+  if (top_smooth_interintra_rd[num_top_cand - 1] == INT64_MAX) return false;
+
+  if (tmp_rd > top_smooth_interintra_rd[num_top_cand - 1]) return true;
+
+  return false;
+}
+
 int av1_handle_inter_intra_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
                                 BLOCK_SIZE bsize, MB_MODE_INFO *mbmi,
                                 HandleInterModeArgs *args, int64_t ref_best_rd,
@@ -826,6 +859,24 @@ int av1_handle_inter_intra_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
     if (ret == IGNORE_MODE) {
       return IGNORE_MODE;
     }
+
+    push_smooth_interintra_rd(
+        x->top_smooth_interintra_rd, best_interintra_rd_nowedge,
+        cpi->sf.inter_sf.skip_interintra_using_top_smooth_rd_lvl);
+
+    if (prune_interintra_using_smooth_rd(
+            x->top_smooth_interintra_rd, best_interintra_rd_nowedge,
+            cpi->sf.inter_sf.skip_interintra_using_top_smooth_rd_lvl)) {
+      return IGNORE_MODE;
+    }
+
+    // Return early if best rd not good enough.
+    if (ref_best_rd < INT64_MAX &&
+        (best_interintra_rd_nowedge >> INTER_INTRA_RD_THRESH_SHIFT) *
+                INTER_INTRA_RD_THRESH_SCALE >
+            ref_best_rd) {
+      return IGNORE_MODE;
+    }
   }

   // Compute wedge interintra
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 169d181100..28649da880 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -522,6 +522,16 @@ static inline void init_comp_avg_est_rd(
   }
 }

+// Initialize estimated RD Cost records of smooth interintra.
+static inline void init_smooth_interintra_est_rd(
+    struct macroblock *x, int skip_interintra_using_top_smooth_rd_lvl) {
+  if (!skip_interintra_using_top_smooth_rd_lvl) return;
+
+  for (int j = 0; j < TOP_SMOOTH_INTERINTRA_RD_COUNT; ++j) {
+    x->top_smooth_interintra_rd[j] = INT64_MAX;
+  }
+}
+
 // Similar to get_horver_correlation, but also takes into account first
 // row/column, when computing horizontal/vertical correlation.
 void av1_get_horver_correlation_full_c(const int16_t *diff, int stride,
@@ -6452,6 +6462,8 @@ void av1_rd_pick_inter_mode(struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
     mode_end = SINGLE_REF_MODE_END;
   }
   init_comp_avg_est_rd(x, sf->inter_sf.skip_cmp_using_top_cmp_avg_est_rd_lvl);
+  init_smooth_interintra_est_rd(
+      x, sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl);
   for (THR_MODES midx = mode_start; midx < mode_end; ++midx) {
     // Get the actual prediction mode we are trying in this iteration
     const THR_MODES mode_enum = av1_default_mode_order[midx];
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 3760b82ebf..249c9d2234 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1206,6 +1206,7 @@ static void set_good_speed_features_framesize_independent(
     sf->inter_sf.prune_comp_using_best_single_mode_ref = 2;
     sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_DISABLED;
     sf->inter_sf.enable_comp_wedge_search_using_model_rd = 1;
+    sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl = 1;

     sf->interp_sf.use_interp_filter = 1;
     sf->interp_sf.skip_model_rd_uv = 1;
@@ -1266,6 +1267,7 @@ static void set_good_speed_features_framesize_independent(
     sf->inter_sf.inter_mode_txfm_breakout = boosted ? 0 : 1;
     sf->inter_sf.alt_ref_search_fp = 1;
     sf->inter_sf.prune_single_ref = boosted ? 1 : 2;
+    sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl = 2;

     sf->interp_sf.adaptive_interp_filter_search = 1;

@@ -2422,6 +2424,7 @@ static inline void init_inter_sf(INTER_MODE_SPEED_FEATURES *inter_sf) {
   inter_sf->skip_cmp_using_top_cmp_avg_est_rd_lvl = 0;
   inter_sf->skip_interinter_wedge_search_based_on_mse = 0;
   inter_sf->enable_comp_wedge_search_using_model_rd = 0;
+  inter_sf->skip_interintra_using_top_smooth_rd_lvl = 0;
   set_txfm_rd_gate_level(inter_sf->txfm_rd_gate_level, 0);
 }

diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 49fdd77afd..c095780a0c 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1270,6 +1270,11 @@ typedef struct INTER_MODE_SPEED_FEATURES {

   // Enable/disable model RD based fast compound wedge mask search.
   int enable_comp_wedge_search_using_model_rd;
+
+  // Avoid further evaluation of interintra modes using top estimate RD Costs of
+  // smooth interintra. Values are 0 (not used),1 - 2 with progressively
+  // increasing aggressiveness, i.e., decreasing number of top candidates.
+  int skip_interintra_using_top_smooth_rd_lvl;
 } INTER_MODE_SPEED_FEATURES;

 typedef struct INTERP_FILTER_SPEED_FEATURES {