Commit 461ead5ace for aom

commit 461ead5aceb3b801e282b0fffd134a547c2ed987
Author: Jerome Jiang <jianj@google.com>
Date:   Tue Jan 13 12:48:55 2026 -0500

    ext rc: override ref frame map with ext rc

    Bug: 461792087
    Change-Id: Ic6807f410e4b5dcc26eaa597336652910543be31

diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 17c8ebb151..22b907cb4e 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -995,6 +995,16 @@ void av1_get_ref_frames(RefFrameMapPair ref_frame_map_pairs[REF_FRAMES],
   // Initialize reference frame mappings.
   for (int i = 0; i < REF_FRAMES; ++i) remapped_ref_idx[i] = INVALID_IDX;

+  if (cpi->ppi->gf_group.use_ext_ref_frame_map[gf_index]) {
+    for (int rf = LAST_FRAME; rf < REF_FRAMES; ++rf) {
+      if (cpi->ppi->gf_group.ref_frame_list[gf_index][rf] != INVALID_IDX) {
+        remapped_ref_idx[rf - LAST_FRAME] =
+            (int)cpi->ppi->gf_group.ref_frame_list[gf_index][rf];
+      }
+    }
+    return;
+  }
+
 #if !CONFIG_REALTIME_ONLY
   if (cpi->use_ducky_encode &&
       cpi->ducky_encode_info.frame_info.gop_mode == DUCKY_ENCODE_GOP_MODE_RCL) {
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index d4b6ef17c6..639eda748a 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -397,6 +397,9 @@ typedef struct GF_GROUP {
   int skip_frame_as_ref[MAX_STATIC_GF_GROUP_LENGTH];
   // Indicates whether a switch frame is due.
   bool is_sframe_due;
+  // Indicates whether the ref frame map is overridden by the external rate
+  // control.
+  int use_ext_ref_frame_map[MAX_STATIC_GF_GROUP_LENGTH];
   /*!\endcond */
 } GF_GROUP;
 /*!\cond */
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c
index 079b8ea2e1..81647520d8 100644
--- a/av1/encoder/gop_structure.c
+++ b/av1/encoder/gop_structure.c
@@ -870,6 +870,18 @@ static void construct_gop_structure_from_rc(
         gop_frame_rc->is_key_frame ? KEY_FRAME : INTER_FRAME;
     gf_group->refbuf_state[frame_index] =
         gop_frame_rc->is_key_frame ? REFBUF_RESET : REFBUF_UPDATE;
+    // Always override the ref frame map from external RC.
+    gf_group->use_ext_ref_frame_map[frame_index] = 1;
+    for (int i = 0; i < REF_FRAMES; ++i) {
+      gf_group->ref_frame_list[frame_index][i] = INVALID_IDX;
+    }
+    for (int i = 0; i < AOM_RC_MAX_REF_FRAMES; ++i) {
+      int ref_name = gop_frame_rc->ref_frame_list.name[i];
+      int buf_idx = gop_frame_rc->ref_frame_list.index[i];
+      if (ref_name >= LAST_FRAME && ref_name <= ALTREF_FRAME) {
+        gf_group->ref_frame_list[frame_index][ref_name] = (int8_t)buf_idx;
+      }
+    }
   }
 }

diff --git a/test/ext_ratectrl_test.cc b/test/ext_ratectrl_test.cc
index 5f950d3e61..c7a413e508 100644
--- a/test/ext_ratectrl_test.cc
+++ b/test/ext_ratectrl_test.cc
@@ -68,33 +68,63 @@ aom_rc_status_t mock_get_gop_decision(aom_rc_model_t /*ratectrl_model*/,
                                       aom_rc_gop_decision_t *gop_decision) {
   gop_decision->gop_frame_count = kGopFrameCount;
   gop_decision->gop_frame_list = gop_frame_list;
+  static const aom_rc_ref_name_t ref_names[] = {
+    AOM_RC_LAST_FRAME,   AOM_RC_LAST2_FRAME,  AOM_RC_LAST3_FRAME,
+    AOM_RC_GOLDEN_FRAME, AOM_RC_BWDREF_FRAME, AOM_RC_ALTREF2_FRAME,
+    AOM_RC_ALTREF_FRAME
+  };
   for (int i = 0; i < kGopFrameCount; ++i) {
     auto current_gop_frame = &gop_decision->gop_frame_list[i];
     current_gop_frame->coding_idx = i;
+    // Set all references to buffer 0 (KF) by default.
+    for (int j = 0; j < 7; ++j) {
+      current_gop_frame->ref_frame_list.name[j] = ref_names[j];
+      current_gop_frame->ref_frame_list.index[j] = 0;
+    }
+    current_gop_frame->update_ref_idx = -1;
+    current_gop_frame->primary_ref_frame.name = AOM_RC_INVALID_REF_FRAME;
+    current_gop_frame->primary_ref_frame.index = -1;
+
     if (i == 0) {
       // Key frame
       current_gop_frame->is_key_frame = true;
       current_gop_frame->update_type = AOM_RC_KF_UPDATE;
       current_gop_frame->layer_depth = 0;
       current_gop_frame->display_idx = 0;
-    } else if (i == 1) {
-      // ALTREF
-      current_gop_frame->is_key_frame = false;
-      current_gop_frame->update_type = AOM_RC_ARF_UPDATE;
-      current_gop_frame->layer_depth = 1;
-      current_gop_frame->display_idx = 4;
-    } else if (i == 5) {
-      // Overlay frame
-      current_gop_frame->is_key_frame = false;
-      current_gop_frame->update_type = AOM_RC_OVERLAY_UPDATE;
-      current_gop_frame->layer_depth = AOM_RC_MAX_ARF_LAYERS - 1;
-      current_gop_frame->display_idx = 4;
+      current_gop_frame->update_ref_idx = 0;
     } else {
-      // Leaf frames
       current_gop_frame->is_key_frame = false;
-      current_gop_frame->update_type = AOM_RC_LF_UPDATE;
-      current_gop_frame->layer_depth = AOM_RC_MAX_ARF_LAYERS - 1;
-      current_gop_frame->display_idx = i - 2;  // Key and ARF in the front
+      if (i == 1) {
+        // ALTREF
+        current_gop_frame->update_type = AOM_RC_ARF_UPDATE;
+        current_gop_frame->layer_depth = 1;
+        current_gop_frame->display_idx = 4;
+        current_gop_frame->update_ref_idx = 1;
+      } else if (i == 5) {
+        // Overlay frame
+        current_gop_frame->is_key_frame = false;
+        current_gop_frame->update_type = AOM_RC_OVERLAY_UPDATE;
+        current_gop_frame->layer_depth = AOM_RC_MAX_ARF_LAYERS - 1;
+        current_gop_frame->display_idx = 4;
+      } else {
+        // Leaf frames
+        current_gop_frame->is_key_frame = false;
+        current_gop_frame->update_type = AOM_RC_LF_UPDATE;
+        current_gop_frame->layer_depth = AOM_RC_MAX_ARF_LAYERS - 1;
+        current_gop_frame->display_idx = i - 2;  // Key and ARF in the front
+        current_gop_frame->update_ref_idx = 2;
+      }
+      // For leaf and overlay frames, set ALTREF to buffer 1.
+      if (i >= 2) {
+        current_gop_frame->ref_frame_list.index[AOM_RC_ALTREF_FRAME] = 1;
+      }
+      // For leaf frames after the first leaf, use buffer 2 as LAST.
+      if (i > 2 && i < 5) {
+        current_gop_frame->ref_frame_list.index[AOM_RC_LAST_FRAME] = 2;
+      }
+
+      current_gop_frame->primary_ref_frame.name = AOM_RC_LAST_FRAME;
+      current_gop_frame->primary_ref_frame.index = (i > 2 && i < 5) ? 2 : 0;
     }
   }
   gop_decision->global_order_idx_offset = 0;