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;