cmdutils: add support for caller-provided option context.
[ffmpeg.git] / cmdutils.c
1 /*
2  * Various utilities for command line tools
3  * Copyright (c) 2000-2003 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <math.h>
26
27 /* Include only the enabled headers since some compilers (namely, Sun
28    Studio) will not omit unused inline functions and create undefined
29    references to libraries that are not being built. */
30
31 #include "config.h"
32 #include "libavformat/avformat.h"
33 #include "libavfilter/avfilter.h"
34 #include "libavdevice/avdevice.h"
35 #include "libswscale/swscale.h"
36 #include "libpostproc/postprocess.h"
37 #include "libavutil/avstring.h"
38 #include "libavutil/parseutils.h"
39 #include "libavutil/pixdesc.h"
40 #include "libavutil/eval.h"
41 #include "libavutil/dict.h"
42 #include "libavutil/opt.h"
43 #include "cmdutils.h"
44 #include "version.h"
45 #if CONFIG_NETWORK
46 #include "libavformat/network.h"
47 #endif
48 #if HAVE_SYS_RESOURCE_H
49 #include <sys/resource.h>
50 #endif
51
52 struct SwsContext *sws_opts;
53 AVDictionary *format_opts, *codec_opts;
54
55 static const int this_year = 2011;
56
57 void init_opts(void)
58 {
59 #if CONFIG_SWSCALE
60     sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC, NULL, NULL, NULL);
61 #endif
62 }
63
64 void uninit_opts(void)
65 {
66 #if CONFIG_SWSCALE
67     sws_freeContext(sws_opts);
68     sws_opts = NULL;
69 #endif
70     av_dict_free(&format_opts);
71     av_dict_free(&codec_opts);
72 }
73
74 void log_callback_help(void* ptr, int level, const char* fmt, va_list vl)
75 {
76     vfprintf(stdout, fmt, vl);
77 }
78
79 double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max)
80 {
81     char *tail;
82     const char *error;
83     double d = av_strtod(numstr, &tail);
84     if (*tail)
85         error= "Expected number for %s but found: %s\n";
86     else if (d < min || d > max)
87         error= "The value for %s was %s which is not within %f - %f\n";
88     else if(type == OPT_INT64 && (int64_t)d != d)
89         error= "Expected int64 for %s but found %s\n";
90     else if (type == OPT_INT && (int)d != d)
91         error= "Expected int for %s but found %s\n";
92     else
93         return d;
94     fprintf(stderr, error, context, numstr, min, max);
95     exit_program(1);
96     return 0;
97 }
98
99 int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration)
100 {
101     int64_t us;
102     if (av_parse_time(&us, timestr, is_duration) < 0) {
103         fprintf(stderr, "Invalid %s specification for %s: %s\n",
104                 is_duration ? "duration" : "date", context, timestr);
105         exit_program(1);
106     }
107     return us;
108 }
109
110 void show_help_options(const OptionDef *options, const char *msg, int mask, int value)
111 {
112     const OptionDef *po;
113     int first;
114
115     first = 1;
116     for(po = options; po->name != NULL; po++) {
117         char buf[64];
118         if ((po->flags & mask) == value) {
119             if (first) {
120                 printf("%s", msg);
121                 first = 0;
122             }
123             av_strlcpy(buf, po->name, sizeof(buf));
124             if (po->flags & HAS_ARG) {
125                 av_strlcat(buf, " ", sizeof(buf));
126                 av_strlcat(buf, po->argname, sizeof(buf));
127             }
128             printf("-%-17s  %s\n", buf, po->help);
129         }
130     }
131 }
132
133 static const OptionDef* find_option(const OptionDef *po, const char *name){
134     const char *p = strchr(name, ':');
135     int len = p ? p - name : strlen(name);
136
137     while (po->name != NULL) {
138         if (!strncmp(name, po->name, len) && strlen(po->name) == len)
139             break;
140         po++;
141     }
142     return po;
143 }
144
145 #if defined(_WIN32) && !defined(__MINGW32CE__)
146 #include <windows.h>
147 /* Will be leaked on exit */
148 static char** win32_argv_utf8 = NULL;
149 static int win32_argc = 0;
150
151 /**
152  * Prepare command line arguments for executable.
153  * For Windows - perform wide-char to UTF-8 conversion.
154  * Input arguments should be main() function arguments.
155  * @param argc_ptr Arguments number (including executable)
156  * @param argv_ptr Arguments list.
157  */
158 static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
159 {
160     char *argstr_flat;
161     wchar_t **argv_w;
162     int i, buffsize = 0, offset = 0;
163
164     if (win32_argv_utf8) {
165         *argc_ptr = win32_argc;
166         *argv_ptr = win32_argv_utf8;
167         return;
168     }
169
170     win32_argc = 0;
171     argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
172     if (win32_argc <= 0 || !argv_w)
173         return;
174
175     /* determine the UTF-8 buffer size (including NULL-termination symbols) */
176     for (i = 0; i < win32_argc; i++)
177         buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
178                                         NULL, 0, NULL, NULL);
179
180     win32_argv_utf8 = av_mallocz(sizeof(char*) * (win32_argc + 1) + buffsize);
181     argstr_flat     = (char*)win32_argv_utf8 + sizeof(char*) * (win32_argc + 1);
182     if (win32_argv_utf8 == NULL) {
183         LocalFree(argv_w);
184         return;
185     }
186
187     for (i = 0; i < win32_argc; i++) {
188         win32_argv_utf8[i] = &argstr_flat[offset];
189         offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
190                                       &argstr_flat[offset],
191                                       buffsize - offset, NULL, NULL);
192     }
193     win32_argv_utf8[i] = NULL;
194     LocalFree(argv_w);
195
196     *argc_ptr = win32_argc;
197     *argv_ptr = win32_argv_utf8;
198 }
199 #else
200 static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
201 {
202     /* nothing to do */
203 }
204 #endif /* WIN32 && !__MINGW32CE__ */
205
206 void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
207                    void (* parse_arg_function)(void *, const char*))
208 {
209     const char *opt, *arg;
210     int optindex, handleoptions=1;
211     const OptionDef *po;
212
213     /* perform system-dependent conversions for arguments list */
214     prepare_app_arguments(&argc, &argv);
215
216     /* parse options */
217     optindex = 1;
218     while (optindex < argc) {
219         void *dst;
220         opt = argv[optindex++];
221
222         if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
223             int bool_val = 1;
224             if (opt[1] == '-' && opt[2] == '\0') {
225                 handleoptions = 0;
226                 continue;
227             }
228             opt++;
229             po= find_option(options, opt);
230             if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
231                 /* handle 'no' bool option */
232                 po = find_option(options, opt + 2);
233                 if (!(po->name && (po->flags & OPT_BOOL)))
234                     goto unknown_opt;
235                 bool_val = 0;
236             }
237             if (!po->name)
238                 po= find_option(options, "default");
239             if (!po->name) {
240 unknown_opt:
241                 fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);
242                 exit_program(1);
243             }
244             arg = NULL;
245             if (po->flags & HAS_ARG) {
246                 arg = argv[optindex++];
247                 if (!arg) {
248                     fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);
249                     exit_program(1);
250                 }
251             }
252             /* new-style options contain an offset into optctx, old-style address of
253              * a global var*/
254             dst = po->flags & OPT_OFFSET ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr;
255             if (po->flags & OPT_STRING) {
256                 char *str;
257                 str = av_strdup(arg);
258                 *(char**)dst = str;
259             } else if (po->flags & OPT_BOOL) {
260                 *(int*)dst = bool_val;
261             } else if (po->flags & OPT_INT) {
262                 *(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
263             } else if (po->flags & OPT_INT64) {
264                 *(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
265             } else if (po->flags & OPT_FLOAT) {
266                 *(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
267             } else if (po->u.func_arg) {
268                 int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) :
269                                                   po->u.func_arg(opt, arg);
270                 if (ret < 0) {
271                     fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt);
272                     exit_program(1);
273                 }
274             }
275             if(po->flags & OPT_EXIT)
276                 exit_program(0);
277         } else {
278             if (parse_arg_function)
279                 parse_arg_function(optctx, opt);
280         }
281     }
282 }
283
284 #define FLAGS (o->type == FF_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
285 int opt_default(const char *opt, const char *arg)
286 {
287     const AVOption *o;
288     char opt_stripped[128];
289     const char *p;
290     const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(), *sc = sws_get_class();
291
292     if (!(p = strchr(opt, ':')))
293         p = opt + strlen(opt);
294     av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1));
295
296     if ((o = av_opt_find(&cc, opt_stripped, NULL, 0, AV_OPT_SEARCH_CHILDREN|AV_OPT_SEARCH_FAKE_OBJ)) ||
297          ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&
298           (o = av_opt_find(&cc, opt+1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ))))
299         av_dict_set(&codec_opts, opt, arg, FLAGS);
300     else if ((o = av_opt_find(&fc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)))
301         av_dict_set(&format_opts, opt, arg, FLAGS);
302     else if ((o = av_opt_find(&sc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
303         // XXX we only support sws_flags, not arbitrary sws options
304         int ret = av_set_string3(sws_opts, opt, arg, 1, NULL);
305         if (ret < 0) {
306             av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
307             return ret;
308         }
309     }
310
311     if (o)
312         return 0;
313     fprintf(stderr, "Unrecognized option '%s'\n", opt);
314     return AVERROR_OPTION_NOT_FOUND;
315 }
316
317 int opt_loglevel(const char *opt, const char *arg)
318 {
319     const struct { const char *name; int level; } log_levels[] = {
320         { "quiet"  , AV_LOG_QUIET   },
321         { "panic"  , AV_LOG_PANIC   },
322         { "fatal"  , AV_LOG_FATAL   },
323         { "error"  , AV_LOG_ERROR   },
324         { "warning", AV_LOG_WARNING },
325         { "info"   , AV_LOG_INFO    },
326         { "verbose", AV_LOG_VERBOSE },
327         { "debug"  , AV_LOG_DEBUG   },
328     };
329     char *tail;
330     int level;
331     int i;
332
333     for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) {
334         if (!strcmp(log_levels[i].name, arg)) {
335             av_log_set_level(log_levels[i].level);
336             return 0;
337         }
338     }
339
340     level = strtol(arg, &tail, 10);
341     if (*tail) {
342         fprintf(stderr, "Invalid loglevel \"%s\". "
343                         "Possible levels are numbers or:\n", arg);
344         for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
345             fprintf(stderr, "\"%s\"\n", log_levels[i].name);
346         exit_program(1);
347     }
348     av_log_set_level(level);
349     return 0;
350 }
351
352 int opt_timelimit(const char *opt, const char *arg)
353 {
354 #if HAVE_SETRLIMIT
355     int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
356     struct rlimit rl = { lim, lim + 1 };
357     if (setrlimit(RLIMIT_CPU, &rl))
358         perror("setrlimit");
359 #else
360     fprintf(stderr, "Warning: -%s not implemented on this OS\n", opt);
361 #endif
362     return 0;
363 }
364
365 void print_error(const char *filename, int err)
366 {
367     char errbuf[128];
368     const char *errbuf_ptr = errbuf;
369
370     if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
371         errbuf_ptr = strerror(AVUNERROR(err));
372     fprintf(stderr, "%s: %s\n", filename, errbuf_ptr);
373 }
374
375 static int warned_cfg = 0;
376
377 #define INDENT        1
378 #define SHOW_VERSION  2
379 #define SHOW_CONFIG   4
380
381 #define PRINT_LIB_INFO(outstream,libname,LIBNAME,flags)                 \
382     if (CONFIG_##LIBNAME) {                                             \
383         const char *indent = flags & INDENT? "  " : "";                 \
384         if (flags & SHOW_VERSION) {                                     \
385             unsigned int version = libname##_version();                 \
386             fprintf(outstream, "%slib%-9s %2d.%3d.%2d / %2d.%3d.%2d\n", \
387                     indent, #libname,                                   \
388                     LIB##LIBNAME##_VERSION_MAJOR,                       \
389                     LIB##LIBNAME##_VERSION_MINOR,                       \
390                     LIB##LIBNAME##_VERSION_MICRO,                       \
391                     version >> 16, version >> 8 & 0xff, version & 0xff); \
392         }                                                               \
393         if (flags & SHOW_CONFIG) {                                      \
394             const char *cfg = libname##_configuration();                \
395             if (strcmp(LIBAV_CONFIGURATION, cfg)) {                     \
396                 if (!warned_cfg) {                                      \
397                     fprintf(outstream,                                  \
398                             "%sWARNING: library configuration mismatch\n", \
399                             indent);                                    \
400                     warned_cfg = 1;                                     \
401                 }                                                       \
402                 fprintf(stderr, "%s%-11s configuration: %s\n",          \
403                         indent, #libname, cfg);                         \
404             }                                                           \
405         }                                                               \
406     }                                                                   \
407
408 static void print_all_libs_info(FILE* outstream, int flags)
409 {
410     PRINT_LIB_INFO(outstream, avutil,   AVUTIL,   flags);
411     PRINT_LIB_INFO(outstream, avcodec,  AVCODEC,  flags);
412     PRINT_LIB_INFO(outstream, avformat, AVFORMAT, flags);
413     PRINT_LIB_INFO(outstream, avdevice, AVDEVICE, flags);
414     PRINT_LIB_INFO(outstream, avfilter, AVFILTER, flags);
415     PRINT_LIB_INFO(outstream, swscale,  SWSCALE,  flags);
416     PRINT_LIB_INFO(outstream, postproc, POSTPROC, flags);
417 }
418
419 void show_banner(void)
420 {
421     fprintf(stderr, "%s version " LIBAV_VERSION ", Copyright (c) %d-%d the Libav developers\n",
422             program_name, program_birth_year, this_year);
423     fprintf(stderr, "  built on %s %s with %s %s\n",
424             __DATE__, __TIME__, CC_TYPE, CC_VERSION);
425     fprintf(stderr, "  configuration: " LIBAV_CONFIGURATION "\n");
426     print_all_libs_info(stderr, INDENT|SHOW_CONFIG);
427     print_all_libs_info(stderr, INDENT|SHOW_VERSION);
428 }
429
430 void show_version(void) {
431     printf("%s " LIBAV_VERSION "\n", program_name);
432     print_all_libs_info(stdout, SHOW_VERSION);
433 }
434
435 void show_license(void)
436 {
437     printf(
438 #if CONFIG_NONFREE
439     "This version of %s has nonfree parts compiled in.\n"
440     "Therefore it is not legally redistributable.\n",
441     program_name
442 #elif CONFIG_GPLV3
443     "%s is free software; you can redistribute it and/or modify\n"
444     "it under the terms of the GNU General Public License as published by\n"
445     "the Free Software Foundation; either version 3 of the License, or\n"
446     "(at your option) any later version.\n"
447     "\n"
448     "%s is distributed in the hope that it will be useful,\n"
449     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
450     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
451     "GNU General Public License for more details.\n"
452     "\n"
453     "You should have received a copy of the GNU General Public License\n"
454     "along with %s.  If not, see <http://www.gnu.org/licenses/>.\n",
455     program_name, program_name, program_name
456 #elif CONFIG_GPL
457     "%s is free software; you can redistribute it and/or modify\n"
458     "it under the terms of the GNU General Public License as published by\n"
459     "the Free Software Foundation; either version 2 of the License, or\n"
460     "(at your option) any later version.\n"
461     "\n"
462     "%s is distributed in the hope that it will be useful,\n"
463     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
464     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
465     "GNU General Public License for more details.\n"
466     "\n"
467     "You should have received a copy of the GNU General Public License\n"
468     "along with %s; if not, write to the Free Software\n"
469     "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
470     program_name, program_name, program_name
471 #elif CONFIG_LGPLV3
472     "%s is free software; you can redistribute it and/or modify\n"
473     "it under the terms of the GNU Lesser General Public License as published by\n"
474     "the Free Software Foundation; either version 3 of the License, or\n"
475     "(at your option) any later version.\n"
476     "\n"
477     "%s is distributed in the hope that it will be useful,\n"
478     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
479     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
480     "GNU Lesser General Public License for more details.\n"
481     "\n"
482     "You should have received a copy of the GNU Lesser General Public License\n"
483     "along with %s.  If not, see <http://www.gnu.org/licenses/>.\n",
484     program_name, program_name, program_name
485 #else
486     "%s is free software; you can redistribute it and/or\n"
487     "modify it under the terms of the GNU Lesser General Public\n"
488     "License as published by the Free Software Foundation; either\n"
489     "version 2.1 of the License, or (at your option) any later version.\n"
490     "\n"
491     "%s is distributed in the hope that it will be useful,\n"
492     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
493     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
494     "Lesser General Public License for more details.\n"
495     "\n"
496     "You should have received a copy of the GNU Lesser General Public\n"
497     "License along with %s; if not, write to the Free Software\n"
498     "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
499     program_name, program_name, program_name
500 #endif
501     );
502 }
503
504 void show_formats(void)
505 {
506     AVInputFormat *ifmt=NULL;
507     AVOutputFormat *ofmt=NULL;
508     const char *last_name;
509
510     printf(
511         "File formats:\n"
512         " D. = Demuxing supported\n"
513         " .E = Muxing supported\n"
514         " --\n");
515     last_name= "000";
516     for(;;){
517         int decode=0;
518         int encode=0;
519         const char *name=NULL;
520         const char *long_name=NULL;
521
522         while((ofmt= av_oformat_next(ofmt))) {
523             if((name == NULL || strcmp(ofmt->name, name)<0) &&
524                 strcmp(ofmt->name, last_name)>0){
525                 name= ofmt->name;
526                 long_name= ofmt->long_name;
527                 encode=1;
528             }
529         }
530         while((ifmt= av_iformat_next(ifmt))) {
531             if((name == NULL || strcmp(ifmt->name, name)<0) &&
532                 strcmp(ifmt->name, last_name)>0){
533                 name= ifmt->name;
534                 long_name= ifmt->long_name;
535                 encode=0;
536             }
537             if(name && strcmp(ifmt->name, name)==0)
538                 decode=1;
539         }
540         if(name==NULL)
541             break;
542         last_name= name;
543
544         printf(
545             " %s%s %-15s %s\n",
546             decode ? "D":" ",
547             encode ? "E":" ",
548             name,
549             long_name ? long_name:" ");
550     }
551 }
552
553 void show_codecs(void)
554 {
555     AVCodec *p=NULL, *p2;
556     const char *last_name;
557     printf(
558         "Codecs:\n"
559         " D..... = Decoding supported\n"
560         " .E.... = Encoding supported\n"
561         " ..V... = Video codec\n"
562         " ..A... = Audio codec\n"
563         " ..S... = Subtitle codec\n"
564         " ...S.. = Supports draw_horiz_band\n"
565         " ....D. = Supports direct rendering method 1\n"
566         " .....T = Supports weird frame truncation\n"
567         " ------\n");
568     last_name= "000";
569     for(;;){
570         int decode=0;
571         int encode=0;
572         int cap=0;
573         const char *type_str;
574
575         p2=NULL;
576         while((p= av_codec_next(p))) {
577             if((p2==NULL || strcmp(p->name, p2->name)<0) &&
578                 strcmp(p->name, last_name)>0){
579                 p2= p;
580                 decode= encode= cap=0;
581             }
582             if(p2 && strcmp(p->name, p2->name)==0){
583                 if(p->decode) decode=1;
584                 if(p->encode) encode=1;
585                 cap |= p->capabilities;
586             }
587         }
588         if(p2==NULL)
589             break;
590         last_name= p2->name;
591
592         switch(p2->type) {
593         case AVMEDIA_TYPE_VIDEO:
594             type_str = "V";
595             break;
596         case AVMEDIA_TYPE_AUDIO:
597             type_str = "A";
598             break;
599         case AVMEDIA_TYPE_SUBTITLE:
600             type_str = "S";
601             break;
602         default:
603             type_str = "?";
604             break;
605         }
606         printf(
607             " %s%s%s%s%s%s %-15s %s",
608             decode ? "D": (/*p2->decoder ? "d":*/" "),
609             encode ? "E":" ",
610             type_str,
611             cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ",
612             cap & CODEC_CAP_DR1 ? "D":" ",
613             cap & CODEC_CAP_TRUNCATED ? "T":" ",
614             p2->name,
615             p2->long_name ? p2->long_name : "");
616        /* if(p2->decoder && decode==0)
617             printf(" use %s for decoding", p2->decoder->name);*/
618         printf("\n");
619     }
620     printf("\n");
621     printf(
622 "Note, the names of encoders and decoders do not always match, so there are\n"
623 "several cases where the above table shows encoder only or decoder only entries\n"
624 "even though both encoding and decoding are supported. For example, the h263\n"
625 "decoder corresponds to the h263 and h263p encoders, for file formats it is even\n"
626 "worse.\n");
627 }
628
629 void show_bsfs(void)
630 {
631     AVBitStreamFilter *bsf=NULL;
632
633     printf("Bitstream filters:\n");
634     while((bsf = av_bitstream_filter_next(bsf)))
635         printf("%s\n", bsf->name);
636     printf("\n");
637 }
638
639 void show_protocols(void)
640 {
641     void *opaque = NULL;
642     const char *name;
643
644     printf("Supported file protocols:\n"
645            "Input:\n");
646     while ((name = avio_enum_protocols(&opaque, 0)))
647         printf("%s\n", name);
648     printf("Output:\n");
649     while ((name = avio_enum_protocols(&opaque, 1)))
650         printf("%s\n", name);
651 }
652
653 void show_filters(void)
654 {
655     AVFilter av_unused(**filter) = NULL;
656
657     printf("Filters:\n");
658 #if CONFIG_AVFILTER
659     while ((filter = av_filter_next(filter)) && *filter)
660         printf("%-16s %s\n", (*filter)->name, (*filter)->description);
661 #endif
662 }
663
664 void show_pix_fmts(void)
665 {
666     enum PixelFormat pix_fmt;
667
668     printf(
669         "Pixel formats:\n"
670         "I.... = Supported Input  format for conversion\n"
671         ".O... = Supported Output format for conversion\n"
672         "..H.. = Hardware accelerated format\n"
673         "...P. = Paletted format\n"
674         "....B = Bitstream format\n"
675         "FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL\n"
676         "-----\n");
677
678 #if !CONFIG_SWSCALE
679 #   define sws_isSupportedInput(x)  0
680 #   define sws_isSupportedOutput(x) 0
681 #endif
682
683     for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) {
684         const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt];
685         printf("%c%c%c%c%c %-16s       %d            %2d\n",
686                sws_isSupportedInput (pix_fmt)      ? 'I' : '.',
687                sws_isSupportedOutput(pix_fmt)      ? 'O' : '.',
688                pix_desc->flags & PIX_FMT_HWACCEL   ? 'H' : '.',
689                pix_desc->flags & PIX_FMT_PAL       ? 'P' : '.',
690                pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.',
691                pix_desc->name,
692                pix_desc->nb_components,
693                av_get_bits_per_pixel(pix_desc));
694     }
695 }
696
697 int read_yesno(void)
698 {
699     int c = getchar();
700     int yesno = (toupper(c) == 'Y');
701
702     while (c != '\n' && c != EOF)
703         c = getchar();
704
705     return yesno;
706 }
707
708 int read_file(const char *filename, char **bufptr, size_t *size)
709 {
710     FILE *f = fopen(filename, "rb");
711
712     if (!f) {
713         fprintf(stderr, "Cannot read file '%s': %s\n", filename, strerror(errno));
714         return AVERROR(errno);
715     }
716     fseek(f, 0, SEEK_END);
717     *size = ftell(f);
718     fseek(f, 0, SEEK_SET);
719     *bufptr = av_malloc(*size + 1);
720     if (!*bufptr) {
721         fprintf(stderr, "Could not allocate file buffer\n");
722         fclose(f);
723         return AVERROR(ENOMEM);
724     }
725     fread(*bufptr, 1, *size, f);
726     (*bufptr)[*size++] = '\0';
727
728     fclose(f);
729     return 0;
730 }
731
732 void init_pts_correction(PtsCorrectionContext *ctx)
733 {
734     ctx->num_faulty_pts = ctx->num_faulty_dts = 0;
735     ctx->last_pts = ctx->last_dts = INT64_MIN;
736 }
737
738 int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts)
739 {
740     int64_t pts = AV_NOPTS_VALUE;
741
742     if (dts != AV_NOPTS_VALUE) {
743         ctx->num_faulty_dts += dts <= ctx->last_dts;
744         ctx->last_dts = dts;
745     }
746     if (reordered_pts != AV_NOPTS_VALUE) {
747         ctx->num_faulty_pts += reordered_pts <= ctx->last_pts;
748         ctx->last_pts = reordered_pts;
749     }
750     if ((ctx->num_faulty_pts<=ctx->num_faulty_dts || dts == AV_NOPTS_VALUE)
751        && reordered_pts != AV_NOPTS_VALUE)
752         pts = reordered_pts;
753     else
754         pts = dts;
755
756     return pts;
757 }
758
759 FILE *get_preset_file(char *filename, size_t filename_size,
760                       const char *preset_name, int is_path, const char *codec_name)
761 {
762     FILE *f = NULL;
763     int i;
764     const char *base[3]= { getenv("AVCONV_DATADIR"),
765                            getenv("HOME"),
766                            AVCONV_DATADIR,
767                          };
768
769     if (is_path) {
770         av_strlcpy(filename, preset_name, filename_size);
771         f = fopen(filename, "r");
772     } else {
773         for (i = 0; i < 3 && !f; i++) {
774             if (!base[i])
775                 continue;
776             snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], i != 1 ? "" : "/.avconv", preset_name);
777             f = fopen(filename, "r");
778             if (!f && codec_name) {
779                 snprintf(filename, filename_size,
780                          "%s%s/%s-%s.ffpreset", base[i],  i != 1 ? "" : "/.avconv", codec_name, preset_name);
781                 f = fopen(filename, "r");
782             }
783         }
784     }
785
786     return f;
787 }
788
789 int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
790 {
791     if (*spec <= '9' && *spec >= '0')                                        /* opt:index */
792         return strtol(spec, NULL, 0) == st->index;
793     else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd') { /* opt:[vasd] */
794         enum AVMediaType type;
795
796         switch (*spec++) {
797         case 'v': type = AVMEDIA_TYPE_VIDEO;    break;
798         case 'a': type = AVMEDIA_TYPE_AUDIO;    break;
799         case 's': type = AVMEDIA_TYPE_SUBTITLE; break;
800         case 'd': type = AVMEDIA_TYPE_DATA;     break;
801         }
802         if (type != st->codec->codec_type)
803             return 0;
804         if (*spec++ == ':') {                                   /* possibly followed by :index */
805             int i, index = strtol(spec, NULL, 0);
806             for (i = 0; i < s->nb_streams; i++)
807                 if (s->streams[i]->codec->codec_type == type && index-- == 0)
808                    return i == st->index;
809             return 0;
810         }
811         return 1;
812     } else if (!*spec) /* empty specifier, matches everything */
813         return 1;
814
815     av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
816     return AVERROR(EINVAL);
817 }
818
819 AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id, AVFormatContext *s, AVStream *st)
820 {
821     AVDictionary    *ret = NULL;
822     AVDictionaryEntry *t = NULL;
823     AVCodec       *codec = s->oformat ? avcodec_find_encoder(codec_id) : avcodec_find_decoder(codec_id);
824     int            flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM : AV_OPT_FLAG_DECODING_PARAM;
825     char          prefix = 0;
826     const AVClass    *cc = avcodec_get_class();
827
828     if (!codec)
829         return NULL;
830
831     switch (codec->type) {
832     case AVMEDIA_TYPE_VIDEO:    prefix = 'v'; flags |= AV_OPT_FLAG_VIDEO_PARAM;    break;
833     case AVMEDIA_TYPE_AUDIO:    prefix = 'a'; flags |= AV_OPT_FLAG_AUDIO_PARAM;    break;
834     case AVMEDIA_TYPE_SUBTITLE: prefix = 's'; flags |= AV_OPT_FLAG_SUBTITLE_PARAM; break;
835     }
836
837     while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) {
838         char *p = strchr(t->key, ':');
839
840         /* check stream specification in opt name */
841         if (p)
842             switch (check_stream_specifier(s, st, p + 1)) {
843             case  1: *p = 0; break;
844             case  0:         continue;
845             default:         return NULL;
846             }
847
848         if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
849             (codec && codec->priv_class && av_opt_find(&codec->priv_class, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ)))
850             av_dict_set(&ret, t->key, t->value, 0);
851         else if (t->key[0] == prefix && av_opt_find(&cc, t->key+1, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ))
852             av_dict_set(&ret, t->key+1, t->value, 0);
853
854         if (p)
855             *p = ':';
856     }
857     return ret;
858 }
859
860 AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts)
861 {
862     int i;
863     AVDictionary **opts;
864
865     if (!s->nb_streams)
866         return NULL;
867     opts = av_mallocz(s->nb_streams * sizeof(*opts));
868     if (!opts) {
869         av_log(NULL, AV_LOG_ERROR, "Could not alloc memory for stream options.\n");
870         return NULL;
871     }
872     for (i = 0; i < s->nb_streams; i++)
873         opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id, s, s->streams[i]);
874     return opts;
875 }
876
877 #if CONFIG_AVFILTER
878
879 static int ffsink_init(AVFilterContext *ctx, const char *args, void *opaque)
880 {
881     FFSinkContext *priv = ctx->priv;
882
883     if (!opaque)
884         return AVERROR(EINVAL);
885     *priv = *(FFSinkContext *)opaque;
886
887     return 0;
888 }
889
890 static void null_end_frame(AVFilterLink *inlink) { }
891
892 static int ffsink_query_formats(AVFilterContext *ctx)
893 {
894     FFSinkContext *priv = ctx->priv;
895     enum PixelFormat pix_fmts[] = { priv->pix_fmt, PIX_FMT_NONE };
896
897     avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
898     return 0;
899 }
900
901 AVFilter ffsink = {
902     .name      = "ffsink",
903     .priv_size = sizeof(FFSinkContext),
904     .init      = ffsink_init,
905
906     .query_formats = ffsink_query_formats,
907
908     .inputs    = (AVFilterPad[]) {{ .name          = "default",
909                                     .type          = AVMEDIA_TYPE_VIDEO,
910                                     .end_frame     = null_end_frame,
911                                     .min_perms     = AV_PERM_READ, },
912                                   { .name = NULL }},
913     .outputs   = (AVFilterPad[]) {{ .name = NULL }},
914 };
915
916 int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
917                              AVFilterBufferRef **picref_ptr, AVRational *tb)
918 {
919     int ret;
920     AVFilterBufferRef *picref;
921
922     if ((ret = avfilter_request_frame(ctx->inputs[0])) < 0)
923         return ret;
924     if (!(picref = ctx->inputs[0]->cur_buf))
925         return AVERROR(ENOENT);
926     *picref_ptr = picref;
927     ctx->inputs[0]->cur_buf = NULL;
928     *tb = ctx->inputs[0]->time_base;
929
930     memcpy(frame->data,     picref->data,     sizeof(frame->data));
931     memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize));
932     frame->interlaced_frame = picref->video->interlaced;
933     frame->top_field_first  = picref->video->top_field_first;
934     frame->key_frame        = picref->video->key_frame;
935     frame->pict_type        = picref->video->pict_type;
936
937     return 1;
938 }
939
940 void *grow_array(void *array, int elem_size, int *size, int new_size)
941 {
942     if (new_size >= INT_MAX / elem_size) {
943         av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
944         exit_program(1);
945     }
946     if (*size < new_size) {
947         uint8_t *tmp = av_realloc(array, new_size*elem_size);
948         if (!tmp) {
949             av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n");
950             exit_program(1);
951         }
952         memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
953         *size = new_size;
954         return tmp;
955     }
956     return array;
957 }
958
959 #endif /* CONFIG_AVFILTER */