Correct buffer fullness Q adjustment.
Fix anomaly in adjustment of active worst quality for RTC.
The real time code adjusts the active worst Q allowed for each
frame based on buffer fullness. The baseline value is derived
from the ambient Q for recent frames. Where there has
been overspend and the buffer has run empty, the allowed worst
Q is increased. Conversely, where we have underspend and the
buffer fullness has risen above the target optimal level, we apply
a downward pressure on Q
This patch fixes an anomaly around transition between these two.
Adjustments up were applied to the measured ambient Q while
adjustments down were applied to the ambient Q * 5/4. This led
to the situation where as the buffer fullness rose above the optimal
level we would transition from (ambient Q +adjustment) to
((ambient Q *5/4) - adjustment). This meant that the value would
initially jump up higher for a time when one would expect it to start
falling.
The main observed impact of this patch is on the RTC screen set.
Bdrate improvements are as follows (opsnr , ssim, vmaf) :-
Screen data set
Speed 10 -2.530, -2.174, -2.187. (speedup 0.769%)
Speed 8 -4.282, -3.816, -3.482, (speedup 3.432%)
Speed 6 -4.108, -3.730, -3.370, (speedup 3.060%)
STATS_CHANGED
Change-Id: I1244626a6fa8dfff22dd07bb3796d72979fb64f2
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 4ea1c9a..ad46187 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -1033,11 +1033,20 @@
ambient_qp = (cm->current_frame.frame_number < num_frames_weight_key)
? AOMMIN(p_rc->avg_frame_qindex[INTER_FRAME], avg_qindex_key)
: p_rc->avg_frame_qindex[INTER_FRAME];
- active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp * 5 / 4);
+
if (p_rc->buffer_level > p_rc->optimal_buffer_level) {
// Adjust down.
- // Maximum limit for down adjustment, ~30%.
- int max_adjustment_down = active_worst_quality / 3;
+ int max_adjustment_down; // Maximum adjustment down for Q
+
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ && !cpi->ppi->use_svc &&
+ (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN)) {
+ active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp);
+ max_adjustment_down = AOMMIN(4, active_worst_quality / 16);
+ } else {
+ active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp * 5 / 4);
+ max_adjustment_down = active_worst_quality / 3;
+ }
+
if (max_adjustment_down) {
buff_lvl_step =
((p_rc->maximum_buffer_size - p_rc->optimal_buffer_level) /
@@ -1049,6 +1058,7 @@
}
} else if (p_rc->buffer_level > critical_level) {
// Adjust up from ambient Q.
+ active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp);
if (critical_level) {
buff_lvl_step = (p_rc->optimal_buffer_level - critical_level);
if (buff_lvl_step) {
@@ -1056,7 +1066,7 @@
(p_rc->optimal_buffer_level - p_rc->buffer_level) /
buff_lvl_step);
}
- active_worst_quality = ambient_qp + adjustment;
+ active_worst_quality += adjustment;
}
} else {
// Set to worst_quality if buffer is below critical level.