Clean-up fb_of_context_type/frame_context_idx
* Move AV1_COMMON.fb_of_context_type[] to AV1_COMP
* Move assignments of fb_of_context_type[] from bitstream to
finalize_encoded_frame()
* Move the derivation of cm->frame_context_idx to a function
get_current_frame_ref_type() and use this as a getter instead
* Move show_existing_frame assignment of cm->cur_frame from bitstream to
finalize_encoded_frame()
This forms part of wider restructuring and refactoring in order to
achieve a clean API separation at the entry to the low-level encoder.
BUG=aomedia:2244
Change-Id: I827ef697d44055c588f9e2da7aaea843dce49319
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 2836160..870a7ad 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -367,6 +367,30 @@
return BLOCK_128X128;
}
+static int get_current_frame_ref_type(const AV1_COMP *const cpi) {
+ const AV1_COMMON *const cm = &cpi->common;
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ // We choose the reference "type" of this frame from the flags which indicate
+ // which reference frames will be refreshed by it. More than one of these
+ // flags may be set, so the order here implies an order of precedence.
+
+ if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
+ cm->force_primary_ref_none)
+ return REGULAR_FRAME;
+ else if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE)
+ return EXT_ARF_FRAME;
+ else if (cpi->refresh_alt_ref_frame)
+ return ARF_FRAME;
+ else if (cpi->rc.is_src_frame_alt_ref)
+ return OVERLAY_FRAME;
+ else if (cpi->refresh_golden_frame)
+ return GLD_FRAME;
+ else if (cpi->refresh_bwd_ref_frame)
+ return BRF_FRAME;
+ else
+ return REGULAR_FRAME;
+}
+
static void setup_frame(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
// Set up entropy context depending on frame type. The decoder mandates
@@ -380,27 +404,13 @@
cm->force_primary_ref_none) {
av1_setup_past_independence(cm);
for (int i = 0; i < REF_FRAMES; i++) {
- cm->fb_of_context_type[i] = -1;
+ cpi->fb_of_context_type[i] = -1;
}
- cm->fb_of_context_type[REGULAR_FRAME] =
+ cpi->fb_of_context_type[REGULAR_FRAME] =
cm->show_frame ? get_ref_frame_map_idx(cm, GOLDEN_FRAME)
: get_ref_frame_map_idx(cm, ALTREF_FRAME);
- cm->frame_context_idx = REGULAR_FRAME;
} else {
- const GF_GROUP *gf_group = &cpi->twopass.gf_group;
- if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE)
- cm->frame_context_idx = EXT_ARF_FRAME;
- else if (cpi->refresh_alt_ref_frame)
- cm->frame_context_idx = ARF_FRAME;
- else if (cpi->rc.is_src_frame_alt_ref)
- cm->frame_context_idx = OVERLAY_FRAME;
- else if (cpi->refresh_golden_frame)
- cm->frame_context_idx = GLD_FRAME;
- else if (cpi->refresh_bwd_ref_frame)
- cm->frame_context_idx = BRF_FRAME;
- else
- cm->frame_context_idx = REGULAR_FRAME;
- int wanted_fb = cm->fb_of_context_type[cm->frame_context_idx];
+ int wanted_fb = cpi->fb_of_context_type[get_current_frame_ref_type(cpi)];
for (int ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
int fb = get_ref_frame_map_idx(cm, ref_frame);
if (fb == wanted_fb) {
@@ -4582,10 +4592,46 @@
static void finalize_encoded_frame(AV1_COMP *const cpi) {
AV1_COMMON *const cm = &cpi->common;
+ CurrentFrame *const current_frame = &cm->current_frame;
// This bitfield indicates which reference frame slots will be overwritten by
// the current frame
- cm->current_frame.refresh_frame_flags = get_refresh_frame_flags(cpi);
+ current_frame->refresh_frame_flags = get_refresh_frame_flags(cpi);
+
+ if (!encode_show_existing_frame(cm)) {
+ // Refresh fb_of_context_type[]: see encoder.h for explanation
+ if (current_frame->frame_type == KEY_FRAME) {
+ // All ref frames are refreshed, pick one that will live long enough
+ cpi->fb_of_context_type[REGULAR_FRAME] = 0;
+ } else {
+ // If more than one frame is refreshed, it doesn't matter which one we
+ // pick so pick the first. LST sometimes doesn't refresh any: this is ok
+ const int current_frame_ref_type = get_current_frame_ref_type(cpi);
+ for (int i = 0; i < REF_FRAMES; i++) {
+ if (current_frame->refresh_frame_flags & (1 << i)) {
+ cpi->fb_of_context_type[current_frame_ref_type] = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!cm->seq_params.reduced_still_picture_hdr &&
+ encode_show_existing_frame(cm)) {
+ RefCntBuffer *const frame_to_show =
+ cm->ref_frame_map[cpi->existing_fb_idx_to_show];
+
+ if (frame_to_show == NULL || frame_to_show->ref_count < 1) {
+ aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
+ "Buffer does not contain a reconstructed frame");
+ }
+ assign_frame_buffer_p(&cm->cur_frame, frame_to_show);
+ if (cm->reset_decoder_state && frame_to_show->frame_type != KEY_FRAME) {
+ aom_internal_error(
+ &cm->error, AOM_CODEC_UNSUP_BITSTREAM,
+ "show_existing_frame to reset state on KEY_FRAME only");
+ }
+ }
}
static int encode_with_recode_loop(AV1_COMP *cpi, size_t *size, uint8_t *dest) {