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