Commit 26f9a4186d for aom
commit 26f9a4186d20b699bfc84fccc2892147c8f7b4c9
Author: Lin Zheng <linzhen@google.com>
Date: Mon Mar 16 17:36:44 2026 +0000
Refactor the initialization of accumulate_stats_stage
Remove the accumulate_stats_stage from p_rc structure, and pass it as an
input of function calc_frame_boost().
Change-Id: I0fb385f4379c7b02bca9cecf5aa34ccbab77525e
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c
index f10bf93730..01c3e764cd 100644
--- a/av1/encoder/gop_structure.c
+++ b/av1/encoder/gop_structure.c
@@ -67,7 +67,7 @@ static inline void set_params_for_leaf_frames(
GF_GROUP *const gf_group, int *cur_frame_idx, int *frame_ind,
int *parallel_frame_count, int max_parallel_frames,
int do_frame_parallel_encode, int *first_frame_index, int *cur_disp_index,
- int layer_depth, int start, int end) {
+ int layer_depth, int start, int end, const bool scale_max_boost) {
gf_group->update_type[*frame_ind] = LF_UPDATE;
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
@@ -78,7 +78,7 @@ static inline void set_params_for_leaf_frames(
gf_group->display_idx[*frame_ind] = (*cur_disp_index);
gf_group->arf_boost[*frame_ind] =
av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, start,
- end - start, 0, NULL, NULL, 0);
+ end - start, 0, NULL, NULL, 0, scale_max_boost);
++(*cur_disp_index);
// Set the level of parallelism for the LF_UPDATE frame.
@@ -120,7 +120,7 @@ static inline void set_params_for_internal_arfs(
int *parallel_frame_count, int max_parallel_frames,
int do_frame_parallel_encode, int *first_frame_index, int depth_thr,
int *cur_disp_idx, int layer_depth, int arf_src_offset, int offset,
- int f_frames, int b_frames) {
+ int f_frames, int b_frames, const bool scale_max_boost) {
gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
gf_group->arf_src_offset[*frame_ind] = arf_src_offset;
gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
@@ -131,7 +131,7 @@ static inline void set_params_for_internal_arfs(
(*cur_disp_idx) + gf_group->arf_src_offset[*frame_ind];
gf_group->arf_boost[*frame_ind] =
av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, offset,
- f_frames, b_frames, NULL, NULL, 0);
+ f_frames, b_frames, NULL, NULL, 0, scale_max_boost);
if (do_frame_parallel_encode) {
if (depth_thr != INT_MAX) {
@@ -179,7 +179,8 @@ static void set_multi_layer_params_for_fp(
RATE_CONTROL *rc, FRAME_INFO *frame_info, int start, int end,
int *cur_frame_idx, int *frame_ind, int *parallel_frame_count,
int max_parallel_frames, int do_frame_parallel_encode,
- int *first_frame_index, int depth_thr, int *cur_disp_idx, int layer_depth) {
+ int *first_frame_index, int depth_thr, int *cur_disp_idx, int layer_depth,
+ const bool scale_max_boost) {
const int num_frames_to_process = end - start;
// Either we are at the last level of the pyramid, or we don't have enough
@@ -188,11 +189,11 @@ static void set_multi_layer_params_for_fp(
num_frames_to_process < 3) {
// Leaf nodes.
while (start < end) {
- set_params_for_leaf_frames(twopass, twopass_frame, p_rc, frame_info,
- gf_group, cur_frame_idx, frame_ind,
- parallel_frame_count, max_parallel_frames,
- do_frame_parallel_encode, first_frame_index,
- cur_disp_idx, layer_depth, start, end);
+ set_params_for_leaf_frames(
+ twopass, twopass_frame, p_rc, frame_info, gf_group, cur_frame_idx,
+ frame_ind, parallel_frame_count, max_parallel_frames,
+ do_frame_parallel_encode, first_frame_index, cur_disp_idx,
+ layer_depth, start, end, scale_max_boost);
++start;
}
} else {
@@ -204,7 +205,7 @@ static void set_multi_layer_params_for_fp(
twopass, twopass_frame, p_rc, frame_info, gf_group, cur_frame_idx,
frame_ind, parallel_frame_count, max_parallel_frames,
do_frame_parallel_encode, first_frame_index, INT_MAX, cur_disp_idx,
- layer_depth, arf_src_offset, m, end - m, m - start);
+ layer_depth, arf_src_offset, m, end - m, m - start, scale_max_boost);
// If encode reordering is enabled, configure the multi-layers accordingly
// and return. For e.g., the encode order for gf-interval 16 after
@@ -226,7 +227,7 @@ static void set_multi_layer_params_for_fp(
frame_ind, parallel_frame_count, max_parallel_frames,
do_frame_parallel_encode, first_frame_index, depth_thr,
cur_disp_idx, layer_depth + 1, arf_src_offsets[i], offset[i],
- f_frames[i], b_frames[i]);
+ f_frames[i], b_frames[i], scale_max_boost);
}
// Initialize the start and end indices to configure LF_UPDATE frames.
@@ -242,7 +243,8 @@ static void set_multi_layer_params_for_fp(
twopass, twopass_frame, gf_group, p_rc, rc, frame_info,
start_idx[i], end_idx[i], cur_frame_idx, frame_ind,
parallel_frame_count, max_parallel_frames, do_frame_parallel_encode,
- first_frame_index, depth_thr, cur_disp_idx, layer_depth + 2);
+ first_frame_index, depth_thr, cur_disp_idx, layer_depth + 2,
+ scale_max_boost);
if (layer_depth_for_intnl_overlay[i] != INVALID_IDX)
set_params_for_intnl_overlay_frames(
gf_group, cur_frame_idx, frame_ind, first_frame_index,
@@ -256,7 +258,7 @@ static void set_multi_layer_params_for_fp(
twopass, twopass_frame, gf_group, p_rc, rc, frame_info, start, m,
cur_frame_idx, frame_ind, parallel_frame_count, max_parallel_frames,
do_frame_parallel_encode, first_frame_index, depth_thr, cur_disp_idx,
- layer_depth + 1);
+ layer_depth + 1, scale_max_boost);
// Overlay for internal ARF.
set_params_for_intnl_overlay_frames(gf_group, cur_frame_idx, frame_ind,
@@ -268,7 +270,7 @@ static void set_multi_layer_params_for_fp(
twopass, twopass_frame, gf_group, p_rc, rc, frame_info, m + 1, end,
cur_frame_idx, frame_ind, parallel_frame_count, max_parallel_frames,
do_frame_parallel_encode, first_frame_index, depth_thr, cur_disp_idx,
- layer_depth + 1);
+ layer_depth + 1, scale_max_boost);
}
}
@@ -381,7 +383,7 @@ static inline void set_multi_layer_params_for_gf14(
int *cur_frame_idx, int *frame_ind, int *count_arf_frames,
int *doh_gf_index_map, int *parallel_frame_count, int *first_frame_index,
int *cur_disp_index, int gf_interval, int layer_depth,
- int max_parallel_frames) {
+ int max_parallel_frames, const bool scale_max_boost) {
assert(layer_depth == 2);
assert(gf_group->max_layer_depth_allowed >= 4);
int layer, node_start, node_end = 0;
@@ -418,7 +420,7 @@ static inline void set_multi_layer_params_for_gf14(
set_params_for_leaf_frames(
twopass, twopass_frame, p_rc, frame_info, gf_group, cur_frame_idx,
frame_ind, parallel_frame_count, max_parallel_frames, 1,
- first_frame_index, cur_disp_index, layer, 0, 0);
+ first_frame_index, cur_disp_index, layer, 0, 0, scale_max_boost);
} else {
// In order to obtain the layer depths of INTNL_OVERLAY_UPDATE frames, get
// the gf index of corresponding INTNL_ARF_UPDATE frames.
@@ -438,7 +440,8 @@ static void set_multi_layer_params(
RATE_CONTROL *rc, FRAME_INFO *frame_info, int start, int end,
int *cur_frame_idx, int *frame_ind, int *parallel_frame_count,
int max_parallel_frames, int do_frame_parallel_encode,
- int *first_frame_index, int *cur_disp_idx, int layer_depth) {
+ int *first_frame_index, int *cur_disp_idx, int layer_depth,
+ const bool scale_max_boost) {
const int num_frames_to_process = end - start;
// Either we are at the last level of the pyramid, or we don't have enough
@@ -454,7 +457,7 @@ static void set_multi_layer_params(
gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS;
gf_group->arf_boost[*frame_ind] =
av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, start,
- end - start, 0, NULL, NULL, 0);
+ end - start, 0, NULL, NULL, 0, scale_max_boost);
gf_group->frame_type[*frame_ind] = INTER_FRAME;
gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
gf_group->max_layer_depth =
@@ -500,7 +503,7 @@ static void set_multi_layer_params(
// Get the boost factor for intermediate ARF frames.
gf_group->arf_boost[*frame_ind] =
av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, m, end - m,
- m - start, NULL, NULL, 0);
+ m - start, NULL, NULL, 0, scale_max_boost);
++(*frame_ind);
// Frames displayed before this internal ARF.
@@ -508,7 +511,7 @@ static void set_multi_layer_params(
frame_info, start, m, cur_frame_idx, frame_ind,
parallel_frame_count, max_parallel_frames,
do_frame_parallel_encode, first_frame_index,
- cur_disp_idx, layer_depth + 1);
+ cur_disp_idx, layer_depth + 1, scale_max_boost);
// Overlay for internal ARF.
gf_group->update_type[*frame_ind] = INTNL_OVERLAY_UPDATE;
@@ -530,7 +533,7 @@ static void set_multi_layer_params(
frame_info, m + 1, end, cur_frame_idx, frame_ind,
parallel_frame_count, max_parallel_frames,
do_frame_parallel_encode, first_frame_index,
- cur_disp_idx, layer_depth + 1);
+ cur_disp_idx, layer_depth + 1, scale_max_boost);
}
}
@@ -667,6 +670,8 @@ static int construct_multi_layer_gf_structure(
gf_group->max_layer_depth_allowed >= 4);
int first_frame_index = cur_frame_index;
+ const bool scale_max_boost = (cpi->oxcf.mode != REALTIME);
+
if (do_frame_parallel_encode) {
// construct_multi_layer_gf_structure() takes the input parameter
// 'gf_interval' as p_rc->baseline_gf_interval - 1 . Below code computes the
@@ -710,7 +715,7 @@ static int construct_multi_layer_gf_structure(
arf_frame_stats, &cur_frame_index, &frame_index, &count_arf_frames,
doh_gf_index_map, ¶llel_frame_count, &first_frame_index,
&cur_disp_index, actual_gf_length, use_altref + 1,
- cpi->ppi->num_fp_contexts);
+ cpi->ppi->num_fp_contexts, scale_max_boost);
// Set gf_group->skip_frame_refresh.
for (int i = 0; i < actual_gf_length; i++) {
@@ -738,7 +743,7 @@ static int construct_multi_layer_gf_structure(
cur_frame_index, gf_interval, &cur_frame_index, &frame_index,
¶llel_frame_count, cpi->ppi->num_fp_contexts,
do_frame_parallel_encode, &first_frame_index, depth_thr,
- &cur_disp_index, use_altref + 1);
+ &cur_disp_index, use_altref + 1, scale_max_boost);
}
is_multi_layer_configured = 1;
}
@@ -750,7 +755,7 @@ static int construct_multi_layer_gf_structure(
&cur_frame_index, &frame_index,
¶llel_frame_count, cpi->ppi->num_fp_contexts,
do_frame_parallel_encode, &first_frame_index,
- &cur_disp_index, use_altref + 1);
+ &cur_disp_index, use_altref + 1, scale_max_boost);
if (use_altref) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index ae0b28b4b4..0c448cf7e5 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -583,10 +583,15 @@ static double baseline_err_per_mb(const FRAME_INFO *frame_info) {
}
}
+// scale_max_boost = (cpi->oxcf.mode != REALTIME) in most cases as it was only
+// tuned in non-rtc cases. The only exception is when we derive
+// gfu_boost_average, we pass scale_max_boost = false for better coding
+// efficiency.
static double calc_frame_boost(const PRIMARY_RATE_CONTROL *p_rc,
const FRAME_INFO *frame_info,
const FIRSTPASS_STATS *this_frame,
- double this_frame_mv_in_out, double max_boost) {
+ double this_frame_mv_in_out, double max_boost,
+ const bool scale_max_boost) {
double frame_boost;
const double lq = av1_convert_qindex_to_q(p_rc->avg_frame_qindex[INTER_FRAME],
frame_info->bit_depth);
@@ -604,8 +609,7 @@ static double calc_frame_boost(const PRIMARY_RATE_CONTROL *p_rc,
// (zoom in). The range for this_frame_mv_in_out is -1.0 to +1.0.
if (this_frame_mv_in_out > 0.0) {
frame_boost += frame_boost * (this_frame_mv_in_out * 2.0);
- if (!p_rc->accumulate_stats_stage)
- max_boost += max_boost * (this_frame_mv_in_out * 2.0);
+ if (scale_max_boost) max_boost += max_boost * (this_frame_mv_in_out * 2.0);
}
// In the extreme case the boost is halved.
else {
@@ -677,7 +681,7 @@ int av1_calc_arf_boost(const TWO_PASS *twopass,
const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info,
int offset, int f_frames, int b_frames,
int *num_fpstats_used, int *num_fpstats_required,
- int project_gfu_boost) {
+ int project_gfu_boost, const bool scale_max_boost) {
int i;
GF_GROUP_STATS gf_stats;
init_gf_stats(&gf_stats);
@@ -710,10 +714,10 @@ int av1_calc_arf_boost(const TWO_PASS *twopass,
: gf_stats.decay_accumulator;
}
- boost_score +=
- gf_stats.decay_accumulator *
- calc_frame_boost(p_rc, frame_info, this_frame,
- gf_stats.this_frame_mv_in_out, GF_MAX_BOOST);
+ boost_score += gf_stats.decay_accumulator *
+ calc_frame_boost(p_rc, frame_info, this_frame,
+ gf_stats.this_frame_mv_in_out, GF_MAX_BOOST,
+ scale_max_boost);
if (num_fpstats_used) (*num_fpstats_used)++;
}
@@ -746,10 +750,10 @@ int av1_calc_arf_boost(const TWO_PASS *twopass,
: gf_stats.decay_accumulator;
}
- boost_score +=
- gf_stats.decay_accumulator *
- calc_frame_boost(p_rc, frame_info, this_frame,
- gf_stats.this_frame_mv_in_out, GF_MAX_BOOST);
+ boost_score += gf_stats.decay_accumulator *
+ calc_frame_boost(p_rc, frame_info, this_frame,
+ gf_stats.this_frame_mv_in_out, GF_MAX_BOOST,
+ scale_max_boost);
if (num_fpstats_used) (*num_fpstats_used)++;
}
arf_boost += (int)boost_score;
@@ -2420,7 +2424,6 @@ static void set_gop_bits_boost(AV1_COMP *cpi, int i, int is_intra_only,
int gfu_boost_sum = 0;
int gfu_count = 0;
int accumulate_i = 0;
- p_rc->accumulate_stats_stage = true;
if (rc->frames_since_key == 0) {
for (int k = 0; k < MAX_NUM_GF_INTERVALS; k++) {
if (p_rc->gf_intervals[k] == 0) {
@@ -2446,11 +2449,14 @@ static void set_gop_bits_boost(AV1_COMP *cpi, int i, int is_intra_only,
}
}
reset_fpf_position(&cpi->twopass_frame, cpi->twopass_frame.stats_in);
- // Calculate the boost for alt ref.
+ // Calculate the boost for alt ref. Note that we pass the
+ // scale_max_boost=false to derive gfu_boost_average, which can help
+ // the coding efficiency for some clips with global motion.
int gfu_boost_tmp = av1_calc_arf_boost(
twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset,
forward_frames, ext_len_new, &p_rc->num_stats_used_for_gfu_boost,
- &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled);
+ &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled,
+ /*scale_max_boost=*/false);
gfu_boost_sum += gfu_boost_tmp;
}
gfu_count++;
@@ -2462,9 +2468,9 @@ static void set_gop_bits_boost(AV1_COMP *cpi, int i, int is_intra_only,
cpi->twopass_frame = stats_in_backup;
}
- p_rc->accumulate_stats_stage = (cpi->oxcf.mode == REALTIME);
-
int ext_len = i - is_intra_only;
+ const bool scale_max_boost = (cpi->oxcf.mode != REALTIME);
+
if (use_alt_ref) {
const int forward_frames = (rc->frames_to_key - i >= ext_len)
? ext_len
@@ -2474,15 +2480,17 @@ static void set_gop_bits_boost(AV1_COMP *cpi, int i, int is_intra_only,
p_rc->gfu_boost = av1_calc_arf_boost(
twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset,
forward_frames, ext_len, &p_rc->num_stats_used_for_gfu_boost,
- &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled);
+ &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled,
+ scale_max_boost);
} else {
reset_fpf_position(&cpi->twopass_frame, start_pos);
- p_rc->gfu_boost = AOMMIN(
- MAX_GF_BOOST,
- av1_calc_arf_boost(
- twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset, ext_len,
- 0, &p_rc->num_stats_used_for_gfu_boost,
- &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled));
+ p_rc->gfu_boost =
+ AOMMIN(MAX_GF_BOOST,
+ av1_calc_arf_boost(twopass, &cpi->twopass_frame, p_rc,
+ frame_info, alt_offset, ext_len, 0,
+ &p_rc->num_stats_used_for_gfu_boost,
+ &p_rc->num_stats_required_for_gfu_boost,
+ cpi->ppi->lap_enabled, scale_max_boost));
}
#define LAST_ALR_BOOST_FACTOR 0.2f
diff --git a/av1/encoder/pass2_strategy.h b/av1/encoder/pass2_strategy.h
index 1ca39ec7b8..be14d8eefb 100644
--- a/av1/encoder/pass2_strategy.h
+++ b/av1/encoder/pass2_strategy.h
@@ -109,7 +109,7 @@ int av1_calc_arf_boost(const TWO_PASS *twopass,
const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info,
int offset, int f_frames, int b_frames,
int *num_fpstats_used, int *num_fpstats_required,
- int project_gfu_boost);
+ int project_gfu_boost, const bool scale_max_boost);
void av1_gop_bit_allocation(const AV1_COMP *cpi, RATE_CONTROL *const rc,
GF_GROUP *gf_group, int is_key_frame, int use_arf,
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index e83b7c0e18..deea12d775 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -333,11 +333,6 @@ typedef struct {
*/
int gfu_boost_average;
- /*!
- * Indicate if it is gfu_boost accumulation stage
- */
- bool accumulate_stats_stage;
-
/*!
* Stores the determined gf group lengths for a set of gf groups
*/
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index da81e041e3..daab015fff 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -1365,10 +1365,10 @@ static void tf_setup_filtering_buffer(AV1_COMP *cpi,
num_before = AOMMIN(is_forward_keyframe ? num_frames / 2 : 0, max_before);
num_after = AOMMIN(num_frames - 1, max_after);
} else {
- int gfu_boost = av1_calc_arf_boost(&cpi->ppi->twopass, &cpi->twopass_frame,
- &cpi->ppi->p_rc, &cpi->frame_info,
- filter_frame_lookahead_idx, max_before,
- max_after, NULL, NULL, 0);
+ int gfu_boost = av1_calc_arf_boost(
+ &cpi->ppi->twopass, &cpi->twopass_frame, &cpi->ppi->p_rc,
+ &cpi->frame_info, filter_frame_lookahead_idx, max_before, max_after,
+ NULL, NULL, 0, cpi->oxcf.mode != REALTIME);
num_frames = AOMMIN(num_frames, gfu_boost / 150);
num_frames += !(num_frames & 1); // Make the number odd.