Commit 3ed2cbebb7 for aom

commit 3ed2cbebb758ac7619cc94b33ffafcbcaefc6283
Author: Ihor Buhaiov <freedbrt@gmail.com>
Date:   Fri Oct 9 18:25:28 2026 +0200

    rtc: Copy inactive superblocks with whole rows

    In the nonrd path a skip segment superblock is coded as one GLOBALMV
    block with a zero motion vector, so its prediction is a plain copy of
    the reference. encode_superblock() built it block by block and plane
    by plane through av1_enc_build_inter_predictor(). On screen
    recordings with a mostly inactive map, that copy was the top encoder
    function in profiles and took 10 to 30 percent of the single thread
    encode time. Copying tall, narrow blocks is slow on memory: a 1440p
    I420 frame takes 0.62 ms in 64x64 blocks and 0.25 ms in whole rows.

    When a superblock row starts, copy each run of skip segment
    superblocks from its reference with whole rows. encode_superblock()
    then skips the prediction build for these blocks. A block that is not
    a zero motion vector copy of the same reference still builds its
    prediction over the copy. The copy is limited to 8 bit buffers and to
    unscaled references with identity global motion. Frames without a
    skip segment, like cyclic refresh frames, skip the row pass.

    The output does not change. Two 2560x1440 screen recordings, speed
    11, screen content, an active map from frame differences, Apple M3
    Pro: encoder cycles per frame drop by 6 to 18 percent with 1 thread
    and by 4 to 12 percent with 4 threads and row mt.

    Change-Id: I9f7070aed11927a0d9aae4ab851bafaaadcc3563

diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index bf706109ef..a9327150ff 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -1382,6 +1382,9 @@ typedef struct macroblock {
   //! Flag to indicate if a fixed partition should be used, only if the
   // speed feature rt_sf->use_fast_fixed_part is enabled.
   int sb_force_fixed_part;
+  //! Reference already copied into the current superblock when its row
+  // started, or NONE_FRAME. Only set for skip segment superblocks.
+  MV_REFERENCE_FRAME sb_copied_ref;
   //! SSE of the current predictor.
   unsigned int pred_sse[REF_FRAMES];
   //! Prediction for ML based partition.
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index da817888b0..3a53e6830f 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -17,6 +17,7 @@

 #include "config/aom_config.h"
 #include "config/aom_dsp_rtcd.h"
+#include "config/aom_scale_rtcd.h"
 #include "config/av1_rtcd.h"

 #include "aom_dsp/aom_dsp_common.h"
@@ -1204,6 +1205,107 @@ static inline void grade_source_content_sb(AV1_COMP *cpi, MACROBLOCK *const x,
     av1_source_content_sb(cpi, x, tile_data, mi_row, mi_col);
 }

+static uint8_t get_sb_segment_id(const AV1_COMP *cpi, int mi_row, int mi_col) {
+  const AV1_COMMON *const cm = &cpi->common;
+  const struct segmentation *const seg = &cm->seg;
+  const uint8_t *const map =
+      seg->update_map ? cpi->enc_seg.map : cm->last_frame_seg_map;
+  if (!map) return 0;
+  return get_segment_id(&cm->mi_params, map, cm->seq_params->sb_size, mi_row,
+                        mi_col);
+}
+
+// Returns true when skip segment superblocks of this frame may be copied from
+// their reference before they are coded.
+static bool can_copy_skip_sbs(const AV1_COMP *cpi) {
+  const AV1_COMMON *const cm = &cpi->common;
+  if (!cm->seg.enabled || frame_is_intra_only(cm) ||
+      !cpi->sf.rt_sf.use_nonrd_pick_mode)
+    return false;
+
+  // Segmentation without a skip segment, like cyclic refresh, has nothing to
+  // copy, so this saves the segment lookups of the whole frame.
+  for (int i = 0; i < MAX_SEGMENTS; ++i) {
+    if (segfeature_active(&cm->seg, i, SEG_LVL_SKIP)) return true;
+  }
+  return false;
+}
+
+// Returns the reference that a superblock in this segment predicts from with
+// a plain copy, or NONE_FRAME when it needs the normal prediction build.
+static MV_REFERENCE_FRAME get_skip_sb_copy_ref(const AV1_COMMON *cm,
+                                               uint8_t segment_id) {
+  const struct segmentation *const seg = &cm->seg;
+  if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) return NONE_FRAME;
+
+  // Same reference as av1_nonrd_pick_inter_mode_sb_seg_skip().
+  const MV_REFERENCE_FRAME ref =
+      segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)
+          ? (MV_REFERENCE_FRAME)get_segdata(seg, segment_id, SEG_LVL_REF_FRAME)
+          : LAST_FRAME;
+  if (ref <= INTRA_FRAME || cm->global_motion[ref].wmtype != IDENTITY)
+    return NONE_FRAME;
+
+  const YV12_BUFFER_CONFIG *const ref_buf = get_ref_frame_yv12_buf(cm, ref);
+  if (!ref_buf || (ref_buf->flags & YV12_FLAG_HIGHBITDEPTH) ||
+      av1_is_scaled(get_ref_scale_factors_const(cm, ref)))
+    return NONE_FRAME;
+  return ref;
+}
+
+// Copies the reference into the superblocks from mi_col_start to mi_col_end
+// of one superblock row, inside the frame area.
+static void copy_sb_span(const AV1_COMMON *cm, MV_REFERENCE_FRAME ref,
+                         int mi_row, int mi_col_start, int mi_col_end) {
+  const YV12_BUFFER_CONFIG *const src = get_ref_frame_yv12_buf(cm, ref);
+  YV12_BUFFER_CONFIG *const dst = &cm->cur_frame->buf;
+  const int x0 = mi_col_start * MI_SIZE;
+  const int x1 = AOMMIN(mi_col_end, cm->mi_params.mi_cols) * MI_SIZE;
+  const int y0 = mi_row * MI_SIZE;
+  const int y1 =
+      AOMMIN(mi_row + cm->seq_params->mib_size, cm->mi_params.mi_rows) *
+      MI_SIZE;
+  aom_yv12_partial_coloc_copy_y(src, dst, x0, x1, y0, y1);
+  if (av1_num_planes(cm) == 1) return;
+
+  const int ss_x = cm->seq_params->subsampling_x;
+  const int ss_y = cm->seq_params->subsampling_y;
+  aom_yv12_partial_coloc_copy_u(src, dst, x0 >> ss_x, x1 >> ss_x, y0 >> ss_y,
+                                y1 >> ss_y);
+  aom_yv12_partial_coloc_copy_v(src, dst, x0 >> ss_x, x1 >> ss_x, y0 >> ss_y,
+                                y1 >> ss_y);
+}
+
+// Fills the skip segment superblocks of a row from their reference before the
+// row is coded. Wide row copies are much faster than copying every 64x64 block
+// plane by plane, so encode_superblock() then skips their prediction.
+static void copy_skip_sbs_of_row(const AV1_COMP *cpi, const TileInfo *tile_info,
+                                 int mi_row) {
+  if (!can_copy_skip_sbs(cpi)) return;
+
+  const AV1_COMMON *const cm = &cpi->common;
+  const int mib_size = cm->seq_params->mib_size;
+  int span_start = -1;
+  MV_REFERENCE_FRAME span_ref = NONE_FRAME;
+
+  for (int mi_col = tile_info->mi_col_start;; mi_col += mib_size) {
+    const int in_tile = mi_col < tile_info->mi_col_end;
+    const MV_REFERENCE_FRAME ref =
+        in_tile
+            ? get_skip_sb_copy_ref(cm, get_sb_segment_id(cpi, mi_row, mi_col))
+            : NONE_FRAME;
+    if (span_start >= 0 && ref != span_ref) {
+      copy_sb_span(cm, span_ref, mi_row, span_start, mi_col);
+      span_start = -1;
+    }
+    if (span_start < 0 && ref != NONE_FRAME) {
+      span_start = mi_col;
+      span_ref = ref;
+    }
+    if (!in_tile) break;
+  }
+}
+
 /*!\brief Encode a superblock row by breaking it into superblocks
  *
  * \ingroup partition_search
@@ -1247,6 +1349,7 @@ static inline void encode_sb_row(AV1_COMP *cpi, ThreadData *td,
   }

   reset_thresh_freq_fact(x);
+  copy_skip_sbs_of_row(cpi, tile_info, mi_row);

   // Code each SB in the row
   for (int mi_col = tile_info->mi_col_start, sb_col_in_tile = 0;
@@ -1318,13 +1421,12 @@ static inline void encode_sb_row(AV1_COMP *cpi, ThreadData *td,
     // Get segment id and skip flag
     const struct segmentation *const seg = &cm->seg;
     int seg_skip = 0;
+    x->sb_copied_ref = NONE_FRAME;
     if (seg->enabled) {
-      const uint8_t *const map =
-          seg->update_map ? cpi->enc_seg.map : cm->last_frame_seg_map;
-      const uint8_t segment_id =
-          map ? get_segment_id(&cm->mi_params, map, sb_size, mi_row, mi_col)
-              : 0;
+      const uint8_t segment_id = get_sb_segment_id(cpi, mi_row, mi_col);
       seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
+      if (seg_skip && !frame_is_intra_only(cm) && use_nonrd_mode)
+        x->sb_copied_ref = get_skip_sb_copy_ref(cm, segment_id);
     }

     produce_gradients_for_sb(cpi, x, sb_size, mi_row, mi_col);
diff --git a/av1/encoder/partition_search.c b/av1/encoder/partition_search.c
index 373116c06b..132871c9c6 100644
--- a/av1/encoder/partition_search.c
+++ b/av1/encoder/partition_search.c
@@ -391,6 +391,17 @@ static void update_zeromv_cnt(const AV1_COMP *const cpi,
   }
 }

+// Returns true when the pixels of this block already match its prediction,
+// because its whole skip superblock was copied from the reference up front.
+static bool is_prediction_copied(const MACROBLOCK *x, const MB_MODE_INFO *mbmi,
+                                 int seg_skip) {
+  if (!seg_skip || x->sb_copied_ref == NONE_FRAME) return false;
+
+  return !has_second_ref(mbmi) && !is_interintra_pred(mbmi) &&
+         mbmi->ref_frame[0] == x->sb_copied_ref &&
+         mbmi->motion_mode == SIMPLE_TRANSLATION && mbmi->mv[0].as_int == 0;
+}
+
 static void encode_superblock(const AV1_COMP *const cpi, TileDataEnc *tile_data,
                               ThreadData *td, TokenExtra **t, RUN_TYPE dry_run,
                               BLOCK_SIZE bsize, int *rate) {
@@ -473,8 +484,10 @@ static void encode_superblock(const AV1_COMP *const cpi, TileDataEnc *tile_data,
          !seg_skip && cm->seq_params->bit_depth == AOM_BITS_8)
             ? 1
             : 0;
-    av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
-                                  start_plane, av1_num_planes(cm) - 1);
+    if (!is_prediction_copied(x, mbmi, seg_skip)) {
+      av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
+                                    start_plane, av1_num_planes(cm) - 1);
+    }
     if (mbmi->motion_mode == OBMC_CAUSAL) {
       assert(cpi->oxcf.motion_mode_cfg.enable_obmc);
       av1_build_obmc_inter_predictors_sb(cm, xd);