From a40fa1f95d3c49424f6366cd91771f801cbac6c3 Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 7 Dec 2017 17:24:41 -0800 Subject: vp9: Reset rc flags on some configuration changes. For large dynamic changes in target avg_frame_bandwidth, or a change in resolution, via the update in change_config()), reset the under/overshoot flags (rc_1_frame, rc_2_frame) to prevent constraining the QP for the first few frames following the change. For SVC use the spatial stream avg_frame_bandwidth in reset condition. For the avg_frame_bandwidth condition, use fairly large threshold (~50%) for now in reset. This allows for better/faster QP response if, for example, application dynamically changes bitrate by large amount. Change-Id: Ib6e3761732d956949d79c9247e50dba744a535c0 --- vp9/encoder/vp9_encoder.c | 17 +++++++++++++++++ vp9/encoder/vp9_ratectrl.c | 2 ++ vp9/encoder/vp9_ratectrl.h | 2 ++ vp9/encoder/vp9_svc_layercontext.c | 23 +++++++++++++++++++++++ vp9/encoder/vp9_svc_layercontext.h | 2 ++ 5 files changed, 46 insertions(+) (limited to 'vp9/encoder') diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index e840155b1..c9f69ef77 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -1853,6 +1853,8 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { cm->mi_rows * cm->mi_cols * sizeof(*cpi->consec_zero_mv)); if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) vp9_cyclic_refresh_reset_resize(cpi); + rc->rc_1_frame = 0; + rc->rc_2_frame = 0; } if ((cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) || @@ -1863,6 +1865,21 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { (int)cpi->oxcf.target_bandwidth); } + // Check for resetting the rc flags (rc_1_frame, rc_2_frame) if the + // configuration change has a large change in avg_frame_bandwidth. + // For SVC check for resetting based on spatial layer average bandwidth. + if (cm->current_video_frame > 0) { + if (cpi->use_svc) { + vp9_svc_check_reset_layer_rc_flag(cpi); + } else { + if (rc->avg_frame_bandwidth > (3 * rc->last_avg_frame_bandwidth >> 1) || + rc->avg_frame_bandwidth < (rc->last_avg_frame_bandwidth >> 1)) { + rc->rc_1_frame = 0; + rc->rc_2_frame = 0; + } + } + } + cpi->alt_ref_source = NULL; rc->is_src_frame_alt_ref = 0; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 3f7fb1e88..b7f3a0e89 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1488,6 +1488,8 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) { cpi->rc.last_frame_is_src_altref = cpi->rc.is_src_frame_alt_ref; } if (cm->frame_type != KEY_FRAME) rc->reset_high_source_sad = 0; + + rc->last_avg_frame_bandwidth = rc->avg_frame_bandwidth; } void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) { diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 8a785c994..c1b210677 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -152,6 +152,8 @@ typedef struct { int rc_2_frame; int q_1_frame; int q_2_frame; + // Keep track of the last target average frame bandwidth. + int last_avg_frame_bandwidth; // Auto frame-scaling variables. FRAME_SCALE_LEVEL frame_size_selector; diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index e0d3bad8b..45a1d142d 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -862,3 +862,26 @@ void vp9_svc_reset_key_frame(VP9_COMP *const cpi) { vp9_update_temporal_layer_framerate(cpi); vp9_restore_layer_context(cpi); } + +void vp9_svc_check_reset_layer_rc_flag(VP9_COMP *const cpi) { + SVC *svc = &cpi->svc; + int sl, tl; + for (sl = 0; sl < svc->number_spatial_layers; ++sl) { + // Check for reset based on avg_frame_bandwidth for spatial layer sl. + int layer = LAYER_IDS_TO_IDX(sl, svc->number_temporal_layers - 1, + svc->number_temporal_layers); + LAYER_CONTEXT *lc = &svc->layer_context[layer]; + RATE_CONTROL *lrc = &lc->rc; + if (lrc->avg_frame_bandwidth > (3 * lrc->last_avg_frame_bandwidth >> 1) || + lrc->avg_frame_bandwidth < (lrc->last_avg_frame_bandwidth >> 1)) { + // Reset for all temporal layers with spatial layer sl. + for (tl = 0; tl < svc->number_temporal_layers; ++tl) { + 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->rc_1_frame = 0; + lrc->rc_2_frame = 0; + } + } + } +} diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h index 16d1d6bb1..b7cdfd962 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -154,6 +154,8 @@ void vp9_free_svc_cyclic_refresh(struct VP9_COMP *const cpi); void vp9_svc_reset_key_frame(struct VP9_COMP *const cpi); +void vp9_svc_check_reset_layer_rc_flag(struct VP9_COMP *const cpi); + #ifdef __cplusplus } // extern "C" #endif -- cgit v1.2.3