Fix to QP for temporal enhancment after keyframe
For temporal enhancement layers in RTC mode:
after a key frame use the avg_qindex_key for the
ambient_qp for the active_worst_quality setting.
And use last_q[KEY/INTER_FRAME] depending on keyframe
distance in adjust_q_cbr().
This reduces some sawtooth-like behavoior in psnr/qp
observed for temporal layers with periodic keyframes.
This also exposed a bug in the external RC where
frames_since_key was not updated in the correct place.
Change-Id: Ia63819a98823b13aefdde79b934fb30b78953986
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 9793a3f..784733d 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -653,9 +653,13 @@
LAYER_CONTEXT *lc = &svc->layer_context[layer];
// lc->rc.avg_frame_bandwidth and lc->p_rc.last_q correspond to the
// last TL0 frame.
+ const int last_qindex_tl0 =
+ rc->frames_since_key < svc->number_temporal_layers
+ ? lc->p_rc.last_q[KEY_FRAME]
+ : lc->p_rc.last_q[INTER_FRAME];
if (rc->avg_frame_bandwidth < lc->rc.avg_frame_bandwidth &&
- q < lc->p_rc.last_q[INTER_FRAME] - 4)
- q = lc->p_rc.last_q[INTER_FRAME] - 4;
+ q < last_qindex_tl0 - 4)
+ q = last_qindex_tl0 - 4;
} else if (cpi->svc.temporal_layer_id == 0 &&
p_rc->buffer_level > (p_rc->optimal_buffer_level >> 2) &&
rc->frame_source_sad < 100000) {
@@ -1123,7 +1127,7 @@
int adjustment = 0;
int active_worst_quality;
int ambient_qp;
- if (cm->current_frame.frame_type == KEY_FRAME) return rc->worst_quality;
+ if (frame_is_intra_only(cm)) return rc->worst_quality;
// For ambient_qp we use minimum of avg_frame_qindex[KEY_FRAME/INTER_FRAME]
// for the first few frames following key frame. These are both initialized
// to worst_quality and updated with (3/4, 1/4) average in postencode_update.
@@ -1138,9 +1142,15 @@
avg_qindex_key =
AOMMIN(lp_rc->avg_frame_qindex[KEY_FRAME], lp_rc->last_q[KEY_FRAME]);
}
- 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];
+ if (svc->temporal_layer_id > 0 &&
+ rc->frames_since_key < 2 * svc->number_temporal_layers) {
+ ambient_qp = avg_qindex_key;
+ } else {
+ 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];
+ }
ambient_qp = AOMMIN(rc->worst_quality, ambient_qp);
if (p_rc->buffer_level > p_rc->optimal_buffer_level) {
diff --git a/av1/ratectrl_rtc.cc b/av1/ratectrl_rtc.cc
index f8c13c6..eab3d1d 100644
--- a/av1/ratectrl_rtc.cc
+++ b/av1/ratectrl_rtc.cc
@@ -283,8 +283,6 @@
cpi_->svc.layer_context[layer].is_key_frame = 0;
}
}
- if (cpi_->svc.spatial_layer_id == cpi_->svc.number_spatial_layers - 1)
- cpi_->rc.frames_since_key++;
if (cpi_->svc.number_spatial_layers > 1 ||
cpi_->svc.number_temporal_layers > 1) {
av1_update_temporal_layer_framerate(cpi_);
@@ -364,9 +362,11 @@
void AV1RateControlRTC::PostEncodeUpdate(uint64_t encoded_frame_size) {
cpi_->common.current_frame.frame_number++;
- if (cpi_->svc.spatial_layer_id == cpi_->svc.number_spatial_layers - 1)
- cpi_->svc.prev_number_spatial_layers = cpi_->svc.number_spatial_layers;
av1_rc_postencode_update(cpi_, encoded_frame_size);
+ if (cpi_->svc.spatial_layer_id == cpi_->svc.number_spatial_layers - 1) {
+ cpi_->svc.prev_number_spatial_layers = cpi_->svc.number_spatial_layers;
+ cpi_->rc.frames_since_key++;
+ }
if (cpi_->svc.number_spatial_layers > 1 ||
cpi_->svc.number_temporal_layers > 1)
av1_save_layer_context(cpi_);