Commit 7bb501d5 authored by Lei's avatar Lei Committed by Ryan Lei

add new experiment loopfiltering_across_tiles_ext

based on the latest discussion in the HW working group about how loop
filter should be integrated with tiles, the following decisions have been
made:
1. two seperated flages should be added for
loop_filter_across_tiles_enabled for horizontal tile boundary and
vertical tile boundary.
2. encoder and decoder should only check these two flags to determine
whether loop filtering (including deblocking, CDEF and loop restoration)
should cross tile boundaries (vertical and/or horizontal) or not
regardless the horitontal depepdent tile flag.

This change list implemented the support for two seperated
loop_filter_across_tiles_enabled flags for vertical and horizontal tile
boundaries. The new experiment is disabled as default before it is
adopted.

Change-Id: I814377947517f5419c08b004a3b71b950d01eadd
parent f263044f
......@@ -553,6 +553,21 @@ enum aome_enc_control_id {
*/
AV1E_SET_DISABLE_TEMPMV,
/*!\brief Codec control function to set loop_filter_across_tiles_v_enabled
* and loop_filter_across_tiles_h_enabled.
* In encoding and decoding, AV1 allows disabling loop filter across tile
* boundary The parameter for this control describes the value of this flag,
* which has a valid range [0, 1]:
* 0 = disable loop filter across tile boundary
* 1 = enable loop filter across tile boundary
*
* By default, the value is 1, i.e. enable loop filter across tile boundary.
*
* Experiment: LOOPFILTERING_ACROSS_TILES_EXT
*/
AV1E_SET_TILE_LOOPFILTER_V,
AV1E_SET_TILE_LOOPFILTER_H,
/*!\brief Codec control function to set loop_filter_across_tiles_enabled.
*
* In encoding and decoding, AV1 allows disabling loop filter across tile
......@@ -726,6 +741,10 @@ AOM_CTRL_USE_TYPE(AV1E_SET_TILE_ROWS, int)
AOM_CTRL_USE_TYPE(AV1E_SET_TILE_DEPENDENT_ROWS, int)
#define AOM_CTRL_AV1E_SET_TILE_DEPENDENT_ROWS
AOM_CTRL_USE_TYPE(AV1E_SET_TILE_LOOPFILTER_V, int)
#define AOM_CTRL_AV1E_SET_TILE_LOOPFILTER_V
AOM_CTRL_USE_TYPE(AV1E_SET_TILE_LOOPFILTER_H, int)
#define AOM_CTRL_AV1E_SET_TILE_LOOPFILTER_H
AOM_CTRL_USE_TYPE(AV1E_SET_TILE_LOOPFILTER, int)
#define AOM_CTRL_AV1E_SET_TILE_LOOPFILTER
......
......@@ -434,8 +434,17 @@ static const arg_def_t tile_dependent_rows =
ARG_DEF(NULL, "tile-dependent-rows", 1, "Enable dependent Tile rows");
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
static const arg_def_t tile_loopfilter_v =
ARG_DEF(NULL, "tile-loopfilter-v", 1,
"Enable loop filter across vertical tile boundary");
static const arg_def_t tile_loopfilter_h =
ARG_DEF(NULL, "tile-loopfilter-h", 1,
"Enable loop filter across horizontal tile boundary");
#else
static const arg_def_t tile_loopfilter = ARG_DEF(
NULL, "tile-loopfilter", 1, "Enable loop filter across tile boundary");
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
static const arg_def_t lossless =
ARG_DEF(NULL, "lossless", 1, "Lossless mode (0: false (default), 1: true)");
......@@ -579,7 +588,12 @@ static const arg_def_t *av1_args[] = { &cpu_used_av1,
&tile_dependent_rows,
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
&tile_loopfilter_v,
&tile_loopfilter_h,
#else
&tile_loopfilter,
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
&arnr_maxframes,
&arnr_strength,
......@@ -638,7 +652,12 @@ static const int av1_arg_ctrl_map[] = { AOME_SET_CPUUSED,
AV1E_SET_TILE_DEPENDENT_ROWS,
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
AV1E_SET_TILE_LOOPFILTER_V,
AV1E_SET_TILE_LOOPFILTER_H,
#else
AV1E_SET_TILE_LOOPFILTER,
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
AOME_SET_ARNR_MAXFRAMES,
AOME_SET_ARNR_STRENGTH,
......
......@@ -43,7 +43,12 @@ struct av1_extracfg {
unsigned int dependent_horz_tiles;
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
unsigned int loop_filter_across_tiles_v_enabled;
unsigned int loop_filter_across_tiles_h_enabled;
#else
unsigned int loop_filter_across_tiles_enabled;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
unsigned int arnr_max_frames;
unsigned int arnr_strength;
......@@ -105,7 +110,12 @@ static struct av1_extracfg default_extra_cfg = {
0, // Dependent Horizontal tiles
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
1, // loop_filter_across_tiles_enabled
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
1, // loop_filter_across_tiles_v_enabled
1, // loop_filter_across_tiles_h_enabled
#else
1, // loop_filter_across_tiles_enabled
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
7, // arnr_max_frames
5, // arnr_strength
......@@ -324,7 +334,12 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(extra_cfg, dependent_horz_tiles, 1);
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
RANGE_CHECK_HI(extra_cfg, loop_filter_across_tiles_v_enabled, 1);
RANGE_CHECK_HI(extra_cfg, loop_filter_across_tiles_h_enabled, 1);
#else
RANGE_CHECK_HI(extra_cfg, loop_filter_across_tiles_enabled, 1);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
RANGE_CHECK_HI(extra_cfg, sharpness, 7);
RANGE_CHECK_HI(extra_cfg, arnr_max_frames, 15);
......@@ -658,8 +673,15 @@ static aom_codec_err_t set_encoder_config(
extra_cfg->dependent_horz_tiles;
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
oxcf->loop_filter_across_tiles_v_enabled =
extra_cfg->loop_filter_across_tiles_v_enabled;
oxcf->loop_filter_across_tiles_h_enabled =
extra_cfg->loop_filter_across_tiles_h_enabled;
#else
oxcf->loop_filter_across_tiles_enabled =
extra_cfg->loop_filter_across_tiles_enabled;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
oxcf->error_resilient_mode = cfg->g_error_resilient;
oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
......@@ -808,6 +830,22 @@ static aom_codec_err_t ctrl_set_tile_dependent_rows(aom_codec_alg_priv_t *ctx,
}
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
static aom_codec_err_t ctrl_set_tile_loopfilter_v(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.loop_filter_across_tiles_v_enabled =
CAST(AV1E_SET_TILE_LOOPFILTER_V, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static aom_codec_err_t ctrl_set_tile_loopfilter_h(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.loop_filter_across_tiles_h_enabled =
CAST(AV1E_SET_TILE_LOOPFILTER_H, args);
return update_extra_cfg(ctx, &extra_cfg);
}
#else
static aom_codec_err_t ctrl_set_tile_loopfilter(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
......@@ -815,6 +853,7 @@ static aom_codec_err_t ctrl_set_tile_loopfilter(aom_codec_alg_priv_t *ctx,
CAST(AV1E_SET_TILE_LOOPFILTER, args);
return update_extra_cfg(ctx, &extra_cfg);
}
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
static aom_codec_err_t ctrl_set_arnr_max_frames(aom_codec_alg_priv_t *ctx,
......@@ -1593,7 +1632,12 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ AV1E_SET_TILE_DEPENDENT_ROWS, ctrl_set_tile_dependent_rows },
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{ AV1E_SET_TILE_LOOPFILTER_V, ctrl_set_tile_loopfilter_v },
{ AV1E_SET_TILE_LOOPFILTER_H, ctrl_set_tile_loopfilter_h },
#else
{ AV1E_SET_TILE_LOOPFILTER, ctrl_set_tile_loopfilter },
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
{ AOME_SET_ARNR_MAXFRAMES, ctrl_set_arnr_max_frames },
{ AOME_SET_ARNR_STRENGTH, ctrl_set_arnr_strength },
......
......@@ -1018,7 +1018,7 @@ static void build_y_mask(AV1_COMMON *const cm,
*int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffffULL) << shift_y;
}
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
// This function update the bit masks for the entire 64x64 region represented
// by mi_row, mi_col. In case one of the edge is a tile boundary, loop filtering
// for that edge is disabled. This function only check the tile boundary info
......@@ -1281,7 +1281,7 @@ void av1_setup_mask(AV1_COMMON *const cm, const int mi_row, const int mi_col,
}
}
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (av1_disable_loopfilter_on_tile_boundary(cm)) {
update_tile_boundary_filter_mask(cm, mi_row, mi_col, lfm);
}
......@@ -1595,7 +1595,7 @@ void av1_filter_block_plane_non420_ver(AV1_COMMON *const cm,
// Disable filtering on the leftmost column or tile boundary
unsigned int border_mask = ~(mi_col == 0 ? 1 : 0);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
MODE_INFO *const mi = cm->mi + (mi_row + idx_r) * cm->mi_stride + mi_col;
if (av1_disable_loopfilter_on_tile_boundary(cm) &&
((mi->mbmi.boundary_info & TILE_LEFT_BOUNDARY) != 0)) {
......@@ -1643,7 +1643,7 @@ void av1_filter_block_plane_non420_hor(AV1_COMMON *const cm,
&lfl[r][0], &mask_4x4_int, NULL,
&row_masks, NULL);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
// Disable filtering on the abovemost row or tile boundary
const MODE_INFO *mi = cm->mi + (mi_row + idx_r) * cm->mi_stride + mi_col;
if ((av1_disable_loopfilter_on_tile_boundary(cm) &&
......@@ -2111,13 +2111,15 @@ static void set_lpf_parameters(
uint32_t level = curr_level;
// prepare outer edge parameters. deblock the edge if it's an edge of a TU
if (coord) {
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
MODE_INFO *const mi_bound = cm->mi + mi_row * cm->mi_stride + mi_col;
if (!av1_disable_loopfilter_on_tile_boundary(cm) ||
((VERT_EDGE == edge_dir) &&
(0 == (mi_bound->mbmi.boundary_info & TILE_LEFT_BOUNDARY))) ||
((HORZ_EDGE == edge_dir) &&
(0 == (mi_bound->mbmi.boundary_info & TILE_ABOVE_BOUNDARY))))
// here, assuming bounfary_info is set correctly based on the
// loop_filter_across_tiles_enabled flag, i.e, tile boundary should
// only be set to true when this flag is set to 0.
int left_boundary = (mi_bound->mbmi.boundary_info & TILE_LEFT_BOUNDARY);
int top_boundary = (mi_bound->mbmi.boundary_info & TILE_ABOVE_BOUNDARY);
if (((VERT_EDGE == edge_dir) && (0 == left_boundary)) ||
((HORZ_EDGE == edge_dir) && (0 == top_boundary)))
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
{
const int32_t tu_edge =
......
......@@ -218,23 +218,40 @@ void av1_cdef_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
nhb = AOMMIN(MI_SIZE_64X64, cm->mi_cols - MI_SIZE_64X64 * fbc);
nvb = AOMMIN(MI_SIZE_64X64, cm->mi_rows - MI_SIZE_64X64 * fbr);
int tile_top, tile_left, tile_bottom, tile_right;
int mi_idx = MI_SIZE_64X64 * fbr * cm->mi_stride + MI_SIZE_64X64 * fbc;
MODE_INFO *const mi_tl = cm->mi + mi_idx;
int mi_row = MI_SIZE_64X64 * fbr;
int mi_col = MI_SIZE_64X64 * fbc;
int mi_idx_tl = mi_row * cm->mi_stride + mi_col;
int mi_idx_tr = mi_row * cm->mi_stride + (mi_col + MI_SIZE_64X64 - 1);
int mi_idx_bl = (mi_row + MI_SIZE_64X64 - 1) * cm->mi_stride + mi_col;
// for the current filter block, it's top left corner mi structure (mi_tl)
// is first accessed to check whether the top and left boundaries are
// tile boundaries. Then bottom-left and top-right mi structures are
// accessed to check whether the bottom and right boundaries
// (respectively) are tile boundaries.
//
// Note that we can't just check the bottom-right mi structure - eg. if
// we're at the right-hand edge of the frame but not the bottom, then
// the bottom-right mi is NULL but the bottom-left is not.
//
// We assume the boundary information is set correctly based on the
// loop_filter_across_tiles_enabled flag, i.e, if this flag is set to 1,
// then boundary_info should not be treated as tile boundaries. Also
// assume CDEF filter block size is 64x64.
MODE_INFO *const mi_tl = cm->mi + mi_idx_tl;
MODE_INFO *const mi_tr = cm->mi + mi_idx_tr;
MODE_INFO *const mi_bl = cm->mi + mi_idx_bl;
BOUNDARY_TYPE boundary_tl = mi_tl->mbmi.boundary_info;
tile_top = boundary_tl & TILE_ABOVE_BOUNDARY;
tile_left = boundary_tl & TILE_LEFT_BOUNDARY;
if (fbr != nvfb - 1 &&
(&cm->mi[mi_idx + (MI_SIZE_64X64 - 1) * cm->mi_stride]))
tile_bottom = cm->mi[mi_idx + (MI_SIZE_64X64 - 1) * cm->mi_stride]
.mbmi.boundary_info &
TILE_BOTTOM_BOUNDARY;
if (fbr != nvfb - 1 && mi_bl)
tile_bottom = mi_bl->mbmi.boundary_info & TILE_BOTTOM_BOUNDARY;
else
tile_bottom = 1;
if (fbc != nhfb - 1 && (&cm->mi[mi_idx + MI_SIZE_64X64 - 1]))
tile_right = cm->mi[mi_idx + MI_SIZE_64X64 - 1].mbmi.boundary_info &
TILE_RIGHT_BOUNDARY;
if (fbc != nhfb - 1 && mi_tr)
tile_right = mi_tr->mbmi.boundary_info & TILE_RIGHT_BOUNDARY;
else
tile_right = 1;
......
......@@ -495,7 +495,12 @@ typedef struct AV1Common {
int tile_group_start_col[MAX_TILE_ROWS][MAX_TILE_COLS];
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
int loop_filter_across_tiles_v_enabled;
int loop_filter_across_tiles_h_enabled;
#else
int loop_filter_across_tiles_enabled;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
int byte_alignment;
......
This diff is collapsed.
......@@ -213,20 +213,26 @@ typedef struct {
#define RESTORATION_LINEBUFFER_WIDTH \
(RESTORATION_TILESIZE_MAX * 3 / 2 + 2 * RESTORATION_EXTRA_HORZ)
// Similarly, the column buffers (used when we're at a vertical tile edge
// that we can't filter across) need space for one processing unit's worth
// of pixels, plus the top/bottom border width
#define RESTORATION_COLBUFFER_HEIGHT \
(RESTORATION_PROC_UNIT_SIZE + 2 * RESTORATION_BORDER)
typedef struct {
// Temporary buffers to save/restore 3 lines above/below the restoration
// 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
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
// 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];
uint16_t tmp_save_left[RESTORATION_BORDER][RESTORATION_COLBUFFER_HEIGHT];
uint16_t tmp_save_right[RESTORATION_BORDER][RESTORATION_COLBUFFER_HEIGHT];
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
} RestorationLineBuffers;
......@@ -314,7 +320,12 @@ void av1_loop_restoration_filter_unit(
const RestorationStripeBoundaries *rsb, RestorationLineBuffers *rlbs,
const AV1PixelRect *tile_rect, int tile_stripe0,
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
int loop_filter_across_tiles_v_enabled,
int loop_filter_across_tiles_h_enabled,
#else
int loop_filter_across_tiles_enabled,
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#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,
......
......@@ -279,7 +279,9 @@ AV1PixelRect av1_get_tile_rect(const TileInfo *tile_info, const AV1_COMMON *cm,
return r;
}
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
// this function should only be called when loop_filter_across_tile flag is
// set to 0
void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
const TileInfo *const tile_info) {
if (cm->tile_cols * cm->tile_rows > 1) {
......@@ -292,9 +294,14 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
const int col_diff = tile_info->mi_col_end - tile_info->mi_col_start;
int row, col;
#if CONFIG_DEPENDENT_HORZTILES
// when CONFIG_LOOPFILTERING_ACROSS_TILES_EXT is enabled, whether tile
// is dependent horizontal tile or not is ignored. tile boundary is always
// initialized based on the actual tile boundary.
#if CONFIG_DEPENDENT_HORZTILES && !CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (!cm->dependent_horz_tiles || tile_info->tg_horz_boundary)
#endif // CONFIG_DEPENDENT_HORZTILES
#elif CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->loop_filter_across_tiles_h_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{
mi = mi_start;
for (col = 0; col < col_diff; ++col) {
......@@ -303,32 +310,50 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
}
}
mi = mi_start;
for (row = 0; row < row_diff; ++row) {
mi->mbmi.boundary_info |= TILE_LEFT_BOUNDARY;
mi += cm->mi_stride;
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->loop_filter_across_tiles_v_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{
mi = mi_start;
for (row = 0; row < row_diff; ++row) {
mi->mbmi.boundary_info |= TILE_LEFT_BOUNDARY;
mi += cm->mi_stride;
}
}
mi = mi_start + (row_diff - 1) * cm->mi_stride;
// explicit bounds checking
assert(mi + col_diff <= cm->mip + cm->mi_alloc_size);
for (col = 0; col < col_diff; ++col) {
mi->mbmi.boundary_info |= TILE_BOTTOM_BOUNDARY;
mi += 1;
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->loop_filter_across_tiles_h_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{
mi = mi_start + (row_diff - 1) * cm->mi_stride;
// explicit bounds checking
assert(mi + col_diff <= cm->mip + cm->mi_alloc_size);
for (col = 0; col < col_diff; ++col) {
mi->mbmi.boundary_info |= TILE_BOTTOM_BOUNDARY;
mi += 1;
}
}
mi = mi_start + col_diff - 1;
for (row = 0; row < row_diff; ++row) {
mi->mbmi.boundary_info |= TILE_RIGHT_BOUNDARY;
mi += cm->mi_stride;
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->loop_filter_across_tiles_v_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{
mi = mi_start + col_diff - 1;
for (row = 0; row < row_diff; ++row) {
mi->mbmi.boundary_info |= TILE_RIGHT_BOUNDARY;
mi += cm->mi_stride;
}
}
}
} // end of cm->tile_cols * cm->tile_rows > 1
}
int av1_disable_loopfilter_on_tile_boundary(const struct AV1Common *cm) {
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
return ((!cm->loop_filter_across_tiles_v_enabled ||
!cm->loop_filter_across_tiles_h_enabled) &&
#else
return (!cm->loop_filter_across_tiles_enabled &&
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
(cm->tile_cols * cm->tile_rows > 1));
}
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
......@@ -54,7 +54,7 @@ typedef struct { int left, top, right, bottom; } AV1PixelRect;
AV1PixelRect av1_get_tile_rect(const TileInfo *tile_info,
const struct AV1Common *cm, int is_uv);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
void av1_setup_across_tile_boundary_info(const struct AV1Common *const cm,
const TileInfo *const tile_info);
int av1_disable_loopfilter_on_tile_boundary(const struct AV1Common *cm);
......
......@@ -1592,10 +1592,23 @@ static void read_tile_info(AV1Decoder *const pbi,
cm->dependent_horz_tiles = 0;
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->tile_cols > 1) {
cm->loop_filter_across_tiles_v_enabled = aom_rb_read_bit(rb);
} else {
cm->loop_filter_across_tiles_v_enabled = 1;
}
if (cm->tile_rows > 1) {
cm->loop_filter_across_tiles_h_enabled = aom_rb_read_bit(rb);
} else {
cm->loop_filter_across_tiles_h_enabled = 1;
}
#else
if (cm->tile_cols * cm->tile_rows > 1)
cm->loop_filter_across_tiles_enabled = aom_rb_read_bit(rb);
else
cm->loop_filter_across_tiles_enabled = 1;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
if (cm->tile_cols * cm->tile_rows > 1) {
......@@ -1648,10 +1661,23 @@ static void read_tile_info(AV1Decoder *const pbi,
cm->dependent_horz_tiles = 0;
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->tile_cols > 1) {
cm->loop_filter_across_tiles_v_enabled = aom_rb_read_bit(rb);
} else {
cm->loop_filter_across_tiles_v_enabled = 1;
}
if (cm->tile_rows > 1) {
cm->loop_filter_across_tiles_h_enabled = aom_rb_read_bit(rb);
} else {
cm->loop_filter_across_tiles_h_enabled = 1;
}
#else
if (cm->tile_cols * cm->tile_rows > 1)
cm->loop_filter_across_tiles_enabled = aom_rb_read_bit(rb);
else
cm->loop_filter_across_tiles_enabled = 1;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
// tile size magnitude
......@@ -1945,14 +1971,18 @@ static void get_tile_buffers(AV1Decoder *pbi, const uint8_t *data,
}
}
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
static void dec_setup_across_tile_boundary_info(
const AV1_COMMON *const cm, const TileInfo *const tile_info) {
if (tile_info->mi_row_start >= tile_info->mi_row_end ||
tile_info->mi_col_start >= tile_info->mi_col_end)
return;
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (!cm->loop_filter_across_tiles_v_enabled ||
!cm->loop_filter_across_tiles_h_enabled) {
#else
if (!cm->loop_filter_across_tiles_enabled) {
#endif
av1_setup_across_tile_boundary_info(cm, tile_info);
}
}
......@@ -2125,7 +2155,7 @@ static const uint8_t *decode_tiles(AV1Decoder *pbi, const uint8_t *data,
av1_reset_loop_restoration(&td->xd);
#endif // CONFIG_LOOP_RESTORATION
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
dec_setup_across_tile_boundary_info(cm, &tile_info);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
......@@ -3236,7 +3266,7 @@ static void dec_setup_frame_boundary_info(AV1_COMMON *const cm) {
// change every frame (particularly when dependent-horztiles is also
// enabled); when it is disabled, the only information stored is the frame
// boundaries, which only depend on the frame size.
#if !CONFIG_LOOPFILTERING_ACROSS_TILES
#if !CONFIG_LOOPFILTERING_ACROSS_TILES && !CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->width != cm->last_width || cm->height != cm->last_height)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
{
......
......@@ -2838,8 +2838,17 @@ static void write_tile_info(const AV1_COMMON *const cm,
#endif // CONFIG_EXT_TILE
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (cm->tile_cols > 1) {
aom_wb_write_bit(wb, cm->loop_filter_across_tiles_v_enabled);
}
if (cm->tile_rows > 1) {
aom_wb_write_bit(wb, cm->loop_filter_across_tiles_h_enabled);
}
#else
if (cm->tile_cols * cm->tile_rows > 1)
aom_wb_write_bit(wb, cm->loop_filter_across_tiles_enabled);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
}
......
......@@ -3389,9 +3389,15 @@ void av1_encode_tile(AV1_COMP *cpi, ThreadData *td, int tile_row,
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
if (!cm->loop_filter_across_tiles_v_enabled ||
!cm->loop_filter_across_tiles_h_enabled)
av1_setup_across_tile_boundary_info(cm, tile_info);
#else
if (!cm->loop_filter_across_tiles_enabled)
av1_setup_across_tile_boundary_info(cm, tile_info);
#endif
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
av1_crc_calculator_init(&td->mb.tx_rd_record.crc_calculator, 24, 0x5D6DCB);
......
......@@ -1016,8 +1016,15 @@ static void set_tile_info(AV1_COMP *cpi) {
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
cm->loop_filter_across_tiles_v_enabled =
cpi->oxcf.loop_filter_across_tiles_v_enabled;
cm->loop_filter_across_tiles_h_enabled =
cpi->oxcf.loop_filter_across_tiles_h_enabled;
#else
cm->loop_filter_across_tiles_enabled =
cpi->oxcf.loop_filter_across_tiles_enabled;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
}
......
......@@ -265,7 +265,12 @@ typedef struct AV1EncoderConfig {
int dependent_horz_tiles;
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
int loop_filter_across_tiles_v_enabled;
int loop_filter_across_tiles_h_enabled;
#else
int loop_filter_across_tiles_enabled;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
int max_threads;
......
......@@ -184,9 +184,14 @@ static int64_t try_restoration_tile(const RestSearchCtxt *rsc,
#if CONFIG_STRIPED_LOOP_RESTORATION
&rsi->boundaries, &rlbs, tile_rect, rsc->tile_stripe0,
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
cm->loop_filter_across_tiles_v_enabled,
cm->loop_filter_across_tiles_h_enabled,
#else
cm->loop_filter_across_tiles_enabled,
#endif
#endif
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
#endif // CONFIG_STRIPED_LOOP_RESTORATION
is_uv && cm->subsampling_x, is_uv && cm->subsampling_y, highbd, bit_depth,
fts->buffers[plane], fts->strides[is_uv], rsc->dst->buffers[plane],
rsc->dst->strides[is_uv], cm->rst_tmpbuf);
......
......@@ -156,6 +156,7 @@ set(CONFIG_INTRA_EDGE 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_JNT_COMP 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_KF_CTX 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_LOOPFILTERING_ACROSS_TILES 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_LOOPFILTERING_ACROSS_TILES_EXT 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_LOOPFILTER_LEVEL 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_LOOP_RESTORATION 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_LPF_SB 0 CACHE NUMBER "AV1 experiment flag.")
......
......@@ -285,6 +285,7 @@ EXPERIMENT_LIST="
parallel_deblocking
deblock_13tap
loopfiltering_across_tiles
loopfiltering_across_tiles_ext
tempmv_signaling
rd_debug
reference_buffer
......@@ -550,6 +551,7 @@ post_process_cmdline() {
enabled loopfilter_level && enable_feature ext_delta_q
enabled striped_loop_restoration && enable_feature loop_restoration
enabled adapt_scan && enable_feature lv_map
enabled loopfiltering_across_tiles_ext && enable_feature loopfiltering_across_tiles
soft_enable daala_tx_dst32
......
......@@ -91,7 +91,12 @@ class AV1ExtTileTest
encoder->Control(AV1E_SET_SUPERBLOCK_SIZE, AOM_SUPERBLOCK_SIZE_64X64);
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
encoder->Control(AV1E_SET_TILE_LOOPFILTER_V, 0);
encoder->Control(AV1E_SET_TILE_LOOPFILTER_H, 0);
#else
encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
#endif
#endif
}
......
......@@ -72,7 +72,12 @@ class AVxEncoderThreadTest
if (!encoder_initialized_) {
SetTileSize(encoder);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
encoder->Control(AV1E_SET_TILE_LOOPFILTER_V, 0);
encoder->Control(AV1E_SET_TILE_LOOPFILTER_H, 0);
#else
encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
if (encoding_mode_ != ::libaom_test::kRealTime) {
......
......@@ -51,7 +51,12 @@ class SuperframeTest
encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_);
encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
encoder->Control(AV1E_SET_TILE_LOOPFILTER_V, 0);
encoder->Control(AV1E_SET_TILE_LOOPFILTER_H, 0);
#else
encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
}
}
......
......@@ -64,7 +64,12 @@ class TileIndependenceTest
encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_);
encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
#if CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
encoder->Control(AV1E_SET_TILE_LOOPFILTER_V, 0);
encoder->Control(AV1E_SET_TILE_LOOPFILTER_H, 0);
#else
encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
SetCpuUsed(encoder);
}
......
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