From f916a3e256bc0e54852b48ec741c594aa58e2f26 Mon Sep 17 00:00:00 2001 From: Minghai Shang Date: Thu, 24 Apr 2014 13:31:46 -0700 Subject: [PATCH] [svc rc] RC improvement for key frames in upper layers for spatial svc. Change-Id: Id6ab59e505be28cd4eb9f1fe114feb47debe0539 --- vp9/encoder/vp9_encoder.h | 3 ++- vp9/encoder/vp9_firstpass.c | 21 ++++++++++++++------- vp9/encoder/vp9_ratectrl.c | 5 +++-- vp9/encoder/vp9_svc_layercontext.c | 13 +++++++++++++ vp9/encoder/vp9_svc_layercontext.h | 4 ++++ 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 8f32494..563f026 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -592,7 +592,8 @@ static INLINE YV12_BUFFER_CONFIG *get_ref_frame_buffer( // alt ref frames tend to be coded at a higher than ambient quality static INLINE int frame_is_boosted(const VP9_COMP *cpi) { return frame_is_intra_only(&cpi->common) || cpi->refresh_alt_ref_frame || - (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref); + (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref) || + vp9_is_upper_layer_key_frame(cpi); } static INLINE int get_token_alloc(int mb_rows, int mb_cols) { diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 3d4b962..a943023 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -1727,8 +1727,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { twopass->gf_bits = gf_bits; } if (i == 1 || - (!rc->source_alt_ref_pending && - cpi->common.frame_type != KEY_FRAME)) { + (!rc->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME && + !vp9_is_upper_layer_key_frame(cpi))) { // Calculate the per frame bit target for this frame. vp9_rc_set_frame_target(cpi, gf_bits); } @@ -2290,11 +2290,16 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { this_frame_copy = this_frame; find_next_key_frame(cpi, &this_frame_copy); // Don't place key frame in any enhancement layers in spatial svc - if (cpi->use_svc && cpi->svc.number_temporal_layers == 1 && - cpi->svc.spatial_layer_id > 0) { - cm->frame_type = INTER_FRAME; + if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) { + lc->is_key_frame = 1; + if (cpi->svc.spatial_layer_id > 0) { + cm->frame_type = INTER_FRAME; + } } } else { + if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) { + lc->is_key_frame = 0; + } cm->frame_type = INTER_FRAME; } @@ -2392,9 +2397,11 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { cpi->twopass.bits_left = MAX(cpi->twopass.bits_left, 0); #ifdef LONG_TERM_VBR_CORRECTION - if (cpi->common.frame_type != KEY_FRAME) { + if (cpi->common.frame_type != KEY_FRAME && + !vp9_is_upper_layer_key_frame(cpi)) { #else - if (cpi->common.frame_type == KEY_FRAME) { + if (cpi->common.frame_type == KEY_FRAME || + vp9_is_upper_layer_key_frame(cpi)) { // For key frames kf_group_bits already had the target bits subtracted out. // So now update to the correct value based on the actual bits used. cpi->twopass.kf_group_bits += cpi->rc.this_frame_target - bits_used; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 6ebd9f3..b123bfd 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -807,7 +807,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, int active_worst_quality = cpi->twopass.active_worst_quality; int q; - if (frame_is_intra_only(cm)) { + if (frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi)) { #if !CONFIG_MULTIPLE_ARF // Handle the special case for key frames forced when we have75 reached // the maximum key frame interval. Here force the Q to a range @@ -928,7 +928,8 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, vp9_clear_system_state(); // Limit Q range for the adaptive loop. - if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) { + if ((cm->frame_type == KEY_FRAME || vp9_is_upper_layer_key_frame(cpi)) && + !rc->this_key_frame_forced) { qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type, active_worst_quality, 2.0); } else if (!rc->is_src_frame_alt_ref && diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 2379f35..5342447 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -220,3 +220,16 @@ void vp9_inc_frame_in_layer(SVC *svc) { : &svc->layer_context[svc->spatial_layer_id]; ++lc->current_video_frame_in_layer; } + +int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi) { + int is_upper_layer_key_frame = 0; + + if (cpi->use_svc && cpi->svc.number_temporal_layers == 1 && + cpi->svc.spatial_layer_id > 0) { + if (cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame) { + is_upper_layer_key_frame = 1; + } + } + + return is_upper_layer_key_frame; +} diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h index 2abed30..74d9c1c 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -30,6 +30,7 @@ typedef struct { struct twopass_rc twopass; struct vpx_fixed_buf rc_twopass_stats_in; unsigned int current_video_frame_in_layer; + int is_key_frame; } LAYER_CONTEXT; typedef struct { @@ -73,6 +74,9 @@ void vp9_init_second_pass_spatial_svc(struct VP9_COMP *cpi); // Increment number of video frames in layer void vp9_inc_frame_in_layer(SVC *svc); +// Check if current layer is key frame in spatial upper layer +int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi); + #ifdef __cplusplus } // extern "C" #endif -- 2.7.4