ref: d6f2ae2c127b4dd61fd7bedf725152138d02b20e
parent: 3ec043a795cdf4dfa4cf31a9a0c82cbeef52c866
author: angiebird <angiebird@google.com>
date: Fri Aug 7 14:12:18 EDT 2020
Avoid division by zero for rate q_step model Change-Id: Ic5709b79131a3969fcb2a0eb3f53994f788b5cc9
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4228,8 +4228,9 @@
// The model predicts bits as follows.
// target_bits = bias - ratio * log2(q_step)
// Given the target_bits, we compute the q_step as follows.
- const double q_step =
- pow(2.0, (rq_model->bias - target_bits) / rq_model->ratio);
+ double q_step;
+ assert(rq_model->ratio > 0);
+ q_step = pow(2.0, (rq_model->bias - target_bits) / rq_model->ratio);
// TODO(angiebird): Make this function support highbitdepth.
return vp9_convert_q_to_qindex(q_step, VPX_BITS_8);
}
@@ -4248,7 +4249,9 @@
}
static double get_bits_percent_diff(int target_bits, int actual_bits) {
- double diff = abs(target_bits - actual_bits) * 1. / target_bits;
+ double diff;
+ target_bits = VPXMAX(target_bits, 1);
+ diff = abs(target_bits - actual_bits) * 1. / target_bits;
return diff * 100;
}
@@ -4295,17 +4298,32 @@
static void rq_model_update(const RATE_QINDEX_HISTORY *rq_history,
int target_bits, RATE_QSTEP_MODEL *rq_model) {
const int recode_count = rq_history->recode_count;
+ const double delta = 0.00001;
if (recode_count >= 2) {
- // Fit the ratio and bias of rq_model based on last two recode histories.
- const double s1 = vp9_convert_qindex_to_q(
- rq_history->q_index_history[recode_count - 2], VPX_BITS_8);
- const double s2 = vp9_convert_qindex_to_q(
- rq_history->q_index_history[recode_count - 1], VPX_BITS_8);
- const double r1 = rq_history->rate_history[recode_count - 2];
- const double r2 = rq_history->rate_history[recode_count - 1];
- rq_model->ratio = (r2 - r1) / (log2(s1) - log2(s2));
- rq_model->bias = r1 + (rq_model->ratio) * log2(s1);
- rq_model->ready = 1;
+ const int q_index1 = rq_history->q_index_history[recode_count - 2];
+ const int q_index2 = rq_history->q_index_history[recode_count - 1];
+ const int r1 = rq_history->rate_history[recode_count - 2];
+ const int r2 = rq_history->rate_history[recode_count - 1];
+ int valid = 0;
+ // lower q_index should yield higher bit rate
+ if (q_index1 < q_index2) {
+ valid = r1 > r2;
+ } else if (q_index1 > q_index2) {
+ valid = r1 < r2;
+ }
+ // Only update the model when the q_index and rate behave normally.
+ if (valid) {
+ // Fit the ratio and bias of rq_model based on last two recode histories.
+ const double s1 = vp9_convert_qindex_to_q(q_index1, VPX_BITS_8);
+ const double s2 = vp9_convert_qindex_to_q(q_index2, VPX_BITS_8);
+ if (fabs(log2(s1) - log2(s2)) > delta) {
+ rq_model->ratio = (r2 - r1) / (log2(s1) - log2(s2));
+ rq_model->bias = r1 + (rq_model->ratio) * log2(s1);
+ if (rq_model->ratio > delta && rq_model->bias > delta) {
+ rq_model->ready = 1;
+ }
+ }
+ }
} else if (recode_count == 1) {
if (rq_model->ready) {
// Update the ratio only when the initial model exists and we only have
@@ -4312,9 +4330,11 @@
// one recode history.
const int prev_q = rq_history->q_index_history[recode_count - 1];
const double prev_q_step = vp9_convert_qindex_to_q(prev_q, VPX_BITS_8);
- const int actual_bits = rq_history->rate_history[recode_count - 1];
- rq_model->ratio =
- rq_model->ratio + (target_bits - actual_bits) / log2(prev_q_step);
+ if (fabs(log2(prev_q_step)) > delta) {
+ const int actual_bits = rq_history->rate_history[recode_count - 1];
+ rq_model->ratio =
+ rq_model->ratio + (target_bits - actual_bits) / log2(prev_q_step);
+ }
}
}
}