Add restoration tilesize to frame header

The restoration tilesize can be now chosen as either 256, 128
or 64 at the frame header.

Change-Id: I852fc42afedc053484d657bdca522de73aaacd67
diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c
index 09f6135..9183fa5 100644
--- a/av1/common/alloccommon.c
+++ b/av1/common/alloccommon.c
@@ -88,6 +88,7 @@
 }
 
 #if CONFIG_LOOP_RESTORATION
+// Assumes cm->rst_info[p].restoration_tilesize is already initialized
 void av1_alloc_restoration_buffers(AV1_COMMON *cm) {
   int p;
   av1_alloc_restoration_struct(cm, &cm->rst_info[0], cm->width, cm->height);
diff --git a/av1/common/restoration.c b/av1/common/restoration.c
index 300c5a2..a2077f6 100644
--- a/av1/common/restoration.c
+++ b/av1/common/restoration.c
@@ -58,8 +58,8 @@
 
 int av1_alloc_restoration_struct(AV1_COMMON *cm, RestorationInfo *rst_info,
                                  int width, int height) {
-  const int ntiles = av1_get_rest_ntiles(width, height, NULL, NULL, NULL, NULL);
-  rst_info->frame_restoration_type = RESTORE_NONE;
+  const int ntiles = av1_get_rest_ntiles(
+      width, height, rst_info->restoration_tilesize, NULL, NULL, NULL, NULL);
   aom_free(rst_info->restoration_type);
   CHECK_MEM_ERROR(cm, rst_info->restoration_type,
                   (RestorationType *)aom_malloc(
@@ -1444,9 +1444,9 @@
   if ((components_pattern >> AOM_PLANE_Y) & 1) {
     if (rsi[0].frame_restoration_type != RESTORE_NONE) {
       cm->rst_internal.ntiles = av1_get_rest_ntiles(
-          cm->width, cm->height, &cm->rst_internal.tile_width,
-          &cm->rst_internal.tile_height, &cm->rst_internal.nhtiles,
-          &cm->rst_internal.nvtiles);
+          cm->width, cm->height, cm->rst_info[AOM_PLANE_Y].restoration_tilesize,
+          &cm->rst_internal.tile_width, &cm->rst_internal.tile_height,
+          &cm->rst_internal.nhtiles, &cm->rst_internal.nvtiles);
       cm->rst_internal.rsi = &rsi[0];
       restore_func =
           restore_funcs[cm->rst_internal.rsi->frame_restoration_type];
@@ -1473,6 +1473,7 @@
       cm->rst_internal.ntiles = av1_get_rest_ntiles(
           ROUND_POWER_OF_TWO(cm->width, cm->subsampling_x),
           ROUND_POWER_OF_TWO(cm->height, cm->subsampling_y),
+          cm->rst_info[AOM_PLANE_U].restoration_tilesize,
           &cm->rst_internal.tile_width, &cm->rst_internal.tile_height,
           &cm->rst_internal.nhtiles, &cm->rst_internal.nvtiles);
       cm->rst_internal.rsi = &rsi[AOM_PLANE_U];
@@ -1501,6 +1502,7 @@
       cm->rst_internal.ntiles = av1_get_rest_ntiles(
           ROUND_POWER_OF_TWO(cm->width, cm->subsampling_x),
           ROUND_POWER_OF_TWO(cm->height, cm->subsampling_y),
+          cm->rst_info[AOM_PLANE_V].restoration_tilesize,
           &cm->rst_internal.tile_width, &cm->rst_internal.tile_height,
           &cm->rst_internal.nhtiles, &cm->rst_internal.nvtiles);
       cm->rst_internal.rsi = &rsi[AOM_PLANE_V];
diff --git a/av1/common/restoration.h b/av1/common/restoration.h
index 6bd145a..e532172 100644
--- a/av1/common/restoration.h
+++ b/av1/common/restoration.h
@@ -24,10 +24,9 @@
 #define CLIP(x, lo, hi) ((x) < (lo) ? (lo) : (x) > (hi) ? (hi) : (x))
 #define RINT(x) ((x) < 0 ? (int)((x)-0.5) : (int)((x) + 0.5))
 
-#define RESTORATION_TILESIZE_SML 128
-#define RESTORATION_TILESIZE_BIG 256
+#define RESTORATION_TILESIZE_MAX 256
 #define RESTORATION_TILEPELS_MAX \
-  (RESTORATION_TILESIZE_BIG * RESTORATION_TILESIZE_BIG * 9 / 4)
+  (RESTORATION_TILESIZE_MAX * RESTORATION_TILESIZE_MAX * 9 / 4)
 
 #if USE_DOMAINTXFMRF
 #define DOMAINTXFMRF_PARAMS_BITS 6
@@ -56,7 +55,7 @@
 // 2 for the restored versions of the frame and
 // 2 for each restoration operation
 #define SGRPROJ_OUTBUF_SIZE \
-  ((RESTORATION_TILESIZE_BIG * 3 / 2) * (RESTORATION_TILESIZE_BIG * 3 / 2 + 16))
+  ((RESTORATION_TILESIZE_MAX * 3 / 2) * (RESTORATION_TILESIZE_MAX * 3 / 2 + 16))
 #define SGRPROJ_TMPBUF_SIZE                         \
   (RESTORATION_TILEPELS_MAX * 2 * sizeof(int32_t) + \
    SGRPROJ_OUTBUF_SIZE * 2 * sizeof(int32_t))
@@ -160,6 +159,7 @@
 #endif  // USE_DOMAINTXFMRF
 
 typedef struct {
+  int restoration_tilesize;
   RestorationType frame_restoration_type;
   RestorationType *restoration_type;
   // Wiener filter
@@ -181,19 +181,11 @@
   int32_t *tmpbuf;
 } RestorationInternal;
 
-static INLINE int get_rest_tilesize(int width, int height) {
-  if (width * height <= 352 * 288)
-    return RESTORATION_TILESIZE_SML;
-  else
-    return RESTORATION_TILESIZE_BIG;
-}
-
-static INLINE int av1_get_rest_ntiles(int width, int height, int *tile_width,
-                                      int *tile_height, int *nhtiles,
-                                      int *nvtiles) {
+static INLINE int av1_get_rest_ntiles(int width, int height, int tilesize,
+                                      int *tile_width, int *tile_height,
+                                      int *nhtiles, int *nvtiles) {
   int nhtiles_, nvtiles_;
   int tile_width_, tile_height_;
-  int tilesize = get_rest_tilesize(width, height);
   tile_width_ = (tilesize < 0) ? width : AOMMIN(tilesize, width);
   tile_height_ = (tilesize < 0) ? height : AOMMIN(tilesize, height);
   nhtiles_ = (width + (tile_width_ >> 1)) / tile_width_;
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 5af7acd..051a338 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -2560,6 +2560,21 @@
     cm->rst_info[p].frame_restoration_type =
         aom_rb_read_bit(rb) ? RESTORE_WIENER : RESTORE_NONE;
   }
+
+  cm->rst_info[0].restoration_tilesize = RESTORATION_TILESIZE_MAX;
+  cm->rst_info[1].restoration_tilesize = RESTORATION_TILESIZE_MAX;
+  cm->rst_info[2].restoration_tilesize = RESTORATION_TILESIZE_MAX;
+  if (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) {
+    rsi = &cm->rst_info[0];
+    rsi->restoration_tilesize >>= aom_rb_read_bit(rb);
+    if (rsi->restoration_tilesize != RESTORATION_TILESIZE_MAX) {
+      rsi->restoration_tilesize >>= aom_rb_read_bit(rb);
+    }
+    cm->rst_info[1].restoration_tilesize = cm->rst_info[0].restoration_tilesize;
+    cm->rst_info[2].restoration_tilesize = cm->rst_info[0].restoration_tilesize;
+  }
 }
 
 static void read_wiener_filter(WienerInfo *wiener_info, aom_reader *rb) {
@@ -2610,12 +2625,13 @@
 
 static void decode_restoration(AV1_COMMON *cm, aom_reader *rb) {
   int i, p;
-  const int ntiles =
-      av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL);
-  const int ntiles_uv =
-      av1_get_rest_ntiles(ROUND_POWER_OF_TWO(cm->width, cm->subsampling_x),
-                          ROUND_POWER_OF_TWO(cm->height, cm->subsampling_y),
-                          NULL, NULL, NULL, NULL);
+  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height,
+                                         cm->rst_info[0].restoration_tilesize,
+                                         NULL, NULL, NULL, NULL);
+  const int ntiles_uv = av1_get_rest_ntiles(
+      ROUND_POWER_OF_TWO(cm->width, cm->subsampling_x),
+      ROUND_POWER_OF_TWO(cm->height, cm->subsampling_y),
+      cm->rst_info[1].restoration_tilesize, NULL, NULL, NULL, NULL);
   RestorationInfo *rsi = &cm->rst_info[0];
   if (rsi->frame_restoration_type != RESTORE_NONE) {
     if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) {
@@ -4376,7 +4392,6 @@
   setup_clpf(pbi, rb);
 #endif
 #if CONFIG_LOOP_RESTORATION
-  av1_alloc_restoration_buffers(cm);
   decode_restoration_mode(cm, rb);
 #endif  // CONFIG_LOOP_RESTORATION
   setup_quantization(cm, rb);
@@ -4579,7 +4594,12 @@
                        "Failed to allocate bool decoder 0");
 
 #if CONFIG_LOOP_RESTORATION
-  decode_restoration(cm, &r);
+  if (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) {
+    av1_alloc_restoration_buffers(cm);
+    decode_restoration(cm, &r);
+  }
 #endif
 
 #if !CONFIG_EC_ADAPT
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index aee5b0f..f37a23a 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3402,6 +3402,19 @@
       default: assert(0);
     }
   }
+  if (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) {
+    rsi = &cm->rst_info[0];
+    if (rsi->restoration_tilesize == RESTORATION_TILESIZE_MAX) {
+      aom_wb_write_bit(wb, 0);
+    }
+    aom_wb_write_bit(wb, rsi->restoration_tilesize != RESTORATION_TILESIZE_MAX);
+    if (rsi->restoration_tilesize != RESTORATION_TILESIZE_MAX) {
+      aom_wb_write_bit(
+          wb, rsi->restoration_tilesize != (RESTORATION_TILESIZE_MAX >> 1));
+    }
+  }
 }
 
 static void write_wiener_filter(WienerInfo *wiener_info, aom_writer *wb) {
@@ -3436,12 +3449,13 @@
 
 static void encode_restoration(AV1_COMMON *cm, aom_writer *wb) {
   int i, p;
-  const int ntiles =
-      av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL);
-  const int ntiles_uv =
-      av1_get_rest_ntiles(ROUND_POWER_OF_TWO(cm->width, cm->subsampling_x),
-                          ROUND_POWER_OF_TWO(cm->height, cm->subsampling_y),
-                          NULL, NULL, NULL, NULL);
+  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height,
+                                         cm->rst_info[0].restoration_tilesize,
+                                         NULL, NULL, NULL, NULL);
+  const int ntiles_uv = av1_get_rest_ntiles(
+      ROUND_POWER_OF_TWO(cm->width, cm->subsampling_x),
+      ROUND_POWER_OF_TWO(cm->height, cm->subsampling_y),
+      cm->rst_info[1].restoration_tilesize, NULL, NULL, NULL, NULL);
   RestorationInfo *rsi = &cm->rst_info[0];
   if (rsi->frame_restoration_type != RESTORE_NONE) {
     if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) {
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 655f749..b3adff5 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -751,9 +751,6 @@
   } else {
     cpi->extra_rstbuf = NULL;
   }
-  for (int i = 0; i < MAX_MB_PLANE; ++i)
-    av1_alloc_restoration_struct(cm, &cpi->rst_search[i], cm->width,
-                                 cm->height);
 #endif  // CONFIG_LOOP_RESTORATION
 
   if (aom_realloc_frame_buffer(&cpi->scaled_source, cm->width, cm->height,
@@ -3912,6 +3909,17 @@
   }
 }
 
+#if CONFIG_LOOP_RESTORATION
+static void set_restoration_tilesize(int width, int height,
+                                     RestorationInfo *rst) {
+  (void)width;
+  (void)height;
+  rst[0].restoration_tilesize = (RESTORATION_TILESIZE_MAX >> 1);
+  rst[1].restoration_tilesize = rst[0].restoration_tilesize;
+  rst[2].restoration_tilesize = rst[0].restoration_tilesize;
+}
+#endif  // CONFIG_LOOP_RESTORATION
+
 static void set_frame_size(AV1_COMP *cpi) {
   int ref_frame;
   AV1_COMMON *const cm = &cpi->common;
@@ -3968,11 +3976,20 @@
     aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
                        "Failed to allocate frame buffer");
 
+#if CONFIG_LOOP_RESTORATION
+  set_restoration_tilesize(cm->width, cm->height, cm->rst_info);
+  for (int i = 0; i < MAX_MB_PLANE; ++i)
+    cm->rst_info[i].frame_restoration_type = RESTORE_NONE;
+  av1_alloc_restoration_buffers(cm);
+  for (int i = 0; i < MAX_MB_PLANE; ++i) {
+    cpi->rst_search[i].restoration_tilesize =
+        cm->rst_info[i].restoration_tilesize;
+    av1_alloc_restoration_struct(cm, &cpi->rst_search[i], cm->width,
+                                 cm->height);
+  }
+#endif  // CONFIG_LOOP_RESTORATION
   alloc_util_frame_buffers(cpi);
   init_motion_estimation(cpi);
-#if CONFIG_LOOP_RESTORATION
-  av1_alloc_restoration_buffers(cm);
-#endif  // CONFIG_LOOP_RESTORATION
 
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
     RefBuffer *const ref_buf = &cm->frame_refs[ref_frame - LAST_FRAME];
diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c
index 6ba6cc2..1a990f8 100644
--- a/av1/encoder/pickrst.c
+++ b/av1/encoder/pickrst.c
@@ -138,8 +138,9 @@
     width = src->uv_crop_width;
     height = src->uv_crop_height;
   }
-  ntiles = av1_get_rest_ntiles(width, height, &tile_width, &tile_height,
-                               &nhtiles, &nvtiles);
+  ntiles = av1_get_rest_ntiles(
+      width, height, cm->rst_info[components_pattern > 1].restoration_tilesize,
+      &tile_width, &tile_height, &nhtiles, &nvtiles);
   (void)ntiles;
 
   av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
@@ -344,8 +345,9 @@
   int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
   int h_start, h_end, v_start, v_end;
   // Allocate for the src buffer at high precision
-  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
-                                         &tile_height, &nhtiles, &nvtiles);
+  const int ntiles = av1_get_rest_ntiles(
+      cm->width, cm->height, cm->rst_info[0].restoration_tilesize, &tile_width,
+      &tile_height, &nhtiles, &nvtiles);
   rsi->frame_restoration_type = RESTORE_SGRPROJ;
 
   for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
@@ -557,8 +559,9 @@
   RestorationInfo *rsi = &cpi->rst_search[0];
   int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
   int h_start, h_end, v_start, v_end;
-  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
-                                         &tile_height, &nhtiles, &nvtiles);
+  const int ntiles = av1_get_rest_ntiles(
+      cm->width, cm->height, cm->rst_info[0].restoration_tilesize, &tile_width,
+      &tile_height, &nhtiles, &nvtiles);
 
   rsi->frame_restoration_type = RESTORE_DOMAINTXFMRF;
 
@@ -964,8 +967,9 @@
   double score;
   int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
   int h_start, h_end, v_start, v_end;
-  const int ntiles = av1_get_rest_ntiles(width, height, &tile_width,
-                                         &tile_height, &nhtiles, &nvtiles);
+  const int ntiles =
+      av1_get_rest_ntiles(width, height, cm->rst_info[1].restoration_tilesize,
+                          &tile_width, &tile_height, &nhtiles, &nvtiles);
   assert(width == dgd->uv_crop_width);
   assert(height == dgd->uv_crop_height);
 
@@ -1101,8 +1105,9 @@
   double score;
   int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
   int h_start, h_end, v_start, v_end;
-  const int ntiles = av1_get_rest_ntiles(width, height, &tile_width,
-                                         &tile_height, &nhtiles, &nvtiles);
+  const int ntiles =
+      av1_get_rest_ntiles(width, height, cm->rst_info[0].restoration_tilesize,
+                          &tile_width, &tile_height, &nhtiles, &nvtiles);
   assert(width == dgd->y_crop_width);
   assert(height == dgd->y_crop_height);
   assert(width == src->y_crop_width);
@@ -1214,8 +1219,9 @@
   AV1_COMMON *const cm = &cpi->common;
   int tile_idx, tile_width, tile_height, nhtiles, nvtiles;
   int h_start, h_end, v_start, v_end;
-  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width,
-                                         &tile_height, &nhtiles, &nvtiles);
+  const int ntiles = av1_get_rest_ntiles(
+      cm->width, cm->height, cm->rst_info[0].restoration_tilesize, &tile_width,
+      &tile_height, &nhtiles, &nvtiles);
   (void)info;
   (void)dst_frame;
   (void)partial_frame;
@@ -1246,8 +1252,9 @@
   MACROBLOCK *x = &cpi->td.mb;
   double cost_switchable = 0;
   int r, bits, tile_idx;
-  const int ntiles =
-      av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL);
+  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height,
+                                         cm->rst_info[0].restoration_tilesize,
+                                         NULL, NULL, NULL, NULL);
   (void)partial_frame;
 
   rsi->frame_restoration_type = RESTORE_SWITCHABLE;
@@ -1285,8 +1292,9 @@
   double best_cost_restore;
   RestorationType r, best_restore;
 
-  const int ntiles =
-      av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL);
+  const int ntiles = av1_get_rest_ntiles(cm->width, cm->height,
+                                         cm->rst_info[0].restoration_tilesize,
+                                         NULL, NULL, NULL, NULL);
 
   for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) {
     tile_cost[r] = (double *)aom_malloc(sizeof(*tile_cost[0]) * ntiles);