[NORMATIVE] New coded_lossless and all_lossless.
- 'coded_lossless' means that the frame is fully-lossless at the *coded*
resolution. When a 'coded_lossless' is on, loop filter and CDEF are
disabled.
- 'all_lossless' means that the frame is fully-lossless at the
*upscaled* resolution. 'all_lossless' implies 'coded_lossless', and
additionally, loop restoration and super-resolution are also disabled.
This changes the semantics, but no new bits are transmitted in the
bitstream.
BUG=aomedia:1646
Change-Id: If192dcf0c9230e9e202993317859a6aaa00483c7
diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c
index 9106070..fab30a7 100644
--- a/av1/common/alloccommon.c
+++ b/av1/common/alloccommon.c
@@ -145,7 +145,7 @@
static int alloc_loop_filter(AV1_COMMON *cm) {
aom_free(cm->lf.lfm);
cm->lf.lfm = NULL;
- if (cm->all_lossless) return 0;
+ if (cm->coded_lossless) return 0;
// Each lfm holds bit masks for all the 4x4 blocks in a max
// 64x64 (128x128 for ext_partitions) region. The stride
// and rows are rounded up / truncated to a multiple of 16
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 83beea7..adc81f1 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -446,7 +446,8 @@
struct loopfilter lf;
struct segmentation seg;
- int all_lossless;
+ int coded_lossless; // frame is fully lossless at the coded resolution.
+ int all_lossless; // frame is fully lossless at the upscaled resolution.
int reduced_tx_set_used;
@@ -1318,20 +1319,23 @@
seq_params->mib_size_log2 = mi_size_wide_log2[seq_params->sb_size];
}
-static INLINE int all_lossless(const AV1_COMMON *cm, const MACROBLOCKD *xd) {
- int i;
- int all_lossless = 1;
+// Returns true if the frame is fully lossless at the coded resolution.
+// Note: If super-resolution is used, such a frame will still NOT be lossless at
+// the upscaled resolution.
+static INLINE int is_coded_lossless(const AV1_COMMON *cm,
+ const MACROBLOCKD *xd) {
+ int coded_lossless = 1;
if (cm->seg.enabled) {
- for (i = 0; i < MAX_SEGMENTS; ++i) {
+ for (int i = 0; i < MAX_SEGMENTS; ++i) {
if (!xd->lossless[i]) {
- all_lossless = 0;
+ coded_lossless = 0;
break;
}
}
} else {
- all_lossless = xd->lossless[0];
+ coded_lossless = xd->lossless[0];
}
- return all_lossless;
+ return coded_lossless;
}
#ifdef __cplusplus
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index eeaddf8..b76e453 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -123,7 +123,7 @@
}
static TX_MODE read_tx_mode(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
- if (cm->all_lossless) return ONLY_4X4;
+ if (cm->coded_lossless) return ONLY_4X4;
return aom_rb_read_bit(rb) ? TX_MODE_SELECT : TX_MODE_LARGEST;
}
@@ -1117,13 +1117,13 @@
static void setup_loopfilter(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
const int num_planes = av1_num_planes(cm);
struct loopfilter *lf = &cm->lf;
- if ((cm->allow_intrabc && NO_FILTER_FOR_IBC) || cm->all_lossless) {
+ if ((cm->allow_intrabc && NO_FILTER_FOR_IBC) || cm->coded_lossless) {
// write default deltas to frame buffer
av1_set_default_ref_deltas(cm->cur_frame->ref_deltas);
av1_set_default_mode_deltas(cm->cur_frame->mode_deltas);
return;
}
- assert(!cm->all_lossless);
+ assert(!cm->coded_lossless);
if (cm->prev_frame) {
// write deltas to frame buffer
memcpy(lf->ref_deltas, cm->prev_frame->ref_deltas, TOTAL_REFS_PER_FRAME);
@@ -1582,8 +1582,8 @@
cm->rst_info[0].frame_restoration_type == RESTORE_NONE &&
cm->rst_info[1].frame_restoration_type == RESTORE_NONE &&
cm->rst_info[2].frame_restoration_type == RESTORE_NONE;
- assert(
- IMPLIES(cm->all_lossless, no_loopfilter && no_cdef && no_restoration));
+ assert(IMPLIES(cm->coded_lossless, no_loopfilter && no_cdef));
+ assert(IMPLIES(cm->all_lossless, no_restoration));
cm->single_tile_decoding = no_loopfilter && no_cdef && no_restoration;
// Read the tile width/height
if (cm->seq_params.sb_size == BLOCK_128X128) {
@@ -3097,26 +3097,28 @@
cm->v_dc_delta_q == 0 && cm->v_ac_delta_q == 0;
xd->qindex[i] = qindex;
}
- cm->all_lossless = all_lossless(cm, xd);
+ cm->coded_lossless = is_coded_lossless(cm, xd);
+ cm->all_lossless = cm->coded_lossless && av1_superres_unscaled(cm);
setup_segmentation_dequant(cm);
- if (cm->all_lossless) {
+ if (cm->coded_lossless) {
cm->lf.filter_level[0] = 0;
cm->lf.filter_level[1] = 0;
cm->cdef_bits = 0;
cm->cdef_strengths[0] = 0;
cm->cdef_uv_strengths[0] = 0;
+ }
+ if (cm->all_lossless) {
cm->rst_info[0].frame_restoration_type = RESTORE_NONE;
cm->rst_info[1].frame_restoration_type = RESTORE_NONE;
cm->rst_info[2].frame_restoration_type = RESTORE_NONE;
- if (!av1_superres_unscaled(cm)) {
- aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
- "Fully lossless frame cannot use super-resolution");
- }
+ assert(av1_superres_unscaled(cm));
}
setup_loopfilter(cm, rb);
- if (!cm->all_lossless) {
+ if (!cm->coded_lossless) {
setup_cdef(cm, rb);
+ }
+ if (!cm->all_lossless) {
decode_restoration_mode(cm, rb);
}
@@ -3214,6 +3216,7 @@
BufferPool *const pool = cm->buffer_pool;
if (av1_superres_unscaled(cm)) return;
+ assert(!cm->all_lossless);
lock_buffer_pool(pool);
av1_superres_upscale(cm, pool);
@@ -3374,7 +3377,7 @@
av1_loop_restoration_save_boundary_lines(&pbi->cur_buf->buf, cm, 0);
}
- if (!cm->skip_loop_filter && !cm->all_lossless &&
+ if (!cm->skip_loop_filter && !cm->coded_lossless &&
(cm->cdef_bits || cm->cdef_strengths[0] || cm->cdef_uv_strengths[0])) {
av1_cdef_frame(&pbi->cur_buf->buf, cm, &pbi->mb);
}
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 46f30e0..0d18a0c 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -38,7 +38,7 @@
static void read_cdef(AV1_COMMON *cm, aom_reader *r, MB_MODE_INFO *const mbmi,
int mi_col, int mi_row) {
- if (cm->all_lossless) return;
+ if (cm->coded_lossless) return;
if (cm->allow_intrabc && NO_FILTER_FOR_IBC) {
assert(cm->cdef_bits == 0);
return;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 3d21c75..e08891a 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -872,7 +872,7 @@
static void write_cdef(AV1_COMMON *cm, aom_writer *w, int skip, int mi_col,
int mi_row) {
- if (cm->all_lossless || (cm->allow_intrabc && NO_FILTER_FOR_IBC)) {
+ if (cm->coded_lossless || (cm->allow_intrabc && NO_FILTER_FOR_IBC)) {
// Initialize to indicate no CDEF for safety.
cm->cdef_bits = 0;
cm->cdef_strengths[0] = 0;
@@ -1989,7 +1989,7 @@
}
static void encode_loopfilter(AV1_COMMON *cm, struct aom_write_bit_buffer *wb) {
- assert(!cm->all_lossless);
+ assert(!cm->coded_lossless);
if (cm->allow_intrabc && NO_FILTER_FOR_IBC) return;
const int num_planes = av1_num_planes(cm);
int i;
@@ -2050,6 +2050,7 @@
}
static void encode_cdef(const AV1_COMMON *cm, struct aom_write_bit_buffer *wb) {
+ assert(!cm->coded_lossless);
if (cm->allow_intrabc && NO_FILTER_FOR_IBC) return;
const int num_planes = av1_num_planes(cm);
int i;
@@ -2153,7 +2154,7 @@
static void write_tx_mode(AV1_COMMON *cm, TX_MODE *mode,
struct aom_write_bit_buffer *wb) {
- if (cm->all_lossless) {
+ if (cm->coded_lossless) {
*mode = ONLY_4X4;
return;
}
@@ -3242,8 +3243,10 @@
if (cm->all_lossless) {
assert(av1_superres_unscaled(cm));
} else {
- encode_loopfilter(cm, wb);
- encode_cdef(cm, wb);
+ if (!cm->coded_lossless) {
+ encode_loopfilter(cm, wb);
+ encode_cdef(cm, wb);
+ }
encode_restoration_mode(cm, wb);
}
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 19ade46..eb885bf 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -3640,7 +3640,7 @@
}
static TX_MODE select_tx_mode(const AV1_COMP *cpi) {
- if (cpi->common.all_lossless) return ONLY_4X4;
+ if (cpi->common.coded_lossless) return ONLY_4X4;
if (cpi->sf.tx_size_search_method == USE_LARGESTALL)
return TX_MODE_LARGEST;
else if (cpi->sf.tx_size_search_method == USE_FULL_RD ||
@@ -4161,7 +4161,8 @@
cpi->optimize_seg_arr[i] = cpi->optimize_speed_feature;
}
}
- cm->all_lossless = all_lossless(cm, xd);
+ cm->coded_lossless = is_coded_lossless(cm, xd);
+ cm->all_lossless = cm->coded_lossless && av1_superres_unscaled(cm);
cm->tx_mode = select_tx_mode(cpi);
@@ -4192,7 +4193,7 @@
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) {
+ if ((cm->allow_intrabc && NO_FILTER_FOR_IBC) || cm->coded_lossless) {
av1_set_default_ref_deltas(cm->lf.ref_deltas);
av1_set_default_mode_deltas(cm->lf.mode_deltas);
} else if (cm->prev_frame) {
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index c955756..f256113 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3793,6 +3793,8 @@
// There has been a change in the encoded frame size
set_size_literal(cpi, width, height);
set_mv_search_params(cpi);
+ // Recalculate 'all_lossless' in case super-resolution was (un)selected.
+ cm->all_lossless = cm->coded_lossless && av1_superres_unscaled(cm);
}
if (cpi->oxcf.pass == 2) {
@@ -4040,6 +4042,7 @@
assert(cpi->oxcf.enable_superres);
assert(!is_lossless_requested(&cpi->oxcf));
+ assert(!cm->all_lossless);
av1_superres_upscale(cm, NULL);
@@ -4074,21 +4077,16 @@
const int num_planes = av1_num_planes(cm);
MACROBLOCKD *xd = &cpi->td.mb.e_mbd;
- assert(IMPLIES(is_lossless_requested(&cpi->oxcf), cm->all_lossless));
+ assert(IMPLIES(is_lossless_requested(&cpi->oxcf),
+ cm->coded_lossless && cm->all_lossless));
+
+ const int no_loopfilter = cm->coded_lossless || cm->large_scale_tile;
+ const int no_cdef =
+ !cpi->oxcf.using_cdef || cm->coded_lossless || cm->large_scale_tile;
+ const int no_restoration =
+ !cpi->oxcf.using_restoration || cm->all_lossless || cm->large_scale_tile;
struct loopfilter *lf = &cm->lf;
- int no_loopfilter = 0;
- int no_restoration = !cpi->oxcf.using_restoration;
-
- if (cm->all_lossless || cm->large_scale_tile) {
- no_loopfilter = 1;
- no_restoration = 1;
- }
-
- int no_cdef = 0;
- if (cm->all_lossless || !cpi->oxcf.using_cdef || cm->large_scale_tile) {
- no_cdef = 1;
- }
if (no_loopfilter) {
lf->filter_level[0] = 0;