[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;