Merge remote-tracking branch 'qatar/master'
* qatar/master: lavc: fix type for thread_type option avconv: move format to options context avconv: move limit_filesize to options context avconv: move start_time, recording_time and input_ts_offset to options context avconv: add a context for options. cmdutils: allow storing per-stream/chapter/.... options in a generic way cmdutils: split per-option code out of parse_options(). cmdutils: add support for caller-provided option context. cmdutils: declare only one pointer type in OptionDef cmdutils: move grow_array() from avconv to cmdutils. cmdutils: move exit_program() declaration to cmdutils from avconv http: Consider the stream as seekable if the reply contains Accept-Ranges: bytes nutenc: add namespace to the api facing functions Conflicts: avconv.c cmdutils.c cmdutils.h ffmpeg.c ffplay.c ffprobe.c ffserver.c libavformat/http.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
155
cmdutils.c
155
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;
|
||||
}
|
||||
@ -202,12 +203,80 @@ 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,
|
||||
int (* parse_arg_function)(const char *opt, const char *arg))
|
||||
|
||||
int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options)
|
||||
{
|
||||
const char *opt, *arg;
|
||||
int optindex, handleoptions=1;
|
||||
const OptionDef *po;
|
||||
int bool_val = 1;
|
||||
int *dstcount;
|
||||
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|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;
|
||||
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_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) {
|
||||
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;
|
||||
int optindex, handleoptions = 1, ret;
|
||||
|
||||
/* perform system-dependent conversions for arguments list */
|
||||
prepare_app_arguments(&argc, &argv);
|
||||
@ -218,60 +287,18 @@ void parse_options(int argc, char **argv, const OptionDef *options,
|
||||
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);
|
||||
exit(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);
|
||||
}
|
||||
}
|
||||
if (po->flags & OPT_STRING) {
|
||||
char *str;
|
||||
str = av_strdup(arg);
|
||||
*po->u.str_arg = str;
|
||||
} else if (po->flags & OPT_BOOL) {
|
||||
*po->u.int_arg = bool_val;
|
||||
} else if (po->flags & OPT_INT) {
|
||||
*po->u.int_arg = 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);
|
||||
} else if (po->flags & OPT_FLOAT) {
|
||||
*po->u.float_arg = 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 ? arg : "[null]", opt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(po->flags & OPT_EXIT)
|
||||
exit(0);
|
||||
|
||||
if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
|
||||
exit_program(1);
|
||||
optindex += ret;
|
||||
} else {
|
||||
if (parse_arg_function) {
|
||||
if (parse_arg_function(NULL, opt) < 0)
|
||||
exit(1);
|
||||
}
|
||||
if (parse_arg_function)
|
||||
parse_arg_function(optctx, opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,7 +365,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;
|
||||
@ -872,3 +899,21 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *cod
|
||||
return opts;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user