[Normative] Move global loopfilter info to ref buf
Let loop filer ref_delta, mode_deltas, sharpness_level
associated with corresponding reference buffer, such
that for error resilient frame or droppable frame, the
decoder could correctly decode contexts.
BUG=aomedia:1581
BUG=aomedia:1588
Change-Id: I3c297ec2b36b32c89b8ac783348c23d57d27d4d0
diff --git a/av1/common/av1_loopfilter.c b/av1/common/av1_loopfilter.c
index 7fe907a..1a5cb1b 100644
--- a/av1/common/av1_loopfilter.c
+++ b/av1/common/av1_loopfilter.c
@@ -655,7 +655,6 @@
// init limits for given sharpness
update_sharpness(lfi, lf->sharpness_level);
- lf->last_sharpness_level = lf->sharpness_level;
// init hev threshold const vectors
for (lvl = 0; lvl <= MAX_LOOP_FILTER; lvl++)
@@ -672,11 +671,8 @@
struct loopfilter *const lf = &cm->lf;
const struct segmentation *const seg = &cm->seg;
- // update limits if sharpness has changed
- if (lf->last_sharpness_level != lf->sharpness_level) {
- update_sharpness(lfi, lf->sharpness_level);
- lf->last_sharpness_level = lf->sharpness_level;
- }
+ // update sharpness limits
+ update_sharpness(lfi, lf->sharpness_level);
for (seg_id = 0; seg_id < MAX_SEGMENTS; seg_id++) {
for (int dir = 0; dir < 2; ++dir) {
diff --git a/av1/common/av1_loopfilter.h b/av1/common/av1_loopfilter.h
index f811129..dbd0795 100644
--- a/av1/common/av1_loopfilter.h
+++ b/av1/common/av1_loopfilter.h
@@ -27,8 +27,6 @@
#define SIMD_WIDTH 16
-#define MAX_MODE_LF_DELTAS 2
-
enum lf_path {
LF_PATH_420,
LF_PATH_444,
@@ -122,7 +120,6 @@
int filter_level_v;
int sharpness_level;
- int last_sharpness_level;
uint8_t mode_ref_delta_enabled;
uint8_t mode_ref_delta_update;
@@ -130,11 +127,9 @@
// 0 = Intra, Last, Last2+Last3,
// GF, BRF, ARF2, ARF
int8_t ref_deltas[TOTAL_REFS_PER_FRAME];
- int8_t last_ref_deltas[TOTAL_REFS_PER_FRAME];
// 0 = ZERO_MV, MV
int8_t mode_deltas[MAX_MODE_LF_DELTAS];
- int8_t last_mode_deltas[MAX_MODE_LF_DELTAS];
#if LOOP_FILTER_BITMASK
LoopFilterMask *lfm;
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index fe44290..9f876a8 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -1144,24 +1144,32 @@
av1_copy(fc->intrabc_cdf, default_intrabc_cdf);
}
+void av1_set_default_ref_deltas(int8_t *ref_deltas) {
+ assert(ref_deltas != NULL);
+
+ ref_deltas[INTRA_FRAME] = 1;
+ ref_deltas[LAST_FRAME] = 0;
+ ref_deltas[LAST2_FRAME] = ref_deltas[LAST_FRAME];
+ ref_deltas[LAST3_FRAME] = ref_deltas[LAST_FRAME];
+ ref_deltas[BWDREF_FRAME] = ref_deltas[LAST_FRAME];
+ ref_deltas[GOLDEN_FRAME] = -1;
+ ref_deltas[ALTREF2_FRAME] = -1;
+ ref_deltas[ALTREF_FRAME] = -1;
+}
+
+void av1_set_default_mode_deltas(int8_t *mode_deltas) {
+ assert(mode_deltas != NULL);
+
+ mode_deltas[0] = 0;
+ mode_deltas[0] = 0;
+}
+
static void set_default_lf_deltas(struct loopfilter *lf) {
lf->mode_ref_delta_enabled = 1;
lf->mode_ref_delta_update = 1;
- lf->ref_deltas[INTRA_FRAME] = 1;
- lf->ref_deltas[LAST_FRAME] = 0;
- lf->ref_deltas[LAST2_FRAME] = lf->ref_deltas[LAST_FRAME];
- lf->ref_deltas[LAST3_FRAME] = lf->ref_deltas[LAST_FRAME];
- lf->ref_deltas[BWDREF_FRAME] = lf->ref_deltas[LAST_FRAME];
- lf->ref_deltas[GOLDEN_FRAME] = -1;
- lf->ref_deltas[ALTREF2_FRAME] = -1;
- lf->ref_deltas[ALTREF_FRAME] = -1;
-
- lf->mode_deltas[0] = 0;
- lf->mode_deltas[1] = 0;
-
- av1_copy(lf->last_ref_deltas, lf->ref_deltas);
- av1_copy(lf->last_mode_deltas, lf->mode_deltas);
+ av1_set_default_ref_deltas(lf->ref_deltas);
+ av1_set_default_mode_deltas(lf->mode_deltas);
}
void av1_setup_frame_contexts(AV1_COMMON *cm) {
@@ -1176,8 +1184,6 @@
void av1_setup_past_independence(AV1_COMMON *cm) {
// Reset the segment feature data to the default stats:
// Features disabled, 0, with delta coding (Default state).
- struct loopfilter *const lf = &cm->lf;
-
av1_clearall_segfeatures(&cm->seg);
cm->current_frame_seg_map = cm->cur_frame->seg_map;
@@ -1185,13 +1191,12 @@
if (cm->current_frame_seg_map)
memset(cm->current_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
- // Reset the mode ref deltas for loop filter
- av1_zero(lf->last_ref_deltas);
- av1_zero(lf->last_mode_deltas);
- set_default_lf_deltas(lf);
-
- // To force update of the sharpness
- lf->last_sharpness_level = -1;
+ // reset mode ref deltas
+ av1_set_default_ref_deltas(cm->cur_frame->ref_deltas);
+ av1_set_default_mode_deltas(cm->cur_frame->mode_deltas);
+ cm->cur_frame->sharpness_level = -1;
+ cm->lf.sharpness_level = -1;
+ set_default_lf_deltas(&cm->lf);
av1_default_coef_probs(cm);
init_mode_probs(cm->fc);
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 0905516..53430c4 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -292,6 +292,8 @@
{ 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 4, 5, 3, 6, 7, 8 },
};
+void av1_set_default_ref_deltas(int8_t *ref_deltas);
+void av1_set_default_mode_deltas(int8_t *mode_deltas);
void av1_setup_frame_contexts(struct AV1Common *cm);
void av1_setup_past_independence(struct AV1Common *cm);
diff --git a/av1/common/enums.h b/av1/common/enums.h
index d2dc31f..400a238 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -78,6 +78,8 @@
#define II_WEDGE_IDX_ENTROPY_CODING 0
#endif
+#define MAX_MODE_LF_DELTAS 2
+
typedef enum COMPOUND_DIST_WEIGHT_MODE {
DIST,
} COMPOUND_DIST_WEIGHT_MODE;
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 5d99d5d..fe88c2d 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -154,6 +154,14 @@
// when the frame is fully decoded.
int row;
int col;
+
+ // Inter frame reference frame delta for loop filter
+ int8_t ref_deltas[TOTAL_REFS_PER_FRAME];
+
+ // 0 = ZERO_MV, MV
+ int8_t mode_deltas[MAX_MODE_LF_DELTAS];
+
+ int sharpness_level;
} RefCntBuffer;
typedef struct BufferPool {
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 280c1c3..4758b18 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1101,8 +1101,23 @@
static void setup_loopfilter(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
assert(!cm->all_lossless);
const int num_planes = av1_num_planes(cm);
- if (cm->allow_intrabc && NO_FILTER_FOR_IBC) return;
struct loopfilter *lf = &cm->lf;
+ if ((cm->allow_intrabc && NO_FILTER_FOR_IBC) || cm->all_lossless) {
+ // write default deltas to frame buffer
+ av1_set_default_ref_deltas(lf->ref_deltas);
+ av1_set_default_mode_deltas(lf->mode_deltas);
+ av1_set_default_ref_deltas(cm->cur_frame->ref_deltas);
+ av1_set_default_mode_deltas(cm->cur_frame->mode_deltas);
+ cm->cur_frame->sharpness_level = -1;
+ lf->sharpness_level = -1;
+ return;
+ }
+ if (cm->prev_frame) {
+ // write deltas to frame buffer
+ memcpy(lf->ref_deltas, cm->prev_frame->ref_deltas, TOTAL_REFS_PER_FRAME);
+ memcpy(lf->mode_deltas, cm->prev_frame->mode_deltas, MAX_MODE_LF_DELTAS);
+ lf->sharpness_level = cm->prev_frame->sharpness_level;
+ }
lf->filter_level[0] = aom_rb_read_literal(rb, 6);
lf->filter_level[1] = aom_rb_read_literal(rb, 6);
if (num_planes > 1) {
@@ -1130,6 +1145,11 @@
lf->mode_deltas[i] = aom_rb_read_inv_signed_literal(rb, 6);
}
}
+
+ // write deltas to frame buffer
+ cm->cur_frame->sharpness_level = lf->sharpness_level;
+ memcpy(cm->cur_frame->ref_deltas, lf->ref_deltas, TOTAL_REFS_PER_FRAME);
+ memcpy(cm->cur_frame->mode_deltas, lf->mode_deltas, MAX_MODE_LF_DELTAS);
}
static void setup_cdef(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
diff --git a/av1/decoder/dthread.c b/av1/decoder/dthread.c
index 20724ff..c186f46 100644
--- a/av1/decoder/dthread.c
+++ b/av1/decoder/dthread.c
@@ -176,7 +176,7 @@
memcpy(dst_cm->lf_info.lfthr, src_cm->lf_info.lfthr,
(MAX_LOOP_FILTER + 1) * sizeof(loop_filter_thresh));
- dst_cm->lf.last_sharpness_level = src_cm->lf.sharpness_level;
+ dst_cm->lf.sharpness_level = src_cm->lf.sharpness_level;
dst_cm->lf.filter_level[0] = src_cm->lf.filter_level[0];
dst_cm->lf.filter_level[1] = src_cm->lf.filter_level[1];
memcpy(dst_cm->lf.ref_deltas, src_cm->lf.ref_deltas, TOTAL_REFS_PER_FRAME);
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 5713d94..840b192 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2021,25 +2021,38 @@
if (lf->mode_ref_delta_enabled) {
aom_wb_write_bit(wb, lf->mode_ref_delta_update);
+
if (lf->mode_ref_delta_update) {
+ const int prime_idx = cm->primary_ref_frame;
+ const int buf_idx =
+ prime_idx == PRIMARY_REF_NONE ? -1 : cm->frame_refs[prime_idx].idx;
+ int8_t last_ref_deltas[TOTAL_REFS_PER_FRAME];
+ if (prime_idx == PRIMARY_REF_NONE || buf_idx < 0) {
+ av1_set_default_ref_deltas(last_ref_deltas);
+ } else {
+ memcpy(last_ref_deltas, cm->buffer_pool->frame_bufs[buf_idx].ref_deltas,
+ TOTAL_REFS_PER_FRAME);
+ }
for (i = 0; i < TOTAL_REFS_PER_FRAME; i++) {
const int delta = lf->ref_deltas[i];
- const int changed = delta != lf->last_ref_deltas[i];
+ const int changed = delta != last_ref_deltas[i];
aom_wb_write_bit(wb, changed);
- if (changed) {
- lf->last_ref_deltas[i] = delta;
- aom_wb_write_inv_signed_literal(wb, delta, 6);
- }
+ if (changed) aom_wb_write_inv_signed_literal(wb, delta, 6);
}
+ int8_t last_mode_deltas[MAX_MODE_LF_DELTAS];
+ if (prime_idx == PRIMARY_REF_NONE || buf_idx < 0) {
+ av1_set_default_mode_deltas(last_mode_deltas);
+ } else {
+ memcpy(last_mode_deltas,
+ cm->buffer_pool->frame_bufs[buf_idx].mode_deltas,
+ MAX_MODE_LF_DELTAS);
+ }
for (i = 0; i < MAX_MODE_LF_DELTAS; i++) {
const int delta = lf->mode_deltas[i];
- const int changed = delta != lf->last_mode_deltas[i];
+ const int changed = delta != last_mode_deltas[i];
aom_wb_write_bit(wb, changed);
- if (changed) {
- lf->last_mode_deltas[i] = delta;
- aom_wb_write_inv_signed_literal(wb, delta, 6);
- }
+ if (changed) aom_wb_write_inv_signed_literal(wb, delta, 6);
}
}
}
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 4b1e80c..29dba41 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4222,6 +4222,25 @@
else
cm->last_frame_seg_map = NULL;
cm->current_frame_seg_map = cm->cur_frame->seg_map;
+ if ((cm->allow_intrabc && NO_FILTER_FOR_IBC) || cm->all_lossless) {
+ cm->lf.sharpness_level = -1;
+ av1_set_default_ref_deltas(cm->lf.ref_deltas);
+ av1_set_default_mode_deltas(cm->lf.mode_deltas);
+ cm->lf.mode_ref_delta_enabled = 1;
+ cm->lf.mode_ref_delta_update = 1;
+ } else if (cm->prev_frame) {
+ cm->lf.sharpness_level = cm->prev_frame->sharpness_level;
+ memcpy(cm->lf.ref_deltas, cm->prev_frame->ref_deltas, TOTAL_REFS_PER_FRAME);
+ memcpy(cm->lf.mode_deltas, cm->prev_frame->mode_deltas, MAX_MODE_LF_DELTAS);
+ cm->lf.mode_ref_delta_enabled = 1;
+ cm->lf.mode_ref_delta_update = 1;
+ } else {
+ cm->lf.mode_ref_delta_enabled = 0;
+ cm->lf.mode_ref_delta_update = 0;
+ }
+ cm->cur_frame->sharpness_level = cm->lf.sharpness_level;
+ memcpy(cm->cur_frame->ref_deltas, cm->lf.ref_deltas, TOTAL_REFS_PER_FRAME);
+ memcpy(cm->cur_frame->mode_deltas, cm->lf.mode_deltas, MAX_MODE_LF_DELTAS);
// Special case: set prev_mi to NULL when the previous mode info
// context cannot be used.
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 6cb6528..f0299c3 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -354,12 +354,6 @@
cm->prev_frame = get_prev_frame(cm);
cpi->vaq_refresh = 0;
-
- if (cm->prev_frame)
- cm->last_frame_seg_map = cm->prev_frame->seg_map;
- else
- cm->last_frame_seg_map = NULL;
- cm->current_frame_seg_map = cm->cur_frame->seg_map;
}
static void enc_setup_mi(AV1_COMMON *cm) {
@@ -549,9 +543,6 @@
av1_copy(cc->nmv_costs, cpi->nmv_costs);
av1_copy(cc->nmv_costs_hp, cpi->nmv_costs_hp);
- av1_copy(cc->last_ref_lf_deltas, cm->lf.last_ref_deltas);
- av1_copy(cc->last_mode_lf_deltas, cm->lf.last_mode_deltas);
-
cc->fc = *cm->fc;
}
@@ -565,9 +556,6 @@
av1_copy(cpi->nmv_costs, cc->nmv_costs);
av1_copy(cpi->nmv_costs_hp, cc->nmv_costs_hp);
- av1_copy(cm->lf.last_ref_deltas, cc->last_ref_lf_deltas);
- av1_copy(cm->lf.last_mode_deltas, cc->last_mode_lf_deltas);
-
*cm->fc = cc->fc;
}
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 4f488ad..e882826 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -51,11 +51,6 @@
int nmv_costs[2][MV_VALS];
int nmv_costs_hp[2][MV_VALS];
- // 0 = Intra, Last, GF, ARF
- int8_t last_ref_lf_deltas[TOTAL_REFS_PER_FRAME];
- // 0 = ZERO_MV, MV
- int8_t last_mode_lf_deltas[MAX_MODE_LF_DELTAS];
-
FRAME_CONTEXT fc;
} CODING_CONTEXT;