Commit a3bbf1482f for aom
commit a3bbf1482fe2746d9ca940bec932e807fa14e94d
Author: Cherma Rajan A <cherma.rajan@ittiam.com>
Date: Mon Sep 28 13:57:49 2026 +0530
Avoid complete TPL evaluation in shorten gf interval decision
For gop_length_decision_method = 1, complete TPL is performed
when sub-gop size is not determined by performing on fewer layer
frames (i.e, ARF, base + 1 and base + 2 frames).
To simplify the design, this patch removes the second call of TPL
from gop_length_decision_method = 1. This patch also removes
gop_length_decision_method = 0 as it was unused.
Enc. Instr. BD-Rate Loss(%)
cpu Reduction(%) avg.psnr ovr.psnr ssim vmaf vmaf_neg
0 0.312 0.0256 0.0240 0.0252 0.0420 0.0393
1 0.681 0.0267 0.0251 0.0219 0.0259 0.0292
2 0.376 0.0173 0.0144 0.0183 0.0262 0.0199
3 0.402 0.0148 0.0140 0.0096 0.0329 0.0134
4 0.416 0.0280 0.0351 0.0398 0.0504 0.0362
STATS_CHANGED for speed 0 to 4.
Change-Id: I326c238c7693f892ac5b08a5c5c03b346a530cba
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 3cf86a2c6e..d660b39dce 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -902,7 +902,7 @@ static int denoise_and_encode(AV1_COMP *const cpi, uint8_t *const dest,
if (allow_tpl) {
if (!cpi->skip_tpl_setup_stats) {
av1_tpl_preload_rc_estimate(cpi, frame_params);
- av1_tpl_setup_stats(cpi, 0, frame_params);
+ av1_tpl_setup_stats(cpi, /*approx_gop_eval=*/false, frame_params);
#if CONFIG_BITRATE_ACCURACY && !CONFIG_THREE_PASS
assert(cpi->gf_frame_index == 0);
av1_vbr_rc_update_q_index_list(&cpi->vbr_rc_info, &cpi->ppi->tpl_data,
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 42e9186f06..6ef6164aa6 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -1118,52 +1118,26 @@ static int is_shorter_gf_interval_better(
av1_encode_for_extrc(&cpi->ext_ratectrl)) {
return 0;
}
- const RATE_CONTROL *const rc = &cpi->rc;
PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int gop_length_decision_method = cpi->sf.tpl_sf.gop_length_decision_method;
- int shorten_gf_interval;
+ int shorten_gf_interval = 0;
av1_tpl_preload_rc_estimate(cpi, frame_params);
- if (gop_length_decision_method == 2) {
+ if (gop_length_decision_method == 1) {
// GF group length is decided based on GF boost and tpl stats of ARFs from
// base layer, (base+1) layer.
shorten_gf_interval =
(p_rc->gfu_boost <
p_rc->num_stats_used_for_gfu_boost * GF_MIN_BOOST * 1.4) &&
- !av1_tpl_setup_stats(cpi, 3, frame_params);
- } else {
- int do_complete_tpl = 1;
- GF_GROUP *const gf_group = &cpi->ppi->gf_group;
- int is_temporal_filter_enabled =
- (rc->frames_since_key > 0 && gf_group->arf_index > -1);
-
- if (gop_length_decision_method == 1) {
- // Check if tpl stats of ARFs from base layer, (base+1) layer,
- // (base+2) layer can decide the GF group length.
- int gop_length_eval = av1_tpl_setup_stats(cpi, 2, frame_params);
-
- if (gop_length_eval != 2) {
- do_complete_tpl = 0;
- shorten_gf_interval = !gop_length_eval;
- }
- }
-
- if (do_complete_tpl) {
- // Decide GF group length based on complete tpl stats.
- shorten_gf_interval = !av1_tpl_setup_stats(cpi, 1, frame_params);
- // Tpl stats is reused when the ARF is temporally filtered and GF
- // interval is not shortened.
- if (is_temporal_filter_enabled && !shorten_gf_interval) {
- cpi->skip_tpl_setup_stats = 1;
-#if CONFIG_BITRATE_ACCURACY && !CONFIG_THREE_PASS
- assert(cpi->gf_frame_index == 0);
- av1_vbr_rc_update_q_index_list(&cpi->vbr_rc_info, &cpi->ppi->tpl_data,
- gf_group,
- cpi->common.seq_params->bit_depth);
-#endif // CONFIG_BITRATE_ACCURACY
- }
- }
+ !av1_tpl_setup_stats(cpi, /*approx_gop_eval=*/true, frame_params);
+ } else if (gop_length_decision_method == 0) {
+ // Check if tpl stats of ARFs from base layer, (base+1) layer,
+ // (base+2) layer can decide the GF group length.
+ int gop_length_eval =
+ av1_tpl_setup_stats(cpi, /*approx_gop_eval=*/true, frame_params);
+ assert(gop_length_eval != -1);
+ shorten_gf_interval = !gop_length_eval;
}
return shorten_gf_interval;
}
@@ -4239,7 +4213,7 @@ void av1_get_second_pass_params(AV1_COMP *cpi,
}
if (max_gop_length > 16 && oxcf->algo_cfg.enable_tpl_model &&
oxcf->gf_cfg.lag_in_frames >= 32 &&
- cpi->sf.tpl_sf.gop_length_decision_method != 3) {
+ cpi->sf.tpl_sf.gop_length_decision_method != 2) {
int this_idx = rc->frames_since_key +
p_rc->gf_intervals[p_rc->cur_gf_index] -
p_rc->regions_offset - 1;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 736ea8ff5f..03e9693daf 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1463,7 +1463,7 @@ static void set_good_speed_features_framesize_independent(
sf->tpl_sf.prune_starting_mv = 3;
sf->tpl_sf.use_y_only_rate_distortion = 1;
sf->tpl_sf.subpel_force_stop = FULL_PEL;
- sf->tpl_sf.gop_length_decision_method = 2;
+ sf->tpl_sf.gop_length_decision_method = 1;
sf->tpl_sf.use_sad_for_mode_decision = 2;
sf->winner_mode_sf.dc_blk_pred_level = 2;
@@ -1497,7 +1497,7 @@ static void set_good_speed_features_framesize_independent(
sf->mv_sf.simple_motion_subpel_force_stop = FULL_PEL;
- sf->tpl_sf.gop_length_decision_method = 3;
+ sf->tpl_sf.gop_length_decision_method = 2;
sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 6 : 8;
@@ -2267,7 +2267,7 @@ static inline void init_fp_sf(FIRST_PASS_SPEED_FEATURES *fp_sf) {
}
static inline void init_tpl_sf(TPL_SPEED_FEATURES *tpl_sf) {
- tpl_sf->gop_length_decision_method = 1;
+ tpl_sf->gop_length_decision_method = 0;
tpl_sf->prune_intra_modes = 0;
tpl_sf->prune_starting_mv = 0;
tpl_sf->reduce_first_step_size = 0;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 3cf4bc26c6..49fdd77afd 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -544,12 +544,11 @@ typedef struct FIRST_PASS_SPEED_FEATURES {
/*!\cond */
typedef struct TPL_SPEED_FEATURES {
// GOP length adaptive decision.
- // If set to 0, tpl model decides whether a shorter gf interval is better.
- // If set to 1, tpl stats of ARFs from base layer, (base+1) layer and
+ // If set to 0, tpl stats of ARFs from base layer, (base+1) layer and
// (base+2) layer decide whether a shorter gf interval is better.
- // If set to 2, tpl stats of ARFs from base layer, (base+1) layer and GF boost
+ // If set to 1, tpl stats of ARFs from base layer, (base+1) layer and GF boost
// decide whether a shorter gf interval is better.
- // If set to 3, gop length adaptive decision is disabled.
+ // If set to 2, gop length adaptive decision is disabled.
int gop_length_decision_method;
// Prune the intra modes search by tpl.
// If set to 0, we will search all intra modes from DC_PRED to PAETH_PRED.
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 34cf2bfd9b..a02adc7649 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1933,23 +1933,19 @@ int av1_tpl_stats_ready(const TplParams *tpl_data, int gf_frame_index) {
return tpl_data->tpl_frame[gf_frame_index].is_valid;
}
-static inline int eval_gop_length(double *beta, int gop_eval) {
- switch (gop_eval) {
- case 1:
+static inline int eval_gop_length(double *beta,
+ int gop_length_decision_method) {
+ switch (gop_length_decision_method) {
+ case 0:
// Allow larger GOP size if the base layer ARF has higher dependency
// factor than the intermediate ARF and both ARFs have reasonably high
// dependency factors.
- return (beta[0] >= beta[1] + 0.7) && beta[0] > 3.0;
- case 2:
- if ((beta[0] >= beta[1] + 0.4) && beta[0] > 1.6)
- return 1; // Don't shorten the gf interval
- else if ((beta[0] < beta[1] + 0.1) || beta[0] <= 1.4)
+ if ((beta[0] < beta[1] + 0.1) || beta[0] <= 1.4)
return 0; // Shorten the gf interval
else
- return 2; // Cannot decide the gf interval, so redo the
- // tpl stats calculation.
- case 3: return beta[0] > 1.1;
- default: return 2;
+ return 1; // Don't shorten the gf interval
+ case 1: return beta[0] > 1.1;
+ default: assert(0 && "Invalid gop length decision method"); return -1;
}
}
@@ -1974,13 +1970,14 @@ void av1_tpl_preload_rc_estimate(AV1_COMP *cpi,
}
static inline int skip_tpl_for_frame(const GF_GROUP *gf_group, int frame_idx,
- int gop_eval, int approx_gop_eval,
+ int gop_length_decision_method,
+ int approx_gop_eval,
int reduce_num_frames) {
- // When gop_eval is set to 2, tpl stats calculation is done for ARFs from base
- // layer, (base+1) layer and (base+2) layer. When gop_eval is set to 3,
- // tpl stats calculation is limited to ARFs from base layer and (base+1)
- // layer.
- const int num_arf_layers = (gop_eval == 2) ? 3 : 2;
+ // When gop_length_decision_method is set to 0, tpl stats calculation is done
+ // for ARFs from base layer, (base+1) layer and (base+2) layer. When
+ // gop_length_decision_method is set to 1, tpl stats calculation is limited to
+ // ARFs from base layer and (base+1) layer.
+ const int num_arf_layers = (gop_length_decision_method == 0) ? 3 : 2;
const int gop_length = get_gop_length(gf_group);
if (gf_group->update_type[frame_idx] == INTNL_OVERLAY_UPDATE ||
@@ -2113,7 +2110,7 @@ static void trim_tpl_stats(struct aom_internal_error_info *error_info,
extrc_tpl_gop_stats->frame_stats_list = new_frame_stats;
}
-int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
+int av1_tpl_setup_stats(AV1_COMP *cpi, int approx_gop_eval,
const EncodeFrameParams *const frame_params) {
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, av1_tpl_setup_stats_time);
@@ -2125,7 +2122,8 @@ int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
GF_GROUP *gf_group = &cpi->ppi->gf_group;
EncodeFrameParams this_frame_params = *frame_params;
TplParams *const tpl_data = &cpi->ppi->tpl_data;
- int approx_gop_eval = (gop_eval > 1);
+ const int gop_length_decision_method =
+ cpi->sf.tpl_sf.gop_length_decision_method;
if (cpi->superres_mode != AOM_SUPERRES_NONE) {
assert(cpi->superres_mode != AOM_SUPERRES_AUTO);
@@ -2196,8 +2194,8 @@ int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
// Backward propagation from tpl_group_frames to 1.
for (int frame_idx = cpi->gf_frame_index; frame_idx < tpl_gf_group_frames;
++frame_idx) {
- if (skip_tpl_for_frame(gf_group, frame_idx, gop_eval, approx_gop_eval,
- reduce_num_frames))
+ if (skip_tpl_for_frame(gf_group, frame_idx, gop_length_decision_method,
+ approx_gop_eval, reduce_num_frames))
continue;
init_mc_flow_dispenser(cpi, frame_idx, pframe_qindex);
@@ -2240,8 +2238,8 @@ int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
for (int frame_idx = tpl_gf_group_frames - 1;
frame_idx >= cpi->gf_frame_index; --frame_idx) {
- if (skip_tpl_for_frame(gf_group, frame_idx, gop_eval, approx_gop_eval,
- reduce_num_frames))
+ if (skip_tpl_for_frame(gf_group, frame_idx, gop_length_decision_method,
+ approx_gop_eval, reduce_num_frames))
continue;
mc_flow_synthesizer(tpl_data, frame_idx, cm->mi_params.mi_rows,
@@ -2257,7 +2255,7 @@ int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
#if CONFIG_COLLECT_COMPONENT_TIMING
// Record the time if the function returns.
if (cpi->common.tiles.large_scale || gf_group->max_layer_depth_allowed == 0 ||
- !gop_eval)
+ !approx_gop_eval)
end_timing(cpi, av1_tpl_setup_stats_time);
#endif
@@ -2268,7 +2266,7 @@ int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
}
if (cpi->common.tiles.large_scale) return 0;
if (gf_group->max_layer_depth_allowed == 0) return 1;
- if (!gop_eval) return 0;
+ if (!approx_gop_eval) return 0;
assert(gf_group->arf_index >= 0);
double beta[2] = { 0.0 };
@@ -2280,7 +2278,7 @@ int av1_tpl_setup_stats(AV1_COMP *cpi, int gop_eval,
#if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, av1_tpl_setup_stats_time);
#endif
- return eval_gop_length(beta, gop_eval);
+ return eval_gop_length(beta, gop_length_decision_method);
}
void av1_tpl_rdmult_setup(AV1_COMP *cpi) {
diff --git a/av1/encoder/tpl_model.h b/av1/encoder/tpl_model.h
index 34bcfc67c7..d8b33ebebd 100644
--- a/av1/encoder/tpl_model.h
+++ b/av1/encoder/tpl_model.h
@@ -482,13 +482,14 @@ static inline bool tpl_alloc_temp_buffers(TplBuffers *tpl_tmp_buffers,
*
*\ingroup tpl_modelling
*
- * \param[in] cpi Top - level encoder instance structure
- * \param[in] gop_eval Flag if it is in the GOP length decision stage
- * \param[in] frame_params Per frame encoding parameters
+ * \param[in] cpi Top - level encoder instance structure
+ * \param[in] approx_gop_eval Flag to indicate TPL is invoked for approximate
+ * GOP size evaluation
+ * \param[in] frame_params Per frame encoding parameters
*
* \return Indicates whether or not we should use a longer GOP length.
*/
-int av1_tpl_setup_stats(struct AV1_COMP *cpi, int gop_eval,
+int av1_tpl_setup_stats(struct AV1_COMP *cpi, int approx_gop_eval,
const struct EncodeFrameParams *const frame_params);
/*!\cond */