ext_tile: add 2 tile encoding modes

Added 2 tile encoding modes:
TILE_NORMAL mode supports the large-scale tile coding up to 1024 x 1024
tiles;
TILE_VR mode supports the large-scale tile coding and also the decoding
of a single tile.

TILE_NORMAL mode allows the non-vr content to be encoded in multiple tiles
without using the coding tool that are designed for vr applications.

Change-Id: Id804806a1bbcb916b7f5dc7e2c5509d88f3defcb
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 9896854..9526015 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -502,6 +502,15 @@
    * Experiment: LOOPFILTERING_ACROSS_TILES
    */
   AV1E_SET_TILE_LOOPFILTER,
+
+  /*!\brief Codec control function to set the tile encoding mode to 0 or 1.
+   *
+   * 0 means that the tile encoding mode is TILE_NORMAL, and 1 means that the
+   * tile encoding mode is TILE_VR.
+   *
+   * Experiment: EXT_TILE
+   */
+  AV1E_SET_TILE_ENCODING_MODE,
 };
 
 /*!\brief aom 1-D scaling mode
@@ -703,6 +712,9 @@
 
 AOM_CTRL_USE_TYPE(AV1E_SET_ANS_WINDOW_SIZE_LOG2, unsigned int)
 #define AOM_CTRL_AV1E_SET_ANS_WINDOW_SIZE_LOG2
+
+AOM_CTRL_USE_TYPE(AV1E_SET_TILE_ENCODING_MODE, unsigned int)
+#define AOM_CTRL_AV1E_SET_TILE_ENCODING_MODE
 /*!\endcond */
 /*! @} - end defgroup aom_encoder */
 #ifdef __cplusplus
diff --git a/aomenc.c b/aomenc.c
index fb43d09..c26d346 100644
--- a/aomenc.c
+++ b/aomenc.c
@@ -370,6 +370,12 @@
 static const arg_def_t tile_rows =
     ARG_DEF(NULL, "tile-rows", 1,
             "Number of tile rows to use, log2 (set to 0 while threads > 1)");
+#if CONFIG_EXT_TILE
+static const arg_def_t tile_encoding_mode =
+    ARG_DEF(NULL, "tile-encoding-mode", 1,
+            "Tile encoding mode (0: normal"
+            " (default), 1: vr)");
+#endif
 #if CONFIG_DEPENDENT_HORZTILES
 static const arg_def_t tile_dependent_rows =
     ARG_DEF(NULL, "tile-dependent-rows", 1, "Enable dependent Tile rows");
@@ -474,6 +480,9 @@
                                        &static_thresh,
                                        &tile_cols,
                                        &tile_rows,
+#if CONFIG_EXT_TILE
+                                       &tile_encoding_mode,
+#endif
 #if CONFIG_DEPENDENT_HORZTILES
                                        &tile_dependent_rows,
 #endif
@@ -522,6 +531,9 @@
                                         AOME_SET_STATIC_THRESHOLD,
                                         AV1E_SET_TILE_COLUMNS,
                                         AV1E_SET_TILE_ROWS,
+#if CONFIG_EXT_TILE
+                                        AV1E_SET_TILE_ENCODING_MODE,
+#endif
 #if CONFIG_DEPENDENT_HORZTILES
                                         AV1E_SET_TILE_DEPENDENT_ROWS,
 #endif
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 4ec146e..6389572 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -75,6 +75,9 @@
 #if CONFIG_ANS && ANS_MAX_SYMBOLS
   int ans_window_size_log2;
 #endif
+#if CONFIG_EXT_TILE
+  unsigned int tile_encoding_mode;
+#endif  // CONFIG_EXT_TILE
 };
 
 static struct av1_extracfg default_extra_cfg = {
@@ -134,6 +137,9 @@
 #if CONFIG_ANS && ANS_MAX_SYMBOLS
   23,  // ans_window_size_log2
 #endif
+#if CONFIG_EXT_TILE
+  0,    // Tile encoding mode is TILE_NORMAL by default.
+#endif  // CONFIG_EXT_TILE
 };
 
 struct aom_codec_alg_priv {
@@ -270,6 +276,7 @@
     if (extra_cfg->tile_rows != UINT_MAX)
       RANGE_CHECK(extra_cfg, tile_rows, 1, 64);
   }
+  RANGE_CHECK_HI(extra_cfg, tile_encoding_mode, 1);
 #else
   RANGE_CHECK_HI(extra_cfg, tile_columns, 6);
   RANGE_CHECK_HI(extra_cfg, tile_rows, 2);
@@ -520,6 +527,7 @@
 #endif  // CONFIG_EXT_PARTITION
     oxcf->tile_columns = AOMMIN(extra_cfg->tile_columns, max);
     oxcf->tile_rows = AOMMIN(extra_cfg->tile_rows, max);
+    oxcf->tile_encoding_mode = extra_cfg->tile_encoding_mode;
   }
 #else
   oxcf->tile_columns = extra_cfg->tile_columns;
@@ -822,6 +830,15 @@
   return update_extra_cfg(ctx, &extra_cfg);
 }
 
+#if CONFIG_EXT_TILE
+static aom_codec_err_t ctrl_set_tile_encoding_mode(aom_codec_alg_priv_t *ctx,
+                                                   va_list args) {
+  struct av1_extracfg extra_cfg = ctx->extra_cfg;
+  extra_cfg.tile_encoding_mode = CAST(AV1E_SET_TILE_ENCODING_MODE, args);
+  return update_extra_cfg(ctx, &extra_cfg);
+}
+#endif  // CONFIG_EXT_TILE
+
 static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
                                         va_list args) {
   struct av1_extracfg extra_cfg = ctx->extra_cfg;
@@ -1449,6 +1466,9 @@
 #if CONFIG_ANS && ANS_MAX_SYMBOLS
   { AV1E_SET_ANS_WINDOW_SIZE_LOG2, ctrl_set_ans_window_size_log2 },
 #endif
+#if CONFIG_EXT_TILE
+  { AV1E_SET_TILE_ENCODING_MODE, ctrl_set_tile_encoding_mode },
+#endif  // CONFIG_EXT_TILE
 
   // Getters
   { AOME_GET_LAST_QUANTIZER, ctrl_get_quantizer },
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index 8cd40a3..f20ea48 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -759,7 +759,8 @@
           yuvconfig2image(&ctx->img, &sd, frame_worker_data->user_priv);
 
 #if CONFIG_EXT_TILE
-          if (frame_worker_data->pbi->dec_tile_row >= 0) {
+          if (cm->tile_encoding_mode &&
+              frame_worker_data->pbi->dec_tile_row >= 0) {
             const int tile_row =
                 AOMMIN(frame_worker_data->pbi->dec_tile_row, cm->tile_rows - 1);
             const int mi_row = tile_row * cm->tile_height;
@@ -774,7 +775,8 @@
                 AOMMIN(cm->tile_height, cm->mi_rows - mi_row) * MI_SIZE;
           }
 
-          if (frame_worker_data->pbi->dec_tile_col >= 0) {
+          if (cm->tile_encoding_mode &&
+              frame_worker_data->pbi->dec_tile_col >= 0) {
             const int tile_col =
                 AOMMIN(frame_worker_data->pbi->dec_tile_col, cm->tile_cols - 1);
             const int mi_col = tile_col * cm->tile_width;
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index eae726c..b2be442 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -861,11 +861,7 @@
 #endif  // CONFIG_INTRA_INTERP
 #endif  // CONFIG_EXT_INTRA
 
-#if CONFIG_EXT_TILE
-#define FIXED_TX_TYPE 1
-#else
 #define FIXED_TX_TYPE 0
-#endif
 
 // Converts block_index for given transform size to index of the block in raster
 // order.
diff --git a/av1/common/enums.h b/av1/common/enums.h
index b42a326..acfcafd 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -55,6 +55,9 @@
 
 // Maximum number of tile rows and tile columns
 #if CONFIG_EXT_TILE
+#define TILE_NORMAL 0
+#define TILE_VR 1
+
 #define MAX_TILE_ROWS 1024
 #define MAX_TILE_COLS 1024
 #else
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 6c28678..5fc92f0 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -356,6 +356,9 @@
 #endif  // !CONFIG_EXT_TILE
   int tile_cols, tile_rows;
   int tile_width, tile_height;  // In MI units
+#if CONFIG_EXT_TILE
+  unsigned int tile_encoding_mode;
+#endif  // CONFIG_EXT_TILE
 
 #if CONFIG_DEPENDENT_HORZTILES
   int dependent_horz_tiles;
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 61fc82f..91b140d 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -2934,6 +2934,7 @@
                            struct aom_read_bit_buffer *const rb) {
   AV1_COMMON *const cm = &pbi->common;
 #if CONFIG_EXT_TILE
+  cm->tile_encoding_mode = aom_rb_read_literal(rb, 1);
 // Read the tile width/height
 #if CONFIG_EXT_PARTITION
   if (cm->sb_size == BLOCK_128X128) {
@@ -3051,7 +3052,8 @@
                             const uint8_t **data, aom_decrypt_cb decrypt_cb,
                             void *decrypt_state,
                             TileBufferDec (*const tile_buffers)[MAX_TILE_COLS],
-                            int tile_size_bytes, int col, int row) {
+                            int tile_size_bytes, int col, int row,
+                            unsigned int tile_encoding_mode) {
   size_t size;
 
   size_t copy_size = 0;
@@ -3070,8 +3072,9 @@
     size = mem_get_varsize(*data, tile_size_bytes);
   }
 
-  // The top bit indicates copy mode
-  if ((size >> (tile_size_bytes * 8 - 1)) == 1) {
+  // If cm->tile_encoding_mode = 1 (i.e. TILE_VR), then the top bit of the tile
+  // header indicates copy mode.
+  if (tile_encoding_mode && (size >> (tile_size_bytes * 8 - 1)) == 1) {
     // The remaining bits in the top byte signal the row offset
     int offset = (size >> (tile_size_bytes - 1) * 8) & 0x7f;
 
@@ -3167,7 +3170,7 @@
 
         get_tile_buffer(tile_col_data_end[c], &pbi->common.error, &data,
                         pbi->decrypt_cb, pbi->decrypt_state, tile_buffers,
-                        tile_size_bytes, c, r);
+                        tile_size_bytes, c, r, cm->tile_encoding_mode);
       }
     }
 
@@ -3182,7 +3185,7 @@
 
         get_tile_buffer(tile_col_data_end[c], &pbi->common.error, &data,
                         pbi->decrypt_cb, pbi->decrypt_state, tile_buffers,
-                        tile_size_bytes, c, r);
+                        tile_size_bytes, c, r, cm->tile_encoding_mode);
       }
     }
   }
@@ -3548,7 +3551,9 @@
 // after the entire frame is decoded.
 #if !CONFIG_VAR_TX && !CONFIG_PARALLEL_DEBLOCKING && !CONFIG_CB4X4
     // Loopfilter one tile row.
-    if (cm->lf.filter_level && !cm->skip_loop_filter) {
+    // Note: If out-of-order tile decoding is used(for example, inv_row_order
+    // = 1), the loopfiltering has be done after all tile rows are decoded.
+    if (!inv_row_order && cm->lf.filter_level && !cm->skip_loop_filter) {
       LFWorkerData *const lf_data = (LFWorkerData *)pbi->lf_worker.data1;
       const int lf_start = AOMMAX(0, tile_info.mi_row_start - cm->mib_size);
       const int lf_end = tile_info.mi_row_end - cm->mib_size;
@@ -4842,6 +4847,17 @@
 
   first_partition_size = read_uncompressed_header(
       pbi, init_read_bit_buffer(pbi, &rb, data, data_end, clear_data));
+
+#if CONFIG_EXT_TILE
+  // If cm->tile_encoding_mode == TILE_NORMAL, the independent decoding of a
+  // single tile or a section of a frame is not allowed.
+  if (!cm->tile_encoding_mode &&
+      (pbi->dec_tile_row >= 0 || pbi->dec_tile_col >= 0)) {
+    pbi->dec_tile_row = -1;
+    pbi->dec_tile_col = -1;
+  }
+#endif  // CONFIG_EXT_TILE
+
 #if CONFIG_TILE_GROUPS
   pbi->first_partition_size = first_partition_size;
   pbi->uncomp_hdr_size = aom_rb_bytes_read(&rb);
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 993ac99..ce518e6 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3731,6 +3731,8 @@
   assert(tile_width > 0);
   assert(tile_height > 0);
 
+  aom_wb_write_literal(wb, cm->tile_encoding_mode, 1);
+
 // Write the tile sizes
 #if CONFIG_EXT_PARTITION
   if (cm->sb_size == BLOCK_128X128) {
@@ -3990,10 +3992,11 @@
         // tile header: size of this tile, or copy offset
         uint32_t tile_header = tile_size;
 
-        // Check if this tile is a copy tile.
+        // If the tile_encoding_mode is 1 (i.e. TILE_VR), check if this tile is
+        // a copy tile.
         // Very low chances to have copy tiles on the key frames, so don't
         // search on key frames to reduce unnecessary search.
-        if (cm->frame_type != KEY_FRAME) {
+        if (cm->frame_type != KEY_FRAME && cm->tile_encoding_mode) {
           const int idendical_tile_offset =
               find_identical_tile(tile_row, tile_col, tile_buffers);
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e430ed4..27a6801 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4824,6 +4824,10 @@
   }
 #endif
 
+#if CONFIG_EXT_TILE
+  cm->tile_encoding_mode = cpi->oxcf.tile_encoding_mode;
+#endif  // CONFIG_EXT_TILE
+
 #if CONFIG_XIPHRC
   if (drop_this_frame) {
     av1_rc_postencode_update_drop_frame(cpi);
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 2299f01..76edaa7 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -267,6 +267,9 @@
 #if CONFIG_ANS && ANS_MAX_SYMBOLS
   int ans_window_size_log2;
 #endif  // CONFIG_ANS && ANS_MAX_SYMBOLS
+#if CONFIG_EXT_TILE
+  unsigned int tile_encoding_mode;
+#endif  // CONFIG_EXT_TILE
 } AV1EncoderConfig;
 
 static INLINE int is_lossless_requested(const AV1EncoderConfig *cfg) {
diff --git a/av1/encoder/picklpf.c b/av1/encoder/picklpf.c
index b925451..fc0ea48 100644
--- a/av1/encoder/picklpf.c
+++ b/av1/encoder/picklpf.c
@@ -206,6 +206,6 @@
   // TODO(any): 0 loopfilter level is only necessary if individual tile
   // decoding is required. We need to communicate this requirement to this
   // code and force loop filter level 0 only if required.
-  lf->filter_level = 0;
+  if (cm->tile_encoding_mode) lf->filter_level = 0;
 #endif  // CONFIG_EXT_TILE
 }
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index bf99c5d..0f9ea75 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -371,11 +371,7 @@
   sf->disable_filter_search_var_thresh = 0;
   sf->adaptive_interp_filter_search = 0;
   sf->allow_partition_search_skip = 0;
-#if CONFIG_EXT_TILE
-  sf->use_upsampled_references = 0;
-#else
   sf->use_upsampled_references = 1;
-#endif  // CONFIG_EXT_TILE
 #if CONFIG_EXT_INTER
   sf->disable_wedge_search_var_thresh = 0;
   sf->fast_wedge_sign_estimate = 0;
@@ -406,12 +402,8 @@
   sf->partition_search_breakout_rate_thr = 0;
   sf->simple_model_rd_from_var = 0;
 
-// Set this at the appropriate speed levels
-#if CONFIG_EXT_TILE
-  sf->use_transform_domain_distortion = 1;
-#else
+  // Set this at the appropriate speed levels
   sf->use_transform_domain_distortion = 0;
-#endif  // CONFIG_EXT_TILE
 
   if (oxcf->mode == GOOD
 #if CONFIG_XIPHRC
diff --git a/test/av1_ext_tile_test.cc b/test/av1_ext_tile_test.cc
index cf70734..f964479 100644
--- a/test/av1_ext_tile_test.cc
+++ b/test/av1_ext_tile_test.cc
@@ -30,6 +30,8 @@
 const int kImgWidth = 704;
 const int kImgHeight = 576;
 
+// This test tests "tile_encoding_mode = TILE_VR" case. The TILE_NORMAL case is
+// tested by the tile_independence test.
 class AV1ExtTileTest
     : public ::libaom_test::EncoderTest,
       public ::libaom_test::CodecTestWith2Params<libaom_test::TestMode, int> {
@@ -81,6 +83,7 @@
       // The tile size is 64x64.
       encoder->Control(AV1E_SET_TILE_COLUMNS, kTileSize);
       encoder->Control(AV1E_SET_TILE_ROWS, kTileSize);
+      encoder->Control(AV1E_SET_TILE_ENCODING_MODE, 1);  // TILE_VR
 #if CONFIG_EXT_PARTITION
       // Always use 64x64 max partition.
       encoder->Control(AV1E_SET_SUPERBLOCK_SIZE, AOM_SUPERBLOCK_SIZE_64X64);
diff --git a/test/tile_independence_test.cc b/test/tile_independence_test.cc
index a98faff..a29051f 100644
--- a/test/tile_independence_test.cc
+++ b/test/tile_independence_test.cc
@@ -62,6 +62,9 @@
     if (video->frame() == 1) {
       encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_);
       encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_);
+#if CONFIG_EXT_TILE
+      encoder->Control(AV1E_SET_TILE_ENCODING_MODE, 0);  // TILE_NORMAL
+#endif                                                   // CONFIG_EXT_TILE
 #if CONFIG_LOOPFILTERING_ACROSS_TILES
       encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
 #endif  // CONFIG_LOOPFILTERING_ACROSS_TILES