Update q_index_list only when gf_frame_index = 0
This will make the q indices for the entire gop more consistent.
Therefore largely reduce the performance hit.
We also store the q indices to vbr_rc_info->q_index_list to
avoid conflicts with the existing code.
Change-Id: Ibbb08dd3a1f9c540d8f0e20be221060747a191f9
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 3da9959..0891c70 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -924,7 +924,7 @@
#endif
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
AV1_COMMON *const cm = &cpi->common;
- const GF_GROUP *const gf_group = &cpi->ppi->gf_group;
+ GF_GROUP *const gf_group = &cpi->ppi->gf_group;
FRAME_UPDATE_TYPE update_type =
get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
@@ -1034,19 +1034,9 @@
av1_tpl_preload_rc_estimate(cpi, frame_params);
av1_tpl_setup_stats(cpi, 0, frame_params, frame_input);
#if CONFIG_BITRATE_ACCURACY
- if (gf_group->update_type[cpi->gf_frame_index] == ARF_UPDATE) {
- double gop_bit_budget = cpi->vbr_rc_info.gop_bit_budget;
- if (gf_group->update_type[0] == KF_UPDATE && cpi->gf_frame_index != 0) {
- gop_bit_budget -= cpi->vbr_rc_info.keyframe_bitrate;
- }
- // Use the gop_bit_budget to determine gf_group->q_val.
- const double arf_qstep_ratio =
- av1_tpl_get_qstep_ratio(&cpi->ppi->tpl_data, cpi->gf_frame_index);
- av1_q_mode_estimate_base_q(
- &cpi->ppi->gf_group, cpi->ppi->tpl_data.txfm_stats_list,
- gop_bit_budget, cpi->gf_frame_index, arf_qstep_ratio,
- cm->seq_params->bit_depth, cpi->vbr_rc_info.scale_factor);
- }
+ av1_vbr_rc_update_q_index_list(&cpi->vbr_rc_info, &cpi->ppi->tpl_data,
+ gf_group, cpi->gf_frame_index,
+ cm->seq_params->bit_depth);
#endif
}
}
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index d3df7590..e78c85a 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2574,7 +2574,7 @@
#endif // CONFIG_RD_COMMAND
#if CONFIG_BITRATE_ACCURACY
- q = (int)cpi->ppi->gf_group.q_val[cpi->gf_frame_index];
+ q = cpi->vbr_rc_info.q_index_list[cpi->gf_frame_index];
#endif
av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
q_cfg->enable_chroma_deltaq);
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index 31ee7fc..7adb91e 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -189,7 +189,7 @@
int max_layer_depth;
int max_layer_depth_allowed;
// This is currently only populated for AOM_Q mode
- unsigned char q_val[MAX_STATIC_GF_GROUP_LENGTH];
+ int q_val[MAX_STATIC_GF_GROUP_LENGTH];
int bit_allocation[MAX_STATIC_GF_GROUP_LENGTH];
// The frame coding type - inter/intra frame
FRAME_TYPE frame_type[MAX_STATIC_GF_GROUP_LENGTH];
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index c32830b..a96b292 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -1062,20 +1062,9 @@
if (is_temporal_filter_enabled && !shorten_gf_interval) {
cpi->skip_tpl_setup_stats = 1;
#if CONFIG_BITRATE_ACCURACY
- if (gf_group->update_type[cpi->gf_frame_index] == ARF_UPDATE) {
- double gop_bit_budget = cpi->vbr_rc_info.gop_bit_budget;
- if (gf_group->update_type[0] == KF_UPDATE &&
- cpi->gf_frame_index != 0) {
- gop_bit_budget -= cpi->vbr_rc_info.keyframe_bitrate;
- }
- // Use the gop_bit_budget to determine gf_group->q_val.
- const double arf_qstep_ratio =
- av1_tpl_get_qstep_ratio(&cpi->ppi->tpl_data, cpi->gf_frame_index);
- av1_q_mode_estimate_base_q(
- &cpi->ppi->gf_group, cpi->ppi->tpl_data.txfm_stats_list,
- gop_bit_budget, cpi->gf_frame_index, arf_qstep_ratio,
- cpi->common.seq_params->bit_depth, cpi->vbr_rc_info.scale_factor);
- }
+ av1_vbr_rc_update_q_index_list(&cpi->vbr_rc_info, &cpi->ppi->tpl_data,
+ gf_group, cpi->gf_frame_index,
+ cpi->common.seq_params->bit_depth);
#endif // CONFIG_BITRATE_ACCURACY
}
}
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index ac82abe..667c0bd 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -3072,12 +3072,13 @@
void av1_q_mode_compute_gop_q_indices(int gf_frame_index, int base_q_index,
double arf_qstep_ratio,
aom_bit_depth_t bit_depth,
- struct GF_GROUP *gf_group) {
+ const struct GF_GROUP *gf_group,
+ int *q_index_list) {
const int arf_q = av1_get_q_index_from_qstep_ratio(
base_q_index, arf_qstep_ratio, bit_depth);
for (int gf_index = gf_frame_index; gf_index < gf_group->size; ++gf_index) {
const int height = gf_group_pyramid_level(gf_group, gf_index);
- gf_group->q_val[gf_index] = av1_q_mode_get_q_index(
+ q_index_list[gf_index] = av1_q_mode_get_q_index(
base_q_index, gf_group->update_type[gf_index], height, arf_q);
}
}
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 583bdf2..4474a75 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -710,18 +710,21 @@
#if !CONFIG_REALTIME_ONLY
/*!\brief Compute the q_indices for the entire GOP.
*
- * Intended to be used only with AOM_Q mode.
- *
* \param[in] gf_frame_index Index of the current frame
* \param[in] base_q_index Base q index
* \param[in] arf_qstep_ratio The quantize step ratio between arf q
- * index and base q index \param[in] bit_depth Bit depth
- * \param[out] gf_group Pointer to the GOP
+ * index and base q index
+ * \param[in] bit_depth Bit depth
+ * \param[in] gf_group Pointer to the GOP
+ * \param[out] q_index_list An array to store output gop q indices.
+ * the array size should be equal or
+ * greater than gf_group.size()
*/
void av1_q_mode_compute_gop_q_indices(int gf_frame_index, int base_q_index,
double arf_qstep_ratio,
aom_bit_depth_t bit_depth,
- struct GF_GROUP *gf_group);
+ const struct GF_GROUP *gf_group,
+ int *q_index_list);
#endif // !CONFIG_REALTIME_ONLY
/*!\brief Compute the q_indices for a single frame.
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 0ca74ac..31bfc77 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1883,8 +1883,7 @@
return est_rate;
}
-double av1_estimate_gop_bitrate(const unsigned char *q_index_list,
- const int frame_count,
+double av1_estimate_gop_bitrate(const int *q_index_list, const int frame_count,
const TplTxfmStats *stats_list) {
double gop_bitrate = 0;
for (int frame_index = 0; frame_index < frame_count; frame_index++) {
@@ -1961,30 +1960,31 @@
/*
* Estimate the optimal base q index for a GOP.
*/
-int av1_q_mode_estimate_base_q(GF_GROUP *gf_group,
+int av1_q_mode_estimate_base_q(const GF_GROUP *gf_group,
const TplTxfmStats *txfm_stats_list,
double bit_budget, int gf_frame_index,
double arf_qstep_ratio,
- aom_bit_depth_t bit_depth, double scale_factor) {
+ aom_bit_depth_t bit_depth, double scale_factor,
+ int *q_index_list) {
int q_max = 255; // Maximum q value.
int q_min = 0; // Minimum q value.
int q = (q_max + q_min) / 2;
av1_q_mode_compute_gop_q_indices(gf_frame_index, q_max, arf_qstep_ratio,
- bit_depth, gf_group);
- double q_max_estimate = av1_estimate_gop_bitrate(
- gf_group->q_val, gf_group->size, txfm_stats_list);
+ bit_depth, gf_group, q_index_list);
+ double q_max_estimate =
+ av1_estimate_gop_bitrate(q_index_list, gf_group->size, txfm_stats_list);
av1_q_mode_compute_gop_q_indices(gf_frame_index, q_min, arf_qstep_ratio,
- bit_depth, gf_group);
- double q_min_estimate = av1_estimate_gop_bitrate(
- gf_group->q_val, gf_group->size, txfm_stats_list);
+ bit_depth, gf_group, q_index_list);
+ double q_min_estimate =
+ av1_estimate_gop_bitrate(q_index_list, gf_group->size, txfm_stats_list);
while (true) {
av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
- bit_depth, gf_group);
+ bit_depth, gf_group, q_index_list);
- double estimate = av1_estimate_gop_bitrate(gf_group->q_val, gf_group->size,
- txfm_stats_list);
+ double estimate =
+ av1_estimate_gop_bitrate(q_index_list, gf_group->size, txfm_stats_list);
estimate *= scale_factor;
@@ -2010,9 +2010,9 @@
}
}
- // Before returning, update the gop q_val.
+ // Before returning, update the q_index_list.
av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
- bit_depth, gf_group);
+ bit_depth, gf_group, q_index_list);
return q;
}
@@ -2061,3 +2061,26 @@
const double qstep_ratio = av1_tpl_get_qstep_ratio(tpl_data, gf_frame_index);
return av1_get_q_index_from_qstep_ratio(leaf_qindex, qstep_ratio, bit_depth);
}
+
+#if CONFIG_BITRATE_ACCURACY
+void av1_vbr_rc_update_q_index_list(VBR_RATECTRL_INFO *vbr_rc_info,
+ const TplParams *tpl_data,
+ const GF_GROUP *gf_group,
+ int gf_frame_index,
+ aom_bit_depth_t bit_depth) {
+ // We always update q_index_list when gf_frame_index is zero.
+ // This will make the q indices for the entire gop more consistent
+ if (gf_frame_index == 0) {
+ double gop_bit_budget = vbr_rc_info->gop_bit_budget;
+ // Use the gop_bit_budget to determine q_index_list.
+ const double arf_qstep_ratio =
+ av1_tpl_get_qstep_ratio(tpl_data, gf_frame_index);
+ // We update the q indices in vbr_rc_info in vbr_rc_info->q_index_list
+ // rather than gf_group->q_val to avoid conflicts with the existing code.
+ av1_q_mode_estimate_base_q(gf_group, tpl_data->txfm_stats_list,
+ gop_bit_budget, gf_frame_index, arf_qstep_ratio,
+ bit_depth, vbr_rc_info->scale_factor,
+ vbr_rc_info->q_index_list);
+ }
+}
+#endif // CONFIG_BITRATE_ACCURACY
diff --git a/av1/encoder/tpl_model.h b/av1/encoder/tpl_model.h
index fec81cf..bc319b8 100644
--- a/av1/encoder/tpl_model.h
+++ b/av1/encoder/tpl_model.h
@@ -239,6 +239,8 @@
int gop_showframe_count; // The number of show frames in the current gop
double gop_bit_budget; // The bitbudget for the current gop
double scale_factor; // Scale factor to improve the budget estimation
+ int q_index_list[MAX_LENGTH_TPL_FRAME_STATS]; // q indices for the current
+ // GOP
} VBR_RATECTRL_INFO;
static INLINE void vbr_rc_init(VBR_RATECTRL_INFO *vbr_rc_info,
@@ -388,8 +390,7 @@
* \param[in] stats array of transform stats, one per frame
*
*/
-double av1_estimate_gop_bitrate(const unsigned char *q_index_list,
- const int frame_count,
+double av1_estimate_gop_bitrate(const int *q_index_list, const int frame_count,
const TplTxfmStats *stats);
/*
@@ -492,14 +493,19 @@
* \param[in] arf_qstep_ratio ARF q step ratio
* \param[in] bit_depth bit depth
* \param[in] scale_factor Used to improve budget estimation
+ * \param[out] q_index_list An array to store output gop
+ * q indices. The array size should
+ * be equal or greater than
+ * gf_group.size().
*
* \return Returns the optimal base q index to use.
*/
-int av1_q_mode_estimate_base_q(struct GF_GROUP *gf_group,
+int av1_q_mode_estimate_base_q(const struct GF_GROUP *gf_group,
const TplTxfmStats *txfm_stats_list,
double bit_budget, int gf_frame_index,
double arf_qstep_ratio,
- aom_bit_depth_t bit_depth, double scale_factor);
+ aom_bit_depth_t bit_depth, double scale_factor,
+ int *q_index_list);
/*!\brief Get current frame's q_index from tpl stats and leaf_qindex
*
@@ -537,6 +543,23 @@
int av1_get_q_index_from_qstep_ratio(int leaf_qindex, double qstep_ratio,
aom_bit_depth_t bit_depth);
+#if CONFIG_BITRATE_ACCURACY
+/*!\brief Update q_index_list in vbr_rc_info based on tpl stats
+ *
+ * \param[out] vbr_rc_info Rate control info for BITRATE_ACCURACY
+ * experiment
+ * \param[in] tpl_data TPL struct
+ * \param[in] gf_group GOP struct
+ * \param[in] gf_frame_index current frame index in the GOP
+ * \param[in] bit_depth bit depth
+ */
+void av1_vbr_rc_update_q_index_list(VBR_RATECTRL_INFO *vbr_rc_info,
+ const TplParams *tpl_data,
+ const struct GF_GROUP *gf_group,
+ int gf_frame_index,
+ aom_bit_depth_t bit_depth);
+#endif // CONFIG_BITRATE_ACCURACY
+
/*!\endcond */
#ifdef __cplusplus
} // extern "C"
diff --git a/test/ratectrl_test.cc b/test/ratectrl_test.cc
index ffb6b9f..7110db6 100644
--- a/test/ratectrl_test.cc
+++ b/test/ratectrl_test.cc
@@ -63,7 +63,8 @@
base_q_index, arf_qstep_ratio, bit_depth);
av1_q_mode_compute_gop_q_indices(gf_frame_index, base_q_index,
- arf_qstep_ratio, bit_depth, &gf_group);
+ arf_qstep_ratio, bit_depth, &gf_group,
+ gf_group.q_val);
for (int i = 0; i < gf_group.size; i++) {
if (layer_depth[i] == 1) {
diff --git a/test/tpl_model_test.cc b/test/tpl_model_test.cc
index bd6f4cc..4d70d80 100644
--- a/test/tpl_model_test.cc
+++ b/test/tpl_model_test.cc
@@ -155,7 +155,7 @@
*/
const int txfm_size = 256; // 16x16
const int frame_count = 16;
- unsigned char q_index_list[16];
+ int q_index_list[16];
TplTxfmStats stats_list[16];
for (int i = 0; i < frame_count; i++) {
@@ -241,7 +241,7 @@
// Initial estimate when q = 255
av1_q_mode_compute_gop_q_indices(gf_frame_index, 255, arf_qstep_ratio,
- bit_depth, &gf_group);
+ bit_depth, &gf_group, gf_group.q_val);
double curr_estimate =
av1_estimate_gop_bitrate(gf_group.q_val, gf_group.size, stats_list);
double best_estimate_budget_distance = fabs(curr_estimate - bit_budget);
@@ -250,7 +250,7 @@
// Start at q = 254 because we already have an estimate for q = 255.
for (int q = 254; q >= 0; q--) {
av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
- bit_depth, &gf_group);
+ bit_depth, &gf_group, gf_group.q_val);
curr_estimate =
av1_estimate_gop_bitrate(gf_group.q_val, gf_group.size, stats_list);
double curr_estimate_budget_distance = fabs(curr_estimate - bit_budget);
@@ -291,8 +291,7 @@
// Binary search method to find the optimal q.
const int result = av1_q_mode_estimate_base_q(
&gf_group, stats_list, bit_budget, gf_frame_index, arf_qstep_ratio,
- bit_depth, scale_factor);
-
+ bit_depth, scale_factor, gf_group.q_val);
const int test_result =
find_gop_q_iterative(bit_budget, arf_qstep_ratio, gf_group, stats_list,
gf_frame_index, bit_depth);