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
diff --git a/aom/aom_codec.h b/aom/aom_codec.h
index 6800bb2..ff9647a 100644
--- a/aom/aom_codec.h
+++ b/aom/aom_codec.h
@@ -499,6 +499,19 @@
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
}
diff --git a/aom/aom_decoder.h b/aom/aom_decoder.h
index d92e43a..0f62bed 100644
--- a/aom/aom_decoder.h
+++ b/aom/aom_decoder.h
@@ -105,6 +105,7 @@
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
diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h
index 516d797..c32e515 100644
--- a/aom/aom_encoder.h
+++ b/aom/aom_encoder.h
@@ -668,6 +668,11 @@
* 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
diff --git a/aom/src/aom_encoder.c b/aom/src/aom_encoder.c
index c5abb9f..e3ac522 100644
--- a/aom/src/aom_encoder.c
+++ b/aom/src/aom_encoder.c
@@ -171,6 +171,11 @@
}
}
+ /* default values */
+ if (cfg) {
+ cfg->cfg.ext_partition = CONFIG_EXT_PARTITION;
+ }
+
return res;
}
diff --git a/aomdec.c b/aomdec.c
index 5f9181f..739cd69 100644
--- a/aomdec.c
+++ b/aomdec.c
@@ -513,7 +513,9 @@
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;
diff --git a/aomenc.c b/aomenc.c
index f6921eb..aa2e32c 100644
--- a/aomenc.c
+++ b/aomenc.c
@@ -165,6 +165,11 @@
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 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 @@
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 @@
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);
@@ -1311,6 +1341,10 @@
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;
for (i = 0; ctrl_args[i]; i++) {
@@ -1614,7 +1648,9 @@
#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 @@
* 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;
diff --git a/args.c b/args.c
index b9384de..0ecbf4b 100644
--- a/args.c
+++ b/args.c
@@ -34,6 +34,65 @@
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;
diff --git a/args.h b/args.h
index c3427bc..d129736 100644
--- a/args.h
+++ b/args.h
@@ -48,6 +48,9 @@
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);
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 024926f..3304634 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -540,6 +540,7 @@
#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 @@
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
} },
};
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index 6ede519..b80cba4 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -119,6 +119,8 @@
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 @@
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;
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index cc19377..df510bd 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -621,6 +621,7 @@
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
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 881abdc..95c2288 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -288,9 +288,11 @@
#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 @@
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 @@
#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;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 404fa48..a3ac132 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -318,6 +318,7 @@
#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) {
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index e1a70ce..2bdc273 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -157,3 +157,4 @@
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.")