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/common/onyxc_int.h b/av1/common/onyxc_int.h
index c114148..5a785f7 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -500,8 +500,6 @@
FRAME_CONTEXT *fc; /* this frame entropy */
FRAME_CONTEXT *default_frame_context;
- unsigned int frame_context_idx; /* Context to use/update */
- int fb_of_context_type[REF_FRAMES];
int primary_ref_frame;
int error_resilient_mode;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 1e6dd16..a19069e 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2832,15 +2832,6 @@
}
if (!seq_params->reduced_still_picture_hdr) {
if (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);
-
aom_wb_write_bit(wb, 1); // show_existing_frame
aom_wb_write_literal(wb, cpi->existing_fb_idx_to_show, 3);
@@ -2853,13 +2844,6 @@
int display_frame_id = cm->ref_frame_id[cpi->existing_fb_idx_to_show];
aom_wb_write_literal(wb, display_frame_id, frame_id_len);
}
-
- 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");
- }
-
return;
} else {
aom_wb_write_bit(wb, 0); // show_existing_frame
@@ -2967,18 +2951,6 @@
current_frame->frame_type == INTRA_ONLY_FRAME)
aom_wb_write_literal(wb, current_frame->refresh_frame_flags, REF_FRAMES);
- // For non-keyframes, we need to update the buffer of reference frame ids.
- // 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
- if (current_frame->frame_type != KEY_FRAME) {
- for (int i = 0; i < REF_FRAMES; i++) {
- if (current_frame->refresh_frame_flags & (1 << i)) {
- cm->fb_of_context_type[cm->frame_context_idx] = i;
- break;
- }
- }
- }
-
if (!frame_is_intra_only(cm) || current_frame->refresh_frame_flags != 0xff) {
// Write all ref frame order hints if error_resilient_mode == 1
if (cm->error_resilient_mode &&
@@ -2996,8 +2968,6 @@
assert(!av1_superres_scaled(cm) || !cm->allow_intrabc);
if (cm->allow_screen_content_tools && !av1_superres_scaled(cm))
aom_wb_write_bit(wb, cm->allow_intrabc);
- // all eight fbs are refreshed, pick one that will live long enough
- cm->fb_of_context_type[REGULAR_FRAME] = 0;
} else {
if (current_frame->frame_type == INTRA_ONLY_FRAME) {
write_frame_size(cm, frame_size_override_flag, wb);
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) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 29cb51a..d33695b 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -637,6 +637,12 @@
int refresh_alt2_ref_frame;
int refresh_alt_ref_frame;
+ // For each type of reference frame, this contains the index of a reference
+ // frame buffer for a reference frame of the same type. We use this to
+ // choose our primary reference frame (which is the most recent reference
+ // frame of the same type as the current frame).
+ int fb_of_context_type[REF_FRAMES];
+
#if USE_SYMM_MULTI_LAYER
// When true, a new rule for backward (future) reference frames is in effect:
// - BWDREF_FRAME is always the closest future frame available