From: Zoe Liu Date: Fri, 22 Jun 2018 02:26:32 +0000 (-0700) Subject: Add reference frame update flags for hierarchical X-Git-Tag: v1.8.0~573^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1f9b095183e3df33d16569f09f0776b2fd01eba1;p=libvpx Add reference frame update flags for hierarchical Previous CLs have implemented the construction of the hierarchical structure at the encoder side. This CL is to define and configure the according flags that will guide the reference frame update according to the constructed hierarchical structure. Change-Id: Iae55f2400f7c7beff41feff9308f87bfc70c7b21 --- diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index ec02a78ee..bd610c5ff 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -514,6 +514,8 @@ typedef struct VP9_COMP { int refresh_last_frame; int refresh_golden_frame; + int refresh_bwd_ref_frame; + int refresh_alt2_ref_frame; int refresh_alt_ref_frame; int ext_refresh_frame_flags_pending; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 6717d961d..7cc4659a9 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -3435,6 +3435,112 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { } // Define the reference buffers that will be updated post encode. +static void configure_multi_arf_buffer_updates(VP9_COMP *cpi) { + TWO_PASS *const twopass = &cpi->twopass; + + cpi->rc.is_src_frame_alt_ref = 0; + cpi->rc.is_bwd_ref_frame = 0; + cpi->rc.is_last_bipred_frame = 0; + cpi->rc.is_bipred_frame = 0; + cpi->rc.is_src_frame_ext_arf = 0; + + switch (twopass->gf_group.update_type[twopass->gf_group.index]) { + case KF_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 1; + cpi->refresh_bwd_ref_frame = 1; + cpi->refresh_alt2_ref_frame = 1; + cpi->refresh_alt_ref_frame = 1; + break; + + case LF_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 0; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + break; + + case GF_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 1; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + break; + + case OVERLAY_UPDATE: + cpi->refresh_last_frame = 0; + cpi->refresh_golden_frame = 1; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + + cpi->rc.is_src_frame_alt_ref = 1; + break; + + case ARF_UPDATE: + cpi->refresh_last_frame = 0; + cpi->refresh_golden_frame = 0; + // NOTE: BWDREF does not get updated along with ALTREF_FRAME. + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 1; + break; + + case BRF_UPDATE: + cpi->refresh_last_frame = 0; + cpi->refresh_golden_frame = 0; + cpi->refresh_bwd_ref_frame = 1; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + + cpi->rc.is_bwd_ref_frame = 1; + break; + + case LAST_BIPRED_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 0; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + + cpi->rc.is_last_bipred_frame = 1; + break; + + case BIPRED_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 0; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + + cpi->rc.is_bipred_frame = 1; + break; + + case INTNL_OVERLAY_UPDATE: + cpi->refresh_last_frame = 1; + cpi->refresh_golden_frame = 0; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 0; + cpi->refresh_alt_ref_frame = 0; + + cpi->rc.is_src_frame_alt_ref = 1; + cpi->rc.is_src_frame_ext_arf = 1; + break; + + case INTNL_ARF_UPDATE: + cpi->refresh_last_frame = 0; + cpi->refresh_golden_frame = 0; + cpi->refresh_bwd_ref_frame = 0; + cpi->refresh_alt2_ref_frame = 1; + cpi->refresh_alt_ref_frame = 0; + break; + + default: assert(0); break; + } +} + static void configure_buffer_updates(VP9_COMP *cpi) { TWO_PASS *const twopass = &cpi->twopass; @@ -3503,7 +3609,13 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { // advance the input pointer as we already have what we need. if (gf_group->update_type[gf_group->index] == ARF_UPDATE) { int target_rate; - configure_buffer_updates(cpi); + + if (cpi->extra_arf_allowed) { + configure_multi_arf_buffer_updates(cpi); + } else { + configure_buffer_updates(cpi); + } + target_rate = gf_group->bit_allocation[gf_group->index]; target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate); rc->base_frame_target = target_rate; @@ -3595,7 +3707,11 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { #endif } - configure_buffer_updates(cpi); + if (cpi->extra_arf_allowed) { + configure_multi_arf_buffer_updates(cpi); + } else { + configure_buffer_updates(cpi); + } // Do the firstpass stats indicate that this frame is skippable for the // partition search? diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 5f4e66fe3..488dae12d 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -109,6 +109,13 @@ typedef struct { // Length of the bi-predictive frame group interval int bipred_group_interval; + // NOTE: Different types of frames may have different bits allocated + // accordingly, aiming to achieve the overall optimal RD performance. + int is_bwd_ref_frame; + int is_last_bipred_frame; + int is_bipred_frame; + int is_src_frame_ext_arf; + int avg_frame_bandwidth; // Average frame size target for clip int min_frame_bandwidth; // Minimum allocation used for any frame int max_frame_bandwidth; // Maximum burst rate allowed for a frame.