Add encoder support for multi-layer GF 16
Currently the use of the new multi-layer GF group of 16 is guarded by
the macro USE_GF16_MULTI_LAYER, which is turned off. Hence this CL
does not change any of the encoder behavior.
Change-Id: I588cd34e19388337a2ecb0a0cb3f796a37647e24
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index f6864cc..ad8d8f4 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3649,10 +3649,31 @@
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
}
-static int get_refresh_mask(AV1_COMP *cpi) {
+#if CONFIG_EXT_REFS
+#if USE_GF16_MULTI_LAYER
+static int get_refresh_mask_gf16(AV1_COMP *cpi) {
int refresh_mask = 0;
+ if (cpi->refresh_last_frame || cpi->refresh_golden_frame ||
+ cpi->refresh_bwd_ref_frame || cpi->refresh_alt2_ref_frame ||
+ cpi->refresh_alt_ref_frame) {
+ assert(cpi->refresh_fb_idx >= 0 && cpi->refresh_fb_idx < REF_FRAMES);
+ refresh_mask |= (1 << cpi->refresh_fb_idx);
+ }
+
+ return refresh_mask;
+}
+#endif // USE_GF16_MULTI_LAYER
+#endif // CONFIG_EXT_REFS
+
+static int get_refresh_mask(AV1_COMP *cpi) {
#if CONFIG_EXT_REFS
+#if USE_GF16_MULTI_LAYER
+ if (cpi->rc.baseline_gf_interval == 16) return get_refresh_mask_gf16(cpi);
+#endif // USE_GF16_MULTI_LAYER
+
+ int refresh_mask = 0;
+
// NOTE(zoeliu): When LAST_FRAME is to get refreshed, the decoder will be
// notified to get LAST3_FRAME refreshed and then the virtual indexes for all
// the 3 LAST reference frames will be updated accordingly, i.e.:
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 512a461..1176dcb 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -989,6 +989,7 @@
cpi->bwd_fb_idx = LAST_REF_FRAMES + 1;
cpi->alt2_fb_idx = LAST_REF_FRAMES + 2;
cpi->alt_fb_idx = LAST_REF_FRAMES + 3;
+ cpi->ext_fb_idx = LAST_REF_FRAMES + 4;
for (fb_idx = 0; fb_idx < MAX_EXT_ARFS + 1; ++fb_idx)
cpi->arf_map[fb_idx] = LAST_REF_FRAMES + 2 + fb_idx;
#else // !CONFIG_EXT_REFS
@@ -3101,7 +3102,53 @@
#endif
#if CONFIG_EXT_REFS && !CONFIG_XIPHRC
+#if USE_GF16_MULTI_LAYER
+static void check_show_existing_frame_gf16(AV1_COMP *cpi) {
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ AV1_COMMON *const cm = &cpi->common;
+ const FRAME_UPDATE_TYPE next_frame_update_type =
+ gf_group->update_type[gf_group->index];
+
+ if (cm->show_existing_frame == 1) {
+ cm->show_existing_frame = 0;
+ } else if (cpi->rc.is_last_bipred_frame) {
+ cpi->rc.is_last_bipred_frame = 0;
+ cm->show_existing_frame = 1;
+ cpi->existing_fb_idx_to_show = cpi->bwd_fb_idx;
+ } else if (next_frame_update_type == OVERLAY_UPDATE ||
+ next_frame_update_type == INTNL_OVERLAY_UPDATE) {
+ // Check the temporal filtering status for the next OVERLAY frame
+ const int num_arfs_in_gf = cpi->num_extra_arfs + 1;
+ int which_arf = 0, arf_idx;
+ // Identify the index to the next overlay frame.
+ for (arf_idx = 0; arf_idx < num_arfs_in_gf; arf_idx++) {
+ if (gf_group->index == cpi->arf_pos_for_ovrly[arf_idx]) {
+ which_arf = arf_idx;
+ break;
+ }
+ }
+ assert(arf_idx < num_arfs_in_gf);
+ if (cpi->is_arf_filter_off[which_arf]) {
+ cm->show_existing_frame = 1;
+ cpi->rc.is_src_frame_alt_ref = 1;
+ cpi->existing_fb_idx_to_show = (next_frame_update_type == OVERLAY_UPDATE)
+ ? cpi->alt_fb_idx
+ : cpi->bwd_fb_idx;
+ cpi->is_arf_filter_off[which_arf] = 0;
+ }
+ }
+ cpi->rc.is_src_frame_ext_arf = 0;
+}
+#endif // USE_GF16_MULTI_LAYER
+
static void check_show_existing_frame(AV1_COMP *cpi) {
+#if USE_GF16_MULTI_LAYER
+ if (cpi->rc.baseline_gf_interval == 16) {
+ check_show_existing_frame_gf16(cpi);
+ return;
+ }
+#endif // USE_GF16_MULTI_LAYER
+
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
AV1_COMMON *const cm = &cpi->common;
const FRAME_UPDATE_TYPE next_frame_update_type =
@@ -3111,9 +3158,9 @@
if (cm->show_existing_frame == 1) {
cm->show_existing_frame = 0;
} else 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
+ // NOTE: 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];
@@ -3351,14 +3398,69 @@
}
#endif // CONFIG_VAR_REFS
-static void update_reference_frames(AV1_COMP *cpi) {
+#if CONFIG_EXT_REFS
+#if USE_GF16_MULTI_LAYER
+static void update_reference_frames_gf16(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
BufferPool *const pool = cm->buffer_pool;
+ if (cm->frame_type == KEY_FRAME) {
+ for (int ref_frame = 0; ref_frame < LAST_REF_FRAMES; ++ref_frame) {
+ ref_cnt_fb(pool->frame_bufs,
+ &cm->ref_frame_map[cpi->lst_fb_idxes[ref_frame]],
+ cm->new_fb_idx);
+ }
+ ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
+ cm->new_fb_idx);
+ ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->bwd_fb_idx],
+ cm->new_fb_idx);
+ ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->alt2_fb_idx],
+ cm->new_fb_idx);
+ ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->alt_fb_idx],
+ cm->new_fb_idx);
+ } else {
+ if (cpi->refresh_last_frame || cpi->refresh_golden_frame ||
+ cpi->refresh_bwd_ref_frame || cpi->refresh_alt2_ref_frame ||
+ cpi->refresh_alt_ref_frame) {
+ assert(cpi->refresh_fb_idx >= 0 && cpi->refresh_fb_idx < REF_FRAMES);
+ ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->refresh_fb_idx],
+ cm->new_fb_idx);
+ }
+
+ // TODO(zoeliu): To handle cpi->interp_filter_selected[].
+
+ // For GF of 16, an additional ref frame index mapping needs to be handled
+ // if this is the last frame to encode in the current GF group.
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ if (gf_group->update_type[gf_group->index + 1] == OVERLAY_UPDATE)
+ av1_ref_frame_map_idx_updates(cpi, gf_group->index + 1);
+ }
+
+#if DUMP_REF_FRAME_IMAGES == 1
+ // Dump out all reference frame images.
+ dump_ref_frame_images(cpi);
+#endif // DUMP_REF_FRAME_IMAGES
+}
+#endif // USE_GF16_MULTI_LAYER
+#endif // CONFIG_EXT_REFS
+
+static void update_reference_frames(AV1_COMP *cpi) {
+ AV1_COMMON *const cm = &cpi->common;
+
// NOTE: Save the new show frame buffer index for --test-code=warn, i.e.,
// for the purpose to verify no mismatch between encoder and decoder.
if (cm->show_frame) cpi->last_show_frame_buf_idx = cm->new_fb_idx;
+#if CONFIG_EXT_REFS
+#if USE_GF16_MULTI_LAYER
+ if (cpi->rc.baseline_gf_interval == 16) {
+ update_reference_frames_gf16(cpi);
+ return;
+ }
+#endif // USE_GF16_MULTI_LAYER
+#endif // CONFIG_EXT_REFS
+
+ BufferPool *const pool = cm->buffer_pool;
// At this point the new frame has been encoded.
// If any buffer copy / swapping is signaled it should be done here.
if (cm->frame_type == KEY_FRAME) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 8792b22..b26c241 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -414,6 +414,10 @@
int alt2_fb_idx; // ALTREF2_FRAME
#endif // CONFIG_EXT_REFS
int alt_fb_idx;
+#if CONFIG_EXT_REFS
+ int ext_fb_idx; // extra ref frame buffer index
+ int refresh_fb_idx; // ref frame buffer index to refresh
+#endif // CONFIG_EXT_REFS
int last_show_frame_buf_idx; // last show frame buffer index
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index daa626b..dc90480 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1700,8 +1700,8 @@
LAST_FRAME, // cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]
LAST2_FRAME, // cpi->lst_fb_idxes[LAST2_FRAME - LAST_FRAME]
LAST3_FRAME, // cpi->lst_fb_idxes[LAST3_FRAME - LAST_FRAME]
- BWDREF_FRAME, // cpi->bwd_fb_idx (BWDREF_FRAME)
GOLDEN_FRAME, // cpi->gld_fb_idx (GOLDEN_FRAME)
+ BWDREF_FRAME, // cpi->bwd_fb_idx (BWDREF_FRAME)
ALTREF2_FRAME, // cpi->alt2_fb_idx (ALTREF2_FRAME)
ALTREF_FRAME, // cpi->alt_fb_idx (ALTREF_FRAME)
REF_FRAMES, // cpi->ext_fb_idx (extra ref frame)
@@ -2116,6 +2116,7 @@
}
};
+// === GF Group of 16 ===
static void define_gf_group_structure_16(AV1_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
TWO_PASS *const twopass = &cpi->twopass;
@@ -2138,13 +2139,26 @@
// Treat KEY_FRAME differently
if (frame_index == 0 && key_frame) {
gf_group->update_type[frame_index] = KF_UPDATE;
+
gf_group->rf_level[frame_index] = KF_STD;
+ gf_group->arf_src_offset[frame_index] = 0;
+ gf_group->brf_src_offset[frame_index] = 0;
+ gf_group->bidir_pred_enabled[frame_index] = 0;
+ for (int ref_idx = 0; ref_idx < REF_FRAMES; ++ref_idx)
+ gf_group->ref_fb_idx_map[frame_index][ref_idx] = ref_idx;
+ gf_group->refresh_idx[frame_index] =
+ cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME];
+ gf_group->refresh_flag[frame_index] =
+ cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME];
+
continue;
}
+ // == update_type ==
gf_group->update_type[frame_index] =
gf16_multi_layer_params[frame_index][param_idx++];
+ // == rf_level ==
// Derive rf_level from update_type
switch (gf_group->update_type[frame_index]) {
case LF_UPDATE: gf_group->rf_level[frame_index] = INTER_NORMAL; break;
@@ -2166,20 +2180,71 @@
default: gf_group->rf_level[frame_index] = INTER_NORMAL; break;
}
+ // == arf_src_offset ==
gf_group->arf_src_offset[frame_index] =
gf16_multi_layer_params[frame_index][param_idx++];
+
+ // == brf_src_offset ==
gf_group->brf_src_offset[frame_index] =
gf16_multi_layer_params[frame_index][param_idx++];
+ // == bidir_pred_enabled ==
+ // Derive bidir_pred_enabled from bidir_src_offset
+ gf_group->bidir_pred_enabled[frame_index] =
+ gf_group->brf_src_offset[frame_index] ? 1 : 0;
+
+ // == ref_fb_idx_map ==
for (int ref_idx = 0; ref_idx < REF_FRAMES; ++ref_idx)
gf_group->ref_fb_idx_map[frame_index][ref_idx] =
gf16_multi_layer_params[frame_index][param_idx++];
+ // == refresh_idx ==
gf_group->refresh_idx[frame_index] =
gf16_multi_layer_params[frame_index][param_idx++];
+
+ // == refresh_flag ==
gf_group->refresh_flag[frame_index] =
gf16_multi_layer_params[frame_index][param_idx];
}
+
+ // Mark the ARF_UPDATE / INTNL_ARF_UPDATE and OVERLAY_UPDATE /
+ // INTNL_OVERLAY_UPDATE for rate allocation
+ // NOTE: Indexes are designed in the display order backward:
+ // ALT[3] .. ALT[2] .. ALT[1] .. ALT[0],
+ // but their coding order is as follows:
+ // ALT0-ALT2-ALT3 .. OVERLAY3 .. OVERLAY2-ALT1 .. OVERLAY1 .. OVERLAY0
+
+ const int num_arfs_in_gf = cpi->num_extra_arfs + 1;
+ const int sub_arf_interval = rc->baseline_gf_interval / num_arfs_in_gf;
+
+ // == arf_pos_for_ovrly ==: Position for OVERLAY
+ for (int arf_idx = 0; arf_idx < num_arfs_in_gf; arf_idx++) {
+ const int prior_num_arfs =
+ (arf_idx <= 1) ? num_arfs_in_gf : (num_arfs_in_gf - 1);
+ cpi->arf_pos_for_ovrly[arf_idx] =
+ sub_arf_interval * (num_arfs_in_gf - arf_idx) + prior_num_arfs;
+ }
+
+ // == arf_pos_in_gf ==: Position for ALTREF
+ cpi->arf_pos_in_gf[0] = 1;
+ cpi->arf_pos_in_gf[1] = cpi->arf_pos_for_ovrly[2] + 1;
+ cpi->arf_pos_in_gf[2] = 2;
+ cpi->arf_pos_in_gf[3] = 3;
+
+ // == arf_update_idx ==
+ // == arf_ref_idx ==
+ // NOTE: Due to the hierarchical nature of GF16, these two parameters only
+ // relect the index to the nearest future overlay.
+ int start_frame_index = 0;
+ for (int arf_idx = (num_arfs_in_gf - 1); arf_idx >= 0; --arf_idx) {
+ const int end_frame_index = cpi->arf_pos_for_ovrly[arf_idx];
+ for (int frame_index = start_frame_index; frame_index <= end_frame_index;
+ ++frame_index) {
+ gf_group->arf_update_idx[frame_index] = arf_idx;
+ gf_group->arf_ref_idx[frame_index] = arf_idx;
+ }
+ start_frame_index = end_frame_index + 1;
+ }
}
#endif // USE_GF16_MULTI_LAYER
#endif // CONFIG_EXT_REFS
@@ -2191,31 +2256,6 @@
#if USE_GF16_MULTI_LAYER
if (rc->baseline_gf_interval == 16) {
define_gf_group_structure_16(cpi);
-
- // Mark the ARF_UPDATE / INTNL_ARF_UPDATE and OVERLAY_UPDATE /
- // INTNL_OVERLAY_UPDATE for rate allocation
- // NOTE: Indexes are designed in the display order backward:
- // ALT[3] .. ALT[2] .. ALT[1] .. ALT[0],
- // but their coding order is as follows:
- // ALT0-ALT2-ALT3 .. OVERLAY3 .. OVERLAY2-ALT1 .. OVERLAY1 .. OVERLAY0
-
- const int num_arfs_in_gf = cpi->num_extra_arfs + 1;
- const int sub_arf_interval = rc->baseline_gf_interval / num_arfs_in_gf;
-
- // arf_pos_for_ovrly[]: Position for OVERLAY
- for (int arf_idx = 0; arf_idx < num_arfs_in_gf; arf_idx++) {
- const int prior_num_arfs =
- (arf_idx <= 1) ? num_arfs_in_gf : (num_arfs_in_gf - 1);
- cpi->arf_pos_for_ovrly[arf_idx] =
- sub_arf_interval * (num_arfs_in_gf - arf_idx) + prior_num_arfs;
- }
-
- // arf_pos_in_gf[]: Position for ALTREF
- cpi->arf_pos_in_gf[0] = 1;
- cpi->arf_pos_in_gf[1] = cpi->arf_pos_for_ovrly[2] + 1;
- cpi->arf_pos_in_gf[2] = 2;
- cpi->arf_pos_in_gf[3] = 3;
-
return;
}
#endif // USE_GF16_MULTI_LAYER
@@ -2223,7 +2263,6 @@
TWO_PASS *const twopass = &cpi->twopass;
GF_GROUP *const gf_group = &twopass->gf_group;
-
int i;
int frame_index = 0;
const int key_frame = cpi->common.frame_type == KEY_FRAME;
@@ -3385,6 +3424,153 @@
twopass->modified_error_left -= kf_group_err;
}
+#if USE_GF16_MULTI_LAYER
+// === GF Group of 16 ===
+void av1_ref_frame_map_idx_updates(AV1_COMP *cpi, int gf_frame_index) {
+ TWO_PASS *const twopass = &cpi->twopass;
+ GF_GROUP *const gf_group = &twopass->gf_group;
+
+ int ref_fb_idx_prev[REF_FRAMES];
+ int ref_fb_idx_curr[REF_FRAMES];
+
+ ref_fb_idx_prev[LAST_FRAME - LAST_FRAME] =
+ cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME];
+ ref_fb_idx_prev[LAST2_FRAME - LAST_FRAME] =
+ cpi->lst_fb_idxes[LAST2_FRAME - LAST_FRAME];
+ ref_fb_idx_prev[LAST3_FRAME - LAST_FRAME] =
+ cpi->lst_fb_idxes[LAST3_FRAME - LAST_FRAME];
+ ref_fb_idx_prev[GOLDEN_FRAME - LAST_FRAME] = cpi->gld_fb_idx;
+ ref_fb_idx_prev[BWDREF_FRAME - LAST_FRAME] = cpi->bwd_fb_idx;
+ ref_fb_idx_prev[ALTREF2_FRAME - LAST_FRAME] = cpi->alt2_fb_idx;
+ ref_fb_idx_prev[ALTREF_FRAME - LAST_FRAME] = cpi->alt_fb_idx;
+ ref_fb_idx_prev[REF_FRAMES - LAST_FRAME] = cpi->ext_fb_idx;
+
+ // Update map index for each reference frame
+ for (int ref_idx = 0; ref_idx < REF_FRAMES; ++ref_idx) {
+ int ref_frame = gf_group->ref_fb_idx_map[gf_frame_index][ref_idx];
+ ref_fb_idx_curr[ref_idx] = ref_fb_idx_prev[ref_frame - LAST_FRAME];
+ }
+
+ cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME] =
+ ref_fb_idx_curr[LAST_FRAME - LAST_FRAME];
+ cpi->lst_fb_idxes[LAST2_FRAME - LAST_FRAME] =
+ ref_fb_idx_curr[LAST2_FRAME - LAST_FRAME];
+ cpi->lst_fb_idxes[LAST3_FRAME - LAST_FRAME] =
+ ref_fb_idx_curr[LAST3_FRAME - LAST_FRAME];
+ cpi->gld_fb_idx = ref_fb_idx_curr[GOLDEN_FRAME - LAST_FRAME];
+ cpi->bwd_fb_idx = ref_fb_idx_curr[BWDREF_FRAME - LAST_FRAME];
+ cpi->alt2_fb_idx = ref_fb_idx_curr[ALTREF2_FRAME - LAST_FRAME];
+ cpi->alt_fb_idx = ref_fb_idx_curr[ALTREF_FRAME - LAST_FRAME];
+ cpi->ext_fb_idx = ref_fb_idx_curr[REF_FRAMES - LAST_FRAME];
+}
+
+// Define the reference buffers that will be updated post encode.
+static void configure_buffer_updates_16(AV1_COMP *cpi) {
+ TWO_PASS *const twopass = &cpi->twopass;
+ GF_GROUP *const gf_group = &twopass->gf_group;
+
+ if (gf_group->update_type[gf_group->index] == KF_UPDATE) {
+ cpi->refresh_fb_idx = 0;
+
+ 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;
+
+ return;
+ }
+
+ // Update reference frame map indexes
+ av1_ref_frame_map_idx_updates(cpi, gf_group->index);
+
+ // Update refresh index
+ switch (gf_group->refresh_idx[gf_group->index]) {
+ case LAST_FRAME:
+ cpi->refresh_fb_idx = cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME];
+ break;
+
+ case LAST2_FRAME:
+ cpi->refresh_fb_idx = cpi->lst_fb_idxes[LAST2_FRAME - LAST_FRAME];
+ break;
+
+ case LAST3_FRAME:
+ cpi->refresh_fb_idx = cpi->lst_fb_idxes[LAST3_FRAME - LAST_FRAME];
+ break;
+
+ case GOLDEN_FRAME: cpi->refresh_fb_idx = cpi->gld_fb_idx; break;
+
+ case BWDREF_FRAME: cpi->refresh_fb_idx = cpi->bwd_fb_idx; break;
+
+ case ALTREF2_FRAME: cpi->refresh_fb_idx = cpi->alt2_fb_idx; break;
+
+ case ALTREF_FRAME: cpi->refresh_fb_idx = cpi->alt_fb_idx; break;
+
+ case REF_FRAMES: cpi->refresh_fb_idx = cpi->ext_fb_idx; break;
+
+ default: assert(0); break;
+ }
+
+ // Update refresh flags
+ switch (gf_group->refresh_flag[gf_group->index]) {
+ case LAST_FRAME:
+ 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 GOLDEN_FRAME:
+ 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;
+ break;
+
+ case BWDREF_FRAME:
+ 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;
+ break;
+
+ case ALTREF2_FRAME:
+ 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;
+
+ case ALTREF_FRAME:
+ cpi->refresh_last_frame = 0;
+ cpi->refresh_golden_frame = 0;
+ cpi->refresh_bwd_ref_frame = 0;
+ cpi->refresh_alt2_ref_frame = 0;
+ cpi->refresh_alt_ref_frame = 1;
+ break;
+
+ default: assert(0); break;
+ }
+
+ switch (gf_group->update_type[gf_group->index]) {
+ case BRF_UPDATE: cpi->rc.is_bwd_ref_frame = 1; break;
+
+ case LAST_BIPRED_UPDATE: cpi->rc.is_last_bipred_frame = 1; break;
+
+ case BIPRED_UPDATE: cpi->rc.is_bipred_frame = 1; break;
+
+ case INTNL_OVERLAY_UPDATE: cpi->rc.is_src_frame_ext_arf = 1;
+ case OVERLAY_UPDATE: cpi->rc.is_src_frame_alt_ref = 1; break;
+
+ default: break;
+ }
+}
+#endif // USE_GF16_MULTI_LAYER
+
// Define the reference buffers that will be updated post encode.
static void configure_buffer_updates(AV1_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass;
@@ -3398,6 +3584,14 @@
cpi->rc.is_last_bipred_frame = 0;
cpi->rc.is_bipred_frame = 0;
cpi->rc.is_src_frame_ext_arf = 0;
+
+#if USE_GF16_MULTI_LAYER
+ RATE_CONTROL *const rc = &cpi->rc;
+ if (rc->baseline_gf_interval == 16) {
+ configure_buffer_updates_16(cpi);
+ return;
+ }
+#endif // USE_GF16_MULTI_LAYER
#endif // CONFIG_EXT_REFS
switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index 7c948a5..9ac542b 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -199,6 +199,10 @@
void av1_twopass_postencode_update(struct AV1_COMP *cpi);
#if CONFIG_EXT_REFS
+#if USE_GF16_MULTI_LAYER
+void av1_ref_frame_map_idx_updates(struct AV1_COMP *cpi, int gf_frame_index);
+#endif // USE_GF16_MULTI_LAYER
+
static INLINE int get_number_of_extra_arfs(int interval, int arf_pending) {
if (arf_pending && MAX_EXT_ARFS > 0)
return interval >= MIN_EXT_ARF_INTERVAL * (MAX_EXT_ARFS + 1)
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index f9304ae..5c1fa32 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -652,14 +652,29 @@
strength = 0;
frames_to_blur = 1;
}
-#endif // CONFIG_EXT_REFS
-#if CONFIG_EXT_REFS
- if (strength == 0 && frames_to_blur == 1) {
- cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 1;
- } else {
- cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 0;
+ int which_arf = gf_group->arf_update_idx[gf_group->index];
+
+#if USE_GF16_MULTI_LAYER
+ if (cpi->rc.baseline_gf_interval == 16) {
+ // Identify the index to the current ARF.
+ const int num_arfs_in_gf = cpi->num_extra_arfs + 1;
+ int arf_idx;
+ for (arf_idx = 0; arf_idx < num_arfs_in_gf; arf_idx++) {
+ if (gf_group->index == cpi->arf_pos_in_gf[arf_idx]) {
+ which_arf = arf_idx;
+ break;
+ }
+ }
+ assert(arf_idx < num_arfs_in_gf);
}
+#endif // USE_GF16_MULTI_LAYER
+
+ // Set the temporal filtering status for the corresponding OVERLAY frame
+ if (strength == 0 && frames_to_blur == 1)
+ cpi->is_arf_filter_off[which_arf] = 1;
+ else
+ cpi->is_arf_filter_off[which_arf] = 0;
#endif // CONFIG_EXT_REFS
frames_to_blur_backward = (frames_to_blur / 2);