1/*
2 * Various utilities for command line tools
3 * Copyright (c) 2000-2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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/pixdesc.h"
39#include "libavcodec/opt.h"
40#include "cmdutils.h"
41#include "version.h"
42#if CONFIG_NETWORK
43#include "libavformat/network.h"
44#endif
45#if HAVE_SYS_RESOURCE_H
46#include <sys/resource.h>
47#endif
48
49const char **opt_names;
50static int opt_name_count;
51AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB];
52AVFormatContext *avformat_opts;
53struct SwsContext *sws_opts;
54
55const int this_year = 2010;
56
57double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max)
58{
59    char *tail;
60    const char *error;
61    double d = strtod(numstr, &tail);
62    if (*tail)
63        error= "Expected number for %s but found: %s\n";
64    else if (d < min || d > max)
65        error= "The value for %s was %s which is not within %f - %f\n";
66    else if(type == OPT_INT64 && (int64_t)d != d)
67        error= "Expected int64 for %s but found %s\n";
68    else
69        return d;
70    fprintf(stderr, error, context, numstr, min, max);
71    exit(1);
72}
73
74int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration)
75{
76    int64_t us = parse_date(timestr, is_duration);
77    if (us == INT64_MIN) {
78        fprintf(stderr, "Invalid %s specification for %s: %s\n",
79                is_duration ? "duration" : "date", context, timestr);
80        exit(1);
81    }
82    return us;
83}
84
85void show_help_options(const OptionDef *options, const char *msg, int mask, int value)
86{
87    const OptionDef *po;
88    int first;
89
90    first = 1;
91    for(po = options; po->name != NULL; po++) {
92        char buf[64];
93        if ((po->flags & mask) == value) {
94            if (first) {
95                printf("%s", msg);
96                first = 0;
97            }
98            av_strlcpy(buf, po->name, sizeof(buf));
99            if (po->flags & HAS_ARG) {
100                av_strlcat(buf, " ", sizeof(buf));
101                av_strlcat(buf, po->argname, sizeof(buf));
102            }
103            printf("-%-17s  %s\n", buf, po->help);
104        }
105    }
106}
107
108static const OptionDef* find_option(const OptionDef *po, const char *name){
109    while (po->name != NULL) {
110        if (!strcmp(name, po->name))
111            break;
112        po++;
113    }
114    return po;
115}
116
117void parse_options(int argc, char **argv, const OptionDef *options,
118                   void (* parse_arg_function)(const char*))
119{
120    const char *opt, *arg;
121    int optindex, handleoptions=1;
122    const OptionDef *po;
123
124    /* parse options */
125    optindex = 1;
126    while (optindex < argc) {
127        opt = argv[optindex++];
128
129        if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
130            int bool_val = 1;
131            if (opt[1] == '-' && opt[2] == '\0') {
132                handleoptions = 0;
133                continue;
134            }
135            opt++;
136            po= find_option(options, opt);
137            if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
138                /* handle 'no' bool option */
139                po = find_option(options, opt + 2);
140                if (!(po->name && (po->flags & OPT_BOOL)))
141                    goto unknown_opt;
142                bool_val = 0;
143            }
144            if (!po->name)
145                po= find_option(options, "default");
146            if (!po->name) {
147unknown_opt:
148                fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);
149                exit(1);
150            }
151            arg = NULL;
152            if (po->flags & HAS_ARG) {
153                arg = argv[optindex++];
154                if (!arg) {
155                    fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);
156                    exit(1);
157                }
158            }
159            if (po->flags & OPT_STRING) {
160                char *str;
161                str = av_strdup(arg);
162                *po->u.str_arg = str;
163            } else if (po->flags & OPT_BOOL) {
164                *po->u.int_arg = bool_val;
165            } else if (po->flags & OPT_INT) {
166                *po->u.int_arg = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
167            } else if (po->flags & OPT_INT64) {
168                *po->u.int64_arg = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
169            } else if (po->flags & OPT_FLOAT) {
170                *po->u.float_arg = parse_number_or_die(opt, arg, OPT_FLOAT, -1.0/0.0, 1.0/0.0);
171            } else if (po->flags & OPT_FUNC2) {
172                if (po->u.func2_arg(opt, arg) < 0) {
173                    fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt);
174                    exit(1);
175                }
176            } else {
177                po->u.func_arg(arg);
178            }
179            if(po->flags & OPT_EXIT)
180                exit(0);
181        } else {
182            if (parse_arg_function)
183                parse_arg_function(opt);
184        }
185    }
186}
187
188int opt_default(const char *opt, const char *arg){
189    int type;
190    int ret= 0;
191    const AVOption *o= NULL;
192    int opt_types[]={AV_OPT_FLAG_VIDEO_PARAM, AV_OPT_FLAG_AUDIO_PARAM, 0, AV_OPT_FLAG_SUBTITLE_PARAM, 0};
193
194    for(type=0; type<AVMEDIA_TYPE_NB && ret>= 0; type++){
195        const AVOption *o2 = av_find_opt(avcodec_opts[0], opt, NULL, opt_types[type], opt_types[type]);
196        if(o2)
197            ret = av_set_string3(avcodec_opts[type], opt, arg, 1, &o);
198    }
199    if(!o)
200        ret = av_set_string3(avformat_opts, opt, arg, 1, &o);
201    if(!o && sws_opts)
202        ret = av_set_string3(sws_opts, opt, arg, 1, &o);
203    if(!o){
204        if(opt[0] == 'a')
205            ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_AUDIO], opt+1, arg, 1, &o);
206        else if(opt[0] == 'v')
207            ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_VIDEO], opt+1, arg, 1, &o);
208        else if(opt[0] == 's')
209            ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], opt+1, arg, 1, &o);
210    }
211    if (o && ret < 0) {
212        fprintf(stderr, "Invalid value '%s' for option '%s'\n", arg, opt);
213        exit(1);
214    }
215    if (!o) {
216        fprintf(stderr, "Unrecognized option '%s'\n", opt);
217        exit(1);
218    }
219
220//    av_log(NULL, AV_LOG_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avcodec_opts, opt, NULL), (int)av_get_int(avcodec_opts, opt, NULL));
221
222    //FIXME we should always use avcodec_opts, ... for storing options so there will not be any need to keep track of what i set over this
223    opt_names= av_realloc(opt_names, sizeof(void*)*(opt_name_count+1));
224    opt_names[opt_name_count++]= o->name;
225
226    if(avcodec_opts[0]->debug || avformat_opts->debug)
227        av_log_set_level(AV_LOG_DEBUG);
228    return 0;
229}
230
231int opt_loglevel(const char *opt, const char *arg)
232{
233    const struct { const char *name; int level; } log_levels[] = {
234        { "quiet"  , AV_LOG_QUIET   },
235        { "panic"  , AV_LOG_PANIC   },
236        { "fatal"  , AV_LOG_FATAL   },
237        { "error"  , AV_LOG_ERROR   },
238        { "warning", AV_LOG_WARNING },
239        { "info"   , AV_LOG_INFO    },
240        { "verbose", AV_LOG_VERBOSE },
241        { "debug"  , AV_LOG_DEBUG   },
242    };
243    char *tail;
244    int level;
245    int i;
246
247    for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) {
248        if (!strcmp(log_levels[i].name, arg)) {
249            av_log_set_level(log_levels[i].level);
250            return 0;
251        }
252    }
253
254    level = strtol(arg, &tail, 10);
255    if (*tail) {
256        fprintf(stderr, "Invalid loglevel \"%s\". "
257                        "Possible levels are numbers or:\n", arg);
258        for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
259            fprintf(stderr, "\"%s\"\n", log_levels[i].name);
260        exit(1);
261    }
262    av_log_set_level(level);
263    return 0;
264}
265
266int opt_timelimit(const char *opt, const char *arg)
267{
268#if HAVE_SETRLIMIT
269    int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
270    struct rlimit rl = { lim, lim + 1 };
271    if (setrlimit(RLIMIT_CPU, &rl))
272        perror("setrlimit");
273#else
274    fprintf(stderr, "Warning: -%s not implemented on this OS\n", opt);
275#endif
276    return 0;
277}
278
279void set_context_opts(void *ctx, void *opts_ctx, int flags)
280{
281    int i;
282    for(i=0; i<opt_name_count; i++){
283        char buf[256];
284        const AVOption *opt;
285        const char *str= av_get_string(opts_ctx, opt_names[i], &opt, buf, sizeof(buf));
286        /* if an option with name opt_names[i] is present in opts_ctx then str is non-NULL */
287        if(str && ((opt->flags & flags) == flags))
288            av_set_string3(ctx, opt_names[i], str, 1, NULL);
289    }
290}
291
292void print_error(const char *filename, int err)
293{
294    char errbuf[128];
295    const char *errbuf_ptr = errbuf;
296
297    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
298        errbuf_ptr = strerror(AVUNERROR(err));
299    fprintf(stderr, "%s: %s\n", filename, errbuf_ptr);
300}
301
302#define PRINT_LIB_VERSION(outstream,libname,LIBNAME,indent)             \
303    if (CONFIG_##LIBNAME) {                                             \
304        unsigned int version = libname##_version();                     \
305        fprintf(outstream, "%slib%-10s %2d.%2d.%2d / %2d.%2d.%2d\n",    \
306                indent? "  " : "", #libname,                            \
307                LIB##LIBNAME##_VERSION_MAJOR,                           \
308                LIB##LIBNAME##_VERSION_MINOR,                           \
309                LIB##LIBNAME##_VERSION_MICRO,                           \
310                version >> 16, version >> 8 & 0xff, version & 0xff);    \
311    }
312
313static void print_all_lib_versions(FILE* outstream, int indent)
314{
315    PRINT_LIB_VERSION(outstream, avutil,   AVUTIL,   indent);
316    PRINT_LIB_VERSION(outstream, avcodec,  AVCODEC,  indent);
317    PRINT_LIB_VERSION(outstream, avformat, AVFORMAT, indent);
318    PRINT_LIB_VERSION(outstream, avdevice, AVDEVICE, indent);
319    PRINT_LIB_VERSION(outstream, avfilter, AVFILTER, indent);
320    PRINT_LIB_VERSION(outstream, swscale,  SWSCALE,  indent);
321    PRINT_LIB_VERSION(outstream, postproc, POSTPROC, indent);
322}
323
324static void maybe_print_config(const char *lib, const char *cfg)
325{
326    static int warned_cfg;
327
328    if (strcmp(FFMPEG_CONFIGURATION, cfg)) {
329        if (!warned_cfg) {
330            fprintf(stderr, "  WARNING: library configuration mismatch\n");
331            warned_cfg = 1;
332        }
333        fprintf(stderr, "  %-11s configuration: %s\n", lib, cfg);
334    }
335}
336
337#define PRINT_LIB_CONFIG(lib, tag, cfg) do {    \
338        if (CONFIG_##lib)                       \
339            maybe_print_config(tag, cfg);       \
340    } while (0)
341
342void show_banner(void)
343{
344    fprintf(stderr, "%s version " FFMPEG_VERSION ", Copyright (c) %d-%d the FFmpeg developers\n",
345            program_name, program_birth_year, this_year);
346    fprintf(stderr, "  built on %s %s with %s %s\n",
347            __DATE__, __TIME__, CC_TYPE, CC_VERSION);
348    fprintf(stderr, "  configuration: " FFMPEG_CONFIGURATION "\n");
349    PRINT_LIB_CONFIG(AVUTIL,   "libavutil",   avutil_configuration());
350    PRINT_LIB_CONFIG(AVCODEC,  "libavcodec",  avcodec_configuration());
351    PRINT_LIB_CONFIG(AVFORMAT, "libavformat", avformat_configuration());
352    PRINT_LIB_CONFIG(AVDEVICE, "libavdevice", avdevice_configuration());
353    PRINT_LIB_CONFIG(AVFILTER, "libavfilter", avfilter_configuration());
354    PRINT_LIB_CONFIG(SWSCALE,  "libswscale",  swscale_configuration());
355    PRINT_LIB_CONFIG(POSTPROC, "libpostproc", postproc_configuration());
356    print_all_lib_versions(stderr, 1);
357}
358
359void show_version(void) {
360    printf("%s " FFMPEG_VERSION "\n", program_name);
361    print_all_lib_versions(stdout, 0);
362}
363
364void show_license(void)
365{
366    printf(
367#if CONFIG_NONFREE
368    "This version of %s has nonfree parts compiled in.\n"
369    "Therefore it is not legally redistributable.\n",
370    program_name
371#elif CONFIG_GPLV3
372    "%s is free software; you can redistribute it and/or modify\n"
373    "it under the terms of the GNU General Public License as published by\n"
374    "the Free Software Foundation; either version 3 of the License, or\n"
375    "(at your option) any later version.\n"
376    "\n"
377    "%s is distributed in the hope that it will be useful,\n"
378    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
379    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
380    "GNU General Public License for more details.\n"
381    "\n"
382    "You should have received a copy of the GNU General Public License\n"
383    "along with %s.  If not, see <http://www.gnu.org/licenses/>.\n",
384    program_name, program_name, program_name
385#elif CONFIG_GPL
386    "%s is free software; you can redistribute it and/or modify\n"
387    "it under the terms of the GNU General Public License as published by\n"
388    "the Free Software Foundation; either version 2 of the License, or\n"
389    "(at your option) any later version.\n"
390    "\n"
391    "%s is distributed in the hope that it will be useful,\n"
392    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
393    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
394    "GNU General Public License for more details.\n"
395    "\n"
396    "You should have received a copy of the GNU General Public License\n"
397    "along with %s; if not, write to the Free Software\n"
398    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
399    program_name, program_name, program_name
400#elif CONFIG_LGPLV3
401    "%s is free software; you can redistribute it and/or modify\n"
402    "it under the terms of the GNU Lesser General Public License as published by\n"
403    "the Free Software Foundation; either version 3 of the License, or\n"
404    "(at your option) any later version.\n"
405    "\n"
406    "%s is distributed in the hope that it will be useful,\n"
407    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
408    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
409    "GNU Lesser General Public License for more details.\n"
410    "\n"
411    "You should have received a copy of the GNU Lesser General Public License\n"
412    "along with %s.  If not, see <http://www.gnu.org/licenses/>.\n",
413    program_name, program_name, program_name
414#else
415    "%s is free software; you can redistribute it and/or\n"
416    "modify it under the terms of the GNU Lesser General Public\n"
417    "License as published by the Free Software Foundation; either\n"
418    "version 2.1 of the License, or (at your option) any later version.\n"
419    "\n"
420    "%s is distributed in the hope that it will be useful,\n"
421    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
422    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
423    "Lesser General Public License for more details.\n"
424    "\n"
425    "You should have received a copy of the GNU Lesser General Public\n"
426    "License along with %s; if not, write to the Free Software\n"
427    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
428    program_name, program_name, program_name
429#endif
430    );
431}
432
433void list_fmts(void (*get_fmt_string)(char *buf, int buf_size, int fmt), int nb_fmts)
434{
435    int i;
436    char fmt_str[128];
437    for (i=-1; i < nb_fmts; i++) {
438        get_fmt_string (fmt_str, sizeof(fmt_str), i);
439        fprintf(stdout, "%s\n", fmt_str);
440    }
441}
442
443void show_formats(void)
444{
445    AVInputFormat *ifmt=NULL;
446    AVOutputFormat *ofmt=NULL;
447    const char *last_name;
448
449    printf(
450        "File formats:\n"
451        " D. = Demuxing supported\n"
452        " .E = Muxing supported\n"
453        " --\n");
454    last_name= "000";
455    for(;;){
456        int decode=0;
457        int encode=0;
458        const char *name=NULL;
459        const char *long_name=NULL;
460
461        while((ofmt= av_oformat_next(ofmt))) {
462            if((name == NULL || strcmp(ofmt->name, name)<0) &&
463                strcmp(ofmt->name, last_name)>0){
464                name= ofmt->name;
465                long_name= ofmt->long_name;
466                encode=1;
467            }
468        }
469        while((ifmt= av_iformat_next(ifmt))) {
470            if((name == NULL || strcmp(ifmt->name, name)<0) &&
471                strcmp(ifmt->name, last_name)>0){
472                name= ifmt->name;
473                long_name= ifmt->long_name;
474                encode=0;
475            }
476            if(name && strcmp(ifmt->name, name)==0)
477                decode=1;
478        }
479        if(name==NULL)
480            break;
481        last_name= name;
482
483        printf(
484            " %s%s %-15s %s\n",
485            decode ? "D":" ",
486            encode ? "E":" ",
487            name,
488            long_name ? long_name:" ");
489    }
490}
491
492void show_codecs(void)
493{
494    AVCodec *p=NULL, *p2;
495    const char *last_name;
496    printf(
497        "Codecs:\n"
498        " D..... = Decoding supported\n"
499        " .E.... = Encoding supported\n"
500        " ..V... = Video codec\n"
501        " ..A... = Audio codec\n"
502        " ..S... = Subtitle codec\n"
503        " ...S.. = Supports draw_horiz_band\n"
504        " ....D. = Supports direct rendering method 1\n"
505        " .....T = Supports weird frame truncation\n"
506        " ------\n");
507    last_name= "000";
508    for(;;){
509        int decode=0;
510        int encode=0;
511        int cap=0;
512        const char *type_str;
513
514        p2=NULL;
515        while((p= av_codec_next(p))) {
516            if((p2==NULL || strcmp(p->name, p2->name)<0) &&
517                strcmp(p->name, last_name)>0){
518                p2= p;
519                decode= encode= cap=0;
520            }
521            if(p2 && strcmp(p->name, p2->name)==0){
522                if(p->decode) decode=1;
523                if(p->encode) encode=1;
524                cap |= p->capabilities;
525            }
526        }
527        if(p2==NULL)
528            break;
529        last_name= p2->name;
530
531        switch(p2->type) {
532        case AVMEDIA_TYPE_VIDEO:
533            type_str = "V";
534            break;
535        case AVMEDIA_TYPE_AUDIO:
536            type_str = "A";
537            break;
538        case AVMEDIA_TYPE_SUBTITLE:
539            type_str = "S";
540            break;
541        default:
542            type_str = "?";
543            break;
544        }
545        printf(
546            " %s%s%s%s%s%s %-15s %s",
547            decode ? "D": (/*p2->decoder ? "d":*/" "),
548            encode ? "E":" ",
549            type_str,
550            cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ",
551            cap & CODEC_CAP_DR1 ? "D":" ",
552            cap & CODEC_CAP_TRUNCATED ? "T":" ",
553            p2->name,
554            p2->long_name ? p2->long_name : "");
555       /* if(p2->decoder && decode==0)
556            printf(" use %s for decoding", p2->decoder->name);*/
557        printf("\n");
558    }
559    printf("\n");
560    printf(
561"Note, the names of encoders and decoders do not always match, so there are\n"
562"several cases where the above table shows encoder only or decoder only entries\n"
563"even though both encoding and decoding are supported. For example, the h263\n"
564"decoder corresponds to the h263 and h263p encoders, for file formats it is even\n"
565"worse.\n");
566}
567
568void show_bsfs(void)
569{
570    AVBitStreamFilter *bsf=NULL;
571
572    printf("Bitstream filters:\n");
573    while((bsf = av_bitstream_filter_next(bsf)))
574        printf("%s\n", bsf->name);
575    printf("\n");
576}
577
578void show_protocols(void)
579{
580    URLProtocol *up=NULL;
581
582    printf("Supported file protocols:\n");
583    while((up = av_protocol_next(up)))
584        printf("%s\n", up->name);
585}
586
587void show_filters(void)
588{
589    AVFilter av_unused(**filter) = NULL;
590
591    printf("Filters:\n");
592#if CONFIG_AVFILTER
593    while ((filter = av_filter_next(filter)) && *filter)
594        printf("%-16s %s\n", (*filter)->name, (*filter)->description);
595#endif
596}
597
598void show_pix_fmts(void)
599{
600    enum PixelFormat pix_fmt;
601
602    printf(
603        "Pixel formats:\n"
604        "I.... = Supported Input  format for conversion\n"
605        ".O... = Supported Output format for conversion\n"
606        "..H.. = Hardware accelerated format\n"
607        "...P. = Paletted format\n"
608        "....B = Bitstream format\n"
609        "FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL\n"
610        "-----\n");
611
612#if !CONFIG_SWSCALE
613#   define sws_isSupportedInput(x)  0
614#   define sws_isSupportedOutput(x) 0
615#endif
616
617    for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) {
618        const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt];
619        printf("%c%c%c%c%c %-16s       %d            %2d\n",
620               sws_isSupportedInput (pix_fmt)      ? 'I' : '.',
621               sws_isSupportedOutput(pix_fmt)      ? 'O' : '.',
622               pix_desc->flags & PIX_FMT_HWACCEL   ? 'H' : '.',
623               pix_desc->flags & PIX_FMT_PAL       ? 'P' : '.',
624               pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.',
625               pix_desc->name,
626               pix_desc->nb_components,
627               av_get_bits_per_pixel(pix_desc));
628    }
629}
630
631int read_yesno(void)
632{
633    int c = getchar();
634    int yesno = (toupper(c) == 'Y');
635
636    while (c != '\n' && c != EOF)
637        c = getchar();
638
639    return yesno;
640}
641
642int read_file(const char *filename, char **bufptr, size_t *size)
643{
644    FILE *f = fopen(filename, "rb");
645
646    if (!f) {
647        fprintf(stderr, "Cannot read file '%s': %s\n", filename, strerror(errno));
648        return AVERROR(errno);
649    }
650    fseek(f, 0, SEEK_END);
651    *size = ftell(f);
652    fseek(f, 0, SEEK_SET);
653    *bufptr = av_malloc(*size + 1);
654    if (!*bufptr) {
655        fprintf(stderr, "Could not allocate file buffer\n");
656        fclose(f);
657        return AVERROR(ENOMEM);
658    }
659    fread(*bufptr, 1, *size, f);
660    (*bufptr)[*size++] = '\0';
661
662    fclose(f);
663    return 0;
664}
665