summaryrefslogtreecommitdiffstats
path: root/third_party/aom/av1/common/restoration.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/aom/av1/common/restoration.h')
-rw-r--r--third_party/aom/av1/common/restoration.h189
1 files changed, 137 insertions, 52 deletions
diff --git a/third_party/aom/av1/common/restoration.h b/third_party/aom/av1/common/restoration.h
index 477f20a42..23a53879e 100644
--- a/third_party/aom/av1/common/restoration.h
+++ b/third_party/aom/av1/common/restoration.h
@@ -24,18 +24,77 @@ extern "C" {
#define CLIP(x, lo, hi) ((x) < (lo) ? (lo) : (x) > (hi) ? (hi) : (x))
#define RINT(x) ((x) < 0 ? (int)((x)-0.5) : (int)((x) + 0.5))
+#define RESTORATION_PROC_UNIT_SIZE 64
+
+#if CONFIG_STRIPED_LOOP_RESTORATION
+// Filter tile grid offset upwards compared to the superblock grid
+#define RESTORATION_TILE_OFFSET 8
+#endif
+
+#if CONFIG_STRIPED_LOOP_RESTORATION
+#define SGRPROJ_BORDER_VERT 2 // Vertical border used for Sgr
+#else
+#define SGRPROJ_BORDER_VERT 1 // Vertical border used for Sgr
+#endif
+#define SGRPROJ_BORDER_HORZ 2 // 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 1 // Vertical border used for Wiener
+#endif
+#define WIENER_HALFWIN 3
+#define WIENER_BORDER_HORZ (WIENER_HALFWIN) // Horizontal border for Wiener
+
+// RESTORATION_BORDER_VERT determines line buffer requirement for LR.
+// Should be set at the max of SGRPROJ_BORDER_VERT and WIENER_BORDER_VERT.
+// Note the line buffer needed is twice the value of this macro.
+#if SGRPROJ_BORDER_VERT >= WIENER_BORDER_VERT
+#define RESTORATION_BORDER_VERT (SGRPROJ_BORDER_VERT)
+#else
+#define RESTORATION_BORDER_VERT (WIENER_BORDER_VERT)
+#endif // SGRPROJ_BORDER_VERT >= WIENER_BORDER_VERT
+
+#if SGRPROJ_BORDER_HORZ >= WIENER_BORDER_HORZ
+#define RESTORATION_BORDER_HORZ (SGRPROJ_BORDER_HORZ)
+#else
+#define RESTORATION_BORDER_HORZ (WIENER_BORDER_HORZ)
+#endif // SGRPROJ_BORDER_VERT >= WIENER_BORDER_VERT
+
+#if CONFIG_STRIPED_LOOP_RESTORATION
+// 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
+
+// Pad up to 20 more (may be much less is needed)
+#define RESTORATION_PADDING 20
+#define RESTORATION_PROC_UNIT_PELS \
+ ((RESTORATION_PROC_UNIT_SIZE + RESTORATION_BORDER_HORZ * 2 + \
+ RESTORATION_PADDING) * \
+ (RESTORATION_PROC_UNIT_SIZE + RESTORATION_BORDER_VERT * 2 + \
+ RESTORATION_PADDING))
+
#define RESTORATION_TILESIZE_MAX 256
+#if CONFIG_STRIPED_LOOP_RESTORATION
+#define RESTORATION_TILEPELS_HORZ_MAX \
+ (RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_BORDER_HORZ + 16)
+#define RESTORATION_TILEPELS_VERT_MAX \
+ ((RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_BORDER_VERT + \
+ RESTORATION_TILE_OFFSET))
#define RESTORATION_TILEPELS_MAX \
- (RESTORATION_TILESIZE_MAX * RESTORATION_TILESIZE_MAX * 9 / 4)
-
-// 4 32-bit buffers needed for the filter:
-// 2 for the restored versions of the frame and
-// 2 for each restoration operation
-#define SGRPROJ_OUTBUF_SIZE \
- ((RESTORATION_TILESIZE_MAX * 3 / 2) * (RESTORATION_TILESIZE_MAX * 3 / 2 + 16))
-#define SGRPROJ_TMPBUF_SIZE \
- (RESTORATION_TILEPELS_MAX * 2 * sizeof(int32_t) + \
- SGRPROJ_OUTBUF_SIZE * 2 * sizeof(int32_t))
+ (RESTORATION_TILEPELS_HORZ_MAX * RESTORATION_TILEPELS_VERT_MAX)
+#else
+#define RESTORATION_TILEPELS_MAX \
+ ((RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_BORDER_HORZ + 16) * \
+ (RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_BORDER_VERT))
+#endif
+
+// 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
+// on the decoder side.
+#define SGRPROJ_TMPBUF_SIZE (RESTORATION_TILEPELS_MAX * 2 * sizeof(int32_t))
+
#define SGRPROJ_EXTBUF_SIZE (0)
#define SGRPROJ_PARAMS_BITS 4
#define SGRPROJ_PARAMS (1 << SGRPROJ_PARAMS_BITS)
@@ -65,19 +124,22 @@ extern "C" {
#define SGRPROJ_BITS (SGRPROJ_PRJ_BITS * 2 + SGRPROJ_PARAMS_BITS)
-#define MAX_RADIUS 3 // Only 1, 2, 3 allowed
+#define MAX_RADIUS 2 // Only 1, 2, 3 allowed
#define MAX_EPS 80 // Max value of eps
#define MAX_NELEM ((2 * MAX_RADIUS + 1) * (2 * MAX_RADIUS + 1))
#define SGRPROJ_MTABLE_BITS 20
#define SGRPROJ_RECIP_BITS 12
-#define WIENER_HALFWIN 3
#define WIENER_HALFWIN1 (WIENER_HALFWIN + 1)
#define WIENER_WIN (2 * WIENER_HALFWIN + 1)
#define WIENER_WIN2 ((WIENER_WIN) * (WIENER_WIN))
#define WIENER_TMPBUF_SIZE (0)
#define WIENER_EXTBUF_SIZE (0)
+// If WIENER_WIN_CHROMA == WIENER_WIN - 2, that implies 5x5 filters are used for
+// chroma. To use 7x7 for chroma set WIENER_WIN_CHROMA to WIENER_WIN.
+#define WIENER_WIN_CHROMA (WIENER_WIN - 2)
+
#define WIENER_FILT_PREC_BITS 7
#define WIENER_FILT_STEP (1 << WIENER_FILT_PREC_BITS)
@@ -131,10 +193,6 @@ extern "C" {
#if WIENER_FILT_PREC_BITS != 7
#error "Wiener filter currently only works if WIENER_FILT_PREC_BITS == 7"
#endif
-typedef struct {
- DECLARE_ALIGNED(16, InterpKernel, vfilter);
- DECLARE_ALIGNED(16, InterpKernel, hfilter);
-} WienerInfo;
typedef struct {
#if USE_HIGHPASS_IN_SGRPROJ
@@ -149,12 +207,8 @@ typedef struct {
} sgr_params_type;
typedef struct {
- int ep;
- int xqd[2];
-} SgrprojInfo;
-
-typedef struct {
int restoration_tilesize;
+ int procunit_width, procunit_height;
RestorationType frame_restoration_type;
RestorationType *restoration_type;
// Wiener filter
@@ -170,6 +224,20 @@ typedef struct {
int tile_width, tile_height;
int nhtiles, nvtiles;
int32_t *tmpbuf;
+#if CONFIG_STRIPED_LOOP_RESTORATION
+ int component;
+ int subsampling_y;
+ uint8_t *stripe_boundary_above[MAX_MB_PLANE];
+ uint8_t *stripe_boundary_below[MAX_MB_PLANE];
+ int stripe_boundary_stride[MAX_MB_PLANE];
+ // Temporary buffers to save/restore 2 lines above/below the restoration
+ // stripe
+ // Allow for filter margin to left and right
+ uint16_t
+ tmp_save_above[2][RESTORATION_TILESIZE_MAX + 2 * RESTORATION_EXTRA_HORZ];
+ uint16_t
+ tmp_save_below[2][RESTORATION_TILESIZE_MAX + 2 * RESTORATION_EXTRA_HORZ];
+#endif
} RestorationInternal;
static INLINE void set_default_sgrproj(SgrprojInfo *sgrproj_info) {
@@ -196,6 +264,8 @@ static INLINE int av1_get_rest_ntiles(int width, int height, int tilesize,
int tile_width_, tile_height_;
tile_width_ = (tilesize < 0) ? width : AOMMIN(tilesize, width);
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 (tile_width) *tile_width = tile_width_;
@@ -205,37 +275,33 @@ static INLINE int av1_get_rest_ntiles(int width, int height, int tilesize,
return (nhtiles_ * nvtiles_);
}
-static INLINE void av1_get_rest_tile_limits(
- int tile_idx, int subtile_idx, int subtile_bits, int nhtiles, int nvtiles,
- int tile_width, int tile_height, int im_width, int im_height, int clamp_h,
- int clamp_v, int *h_start, int *h_end, int *v_start, int *v_end) {
+typedef struct { int h_start, h_end, v_start, v_end; } RestorationTileLimits;
+
+static INLINE RestorationTileLimits
+av1_get_rest_tile_limits(int tile_idx, int nhtiles, int nvtiles, int tile_width,
+ int tile_height, int im_width,
+#if CONFIG_STRIPED_LOOP_RESTORATION
+ int im_height, int subsampling_y) {
+#else
+ int im_height) {
+#endif
const int htile_idx = tile_idx % nhtiles;
const int vtile_idx = tile_idx / nhtiles;
- *h_start = htile_idx * tile_width;
- *v_start = vtile_idx * tile_height;
- *h_end = (htile_idx < nhtiles - 1) ? *h_start + tile_width : im_width;
- *v_end = (vtile_idx < nvtiles - 1) ? *v_start + tile_height : im_height;
- if (subtile_bits) {
- const int num_subtiles_1d = (1 << subtile_bits);
- const int subtile_width = (*h_end - *h_start) >> subtile_bits;
- const int subtile_height = (*v_end - *v_start) >> subtile_bits;
- const int subtile_idx_h = subtile_idx & (num_subtiles_1d - 1);
- const int subtile_idx_v = subtile_idx >> subtile_bits;
- *h_start += subtile_idx_h * subtile_width;
- *v_start += subtile_idx_v * subtile_height;
- *h_end = subtile_idx_h == num_subtiles_1d - 1 ? *h_end
- : *h_start + subtile_width;
- *v_end = subtile_idx_v == num_subtiles_1d - 1 ? *v_end
- : *v_start + subtile_height;
- }
- if (clamp_h) {
- *h_start = AOMMAX(*h_start, clamp_h);
- *h_end = AOMMIN(*h_end, im_width - clamp_h);
- }
- if (clamp_v) {
- *v_start = AOMMAX(*v_start, clamp_v);
- *v_end = AOMMIN(*v_end, im_height - clamp_v);
- }
+ RestorationTileLimits limits;
+ limits.h_start = htile_idx * tile_width;
+ limits.v_start = vtile_idx * tile_height;
+ limits.h_end =
+ (htile_idx < nhtiles - 1) ? limits.h_start + tile_width : im_width;
+ limits.v_end =
+ (vtile_idx < nvtiles - 1) ? limits.v_start + tile_height : im_height;
+#if CONFIG_STRIPED_LOOP_RESTORATION
+ // Offset the tile upwards to align with the restoration processing stripe
+ limits.v_start -= RESTORATION_TILE_OFFSET >> subsampling_y;
+ if (limits.v_start < 0) limits.v_start = 0;
+ if (limits.v_end < im_height)
+ limits.v_end -= RESTORATION_TILE_OFFSET >> subsampling_y;
+#endif
+ return limits;
}
extern const sgr_params_type sgr_params[SGRPROJ_PARAMS];
@@ -248,15 +314,34 @@ int av1_alloc_restoration_struct(struct AV1Common *cm,
int height);
void av1_free_restoration_struct(RestorationInfo *rst_info);
-void extend_frame(uint8_t *data, int width, int height, int stride);
+void extend_frame(uint8_t *data, int width, int height, int stride,
+ int border_horz, int border_vert);
#if CONFIG_HIGHBITDEPTH
-void extend_frame_highbd(uint16_t *data, int width, int height, int stride);
+void extend_frame_highbd(uint16_t *data, int width, int height, int stride,
+ int border_horz, int border_vert);
#endif // CONFIG_HIGHBITDEPTH
void decode_xq(int *xqd, int *xq);
void av1_loop_restoration_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm,
RestorationInfo *rsi, int components_pattern,
int partial_frame, YV12_BUFFER_CONFIG *dst);
void av1_loop_restoration_precal();
+
+// Return 1 iff the block at mi_row, mi_col with size bsize is a
+// top-level superblock containing the top-left corner of at least one
+// 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.
+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);
+
+void av1_loop_restoration_save_boundary_lines(YV12_BUFFER_CONFIG *frame,
+ struct AV1Common *cm);
#ifdef __cplusplus
} // extern "C"
#endif