[NORMATIVE, fwd-kf] Signal refresh_frame_flags for fwd keyframes Unlike shown keyframes, forward keyframes do not want to overwrite all of the reference slots immediately on decoding. This is so that we can use both the "previous" and "next" keyframes as references while decoding intermediate frames. To support this, we need to make two changes: * Non-shown keyframes should explicitly signal which reference slots to overwrite; * We shouldn't overwrite all of the frame context slots at the start of decoding a forward key frame (in av1_setup_frame_contexts()). Instead, we should only overwrite the special 'default' context, just as for intra-only or error-resilient frames. In fact, it seems that we don't need to overwrite all the frame contexts even for shown key frames, since we will update all of the reference slots to point to the correct frame context once we're finished decoding the frame anyway. BUG=aomedia:1509 Change-Id: I3a4e90a0b9dceab25f94312bd4ecc96ea016f624
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c index a2a542c..ae8dab0 100644 --- a/av1/common/entropymode.c +++ b/av1/common/entropymode.c
@@ -1186,21 +1186,16 @@ } void av1_setup_frame_contexts(AV1_COMMON *cm) { - int i; #if CONFIG_NO_FRAME_CONTEXT_SIGNALING - if (cm->frame_type == KEY_FRAME) { - // Reset all frame contexts, as all reference frames will be lost. - for (i = 0; i < FRAME_CONTEXTS; ++i) cm->frame_contexts[i] = *cm->fc; - } else if (frame_is_intra_only(cm) || cm->error_resilient_mode) { - // Store the frame context into a special slot (not associated with any - // reference buffer), so that we can set up cm->pre_fc correctly later - cm->frame_contexts[FRAME_CONTEXT_DEFAULTS] = *cm->fc; - } + assert(frame_is_intra_only(cm) || cm->error_resilient_mode); + // Store the frame context into a special slot (not associated with any + // reference buffer), so that we can set up cm->pre_fc correctly later + cm->frame_contexts[FRAME_CONTEXT_DEFAULTS] = *cm->fc; #else if (cm->frame_type == KEY_FRAME || cm->error_resilient_mode || cm->reset_frame_context == RESET_FRAME_CONTEXT_ALL) { // Reset all frame contexts. - for (i = 0; i < FRAME_CONTEXTS; ++i) cm->frame_contexts[i] = *cm->fc; + for (int i = 0; i < FRAME_CONTEXTS; ++i) cm->frame_contexts[i] = *cm->fc; } else if (cm->reset_frame_context == RESET_FRAME_CONTEXT_CURRENT) { // Reset only the frame context specified in the frame header. cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index efbffec..0071fc5 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -2778,7 +2778,12 @@ if (cm->frame_type == KEY_FRAME) { wrap_around_current_video_frame(pbi); - pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; +#if CONFIG_FWD_KF + if (!cm->show_frame) // unshown keyframe (forward keyframe) + pbi->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES); + else // shown keyframe +#endif // CONFIG_FWD_KF + pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) { cm->frame_refs[i].idx = INVALID_IDX;