Add new experiment: frame_context_signaling.
This stores frame contexts alongside a reference frame, and always
uses the frame in reference slot 0 (LAST_FRAME) as the source of
the frame context.
The encoder could then reorder reference frames as to control
which frame context is used, however currently it does not.
Low Latency AWCY result:
PSNR | PSNR Cb | PSNR Cr | PSNR HVS | SSIM | MS SSIM | CIEDE 2000
-0.1438 | 0.4161 | N/A | 0.0386 | -0.0281 | 0.0453 | 0.2514
https://arewecompressedyet.com/?job=before-frame-context-signaling%402017-06-07T23%3A20%3A49.473Z&job=after-frame-context-signaling%402017-06-07T23%3A21%3A36.117Z
Change-Id: I4f6f9b12cb403573efbf9e5c3077d62f5dedc467
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index a4a060b..e07e006 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -296,6 +296,10 @@
if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
av1_setup_past_independence(cm);
} else {
+#if CONFIG_NO_FRAME_CONTEXT_SIGNALING
+// Just use frame context from first signaled reference frame.
+// This will always be LAST_FRAME for now.
+#else
#if CONFIG_EXT_REFS
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
if (gf_group->rf_level[gf_group->index] == GF_ARF_LOW)
@@ -315,6 +319,7 @@
#endif // CONFIG_EXT_REFS
else
cm->frame_context_idx = REGULAR_FRAME;
+#endif // CONFIG_NO_FRAME_CONTEXT_SIGNALING
}
if (cm->frame_type == KEY_FRAME) {
@@ -322,7 +327,16 @@
cpi->refresh_alt_ref_frame = 1;
av1_zero(cpi->interp_filter_selected);
} else {
+#if CONFIG_NO_FRAME_CONTEXT_SIGNALING
+ if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
+ cm->frame_refs[0].idx < 0) {
+ *cm->fc = cm->frame_contexts[FRAME_CONTEXT_DEFAULTS];
+ } else {
+ *cm->fc = cm->frame_contexts[cm->frame_refs[0].idx];
+ }
+#else
*cm->fc = cm->frame_contexts[cm->frame_context_idx];
+#endif // CONFIG_NO_FRAME_CONTEXT_SIGNALING
av1_zero(cpi->interp_filter_selected[0]);
}
#if CONFIG_EXT_REFS
@@ -333,7 +347,16 @@
}
#endif
#endif
+#if CONFIG_NO_FRAME_CONTEXT_SIGNALING
+ if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+ // use default frame context values
+ cm->pre_fc = &cm->frame_contexts[FRAME_CONTEXT_DEFAULTS];
+ } else {
+ cm->pre_fc = &cm->frame_contexts[cm->frame_refs[0].idx];
+ }
+#else
cm->pre_fc = &cm->frame_contexts[cm->frame_context_idx];
+#endif // CONFIG_NO_FRAME_CONTEXT_SIGNALING
cpi->vaq_refresh = 0;
@@ -350,7 +373,6 @@
// Clear left border column
for (i = 1; i < cm->mi_rows + 1; ++i)
memset(&cm->prev_mip[i * cm->mi_stride], 0, sizeof(*cm->prev_mip));
-
cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1;
cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mi_stride + 1;
@@ -4164,7 +4186,13 @@
cm->reset_frame_context == RESET_FRAME_CONTEXT_ALL) {
for (i = 0; i < FRAME_CONTEXTS; ++i) cm->frame_contexts[i] = *cm->fc;
} else if (cm->reset_frame_context == RESET_FRAME_CONTEXT_CURRENT) {
+#if CONFIG_NO_FRAME_CONTEXT_SIGNALING
+ if (cm->frame_refs[0].idx >= 0) {
+ cm->frame_contexts[cm->frame_refs[0].idx] = *cm->fc;
+ }
+#else
cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
+#endif
}
}
#endif // CONFIG_Q_ADAPT_PROBS
@@ -5705,9 +5733,13 @@
Pass0Encode(cpi, size, dest, 0, frame_flags);
}
#endif
-
+#if CONFIG_NO_FRAME_CONTEXT_SIGNALING
+ // TODO(tdaede): Check if this condition is really needed.
+ if (!cm->error_resilient_mode) cm->frame_contexts[cm->new_fb_idx] = *cm->fc;
+#else
if (!cm->error_resilient_mode)
cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
+#endif // CONFIG_NO_FRAME_CONTEXT_SIGNALING
// No frame encoded, or frame was dropped, release scaled references.
if ((*size == 0) && (frame_is_intra_only(cm) == 0)) {