Change reference buffer update rules when new gf struture used In the new gf structure, backward reference frames are always coded in reverse order (i.e. farthest frames will be coded first). Whenever a backward reference is coded, we first shift the reference frames as follows: BWDREF -> ALTREF2-> EXT_REF, and then have BWDREF refreshed by the newly coded frame. When an overlay frame to be shown, we display the frame stored in BWDREF and shift the reference as follow: BWDREF <- ALT2REF <- EXT_REF, so that BWDREF points the next backward reference frame to be shown. Change-Id: Ie615fb4e7c1e4f1a3440468b2e6525f3540d9783
diff --git a/av1/common/enums.h b/av1/common/enums.h index eee3a8a..689c25f 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h
@@ -557,6 +557,7 @@ #define BWDREF_FRAME 5 #define ALTREF2_FRAME 6 #define ALTREF_FRAME 7 +#define EXTREF_FRAME REF_FRAMES #define LAST_REF_FRAMES (LAST3_FRAME - LAST_FRAME + 1) #define INTER_REFS_PER_FRAME (ALTREF_FRAME - LAST_FRAME + 1)
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index 131a670..fce370f 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -2258,9 +2258,15 @@ // LAST3_FRAME. refresh_mask |= (cpi->refresh_last_frame << cpi->ref_fb_idx[LAST_REF_FRAMES - 1]); - +#if SHIFT_BWDREF_BUF + refresh_mask |= + (cpi->new_bwdref_update_rule == 1) + ? (cpi->refresh_bwd_ref_frame << cpi->ref_fb_idx[EXTREF_FRAME - 1]) + : (cpi->refresh_bwd_ref_frame << cpi->ref_fb_idx[BWDREF_FRAME - 1]); +#else refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->ref_fb_idx[BWDREF_FRAME - 1]); +#endif refresh_mask |= (cpi->refresh_alt2_ref_frame << cpi->ref_fb_idx[ALTREF2_FRAME - 1]);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 5d97730..a4dbda7 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -3311,6 +3311,48 @@ } } +#if SHIFT_BWDREF_BUF +// This function is used to shift the virtual indices of bwd reference +// frames as follows: +// BWD_REF -> ALT2_REF -> EXT_REF +// to clear a space to store the closest bwdref +static INLINE void rshift_bwd_ref_frames(AV1_COMP *cpi) { + // TODO(isbs): shift the scaled indices as well + static const int ordered_bwd[3] = { BWDREF_FRAME - 1, ALTREF2_FRAME - 1, + EXTREF_FRAME - 1 }; + + for (int i = 2; i > 0; --i) { + cpi->ref_fb_idx[ordered_bwd[i]] = cpi->ref_fb_idx[ordered_bwd[i - 1]]; + + // [0] is allocated to the current coded frame, i.e. bwdref + memcpy( + cpi->interp_filter_selected[ordered_bwd[i] + LAST_FRAME], + cpi->interp_filter_selected[ordered_bwd[i - 1] + LAST_FRAME], + sizeof(cpi->interp_filter_selected[ordered_bwd[i - 1] + LAST_FRAME])); + } +} + +// This function is used to shift the virtual indices of bwd reference +// frames as follows: +// BWD_REF <- ALT2_REF <- EXT_REF +// to update the bwd reference frame for coding the next frame. +static INLINE void lshift_bwd_ref_frames(AV1_COMP *cpi) { + // TODO(isbs): shift the scaled indices as well + static const int ordered_bwd[3] = { BWDREF_FRAME - 1, ALTREF2_FRAME - 1, + EXTREF_FRAME - 1 }; + + for (int i = 0; i < 2; ++i) { + cpi->ref_fb_idx[ordered_bwd[i]] = cpi->ref_fb_idx[ordered_bwd[i + 1]]; + + // [0] is allocated to the current coded frame, i.e. bwdref + memcpy( + cpi->interp_filter_selected[ordered_bwd[i] + LAST_FRAME], + cpi->interp_filter_selected[ordered_bwd[i + 1] + LAST_FRAME], + sizeof(cpi->interp_filter_selected[ordered_bwd[i + 1] + LAST_FRAME])); + } +} +#endif // SHIFT_BWDREF_BUF + #if USE_GF16_MULTI_LAYER static void update_reference_frames_gf16(AV1_COMP *cpi) { AV1_COMMON *const cm = &cpi->common; @@ -3415,11 +3457,22 @@ shift_last_ref_frames(cpi); cpi->ref_fb_idx[LAST_FRAME - 1] = cpi->ref_fb_idx[bwdref_to_show - 1]; - cpi->ref_fb_idx[bwdref_to_show - 1] = tmp; memcpy(cpi->interp_filter_selected[LAST_FRAME], cpi->interp_filter_selected[bwdref_to_show], sizeof(cpi->interp_filter_selected[bwdref_to_show])); +#if SHIFT_BWDREF_BUF + if (cpi->new_bwdref_update_rule == 1) { + lshift_bwd_ref_frames(cpi); + // pass outdated forward reference frame (previous LAST3) to the + // spared space + cpi->ref_fb_idx[EXTREF_FRAME - 1] = tmp; + } else { +#endif + cpi->ref_fb_idx[bwdref_to_show - 1] = tmp; +#if SHIFT_BWDREF_BUF + } +#endif } else { /* For non key/golden frames */ // === ALTREF_FRAME === if (cpi->refresh_alt_ref_frame) { @@ -3444,10 +3497,25 @@ // === BWDREF_FRAME === if (cpi->refresh_bwd_ref_frame) { - ref_cnt_fb(pool->frame_bufs, - &cm->ref_frame_map[cpi->ref_fb_idx[BWDREF_FRAME - 1]], - cm->new_fb_idx); +#if SHIFT_BWDREF_BUF + if (cpi->new_bwdref_update_rule) { + // We shift the backward reference frame as follows: + // BWDREF -> ALTREF2 -> EXTREF + // and assign the newly coded frame to BWDREF so that it always + // keeps the nearest future frame + int tmp = cpi->ref_fb_idx[EXTREF_FRAME - 1]; + ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[tmp], cm->new_fb_idx); + rshift_bwd_ref_frames(cpi); + cpi->ref_fb_idx[BWDREF_FRAME - 1] = tmp; + } else { +#endif // SHIFT_BWDREF_BUF + ref_cnt_fb(pool->frame_bufs, + &cm->ref_frame_map[cpi->ref_fb_idx[BWDREF_FRAME - 1]], + cm->new_fb_idx); +#if SHIFT_BWDREF_BUF + } +#endif memcpy(cpi->interp_filter_selected[BWDREF_FRAME], cpi->interp_filter_selected[0], sizeof(cpi->interp_filter_selected[0]));
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index ece73fd..b3a33fd 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -36,8 +36,10 @@ #if USE_SYMM_MULTI_LAYER #define MATCH_OLD_BITRATE 1 +#define SHIFT_BWDREF_BUF 1 #else #define MATCH_OLD_BITRATE 0 +#define SHIFT_BWDREF_BUF 0 #endif #define MIN_GF_INTERVAL 4