diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
| commit | f7813a5324be39d13ab536c245d15dfc602a7849 (patch) | |
| tree | fad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/cmdutils.c | |
| parent | b7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff) | |
basic type mechanism working
Diffstat (limited to 'ffmpeg/cmdutils.c')
| -rw-r--r-- | ffmpeg/cmdutils.c | 250 |
1 files changed, 201 insertions, 49 deletions
diff --git a/ffmpeg/cmdutils.c b/ffmpeg/cmdutils.c index ca1c965..fc4b424 100644 --- a/ffmpeg/cmdutils.c +++ b/ffmpeg/cmdutils.c @@ -20,6 +20,7 @@ */ #include <string.h> +#include <stdint.h> #include <stdlib.h> #include <errno.h> #include <math.h> @@ -47,8 +48,9 @@ #include "libavutil/eval.h" #include "libavutil/dict.h" #include "libavutil/opt.h" +#include "libavutil/cpu.h" +#include "libavutil/ffversion.h" #include "cmdutils.h" -#include "version.h" #if CONFIG_NETWORK #include "libavformat/network.h" #endif @@ -63,8 +65,6 @@ struct SwsContext *sws_opts; AVDictionary *swr_opts; AVDictionary *format_opts, *codec_opts, *resample_opts; -const int this_year = 2013; - static FILE *report_file; void init_opts(void) @@ -107,6 +107,21 @@ static void log_callback_report(void *ptr, int level, const char *fmt, va_list v fflush(report_file); } +static void (*program_exit)(int ret); + +void register_exit(void (*cb)(int ret)) +{ + program_exit = cb; +} + +void exit_program(int ret) +{ + if (program_exit) + program_exit(ret); + + exit(ret); +} + double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max) { @@ -124,7 +139,7 @@ double parse_number_or_die(const char *context, const char *numstr, int type, else return d; av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); - exit(1); + exit_program(1); return 0; } @@ -135,7 +150,7 @@ int64_t parse_time_or_die(const char *context, const char *timestr, if (av_parse_time(&us, timestr, is_duration) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n", is_duration ? "duration" : "date", context, timestr); - exit(1); + exit_program(1); } return us; } @@ -194,7 +209,10 @@ static const OptionDef *find_option(const OptionDef *po, const char *name) return po; } -#if HAVE_COMMANDLINETOARGVW +/* _WIN32 means using the windows libc - cygwin doesn't define that + * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while + * it doesn't provide the actual command line via GetCommandLineW(). */ +#if HAVE_COMMANDLINETOARGVW && defined(_WIN32) #include <windows.h> #include <shellapi.h> /* Will be leaked on exit */ @@ -300,7 +318,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, } } if (po->flags & OPT_EXIT) - exit(0); + exit_program(0); return 0; } @@ -360,7 +378,7 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options opt++; if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) - exit(1); + exit_program(1); optindex += ret; } else { if (parse_arg_function) @@ -475,6 +493,15 @@ void parse_loglevel(int argc, char **argv, const OptionDef *options) } } +static const AVOption *opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags) +{ + const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags); + if(o && !o->flags) + return NULL; + return o; +} + #define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0 int opt_default(void *optctx, const char *opt, const char *arg) { @@ -495,14 +522,14 @@ int opt_default(void *optctx, const char *opt, const char *arg) p = opt + strlen(opt); av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); - if ((o = av_opt_find(&cc, opt_stripped, NULL, 0, + if ((o = opt_find(&cc, opt_stripped, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && - (o = av_opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { + (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { av_dict_set(&codec_opts, opt, arg, FLAGS); consumed = 1; } - if ((o = av_opt_find(&fc, opt, NULL, 0, + if ((o = opt_find(&fc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { av_dict_set(&format_opts, opt, arg, FLAGS); if (consumed) @@ -511,7 +538,7 @@ int opt_default(void *optctx, const char *opt, const char *arg) } #if CONFIG_SWSCALE sc = sws_get_class(); - if (!consumed && av_opt_find(&sc, opt, NULL, 0, + if (!consumed && opt_find(&sc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { // XXX we only support sws_flags, not arbitrary sws options int ret = av_opt_set(sws_opts, opt, arg, 0); @@ -524,7 +551,7 @@ int opt_default(void *optctx, const char *opt, const char *arg) #endif #if CONFIG_SWRESAMPLE swr_class = swr_get_class(); - if (!consumed && (o=av_opt_find(&swr_class, opt, NULL, 0, + if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { struct SwrContext *swr = swr_alloc(); int ret = av_opt_set(swr, opt, arg, 0); @@ -538,7 +565,7 @@ int opt_default(void *optctx, const char *opt, const char *arg) } #endif #if CONFIG_AVRESAMPLE - if ((o=av_opt_find(&rc, opt, NULL, 0, + if ((o=opt_find(&rc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { av_dict_set(&resample_opts, opt, arg, FLAGS); consumed = 1; @@ -547,8 +574,6 @@ int opt_default(void *optctx, const char *opt, const char *arg) if (consumed) return 0; - av_log(NULL, AV_LOG_ERROR, "Could not find option '%s' in any of the FFmpeg subsystems " - "(codec, format, scaler, resampler contexts)\n", opt); return AVERROR_OPTION_NOT_FOUND; } @@ -635,7 +660,7 @@ static void init_parse_context(OptionParseContext *octx, octx->nb_groups = nb_groups; octx->groups = av_mallocz(sizeof(*octx->groups) * octx->nb_groups); if (!octx->groups) - exit(1); + exit_program(1); for (i = 0; i < octx->nb_groups; i++) octx->groups[i].group_def = &groups[i]; @@ -779,6 +804,18 @@ do { \ return 0; } +int opt_cpuflags(void *optctx, const char *opt, const char *arg) +{ + int ret; + unsigned flags = av_get_cpu_flags(); + + if ((ret = av_parse_cpu_caps(&flags, arg)) < 0) + return ret; + + av_force_cpu_flags(flags); + return 0; +} + int opt_loglevel(void *optctx, const char *opt, const char *arg) { const struct { const char *name; int level; } log_levels[] = { @@ -795,6 +832,13 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) int level; int i; + tail = strstr(arg, "repeat"); + av_log_set_flags(tail ? 0 : AV_LOG_SKIP_REPEATED); + if (tail == arg) + arg += 6 + (arg[6]=='+'); + if(tail && !*arg) + return 0; + for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) { if (!strcmp(log_levels[i].name, arg)) { av_log_set_level(log_levels[i].level); @@ -808,7 +852,7 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) "Possible levels are numbers or:\n", arg); for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); - exit(1); + exit_program(1); } av_log_set_level(level); return 0; @@ -901,7 +945,6 @@ static int init_report(const char *env) tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, filename.str); - av_log_set_level(FFMAX(av_log_get_level(), AV_LOG_VERBOSE)); av_bprint_finalize(&filename, NULL); return 0; } @@ -919,24 +962,12 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg) max = strtol(arg, &tail, 10); if (*tail) { av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg); - exit(1); + exit_program(1); } av_max_alloc(max); return 0; } -int opt_cpuflags(void *optctx, const char *opt, const char *arg) -{ - int ret; - unsigned flags = av_get_cpu_flags(); - - if ((ret = av_parse_cpu_caps(&flags, arg)) < 0) - return ret; - - av_force_cpu_flags(flags); - return 0; -} - int opt_timelimit(void *optctx, const char *opt, const char *arg) { #if HAVE_SETRLIMIT @@ -1015,7 +1046,7 @@ static void print_program_info(int flags, int level) av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name); if (flags & SHOW_COPYRIGHT) av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers", - program_birth_year, this_year); + program_birth_year, CONFIG_THIS_YEAR); av_log(NULL, level, "\n"); av_log(NULL, level, "%sbuilt on %s %s with %s\n", indent, __DATE__, __TIME__, CC_IDENT); @@ -1023,6 +1054,32 @@ static void print_program_info(int flags, int level) av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent); } +static void print_buildconf(int flags, int level) +{ + const char *indent = flags & INDENT ? " " : ""; + char str[] = { FFMPEG_CONFIGURATION }; + char *conflist, *remove_tilde, *splitconf; + + // Change all the ' --' strings to '~--' so that + // they can be identified as tokens. + while ((conflist = strstr(str, " --")) != NULL) { + strncpy(conflist, "~--", 3); + } + + // Compensate for the weirdness this would cause + // when passing 'pkg-config --static'. + while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) { + strncpy(remove_tilde, "pkg-config ", 11); + } + + splitconf = strtok(str, "~"); + av_log(NULL, level, "\n%sconfiguration:\n", indent); + while (splitconf != NULL) { + av_log(NULL, level, "%s%s%s\n", indent, indent, splitconf); + splitconf = strtok(NULL, "~"); + } +} + void show_banner(int argc, char **argv, const OptionDef *options) { int idx = locate_option(argc, argv, options, "version"); @@ -1043,6 +1100,14 @@ int show_version(void *optctx, const char *opt, const char *arg) return 0; } +int show_buildconf(void *optctx, const char *opt, const char *arg) +{ + av_log_set_callback(log_callback_help); + print_buildconf (INDENT|0, AV_LOG_INFO); + + return 0; +} + int show_license(void *optctx, const char *opt, const char *arg) { #if CONFIG_NONFREE @@ -1185,7 +1250,8 @@ static void print_codec(const AVCodec *c) printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name, c->long_name ? c->long_name : ""); - if (c->type == AVMEDIA_TYPE_VIDEO) { + if (c->type == AVMEDIA_TYPE_VIDEO || + c->type == AVMEDIA_TYPE_AUDIO) { printf(" Threading capabilities: "); switch (c->capabilities & (CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS)) { @@ -1266,7 +1332,7 @@ static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) nb_codecs++; if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) { av_log(NULL, AV_LOG_ERROR, "Out of memory\n"); - exit(1); + exit_program(1); } desc = NULL; while ((desc = avcodec_descriptor_next(desc))) @@ -1419,36 +1485,62 @@ int show_protocols(void *optctx, const char *opt, const char *arg) int show_filters(void *optctx, const char *opt, const char *arg) { - AVFilter av_unused(**filter) = NULL; + const AVFilter av_unused(*filter) = NULL; char descr[64], *descr_cur; int i, j; const AVFilterPad *pad; - printf("Filters:\n"); + printf("Filters:\n" + " T.. = Timeline support\n" + " .S. = Slice threading\n" + " ..C = Commmand support\n" + " A = Audio input/output\n" + " V = Video input/output\n" + " N = Dynamic number and/or type of input/output\n" + " | = Source or sink filter\n"); #if CONFIG_AVFILTER - while ((filter = av_filter_next(filter)) && *filter) { + while ((filter = avfilter_next(filter))) { descr_cur = descr; for (i = 0; i < 2; i++) { if (i) { *(descr_cur++) = '-'; *(descr_cur++) = '>'; } - pad = i ? (*filter)->outputs : (*filter)->inputs; + pad = i ? filter->outputs : filter->inputs; for (j = 0; pad && pad[j].name; j++) { if (descr_cur >= descr + sizeof(descr) - 4) break; *(descr_cur++) = get_media_type_char(pad[j].type); } if (!j) - *(descr_cur++) = '|'; + *(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) || + ( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|'; } *descr_cur = 0; - printf("%-16s %-10s %s\n", (*filter)->name, descr, (*filter)->description); + printf(" %c%c%c %-16s %-10s %s\n", + filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.', + filter->flags & AVFILTER_FLAG_SLICE_THREADS ? 'S' : '.', + filter->process_command ? 'C' : '.', + filter->name, descr, filter->description); } #endif return 0; } +int show_colors(void *optctx, const char *opt, const char *arg) +{ + const char *name; + const uint8_t *rgb; + int i; + + printf("%-32s #RRGGBB\n", "name"); + + for (i = 0; name = av_get_known_color_name(i, &rgb); i++) + printf("%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]); + + return 0; +} + int show_pix_fmts(void *optctx, const char *opt, const char *arg) { const AVPixFmtDescriptor *pix_desc = NULL; @@ -1470,11 +1562,11 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(pix_desc); printf("%c%c%c%c%c %-16s %d %2d\n", - sws_isSupportedInput (pix_fmt) ? 'I' : '.', - sws_isSupportedOutput(pix_fmt) ? 'O' : '.', - pix_desc->flags & PIX_FMT_HWACCEL ? 'H' : '.', - pix_desc->flags & PIX_FMT_PAL ? 'P' : '.', - pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.', + sws_isSupportedInput (pix_fmt) ? 'I' : '.', + sws_isSupportedOutput(pix_fmt) ? 'O' : '.', + pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL ? 'H' : '.', + pix_desc->flags & AV_PIX_FMT_FLAG_PAL ? 'P' : '.', + pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.', pix_desc->name, pix_desc->nb_components, av_get_bits_per_pixel(pix_desc)); @@ -1606,6 +1698,62 @@ static void show_help_muxer(const char *name) show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM); } +#if CONFIG_AVFILTER +static void show_help_filter(const char *name) +{ +#if CONFIG_AVFILTER + const AVFilter *f = avfilter_get_by_name(name); + int i, count; + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No filter name specified.\n"); + return; + } else if (!f) { + av_log(NULL, AV_LOG_ERROR, "Unknown filter '%s'.\n", name); + return; + } + + printf("Filter %s\n", f->name); + if (f->description) + printf(" %s\n", f->description); + + if (f->flags & AVFILTER_FLAG_SLICE_THREADS) + printf(" slice threading supported\n"); + + printf(" Inputs:\n"); + count = avfilter_pad_count(f->inputs); + for (i = 0; i < count; i++) { + printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i), + media_type_string(avfilter_pad_get_type(f->inputs, i))); + } + if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS) + printf(" dynamic (depending on the options)\n"); + else if (!count) + printf(" none (source filter)\n"); + + printf(" Outputs:\n"); + count = avfilter_pad_count(f->outputs); + for (i = 0; i < count; i++) { + printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i), + media_type_string(avfilter_pad_get_type(f->outputs, i))); + } + if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS) + printf(" dynamic (depending on the options)\n"); + else if (!count) + printf(" none (sink filter)\n"); + + if (f->priv_class) + show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | + AV_OPT_FLAG_AUDIO_PARAM); + if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) + printf("This filter has support for timeline through the 'enable' option.\n"); +#else + av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; " + "can not to satisfy request\n"); +#endif +} +#endif + int show_help(void *optctx, const char *opt, const char *arg) { char *topic, *par; @@ -1626,6 +1774,10 @@ int show_help(void *optctx, const char *opt, const char *arg) show_help_demuxer(par); } else if (!strcmp(topic, "muxer")) { show_help_muxer(par); +#if CONFIG_AVFILTER + } else if (!strcmp(topic, "filter")) { + show_help_filter(par); +#endif } else { show_help_default(topic, par); } @@ -1648,7 +1800,7 @@ int read_yesno(void) int cmdutils_read_file(const char *filename, char **bufptr, size_t *size) { int ret; - FILE *f = fopen(filename, "rb"); + FILE *f = av_fopen_utf8(filename, "rb"); if (!f) { av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, @@ -1825,13 +1977,13 @@ 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(1); + 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(1); + exit_program(1); } memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); *size = new_size; |
