Commit bcb65fe6 authored by Rupert Swarbrick's avatar Rupert Swarbrick

Stop loop rest units from straddling tile boundaries

With this patch, restoration units are allocated within each tile as
if it were its own image. Arrays of information that need one entry
per restoration unit are laid out in tiles, with rsi->units_per_tile
units for each tile.

Change-Id: I485c17166f33e24d281079b3138b76f98f0fe081
parent 4be87e0f
......@@ -132,9 +132,15 @@ void av1_free_ref_frame_buffers(BufferPool *pool) {
}
#if CONFIG_LOOP_RESTORATION
// Assumes cm->rst_info[p].restoration_tilesize is already initialized
// Assumes cm->rst_info[p].restoration_unit_size is already initialized
void av1_alloc_restoration_buffers(AV1_COMMON *cm) {
int p;
for (int p = 0; p < MAX_MB_PLANE; ++p)
av1_alloc_restoration_struct(cm, &cm->rst_info[p], p > 0);
aom_free(cm->rst_tmpbuf);
CHECK_MEM_ERROR(cm, cm->rst_tmpbuf,
(int32_t *)aom_memalign(16, RESTORATION_TMPBUF_SIZE));
#if CONFIG_STRIPED_LOOP_RESTORATION
#if CONFIG_FRAME_SUPERRES
int width = cm->superres_upscaled_width;
int height = cm->superres_upscaled_height;
......@@ -142,18 +148,9 @@ void av1_alloc_restoration_buffers(AV1_COMMON *cm) {
int width = cm->width;
int height = cm->height;
#endif // CONFIG_FRAME_SUPERRES
av1_alloc_restoration_struct(cm, &cm->rst_info[0], width, height);
for (p = 1; p < MAX_MB_PLANE; ++p)
av1_alloc_restoration_struct(cm, &cm->rst_info[p],
ROUND_POWER_OF_TWO(width, cm->subsampling_x),
ROUND_POWER_OF_TWO(height, cm->subsampling_y));
aom_free(cm->rst_tmpbuf);
CHECK_MEM_ERROR(cm, cm->rst_tmpbuf,
(int32_t *)aom_memalign(16, RESTORATION_TMPBUF_SIZE));
#if CONFIG_STRIPED_LOOP_RESTORATION
// Allocate internal storage for the loop restoration stripe boundary lines
for (p = 0; p < MAX_MB_PLANE; ++p) {
for (int p = 0; p < MAX_MB_PLANE; ++p) {
int w = p == 0 ? width : ROUND_POWER_OF_TWO(width, cm->subsampling_x);
int align_bits = 5; // align for efficiency
int stride = ALIGN_POWER_OF_TWO(w + 2 * RESTORATION_EXTRA_HORZ, align_bits);
......
This diff is collapsed.
......@@ -234,8 +234,19 @@ typedef struct {
typedef struct {
RestorationType frame_restoration_type;
int restoration_tilesize;
int restoration_unit_size;
int procunit_width, procunit_height;
// Fields below here are allocated and initialised by
// av1_alloc_restoration_struct. (horz_)units_per_tile give the number of
// restoration units in (one row of) the largest tile in the frame. The data
// in unit_info is laid out with units_per_tile entries for each tile, which
// have stride horz_units_per_tile.
//
// Even if there are tiles of different sizes, the data in unit_info is laid
// out as if all tiles are of full size.
int units_per_tile;
int vert_units_per_tile, horz_units_per_tile;
RestorationUnitInfo *unit_info;
#if CONFIG_STRIPED_LOOP_RESTORATION
RestorationStripeBoundaries boundaries;
......@@ -259,20 +270,6 @@ static INLINE void set_default_wiener(WienerInfo *wiener_info) {
wiener_info->vfilter[6] = wiener_info->hfilter[6] = WIENER_FILT_TAP0_MIDV;
}
static INLINE int av1_get_rest_ntiles(int width, int height, int tilesize,
int *nhtiles, int *nvtiles) {
int nhtiles_, nvtiles_;
const int tile_width = (tilesize < 0) ? width : AOMMIN(tilesize, width);
const int tile_height = (tilesize < 0) ? height : AOMMIN(tilesize, height);
assert(tile_width > 0 && tile_height > 0);
nhtiles_ = (width + (tile_width >> 1)) / tile_width;
nvtiles_ = (height + (tile_height >> 1)) / tile_height;
if (nhtiles) *nhtiles = nhtiles_;
if (nvtiles) *nvtiles = nvtiles_;
return (nhtiles_ * nvtiles_);
}
typedef struct { int h_start, h_end, v_start, v_end; } RestorationTileLimits;
extern const sgr_params_type sgr_params[SGRPROJ_PARAMS];
......@@ -280,9 +277,8 @@ extern int sgrproj_mtable[MAX_EPS][MAX_NELEM];
extern const int32_t x_by_xplus1[256];
extern const int32_t one_by_x[MAX_NELEM];
int av1_alloc_restoration_struct(struct AV1Common *cm,
RestorationInfo *rst_info, int width,
int height);
void av1_alloc_restoration_struct(struct AV1Common *cm, RestorationInfo *rsi,
int is_uv);
void av1_free_restoration_struct(RestorationInfo *rst_info);
void extend_frame(uint8_t *data, int width, int height, int stride,
......@@ -344,14 +340,14 @@ void av1_foreach_rest_unit_in_frame(const struct AV1Common *cm, int plane,
// loop restoration tile.
//
// If the block is a top-level superblock, the function writes to
// *rcol0, *rcol1, *rrow0, *rrow1. The rectangle of indices given by
// [*rcol0, *rcol1) x [*rrow0, *rrow1) will point at the set of rtiles
// whose top left corners lie in the superblock. Note that the set is
// only nonempty if *rcol0 < *rcol1 and *rrow0 < *rrow1.
// *rcol0, *rcol1, *rrow0, *rrow1. The rectangle of restoration unit
// indices given by [*rcol0, *rcol1) x [*rrow0, *rrow1) are relative
// to the current tile, whose starting index is returned as
// *tile_tl_idx.
int av1_loop_restoration_corners_in_sb(const struct AV1Common *cm, int plane,
int mi_row, int mi_col, BLOCK_SIZE bsize,
int *rcol0, int *rcol1, int *rrow0,
int *rrow1, int *nhtiles);
int *rrow1, int *tile_tl_idx);
void av1_loop_restoration_save_boundary_lines(const YV12_BUFFER_CONFIG *frame,
struct AV1Common *cm);
......
......@@ -1287,13 +1287,14 @@ static void decode_partition(AV1Decoder *const pbi, MACROBLOCKD *const xd,
#endif // CONFIG_CDEF
#if CONFIG_LOOP_RESTORATION
for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
int rcol0, rcol1, rrow0, rrow1, nhtiles;
int rcol0, rcol1, rrow0, rrow1, tile_tl_idx;
if (av1_loop_restoration_corners_in_sb(cm, plane, mi_row, mi_col, bsize,
&rcol0, &rcol1, &rrow0, &rrow1,
&nhtiles)) {
&tile_tl_idx)) {
const int rstride = cm->rst_info[plane].horz_units_per_tile;
for (int rrow = rrow0; rrow < rrow1; ++rrow) {
for (int rcol = rcol0; rcol < rcol1; ++rcol) {
int rtile_idx = rcol + rrow * nhtiles;
const int rtile_idx = tile_tl_idx + rcol + rrow * rstride;
loop_restoration_read_sb_coeffs(cm, xd, r, plane, rtile_idx);
}
}
......@@ -1389,30 +1390,31 @@ static void decode_restoration_mode(AV1_COMMON *cm,
aom_rb_read_bit(rb) ? RESTORE_SWITCHABLE : 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;
cm->rst_info[0].restoration_unit_size = RESTORATION_TILESIZE_MAX;
cm->rst_info[1].restoration_unit_size = RESTORATION_TILESIZE_MAX;
cm->rst_info[2].restoration_unit_size = 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) {
cm->rst_info[0].restoration_tilesize = RESTORATION_TILESIZE_MAX >> 2;
cm->rst_info[1].restoration_tilesize = RESTORATION_TILESIZE_MAX >> 2;
cm->rst_info[2].restoration_tilesize = RESTORATION_TILESIZE_MAX >> 2;
cm->rst_info[0].restoration_unit_size = RESTORATION_TILESIZE_MAX >> 2;
cm->rst_info[1].restoration_unit_size = RESTORATION_TILESIZE_MAX >> 2;
cm->rst_info[2].restoration_unit_size = RESTORATION_TILESIZE_MAX >> 2;
rsi = &cm->rst_info[0];
rsi->restoration_tilesize <<= aom_rb_read_bit(rb);
if (rsi->restoration_tilesize != (RESTORATION_TILESIZE_MAX >> 2)) {
rsi->restoration_tilesize <<= aom_rb_read_bit(rb);
rsi->restoration_unit_size <<= aom_rb_read_bit(rb);
if (rsi->restoration_unit_size != (RESTORATION_TILESIZE_MAX >> 2)) {
rsi->restoration_unit_size <<= aom_rb_read_bit(rb);
}
}
int s = AOMMIN(cm->subsampling_x, cm->subsampling_y);
if (s && (cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
cm->rst_info[2].frame_restoration_type != RESTORE_NONE)) {
cm->rst_info[1].restoration_tilesize =
cm->rst_info[0].restoration_tilesize >> (aom_rb_read_bit(rb) * s);
cm->rst_info[1].restoration_unit_size =
cm->rst_info[0].restoration_unit_size >> (aom_rb_read_bit(rb) * s);
} else {
cm->rst_info[1].restoration_tilesize = cm->rst_info[0].restoration_tilesize;
cm->rst_info[1].restoration_unit_size =
cm->rst_info[0].restoration_unit_size;
}
cm->rst_info[2].restoration_tilesize = cm->rst_info[1].restoration_tilesize;
cm->rst_info[2].restoration_unit_size = cm->rst_info[1].restoration_unit_size;
cm->rst_info[0].procunit_width = cm->rst_info[0].procunit_height =
RESTORATION_PROC_UNIT_SIZE;
......
......@@ -2675,13 +2675,14 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile,
#endif
#if CONFIG_LOOP_RESTORATION
for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
int rcol0, rcol1, rrow0, rrow1, nhtiles;
int rcol0, rcol1, rrow0, rrow1, tile_tl_idx;
if (av1_loop_restoration_corners_in_sb(cm, plane, mi_row, mi_col, bsize,
&rcol0, &rcol1, &rrow0, &rrow1,
&nhtiles)) {
&tile_tl_idx)) {
const int rstride = cm->rst_info[plane].horz_units_per_tile;
for (int rrow = rrow0; rrow < rrow1; ++rrow) {
for (int rcol = rcol0; rcol < rcol1; ++rcol) {
int rtile_idx = rcol + rrow * nhtiles;
const int rtile_idx = tile_tl_idx + rcol + rrow * rstride;
const RestorationUnitInfo *rui =
&cm->rst_info[plane].unit_info[rtile_idx];
loop_restoration_write_sb_coeffs(cm, xd, rui, w, plane);
......@@ -2767,29 +2768,29 @@ static void encode_restoration_mode(AV1_COMMON *cm,
cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
cm->rst_info[2].frame_restoration_type != RESTORE_NONE) {
aom_wb_write_bit(
wb, rsi->restoration_tilesize != (RESTORATION_TILESIZE_MAX >> 2));
if (rsi->restoration_tilesize != (RESTORATION_TILESIZE_MAX >> 2)) {
wb, rsi->restoration_unit_size != (RESTORATION_TILESIZE_MAX >> 2));
if (rsi->restoration_unit_size != (RESTORATION_TILESIZE_MAX >> 2)) {
aom_wb_write_bit(
wb, rsi->restoration_tilesize != (RESTORATION_TILESIZE_MAX >> 1));
wb, rsi->restoration_unit_size != (RESTORATION_TILESIZE_MAX >> 1));
}
}
int s = AOMMIN(cm->subsampling_x, cm->subsampling_y);
if (s && (cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
cm->rst_info[2].frame_restoration_type != RESTORE_NONE)) {
aom_wb_write_bit(wb,
cm->rst_info[1].restoration_tilesize !=
cm->rst_info[0].restoration_tilesize);
assert(cm->rst_info[1].restoration_tilesize ==
cm->rst_info[0].restoration_tilesize ||
cm->rst_info[1].restoration_tilesize ==
(cm->rst_info[0].restoration_tilesize >> s));
assert(cm->rst_info[2].restoration_tilesize ==
cm->rst_info[1].restoration_tilesize);
cm->rst_info[1].restoration_unit_size !=
cm->rst_info[0].restoration_unit_size);
assert(cm->rst_info[1].restoration_unit_size ==
cm->rst_info[0].restoration_unit_size ||
cm->rst_info[1].restoration_unit_size ==
(cm->rst_info[0].restoration_unit_size >> s));
assert(cm->rst_info[2].restoration_unit_size ==
cm->rst_info[1].restoration_unit_size);
} else if (!s) {
assert(cm->rst_info[1].restoration_tilesize ==
cm->rst_info[0].restoration_tilesize);
assert(cm->rst_info[2].restoration_tilesize ==
cm->rst_info[1].restoration_tilesize);
assert(cm->rst_info[1].restoration_unit_size ==
cm->rst_info[0].restoration_unit_size);
assert(cm->rst_info[2].restoration_unit_size ==
cm->rst_info[1].restoration_unit_size);
}
}
......
......@@ -4171,8 +4171,8 @@ static void init_motion_estimation(AV1_COMP *cpi) {
#if CONFIG_LOOP_RESTORATION
#define COUPLED_CHROMA_FROM_LUMA_RESTORATION 0
static void set_restoration_tilesize(int width, int height, int sx, int sy,
RestorationInfo *rst) {
static void set_restoration_unit_size(int width, int height, int sx, int sy,
RestorationInfo *rst) {
(void)width;
(void)height;
(void)sx;
......@@ -4183,9 +4183,9 @@ static void set_restoration_tilesize(int width, int height, int sx, int sy,
int s = 0;
#endif // !COUPLED_CHROMA_FROM_LUMA_RESTORATION
rst[0].restoration_tilesize = (RESTORATION_TILESIZE_MAX >> 1);
rst[1].restoration_tilesize = rst[0].restoration_tilesize >> s;
rst[2].restoration_tilesize = rst[1].restoration_tilesize;
rst[0].restoration_unit_size = (RESTORATION_TILESIZE_MAX >> 1);
rst[1].restoration_unit_size = rst[0].restoration_unit_size >> s;
rst[2].restoration_unit_size = rst[1].restoration_unit_size;
rst[0].procunit_width = rst[0].procunit_height = RESTORATION_PROC_UNIT_SIZE;
rst[1].procunit_width = rst[2].procunit_width =
......@@ -4307,8 +4307,8 @@ static void set_frame_size(AV1_COMP *cpi, int width, int height) {
const int frame_width = cm->width;
const int frame_height = cm->height;
#endif
set_restoration_tilesize(frame_width, frame_height, cm->subsampling_x,
cm->subsampling_y, cm->rst_info);
set_restoration_unit_size(frame_width, frame_height, cm->subsampling_x,
cm->subsampling_y, cm->rst_info);
for (int i = 0; i < MAX_MB_PLANE; ++i)
cm->rst_info[i].frame_restoration_type = RESTORE_NONE;
......
......@@ -1158,14 +1158,17 @@ static double search_rest_type(RestSearchCtxt *rsc, RestorationType rtype) {
return RDCOST_DBL(rsc->x->rdmult, rsc->bits >> 4, rsc->sse);
}
static int rest_tiles_in_plane(const AV1_COMMON *cm, int plane) {
const RestorationInfo *rsi = &cm->rst_info[plane];
return cm->tile_rows * cm->tile_cols * rsi->units_per_tile;
}
void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
int ntiles[2];
for (int is_uv = 0; is_uv < 2; ++is_uv)
ntiles[is_uv] = av1_get_rest_ntiles(
src->crop_widths[is_uv], src->crop_heights[is_uv],
cm->rst_info[is_uv].restoration_tilesize, NULL, NULL);
ntiles[is_uv] = rest_tiles_in_plane(cm, is_uv);
assert(ntiles[1] <= ntiles[0]);
RestUnitSearchInfo *rusi =
......
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