From: Zoe Liu Date: Thu, 3 Dec 2015 00:27:46 +0000 (-0800) Subject: Restore the flexibility for the new 3 references X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ec36a2b061bd4acacc75f15c7d8eadfa8f6cf0fd;p=libvpx Restore the flexibility for the new 3 references For the experiment of EXT_REFS, removed the previous special handling on the new last 3 references, i.e. LAST2_FRAME, LAST3_FRAME, and LAST4_FRAME, at the decoder, so that these new last references are treated the same way as the other 3 references (LAST_FRAME, GOLDEN_FRAME, and ALTREF_FRAME). Encoder changes have been made accordingly to realize this flexibility. Change-Id: Ic6546f9443b4377bb7e7b101bfa3e70a8b8d1c65 --- diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index 5b8ed2a26..fc7138715 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -72,11 +72,13 @@ typedef struct { #define GOLDEN_FRAME 5 #define ALTREF_FRAME 6 #define MAX_REF_FRAMES 7 +#define LAST_REF_FRAMES (LAST4_FRAME - LAST_FRAME + 1) #else #define GOLDEN_FRAME 2 #define ALTREF_FRAME 3 #define MAX_REF_FRAMES 4 #endif // CONFIG_EXT_REFS + typedef int8_t MV_REFERENCE_FRAME; typedef struct { diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 7fed6d53c..c0325b73a 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -2130,64 +2130,15 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, // Generate next_ref_frame_map. lock_buffer_pool(pool); for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { -#if CONFIG_EXT_REFS -// TODO(zoeliu): To move the following #define's to a header file -#define PBI_LST_FB_IDX 0 -#define PBI_LST2_FB_IDX 1 -#define PBI_LST3_FB_IDX 2 -#define PBI_LST4_FB_IDX 3 -#define PBI_GLD_FB_IDX 4 -#define PBI_ALT_FB_IDX 5 - // NOTE(zoeliu): - // (1) When ref_index == PBI_LST2_FB_IDX and the corresponding mask bit is - // set, it indicates that LAST2_FRAME shall be refreshed, but keep in - // mind that this has already been handled when LAST_FRAME is being - // refreshed, i.e., when ref_index == PBI_LST_FB_IDX and the mask bit - // is being set correspondingly; - // (2) The only exception is that when current frame is a KEY_FRAME, where - // all the frames in the frame buffer shall get refreshed; - // (3) Similar handling for when ref_index == PBI_LST3_FB_IDX or when - // ref_indx == PBI_LST4_FB_IDX. - if ((mask & 1) && - (cm->frame_type == KEY_FRAME || (ref_index != PBI_LST2_FB_IDX && - ref_index != PBI_LST3_FB_IDX && - ref_index != PBI_LST4_FB_IDX))) { - // The reference frame map for the decoding of the next frame is updated - // and held by either current thread or possibly another decoder thread. - if (cm->frame_type != KEY_FRAME && ref_index == PBI_LST_FB_IDX && - (mask & (1 << PBI_LST2_FB_IDX))) { - if (mask & (1 << PBI_LST3_FB_IDX)) { - if (mask & (1 << PBI_LST4_FB_IDX)) { - cm->next_ref_frame_map[PBI_LST4_FB_IDX] = - cm->next_ref_frame_map[PBI_LST3_FB_IDX]; - ++frame_bufs[cm->next_ref_frame_map[PBI_LST3_FB_IDX]].ref_count; - } - cm->next_ref_frame_map[PBI_LST3_FB_IDX] = - cm->next_ref_frame_map[PBI_LST2_FB_IDX]; - ++frame_bufs[cm->next_ref_frame_map[PBI_LST2_FB_IDX]].ref_count; - } - cm->next_ref_frame_map[PBI_LST2_FB_IDX] = - cm->next_ref_frame_map[PBI_LST_FB_IDX]; - ++frame_bufs[cm->next_ref_frame_map[PBI_LST_FB_IDX]].ref_count; - } - cm->next_ref_frame_map[ref_index] = cm->new_fb_idx; - ++frame_bufs[cm->new_fb_idx].ref_count; - } else if (!(mask & 1)) { - cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index]; - } -#else if (mask & 1) { cm->next_ref_frame_map[ref_index] = cm->new_fb_idx; ++frame_bufs[cm->new_fb_idx].ref_count; } else { cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index]; } -#endif // CONFIG_EXT_REFS - // Current thread holds the reference frame. if (cm->ref_frame_map[ref_index] >= 0) ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; - ++ref_index; } diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 434cc99f7..e559da085 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -1483,6 +1483,16 @@ static void write_tile_info(const VP10_COMMON *const cm, } static int get_refresh_mask(VP10_COMP *cpi) { +#if CONFIG_EXT_REFS + int refresh_mask = 0; + int ref_frame; + + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) { + refresh_mask |= (cpi->refresh_last_frames[ref_frame - LAST_FRAME] << + cpi->lst_fb_idxes[ref_frame - LAST_FRAME]); + } +#endif // CONFIG_EXT_REFS + if (vp10_preserve_existing_gf(cpi)) { // We have decided to preserve the previously existing golden frame as our // new ARF frame. However, in the short term we leave it in the GF slot and, @@ -1494,11 +1504,10 @@ static int get_refresh_mask(VP10_COMP *cpi) { // Note: This is highly specific to the use of ARF as a forward reference, // and this needs to be generalized as other uses are implemented // (like RTC/temporal scalability). - return (cpi->refresh_last_frame << cpi->lst_fb_idx) | #if CONFIG_EXT_REFS - (cpi->refresh_last2_frame << cpi->lst2_fb_idx) | - (cpi->refresh_last3_frame << cpi->lst3_fb_idx) | - (cpi->refresh_last4_frame << cpi->lst4_fb_idx) | + return refresh_mask | +#else + return (cpi->refresh_last_frame << cpi->lst_fb_idx) | #endif // CONFIG_EXT_REFS (cpi->refresh_golden_frame << cpi->alt_fb_idx); } else { @@ -1507,11 +1516,10 @@ static int get_refresh_mask(VP10_COMP *cpi) { const GF_GROUP *const gf_group = &cpi->twopass.gf_group; arf_idx = gf_group->arf_update_idx[gf_group->index]; } - return (cpi->refresh_last_frame << cpi->lst_fb_idx) | #if CONFIG_EXT_REFS - (cpi->refresh_last2_frame << cpi->lst2_fb_idx) | - (cpi->refresh_last3_frame << cpi->lst3_fb_idx) | - (cpi->refresh_last4_frame << cpi->lst4_fb_idx) | + return refresh_mask | +#else + return (cpi->refresh_last_frame << cpi->lst_fb_idx) | #endif // CONFIG_EXT_REFS (cpi->refresh_golden_frame << cpi->gld_fb_idx) | (cpi->refresh_alt_ref_frame << arf_idx); @@ -1683,13 +1691,6 @@ static void write_uncompressed_header(VP10_COMP *cpi, vpx_wb_write_bit(wb, cm->show_frame); vpx_wb_write_bit(wb, cm->error_resilient_mode); -#if CONFIG_EXT_REFS - cpi->refresh_last2_frame = - (cm->frame_type == KEY_FRAME || cpi->refresh_last_frame) ? 1 : 0; - cpi->refresh_last3_frame = cpi->refresh_last2_frame ? 1 : 0; - cpi->refresh_last4_frame = cpi->refresh_last3_frame ? 1 : 0; -#endif // CONFIG_EXT_REFS - if (cm->frame_type == KEY_FRAME) { write_sync_code(wb); write_bitdepth_colorspace_sampling(cm, wb); diff --git a/vp10/encoder/denoiser.c b/vp10/encoder/denoiser.c index c4955fe9f..43647b0f4 100644 --- a/vp10/encoder/denoiser.c +++ b/vp10/encoder/denoiser.c @@ -377,9 +377,17 @@ static void swap_frame_buffer(YV12_BUFFER_CONFIG *dest, void vp10_denoiser_update_frame_info(VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type, +#if CONFIG_EXT_REFS + int refresh_last_frames[LAST_REF_FRAMES], +#else + int refresh_last_frame, +#endif // CONFIG_EXT_REFS int refresh_alt_ref_frame, - int refresh_golden_frame, - int refresh_last_frame) { + int refresh_golden_frame) { +#if CONFIG_EXT_REFS + int ref_frame; +#endif // CONFIG_EXT_REFS + if (frame_type == KEY_FRAME) { int i; // Start at 1 so as not to overwrite the INTRA_FRAME @@ -397,18 +405,19 @@ void vp10_denoiser_update_frame_info(VP9_DENOISER *denoiser, swap_frame_buffer(&denoiser->running_avg_y[GOLDEN_FRAME], &denoiser->running_avg_y[INTRA_FRAME]); } - if (refresh_last_frame) { #if CONFIG_EXT_REFS - swap_frame_buffer(&denoiser->running_avg_y[LAST4_FRAME], - &denoiser->running_avg_y[LAST3_FRAME]); - swap_frame_buffer(&denoiser->running_avg_y[LAST3_FRAME], - &denoiser->running_avg_y[LAST2_FRAME]); - swap_frame_buffer(&denoiser->running_avg_y[LAST2_FRAME], - &denoiser->running_avg_y[LAST_FRAME]); -#endif // CONFIG_EXT_REFS + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) { + if (refresh_last_frames[ref_frame - LAST_FRAME]) { + swap_frame_buffer(&denoiser->running_avg_y[ref_frame], + &denoiser->running_avg_y[INTRA_FRAME]); + } + } +#else + if (refresh_last_frame) { swap_frame_buffer(&denoiser->running_avg_y[LAST_FRAME], &denoiser->running_avg_y[INTRA_FRAME]); } +#endif // CONFIG_EXT_REFS } void vp10_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { diff --git a/vp10/encoder/denoiser.h b/vp10/encoder/denoiser.h index e543fb05f..f48cbb0d0 100644 --- a/vp10/encoder/denoiser.h +++ b/vp10/encoder/denoiser.h @@ -35,9 +35,13 @@ typedef struct vp10_denoiser { void vp10_denoiser_update_frame_info(VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type, +#if CONFIG_EXT_REFS + int refresh_last_frames[LAST_REF_FRAMES], +#else + int refresh_last_frame, +#endif // CONFIG_EXT_REFS int refresh_alt_ref_frame, - int refresh_golden_frame, - int refresh_last_frame); + int refresh_golden_frame); void vp10_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, int mi_row, int mi_col, BLOCK_SIZE bs, diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index b42e3d6b0..704217467 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -717,14 +717,14 @@ static void update_frame_size(VP10_COMP *cpi) { } static void init_buffer_indices(VP10_COMP *cpi) { - cpi->lst_fb_idx = 0; #if CONFIG_EXT_REFS - cpi->lst2_fb_idx = 1; - cpi->lst3_fb_idx = 2; - cpi->lst4_fb_idx = 3; - cpi->gld_fb_idx = 4; - cpi->alt_fb_idx = 5; + int fb_idx; + for (fb_idx = 0; fb_idx < LAST_REF_FRAMES; ++fb_idx) + cpi->lst_fb_idxes[fb_idx] = fb_idx; + cpi->gld_fb_idx = LAST_REF_FRAMES; + cpi->alt_fb_idx = cpi->gld_fb_idx + 1; #else + cpi->lst_fb_idx = 0; cpi->gld_fb_idx = 1; cpi->alt_fb_idx = 2; #endif // CONFIG_EXT_REFS @@ -752,6 +752,10 @@ static void init_config(struct VP10_COMP *cpi, VP10EncoderConfig *oxcf) { cpi->td.counts = &cm->counts; // change includes all joint functionality +#if CONFIG_EXT_REFS + cpi->last_ref_to_refresh = LAST_FRAME; +#endif // CONFIG_EXT_REFS + vp10_change_config(cpi, oxcf); cpi->static_mb_pct = 0; @@ -1409,6 +1413,9 @@ static void realloc_segmentation_maps(VP10_COMP *cpi) { void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) { VP10_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; +#if CONFIG_EXT_REFS + int ref_frame; +#endif // CONFIG_EXT_REFS if (cm->profile != oxcf->profile) cm->profile = oxcf->profile; @@ -1433,11 +1440,16 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) { } cpi->refresh_golden_frame = 0; - cpi->refresh_last_frame = 1; + #if CONFIG_EXT_REFS - cpi->refresh_last2_frame = 0; - cpi->refresh_last3_frame = 0; - cpi->refresh_last4_frame = 0; + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) { + if (ref_frame == cpi->last_ref_to_refresh) + cpi->refresh_last_frames[ref_frame - LAST_FRAME] = 1; + else + cpi->refresh_last_frames[ref_frame - LAST_FRAME] = 0; + } +#else + cpi->refresh_last_frame = 1; #endif // CONFIG_EXT_REFS cm->refresh_frame_context = @@ -2307,11 +2319,13 @@ int vp10_use_as_reference(VP10_COMP *cpi, int ref_frame_flags) { void vp10_update_reference(VP10_COMP *cpi, int ref_frame_flags) { cpi->ext_refresh_golden_frame = (ref_frame_flags & VP9_GOLD_FLAG) != 0; cpi->ext_refresh_alt_ref_frame = (ref_frame_flags & VP9_ALT_FLAG) != 0; - cpi->ext_refresh_last_frame = (ref_frame_flags & VP9_LAST_FLAG) != 0; #if CONFIG_EXT_REFS - cpi->ext_refresh_last2_frame = (ref_frame_flags & VP9_LAST2_FLAG) != 0; - cpi->ext_refresh_last3_frame = (ref_frame_flags & VP9_LAST3_FLAG) != 0; - cpi->ext_refresh_last4_frame = (ref_frame_flags & VP9_LAST4_FLAG) != 0; + cpi->ext_refresh_last_frames[0] = (ref_frame_flags & VP9_LAST_FLAG) != 0; + cpi->ext_refresh_last_frames[1] = (ref_frame_flags & VP9_LAST2_FLAG) != 0; + cpi->ext_refresh_last_frames[2] = (ref_frame_flags & VP9_LAST3_FLAG) != 0; + cpi->ext_refresh_last_frames[3] = (ref_frame_flags & VP9_LAST4_FLAG) != 0; +#else + cpi->ext_refresh_last_frame = (ref_frame_flags & VP9_LAST_FLAG) != 0; #endif // CONFIG_EXT_REFS cpi->ext_refresh_frame_flags_pending = 1; } @@ -2610,6 +2624,9 @@ static int recode_loop_test(VP10_COMP *cpi, void vp10_update_reference_frames(VP10_COMP *cpi) { VP10_COMMON * const cm = &cpi->common; BufferPool *const pool = cm->buffer_pool; +#if CONFIG_EXT_REFS + int ref_frame; +#endif // CONFIG_EXT_REFS // At this point the new frame has been encoded. // If any buffer copy / swapping is signaled it should be done here. @@ -2664,92 +2681,49 @@ void vp10_update_reference_frames(VP10_COMP *cpi) { } } - if (cpi->refresh_last_frame) { #if CONFIG_EXT_REFS - if (cpi->refresh_last2_frame) { - if (cpi->refresh_last3_frame) { - if (cpi->refresh_last4_frame) { - if (cm->frame_type == KEY_FRAME) - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->lst4_fb_idx], - cm->new_fb_idx); - else - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->lst4_fb_idx], - cm->ref_frame_map[cpi->lst3_fb_idx]); - } - - if (cm->frame_type == KEY_FRAME) - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->lst3_fb_idx], - cm->new_fb_idx); - else - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->lst3_fb_idx], - cm->ref_frame_map[cpi->lst2_fb_idx]); + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) { + const int ref_idx = ref_frame - LAST_FRAME; + if (cpi->refresh_last_frames[ref_idx]) { + ref_cnt_fb(pool->frame_bufs, + &cm->ref_frame_map[cpi->lst_fb_idxes[ref_idx]], + cm->new_fb_idx); + if (!cpi->rc.is_src_frame_alt_ref) { + memcpy(cpi->interp_filter_selected[ref_frame], + cpi->interp_filter_selected[0], + sizeof(cpi->interp_filter_selected[0])); } - - if (cm->frame_type == KEY_FRAME) - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->lst2_fb_idx], - cm->new_fb_idx); - else - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->lst2_fb_idx], - cm->ref_frame_map[cpi->lst_fb_idx]); } -#endif // CONFIG_EXT_REFS + } + // NOTE: The order for the refreshing of the 4 last reference frames are: + // LAST_FRAME -> LAST2_FRAME -> LAST3_FRAME -> LAST4_FRAME -> LAST_FRAME + cpi->last_ref_to_refresh += 1; + if (cpi->last_ref_to_refresh == LAST4_FRAME) + cpi->last_ref_to_refresh = LAST_FRAME; +#else + if (cpi->refresh_last_frame) { ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx); - if (!cpi->rc.is_src_frame_alt_ref) { -#if CONFIG_EXT_REFS - if (cpi->refresh_last2_frame) { - if (cpi->refresh_last3_frame) { - if (cpi->refresh_last4_frame) { - if (cm->frame_type == KEY_FRAME) - memcpy(cpi->interp_filter_selected[LAST4_FRAME], - cpi->interp_filter_selected[0], - sizeof(cpi->interp_filter_selected[0])); - else - memcpy(cpi->interp_filter_selected[LAST4_FRAME], - cpi->interp_filter_selected[LAST3_FRAME], - sizeof(cpi->interp_filter_selected[LAST3_FRAME])); - } - - if (cm->frame_type == KEY_FRAME) - memcpy(cpi->interp_filter_selected[LAST3_FRAME], - cpi->interp_filter_selected[0], - sizeof(cpi->interp_filter_selected[0])); - else - memcpy(cpi->interp_filter_selected[LAST3_FRAME], - cpi->interp_filter_selected[LAST2_FRAME], - sizeof(cpi->interp_filter_selected[LAST2_FRAME])); - } - - if (cm->frame_type == KEY_FRAME) - memcpy(cpi->interp_filter_selected[LAST2_FRAME], - cpi->interp_filter_selected[0], - sizeof(cpi->interp_filter_selected[0])); - else - memcpy(cpi->interp_filter_selected[LAST2_FRAME], - cpi->interp_filter_selected[LAST_FRAME], - sizeof(cpi->interp_filter_selected[LAST_FRAME])); - } -#endif // CONFIG_EXT_REFS memcpy(cpi->interp_filter_selected[LAST_FRAME], cpi->interp_filter_selected[0], sizeof(cpi->interp_filter_selected[0])); } } +#endif // CONFIG_EXT_REFS + #if CONFIG_VP9_TEMPORAL_DENOISING if (cpi->oxcf.noise_sensitivity > 0) { vp10_denoiser_update_frame_info(&cpi->denoiser, *cpi->Source, cpi->common.frame_type, +#if CONFIG_EXT_REFS + cpi->refresh_last_frames, +#else + cpi->refresh_last_frame, +#endif // CONFIG_EXT_REFS cpi->refresh_alt_ref_frame, - cpi->refresh_golden_frame, - cpi->refresh_last_frame); + cpi->refresh_golden_frame); } #endif } @@ -2902,14 +2876,14 @@ static void release_scaled_references(VP10_COMP *cpi) { // Only release scaled references under certain conditions: // if reference will be updated, or if scaled reference has same resolution. int refresh[REFS_PER_FRAME]; - refresh[0] = (cpi->refresh_last_frame) ? 1 : 0; #if CONFIG_EXT_REFS - refresh[1] = (cpi->refresh_last2_frame) ? 1 : 0; - refresh[2] = (cpi->refresh_last3_frame) ? 1 : 0; - refresh[3] = (cpi->refresh_last4_frame) ? 1 : 0; + for (i = LAST_FRAME; i <= LAST4_FRAME; ++i) + refresh[i - LAST_FRAME] = + (cpi->refresh_last_frames[i - LAST_FRAME]) ? 1 : 0; refresh[4] = (cpi->refresh_golden_frame) ? 1 : 0; refresh[5] = (cpi->refresh_alt_ref_frame) ? 1 : 0; #else + refresh[0] = (cpi->refresh_last_frame) ? 1 : 0; refresh[1] = (cpi->refresh_golden_frame) ? 1 : 0; refresh[2] = (cpi->refresh_alt_ref_frame) ? 1 : 0; #endif // CONFIG_EXT_REFS @@ -3545,26 +3519,36 @@ static void encode_with_recode_loop(VP10_COMP *cpi, static int get_ref_frame_flags(const VP10_COMP *cpi) { const int *const map = cpi->common.ref_frame_map; - const int gold_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx]; - const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx]; - const int gold_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx]; #if CONFIG_EXT_REFS - const int last2_is_last = map[cpi->lst2_fb_idx] == map[cpi->lst_fb_idx]; - const int gld_is_last2 = map[cpi->gld_fb_idx] == map[cpi->lst2_fb_idx]; - const int alt_is_last2 = map[cpi->alt_fb_idx] == map[cpi->lst2_fb_idx]; - - const int last3_is_last = map[cpi->lst3_fb_idx] == map[cpi->lst_fb_idx]; - const int last3_is_last2 = map[cpi->lst3_fb_idx] == map[cpi->lst2_fb_idx]; - const int gld_is_last3 = map[cpi->gld_fb_idx] == map[cpi->lst3_fb_idx]; - const int alt_is_last3 = map[cpi->alt_fb_idx] == map[cpi->lst3_fb_idx]; - - const int last4_is_last = map[cpi->lst4_fb_idx] == map[cpi->lst_fb_idx]; - const int last4_is_last2 = map[cpi->lst4_fb_idx] == map[cpi->lst2_fb_idx]; - const int last4_is_last3 = map[cpi->lst4_fb_idx] == map[cpi->lst3_fb_idx]; - const int gld_is_last4 = map[cpi->gld_fb_idx] == map[cpi->lst4_fb_idx]; - const int alt_is_last4 = map[cpi->alt_fb_idx] == map[cpi->lst4_fb_idx]; + const int gld_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[0]]; + const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idxes[0]]; + + const int last2_is_last = + map[cpi->lst_fb_idxes[1]] == map[cpi->lst_fb_idxes[0]]; + const int gld_is_last2 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[1]]; + const int alt_is_last2 = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idxes[1]]; + + const int last3_is_last = + map[cpi->lst_fb_idxes[2]] == map[cpi->lst_fb_idxes[0]]; + const int last3_is_last2 = + map[cpi->lst_fb_idxes[2]] == map[cpi->lst_fb_idxes[1]]; + const int gld_is_last3 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[2]]; + const int alt_is_last3 = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idxes[2]]; + + const int last4_is_last = + map[cpi->lst_fb_idxes[3]] == map[cpi->lst_fb_idxes[0]]; + const int last4_is_last2 = + map[cpi->lst_fb_idxes[3]] == map[cpi->lst_fb_idxes[1]]; + const int last4_is_last3 = + map[cpi->lst_fb_idxes[3]] == map[cpi->lst_fb_idxes[2]]; + const int gld_is_last4 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[3]]; + const int alt_is_last4 = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idxes[3]]; +#else + const int gld_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx]; + const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx]; #endif // CONFIG_EXT_REFS + const int gld_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx]; int flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG; #if CONFIG_EXT_REFS @@ -3573,7 +3557,7 @@ static int get_ref_frame_flags(const VP10_COMP *cpi) { flags |= VP9_LAST4_FLAG; #endif // CONFIG_EXT_REFS - if (gold_is_last) + if (gld_is_last) flags &= ~VP9_GOLD_FLAG; if (cpi->rc.frames_till_gf_update_due == INT_MAX) @@ -3582,35 +3566,23 @@ static int get_ref_frame_flags(const VP10_COMP *cpi) { if (alt_is_last) flags &= ~VP9_ALT_FLAG; - if (gold_is_alt) + if (gld_is_alt) flags &= ~VP9_ALT_FLAG; #if CONFIG_EXT_REFS if (last4_is_last || last4_is_last2 || last4_is_last3) flags &= ~VP9_LAST4_FLAG; - if (gld_is_last4) - flags &= ~VP9_GOLD_FLAG; - - if (alt_is_last4) - flags &= ~VP9_ALT_FLAG; - if (last3_is_last || last3_is_last2) flags &= ~VP9_LAST3_FLAG; - if (gld_is_last3) - flags &= ~VP9_GOLD_FLAG; - - if (alt_is_last3) - flags &= ~VP9_ALT_FLAG; - if (last2_is_last) flags &= ~VP9_LAST2_FLAG; - if (gld_is_last2) + if (gld_is_last4 || gld_is_last3 || gld_is_last2) flags &= ~VP9_GOLD_FLAG; - if (alt_is_last2) + if (alt_is_last4 || alt_is_last3 || alt_is_last2) flags &= ~VP9_ALT_FLAG; #endif // CONFIG_EXT_REFS @@ -3627,11 +3599,14 @@ static void set_ext_overrides(VP10_COMP *cpi) { cpi->ext_refresh_frame_context_pending = 0; } if (cpi->ext_refresh_frame_flags_pending) { - cpi->refresh_last_frame = cpi->ext_refresh_last_frame; #if CONFIG_EXT_REFS - cpi->refresh_last2_frame = cpi->ext_refresh_last2_frame; - cpi->refresh_last3_frame = cpi->ext_refresh_last3_frame; - cpi->refresh_last4_frame = cpi->ext_refresh_last4_frame; + int ref_frame; + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) { + cpi->refresh_last_frames[ref_frame - LAST_FRAME] = + cpi->ext_refresh_last_frames[ref_frame - LAST_FRAME]; + } +#else + cpi->refresh_last_frame = cpi->ext_refresh_last_frame; #endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = cpi->ext_refresh_golden_frame; cpi->refresh_alt_ref_frame = cpi->ext_refresh_alt_ref_frame; @@ -3828,8 +3803,16 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, } // If the encoder forced a KEY_FRAME decision - if (cm->frame_type == KEY_FRAME) + if (cm->frame_type == KEY_FRAME) { +#if CONFIG_EXT_REFS + int ref_frame; + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) + cpi->refresh_last_frames[ref_frame - LAST_FRAME] = 1; + cpi->last_ref_to_refresh = LAST_FRAME; +#else cpi->refresh_last_frame = 1; +#endif // CONFIG_EXT_REFS + } cm->frame_to_show = get_frame_new_buffer(cm); cm->frame_to_show->color_space = cm->color_space; @@ -4045,11 +4028,13 @@ static int frame_is_reference(const VP10_COMP *cpi) { const VP10_COMMON *cm = &cpi->common; return cm->frame_type == KEY_FRAME || - cpi->refresh_last_frame || #if CONFIG_EXT_REFS - cpi->refresh_last2_frame || - cpi->refresh_last3_frame || - cpi->refresh_last4_frame || + cpi->refresh_last_frames[LAST_FRAME - LAST_FRAME] || + cpi->refresh_last_frames[LAST2_FRAME - LAST_FRAME] || + cpi->refresh_last_frames[LAST3_FRAME - LAST_FRAME] || + cpi->refresh_last_frames[LAST4_FRAME - LAST_FRAME] || +#else + cpi->refresh_last_frame || #endif // CONFIG_EXT_REFS cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame || @@ -4130,12 +4115,21 @@ static void check_src_altref(VP10_COMP *cpi, } if (rc->is_src_frame_alt_ref) { +#if CONFIG_EXT_REFS + int ref_frame; +#endif // CONFIG_EXT_REFS + // Current frame is an ARF overlay frame. cpi->alt_ref_source = NULL; // Don't refresh the last buffer for an ARF overlay frame. It will // become the GF so preserve last as an alternative prediction option. +#if CONFIG_EXT_REFS + for (ref_frame = LAST_FRAME; ref_frame <= LAST4_FRAME; ++ref_frame) + cpi->refresh_last_frames[ref_frame - LAST_FRAME] = 0; +#else cpi->refresh_last_frame = 0; +#endif // CONFIG_EXT_REFS } } @@ -4186,11 +4180,15 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, oxcf->frame_parallel_decoding_mode ? REFRESH_FRAME_CONTEXT_FORWARD : REFRESH_FRAME_CONTEXT_BACKWARD; - cpi->refresh_last_frame = 1; #if CONFIG_EXT_REFS - cpi->refresh_last2_frame = 0; - cpi->refresh_last3_frame = 0; - cpi->refresh_last4_frame = 0; + for (i = LAST_FRAME; i <= LAST4_FRAME; ++i) { + if (i == cpi->last_ref_to_refresh) + cpi->refresh_last_frames[i - LAST_FRAME] = 1; + else + cpi->refresh_last_frames[i - LAST_FRAME] = 0; + } +#else + cpi->refresh_last_frame = 1; #endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = 0; cpi->refresh_alt_ref_frame = 0; @@ -4215,17 +4213,15 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, cm->intra_only = 0; cpi->refresh_alt_ref_frame = 1; cpi->refresh_golden_frame = 0; - cpi->refresh_last_frame = 0; #if CONFIG_EXT_REFS - cpi->refresh_last2_frame = 0; - cpi->refresh_last3_frame = 0; - cpi->refresh_last4_frame = 0; + for (i = LAST_FRAME; i <= LAST4_FRAME; ++i) + cpi->refresh_last_frames[i - LAST_FRAME] = 0; +#else + cpi->refresh_last_frame = 0; #endif // CONFIG_EXT_REFS rc->is_src_frame_alt_ref = 0; - rc->source_alt_ref_pending = 0; - } else { - rc->source_alt_ref_pending = 0; } + rc->source_alt_ref_pending = 0; } if (!source) { diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index c45be4ce0..dc7374b1e 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -304,31 +304,32 @@ typedef struct VP10_COMP { // For a still frame, this flag is set to 1 to skip partition search. int partition_search_skippable_frame; +#if CONFIG_EXT_REFS + int last_ref_to_refresh; +#endif // CONFIG_EXT_REFS + int scaled_ref_idx[MAX_REF_FRAMES]; - int lst_fb_idx; #if CONFIG_EXT_REFS - int lst2_fb_idx; - int lst3_fb_idx; - int lst4_fb_idx; + int lst_fb_idxes[LAST_REF_FRAMES]; +#else + int lst_fb_idx; #endif // CONFIG_EXT_REFS int gld_fb_idx; int alt_fb_idx; - int refresh_last_frame; #if CONFIG_EXT_REFS - int refresh_last2_frame; - int refresh_last3_frame; - int refresh_last4_frame; + int refresh_last_frames[LAST_REF_FRAMES]; +#else + int refresh_last_frame; #endif // CONFIG_EXT_REFS int refresh_golden_frame; int refresh_alt_ref_frame; int ext_refresh_frame_flags_pending; - int ext_refresh_last_frame; #if CONFIG_EXT_REFS - int ext_refresh_last2_frame; - int ext_refresh_last3_frame; - int ext_refresh_last4_frame; + int ext_refresh_last_frames[LAST_REF_FRAMES]; +#else + int ext_refresh_last_frame; #endif // CONFIG_EXT_REFS int ext_refresh_golden_frame; int ext_refresh_alt_ref_frame; @@ -575,21 +576,17 @@ static INLINE int frame_is_kf_gf_arf(const VP10_COMP *cpi) { static INLINE int get_ref_frame_map_idx(const VP10_COMP *cpi, MV_REFERENCE_FRAME ref_frame) { - if (ref_frame == LAST_FRAME) { - return cpi->lst_fb_idx; #if CONFIG_EXT_REFS - } else if (ref_frame == LAST2_FRAME) { - return cpi->lst2_fb_idx; - } else if (ref_frame == LAST3_FRAME) { - return cpi->lst3_fb_idx; - } else if (ref_frame == LAST4_FRAME) { - return cpi->lst4_fb_idx; + if (ref_frame >= LAST_FRAME && ref_frame <= LAST4_FRAME) + return cpi->lst_fb_idxes[ref_frame - 1]; +#else + if (ref_frame == LAST_FRAME) + return cpi->lst_fb_idx; #endif // CONFIG_EXT_REFS - } else if (ref_frame == GOLDEN_FRAME) { + else if (ref_frame == GOLDEN_FRAME) return cpi->gld_fb_idx; - } else { + else return cpi->alt_fb_idx; - } } static INLINE int get_ref_frame_buf_idx(const VP10_COMP *const cpi, diff --git a/vp10/encoder/firstpass.c b/vp10/encoder/firstpass.c index c41fa3e39..c865408d7 100644 --- a/vp10/encoder/firstpass.c +++ b/vp10/encoder/firstpass.c @@ -1044,8 +1044,13 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) { ((twopass->this_frame_stats.intra_error / DOUBLE_DIVIDE_CHECK(twopass->this_frame_stats.coded_error)) > 2.0))) { if (gld_yv12 != NULL) { +#if CONFIG_EXT_REFS + ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx], + cm->ref_frame_map[cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]]); +#else ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx], cm->ref_frame_map[cpi->lst_fb_idx]); +#endif // CONFIG_EXT_REFS } twopass->sr_update_lag = 1; } else { @@ -1055,14 +1060,25 @@ void vp10_first_pass(VP10_COMP *cpi, const struct lookahead_entry *source) { vpx_extend_frame_borders(new_yv12); // The frame we just compressed now becomes the last frame. +#if CONFIG_EXT_REFS + ref_cnt_fb(pool->frame_bufs, + &cm->ref_frame_map[cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]], + cm->new_fb_idx); +#else ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx); +#endif // CONFIG_EXT_REFS // Special case for the first frame. Copy into the GF buffer as a second // reference. if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) { +#if CONFIG_EXT_REFS + ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx], + cm->ref_frame_map[cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]]); +#else ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx], cm->ref_frame_map[cpi->lst_fb_idx]); +#endif // CONFIG_EXT_REFS } // Use this to see what the first pass reconstruction looks like. @@ -2382,28 +2398,48 @@ static void configure_buffer_updates(VP10_COMP *cpi) { cpi->rc.is_src_frame_alt_ref = 0; switch (twopass->gf_group.update_type[twopass->gf_group.index]) { case KF_UPDATE: +#if CONFIG_EXT_REFS + cpi->refresh_last_frames[LAST_FRAME - LAST_FRAME] = 1; +#else cpi->refresh_last_frame = 1; +#endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = 1; cpi->refresh_alt_ref_frame = 1; break; case LF_UPDATE: +#if CONFIG_EXT_REFS + cpi->refresh_last_frames[LAST_FRAME - LAST_FRAME] = 1; +#else cpi->refresh_last_frame = 1; +#endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = 0; cpi->refresh_alt_ref_frame = 0; break; case GF_UPDATE: +#if CONFIG_EXT_REFS + cpi->refresh_last_frames[LAST_FRAME - LAST_FRAME] = 1; +#else cpi->refresh_last_frame = 1; +#endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = 1; cpi->refresh_alt_ref_frame = 0; break; case OVERLAY_UPDATE: +#if CONFIG_EXT_REFS + cpi->refresh_last_frames[LAST_FRAME - LAST_FRAME] = 0; +#else cpi->refresh_last_frame = 0; +#endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = 1; cpi->refresh_alt_ref_frame = 0; cpi->rc.is_src_frame_alt_ref = 1; break; case ARF_UPDATE: +#if CONFIG_EXT_REFS + cpi->refresh_last_frames[LAST_FRAME - LAST_FRAME] = 0; +#else cpi->refresh_last_frame = 0; +#endif // CONFIG_EXT_REFS cpi->refresh_golden_frame = 0; cpi->refresh_alt_ref_frame = 1; break; diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index c65021b4b..4e3bf053c 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -5126,20 +5126,6 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, if (mode_skip_mask[ref_frame] & (1 << this_mode)) continue; -#if CONFIG_EXT_REFS - if (cm->last_frame_type == KEY_FRAME && ref_frame == LAST2_FRAME) - continue; - - if ((cm->last2_frame_type == KEY_FRAME || - cm->last_frame_type == KEY_FRAME) && ref_frame == LAST3_FRAME) - continue; - - if ((cm->last3_frame_type == KEY_FRAME || - cm->last2_frame_type == KEY_FRAME || - cm->last_frame_type == KEY_FRAME) && ref_frame == LAST4_FRAME) - continue; -#endif // CONFIG_EXT_REFS - // Test best rd so far against threshold for trying this mode. if (best_mode_skippable && sf->schedule_mode_search) mode_threshold[mode_index] <<= 1; @@ -5889,20 +5875,6 @@ void vp10_rd_pick_inter_mode_sub8x8(VP10_COMP *cpi, ref_frame = vp10_ref_order[ref_index].ref_frame[0]; second_ref_frame = vp10_ref_order[ref_index].ref_frame[1]; -#if CONFIG_EXT_REFS - if (cm->last_frame_type == KEY_FRAME && ref_frame == LAST2_FRAME) - continue; - - if ((cm->last2_frame_type == KEY_FRAME || - cm->last_frame_type == KEY_FRAME) && ref_frame == LAST3_FRAME) - continue; - - if ((cm->last3_frame_type == KEY_FRAME || - cm->last2_frame_type == KEY_FRAME || - cm->last_frame_type == KEY_FRAME) && ref_frame == LAST4_FRAME) - continue; -#endif // CONFIG_EXT_REFS - // Look at the reference frame of the best mode so far and set the // skip mask to look at a subset of the remaining modes. if (ref_index > 2 && sf->mode_skip_start < MAX_MODES) {