Commit f0160a1b1c for aom

commit f0160a1b1cd9f548e1f47308e1ede4c757a4af4d
Author: Marco Paniconi <marpan@google.com>
Date:   Wed Jan 21 20:49:54 2026 -0800

    Adjust gop decision for realtime lookahead mode

    For the realtime with lookahead encoding mode:
    constrain the gop length on scene cuts, and
    allow for disabling the arf frame for high motion
    content.

    Change-Id: I63b02871058d9286735aeda7d49fc888d23c5ae0

diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 0dec565400..06905b3f1c 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -2216,10 +2216,15 @@ static void define_gf_group_pass0(AV1_COMP *cpi, const int is_final_pass) {

   // Rare case when the look-ahead is less than the target GOP length, can't
   // generate ARF frame.
+  // Also disable ARF frame if the motion content (source_sad) is high in
+  // lookahead buffer.
+  const uint64_t thresh_sad = 8 * 64 * 64;
   if (p_rc->baseline_gf_interval > gf_cfg->lag_in_frames ||
       !is_altref_enabled(gf_cfg->lag_in_frames, gf_cfg->enable_auto_arf) ||
-      p_rc->baseline_gf_interval < rc->min_gf_interval)
+      p_rc->baseline_gf_interval < rc->min_gf_interval ||
+      rc->frame_source_sad_lag[0] > thresh_sad) {
     gf_group->max_layer_depth_allowed = 0;
+  }

   // Set up the structure of this Group-Of-Pictures (same as GF_GROUP)
   av1_gop_setup_structure(cpi, is_final_pass);
@@ -3812,6 +3817,10 @@ static void get_one_pass_rt_lag_params(AV1_COMP *cpi, unsigned int frame_flags,
     max_gop_length = AOMMIN(max_gop_length, rc->frames_to_key);
     // Go through source frames in lookahead buffer and compute source metrics:
     // scene change, frame average source sad, etc.
+    int num_frames = 1;
+    int scene_change_gop_frame_index = 0;
+    rc->frame_source_sad_lag[0] = 0;
+    rc->avg_source_sad = 0;
     for (int i = 1; i < max_gop_length; i++) {
       EncodeFrameInput frame_input;
       memset(&frame_input, 0, sizeof(frame_input));
@@ -3824,22 +3833,30 @@ static void get_one_pass_rt_lag_params(AV1_COMP *cpi, unsigned int frame_flags,
         frame_input.last_source = &e_prev->img;
         rc->high_source_sad_lag[i] = -1;
         rc->frame_source_sad_lag[i] = 0;
-        rc->avg_source_sad = 0;
         av1_rc_scene_detection_onepass_rt(cpi, &frame_input);
         rc->high_source_sad_lag[i] = rc->high_source_sad;
         rc->frame_source_sad_lag[i] = rc->frame_source_sad;
-        // Use rc->high_source_sad_lag[i] and frame_source_sad_lag[i] to
-        // adjust/adapt the gop parameters. Reset the parameters for the
-        // encoding.
-        rc->high_source_sad = 0;
-        rc->frame_source_sad = UINT64_MAX;
+        if (rc->high_source_sad_lag[i] == 1 && i > 1) {
+          // Scene change, so exit and constrain the gop to this frame.
+          scene_change_gop_frame_index = i;
+          break;
+        }
+        num_frames++;
+        rc->frame_source_sad_lag[0] += rc->frame_source_sad_lag[i];
       }
     }
+    if (scene_change_gop_frame_index > 0)
+      max_gop_length = AOMMIN(max_gop_length, scene_change_gop_frame_index);
+    rc->frame_source_sad_lag[0] = rc->frame_source_sad_lag[0] / num_frames;
     calculate_gf_length(cpi, max_gop_length, MAX_NUM_GF_INTERVALS);
     define_gf_group(cpi, frame_params, 0);
     rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
     frame_params->frame_type = gf_group->frame_type[cpi->gf_frame_index];
     av1_setup_target_rate(cpi);
+    // Reset the source_sad parameters for the encoding.
+    rc->high_source_sad = 0;
+    rc->frame_source_sad = UINT64_MAX;
+    rc->avg_source_sad = 0;
   }
 }