[NORMATIVE] Allow LR units to cross tiles

Since fully independent decoding of tiles is no longer supported,
instead of dividing each tile into loop restoration units
independently, divide the frame as a whole into units.
This avoids having very narrow units at the bottom of each
tile, and makes the process mich simpler.

The new simplified scheme is implemented within the
CONFIG_SIMPLE_LRUNIT experiment.

BUG=aomedia:1674

Change-Id: If43cea55325d1a3693ab19b71efdacaa220b961d
diff --git a/av1/common/restoration.c b/av1/common/restoration.c
index acf5cda..5ca9f96 100644
--- a/av1/common/restoration.c
+++ b/av1/common/restoration.c
@@ -33,6 +33,21 @@
   { 0, 0, 1, 11 },  { 0, 0, 1, 14 },  { 2, 30, 0, 0 },  { 2, 75, 0, 0 },
 };
 
+#if CONFIG_SIMPLE_LRUNIT
+static AV1PixelRect whole_frame_rect(const AV1_COMMON *cm, int is_uv) {
+  AV1PixelRect rect;
+
+  int ss_x = is_uv && cm->subsampling_x;
+  int ss_y = is_uv && cm->subsampling_y;
+
+  rect.top = 0;
+  rect.bottom = ROUND_POWER_OF_TWO(cm->height, ss_y);
+  rect.left = 0;
+  rect.right = ROUND_POWER_OF_TWO(cm->superres_upscaled_width, ss_x);
+  return rect;
+}
+#endif  // CONFIG_SIMPLE_LRUNIT
+
 // Count horizontal or vertical units per tile (use a width or height for
 // tile_size, respectively). We basically want to divide the tile size by the
 // size of a restoration unit. Rather than rounding up unconditionally as you
@@ -46,11 +61,14 @@
 
 void av1_alloc_restoration_struct(AV1_COMMON *cm, RestorationInfo *rsi,
                                   int is_uv) {
-  // We need to allocate enough space for restoration units to cover the
-  // largest tile. Without CONFIG_MAX_TILE, this is always the tile at the
-  // top-left and we can use av1_get_tile_rect(). With CONFIG_MAX_TILE, we have
-  // to do the computation ourselves, iterating over the tiles and keeping
-  // track of the largest width and height, then upscaling.
+// We need to allocate enough space for restoration units to cover the
+// largest tile. Without CONFIG_MAX_TILE, this is always the tile at the
+// top-left and we can use av1_get_tile_rect(). With CONFIG_MAX_TILE, we have
+// to do the computation ourselves, iterating over the tiles and keeping
+// track of the largest width and height, then upscaling.
+#if CONFIG_SIMPLE_LRUNIT
+  const AV1PixelRect tile_rect = whole_frame_rect(cm, is_uv);
+#else
   TileInfo tile;
   int max_mi_w = 0;
   int max_mi_h = 0;
@@ -74,6 +92,7 @@
   av1_tile_init(&tile_info, cm, tile_row, tile_col);
 
   const AV1PixelRect tile_rect = av1_get_tile_rect(&tile_info, cm, is_uv);
+#endif  // CONFIG_SIMPLE_LRUNIT
   const int max_tile_w = tile_rect.right - tile_rect.left;
   const int max_tile_h = tile_rect.bottom - tile_rect.top;
 
@@ -92,7 +111,11 @@
   rsi->horz_units_per_tile = hpertile;
   rsi->vert_units_per_tile = vpertile;
 
+#if CONFIG_SIMPLE_LRUNIT
+  const int ntiles = 1;
+#else
   const int ntiles = cm->tile_rows * cm->tile_cols;
+#endif  // CONFIG_SIMPLE_LRUNIT
   const int nunits = ntiles * rsi->units_per_tile;
 
   aom_free(rsi->unit_info);
@@ -1212,6 +1235,15 @@
 
   const RestorationInfo *rsi = &cm->rst_info[plane];
 
+#if CONFIG_SIMPLE_LRUNIT
+  const AV1PixelRect tile_rect = whole_frame_rect(cm, is_uv);
+
+  if (on_tile) on_tile(0, 0, priv);
+
+  foreach_rest_unit_in_tile(&tile_rect, 0, 0, 1, rsi->horz_units_per_tile,
+                            rsi->units_per_tile, rsi->restoration_unit_size,
+                            ss_y, on_rest_unit, priv);
+#else
   TileInfo tile_info;
   for (int tile_row = 0; tile_row < cm->tile_rows; ++tile_row) {
     av1_tile_set_row(&tile_info, cm, tile_row);
@@ -1228,8 +1260,10 @@
                                 priv);
     }
   }
+#endif  // CONFIG_SIMPLE_LRUNIT
 }
 
+#if !CONFIG_SIMPLE_LRUNIT
 // Get the horizontal or vertical index of the tile containing mi_x. For a
 // horizontal index, mi_x should be the left-most column for some block in mi
 // units and tile_x_start_sb should be cm->tile_col_start_sb. The return value
@@ -1250,6 +1284,7 @@
   assert(0);
   return 0;
 }
+#endif  // !CONFIG_SIMPLE_LRUNIT
 
 int av1_loop_restoration_corners_in_sb(const struct AV1Common *cm, int plane,
                                        int mi_row, int mi_col, BLOCK_SIZE bsize,
@@ -1264,6 +1299,14 @@
 
   const int is_uv = plane > 0;
 
+#if CONFIG_SIMPLE_LRUNIT
+  const AV1PixelRect tile_rect = whole_frame_rect(cm, is_uv);
+  const int tile_w = tile_rect.right - tile_rect.left;
+  const int tile_h = tile_rect.bottom - tile_rect.top;
+
+  const int mi_top = 0;
+  const int mi_left = 0;
+#else
   // Which tile contains the superblock? Find that tile's top-left in mi-units,
   // together with the tile's size in pixels.
   const int mib_log2 = cm->seq_params.mib_size_log2;
@@ -1279,6 +1322,7 @@
 
   const int mi_top = tile_info.mi_row_start;
   const int mi_left = tile_info.mi_col_start;
+#endif  // CONFIG_SIMPLE_LRUNIT
 
   // Compute the mi-unit corners of the superblock relative to the top-left of
   // the tile
@@ -1333,7 +1377,11 @@
   *rcol1 = AOMMIN((mi_rel_col1 * mi_to_num_x + rnd_x) / denom_x, horz_units);
   *rrow1 = AOMMIN((mi_rel_row1 * mi_to_num_y + rnd_y) / denom_y, vert_units);
 
+#if CONFIG_SIMPLE_LRUNIT
+  const int tile_idx = 0;
+#else
   const int tile_idx = tile_col + tile_row * cm->tile_cols;
+#endif  // CONFIG_SIMPLE_LRUNIT
   *tile_tl_idx = tile_idx * rsi->units_per_tile;
 
   return *rcol0 < *rcol1 && *rrow0 < *rrow1;
@@ -1446,8 +1494,10 @@
 }
 
 static void save_tile_row_boundary_lines(const YV12_BUFFER_CONFIG *frame,
+#if !CONFIG_SIMPLE_LRUNIT
                                          int tile_row,
                                          const TileInfo *tile_info,
+#endif  // !CONFIG_SIMPLE_LRUNIT
                                          int use_highbd, int plane,
                                          AV1_COMMON *cm, int after_cdef) {
   const int is_uv = plane > 0;
@@ -1457,12 +1507,16 @@
 
   // Get the tile rectangle, with height rounded up to the next multiple of 8
   // luma pixels (only relevant for the bottom tile of the frame)
+#if CONFIG_SIMPLE_LRUNIT
+  const AV1PixelRect tile_rect = whole_frame_rect(cm, is_uv);
+  const int stripe0 = 0;
+#else
   const AV1PixelRect tile_rect = av1_get_tile_rect(tile_info, cm, is_uv);
+  const int stripe0 = (tile_row == 0) ? 0 : cm->rst_end_stripe[tile_row - 1];
+#endif  // CONFIG_SIMPLE_LRUNIT
 
   RestorationStripeBoundaries *boundaries = &cm->rst_info[plane].boundaries;
 
-  const int stripe0 = (tile_row == 0) ? 0 : cm->rst_end_stripe[tile_row - 1];
-
   int plane_height = ROUND_POWER_OF_TWO(cm->height, ss_y);
 
   int tile_stripe;
@@ -1520,11 +1574,15 @@
   const int num_planes = av1_num_planes(cm);
   const int use_highbd = cm->use_highbitdepth;
   for (int p = 0; p < num_planes; ++p) {
+#if CONFIG_SIMPLE_LRUNIT
+    save_tile_row_boundary_lines(frame, use_highbd, p, cm, after_cdef);
+#else
     TileInfo tile_info;
     for (int tile_row = 0; tile_row < cm->tile_rows; ++tile_row) {
       av1_tile_init(&tile_info, cm, tile_row, 0);
       save_tile_row_boundary_lines(frame, tile_row, &tile_info, use_highbd, p,
                                    cm, after_cdef);
     }
+#endif  // CONFIG_SIMPLE_LRUNIT
   }
 }
diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c
index 9e283c9..31669d4 100644
--- a/av1/encoder/pickrst.c
+++ b/av1/encoder/pickrst.c
@@ -1160,7 +1160,11 @@
 
 static int rest_tiles_in_plane(const AV1_COMMON *cm, int plane) {
   const RestorationInfo *rsi = &cm->rst_info[plane];
+#if CONFIG_SIMPLE_LRUNIT
+  return rsi->units_per_tile;
+#else
   return cm->tile_rows * cm->tile_cols * rsi->units_per_tile;
+#endif  // CONFIG_SIMPLE_LRUNIT
 }
 
 void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi) {
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index e638fcf..4865394 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -96,5 +96,6 @@
 set(CONFIG_FP_MB_STATS 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_INTER_STATS_ONLY 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_RD_DEBUG 0 CACHE NUMBER "AV1 experiment flag.")
+set(CONFIG_SIMPLE_LRUNIT 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_TRAILING_BITS 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_FILEOPTIONS 1 CACHE NUMBER "AV1 config option flag.")