[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.")