Commit 1e7f2d0c authored by Ola Hugosson's avatar Ola Hugosson Committed by Ola Hugosson

Add striped_loop_restoration experiment

This experiment offset the filter tile grid 8 pixels upwards.
Deblocked pixels (rather than CDEFed pixels) are used for the
2 lines above and below the filter processing unit. The 8 pixel
offset is the offset produced by deblock/cdef. This way the
loop_restoration does not need additional line buffers in a
single pass hardware implementation.

Change-Id: I89e0831dc28413a5d3e02d7a426ce2885ab629d7
parent 7f7dd08a
......@@ -135,6 +135,33 @@ void av1_alloc_restoration_buffers(AV1_COMMON *cm) {
aom_free(cm->rst_internal.tmpbuf);
CHECK_MEM_ERROR(cm, cm->rst_internal.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) {
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, align_bits);
int num_stripes = (height + 63) / 64;
// for each processing stripe: 2 lines above, 2 below
int buf_size = num_stripes * 2 * stride;
uint8_t *above_buf, *below_buf;
aom_free(cm->rst_internal.stripe_boundary_above[p]);
aom_free(cm->rst_internal.stripe_boundary_below[p]);
#if CONFIG_HIGHBITDEPTH
if (cm->use_highbitdepth) buf_size = buf_size * 2;
#endif
CHECK_MEM_ERROR(cm, above_buf,
(uint8_t *)aom_memalign(1 << align_bits, buf_size));
CHECK_MEM_ERROR(cm, below_buf,
(uint8_t *)aom_memalign(1 << align_bits, buf_size));
cm->rst_internal.stripe_boundary_above[p] = above_buf;
cm->rst_internal.stripe_boundary_below[p] = below_buf;
cm->rst_internal.stripe_boundary_stride[p] = stride;
}
#endif // CONFIG_STRIPED_LOOP_RESTORATION
}
void av1_free_restoration_buffers(AV1_COMMON *cm) {
......
This diff is collapsed.
......@@ -26,10 +26,23 @@ extern "C" {
#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
......@@ -48,6 +61,12 @@ extern "C" {
#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 \
......@@ -57,9 +76,19 @@ extern "C" {
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_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
......@@ -195,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) {
......@@ -236,7 +279,12 @@ 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, int im_height) {
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;
RestorationTileLimits limits;
......@@ -246,6 +294,13 @@ av1_get_rest_tile_limits(int tile_idx, int nhtiles, int nvtiles, int tile_width,
(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;
}
......@@ -284,6 +339,9 @@ 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
......
......@@ -86,6 +86,10 @@
#include "av1/common/cfl.h"
#endif
#if CONFIG_STRIPED_LOOP_RESTORATION && !CONFIG_LOOP_RESTORATION
#error "striped_loop_restoration requires loop_restoration"
#endif
#if CONFIG_LOOP_RESTORATION
static void loop_restoration_read_sb_coeffs(const AV1_COMMON *const cm,
MACROBLOCKD *xd,
......@@ -5589,6 +5593,14 @@ void av1_decode_frame(AV1Decoder *pbi, const uint8_t *data,
cm->tile_rows * cm->tile_cols - 1);
}
#if CONFIG_STRIPED_LOOP_RESTORATION
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);
}
#endif
#if CONFIG_CDEF
if (!cm->skip_loop_filter && !cm->all_lossless) {
av1_cdef_frame(&pbi->cur_buf->buf, cm, &pbi->mb);
......@@ -5905,6 +5917,14 @@ void av1_decode_tg_tiles_and_wrapup(AV1Decoder *pbi, const uint8_t *data,
return;
}
#if CONFIG_STRIPED_LOOP_RESTORATION
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);
}
#endif
#if CONFIG_CDEF
if (!cm->skip_loop_filter && !cm->all_lossless) {
av1_cdef_frame(&pbi->cur_buf->buf, cm, &pbi->mb);
......
......@@ -4525,6 +4525,10 @@ static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) {
#endif
}
#if CONFIG_STRIPED_LOOP_RESTORATION
av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm);
#endif
#if CONFIG_CDEF
if (is_lossless_requested(&cpi->oxcf)) {
cm->cdef_bits = 0;
......
......@@ -150,7 +150,12 @@ static int64_t try_restoration_tile(const YV12_BUFFER_CONFIG *src,
av1_loop_restoration_frame(cm->frame_to_show, cm, rsi, components_pattern,
partial_frame, dst_frame);
RestorationTileLimits limits = av1_get_rest_tile_limits(
tile_idx, nhtiles, nvtiles, tile_width, tile_height, width, height);
tile_idx, nhtiles, nvtiles, tile_width, tile_height, width,
#if CONFIG_STRIPED_LOOP_RESTORATION
height, components_pattern > 1 ? cm->subsampling_y : 0);
#else
height);
#endif
filt_err = sse_restoration_tile(
src, dst_frame, cm, limits.h_start, limits.h_end - limits.h_start,
limits.v_start, limits.v_end - limits.v_start, components_pattern);
......@@ -550,7 +555,12 @@ static void foreach_rtile_in_tile(const struct rest_search_ctxt *ctxt,
const int rtile_idx = rtile_row * ctxt->nrtiles_x + rtile_col;
RestorationTileLimits limits = av1_get_rest_tile_limits(
rtile_idx, ctxt->nrtiles_x, ctxt->nrtiles_y, rtile_width,
rtile_height, ctxt->plane_width, ctxt->plane_height);
rtile_height, ctxt->plane_width,
#if CONFIG_STRIPED_LOOP_RESTORATION
ctxt->plane_height, ctxt->plane > 0 ? cm->subsampling_y : 0);
#else
ctxt->plane_height);
#endif
fun(ctxt, rtile_idx, &limits, arg);
}
}
......@@ -1324,7 +1334,12 @@ static double search_norestore(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi,
info->frame_restoration_type = RESTORE_NONE;
for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
RestorationTileLimits limits = av1_get_rest_tile_limits(
tile_idx, nhtiles, nvtiles, tile_width, tile_height, width, height);
tile_idx, nhtiles, nvtiles, tile_width, tile_height, width,
#if CONFIG_STRIPED_LOOP_RESTORATION
height, plane != AOM_PLANE_Y ? cm->subsampling_y : 0);
#else
height);
#endif
err = sse_restoration_tile(src, cm->frame_to_show, cm, limits.h_start,
limits.h_end - limits.h_start, limits.v_start,
limits.v_end - limits.v_start, 1 << plane);
......
......@@ -196,6 +196,7 @@ set(CONFIG_SBL_SYMBOL 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SEGMENT_ZEROMV 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SMOOTH_HV 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SPEED_REFS 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_STRIPED_LOOP_RESTORATION 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SUPERTX 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TEMPMV_SIGNALING 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TPL_MV 0 CACHE NUMBER "AV1 experiment flag.")
......
......@@ -220,6 +220,12 @@ if (CONFIG_EXT_COMP_REFS)
endif()
endif()
if (CONFIG_STRIPED_LOOP_RESTORATION)
if (NOT CONFIG_LOOP_RESTORATION)
change_config_and_warn(CONFIG_LOOP_RESTORATION 1 CONFIG_STRIPED_LOOP_RESTORATION)
endif()
endif()
if (CONFIG_WARPED_MOTION)
if (CONFIG_NCOBMC)
change_config_and_warn(CONFIG_NCOBMC 0 CONFIG_WARPED_MOTION)
......
......@@ -276,6 +276,7 @@ EXPERIMENT_LIST="
supertx
ans
loop_restoration
striped_loop_restoration
ext_partition
ext_partition_types
ext_partition_types_ab
......@@ -626,6 +627,17 @@ post_process_cmdline() {
log_echo "amvr requires hash_me"
enable_feature hash_me
fi
if enabled striped_loop_restoration && ! enabled loop_restoration ; then
log_echo "striped_loop_restoration requires loop_restoration"
log_echo "enable loop_restoration"
enable_feature loop_restoration
fi
if enabled striped_loop_restoration && enabled frame_superres ; then
log_echo "striped_loop_restoration not compatible with frame_superres"
log_echo "disabling striped_loop_restoration"
disable_feature striped_loop_restoration
fi
}
process_targets() {
......
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