[NORMATIVE] Check primary_ref_frame in more places
There are a few cases where we should treat frames with
primary_ref_frame == PRIMARY_REF_NONE the same way as intra-only
and/or error-resilient frames, even if the frame of interest
is neither intra-only nor error resilient.
Note, however, that they shouldn't be treated the same in all cases.
This patch changes the following cases:
* Always signal segmentation map + features when using PRIMARY_REF_NONE
* Call setup_past_independence() when using PRIMARY_REF_NONE, so that
we don't accidentally depend on old data. This should be equivalent
to the old behaviour, but makes it less likely to miss anything
in future.
* Simplify some code using the fact that, once cm->prev_frame has
been set up, the following are all equivalent:
"cm->prev_frame == NULL";
"cm->primary_ref_frame == PRIMARY_REF_NONE";
"cm->error_resilient_mode || cm->intra_only ||
[primary_ref_frame explicitly signalled as PRIMARY_REF_NONE]"
Change-Id: If8e417a11040ba8a4ad58fc6e37d985a94533d68
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 89ae7ed..adcfc40 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -838,7 +838,7 @@
cm->last_frame_seg_map = NULL;
}
// Read update flags
- if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+ if (cm->primary_ref_frame == PRIMARY_REF_NONE) {
// These frames can't use previous frames, so must signal map + features
seg->update_map = 1;
seg->temporal_update = 0;
@@ -2407,9 +2407,8 @@
static void read_global_motion(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
for (int frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
const WarpedMotionParams *ref_params =
- (cm->error_resilient_mode || cm->prev_frame == NULL)
- ? &default_warp_params
- : &cm->prev_frame->global_motion[frame];
+ cm->prev_frame ? &cm->prev_frame->global_motion[frame]
+ : &default_warp_params;
int good_params = read_global_motion_params(
&cm->global_motion[frame], ref_params, rb, cm->allow_high_precision_mv);
if (!good_params) {
@@ -2913,13 +2912,11 @@
}
cm->prev_frame = get_prev_frame(cm);
- if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) {
- if (cm->primary_ref_frame != PRIMARY_REF_NONE &&
- cm->frame_refs[cm->primary_ref_frame].idx < 0) {
- aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
- "Reference frame containing this frame's initial "
- "frame context is unavailable.");
- }
+ if (cm->primary_ref_frame != PRIMARY_REF_NONE &&
+ cm->frame_refs[cm->primary_ref_frame].idx < 0) {
+ aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
+ "Reference frame containing this frame's initial "
+ "frame context is unavailable.");
}
if (!cm->intra_only && pbi->need_resync != 1) {
@@ -3029,16 +3026,9 @@
setup_quantization(cm, rb);
xd->bd = (int)cm->bit_depth;
- if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+
+ if (cm->primary_ref_frame == PRIMARY_REF_NONE) {
av1_setup_past_independence(cm);
- av1_setup_frame_contexts(cm);
- } else if (cm->primary_ref_frame == PRIMARY_REF_NONE) {
- // The default coefficient CDFs depend on base_qindex. So, in order to
- // ensure that we don't depend on the frame decoding order, we explicitly
- // reset the coefficient CDFs with the value of base_qindex for this frame.
- *cm->fc = cm->frame_contexts[FRAME_CONTEXT_DEFAULTS];
- av1_default_coef_probs(cm);
- cm->frame_contexts[FRAME_CONTEXT_DEFAULTS] = *cm->fc;
}
setup_segmentation(cm, rb);
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 89a9150..ff1dcb0 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2121,7 +2121,7 @@
if (!seg->enabled) return;
// Write update flags
- if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+ if (cm->primary_ref_frame == PRIMARY_REF_NONE) {
assert(seg->update_map == 1);
seg->temporal_update = 0;
assert(seg->update_data == 1);
@@ -2882,9 +2882,8 @@
int frame;
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
const WarpedMotionParams *ref_params =
- (cm->error_resilient_mode || cm->prev_frame == NULL)
- ? &default_warp_params
- : &cm->prev_frame->global_motion[frame];
+ cm->prev_frame ? &cm->prev_frame->global_motion[frame]
+ : &default_warp_params;
write_global_motion_params(&cm->global_motion[frame], ref_params, wb,
cm->allow_high_precision_mv);
// TODO(sarahparker, debargha): The logic in the commented out code below
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index cfe6984..0442786 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4253,9 +4253,8 @@
int pframe;
cm->global_motion[frame] = default_warp_params;
const WarpedMotionParams *ref_params =
- (cm->error_resilient_mode || cm->prev_frame == NULL)
- ? &default_warp_params
- : &cm->prev_frame->global_motion[frame];
+ cm->prev_frame ? &cm->prev_frame->global_motion[frame]
+ : &default_warp_params;
// check for duplicate buffer
for (pframe = LAST_FRAME; pframe < frame; ++pframe) {
if (ref_buf[frame] == ref_buf[pframe]) break;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 0f86b6b..f639a01 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -349,10 +349,9 @@
} else {
if (cm->primary_ref_frame == PRIMARY_REF_NONE ||
cm->frame_refs[cm->primary_ref_frame].idx < 0) {
- *cm->fc = cm->frame_contexts[FRAME_CONTEXT_DEFAULTS];
- // Ensure the coefficient CDFs are correct
- av1_default_coef_probs(cm);
- cm->frame_contexts[FRAME_CONTEXT_DEFAULTS] = *cm->fc;
+ av1_setup_past_independence(cm);
+ cm->seg.update_map = 1;
+ cm->seg.update_data = 1;
cm->pre_fc = &cm->frame_contexts[FRAME_CONTEXT_DEFAULTS];
} else {
*cm->fc = cm->frame_contexts[cm->frame_refs[cm->primary_ref_frame].idx];
@@ -4407,14 +4406,10 @@
// Base q-index may have changed, so we need to assign proper default coef
// probs before every iteration.
- if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+ if (cm->primary_ref_frame == PRIMARY_REF_NONE ||
+ cm->frame_refs[cm->primary_ref_frame].idx < 0) {
av1_default_coef_probs(cm);
av1_setup_frame_contexts(cm);
- } else if (cm->primary_ref_frame == PRIMARY_REF_NONE ||
- cm->frame_refs[cm->primary_ref_frame].idx < 0) {
- *cm->fc = cm->frame_contexts[FRAME_CONTEXT_DEFAULTS];
- av1_default_coef_probs(cm);
- cm->frame_contexts[FRAME_CONTEXT_DEFAULTS] = *cm->fc;
}
// Variance adaptive and in frame q adjustment experiments are mutually
diff --git a/av1/encoder/segmentation.c b/av1/encoder/segmentation.c
index dfc2e3d..7014fb6 100644
--- a/av1/encoder/segmentation.c
+++ b/av1/encoder/segmentation.c
@@ -211,8 +211,8 @@
for (int i = 0; i < MAX_SEGMENTS; ++i)
no_pred_cost += no_pred_segcounts[i] * seg_id_cost[i];
- // Key frames cannot use temporal prediction
- if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
+ // Frames without past dependency cannot use temporal prediction
+ if (cm->primary_ref_frame != PRIMARY_REF_NONE) {
int pred_flag_cost[SEG_TEMPORAL_PRED_CTXS][2];
for (int i = 0; i < SEG_TEMPORAL_PRED_CTXS; ++i)
av1_cost_tokens_from_cdf(pred_flag_cost[i], segp->pred_cdf[i], NULL);