Commit 921b334f authored by Rupert Swarbrick's avatar Rupert Swarbrick Committed by Debargha Mukherjee

striped-loop-restoration: Respect tile experiments

As of patch https://aomedia-review.googlesource.com/c/aom/+/28821 ,
loop-restoration units cannot cross tile borders. But the context
around each processing unit was still allowed to cross tile borders.
This is fine in the usual case - but, when loop filtering across tiles
is switched off, we're supposed to be able to decode each tile completely
independently (each tile column, if dependent-horztiles is on).

Roughly, the change we need to make is:
When loop filtering across tiles is switched off, we treat each tile
as if it were a full frame, and extend the CDEF output for that tile
to form a 3-pixel border around the tile. We only use deblocked
above/below pixels for processing unit boundaries which lie inside
a tile.

In terms of the code, this is implemented in two parts. This only
applies when the loop_filter_across_tiles_flag is false; otherwise,
we keep the old behaviour.

* For processing units at the top edge of a tile, fill the above context
  with copies of the topmost line of CDEF output *from the same tile*,
  rather than using deblocked pixels from the tile above.
  The below context of processing units at the bottom edge of a tile
  is treated analogously.

* When setting up the boundary for a processing stripe at the left edge
  of a tile, fill the stripe's left boundary with copies of the
  leftmost column of CDEF output from the same tile. Again, processing
  stripes at the right edge of a tile are treated analogously.

  Similarly to the above/below boundaries, we store the overwritten
  pixels into a pair of left/right context buffers, and restore them
  to their original values once we've dealt with that processing stripe.

Change-Id: I53a0932793c1c56dc037683c6a4353a3f5dc4539
parent d728c216
This diff is collapsed.
......@@ -29,20 +29,20 @@ extern "C" {
#if CONFIG_STRIPED_LOOP_RESTORATION
// Filter tile grid offset upwards compared to the superblock grid
#define RESTORATION_TILE_OFFSET 8
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
#if CONFIG_STRIPED_LOOP_RESTORATION
#define SGRPROJ_BORDER_VERT 3 // Vertical border used for Sgr
#else
#define SGRPROJ_BORDER_VERT 3 // Vertical border used for Sgr
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
#define SGRPROJ_BORDER_HORZ 3 // Horizontal border used for Sgr
#if CONFIG_STRIPED_LOOP_RESTORATION
#define WIENER_BORDER_VERT 2 // Vertical border used for Wiener
#else
#define WIENER_BORDER_VERT 3 // Vertical border used for Wiener
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
#define WIENER_HALFWIN 3
#define WIENER_BORDER_HORZ (WIENER_HALFWIN) // Horizontal border for Wiener
......@@ -72,7 +72,7 @@ extern "C" {
// Additional pixels to the left and right in above/below buffers
// It is RESTORATION_BORDER_HORZ rounded up to get nicer buffer alignment
#define RESTORATION_EXTRA_HORZ 4
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
// Pad up to 20 more (may be much less is needed)
#define RESTORATION_PADDING 20
......@@ -95,7 +95,7 @@ extern "C" {
#define RESTORATION_TILEPELS_MAX \
((RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_BORDER_HORZ + 16) * \
(RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_BORDER_VERT))
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
// Two 32-bit buffers needed for the restored versions from two filters
// TODO(debargha, rupert): Refactor to not need the large tilesize to be stored
......@@ -230,6 +230,16 @@ typedef struct {
// stripe.
uint16_t tmp_save_above[RESTORATION_BORDER][RESTORATION_LINEBUFFER_WIDTH];
uint16_t tmp_save_below[RESTORATION_BORDER][RESTORATION_LINEBUFFER_WIDTH];
#if CONFIG_LOOPFILTERING_ACROSS_TILES
// Column buffers, for storing 3 pixels at the left/right of each tile
// when loopfiltering across tiles is disabled.
//
// Note: These arrays only need to store the pixels immediately left/right
// of each processing unit; the corner pixels (top-left, etc.) are always
// stored into the above/below arrays.
uint16_t tmp_save_left[RESTORATION_BORDER][RESTORATION_PROC_UNIT_SIZE];
uint16_t tmp_save_right[RESTORATION_BORDER][RESTORATION_PROC_UNIT_SIZE];
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
} RestorationLineBuffers;
typedef struct {
......@@ -237,7 +247,7 @@ typedef struct {
uint8_t *stripe_boundary_below;
int stripe_boundary_stride;
} RestorationStripeBoundaries;
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
typedef struct {
RestorationType frame_restoration_type;
......@@ -256,7 +266,7 @@ typedef struct {
RestorationUnitInfo *unit_info;
#if CONFIG_STRIPED_LOOP_RESTORATION
RestorationStripeBoundaries boundaries;
#endif
#endif // CONFIG_STRIPED_LOOP_RESTORATION
} RestorationInfo;
static INLINE void set_default_sgrproj(SgrprojInfo *sgrproj_info) {
......@@ -315,7 +325,10 @@ void av1_loop_restoration_filter_unit(
#if CONFIG_STRIPED_LOOP_RESTORATION
const RestorationStripeBoundaries *rsb, RestorationLineBuffers *rlbs,
const AV1PixelRect *tile_rect, int tile_stripe0,
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
int loop_filter_across_tiles_enabled,
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
#endif // CONFIG_STRIPED_LOOP_RESTORATION
int ss_x, int ss_y, int highbd, int bit_depth, uint8_t *data8, int stride,
uint8_t *dst8, int dst_stride, int32_t *tmpbuf);
......@@ -355,7 +368,8 @@ int av1_loop_restoration_corners_in_sb(const struct AV1Common *cm, int plane,
int *rrow1, int *tile_tl_idx);
void av1_loop_restoration_save_boundary_lines(const YV12_BUFFER_CONFIG *frame,
struct AV1Common *cm);
struct AV1Common *cm,
int after_cdef);
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -3705,7 +3705,7 @@ void av1_decode_tg_tiles_and_wrapup(AV1Decoder *pbi, const uint8_t *data,
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_loop_restoration_save_boundary_lines(&pbi->cur_buf->buf, cm);
av1_loop_restoration_save_boundary_lines(&pbi->cur_buf->buf, cm, 0);
}
#endif
......@@ -3723,6 +3723,7 @@ void av1_decode_tg_tiles_and_wrapup(AV1Decoder *pbi, const uint8_t *data,
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_loop_restoration_save_boundary_lines(&pbi->cur_buf->buf, cm, 1);
av1_loop_restoration_filter_frame((YV12_BUFFER_CONFIG *)xd->cur_buf, cm,
cm->rst_info, 7, NULL);
}
......
......@@ -4685,7 +4685,7 @@ static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) {
#if CONFIG_FRAME_SUPERRES && CONFIG_HORZONLY_FRAME_SUPERRES
if (!av1_superres_unscaled(cm)) aom_extend_frame_borders(cm->frame_to_show);
#endif
av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm);
av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm, 0);
#endif
#if CONFIG_CDEF
......@@ -4708,6 +4708,7 @@ static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) {
#endif // CONFIG_FRAME_SUPERRES
#if CONFIG_LOOP_RESTORATION
av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm, 1);
av1_pick_filter_restoration(cpi->source, cpi);
if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE ||
cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
......
......@@ -182,6 +182,9 @@ static int64_t try_restoration_tile(const RestSearchCtxt *rsc,
limits, rui,
#if CONFIG_STRIPED_LOOP_RESTORATION
&rsi->boundaries, &rlbs, tile_rect, rsc->tile_stripe0,
#if CONFIG_LOOPFILTERING_ACROSS_TILES
cm->loop_filter_across_tiles_enabled,
#endif
#endif
is_uv && cm->subsampling_x, is_uv && cm->subsampling_y, highbd, bit_depth,
fts->buffers[plane], fts->strides[is_uv], rsc->dst->buffers[plane],
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment