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