Encode loop restoration coefficients per tile

This is a baby-step towards encoding the coefficients at the start of
superblocks at the top-left of loop restoration tiles. Note that this
patch causes us to reset "wiener_info" and "sgrproj_info" at each tile
boundary, which will cause a performance drop.

This is necessary because, in order for tiles to be processed in
parallel, we cannot delta-encode coefficients across tile boundaries
if the coefficients are signalled within tiles. We could probably do
better than the current patch by, say, delta-encoding against previous
frames.

This patch also fixes up the costing in pickrst.c to match

Change-Id: I5b8b91d63aaf49627cde40219c31c0ac776dfd38
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 201d97f..9561159 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3341,8 +3341,75 @@
   memcpy(ref_sgrproj_info, sgrproj_info, sizeof(*sgrproj_info));
 }
 
+static void encode_restoration_for_tile(AV1_COMMON *cm, aom_writer *wb,
+                                        int tile_row, int tile_col,
+                                        const int nrtiles_x[2],
+                                        const int nrtiles_y[2]) {
+  for (int p = 0; p < MAX_MB_PLANE; ++p) {
+    RestorationInfo *rsi = &cm->rst_info[p];
+    if (rsi->frame_restoration_type == RESTORE_NONE) continue;
+
+    const int tile_width =
+        (p > 0) ? ROUND_POWER_OF_TWO(cm->tile_width, cm->subsampling_x)
+                : cm->tile_width;
+    const int tile_height =
+        (p > 0) ? ROUND_POWER_OF_TWO(cm->tile_height, cm->subsampling_y)
+                : cm->tile_height;
+    const int rtile_size = rsi->restoration_tilesize;
+    const int rtiles_per_tile_x = tile_width * MI_SIZE / rtile_size;
+    const int rtiles_per_tile_y = tile_height * MI_SIZE / rtile_size;
+
+    const int rtile_row0 = rtiles_per_tile_y * tile_row;
+    const int rtile_row1 =
+        AOMMIN(rtile_row0 + rtiles_per_tile_y, nrtiles_y[p > 0]);
+
+    const int rtile_col0 = rtiles_per_tile_x * tile_col;
+    const int rtile_col1 =
+        AOMMIN(rtile_col0 + rtiles_per_tile_x, nrtiles_x[p > 0]);
+
+    WienerInfo wiener_info;
+    SgrprojInfo sgrproj_info;
+    set_default_wiener(&wiener_info);
+    set_default_sgrproj(&sgrproj_info);
+
+    const int wiener_win = (p > 0) ? WIENER_WIN_CHROMA : WIENER_WIN;
+
+    for (int rtile_row = rtile_row0; rtile_row < rtile_row1; ++rtile_row) {
+      for (int rtile_col = rtile_col0; rtile_col < rtile_col1; ++rtile_col) {
+        const int rtile_idx = rtile_row * nrtiles_x[p > 0] + rtile_col;
+        if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) {
+          assert(p == 0);
+          av1_write_token(
+              wb, av1_switchable_restore_tree, cm->fc->switchable_restore_prob,
+              &switchable_restore_encodings[rsi->restoration_type[rtile_idx]]);
+          if (rsi->restoration_type[rtile_idx] == RESTORE_WIENER) {
+            write_wiener_filter(wiener_win, &rsi->wiener_info[rtile_idx],
+                                &wiener_info, wb);
+          } else if (rsi->restoration_type[rtile_idx] == RESTORE_SGRPROJ) {
+            write_sgrproj_filter(&rsi->sgrproj_info[rtile_idx], &sgrproj_info,
+                                 wb);
+          }
+        } else if (rsi->frame_restoration_type == RESTORE_WIENER) {
+          aom_write(wb, rsi->restoration_type[rtile_idx] != RESTORE_NONE,
+                    RESTORE_NONE_WIENER_PROB);
+          if (rsi->restoration_type[rtile_idx] != RESTORE_NONE) {
+            write_wiener_filter(wiener_win, &rsi->wiener_info[rtile_idx],
+                                &wiener_info, wb);
+          }
+        } else if (rsi->frame_restoration_type == RESTORE_SGRPROJ) {
+          aom_write(wb, rsi->restoration_type[rtile_idx] != RESTORE_NONE,
+                    RESTORE_NONE_SGRPROJ_PROB);
+          if (rsi->restoration_type[rtile_idx] != RESTORE_NONE) {
+            write_sgrproj_filter(&rsi->sgrproj_info[rtile_idx], &sgrproj_info,
+                                 wb);
+          }
+        }
+      }
+    }
+  }
+}
+
 static void encode_restoration(AV1_COMMON *cm, aom_writer *wb) {
-  int i, p;
 #if CONFIG_FRAME_SUPERRES
   const int width = cm->superres_upscaled_width;
   const int height = cm->superres_upscaled_height;
@@ -3350,76 +3417,19 @@
   const int width = cm->width;
   const int height = cm->height;
 #endif  // CONFIG_FRAME_SUPERRES
-  const int ntiles =
-      av1_get_rest_ntiles(width, height, cm->rst_info[0].restoration_tilesize,
-                          NULL, NULL, NULL, NULL);
-  WienerInfo ref_wiener_info;
-  SgrprojInfo ref_sgrproj_info;
-  set_default_wiener(&ref_wiener_info);
-  set_default_sgrproj(&ref_sgrproj_info);
-  const int ntiles_uv = av1_get_rest_ntiles(
-      ROUND_POWER_OF_TWO(width, cm->subsampling_x),
-      ROUND_POWER_OF_TWO(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) {
-      // RESTORE_SWITCHABLE
-      for (i = 0; i < ntiles; ++i) {
-        av1_write_token(
-            wb, av1_switchable_restore_tree, cm->fc->switchable_restore_prob,
-            &switchable_restore_encodings[rsi->restoration_type[i]]);
-        if (rsi->restoration_type[i] == RESTORE_WIENER) {
-          write_wiener_filter(WIENER_WIN, &rsi->wiener_info[i],
-                              &ref_wiener_info, wb);
-        } else if (rsi->restoration_type[i] == RESTORE_SGRPROJ) {
-          write_sgrproj_filter(&rsi->sgrproj_info[i], &ref_sgrproj_info, wb);
-        }
-      }
-    } else if (rsi->frame_restoration_type == RESTORE_WIENER) {
-      for (i = 0; i < ntiles; ++i) {
-        aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE,
-                  RESTORE_NONE_WIENER_PROB);
-        if (rsi->restoration_type[i] != RESTORE_NONE) {
-          write_wiener_filter(WIENER_WIN, &rsi->wiener_info[i],
-                              &ref_wiener_info, wb);
-        }
-      }
-    } else if (rsi->frame_restoration_type == RESTORE_SGRPROJ) {
-      for (i = 0; i < ntiles; ++i) {
-        aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE,
-                  RESTORE_NONE_SGRPROJ_PROB);
-        if (rsi->restoration_type[i] != RESTORE_NONE) {
-          write_sgrproj_filter(&rsi->sgrproj_info[i], &ref_sgrproj_info, wb);
-        }
-      }
-    }
-  }
-  for (p = 1; p < MAX_MB_PLANE; ++p) {
-    set_default_wiener(&ref_wiener_info);
-    set_default_sgrproj(&ref_sgrproj_info);
-    rsi = &cm->rst_info[p];
-    if (rsi->frame_restoration_type == RESTORE_WIENER) {
-      for (i = 0; i < ntiles_uv; ++i) {
-        if (ntiles_uv > 1)
-          aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE,
-                    RESTORE_NONE_WIENER_PROB);
-        if (rsi->restoration_type[i] != RESTORE_NONE) {
-          write_wiener_filter(WIENER_WIN_CHROMA, &rsi->wiener_info[i],
-                              &ref_wiener_info, wb);
-        }
-      }
-    } else if (rsi->frame_restoration_type == RESTORE_SGRPROJ) {
-      for (i = 0; i < ntiles_uv; ++i) {
-        if (ntiles_uv > 1)
-          aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE,
-                    RESTORE_NONE_SGRPROJ_PROB);
-        if (rsi->restoration_type[i] != RESTORE_NONE) {
-          write_sgrproj_filter(&rsi->sgrproj_info[i], &ref_sgrproj_info, wb);
-        }
-      }
-    } else if (rsi->frame_restoration_type != RESTORE_NONE) {
-      assert(0);
+
+  int nrtiles_x[2], nrtiles_y[2];
+  av1_get_rest_ntiles(width, height, cm->rst_info[0].restoration_tilesize, NULL,
+                      NULL, &nrtiles_x[0], &nrtiles_y[0]);
+  av1_get_rest_ntiles(ROUND_POWER_OF_TWO(width, cm->subsampling_x),
+                      ROUND_POWER_OF_TWO(height, cm->subsampling_y),
+                      cm->rst_info[1].restoration_tilesize, NULL, NULL,
+                      &nrtiles_x[1], &nrtiles_y[1]);
+
+  for (int tile_row = 0; tile_row < cm->tile_rows; ++tile_row) {
+    for (int tile_col = 0; tile_col < cm->tile_cols; ++tile_col) {
+      encode_restoration_for_tile(cm, wb, tile_row, tile_col, nrtiles_x,
+                                  nrtiles_y);
     }
   }
 }