Commit cc6e0e16 authored by Maxym Dmytrychenko's avatar Maxym Dmytrychenko Committed by maxd

Adding config file parsing implementation

Parameters from config file will be added at --cfg options location to
be processed

Config file example:
 #ignore comment
 ext-partition   : 1 #ignore as well
 codec           : av1
 psnr            : ON

Note(s):
    - Config file is a simple text file
    - Comment starts with hash(#)
      Can be full line or part of the line, after hash(#) details are
ignored
    - Format: field : value
      colon(:) as delimeter, otherwise full line will be ignored
      Space(s) and tab(s) can be used, not inside field
    - long names for field are prefered
       existing --long_name option format
    - "no value" fields should contain ON as value

Example of usage:
    aomenc --cfg=some.cfg src_filename

Configurations support matrix:
enable-ext-partition         : done
enable-loop-restoration      : wip
enable-deblocking            : wip
...

Change-Id: Iad867c5d2da64271cdafa825c89f7d6444582f61
parent 5e911428
......@@ -499,6 +499,19 @@ typedef enum {
OBU_METADATA_TYPE_SCALABILITY = 3,
} OBU_METADATA_TYPE;
/*!\brief Config Options
*
* This type allows to enumerate and control options defined for control
* via config file at runtime.
*/
typedef struct cfg_options {
/*!\brief Reflects if ext_partition should be enabled
*
* If this value is non-zero it enabled the feature
*/
unsigned int ext_partition;
} cfg_options_t;
/*!@} - end defgroup codec*/
#ifdef __cplusplus
}
......
......@@ -105,6 +105,7 @@ typedef struct aom_codec_dec_cfg {
unsigned int w; /**< Width */
unsigned int h; /**< Height */
unsigned int allow_lowbitdepth; /**< Allow use of low-bitdepth coding path */
cfg_options_t cfg; /**< Options defined per config attributes */
} aom_codec_dec_cfg_t; /**< alias for struct aom_codec_dec_cfg */
/*!\brief Initialize a decoder instance
......
......@@ -668,6 +668,11 @@ typedef struct aom_codec_enc_cfg {
* The number of heights specified is given by tile_height_count
*/
int tile_heights[MAX_TILE_HEIGHTS];
/*!\brief Options defined per config file
*
*/
cfg_options_t cfg;
} aom_codec_enc_cfg_t; /**< alias for struct aom_codec_enc_cfg */
/*!\brief Initialize an encoder instance
......
......@@ -171,6 +171,11 @@ aom_codec_err_t aom_codec_enc_config_default(aom_codec_iface_t *iface,
}
}
/* default values */
if (cfg) {
cfg->cfg.ext_partition = CONFIG_EXT_PARTITION;
}
return res;
}
......
......@@ -513,7 +513,9 @@ static int main_loop(int argc, const char **argv_) {
int opt_yv12 = 0;
int opt_i420 = 0;
int opt_raw = 0;
aom_codec_dec_cfg_t cfg = { 0, 0, 0, CONFIG_LOWBITDEPTH };
aom_codec_dec_cfg_t cfg = {
0, 0, 0, CONFIG_LOWBITDEPTH, { CONFIG_EXT_PARTITION }
};
unsigned int output_bit_depth = 0;
#if CONFIG_EXT_TILE
unsigned int tile_mode = 0;
......
......@@ -165,6 +165,11 @@ static const arg_def_t verbosearg =
ARG_DEF("v", "verbose", 0, "Show encoder parameters");
static const arg_def_t psnrarg =
ARG_DEF(NULL, "psnr", 0, "Show PSNR in status line");
#if CONFIG_FILEOPTIONS
static const arg_def_t use_cfg = ARG_DEF("c", "cfg", 1, "Config file to use");
static const arg_def_t ext_partition =
ARG_DEF(NULL, "ext-partition", 1, "corresponds to CONFIG_EXT_PARTITION");
#endif
static const struct arg_enum_list test_decode_enum[] = {
{ "off", TEST_DECODE_OFF },
......@@ -206,6 +211,9 @@ static const arg_def_t bitdeptharg = ARG_DEF_ENUM(
static const arg_def_t inbitdeptharg =
ARG_DEF(NULL, "input-bit-depth", 1, "Bit depth of input");
static const arg_def_t *main_args[] = { &help,
#if CONFIG_FILEOPTIONS
&use_cfg,
#endif
&debugmode,
&outputfile,
&codecarg,
......@@ -915,11 +923,15 @@ static void validate_positive_rational(const char *msg,
if (!rat->den) die("Error: %s has zero denominator\n", msg);
}
static void parse_global_config(struct AvxEncoderConfig *global, char **argv) {
static void parse_global_config(struct AvxEncoderConfig *global, int *argc,
char ***argv) {
char **argi, **argj;
struct arg arg;
const int num_encoder = get_aom_encoder_count();
char **argv_local = (char **)*argv;
#if CONFIG_FILEOPTIONS
int argc_local = *argc;
#endif
if (num_encoder < 1) die("Error: no valid encoder available\n");
/* Initialize default parameters */
......@@ -928,9 +940,27 @@ static void parse_global_config(struct AvxEncoderConfig *global, char **argv) {
global->passes = 0;
global->color_type = I420;
for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
#if CONFIG_FILEOPTIONS
const char *cfg = NULL;
int cfg_included = 0;
#endif
for (argi = argj = argv_local; (*argj = *argi); argi += arg.argv_step) {
arg.argv_step = 1;
#if CONFIG_FILEOPTIONS
if (arg_match(&arg, &use_cfg, argi)) {
if (cfg_included) continue;
cfg = arg.val;
arg_cfg(&argc_local, &argv_local, cfg);
*argj = *argi = *argv_local;
argj = argi = argv_local;
*argv = argv_local;
cfg_included = 1;
continue;
}
#endif
if (arg_match(&arg, &help, argi)) {
show_help(stdout, 0);
exit(EXIT_SUCCESS);
......@@ -1310,6 +1340,10 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
} 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
#if CONFIG_FILEOPTIONS
} else if (arg_match(&arg, &ext_partition, argi)) {
config->cfg.cfg.ext_partition = !!arg_parse_uint(&arg) > 0;
#endif
} else {
int i, match = 0;
......@@ -1614,7 +1648,9 @@ static void initialize_encoder(struct stream_state *stream,
#if CONFIG_AV1_DECODER
if (global->test_decode != TEST_DECODE_OFF) {
const AvxInterface *decoder = get_aom_decoder_by_name(global->codec->name);
aom_codec_dec_cfg_t cfg = { 0, 0, 0, CONFIG_LOWBITDEPTH };
aom_codec_dec_cfg_t cfg = {
0, 0, 0, CONFIG_LOWBITDEPTH, { CONFIG_EXT_PARTITION }
};
aom_codec_dec_init(&stream->decoder, decoder->codec_interface(), &cfg, 0);
#if CONFIG_EXT_TILE
......@@ -1959,9 +1995,13 @@ int main(int argc, const char **argv_) {
* codec.
*/
argv = argv_dup(argc - 1, argv_ + 1);
parse_global_config(&global, argv);
parse_global_config(&global, &argc, &argv);
#if CONFIG_FILEOPTIONS
if (argc < 2) usage_exit();
#else
if (argc < 3) usage_exit();
#endif
switch (global.color_type) {
case I420: input.fmt = AOM_IMG_FMT_I420; break;
......
......@@ -34,6 +34,65 @@ struct arg arg_init(char **argv) {
return a;
}
char *ignore_front_spaces(const char *str) {
while (str[0] == ' ' || str[0] == '\t') ++str;
return (char *)str;
}
void ignore_end_spaces(char *str) {
char *end = str + strlen(str);
while (end > str && (end[0] == ' ' || end[0] == '\t' || end[0] == '\n' ||
end[0] == '\r' || end[0] == '\0'))
--end;
if (end >= str) end[1] = '\0';
}
int arg_cfg(int *argc, char ***argv, const char *file) {
char **argv_local = (char **)*argv;
char **argv_org = (char **)*argv;
char line[1024 * 10];
FILE *f = fopen(file, "r");
if (!f) return 1;
while (fgets(line, sizeof(line) - 1, f)) {
char *actual_line = ignore_front_spaces(line);
char *left, *right, *comment;
size_t length = strlen(actual_line);
if (length == 0 || actual_line[0] == '#') continue;
right = strchr(actual_line, ':');
if (right == NULL) continue;
right[0] = '\0';
left = ignore_front_spaces(actual_line);
right = ignore_front_spaces(right + 1);
comment = strchr(right, '#');
if (comment != NULL) comment[0] = '\0';
ignore_end_spaces(left);
ignore_end_spaces(right);
char **new_args = argv_dup(*argc, (const char **)argv_local);
char *new_line = (char *)malloc(sizeof(*new_line) * 128);
if (argv_local != argv_org) free(argv_local);
if (!strcmp(right, "ON"))
snprintf(new_line, sizeof(*new_line) * 128, "--%s", left);
else
snprintf(new_line, sizeof(*new_line) * 128, "--%s=%s", left, right);
new_args[(*argc) - 1] = new_args[(*argc) - 2];
new_args[(*argc) - 2] = new_line;
argv_local = new_args;
*argv = new_args;
(*argc)++;
}
fclose(f);
return 0;
}
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
struct arg arg;
......
......@@ -48,6 +48,9 @@ typedef struct arg_def {
struct arg arg_init(char **argv);
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
char *ignore_front_spaces(const char *str);
void ignore_end_spaces(char *str);
int arg_cfg(int *argc, char ***argv, const char *file);
const char *arg_next(struct arg *arg);
void arg_show_usage(FILE *fp, const struct arg_def *const *defs);
char **argv_dup(int argc, const char **argv);
......
......@@ -540,6 +540,7 @@ static aom_codec_err_t set_encoder_config(
#endif
oxcf->mode = GOOD;
oxcf->cfg = &cfg->cfg;
switch (cfg->g_pass) {
case AOM_RC_ONE_PASS: oxcf->pass = 0; break;
......@@ -1886,15 +1887,16 @@ static aom_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
2000, // rc_two_pass_vbrmax_section
// keyframing settings (kf)
AOM_KF_AUTO, // g_kfmode
0, // kf_min_dist
9999, // kf_max_dist
0, // large_scale_tile
0, // monochrome
0, // tile_width_count
0, // tile_height_count
{ 0 }, // tile_widths
{ 0 }, // tile_heights
AOM_KF_AUTO, // g_kfmode
0, // kf_min_dist
9999, // kf_max_dist
0, // large_scale_tile
0, // monochrome
0, // tile_width_count
0, // tile_height_count
{ 0 }, // tile_widths
{ 0 }, // tile_heights
{ CONFIG_EXT_PARTITION }, // config file
} },
};
......
......@@ -119,6 +119,8 @@ static aom_codec_err_t decoder_init(aom_codec_ctx_t *ctx,
if (ctx->config.dec) {
priv->cfg = *ctx->config.dec;
ctx->config.dec = &priv->cfg;
// default values
priv->cfg.cfg.ext_partition = CONFIG_EXT_PARTITION;
}
#if CONFIG_FILM_GRAIN
priv->image_with_grain = NULL;
......@@ -597,6 +599,7 @@ static aom_codec_err_t init_decoder(aom_codec_alg_priv_t *ctx) {
set_error_detail(ctx, "Failed to allocate frame_worker_data");
return AOM_CODEC_MEM_ERROR;
}
frame_worker_data->pbi->common.options = &ctx->cfg.cfg;
frame_worker_data->pbi->frame_worker_owner = worker;
frame_worker_data->worker_id = i;
frame_worker_data->scratch_buffer = NULL;
......
......@@ -621,6 +621,7 @@ typedef struct AV1Common {
int64_t txcoeff_cost_timer;
int64_t txcoeff_cost_count;
#endif
const cfg_options_t *options;
} AV1_COMMON;
// TODO(hkuang): Don't need to lock the whole pool after implementing atomic
......
......@@ -288,9 +288,11 @@ static BLOCK_SIZE select_sb_size(const AV1_COMP *const cpi) {
#if CONFIG_EXT_PARTITION
if (cpi->oxcf.superblock_size == AOM_SUPERBLOCK_SIZE_64X64)
return BLOCK_64X64;
if (cpi->oxcf.superblock_size == AOM_SUPERBLOCK_SIZE_128X128)
return BLOCK_128X128;
#if CONFIG_FILEOPTIONS
if (cpi->common.options && cpi->common.options->ext_partition)
#endif
if (cpi->oxcf.superblock_size == AOM_SUPERBLOCK_SIZE_128X128)
return BLOCK_128X128;
assert(cpi->oxcf.superblock_size == AOM_SUPERBLOCK_SIZE_DYNAMIC);
......@@ -303,7 +305,11 @@ static BLOCK_SIZE select_sb_size(const AV1_COMP *const cpi) {
cpi->common.tile_height % MAX_MIB_SIZE == 0));
#endif
// TODO(any): Possibly could improve this with a heuristic.
// TODO(any): Possibly could improve this with a heuristic.
#if CONFIG_FILEOPTIONS
if (cpi->common.options && !cpi->common.options->ext_partition)
return BLOCK_64X64;
#endif
return BLOCK_128X128;
#else
(void)cpi;
......@@ -3153,6 +3159,7 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
#endif
cpi->oxcf = *oxcf;
cpi->common.options = oxcf->cfg;
x->e_mbd.bd = (int)cm->bit_depth;
x->e_mbd.global_motion = cm->global_motion;
......
......@@ -318,6 +318,7 @@ typedef struct AV1EncoderConfig {
#endif // CONFIG_MONO_VIDEO
unsigned int motion_vector_unit_test;
const cfg_options_t *cfg;
} AV1EncoderConfig;
static INLINE int is_lossless_requested(const AV1EncoderConfig *cfg) {
......
......@@ -157,3 +157,4 @@ set(CONFIG_TIMING_INFO_IN_SEQ_HEADERS 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TMV 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TX64X64 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TXK_SEL 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_FILEOPTIONS 1 CACHE NUMBER "AV1 config option flag.")
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