Commit aff92d58 authored by Zoe Liu's avatar Zoe Liu

Make last_bipred_frame a reference frame

The frame marked as last_bipred at the encoder side is the frame right
before the source frame of BWDREF_FRAME, which was not used as a
reference. This CL is to add this type of frames to the reference frame
buffer and use them as reference for the coding of future frames. This
is a non-normative change.

A tiny gain is observed (lowres BDRate -0.016% in avg psnr). The main
target of this CL is to make it possible to have more flexible gf group
structure. For instance, LAST_BIPRED_UPDATE can be replaced by
LAST_UPDATE followed by an extra alt ref frame.

Change-Id: If3dbce0959bb468e95d01a1feca1dac6bfb91d36
parent 9bcff194
......@@ -3347,19 +3347,6 @@ void av1_update_reference_frames(AV1_COMP *cpi) {
// TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
// cpi->interp_filter_selected[GOLDEN_FRAME]?
#if CONFIG_EXT_REFS
} else if (cpi->rc.is_last_bipred_frame) {
// Refresh the LAST_FRAME with the BWDREF_FRAME and retire the LAST3_FRAME
// by updating the virtual indices. Note that the frame BWDREF_FRAME points
// to now should be retired, and it should not be used before refreshed.
int tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
shift_last_ref_frames(cpi);
cpi->lst_fb_idxes[0] = cpi->bwd_fb_idx;
cpi->bwd_fb_idx = tmp;
memcpy(cpi->interp_filter_selected[LAST_FRAME],
cpi->interp_filter_selected[BWDREF_FRAME],
sizeof(cpi->interp_filter_selected[BWDREF_FRAME]));
} else if (cpi->rc.is_src_frame_ext_arf && cm->show_existing_frame) {
// Deal with the special case for showing existing internal ALTREF_FRAME
// Refresh the LAST_FRAME with the ALTREF_FRAME and retire the LAST3_FRAME
......@@ -3499,11 +3486,29 @@ void av1_update_reference_frames(AV1_COMP *cpi) {
cpi->lst_fb_idxes[0] = tmp;
assert(cm->show_existing_frame == 0);
// NOTE: Currently only LF_UPDATE and INTNL_OVERLAY_UPDATE frames are to
// refresh the LAST_FRAME.
memcpy(cpi->interp_filter_selected[LAST_FRAME],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
if (cpi->rc.is_last_bipred_frame) {
// Refresh the LAST_FRAME with the BWDREF_FRAME and retire the
// LAST3_FRAME by updating the virtual indices.
//
// NOTE: The source frame for BWDREF does not have a holding position as
// the OVERLAY frame for ALTREF's. Hence, to resolve the reference
// virtual index reshuffling for BWDREF, the encoder always
// specifies a LAST_BIPRED right before BWDREF and completes the
// reshuffling job accordingly.
tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
shift_last_ref_frames(cpi);
cpi->lst_fb_idxes[0] = cpi->bwd_fb_idx;
cpi->bwd_fb_idx = tmp;
memcpy(cpi->interp_filter_selected[LAST_FRAME],
cpi->interp_filter_selected[BWDREF_FRAME],
sizeof(cpi->interp_filter_selected[BWDREF_FRAME]));
}
}
#else
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
......
......@@ -2708,7 +2708,7 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
break;
case LAST_BIPRED_UPDATE:
cpi->refresh_last_frame = 0;
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
cpi->refresh_alt_ref_frame = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment