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