From f58f111fb3e36dfc395196f8dc8b16d69d6261c7 Mon Sep 17 00:00:00 2001 From: Dominic Symes <dominic.symes@arm.com> Date: Mon, 25 Sep 2017 12:47:40 +0200 Subject: [PATCH] MAX_TILE experiment: add explicit tiles This patch is designed to complete the CONFIG_MAX_TILE experiment. It adds the following features: - Explicit tiles of same width can be signalled with command line --tile_width - Explicit tiles of same hieght can be signalled with command line --tile_height - max_tile now works with the depenedent horizontal tiles experiment - additional checking added to ensure maximum number of rows/columns <= 64 - one fix to the tile group code for when the number of tiles is not a power of two Change-Id: I749a68fdb3dcdd8d1ced2b3558f3817e4b832c06 --- aom/aomcx.h | 25 +++++++++++++++++++++++++ aomenc.c | 14 ++++++++++++++ av1/av1_cx_iface.c | 37 +++++++++++++++++++++++++++++++++++-- av1/common/onyxc_int.h | 3 +++ av1/common/tile_common.c | 28 +++++++++++++++++++++++----- av1/decoder/decodeframe.c | 8 ++++---- av1/encoder/bitstream.c | 4 ++-- av1/encoder/encoder.c | 28 ++++++++++++++++++++++++---- av1/encoder/encoder.h | 4 ++++ 9 files changed, 134 insertions(+), 17 deletions(-) diff --git a/aom/aomcx.h b/aom/aomcx.h index 5db659a16c..cc22b329af 100644 --- a/aom/aomcx.h +++ b/aom/aomcx.h @@ -492,6 +492,26 @@ enum aome_enc_control_id { */ AV1E_SET_MTU, + /*!\brief Codec control function to set tile_width. + * + * In encoding this sets expilcit tiles of the given tile width + * + * By default, the value is 0 and explicit tiles are disabled. + * + * Experiment: MAX_TILE + */ + AV1E_SET_TILE_WIDTH, + + /*!\brief Codec control function to set tile_height. + * + * In encoding this sets expilcit tiles of the given tile height + * + * By default, the value is 0 and explicit tiles are disabled. + * + * Experiment: MAX_TILE + */ + AV1E_SET_TILE_HEIGHT, + /*!\brief Codec control function to set dependent_horz_tiles. * * In encoding and decoding, AV1 allows enabling dependent horizontal tile @@ -688,6 +708,11 @@ AOM_CTRL_USE_TYPE(AV1E_SET_TILE_COLUMNS, int) AOM_CTRL_USE_TYPE(AV1E_SET_TILE_ROWS, int) #define AOM_CTRL_AV1E_SET_TILE_ROWS +AOM_CTRL_USE_TYPE(AV1E_SET_TILE_WIDTH, int) +#define AOM_CTRL_AV1E_SET_TILE_WIDTH +AOM_CTRL_USE_TYPE(AV1E_SET_TILE_HEIGHT, int) +#define AOM_CTRL_AV1E_SET_TILE_HEIGHT + AOM_CTRL_USE_TYPE(AV1E_SET_TILE_DEPENDENT_ROWS, int) #define AOM_CTRL_AV1E_SET_TILE_DEPENDENT_ROWS diff --git a/aomenc.c b/aomenc.c index fd334faa02..d3edb122a1 100644 --- a/aomenc.c +++ b/aomenc.c @@ -412,6 +412,12 @@ static const arg_def_t tile_cols = static const arg_def_t tile_rows = ARG_DEF(NULL, "tile-rows", 1, "Number of tile rows to use, log2 (set to 0 while threads > 1)"); +#if CONFIG_MAX_TILE +static const arg_def_t tile_width = + ARG_DEF(NULL, "tile-width", 1, "Width of each tile"); +static const arg_def_t tile_height = + ARG_DEF(NULL, "tile-height", 1, "Height of each tile"); +#endif #if CONFIG_DEPENDENT_HORZTILES static const arg_def_t tile_dependent_rows = ARG_DEF(NULL, "tile-dependent-rows", 1, "Enable dependent Tile rows"); @@ -547,6 +553,10 @@ static const arg_def_t *av1_args[] = { &cpu_used_av1, #endif // CONFIG_EXT_TILE &tile_cols, &tile_rows, +#if CONFIG_MAX_TILE + &tile_width, + &tile_height, +#endif #if CONFIG_DEPENDENT_HORZTILES &tile_dependent_rows, #endif @@ -604,6 +614,10 @@ static const int av1_arg_ctrl_map[] = { AOME_SET_CPUUSED, #endif // CONFIG_EXT_TILE AV1E_SET_TILE_COLUMNS, AV1E_SET_TILE_ROWS, +#if CONFIG_MAX_TILE + AV1E_SET_TILE_WIDTH, + AV1E_SET_TILE_HEIGHT, +#endif #if CONFIG_DEPENDENT_HORZTILES AV1E_SET_TILE_DEPENDENT_ROWS, #endif diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index 1a946ebf72..ec35ef2594 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c @@ -34,8 +34,12 @@ struct av1_extracfg { unsigned int noise_sensitivity; unsigned int sharpness; unsigned int static_thresh; - unsigned int tile_columns; - unsigned int tile_rows; + unsigned int tile_columns; // log2 number of tile columns + unsigned int tile_rows; // log2 number of tile rows +#if CONFIG_MAX_TILE + unsigned int tile_width; // tile width in superblocks (if non zero) + unsigned int tile_height; // tile height in superblocks (if non zero) +#endif #if CONFIG_DEPENDENT_HORZTILES unsigned int dependent_horz_tiles; #endif @@ -101,6 +105,10 @@ static struct av1_extracfg default_extra_cfg = { 0, // static_thresh 0, // tile_columns 0, // tile_rows +#if CONFIG_MAX_TILE + 0, // tile_width + 0, // tile_height +#endif #if CONFIG_DEPENDENT_HORZTILES 0, // Dependent Horizontal tiles #endif @@ -308,6 +316,7 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx, #if CONFIG_MAX_TILE RANGE_CHECK_HI(extra_cfg, tile_columns, 6); RANGE_CHECK_HI(extra_cfg, tile_rows, 6); + RANGE_CHECK_HI(extra_cfg, tile_width, MAX_TILE_WIDTH_SB); #else // CONFIG_MAX_TILE RANGE_CHECK_HI(extra_cfg, tile_columns, 6); RANGE_CHECK_HI(extra_cfg, tile_rows, 2); @@ -629,6 +638,10 @@ static aom_codec_err_t set_encoder_config( } #endif // CONFIG_EXT_TILE +#if CONFIG_MAX_TILE + oxcf->tile_width = extra_cfg->tile_width; + oxcf->tile_height = extra_cfg->tile_height; +#endif #if CONFIG_DEPENDENT_HORZTILES oxcf->dependent_horz_tiles = #if CONFIG_EXT_TILE @@ -773,6 +786,22 @@ static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx, extra_cfg.tile_rows = CAST(AV1E_SET_TILE_ROWS, args); return update_extra_cfg(ctx, &extra_cfg); } + +#if CONFIG_MAX_TILE +static aom_codec_err_t ctrl_set_tile_width(aom_codec_alg_priv_t *ctx, + va_list args) { + struct av1_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.tile_width = CAST(AV1E_SET_TILE_WIDTH, args); + return update_extra_cfg(ctx, &extra_cfg); +} + +static aom_codec_err_t ctrl_set_tile_height(aom_codec_alg_priv_t *ctx, + va_list args) { + struct av1_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.tile_height = CAST(AV1E_SET_TILE_HEIGHT, args); + return update_extra_cfg(ctx, &extra_cfg); +} +#endif #if CONFIG_DEPENDENT_HORZTILES static aom_codec_err_t ctrl_set_tile_dependent_rows(aom_codec_alg_priv_t *ctx, va_list args) { @@ -1551,6 +1580,10 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { { AOME_SET_STATIC_THRESHOLD, ctrl_set_static_thresh }, { AV1E_SET_TILE_COLUMNS, ctrl_set_tile_columns }, { AV1E_SET_TILE_ROWS, ctrl_set_tile_rows }, +#if CONFIG_MAX_TILE + { AV1E_SET_TILE_WIDTH, ctrl_set_tile_width }, + { AV1E_SET_TILE_HEIGHT, ctrl_set_tile_height }, +#endif #if CONFIG_DEPENDENT_HORZTILES { AV1E_SET_TILE_DEPENDENT_ROWS, ctrl_set_tile_dependent_rows }, #endif diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h index 795100e4aa..35b1b23781 100644 --- a/av1/common/onyxc_int.h +++ b/av1/common/onyxc_int.h @@ -431,6 +431,9 @@ typedef struct AV1Common { int log2_tile_rows; // only valid for uniform tiles int tile_col_start_sb[MAX_TILE_COLS + 1]; // valid for 0 <= i <= tile_cols int tile_row_start_sb[MAX_TILE_ROWS + 1]; // valid for 0 <= i <= tile_rows +#if CONFIG_DEPENDENT_HORZTILES + int tile_row_independent[MAX_TILE_ROWS]; // valid for 0 <= i < tile_rows +#endif #else int log2_tile_cols, log2_tile_rows; // Used in non-large_scale_tile_coding. int tile_width, tile_height; // In MI units diff --git a/av1/common/tile_common.c b/av1/common/tile_common.c index f73c39cc3f..c3dedbf858 100644 --- a/av1/common/tile_common.c +++ b/av1/common/tile_common.c @@ -26,6 +26,11 @@ void av1_tile_set_tg_boundary(TileInfo *tile, const AV1_COMMON *const cm, tile->tg_horz_boundary = (row == cm->tile_group_start_row[row][col] ? 1 : 0); } +#if CONFIG_MAX_TILE + if (cm->tile_row_independent[row]) { + tile->tg_horz_boundary = 1; // this tile row is independent + } +#endif } #endif void av1_tile_init(TileInfo *tile, const AV1_COMMON *cm, int row, int col) { @@ -53,8 +58,8 @@ void av1_get_tile_limits(AV1_COMMON *const cm) { int sb_rows = mi_rows >> MAX_MIB_SIZE_LOG2; cm->min_log2_tile_cols = tile_log2(MAX_TILE_WIDTH_SB, sb_cols); - cm->max_log2_tile_cols = tile_log2(1, sb_cols); - cm->max_log2_tile_rows = tile_log2(1, sb_rows); + cm->max_log2_tile_cols = tile_log2(1, AOMMIN(sb_cols, MAX_TILE_COLS)); + cm->max_log2_tile_rows = tile_log2(1, AOMMIN(sb_rows, MAX_TILE_ROWS)); cm->min_log2_tiles = tile_log2(MAX_TILE_AREA_SB, sb_cols * sb_rows); cm->min_log2_tiles = AOMMAX(cm->min_log2_tiles, cm->min_log2_tile_cols); // TODO(dominic.symes@arm.com): @@ -78,11 +83,13 @@ void av1_calculate_tile_cols(AV1_COMMON *const cm) { start_sb += size_sb; } cm->tile_cols = i; - cm->tile_col_start_sb[i] = start_sb; + cm->tile_col_start_sb[i] = sb_cols; cm->min_log2_tile_rows = AOMMAX(cm->min_log2_tiles - cm->log2_tile_cols, 0); + cm->max_tile_height_sb = sb_rows >> cm->min_log2_tile_rows; } else { int max_tile_area_sb = (sb_rows * sb_cols); int max_tile_width_sb = 0; + cm->log2_tile_cols = tile_log2(1, cm->tile_cols); for (i = 0; i < cm->tile_cols; i++) { int size_sb = cm->tile_col_start_sb[i + 1] - cm->tile_col_start_sb[i]; max_tile_width_sb = AOMMAX(max_tile_width_sb, size_sb); @@ -108,10 +115,21 @@ void av1_calculate_tile_rows(AV1_COMMON *const cm) { start_sb += size_sb; } cm->tile_rows = i; - cm->tile_row_start_sb[i] = start_sb; + cm->tile_row_start_sb[i] = sb_rows; } else { - // No action + cm->log2_tile_rows = tile_log2(1, cm->tile_rows); + } + +#if CONFIG_DEPENDENT_HORZTILES + // Record which tile rows must be indpendent for parallelism + for (i = 0, start_sb = 0; i < cm->tile_rows; i++) { + cm->tile_row_independent[i] = 0; + if (cm->tile_row_start_sb[i + 1] - start_sb > cm->max_tile_height_sb) { + cm->tile_row_independent[i] = 1; + start_sb = cm->tile_row_start_sb[i]; + } } +#endif } void av1_tile_set_row(TileInfo *tile, const AV1_COMMON *cm, int row) { diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index c03dff9770..471625818e 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c @@ -3246,14 +3246,14 @@ static void read_tile_info_max_tile(AV1_COMMON *const cm, cm->log2_tile_cols++; } } else { - for (i = 0, start_sb = 0; width_sb > 0; i++) { + for (i = 0, start_sb = 0; width_sb > 0 && i < MAX_TILE_COLS; i++) { size_sb = 1 + rb_read_uniform(rb, AOMMIN(width_sb, MAX_TILE_WIDTH_SB)); cm->tile_col_start_sb[i] = start_sb; start_sb += size_sb; width_sb -= size_sb; } cm->tile_cols = i; - cm->tile_col_start_sb[i] = start_sb; + cm->tile_col_start_sb[i] = start_sb + width_sb; } av1_calculate_tile_cols(cm); @@ -3267,7 +3267,7 @@ static void read_tile_info_max_tile(AV1_COMMON *const cm, cm->log2_tile_rows++; } } else { - for (i = 0, start_sb = 0; height_sb > 0; i++) { + for (i = 0, start_sb = 0; height_sb > 0 && i < MAX_TILE_ROWS; i++) { size_sb = 1 + rb_read_uniform(rb, AOMMIN(height_sb, cm->max_tile_height_sb)); cm->tile_row_start_sb[i] = start_sb; @@ -3275,7 +3275,7 @@ static void read_tile_info_max_tile(AV1_COMMON *const cm, height_sb -= size_sb; } cm->tile_rows = i; - cm->tile_row_start_sb[i] = start_sb; + cm->tile_row_start_sb[i] = start_sb + height_sb; } av1_calculate_tile_rows(cm); } diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index ebf2e68f0e..1fe6cbf801 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c @@ -4180,8 +4180,8 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, } // Write the final tile group size if (n_log2_tiles) { - aom_wb_overwrite_literal(&tg_params_wb, (1 << n_log2_tiles) - tile_count, - n_log2_tiles); + aom_wb_overwrite_literal( + &tg_params_wb, (tile_cols * tile_rows) - tile_count, n_log2_tiles); aom_wb_overwrite_literal(&tg_params_wb, tile_count - 1, n_log2_tiles); } // Remux if possible. TODO (Thomas Davies): do this for more than one tile diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index fa4093e079..9787097708 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c @@ -866,16 +866,26 @@ void av1_new_framerate(AV1_COMP *cpi, double framerate) { static void set_tile_info_max_tile(AV1_COMP *cpi) { AV1_COMMON *const cm = &cpi->common; + int i, start_sb; av1_get_tile_limits(cm); - // Configure uniform spaced tiles - // (API is not yet upgraded to general tiles) - cm->uniform_tile_spacing_flag = 1; // configure tile columns - if (cm->uniform_tile_spacing_flag) { + if (cpi->oxcf.tile_width == 0 || cpi->oxcf.tile_height == 0) { + cm->uniform_tile_spacing_flag = 1; cm->log2_tile_cols = AOMMAX(cpi->oxcf.tile_columns, cm->min_log2_tile_cols); cm->log2_tile_cols = AOMMIN(cm->log2_tile_cols, cm->max_log2_tile_cols); + } else { + int mi_cols = ALIGN_POWER_OF_TWO(cm->mi_cols, MAX_MIB_SIZE_LOG2); + int sb_cols = mi_cols >> MAX_MIB_SIZE_LOG2; + int size_sb = AOMMIN(cpi->oxcf.tile_width, MAX_TILE_WIDTH_SB); + cm->uniform_tile_spacing_flag = 0; + for (i = 0, start_sb = 0; start_sb < sb_cols && i < MAX_TILE_COLS; i++) { + cm->tile_col_start_sb[i] = start_sb; + start_sb += size_sb; + } + cm->tile_cols = i; + cm->tile_col_start_sb[i] = sb_cols; } av1_calculate_tile_cols(cm); @@ -883,6 +893,16 @@ static void set_tile_info_max_tile(AV1_COMP *cpi) { if (cm->uniform_tile_spacing_flag) { cm->log2_tile_rows = AOMMAX(cpi->oxcf.tile_rows, cm->min_log2_tile_rows); cm->log2_tile_rows = AOMMIN(cm->log2_tile_rows, cm->max_log2_tile_rows); + } else { + int mi_rows = ALIGN_POWER_OF_TWO(cm->mi_rows, MAX_MIB_SIZE_LOG2); + int sb_rows = mi_rows >> MAX_MIB_SIZE_LOG2; + int size_sb = AOMMIN(cpi->oxcf.tile_height, cm->max_tile_height_sb); + for (i = 0, start_sb = 0; start_sb < sb_rows && i < MAX_TILE_ROWS; i++) { + cm->tile_row_start_sb[i] = start_sb; + start_sb += size_sb; + } + cm->tile_rows = i; + cm->tile_row_start_sb[i] = sb_rows; } av1_calculate_tile_rows(cm); } diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index df681fbee1..889d48af25 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h @@ -269,6 +269,10 @@ typedef struct AV1EncoderConfig { int tile_columns; int tile_rows; +#if CONFIG_MAX_TILE + int tile_width; + int tile_height; +#endif #if CONFIG_DEPENDENT_HORZTILES int dependent_horz_tiles; #endif -- GitLab