From 26ad0b22dcd8b4f5109e3907aa1872915014d88e Mon Sep 17 00:00:00 2001 From: Dominic Symes Date: Sun, 1 Oct 2017 16:35:13 +0200 Subject: [PATCH] MAX_TILE: Allow list of tile widths/heights The aomenc API is modified to allow --tile_width and --tile_height to take a list of sizes. For example, --tile_width=2,3 will give tiles of widths 2,3,2,3,... until the image width is exhausted. --tile_width=2 will still work to gives tiles of width 2. Change-Id: I2afa14d404557aa8b7341b20f7477590e03e0bdb --- aom/aom_encoder.h | 42 ++++++++++++++++++++++++++++++++++++++++++ aom/aomcx.h | 20 -------------------- aomenc.c | 20 ++++++++++---------- args.c | 25 +++++++++++++++++++++++++ args.h | 1 + av1/av1_cx_iface.c | 42 ++++++++++++------------------------------ av1/encoder/encoder.c | 14 +++++++++----- av1/encoder/encoder.h | 6 ++++-- 8 files changed, 103 insertions(+), 67 deletions(-) diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h index ff02847b2..c8fe99654 100644 --- a/aom/aom_encoder.h +++ b/aom/aom_encoder.h @@ -619,6 +619,48 @@ typedef struct aom_codec_enc_cfg { * implies a large-scale tile coding. */ unsigned int large_scale_tile; + + /*!\brief Number of explicit tile widths specified + * + * This value indicates the number of tile widths specified + * A value of 0 implies no tile widths are specified. + * Tile widths are given in the array tile_widths[] + */ + int tile_width_count; + + /*!\brief Number of explicit tile heights specified + * + * This value indicates the number of tile heights specified + * A value of 0 implies no tile heights are specified. + * Tile heights are given in the array tile_heights[] + */ + int tile_height_count; + +/*!\brief Maximum number of tile widths in tile widths array + * + * This define gives the maximum number of elements in the tile_widths array. + */ +#define MAX_TILE_WIDTHS 64 // maximum tile width array length + + /*!\brief Array of specified tile widths + * + * This array specifies tile widths (and may be empty) + * The number of widths specified is given by tile_width_count + */ + int tile_widths[MAX_TILE_WIDTHS]; + +/*!\brief Maximum number of tile heights in tile heights array. + * + * This define gives the maximum number of elements in the tile_heights array. + */ +#define MAX_TILE_HEIGHTS 64 // maximum tile height array length + + /*!\brief Array of specified tile heights + * + * This array specifies tile heights (and may be empty) + * The number of heights specified is given by tile_height_count + */ + int tile_heights[MAX_TILE_HEIGHTS]; } aom_codec_enc_cfg_t; /**< alias for struct aom_codec_enc_cfg */ /*!\brief Initialize an encoder instance diff --git a/aom/aomcx.h b/aom/aomcx.h index abe20cb4b..792802c29 100644 --- a/aom/aomcx.h +++ b/aom/aomcx.h @@ -492,26 +492,6 @@ 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 diff --git a/aomenc.c b/aomenc.c index b167eb371..99463a3e3 100644 --- a/aomenc.c +++ b/aomenc.c @@ -414,9 +414,9 @@ static const arg_def_t tile_rows = "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"); + ARG_DEF(NULL, "tile-width", 1, "Tile widths (comma separated)"); static const arg_def_t tile_height = - ARG_DEF(NULL, "tile-height", 1, "Height of each tile"); + ARG_DEF(NULL, "tile-height", 1, "Tile heights (command separated)"); #endif #if CONFIG_DEPENDENT_HORZTILES static const arg_def_t tile_dependent_rows = @@ -553,10 +553,6 @@ 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 @@ -614,10 +610,6 @@ 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 @@ -1119,6 +1111,14 @@ static int parse_stream_params(struct AvxEncoderConfig *global, config->cfg.kf_max_dist = arg_parse_uint(&arg); } else if (arg_match(&arg, &kf_disabled, argi)) { config->cfg.kf_mode = AOM_KF_DISABLED; +#if CONFIG_MAX_TILE + } else if (arg_match(&arg, &tile_width, argi)) { + config->cfg.tile_width_count = + arg_parse_list(&arg, config->cfg.tile_widths, MAX_TILE_WIDTHS); + } else if (arg_match(&arg, &tile_height, argi)) { + config->cfg.tile_height_count = + arg_parse_list(&arg, config->cfg.tile_heights, MAX_TILE_HEIGHTS); +#endif } else { int i, match = 0; for (i = 0; ctrl_args[i]; i++) { diff --git a/args.c b/args.c index 571103595..b9384de70 100644 --- a/args.c +++ b/args.c @@ -210,3 +210,28 @@ int arg_parse_enum_or_int(const struct arg *arg) { if (arg->def->enums) return arg_parse_enum(arg); return arg_parse_int(arg); } + +// parse a comma separated list of at most n integers +// return the number of elements in the list +int arg_parse_list(const struct arg *arg, int *list, int n) { + const char *ptr = arg->val; + char *endptr; + int i = 0; + + while (ptr[0] != '\0') { + int32_t rawval = (int32_t)strtol(ptr, &endptr, 10); + if (rawval < INT_MIN || rawval > INT_MAX) { + die("Option %s: Value %ld out of range for signed int\n", arg->name, + rawval); + } else if (i >= n) { + die("Option %s: List has more than %d entries\n", arg->name, n); + } else if (*endptr == ',') { + endptr++; + } else if (*endptr != '\0') { + die("Option %s: Bad list separator '%c'\n", arg->name, *endptr); + } + list[i++] = (int)rawval; + ptr = endptr; + } + return i; +} diff --git a/args.h b/args.h index e7841fc64..c3427bcfa 100644 --- a/args.h +++ b/args.h @@ -57,6 +57,7 @@ int arg_parse_int(const struct arg *arg); struct aom_rational arg_parse_rational(const struct arg *arg); int arg_parse_enum(const struct arg *arg); int arg_parse_enum_or_int(const struct arg *arg); +int arg_parse_list(const struct arg *arg, int *list, int n); #ifdef __cplusplus } // extern "C" #endif diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index a02193bce..457c32c19 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c @@ -36,10 +36,6 @@ struct av1_extracfg { unsigned int static_thresh; 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 @@ -105,10 +101,6 @@ 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 @@ -316,7 +308,6 @@ 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); @@ -639,8 +630,14 @@ 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; + oxcf->tile_width_count = AOMMIN(cfg->tile_width_count, MAX_TILE_COLS); + oxcf->tile_height_count = AOMMIN(cfg->tile_height_count, MAX_TILE_ROWS); + for (int i = 0; i < oxcf->tile_width_count; i++) { + oxcf->tile_widths[i] = AOMMAX(cfg->tile_widths[i], 1); + } + for (int i = 0; i < oxcf->tile_height_count; i++) { + oxcf->tile_heights[i] = AOMMAX(cfg->tile_heights[i], 1); + } #endif #if CONFIG_DEPENDENT_HORZTILES oxcf->dependent_horz_tiles = @@ -787,21 +784,6 @@ static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx, 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) { @@ -1582,10 +1564,6 @@ 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 @@ -1701,6 +1679,10 @@ static aom_codec_enc_cfg_map_t encoder_usage_cfg_map[] = { 0, // kf_min_dist 9999, // kf_max_dist 0, // large_scale_tile + 0, // tile_width_count + 0, // tile_height_count + { 0 }, // tile_widths + { 0 }, // tile_heights } }, }; diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index cc2d58055..2de36dea7 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c @@ -927,18 +927,20 @@ static void set_tile_info_max_tile(AV1_COMP *cpi) { av1_get_tile_limits(cm); // configure tile columns - if (cpi->oxcf.tile_width == 0 || cpi->oxcf.tile_height == 0) { + if (cpi->oxcf.tile_width_count == 0 || cpi->oxcf.tile_height_count == 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); + int size_sb, j = 0; 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; + size_sb = cpi->oxcf.tile_widths[j++]; + if (j >= cpi->oxcf.tile_width_count) j = 0; + start_sb += AOMMIN(size_sb, MAX_TILE_WIDTH_SB); } cm->tile_cols = i; cm->tile_col_start_sb[i] = sb_cols; @@ -952,10 +954,12 @@ static void set_tile_info_max_tile(AV1_COMP *cpi) { } 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); + int size_sb, j = 0; 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; + size_sb = cpi->oxcf.tile_heights[j++]; + if (j >= cpi->oxcf.tile_height_count) j = 0; + start_sb += AOMMIN(size_sb, cm->max_tile_height_sb); } cm->tile_rows = i; cm->tile_row_start_sb[i] = sb_rows; diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 84a7c2628..27f96b521 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h @@ -266,8 +266,10 @@ typedef struct AV1EncoderConfig { int tile_columns; int tile_rows; #if CONFIG_MAX_TILE - int tile_width; - int tile_height; + int tile_width_count; + int tile_height_count; + int tile_widths[MAX_TILE_COLS]; + int tile_heights[MAX_TILE_ROWS]; #endif #if CONFIG_DEPENDENT_HORZTILES int dependent_horz_tiles;