From b2f37bac65457d327002130a58d98ae2d2dcab7f Mon Sep 17 00:00:00 2001 From: Marco Paniconi Date: Mon, 3 Dec 2018 10:49:41 -0800 Subject: vp9: Overshoot detection for skipped base layer. If scene/slide change is detected on current superframe and max-q set because of high overshoot: then if the lower/base spatial layer are skipped on the current superframe, max-q is forced on the next encoded base/lower spatial layers. Change-Id: Id61efda86ee545395012e19476d19845e3932678 --- vp9/encoder/vp9_encoder.c | 7 ++++--- vp9/encoder/vp9_ratectrl.c | 32 +++++++++++++++++++------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 04d25247d..353857b8a 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3832,9 +3832,10 @@ static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size, if (svc->spatial_layer_id == svc->first_spatial_layer_to_encode) { svc->high_source_sad_superframe = cpi->rc.high_source_sad; // On scene change reset temporal layer pattern to TL0. - // TODO(marpan/jianj): Fix this to handle case where base - // spatial layers are skipped, in which case we should insert - // and reset to spatial layer 0 on scene change. + // Note that if the base/lower spatial layers are skipped: instead of + // inserting base layer here, we force max-q for the next superframe + // with lower spatial layers: this is done in vp9_encodedframe_overshoot() + // when max-q is decided for the current layer. if (svc->high_source_sad_superframe && svc->temporal_layer_id > 0) { // rc->high_source_sad will get reset so copy it to restore it. int tmp_high_source_sad = cpi->rc.high_source_sad; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 396ba0269..4c0bf378f 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -3081,21 +3081,27 @@ int vp9_encodedframe_overshoot(VP9_COMP *cpi, int frame_size, int *q) { cpi->rc.rate_correction_factors[INTER_NORMAL] = rate_correction_factor; } // For temporal layers, reset the rate control parametes across all - // temporal layers. + // temporal layers. If the first_spatial_layer_to_encode > 0, then this + // superframe has skipped lower base layers. So in this case we should also + // reset and force max-q for spatial layers < first_spatial_layer_to_encode. if (cpi->use_svc) { - int i = 0; + int tl = 0; + int sl = 0; SVC *svc = &cpi->svc; - for (i = 0; i < svc->number_temporal_layers; ++i) { - const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id, i, - svc->number_temporal_layers); - LAYER_CONTEXT *lc = &svc->layer_context[layer]; - RATE_CONTROL *lrc = &lc->rc; - lrc->avg_frame_qindex[INTER_FRAME] = *q; - lrc->buffer_level = lrc->optimal_buffer_level; - lrc->bits_off_target = lrc->optimal_buffer_level; - lrc->rc_1_frame = 0; - lrc->rc_2_frame = 0; - lrc->rate_correction_factors[INTER_NORMAL] = rate_correction_factor; + for (sl = 0; sl < svc->first_spatial_layer_to_encode; ++sl) { + for (tl = 0; tl < svc->number_temporal_layers; ++tl) { + const int layer = + LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers); + LAYER_CONTEXT *lc = &svc->layer_context[layer]; + RATE_CONTROL *lrc = &lc->rc; + lrc->avg_frame_qindex[INTER_FRAME] = *q; + lrc->buffer_level = lrc->optimal_buffer_level; + lrc->bits_off_target = lrc->optimal_buffer_level; + lrc->rc_1_frame = 0; + lrc->rc_2_frame = 0; + lrc->rate_correction_factors[INTER_NORMAL] = rate_correction_factor; + lrc->force_max_q = 1; + } } } return 1; -- cgit v1.2.3