From: Wei-ting Lin Date: Tue, 12 Jul 2016 20:19:45 +0000 (-0700) Subject: Allow OVERLAY frames to use the show_exsiting_frame flag X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ccc9e7cfc69f6b5ec6818e4489848912a6a4681f;p=libvpx Allow OVERLAY frames to use the show_exsiting_frame flag ARF with zero strength temporal filter can be reused by setting the show_existing_frame = 1, and in this case, there is no need to refresh the reference frame buffer. However, we used the flag "refresh_golden_frame" as the identifier for the starting point of a gf group. A new flags "is_arf_filter_off" is used to record if the filter with strengrh zero is used. Change-Id: I25971a760f6e1638d5147fe30488c48125512b1a --- diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 3999c9460..4ef16a869 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -2671,7 +2671,6 @@ static void write_tile_info(const VP10_COMMON *const cm, vpx_wb_write_bit(wb, cm->log2_tile_rows != 1); #endif // CONFIG_EXT_TILE } - static int get_refresh_mask(VP10_COMP *cpi) { int refresh_mask = 0; diff --git a/vp10/encoder/bitstream.h b/vp10/encoder/bitstream.h index cacdb43eb..24934fe6b 100644 --- a/vp10/encoder/bitstream.h +++ b/vp10/encoder/bitstream.h @@ -23,8 +23,12 @@ void vp10_pack_bitstream(VP10_COMP *const cpi, uint8_t *dest, size_t *size); void vp10_encode_token_init(void); static INLINE int vp10_preserve_existing_gf(VP10_COMP *cpi) { +#if CONFIG_EXT_REFS + return !cpi->multi_arf_allowed && cpi->rc.is_src_frame_alt_ref; +#else return !cpi->multi_arf_allowed && cpi->refresh_golden_frame && cpi->rc.is_src_frame_alt_ref; +#endif } #ifdef __cplusplus diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index 5adba4ca9..0620b885c 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -85,6 +85,7 @@ FILE *yuv_skinmap_file = NULL; #endif #ifdef OUTPUT_YUV_REC FILE *yuv_rec_file; +#define FILE_NAME_LEN 80 #endif #if 0 @@ -3061,9 +3062,36 @@ void vp10_write_yuv_frame_420(YV12_BUFFER_CONFIG *s, FILE *f) { } #endif +#if CONFIG_EXT_REFS +static void check_show_existing_frame(VP10_COMP *cpi) { + const GF_GROUP *const gf_group = &cpi->twopass.gf_group; + VP10_COMMON *const cm = &cpi->common; + const FRAME_UPDATE_TYPE next_frame_update_type = + gf_group->update_type[gf_group->index]; + + if (cpi->rc.is_last_bipred_frame) { + // NOTE(zoeliu): If the current frame is a last bi-predictive frame, it is + // needed next to show the BWDREF_FRAME, which is pointed by + // the last_fb_idxes[0] after reference frame buffer update + cpi->rc.is_last_bipred_frame = 0; + cm->show_existing_frame = 1; + cpi->existing_fb_idx_to_show = cpi->lst_fb_idxes[0]; + } else if (next_frame_update_type == OVERLAY_UPDATE && + cpi->is_arf_filter_off) { + // Other parameters related to OVERLAY_UPDATE will be taken care of + // in vp10_rc_get_second_pass_params(cpi) + cm->show_existing_frame = 1; + cpi->rc.is_src_frame_alt_ref = 1; + cpi->existing_fb_idx_to_show = cpi->alt_fb_idx; + cpi->is_arf_filter_off = 0; + } else { + cm->show_existing_frame = 0; + } +} +#endif + #ifdef OUTPUT_YUV_REC -void vp10_write_yuv_rec_frame(VP10_COMMON *cm) { - YV12_BUFFER_CONFIG *s = cm->frame_to_show; +void vp10_write_one_yuv_frame(VP10_COMMON *cm, YV12_BUFFER_CONFIG *s) { uint8_t *src = s->y_buffer; int h = cm->height; @@ -3120,7 +3148,7 @@ void vp10_write_yuv_rec_frame(VP10_COMMON *cm) { fflush(yuv_rec_file); } -#endif +#endif // OUTPUT_YUV_REC #if CONFIG_VP9_HIGHBITDEPTH static void scale_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src, @@ -4849,6 +4877,15 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, // Update the frame type cm->last_frame_type = cm->frame_type; +#if CONFIG_EXT_REFS + // Since we allocate a spot for the OVERLAY frame in the gf group, we need + // to do post-encoding update accordingly. + if (cpi->rc.is_src_frame_alt_ref) { + vp10_set_target_rate(cpi); + vp10_rc_postencode_update(cpi, *size); + } +#endif + cm->last_width = cm->width; cm->last_height = cm->height; @@ -4976,14 +5013,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, dump_filtered_recon_frames(cpi); #endif // DUMP_RECON_FRAMES -#if CONFIG_EXT_REFS - if (cpi->rc.is_last_bipred_frame) { - // NOTE: If the current frame is a LAST_BIPRED_FRAME, next it is needed - // to show the BWDREF_FRAME. - cpi->existing_fb_idx_to_show = cpi->bwd_fb_idx; - } -#endif // CONFIG_EXT_REFS - if (cm->seg.update_map) update_reference_segmentation_map(cpi); @@ -5097,13 +5126,20 @@ static void Pass0Encode(VP10_COMP *cpi, size_t *size, uint8_t *dest, static void Pass2Encode(VP10_COMP *cpi, size_t *size, uint8_t *dest, unsigned int *frame_flags) { cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED; + encode_frame_to_data_rate(cpi, size, dest, frame_flags); #if CONFIG_EXT_REFS - // Donot do the post-encoding update for show_existing_frame==1. - if (!cpi->common.show_existing_frame) -#endif // CONFIG_EXT_REFS + // Do not do post-encoding update for those frames that do not have a spot in + // a gf group, but note that an OVERLAY frame always has a spot in a gf group, + // even when show_existing_frame is used. + if (!cpi->common.show_existing_frame || cpi->rc.is_src_frame_alt_ref) { vp10_twopass_postencode_update(cpi); + } + check_show_existing_frame(cpi); +#else + vp10_twopass_postencode_update(cpi); +#endif // CONFIG_EXT_REFS } static void init_ref_frame_bufs(VP10_COMMON *cm) { @@ -5500,6 +5536,11 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, *time_stamp = source->ts_start; *time_end = source->ts_end; + // We need to adjust frame rate for an overlay frame + if (cpi->rc.is_src_frame_alt_ref) { + adjust_frame_rate(cpi, source); + } + // Find a free buffer for the new frame, releasing the reference previously // held. if (cm->new_fb_idx != INVALID_IDX) { @@ -5516,6 +5557,11 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, // Start with a 0 size frame. *size = 0; + // We need to update the gf_group for show_existing overlay frame + if (cpi->rc.is_src_frame_alt_ref) { + vp10_rc_get_second_pass_params(cpi); + } + Pass2Encode(cpi, size, dest, frame_flags); if (cpi->b_calculate_psnr) @@ -5717,17 +5763,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, vpx_clear_system_state(); -#if CONFIG_EXT_REFS - if (cpi->rc.is_last_bipred_frame) { - // NOTE(zoeliu): If the current frame is a last bi-predictive frame, it is - // needed next to show the BWDREF_FRAME. - cpi->rc.is_last_bipred_frame = 0; - cm->show_existing_frame = 1; - } else { - cm->show_existing_frame = 0; - } -#endif // CONFIG_EXT_REFS - return 0; } diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index d7c62b258..c8555f267 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -614,6 +614,7 @@ typedef struct VP10_COMP { #if CONFIG_EXT_REFS int refresh_frame_mask; int existing_fb_idx_to_show; + int is_arf_filter_off; #endif // CONFIG_EXT_REFS } VP10_COMP; diff --git a/vp10/encoder/firstpass.c b/vp10/encoder/firstpass.c index add251036..6bb716554 100644 --- a/vp10/encoder/firstpass.c +++ b/vp10/encoder/firstpass.c @@ -2519,6 +2519,9 @@ static void find_next_key_frame(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) { static void configure_buffer_updates(VP10_COMP *cpi) { TWO_PASS *const twopass = &cpi->twopass; + // Wei-Ting: Should we define another function to take care of + // cpi->rc.is_$Source_Type to make this function as it is in the comment? + cpi->rc.is_src_frame_alt_ref = 0; #if CONFIG_EXT_REFS cpi->rc.is_bwd_ref_frame = 0; @@ -2739,6 +2742,7 @@ void vp10_rc_get_second_pass_params(VP10_COMP *cpi) { } target_rate = gf_group->bit_allocation[gf_group->index]; + if (cpi->common.frame_type == KEY_FRAME) target_rate = vp10_rc_clamp_iframe_target_size(cpi, target_rate); else diff --git a/vp10/encoder/ratectrl.c b/vp10/encoder/ratectrl.c index 5dd42d417..2f2f2b72d 100644 --- a/vp10/encoder/ratectrl.c +++ b/vp10/encoder/ratectrl.c @@ -203,7 +203,11 @@ int vp10_rc_clamp_pframe_target_size(const VP10_COMP *const cpi, int target) { rc->avg_frame_bandwidth >> 5); if (target < min_frame_target) target = min_frame_target; +#if CONFIG_EXT_REFS + if (cpi->rc.is_src_frame_alt_ref) { +#else if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) { +#endif // If there is an active ARF at this location use the minimum // bits on this frame even if it is a constructed arf. // The active maximum quantizer insures that an appropriate @@ -1232,8 +1236,16 @@ static void update_alt_ref_frame_stats(VP10_COMP *cpi) { static void update_golden_frame_stats(VP10_COMP *cpi) { RATE_CONTROL *const rc = &cpi->rc; +#if CONFIG_EXT_REFS // Update the Golden frame usage counts. + // Wei-Ting: If we use show_existing_frame for an OVERLAY frame, only the + // virtual indices for the reference frame will be updated and + // cpi->refresh_golden_frame will still be zero. + if (cpi->refresh_golden_frame || rc->is_src_frame_alt_ref) { +#else + // Update the Golden frame usage counts. if (cpi->refresh_golden_frame) { +#endif // this frame refreshes means next frames don't unless specified by user rc->frames_since_golden = 0; diff --git a/vp10/encoder/temporal_filter.c b/vp10/encoder/temporal_filter.c index d125daec1..707de96fa 100644 --- a/vp10/encoder/temporal_filter.c +++ b/vp10/encoder/temporal_filter.c @@ -733,6 +733,12 @@ void vp10_temporal_filter(VP10_COMP *cpi, int distance) { // Apply context specific adjustments to the arnr filter parameters. adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength); +#if CONFIG_EXT_REFS + if (strength == 0 && frames_to_blur == 1) + cpi->is_arf_filter_off = 1; + else + cpi->is_arf_filter_off = 0; +#endif frames_to_blur_backward = (frames_to_blur / 2); frames_to_blur_forward = ((frames_to_blur - 1) / 2); start_frame = distance + frames_to_blur_forward;