Add bitrate accuracy estimation.
The function av1_q_mode_estimate_base_q accepts a GF_GROUP and a
bit budget, and outputs a base q index to use for encoding.
Edited the interface of av1_q_mode_compute_gop_q_indices to
accept an arf_q.
BUG=aomedia:3045
Change-Id: I072cf4e84d5d353d42dd73e3cc875010e72da208
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 2c6d2a0..2218927 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -3135,12 +3135,7 @@
* Intended to be used only with AOM_Q mode.
*/
void av1_q_mode_compute_gop_q_indices(int gf_frame_index, int base_q_index,
- int gfu_boost, int bit_depth,
- double arf_boost_factor,
- struct GF_GROUP *gf_group) {
- int arf_q =
- av1_get_arf_q_index(base_q_index, gfu_boost, bit_depth, arf_boost_factor);
-
+ int arf_q, struct GF_GROUP *gf_group) {
for (int gf_index = gf_frame_index; gf_index < gf_group->size; ++gf_index) {
int height = gf_group_pyramid_level(gf_group, gf_index);
gf_group->q_val[gf_index] = av1_q_mode_get_q_index(
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index c88d5c0..a25d7f5 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -707,15 +707,12 @@
*
* \param[in] gf_frame_index Index of the current frame
* \param[in] base_q_index Base q index
- * \param[in] gfu_boost GFU boost
* \param[in] bit_depth Bit depth
- * \param[in] arf_boost_factor ARF boost factor
+ * \param[in] arf_q ARF q index
* \param[out] gf_group Pointer to the GOP
*/
void av1_q_mode_compute_gop_q_indices(int gf_frame_index, int base_q_index,
- int gfu_boost, int bit_depth,
- double arf_boost_factor,
- struct GF_GROUP *gf_group);
+ int arf_q, struct GF_GROUP *gf_group);
/*!\brief Compute the q_indices for a single frame.
*
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index ac5812e..ab7423f 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1958,3 +1958,52 @@
fclose(fptr);
}
#endif // CONFIG_RD_COMMAND
+
+/*
+ * Estimate the optimal base q index for a GOP.
+ */
+int av1_q_mode_estimate_base_q(GF_GROUP *gf_group,
+ const TplTxfmStats *txfm_stats_list,
+ double bit_budget, int gf_frame_index,
+ int arf_q) {
+ 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_q, gf_group);
+ double q_max_estimate = av1_estimate_gop_bitrate(
+ gf_group->q_val, gf_group->size, txfm_stats_list);
+ av1_q_mode_compute_gop_q_indices(gf_frame_index, q_min, arf_q, gf_group);
+ double q_min_estimate = av1_estimate_gop_bitrate(
+ gf_group->q_val, gf_group->size, txfm_stats_list);
+
+ while (true) {
+ av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_q, gf_group);
+
+ double estimate = av1_estimate_gop_bitrate(gf_group->q_val, gf_group->size,
+ txfm_stats_list);
+
+ // We want to find the lowest q that satisfies the bit budget constraint.
+ // A binary search narrows the result down to two values: q_min and q_max.
+ if (q_max <= q_min + 1 || estimate == bit_budget) {
+ // Pick the estimate that lands closest to the budget.
+ if (fabs(q_max_estimate - bit_budget) <
+ fabs(q_min_estimate - bit_budget)) {
+ q = q_max;
+ } else {
+ q = q_min;
+ }
+ break;
+ } else if (estimate > bit_budget) {
+ q_min = q;
+ q_min_estimate = estimate;
+ q = (q_max + q_min) / 2;
+ } else if (estimate < bit_budget) {
+ q_max = q;
+ q_max_estimate = estimate;
+ q = (q_max + q_min) / 2;
+ }
+ }
+
+ return q;
+}
diff --git a/av1/encoder/tpl_model.h b/av1/encoder/tpl_model.h
index c2fdb40..197bf4e 100644
--- a/av1/encoder/tpl_model.h
+++ b/av1/encoder/tpl_model.h
@@ -23,6 +23,7 @@
struct AV1_SEQ_CODING_TOOLS;
struct EncodeFrameParams;
struct EncodeFrameInput;
+struct GF_GROUP;
#include "config/aom_config.h"
@@ -441,6 +442,26 @@
int av1_get_overlap_area(int row_a, int col_a, int row_b, int col_b, int width,
int height);
+/*!\brief Estimate the optimal base q index for a GOP.
+ *
+ * This function picks q based on a chosen bit rate. It
+ * estimates the bit rate using the starting base q, then uses
+ * a binary search to find q to achieve the specified bit rate.
+ *
+ * \param[in] gf_group GOP structure
+ * \param[in] stats Transform stats struct
+ * \param[in] bit_budget The specified bit budget to achieve
+ * \param[in] gf_frame_index current frame in the GOP
+ * \param[in] bit_depth Bit depth
+ * \param[in] arf_q ARF q index
+ *
+ * \return Returns the optimal base q index to use.
+ */
+int av1_q_mode_estimate_base_q(struct GF_GROUP *gf_group,
+ const TplTxfmStats *txfm_stats_list,
+ double bit_budget, int gf_frame_index,
+ int arf_q);
+
/*!\endcond */
#ifdef __cplusplus
} // extern "C"
diff --git a/test/ratectrl_test.cc b/test/ratectrl_test.cc
index 7dfc947..735deee 100644
--- a/test/ratectrl_test.cc
+++ b/test/ratectrl_test.cc
@@ -41,9 +41,7 @@
TEST(RatectrlTest, QModeComputeGOPQIndicesTest) {
int base_q_index = 36;
- int gfu_boost = 500;
- int bit_depth = AOM_BITS_8;
- double arf_boost_factor = 0.20;
+ int arf_q = 36;
int gf_frame_index = 0;
GF_GROUP gf_group = {};
@@ -57,11 +55,15 @@
gf_group.update_type[i] = update_type[i];
}
- av1_q_mode_compute_gop_q_indices(gf_frame_index, base_q_index, gfu_boost,
- bit_depth, arf_boost_factor, &gf_group);
+ av1_q_mode_compute_gop_q_indices(gf_frame_index, base_q_index, arf_q,
+ &gf_group);
for (int i = 0; i < gf_group.size; i++) {
- EXPECT_LE(gf_group.q_val[i], base_q_index);
+ if (arf_q == base_q_index) {
+ EXPECT_EQ(gf_group.q_val[i], base_q_index);
+ } else {
+ EXPECT_LE(gf_group.q_val[i], base_q_index);
+ }
}
}