Commit 8986ad6a7f for aom

commit 8986ad6a7f776c6451f60558b1fae65e1c6b3019
Author: Marco Paniconi <marpan@google.com>
Date:   Tue Apr 14 20:21:00 2026 -0700

    rtc: Allow for scroll sb detection for non-screen

    For resoln > 720p non-screen mode, allow for
    superblock motion estimation that can capture scroll.

    Reduces encode size spikes for scroll video content in
    the issue below.

    Bug: 500972837
    Change-Id: I65f9f5f5907e0c064b1808dd438dff25780c4ddf

diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 85df081bb1..9ccb2da051 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -2141,7 +2141,8 @@ int av1_vector_match(const int16_t *ref, const int16_t *src, int bwl,
 unsigned int av1_int_pro_motion_estimation(
     const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
     int mi_col, const MV *ref_mv, unsigned int *y_sad_zero,
-    int me_search_size_col, int me_search_size_row, int is_var_part) {
+    int me_search_size_col, int me_search_size_row, int is_var_part,
+    int use_larger_search) {
   const AV1_COMMON *const cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mi = xd->mi[0];
@@ -2151,8 +2152,8 @@ unsigned int av1_int_pro_motion_estimation(
   const int bh = block_size_high[bsize];
   const int is_screen = cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN;
   const int full_search = is_screen;
-  const bool screen_scroll_superblock =
-      is_screen && bsize == cm->seq_params->sb_size;
+  const bool scroll_superblock =
+      use_larger_search && bsize == cm->seq_params->sb_size;
   // Keep border a multiple of 16.
   const int border = (cpi->oxcf.border_in_pixels >> 4) << 4;
   int search_size_width_left = me_search_size_col;
@@ -2160,7 +2161,7 @@ unsigned int av1_int_pro_motion_estimation(
   int search_size_height_top = me_search_size_row;
   int search_size_height_bottom = me_search_size_row;
   // Allow for larger search size for column/horizontal screen motion.
-  if (screen_scroll_superblock && is_var_part) {
+  if (scroll_superblock && is_var_part) {
     if (((mi_col << 2) - search_size_width_left) < -border)
       search_size_width_left = (mi_col << 2) + border;
     if (((mi_col << 2) + search_size_width_right + bw) > cm->width + border)
@@ -2174,7 +2175,7 @@ unsigned int av1_int_pro_motion_estimation(
     }
   }
   // Allow for larger search size for row/vertical screen motion.
-  if (screen_scroll_superblock && is_var_part) {
+  if (scroll_superblock && is_var_part) {
     if (((mi_row << 2) - search_size_height_top) < -border)
       search_size_height_top = (mi_row << 2) + border;
     if (((mi_row << 2) + search_size_height_bottom + bh) > cm->height + border)
@@ -2285,6 +2286,16 @@ unsigned int av1_int_pro_motion_estimation(
   best_sad =
       cpi->ppi->fn_ptr[bsize].sdf(src_buf, src_stride, ref_buf, ref_stride);

+  if (!is_screen && scroll_superblock) {
+    if (best_sad_col < best_sad_row && best_sad_col < (int)best_sad) {
+      best_int_mv->as_fullmv.row = 0;
+      best_sad = best_sad_col;
+    } else if (best_sad_row < best_sad_col && best_sad_row < (int)best_sad) {
+      best_int_mv->as_fullmv.col = 0;
+      best_sad = best_sad_row;
+    }
+  }
+
   // Evaluate zero MV if found MV is non-zero.
   if (best_int_mv->as_int != 0) {
     tmp_sad = cpi->ppi->fn_ptr[bsize].sdf(x->plane[0].src.buf, src_stride,
@@ -2300,7 +2311,7 @@ unsigned int av1_int_pro_motion_estimation(
     *y_sad_zero = best_sad;
   }

-  if (!screen_scroll_superblock) {
+  if (!scroll_superblock) {
     const uint8_t *const pos[4] = {
       ref_buf - ref_stride,
       ref_buf - 1,
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index d268481167..eb70c29d0e 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -246,7 +246,8 @@ int av1_vector_match(const int16_t *ref, const int16_t *src, int bwl,
 unsigned int av1_int_pro_motion_estimation(
     const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
     int mi_col, const MV *ref_mv, unsigned int *y_sad_zero,
-    int me_search_size_col, int me_search_size_row, int is_var_part);
+    int me_search_size_col, int me_search_size_row, int is_var_part,
+    int use_larger_search);

 int av1_refining_search_8p_c(const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
                              const FULLPEL_MV start_mv, FULLPEL_MV *best_mv);
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 49953d0c3e..6f6dc889c4 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -331,7 +331,7 @@ static int search_new_mv(AV1_COMP *cpi, MACROBLOCK *x,
     MV ref_mv = av1_get_ref_mv(x, 0).as_mv;
     tmp_sad = av1_int_pro_motion_estimation(
         cpi, x, bsize, mi_row, mi_col, &ref_mv, &y_sad_zero, me_search_size_col,
-        me_search_size_row, 0);
+        me_search_size_row, 0, 0);

     if (tmp_sad > x->pred_mv_sad[LAST_FRAME]) return -1;

diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index b0c1a5bd89..ea2053fa43 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -1339,16 +1339,21 @@ static void do_int_pro_motion_estimation(AV1_COMP *cpi, MACROBLOCK *x,
   AV1_COMMON *const cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mi = xd->mi[0];
-  const int is_screen = cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN;
+  const int large_search =
+      cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN ||
+      (source_sad_nonrd > kMedSad && cm->width * cm->height > 1280 * 720 &&
+       !cpi->rc.high_motion_content_screen_rtc);
+  const int max_sw =
+      (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) ? 512 : 256;
   const int increase_col_sw =
       source_sad_nonrd > kMedSad && !cpi->rc.high_motion_content_screen_rtc;
-  int me_search_size_col = is_screen
-                               ? increase_col_sw ? 512 : 96
+  int me_search_size_col = large_search
+                               ? increase_col_sw ? max_sw : 96
                                : block_size_wide[cm->seq_params->sb_size] >> 1;
-  // For screen use larger search size row motion to capture
+  // Use larger search size row motion to capture
   // vertical scroll, which can be larger motion.
-  int me_search_size_row = is_screen
-                               ? source_sad_nonrd > kMedSad ? 512 : 192
+  int me_search_size_row = large_search
+                               ? source_sad_nonrd > kMedSad ? max_sw : 192
                                : block_size_high[cm->seq_params->sb_size] >> 1;
   if (cm->width * cm->height >= 3840 * 2160) {
     me_search_size_row = me_search_size_row << 1;
@@ -1357,11 +1362,10 @@ static void do_int_pro_motion_estimation(AV1_COMP *cpi, MACROBLOCK *x,
   unsigned int y_sad_zero;
   *y_sad = av1_int_pro_motion_estimation(
       cpi, x, cm->seq_params->sb_size, mi_row, mi_col, &kZeroMv, &y_sad_zero,
-      me_search_size_col, me_search_size_row, 1);
+      me_search_size_col, me_search_size_row, 1, large_search);
   // The logic below selects whether the motion estimated in the
-  // int_pro_motion() will be used in nonrd_pickmode. Only do this
-  // for screen for now.
-  if (is_screen) {
+  // int_pro_motion() will be used in nonrd_pickmode.
+  if (large_search) {
     unsigned int thresh_sad =
         (cm->seq_params->sb_size == BLOCK_128X128) ? 50000 : 20000;
     if (*y_sad < (y_sad_zero >> 1) && *y_sad < thresh_sad) {