From dad09ff93f5df1ec987493f404d43cd16991e992 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 29 Aug 2011 07:03:24 +0200 Subject: cmdutils: move exit_program() declaration to cmdutils from avconv Allows cmdutils to call each tool's own cleanup function. --- cmdutils.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'cmdutils.c') diff --git a/cmdutils.c b/cmdutils.c index a6402af596..a86c55bc6d 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -92,7 +92,8 @@ double parse_number_or_die(const char *context, const char *numstr, int type, do else return d; fprintf(stderr, error, context, numstr, min, max); - exit(1); + exit_program(1); + return 0; } int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration) @@ -101,7 +102,7 @@ int64_t parse_time_or_die(const char *context, const char *timestr, int is_durat if (av_parse_time(&us, timestr, is_duration) < 0) { fprintf(stderr, "Invalid %s specification for %s: %s\n", is_duration ? "duration" : "date", context, timestr); - exit(1); + exit_program(1); } return us; } @@ -237,14 +238,14 @@ void parse_options(int argc, char **argv, const OptionDef *options, if (!po->name) { unknown_opt: fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt); - exit(1); + exit_program(1); } arg = NULL; if (po->flags & HAS_ARG) { arg = argv[optindex++]; if (!arg) { fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt); - exit(1); + exit_program(1); } } if (po->flags & OPT_STRING) { @@ -262,11 +263,11 @@ unknown_opt: } else if (po->u.func_arg) { if (po->u.func_arg(opt, arg) < 0) { fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt); - exit(1); + exit_program(1); } } if(po->flags & OPT_EXIT) - exit(0); + exit_program(0); } else { if (parse_arg_function) parse_arg_function(opt); @@ -336,7 +337,7 @@ int opt_loglevel(const char *opt, const char *arg) "Possible levels are numbers or:\n", arg); for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) fprintf(stderr, "\"%s\"\n", log_levels[i].name); - exit(1); + exit_program(1); } av_log_set_level(level); return 0; -- cgit v1.2.3 From cac651c83417dde3b64a6620cac32f078c9c399f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 29 Aug 2011 07:11:57 +0200 Subject: cmdutils: move grow_array() from avconv to cmdutils. --- avconv.c | 20 -------------------- cmdutils.c | 19 +++++++++++++++++++ cmdutils.h | 10 ++++++++++ ffmpeg.c | 20 -------------------- 4 files changed, 29 insertions(+), 40 deletions(-) (limited to 'cmdutils.c') diff --git a/avconv.c b/avconv.c index 52a71085fa..33da836a90 100644 --- a/avconv.c +++ b/avconv.c @@ -511,26 +511,6 @@ static void assert_codec_experimental(AVCodecContext *c, int encoder) } } -/* similar to ff_dynarray_add() and av_fast_realloc() */ -static void *grow_array(void *array, int elem_size, int *size, int new_size) -{ - if (new_size >= INT_MAX / elem_size) { - fprintf(stderr, "Array too big.\n"); - exit_program(1); - } - if (*size < new_size) { - uint8_t *tmp = av_realloc(array, new_size*elem_size); - if (!tmp) { - fprintf(stderr, "Could not alloc buffer.\n"); - exit_program(1); - } - memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); - *size = new_size; - return tmp; - } - return array; -} - static void choose_sample_fmt(AVStream *st, AVCodec *codec) { if(codec && codec->sample_fmts){ diff --git a/cmdutils.c b/cmdutils.c index a86c55bc6d..9e34e43128 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -931,4 +931,23 @@ int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame, return 1; } +void *grow_array(void *array, int elem_size, int *size, int new_size) +{ + if (new_size >= INT_MAX / elem_size) { + av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); + exit_program(1); + } + if (*size < new_size) { + uint8_t *tmp = av_realloc(array, new_size*elem_size); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); + exit_program(1); + } + memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); + *size = new_size; + return tmp; + } + return array; +} + #endif /* CONFIG_AVFILTER */ diff --git a/cmdutils.h b/cmdutils.h index 65b1ae48b7..2173f0d34b 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -333,4 +333,14 @@ int get_filtered_video_frame(AVFilterContext *sink, AVFrame *frame, */ void exit_program(int ret); +/** + * Realloc array to hold new_size elements of elem_size. + * Calls exit_program() on failure. + * + * @param elem_size size in bytes of each element + * @param size new element count will be written here + * @return reallocated array + */ +void *grow_array(void *array, int elem_size, int *size, int new_size); + #endif /* LIBAV_CMDUTILS_H */ diff --git a/ffmpeg.c b/ffmpeg.c index eec028f8eb..242cd3ffa7 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -529,26 +529,6 @@ static void assert_codec_experimental(AVCodecContext *c, int encoder) } } -/* similar to ff_dynarray_add() and av_fast_realloc() */ -static void *grow_array(void *array, int elem_size, int *size, int new_size) -{ - if (new_size >= INT_MAX / elem_size) { - fprintf(stderr, "Array too big.\n"); - exit_program(1); - } - if (*size < new_size) { - uint8_t *tmp = av_realloc(array, new_size*elem_size); - if (!tmp) { - fprintf(stderr, "Could not alloc buffer.\n"); - exit_program(1); - } - memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); - *size = new_size; - return tmp; - } - return array; -} - static void choose_sample_fmt(AVStream *st, AVCodec *codec) { if(codec && codec->sample_fmts){ -- cgit v1.2.3 From 7efe05ab298ae18437c9796f43b9f47474763a39 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 Aug 2011 14:27:27 +0200 Subject: cmdutils: declare only one pointer type in OptionDef This will be useful in the following commit. --- cmdutils.c | 12 +++++++----- cmdutils.h | 5 +---- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'cmdutils.c') diff --git a/cmdutils.c b/cmdutils.c index 9e34e43128..53ef7aed3c 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -216,6 +216,7 @@ void parse_options(int argc, char **argv, const OptionDef *options, /* parse options */ optindex = 1; while (optindex < argc) { + void *dst; opt = argv[optindex++]; if (handleoptions && opt[0] == '-' && opt[1] != '\0') { @@ -248,18 +249,19 @@ unknown_opt: exit_program(1); } } + dst = po->u.dst_ptr; if (po->flags & OPT_STRING) { char *str; str = av_strdup(arg); - *po->u.str_arg = str; + *(char**)dst = str; } else if (po->flags & OPT_BOOL) { - *po->u.int_arg = bool_val; + *(int*)dst = bool_val; } else if (po->flags & OPT_INT) { - *po->u.int_arg = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); + *(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); } else if (po->flags & OPT_INT64) { - *po->u.int64_arg = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); + *(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); } else if (po->flags & OPT_FLOAT) { - *po->u.float_arg = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); + *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); } else if (po->u.func_arg) { if (po->u.func_arg(opt, arg) < 0) { fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt); diff --git a/cmdutils.h b/cmdutils.h index 2173f0d34b..e72c730fa7 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -125,11 +125,8 @@ typedef struct { #define OPT_EXIT 0x0800 #define OPT_DATA 0x1000 union { - int *int_arg; - char **str_arg; - float *float_arg; + void *dst_ptr; int (*func_arg)(const char *, const char *); - int64_t *int64_arg; } u; const char *help; const char *argname; -- cgit v1.2.3 From 7cc8d6385aaf1005700305f21d5d56b51b38c537 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 Aug 2011 14:43:54 +0200 Subject: cmdutils: add support for caller-provided option context. This is the first step to removing the globals plague from avtools. --- avconv.c | 4 ++-- avplay.c | 4 ++-- avprobe.c | 4 ++-- avserver.c | 2 +- cmdutils.c | 14 +++++++++----- cmdutils.h | 10 ++++++++-- ffmpeg.c | 4 ++-- 7 files changed, 26 insertions(+), 16 deletions(-) (limited to 'cmdutils.c') diff --git a/avconv.c b/avconv.c index 33da836a90..92273f1ce7 100644 --- a/avconv.c +++ b/avconv.c @@ -3403,7 +3403,7 @@ static int read_avserver_streams(AVFormatContext *s, const char *filename) return 0; } -static void opt_output_file(const char *filename) +static void opt_output_file(void *optctx, const char *filename) { AVFormatContext *oc; int i, err; @@ -4143,7 +4143,7 @@ int main(int argc, char **argv) show_banner(); /* parse options */ - parse_options(argc, argv, options, opt_output_file); + parse_options(NULL, argc, argv, options, opt_output_file); if(nb_output_files <= 0 && nb_input_files == 0) { show_usage(); diff --git a/avplay.c b/avplay.c index 212ab2c9b2..198dce1d2b 100644 --- a/avplay.c +++ b/avplay.c @@ -3015,7 +3015,7 @@ static void show_help(void) ); } -static void opt_input_file(const char *filename) +static void opt_input_file(void *optctx, const char *filename) { if (input_filename) { fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n", @@ -3048,7 +3048,7 @@ int main(int argc, char **argv) show_banner(); - parse_options(argc, argv, options, opt_input_file); + parse_options(NULL, argc, argv, options, opt_input_file); if (!input_filename) { show_usage(); diff --git a/avprobe.c b/avprobe.c index a8a0f14eb7..5e83916f87 100644 --- a/avprobe.c +++ b/avprobe.c @@ -346,7 +346,7 @@ static int opt_format(const char *opt, const char *arg) return 0; } -static void opt_input_file(const char *arg) +static void opt_input_file(void *optctx, const char *arg) { if (input_filename) { fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n", @@ -406,7 +406,7 @@ int main(int argc, char **argv) #endif show_banner(); - parse_options(argc, argv, options, opt_input_file); + parse_options(NULL, argc, argv, options, opt_input_file); if (!input_filename) { show_usage(); diff --git a/avserver.c b/avserver.c index 1b11cbf973..df9d07d1ad 100644 --- a/avserver.c +++ b/avserver.c @@ -4676,7 +4676,7 @@ int main(int argc, char **argv) my_program_dir = getcwd(0, 0); avserver_daemon = 1; - parse_options(argc, argv, options, NULL); + parse_options(NULL, argc, argv, options, NULL); unsetenv("http_proxy"); /* Kill the http_proxy */ diff --git a/cmdutils.c b/cmdutils.c index 53ef7aed3c..ea25836f8f 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -203,8 +203,8 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) } #endif /* WIN32 && !__MINGW32CE__ */ -void parse_options(int argc, char **argv, const OptionDef *options, - void (* parse_arg_function)(const char*)) +void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, + void (* parse_arg_function)(void *, const char*)) { const char *opt, *arg; int optindex, handleoptions=1; @@ -249,7 +249,9 @@ unknown_opt: exit_program(1); } } - dst = po->u.dst_ptr; + /* new-style options contain an offset into optctx, old-style address of + * a global var*/ + dst = po->flags & OPT_OFFSET ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr; if (po->flags & OPT_STRING) { char *str; str = av_strdup(arg); @@ -263,7 +265,9 @@ unknown_opt: } else if (po->flags & OPT_FLOAT) { *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); } else if (po->u.func_arg) { - if (po->u.func_arg(opt, arg) < 0) { + int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) : + po->u.func_arg(opt, arg); + if (ret < 0) { fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt); exit_program(1); } @@ -272,7 +276,7 @@ unknown_opt: exit_program(0); } else { if (parse_arg_function) - parse_arg_function(opt); + parse_arg_function(optctx, opt); } } } diff --git a/cmdutils.h b/cmdutils.h index e72c730fa7..a4716cad61 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -124,9 +124,13 @@ typedef struct { #define OPT_INT64 0x0400 #define OPT_EXIT 0x0800 #define OPT_DATA 0x1000 +#define OPT_FUNC2 0x2000 +#define OPT_OFFSET 0x4000 /* option is specified as an offset in a passed optctx */ union { void *dst_ptr; int (*func_arg)(const char *, const char *); + int (*func2_arg)(void *, const char *, const char *); + size_t off; } u; const char *help; const char *argname; @@ -136,14 +140,16 @@ void show_help_options(const OptionDef *options, const char *msg, int mask, int /** * Parse the command line arguments. + * + * @param optctx an opaque options context * @param options Array with the definitions required to interpret every * option of the form: -option_name [argument] * @param parse_arg_function Name of the function called to process every * argument without a leading option name flag. NULL if such arguments do * not have to be processed. */ -void parse_options(int argc, char **argv, const OptionDef *options, - void (* parse_arg_function)(const char*)); +void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, + void (* parse_arg_function)(void *optctx, const char*)); /** * Check if the given stream matches a stream specifier. diff --git a/ffmpeg.c b/ffmpeg.c index 242cd3ffa7..a440b9dacb 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -3702,7 +3702,7 @@ static int opt_streamid(const char *opt, const char *arg) return 0; } -static void opt_output_file(const char *filename) +static void opt_output_file(void *optctx, const char *filename) { AVFormatContext *oc; int err, use_video, use_audio, use_subtitle, use_data; @@ -4376,7 +4376,7 @@ int main(int argc, char **argv) "(see Changelog for the list of incompatible changes).\n"); /* parse options */ - parse_options(argc, argv, options, opt_output_file); + parse_options(NULL, argc, argv, options, opt_output_file); if(nb_output_files <= 0 && nb_input_files == 0) { show_usage(); -- cgit v1.2.3 From 2f8e586df14649ebf1538dc610928c844e0068ec Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 29 Aug 2011 08:11:03 +0200 Subject: cmdutils: split per-option code out of parse_options(). This allows options like -target, which are just shortcuts for other options, to work without dummy function for all options they invoke. --- cmdutils.c | 112 +++++++++++++++++++++++++++++++++---------------------------- cmdutils.h | 7 ++++ 2 files changed, 67 insertions(+), 52 deletions(-) (limited to 'cmdutils.c') diff --git a/cmdutils.c b/cmdutils.c index ea25836f8f..1eed404647 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -203,12 +203,66 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) } #endif /* WIN32 && !__MINGW32CE__ */ +int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options) +{ + const OptionDef *po; + int bool_val = 1; + void *dst; + + po = find_option(options, opt); + if (!po->name && opt[0] == 'n' && opt[1] == 'o') { + /* handle 'no' bool option */ + po = find_option(options, opt + 2); + if (!(po->name && (po->flags & OPT_BOOL))) + goto unknown_opt; + bool_val = 0; + } + if (!po->name) + po = find_option(options, "default"); + if (!po->name) { +unknown_opt: + av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); + return AVERROR(EINVAL); + } + if (po->flags & HAS_ARG && !arg) { + av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); + return AVERROR(EINVAL); + } + + /* new-style options contain an offset into optctx, old-style address of + * a global var*/ + dst = po->flags & (OPT_OFFSET) ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr; + + if (po->flags & OPT_STRING) { + char *str; + str = av_strdup(arg); + *(char**)dst = str; + } else if (po->flags & OPT_BOOL) { + *(int*)dst = bool_val; + } else if (po->flags & OPT_INT) { + *(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); + } else if (po->flags & OPT_INT64) { + *(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); + } else if (po->flags & OPT_FLOAT) { + *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); + } else if (po->u.func_arg) { + int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) : + po->u.func_arg(opt, arg); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to set value '%s' for option '%s'\n", arg, opt); + return ret; + } + } + if (po->flags & OPT_EXIT) + exit_program(0); + return !!(po->flags & HAS_ARG); +} + void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void (* parse_arg_function)(void *, const char*)) { - const char *opt, *arg; - int optindex, handleoptions=1; - const OptionDef *po; + const char *opt; + int optindex, handleoptions = 1, ret; /* perform system-dependent conversions for arguments list */ prepare_app_arguments(&argc, &argv); @@ -216,64 +270,18 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options /* parse options */ optindex = 1; while (optindex < argc) { - void *dst; opt = argv[optindex++]; if (handleoptions && opt[0] == '-' && opt[1] != '\0') { - int bool_val = 1; if (opt[1] == '-' && opt[2] == '\0') { handleoptions = 0; continue; } opt++; - po= find_option(options, opt); - if (!po->name && opt[0] == 'n' && opt[1] == 'o') { - /* handle 'no' bool option */ - po = find_option(options, opt + 2); - if (!(po->name && (po->flags & OPT_BOOL))) - goto unknown_opt; - bool_val = 0; - } - if (!po->name) - po= find_option(options, "default"); - if (!po->name) { -unknown_opt: - fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt); + + if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) exit_program(1); - } - arg = NULL; - if (po->flags & HAS_ARG) { - arg = argv[optindex++]; - if (!arg) { - fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt); - exit_program(1); - } - } - /* new-style options contain an offset into optctx, old-style address of - * a global var*/ - dst = po->flags & OPT_OFFSET ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr; - if (po->flags & OPT_STRING) { - char *str; - str = av_strdup(arg); - *(char**)dst = str; - } else if (po->flags & OPT_BOOL) { - *(int*)dst = bool_val; - } else if (po->flags & OPT_INT) { - *(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); - } else if (po->flags & OPT_INT64) { - *(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); - } else if (po->flags & OPT_FLOAT) { - *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); - } else if (po->u.func_arg) { - int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) : - po->u.func_arg(opt, arg); - if (ret < 0) { - fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt); - exit_program(1); - } - } - if(po->flags & OPT_EXIT) - exit_program(0); + optindex += ret; } else { if (parse_arg_function) parse_arg_function(optctx, opt); diff --git a/cmdutils.h b/cmdutils.h index a4716cad61..f0c9079647 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -151,6 +151,13 @@ void show_help_options(const OptionDef *options, const char *msg, int mask, int void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void (* parse_arg_function)(void *optctx, const char*)); +/** + * Parse one given option. + * + * @return on success 1 if arg was consumed, 0 otherwise; negative number on error + */ +int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options); + /** * Check if the given stream matches a stream specifier. * -- cgit v1.2.3 From 6361c5e1e61033259e91b480f23ae81bed775c8b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 29 Aug 2011 07:54:56 +0200 Subject: cmdutils: allow storing per-stream/chapter/.... options in a generic way --- cmdutils.c | 13 ++++++++++++- cmdutils.h | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'cmdutils.c') diff --git a/cmdutils.c b/cmdutils.c index 1eed404647..6c64d47d01 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -207,6 +207,7 @@ int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef { const OptionDef *po; int bool_val = 1; + int *dstcount; void *dst; po = find_option(options, opt); @@ -231,7 +232,17 @@ unknown_opt: /* new-style options contain an offset into optctx, old-style address of * a global var*/ - dst = po->flags & (OPT_OFFSET) ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr; + dst = po->flags & (OPT_OFFSET|OPT_SPEC) ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr; + + if (po->flags & OPT_SPEC) { + SpecifierOpt **so = dst; + char *p = strchr(opt, ':'); + + dstcount = (int*)(so + 1); + *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); + (*so)[*dstcount - 1].specifier = av_strdup(p ? p + 1 : ""); + dst = &(*so)[*dstcount - 1].u; + } if (po->flags & OPT_STRING) { char *str; diff --git a/cmdutils.h b/cmdutils.h index f0c9079647..003c928fc6 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -108,6 +108,16 @@ double parse_number_or_die(const char *context, const char *numstr, int type, do */ int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration); +typedef struct SpecifierOpt { + char *specifier; /**< stream/chapter/program/... specifier */ + union { + uint8_t *str; + int i; + int64_t i64; + float f; + } u; +} SpecifierOpt; + typedef struct { const char *name; int flags; @@ -126,6 +136,9 @@ typedef struct { #define OPT_DATA 0x1000 #define OPT_FUNC2 0x2000 #define OPT_OFFSET 0x4000 /* option is specified as an offset in a passed optctx */ +#define OPT_SPEC 0x8000 /* option is to be stored in an array of SpecifierOpt. + Implies OPT_OFFSET. Next element after the offset is + an int containing element count in the array. */ union { void *dst_ptr; int (*func_arg)(const char *, const char *); -- cgit v1.2.3 From 6b779cccaab1856575b1840e09510b0f54e988a6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 Aug 2011 18:20:17 +0200 Subject: avconv: move start_time, recording_time and input_ts_offset to options context --- avconv.c | 68 +++++++++++++++++++----------------------------- cmdutils.c | 2 ++ cmdutils.h | 1 + tests/fate.mak | 4 +-- tests/fate2.mak | 2 +- tests/lavf-regression.sh | 4 +-- 6 files changed, 35 insertions(+), 46 deletions(-) (limited to 'cmdutils.c') diff --git a/avconv.c b/avconv.c index d1b99cdce1..1e354ff58d 100644 --- a/avconv.c +++ b/avconv.c @@ -158,9 +158,6 @@ static unsigned int data_codec_tag = 0; static float mux_preload= 0.5; static float mux_max_delay= 0.7; -static int64_t recording_time = INT64_MAX; -static int64_t start_time = 0; -static int64_t input_ts_offset = 0; static int file_overwrite = 0; static AVDictionary *metadata; static int do_benchmark = 0; @@ -315,9 +312,17 @@ static OutputFile *output_files = NULL; static int nb_output_files = 0; typedef struct OptionsContext { + /* input/output options */ + int64_t start_time; + + /* input options */ + int64_t input_ts_offset; + /* output options */ StreamMap *stream_maps; int nb_stream_maps; + + int64_t recording_time; } OptionsContext; static void reset_options(OptionsContext *o) @@ -346,6 +351,9 @@ static void reset_options(OptionsContext *o) av_freep(&o->stream_maps); memset(o, 0, sizeof(*o)); + + o->recording_time = INT64_MAX; + uninit_opts(); init_opts(); } @@ -2778,24 +2786,6 @@ static int opt_input_ts_scale(const char *opt, const char *arg) return av_dict_set(&ts_scale, opt, arg, 0); } -static int opt_recording_time(const char *opt, const char *arg) -{ - recording_time = parse_time_or_die(opt, arg, 1); - return 0; -} - -static int opt_start_time(const char *opt, const char *arg) -{ - start_time = parse_time_or_die(opt, arg, 1); - return 0; -} - -static int opt_input_ts_offset(const char *opt, const char *arg) -{ - input_ts_offset = parse_time_or_die(opt, arg, 1); - return 0; -} - static enum CodecID find_codec_or_die(const char *name, enum AVMediaType type, int encoder) { const char *codec_string = encoder ? "encoder" : "decoder"; @@ -3030,20 +3020,18 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena exit_program(1); } - timestamp = start_time; + timestamp = o->start_time; /* add the stream start time */ if (ic->start_time != AV_NOPTS_VALUE) timestamp += ic->start_time; /* if seeking requested, we execute it */ - if (start_time != 0) { + if (o->start_time != 0) { ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD); if (ret < 0) { fprintf(stderr, "%s: could not seek to position %0.3f\n", filename, (double)timestamp / AV_TIME_BASE); } - /* reset seek info */ - start_time = 0; } /* update the current parameters so that they match the one of the input stream */ @@ -3056,7 +3044,7 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1); input_files[nb_input_files - 1].ctx = ic; input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams; - input_files[nb_input_files - 1].ts_offset = input_ts_offset - (copy_ts ? 0 : timestamp); + input_files[nb_input_files - 1].ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp); input_files[nb_input_files - 1].nb_streams = ic->nb_streams; frame_rate = (AVRational){0, 0}; @@ -3067,7 +3055,6 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena audio_channels = 0; audio_sample_fmt = AV_SAMPLE_FMT_NONE; av_dict_free(&ts_scale); - input_ts_offset = 0; for (i = 0; i < orig_nb_streams; i++) av_dict_free(&opts[i]); @@ -3364,18 +3351,18 @@ static int opt_streamid(const char *opt, const char *arg) return 0; } -static int copy_chapters(int infile, int outfile) +static int copy_chapters(InputFile *ifile, OutputFile *ofile) { - AVFormatContext *is = input_files[infile].ctx; - AVFormatContext *os = output_files[outfile].ctx; + AVFormatContext *is = ifile->ctx; + AVFormatContext *os = ofile->ctx; int i; for (i = 0; i < is->nb_chapters; i++) { AVChapter *in_ch = is->chapters[i], *out_ch; - int64_t ts_off = av_rescale_q(start_time - input_files[infile].ts_offset, + int64_t ts_off = av_rescale_q(ofile->start_time - ifile->ts_offset, AV_TIME_BASE_Q, in_ch->time_base); - int64_t rt = (recording_time == INT64_MAX) ? INT64_MAX : - av_rescale_q(recording_time, AV_TIME_BASE_Q, in_ch->time_base); + int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : + av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); if (in_ch->end < ts_off) @@ -3563,8 +3550,8 @@ static void opt_output_file(void *optctx, const char *filename) output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1); output_files[nb_output_files - 1].ctx = oc; output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; - output_files[nb_output_files - 1].recording_time = recording_time; - output_files[nb_output_files - 1].start_time = start_time; + output_files[nb_output_files - 1].recording_time = o->recording_time; + output_files[nb_output_files - 1].start_time = o->start_time; output_files[nb_output_files - 1].limit_filesize = limit_filesize; av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); @@ -3626,7 +3613,7 @@ static void opt_output_file(void *optctx, const char *filename) } } if (chapters_input_file >= 0) - copy_chapters(chapters_input_file, nb_output_files - 1); + copy_chapters(&input_files[chapters_input_file], &output_files[nb_output_files - 1]); /* copy metadata */ for (i = 0; i < nb_meta_data_maps; i++) { @@ -3691,8 +3678,6 @@ static void opt_output_file(void *optctx, const char *filename) audio_channels = 0; audio_sample_fmt = AV_SAMPLE_FMT_NONE; chapters_input_file = INT_MAX; - recording_time = INT64_MAX; - start_time = 0; limit_filesize = UINT64_MAX; av_freep(&meta_data_maps); @@ -4042,6 +4027,7 @@ static int opt_bsf(const char *opt, const char *arg) return 0; } +#define OFFSET(x) offsetof(OptionsContext, x) static const OptionDef options[] = { /* main options */ #include "cmdutils_common_opts.h" @@ -4054,10 +4040,10 @@ static const OptionDef options[] = { { "map_metadata", HAS_ARG | OPT_EXPERT, {(void*)opt_map_metadata}, "set metadata information of outfile from infile", "outfile[,metadata]:infile[,metadata]" }, { "map_chapters", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&chapters_input_file}, "set chapters mapping", "input_file_index" }, - { "t", HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" }, + { "t", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(recording_time)}, "record or transcode \"duration\" seconds of audio/video", "duration" }, { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, // - { "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, - { "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, + { "ss", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(start_time)}, "set the start time offset", "time_off" }, + { "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(input_ts_offset)}, "set the input ts offset", "time_off" }, { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "scale" }, { "metadata", HAS_ARG, {(void*)opt_metadata}, "add metadata", "string=string" }, { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[AVMEDIA_TYPE_DATA]}, "set the number of data frames to record", "number" }, diff --git a/cmdutils.c b/cmdutils.c index 6c64d47d01..3a41f45dbd 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -254,6 +254,8 @@ unknown_opt: *(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); } else if (po->flags & OPT_INT64) { *(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); + } else if (po->flags & OPT_TIME) { + *(int64_t*)dst = parse_time_or_die(opt, arg, 1); } else if (po->flags & OPT_FLOAT) { *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); } else if (po->u.func_arg) { diff --git a/cmdutils.h b/cmdutils.h index 003c928fc6..61cfc229b7 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -139,6 +139,7 @@ typedef struct { #define OPT_SPEC 0x8000 /* option is to be stored in an array of SpecifierOpt. Implies OPT_OFFSET. Next element after the offset is an int containing element count in the array. */ +#define OPT_TIME 0x10000 union { void *dst_ptr; int (*func_arg)(const char *, const char *); diff --git a/tests/fate.mak b/tests/fate.mak index 0e3331178b..a349e5cf23 100644 --- a/tests/fate.mak +++ b/tests/fate.mak @@ -35,7 +35,7 @@ fate-bink-demux-video: CMD = framecrc -i $(SAMPLES)/bink/hol2br.bik FATE_TESTS += fate-caf fate-caf: CMD = crc -i $(SAMPLES)/caf/caf-pcm16.caf FATE_TESTS += fate-cdgraphics -fate-cdgraphics: CMD = framecrc -t 1 -i $(SAMPLES)/cdgraphics/BrotherJohn.cdg -pix_fmt rgb24 +fate-cdgraphics: CMD = framecrc -i $(SAMPLES)/cdgraphics/BrotherJohn.cdg -pix_fmt rgb24 -t 1 FATE_TESTS += fate-cljr fate-cljr: CMD = framecrc -i $(SAMPLES)/cljr/testcljr-partial.avi FATE_TESTS += fate-corepng @@ -129,7 +129,7 @@ fate-id-cin-video: CMD = framecrc -i $(SAMPLES)/idcin/idlog-2MB.cin -pix_fmt rg FATE_TESTS += fate-idroq-video-dpcm fate-idroq-video-dpcm: CMD = framecrc -i $(SAMPLES)/idroq/idlogo.roq FATE_TESTS += fate-idroq-video-encode -fate-idroq-video-encode: CMD = md5 -t 0.2 -f image2 -vcodec pgmyuv -i $(SAMPLES)/ffmpeg-synthetic/vsynth1/%02d.pgm -sws_flags +bitexact -vf pad=512:512:80:112 -f RoQ +fate-idroq-video-encode: CMD = md5 -f image2 -vcodec pgmyuv -i $(SAMPLES)/ffmpeg-synthetic/vsynth1/%02d.pgm -sws_flags +bitexact -vf pad=512:512:80:112 -f RoQ -t 0.2 FATE_TESTS += fate-iff-byterun1 fate-iff-byterun1: CMD = framecrc -i $(SAMPLES)/iff/ASH.LBM -pix_fmt rgb24 FATE_TESTS += fate-iff-fibonacci diff --git a/tests/fate2.mak b/tests/fate2.mak index a743f0cd59..6a01412eb3 100644 --- a/tests/fate2.mak +++ b/tests/fate2.mak @@ -125,7 +125,7 @@ fate-atrac3-3: CMP = oneoff fate-atrac3-3: REF = $(SAMPLES)/atrac3/mc_sich_at3_132_small.pcm FATE_TESTS += fate-gsm -fate-gsm: CMD = framecrc -t 10 -i $(SAMPLES)/gsm/sample-gsm-8000.mov +fate-gsm: CMD = framecrc -i $(SAMPLES)/gsm/sample-gsm-8000.mov -t 10 FATE_TESTS += fate-gsm-ms fate-gsm-ms: CMD = framecrc -i $(SAMPLES)/gsm/ciao.wav diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh index 1d7f640124..303e7bd1ac 100755 --- a/tests/lavf-regression.sh +++ b/tests/lavf-regression.sh @@ -227,8 +227,8 @@ conversions="yuv420p yuv422p yuv444p yuyv422 yuv410p yuv411p yuvj420p \ monob yuv440p yuvj440p" for pix_fmt in $conversions ; do file=${outfile}${pix_fmt}.yuv - run_avconv $DEC_OPTS -r 1 -t 1 -f image2 -vcodec pgmyuv -i $raw_src \ - $ENC_OPTS -f rawvideo -s 352x288 -pix_fmt $pix_fmt $target_path/$raw_dst + run_avconv $DEC_OPTS -r 1 -f image2 -vcodec pgmyuv -i $raw_src \ + $ENC_OPTS -f rawvideo -t 1 -s 352x288 -pix_fmt $pix_fmt $target_path/$raw_dst do_avconv $file $DEC_OPTS -f rawvideo -s 352x288 -pix_fmt $pix_fmt -i $target_path/$raw_dst \ $ENC_OPTS -f rawvideo -s 352x288 -pix_fmt yuv444p done -- cgit v1.2.3