Correct striped-loop-restoration with multiple tile rows
Before this patch, striped loop restoration didn't restart correctly
on each tile row. Now, the loop restoration stripes start at the top
of a tile row in the same way as if it were the top of the entire
frame.
Change-Id: I0a88a28d7804b2f09d792ecbbf4f22f666f67012
diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c
index 18e03a8..b51e1c7 100644
--- a/av1/encoder/pickrst.c
+++ b/av1/encoder/pickrst.c
@@ -70,15 +70,103 @@
limits->v_start, limits->v_end - limits->v_start);
}
-static int64_t try_restoration_tile(const AV1_COMMON *cm,
- const YV12_BUFFER_CONFIG *src,
+typedef struct {
+ // The best coefficients for Wiener or Sgrproj restoration
+ WienerInfo wiener;
+ SgrprojInfo sgrproj;
+
+ // The sum of squared errors for this rtype.
+ int64_t sse[RESTORE_SWITCHABLE_TYPES];
+
+ // The rtype to use for this unit given a frame rtype as
+ // index. Indices: WIENER, SGRPROJ, SWITCHABLE.
+ RestorationType best_rtype[RESTORE_TYPES - 1];
+} RestUnitSearchInfo;
+
+typedef struct {
+ const YV12_BUFFER_CONFIG *src;
+ YV12_BUFFER_CONFIG *dst;
+
+ const AV1_COMMON *cm;
+ const MACROBLOCK *x;
+ int plane;
+ int plane_width;
+ int plane_height;
+ RestUnitSearchInfo *rusi;
+
+ uint8_t *dgd_buffer;
+ int dgd_stride;
+ const uint8_t *src_buffer;
+ int src_stride;
+
+ // sse and bits are initialised by reset_rsc in search_rest_type
+ int64_t sse;
+ int64_t bits;
+
+#if CONFIG_STRIPED_LOOP_RESTORATION
+ int tile_y0, tile_stripe0;
+#endif
+
+ // sgrproj and wiener are initialised by rsc_on_tile when starting the first
+ // tile in the frame.
+ SgrprojInfo sgrproj;
+ WienerInfo wiener;
+} RestSearchCtxt;
+
+static void rsc_on_tile(int tile_row, int tile_col, void *priv) {
+ (void)tile_col;
+
+ RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
+ set_default_sgrproj(&rsc->sgrproj);
+ set_default_wiener(&rsc->wiener);
+
+#if CONFIG_STRIPED_LOOP_RESTORATION
+ rsc->tile_stripe0 =
+ (tile_row == 0) ? 0 : rsc->cm->rst_end_stripe[tile_row - 1];
+#else
+ (void)tile_row;
+#endif
+}
+
+static void reset_rsc(RestSearchCtxt *rsc) {
+ rsc->sse = 0;
+ rsc->bits = 0;
+}
+
+static void init_rsc(const YV12_BUFFER_CONFIG *src, const AV1_COMMON *cm,
+ const MACROBLOCK *x, int plane, RestUnitSearchInfo *rusi,
+ YV12_BUFFER_CONFIG *dst, RestSearchCtxt *rsc) {
+ rsc->src = src;
+ rsc->dst = dst;
+ rsc->cm = cm;
+ rsc->x = x;
+ rsc->plane = plane;
+ rsc->rusi = rusi;
+
+ const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
+ const int is_uv = plane != AOM_PLANE_Y;
+ rsc->plane_width = src->crop_widths[is_uv];
+ rsc->plane_height = src->crop_heights[is_uv];
+ rsc->src_buffer = src->buffers[plane];
+ rsc->src_stride = src->strides[is_uv];
+ rsc->dgd_buffer = dgd->buffers[plane];
+ rsc->dgd_stride = dgd->strides[is_uv];
+ assert(src->crop_widths[is_uv] == dgd->crop_widths[is_uv]);
+ assert(src->crop_heights[is_uv] == dgd->crop_heights[is_uv]);
+}
+
+static int64_t try_restoration_tile(const RestSearchCtxt *rsc,
const RestorationTileLimits *limits,
- const RestorationUnitInfo *rui,
- YV12_BUFFER_CONFIG *dst, int plane) {
+ const AV1PixelRect *tile_rect,
+ const RestorationUnitInfo *rui) {
+ const AV1_COMMON *const cm = rsc->cm;
+ const int plane = rsc->plane;
const int is_uv = plane > 0;
#if CONFIG_STRIPED_LOOP_RESTORATION
const RestorationInfo *rsi = &cm->rst_info[plane];
RestorationLineBuffers rlbs;
+#else
+ (void)tile_rect;
#endif
#if CONFIG_HIGHBITDEPTH
const int bit_depth = cm->bit_depth;
@@ -93,13 +181,13 @@
av1_loop_restoration_filter_unit(
limits, rui,
#if CONFIG_STRIPED_LOOP_RESTORATION
- &rsi->boundaries, &rlbs,
+ &rsi->boundaries, &rlbs, tile_rect, rsc->tile_stripe0,
#endif
is_uv && cm->subsampling_x, is_uv && cm->subsampling_y, highbd, bit_depth,
- fts->buffers[plane], fts->strides[is_uv], dst->buffers[plane],
- dst->strides[is_uv], cm->rst_tmpbuf);
+ fts->buffers[plane], fts->strides[is_uv], rsc->dst->buffers[plane],
+ rsc->dst->strides[is_uv], cm->rst_tmpbuf);
- return sse_restoration_tile(limits, src, dst, plane, highbd);
+ return sse_restoration_tile(limits, rsc->src, rsc->dst, plane, highbd);
}
static int64_t get_pixel_proj_error(const uint8_t *src8, int width, int height,
@@ -390,82 +478,9 @@
return bits;
}
-typedef struct {
- // The best coefficients for Wiener or Sgrproj restoration
- WienerInfo wiener;
- SgrprojInfo sgrproj;
-
- // The sum of squared errors for this rtype.
- int64_t sse[RESTORE_SWITCHABLE_TYPES];
-
- // The rtype to use for this unit given a frame rtype as
- // index. Indices: WIENER, SGRPROJ, SWITCHABLE.
- RestorationType best_rtype[RESTORE_TYPES - 1];
-} RestUnitSearchInfo;
-
-typedef struct {
- const YV12_BUFFER_CONFIG *src;
- const AV1_COMMON *cm;
- const MACROBLOCK *x;
- int plane;
- int plane_width;
- int plane_height;
- RestUnitSearchInfo *rusi;
- YV12_BUFFER_CONFIG *dst_frame;
-
- uint8_t *dgd_buffer;
- int dgd_stride;
- const uint8_t *src_buffer;
- int src_stride;
-
- // sse and bits are initialised by reset_rsc in search_rest_type
- int64_t sse;
- int64_t bits;
-
- // sgrproj and wiener are initialised by rsc_on_tile when starting the first
- // tile in the frame.
- SgrprojInfo sgrproj;
- WienerInfo wiener;
-} RestSearchCtxt;
-
-static void rsc_on_tile(int tile_row, int tile_col, void *priv) {
- (void)tile_row;
- (void)tile_col;
-
- RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
- set_default_sgrproj(&rsc->sgrproj);
- set_default_wiener(&rsc->wiener);
-}
-
-static void reset_rsc(RestSearchCtxt *rsc) {
- rsc->sse = 0;
- rsc->bits = 0;
-}
-
-static void init_rsc(const YV12_BUFFER_CONFIG *src, const AV1_COMMON *cm,
- const MACROBLOCK *x, int plane, RestUnitSearchInfo *rusi,
- YV12_BUFFER_CONFIG *dst_frame, RestSearchCtxt *rsc) {
- rsc->src = src;
- rsc->cm = cm;
- rsc->x = x;
- rsc->plane = plane;
- rsc->rusi = rusi;
- rsc->dst_frame = dst_frame;
-
- const YV12_BUFFER_CONFIG *dgd = cm->frame_to_show;
- const int is_uv = plane != AOM_PLANE_Y;
- rsc->plane_width = src->crop_widths[is_uv];
- rsc->plane_height = src->crop_heights[is_uv];
- rsc->src_buffer = src->buffers[plane];
- rsc->src_stride = src->strides[is_uv];
- rsc->dgd_buffer = dgd->buffers[plane];
- rsc->dgd_stride = dgd->strides[is_uv];
- assert(src->crop_widths[is_uv] == dgd->crop_widths[is_uv]);
- assert(src->crop_heights[is_uv] == dgd->crop_heights[is_uv]);
-}
-
static void search_sgrproj(const RestorationTileLimits *limits,
- int rest_unit_idx, void *priv) {
+ const AV1PixelRect *tile, int rest_unit_idx,
+ void *priv) {
RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];
@@ -500,8 +515,7 @@
rui.restoration_type = RESTORE_SGRPROJ;
rui.sgrproj_info = rusi->sgrproj;
- rusi->sse[RESTORE_SGRPROJ] = try_restoration_tile(cm, rsc->src, limits, &rui,
- rsc->dst_frame, rsc->plane);
+ rusi->sse[RESTORE_SGRPROJ] = try_restoration_tile(rsc, limits, tile, &rui);
const int64_t bits_none = x->sgrproj_restore_cost[0];
const int64_t bits_sgr = x->sgrproj_restore_cost[1] +
@@ -878,13 +892,13 @@
}
#define USE_WIENER_REFINEMENT_SEARCH 1
-static int64_t finer_tile_search_wiener(
- const AV1_COMMON *cm, const YV12_BUFFER_CONFIG *src,
- const RestorationTileLimits *limits, RestorationUnitInfo *rui,
- int start_step, int plane, int wiener_win, YV12_BUFFER_CONFIG *dst_frame) {
+static int64_t finer_tile_search_wiener(const RestSearchCtxt *rsc,
+ const RestorationTileLimits *limits,
+ const AV1PixelRect *tile,
+ RestorationUnitInfo *rui,
+ int wiener_win) {
const int plane_off = (WIENER_WIN - wiener_win) >> 1;
- int64_t err = try_restoration_tile(cm, src, limits, rui, dst_frame, plane);
- (void)start_step;
+ int64_t err = try_restoration_tile(rsc, limits, tile, rui);
#if USE_WIENER_REFINEMENT_SEARCH
int64_t err2;
int tap_min[] = { WIENER_FILT_TAP0_MINV, WIENER_FILT_TAP1_MINV,
@@ -895,6 +909,7 @@
WienerInfo *plane_wiener = &rui->wiener_info;
// printf("err pre = %"PRId64"\n", err);
+ const int start_step = 4;
for (int s = start_step; s >= 1; s >>= 1) {
for (int p = plane_off; p < WIENER_HALFWIN; ++p) {
int skip = 0;
@@ -903,7 +918,7 @@
plane_wiener->hfilter[p] -= s;
plane_wiener->hfilter[WIENER_WIN - p - 1] -= s;
plane_wiener->hfilter[WIENER_HALFWIN] += 2 * s;
- err2 = try_restoration_tile(cm, src, limits, rui, dst_frame, plane);
+ err2 = try_restoration_tile(rsc, limits, tile, rui);
if (err2 > err) {
plane_wiener->hfilter[p] += s;
plane_wiener->hfilter[WIENER_WIN - p - 1] += s;
@@ -923,7 +938,7 @@
plane_wiener->hfilter[p] += s;
plane_wiener->hfilter[WIENER_WIN - p - 1] += s;
plane_wiener->hfilter[WIENER_HALFWIN] -= 2 * s;
- err2 = try_restoration_tile(cm, src, limits, rui, dst_frame, plane);
+ err2 = try_restoration_tile(rsc, limits, tile, rui);
if (err2 > err) {
plane_wiener->hfilter[p] -= s;
plane_wiener->hfilter[WIENER_WIN - p - 1] -= s;
@@ -944,7 +959,7 @@
plane_wiener->vfilter[p] -= s;
plane_wiener->vfilter[WIENER_WIN - p - 1] -= s;
plane_wiener->vfilter[WIENER_HALFWIN] += 2 * s;
- err2 = try_restoration_tile(cm, src, limits, rui, dst_frame, plane);
+ err2 = try_restoration_tile(rsc, limits, tile, rui);
if (err2 > err) {
plane_wiener->vfilter[p] += s;
plane_wiener->vfilter[WIENER_WIN - p - 1] += s;
@@ -964,7 +979,7 @@
plane_wiener->vfilter[p] += s;
plane_wiener->vfilter[WIENER_WIN - p - 1] += s;
plane_wiener->vfilter[WIENER_HALFWIN] -= 2 * s;
- err2 = try_restoration_tile(cm, src, limits, rui, dst_frame, plane);
+ err2 = try_restoration_tile(rsc, limits, tile, rui);
if (err2 > err) {
plane_wiener->vfilter[p] -= s;
plane_wiener->vfilter[WIENER_WIN - p - 1] -= s;
@@ -985,7 +1000,8 @@
}
static void search_wiener(const RestorationTileLimits *limits,
- int rest_unit_idx, void *priv) {
+ const AV1PixelRect *tile_rect, int rest_unit_idx,
+ void *priv) {
RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];
@@ -1040,8 +1056,7 @@
aom_clear_system_state();
rusi->sse[RESTORE_WIENER] =
- finer_tile_search_wiener(rsc->cm, rsc->src, limits, &rui, 4, rsc->plane,
- wiener_win, rsc->dst_frame);
+ finer_tile_search_wiener(rsc, limits, tile_rect, &rui, wiener_win);
rusi->wiener = rui.wiener_info;
if (wiener_win != WIENER_WIN) {
@@ -1071,7 +1086,10 @@
}
static void search_norestore(const RestorationTileLimits *limits,
- int rest_unit_idx, void *priv) {
+ const AV1PixelRect *tile_rect, int rest_unit_idx,
+ void *priv) {
+ (void)tile_rect;
+
RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];
@@ -1088,8 +1106,10 @@
}
static void search_switchable(const RestorationTileLimits *limits,
- int rest_unit_idx, void *priv) {
+ const AV1PixelRect *tile_rect, int rest_unit_idx,
+ void *priv) {
(void)limits;
+ (void)tile_rect;
RestSearchCtxt *rsc = (RestSearchCtxt *)priv;
RestUnitSearchInfo *rusi = &rsc->rusi[rest_unit_idx];