cmdutils.c 71.3 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1 2 3 4
/*
 * Various utilities for command line tools
 * Copyright (c) 2000-2003 Fabrice Bellard
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
Fabrice Bellard's avatar
Fabrice Bellard committed
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
21

22
#include <string.h>
23
#include <stdint.h>
24 25
#include <stdlib.h>
#include <errno.h>
26
#include <math.h>
27

28 29 30 31
/* Include only the enabled headers since some compilers (namely, Sun
   Studio) will not omit unused inline functions and create undefined
   references to libraries that are not being built. */

32
#include "config.h"
33
#include "compat/va_copy.h"
34 35 36
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavdevice/avdevice.h"
37
#include "libavresample/avresample.h"
38
#include "libswscale/swscale.h"
39
#include "libswresample/swresample.h"
40
#include "libpostproc/postprocess.h"
41
#include "libavutil/avassert.h"
42
#include "libavutil/avstring.h"
43
#include "libavutil/bprint.h"
44
#include "libavutil/display.h"
45
#include "libavutil/mathematics.h"
46
#include "libavutil/imgutils.h"
47
#include "libavutil/libm.h"
48
#include "libavutil/parseutils.h"
49
#include "libavutil/pixdesc.h"
50
#include "libavutil/eval.h"
51
#include "libavutil/dict.h"
52
#include "libavutil/opt.h"
53
#include "libavutil/cpu.h"
54
#include "libavutil/ffversion.h"
55
#include "libavutil/version.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
56
#include "cmdutils.h"
Ramiro Polla's avatar
Ramiro Polla committed
57
#if CONFIG_NETWORK
58
#include "libavformat/network.h"
Ramiro Polla's avatar
Ramiro Polla committed
59
#endif
Måns Rullgård's avatar
Måns Rullgård committed
60
#if HAVE_SYS_RESOURCE_H
61
#include <sys/time.h>
Måns Rullgård's avatar
Måns Rullgård committed
62 63
#include <sys/resource.h>
#endif
64 65 66
#if HAVE_SETDLLDIRECTORY
#include <windows.h>
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
67

68 69
static int init_report(const char *env);

70
AVDictionary *sws_dict;
71
AVDictionary *swr_opts;
72
AVDictionary *format_opts, *codec_opts, *resample_opts;
73

74
static FILE *report_file;
75
static int report_file_level = AV_LOG_DEBUG;
76
int hide_banner = 0;
77

78 79
void init_opts(void)
{
80
    av_dict_set(&sws_dict, "flags", "bicubic", 0);
81 82 83 84
}

void uninit_opts(void)
{
85
    av_dict_free(&swr_opts);
86
    av_dict_free(&sws_dict);
87
    av_dict_free(&format_opts);
88
    av_dict_free(&codec_opts);
89
    av_dict_free(&resample_opts);
90 91
}

92
void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
93 94 95 96
{
    vfprintf(stdout, fmt, vl);
}

97 98 99 100 101 102 103 104 105 106
static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl)
{
    va_list vl2;
    char line[1024];
    static int print_prefix = 1;

    va_copy(vl2, vl);
    av_log_default_callback(ptr, level, fmt, vl);
    av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
    va_end(vl2);
107 108 109 110
    if (report_file_level >= level) {
        fputs(line, report_file);
        fflush(report_file);
    }
111 112
}

113 114
void init_dynload(void)
{
115
#if HAVE_SETDLLDIRECTORY
116 117 118 119 120 121
    /* Calling SetDllDirectory with the empty string (but not NULL) removes the
     * current working directory from the DLL search path as a security pre-caution. */
    SetDllDirectory("");
#endif
}

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
static void (*program_exit)(int ret);

void register_exit(void (*cb)(int ret))
{
    program_exit = cb;
}

void exit_program(int ret)
{
    if (program_exit)
        program_exit(ret);

    exit(ret);
}

137 138
double parse_number_or_die(const char *context, const char *numstr, int type,
                           double min, double max)
139 140 141
{
    char *tail;
    const char *error;
142
    double d = av_strtod(numstr, &tail);
143
    if (*tail)
144
        error = "Expected number for %s but found: %s\n";
145
    else if (d < min || d > max)
146 147 148
        error = "The value for %s was %s which is not within %f - %f\n";
    else if (type == OPT_INT64 && (int64_t)d != d)
        error = "Expected int64 for %s but found %s\n";
149
    else if (type == OPT_INT && (int)d != d)
150
        error = "Expected int for %s but found %s\n";
151 152
    else
        return d;
153
    av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
154
    exit_program(1);
155
    return 0;
156 157
}

158 159
int64_t parse_time_or_die(const char *context, const char *timestr,
                          int is_duration)
160
{
161 162
    int64_t us;
    if (av_parse_time(&us, timestr, is_duration) < 0) {
163 164
        av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n",
               is_duration ? "duration" : "date", context, timestr);
165
        exit_program(1);
166 167 168 169
    }
    return us;
}

170
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
171
                       int rej_flags, int alt_flags)
Fabrice Bellard's avatar
Fabrice Bellard committed
172 173
{
    const OptionDef *po;
174
    int first;
Fabrice Bellard's avatar
Fabrice Bellard committed
175

176
    first = 1;
177
    for (po = options; po->name; po++) {
178
        char buf[64];
179 180

        if (((po->flags & req_flags) != req_flags) ||
181
            (alt_flags && !(po->flags & alt_flags)) ||
182 183 184 185 186 187 188 189
            (po->flags & rej_flags))
            continue;

        if (first) {
            printf("%s\n", msg);
            first = 0;
        }
        av_strlcpy(buf, po->name, sizeof(buf));
190
        if (po->argname) {
191 192
            av_strlcat(buf, " ", sizeof(buf));
            av_strlcat(buf, po->argname, sizeof(buf));
Fabrice Bellard's avatar
Fabrice Bellard committed
193
        }
194
        printf("-%-17s  %s\n", buf, po->help);
Fabrice Bellard's avatar
Fabrice Bellard committed
195
    }
196
    printf("\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
197 198
}

199 200 201
void show_help_children(const AVClass *class, int flags)
{
    const AVClass *child = NULL;
202 203 204 205
    if (class->option) {
        av_opt_show2(&class, NULL, flags, 0);
        printf("\n");
    }
206 207 208 209 210

    while (child = av_opt_child_class_next(class, child))
        show_help_children(child, flags);
}

211 212
static const OptionDef *find_option(const OptionDef *po, const char *name)
{
213 214 215
    const char *p = strchr(name, ':');
    int len = p ? p - name : strlen(name);

216
    while (po->name) {
217
        if (!strncmp(name, po->name, len) && strlen(po->name) == len)
218 219 220 221 222 223
            break;
        po++;
    }
    return po;
}

224 225 226 227
/* _WIN32 means using the windows libc - cygwin doesn't define that
 * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while
 * it doesn't provide the actual command line via GetCommandLineW(). */
#if HAVE_COMMANDLINETOARGVW && defined(_WIN32)
228
#include <windows.h>
229
#include <shellapi.h>
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
/* Will be leaked on exit */
static char** win32_argv_utf8 = NULL;
static int win32_argc = 0;

/**
 * Prepare command line arguments for executable.
 * For Windows - perform wide-char to UTF-8 conversion.
 * Input arguments should be main() function arguments.
 * @param argc_ptr Arguments number (including executable)
 * @param argv_ptr Arguments list.
 */
static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
{
    char *argstr_flat;
    wchar_t **argv_w;
    int i, buffsize = 0, offset = 0;

    if (win32_argv_utf8) {
        *argc_ptr = win32_argc;
        *argv_ptr = win32_argv_utf8;
        return;
    }

    win32_argc = 0;
    argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
    if (win32_argc <= 0 || !argv_w)
        return;

    /* determine the UTF-8 buffer size (including NULL-termination symbols) */
    for (i = 0; i < win32_argc; i++)
        buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
                                        NULL, 0, NULL, NULL);

263 264
    win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize);
    argstr_flat     = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1);
265
    if (!win32_argv_utf8) {
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
        LocalFree(argv_w);
        return;
    }

    for (i = 0; i < win32_argc; i++) {
        win32_argv_utf8[i] = &argstr_flat[offset];
        offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
                                      &argstr_flat[offset],
                                      buffsize - offset, NULL, NULL);
    }
    win32_argv_utf8[i] = NULL;
    LocalFree(argv_w);

    *argc_ptr = win32_argc;
    *argv_ptr = win32_argv_utf8;
}
#else
static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
{
    /* nothing to do */
}
287
#endif /* HAVE_COMMANDLINETOARGVW */
288

289 290
static int write_option(void *optctx, const OptionDef *po, const char *opt,
                        const char *arg)
Fabrice Bellard's avatar
Fabrice Bellard committed
291
{
292 293
    /* new-style options contain an offset into optctx, old-style address of
     * a global var*/
294 295 296
    void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ?
                (uint8_t *)optctx + po->u.off : po->u.dst_ptr;
    int *dstcount;
297 298 299 300

    if (po->flags & OPT_SPEC) {
        SpecifierOpt **so = dst;
        char *p = strchr(opt, ':');
301
        char *str;
302

303
        dstcount = (int *)(so + 1);
304
        *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1);
305 306 307 308
        str = av_strdup(p ? p + 1 : "");
        if (!str)
            return AVERROR(ENOMEM);
        (*so)[*dstcount - 1].specifier = str;
309 310
        dst = &(*so)[*dstcount - 1].u;
    }
311 312 313 314

    if (po->flags & OPT_STRING) {
        char *str;
        str = av_strdup(arg);
315
        av_freep(dst);
316 317
        if (!str)
            return AVERROR(ENOMEM);
318
        *(char **)dst = str;
319
    } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) {
320
        *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
321
    } else if (po->flags & OPT_INT64) {
322
        *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
323
    } else if (po->flags & OPT_TIME) {
324
        *(int64_t *)dst = parse_time_or_die(opt, arg, 1);
325
    } else if (po->flags & OPT_FLOAT) {
326
        *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
327
    } else if (po->flags & OPT_DOUBLE) {
328
        *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY);
329
    } else if (po->u.func_arg) {
330
        int ret = po->u.func_arg(optctx, opt, arg);
331
        if (ret < 0) {
332
            av_log(NULL, AV_LOG_ERROR,
333 334
                   "Failed to set value '%s' for option '%s': %s\n",
                   arg, opt, av_err2str(ret));
335 336 337 338
            return ret;
        }
    }
    if (po->flags & OPT_EXIT)
339
        exit_program(0);
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373

    return 0;
}

int parse_option(void *optctx, const char *opt, const char *arg,
                 const OptionDef *options)
{
    const OptionDef *po;
    int ret;

    po = find_option(options, opt);
    if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
        /* handle 'no' bool option */
        po = find_option(options, opt + 2);
        if ((po->name && (po->flags & OPT_BOOL)))
            arg = "0";
    } else if (po->flags & OPT_BOOL)
        arg = "1";

    if (!po->name)
        po = find_option(options, "default");
    if (!po->name) {
        av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
        return AVERROR(EINVAL);
    }
    if (po->flags & HAS_ARG && !arg) {
        av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt);
        return AVERROR(EINVAL);
    }

    ret = write_option(optctx, po, opt, arg);
    if (ret < 0)
        return ret;

374 375 376
    return !!(po->flags & HAS_ARG);
}

377
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
378
                   void (*parse_arg_function)(void *, const char*))
Fabrice Bellard's avatar
Fabrice Bellard committed
379
{
380 381
    const char *opt;
    int optindex, handleoptions = 1, ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
382

383 384 385
    /* perform system-dependent conversions for arguments list */
    prepare_app_arguments(&argc, &argv);

Fabrice Bellard's avatar
Fabrice Bellard committed
386 387 388 389
    /* parse options */
    optindex = 1;
    while (optindex < argc) {
        opt = argv[optindex++];
390

391
        if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
Stefano Sabatini's avatar
Stefano Sabatini committed
392 393 394 395
            if (opt[1] == '-' && opt[2] == '\0') {
                handleoptions = 0;
                continue;
            }
396
            opt++;
397 398

            if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
399
                exit_program(1);
400
            optindex += ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
401
        } else {
402
            if (parse_arg_function)
403
                parse_arg_function(optctx, opt);
Fabrice Bellard's avatar
Fabrice Bellard committed
404 405 406 407
        }
    }
}

408 409 410 411 412 413 414 415 416 417
int parse_optgroup(void *optctx, OptionGroup *g)
{
    int i, ret;

    av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n",
           g->group_def->name, g->arg);

    for (i = 0; i < g->nb_opts; i++) {
        Option *o = &g->opts[i];

418 419 420 421 422 423 424 425 426 427
        if (g->group_def->flags &&
            !(g->group_def->flags & o->opt->flags)) {
            av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to "
                   "%s %s -- you are trying to apply an input option to an "
                   "output file or vice versa. Move this option before the "
                   "file it belongs to.\n", o->key, o->opt->help,
                   g->group_def->name, g->arg);
            return AVERROR(EINVAL);
        }

428 429 430 431 432 433 434 435 436 437 438 439 440
        av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n",
               o->key, o->opt->help, o->val);

        ret = write_option(optctx, o->opt, o->key, o->val);
        if (ret < 0)
            return ret;
    }

    av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n");

    return 0;
}

441 442
int locate_option(int argc, char **argv, const OptionDef *options,
                  const char *optname)
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
{
    const OptionDef *po;
    int i;

    for (i = 1; i < argc; i++) {
        const char *cur_opt = argv[i];

        if (*cur_opt++ != '-')
            continue;

        po = find_option(options, cur_opt);
        if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o')
            po = find_option(options, cur_opt + 2);

        if ((!po->name && !strcmp(cur_opt, optname)) ||
             (po->name && !strcmp(optname, po->name)))
            return i;

461
        if (!po->name || po->flags & HAS_ARG)
462 463 464 465 466
            i++;
    }
    return 0;
}

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
static void dump_argument(const char *a)
{
    const unsigned char *p;

    for (p = a; *p; p++)
        if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') ||
              *p == '_' || (*p >= 'a' && *p <= 'z')))
            break;
    if (!*p) {
        fputs(a, report_file);
        return;
    }
    fputc('"', report_file);
    for (p = a; *p; p++) {
        if (*p == '\\' || *p == '"' || *p == '$' || *p == '`')
            fprintf(report_file, "\\%c", *p);
        else if (*p < ' ' || *p > '~')
            fprintf(report_file, "\\x%02x", *p);
        else
            fputc(*p, report_file);
    }
    fputc('"', report_file);
}

491 492 493 494 495 496 497 498 499
static void check_options(const OptionDef *po)
{
    while (po->name) {
        if (po->flags & OPT_PERFILE)
            av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT));
        po++;
    }
}

500 501 502
void parse_loglevel(int argc, char **argv, const OptionDef *options)
{
    int idx = locate_option(argc, argv, options, "loglevel");
503
    const char *env;
504 505 506

    check_options(options);

507 508
    if (!idx)
        idx = locate_option(argc, argv, options, "v");
509
    if (idx && argv[idx + 1])
510
        opt_loglevel(NULL, "loglevel", argv[idx + 1]);
511
    idx = locate_option(argc, argv, options, "report");
512 513
    if ((env = getenv("FFREPORT")) || idx) {
        init_report(env);
514 515 516 517 518 519 520 521 522 523
        if (report_file) {
            int i;
            fprintf(report_file, "Command line:\n");
            for (i = 0; i < argc; i++) {
                dump_argument(argv[i]);
                fputc(i < argc - 1 ? ' ' : '\n', report_file);
            }
            fflush(report_file);
        }
    }
524 525 526
    idx = locate_option(argc, argv, options, "hide_banner");
    if (idx)
        hide_banner = 1;
527 528
}

529 530 531
static const AVOption *opt_find(void *obj, const char *name, const char *unit,
                            int opt_flags, int search_flags)
{
532
    const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags);
533 534 535 536 537
    if(o && !o->flags)
        return NULL;
    return o;
}

538
#define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0
539
int opt_default(void *optctx, const char *opt, const char *arg)
540
{
541
    const AVOption *o;
542
    int consumed = 0;
543 544
    char opt_stripped[128];
    const char *p;
545
    const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class();
546
#if CONFIG_AVRESAMPLE
547
    const AVClass *rc = avresample_get_class();
548
#endif
549 550 551 552 553 554
#if CONFIG_SWSCALE
    const AVClass *sc = sws_get_class();
#endif
#if CONFIG_SWRESAMPLE
    const AVClass *swr_class = swr_get_class();
#endif
555

556 557 558
    if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug"))
        av_log_set_level(AV_LOG_DEBUG);

559 560 561 562
    if (!(p = strchr(opt, ':')))
        p = opt + strlen(opt);
    av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1));

563
    if ((o = opt_find(&cc, opt_stripped, NULL, 0,
564 565
                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) ||
        ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&
566
         (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) {
567
        av_dict_set(&codec_opts, opt, arg, FLAGS);
568 569
        consumed = 1;
    }
570
    if ((o = opt_find(&fc, opt, NULL, 0,
571
                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
572
        av_dict_set(&format_opts, opt, arg, FLAGS);
573
        if (consumed)
574
            av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt);
575 576
        consumed = 1;
    }
577
#if CONFIG_SWSCALE
578 579 580 581 582
    if (!consumed && (o = opt_find(&sc, opt, NULL, 0,
                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
        struct SwsContext *sws = sws_alloc_context();
        int ret = av_opt_set(sws, opt, arg, 0);
        sws_freeContext(sws);
583 584 585 586 587 588
        if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") ||
            !strcmp(opt, "dstw") || !strcmp(opt, "dsth") ||
            !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) {
            av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n");
            return AVERROR(EINVAL);
        }
589 590 591 592
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
            return ret;
        }
593 594 595

        av_dict_set(&sws_dict, opt, arg, FLAGS);

596
        consumed = 1;
597
    }
598 599 600 601 602
#else
    if (!consumed && !strcmp(opt, "sws_flags")) {
        av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg);
        consumed = 1;
    }
603
#endif
604
#if CONFIG_SWRESAMPLE
605
    if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0,
606 607 608 609
                                    AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
        struct SwrContext *swr = swr_alloc();
        int ret = av_opt_set(swr, opt, arg, 0);
        swr_free(&swr);
610 611 612 613
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
            return ret;
        }
614
        av_dict_set(&swr_opts, opt, arg, FLAGS);
615
        consumed = 1;
616
    }
617
#endif
618
#if CONFIG_AVRESAMPLE
619
    if ((o=opt_find(&rc, opt, NULL, 0,
620
                       AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
621 622
        av_dict_set(&resample_opts, opt, arg, FLAGS);
        consumed = 1;
623
    }
624
#endif
625

626
    if (consumed)
627 628 629
        return 0;
    return AVERROR_OPTION_NOT_FOUND;
}
630

631 632 633 634 635
/*
 * Check whether given option is a group separator.
 *
 * @return index of the group definition that matched or -1 if none
 */
636 637
static int match_group_separator(const OptionGroupDef *groups, int nb_groups,
                                 const char *opt)
638
{
639
    int i;
640

641 642
    for (i = 0; i < nb_groups; i++) {
        const OptionGroupDef *p = &groups[i];
643
        if (p->sep && !strcmp(p->sep, opt))
644
            return i;
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
    }

    return -1;
}

/*
 * Finish parsing an option group.
 *
 * @param group_idx which group definition should this group belong to
 * @param arg argument of the group delimiting option
 */
static void finish_group(OptionParseContext *octx, int group_idx,
                         const char *arg)
{
    OptionGroupList *l = &octx->groups[group_idx];
    OptionGroup *g;

    GROW_ARRAY(l->groups, l->nb_groups);
    g = &l->groups[l->nb_groups - 1];

    *g             = octx->cur_group;
    g->arg         = arg;
    g->group_def   = l->group_def;
668
    g->sws_dict    = sws_dict;
669
    g->swr_opts    = swr_opts;
670 671
    g->codec_opts  = codec_opts;
    g->format_opts = format_opts;
672
    g->resample_opts = resample_opts;
673 674 675

    codec_opts  = NULL;
    format_opts = NULL;
676
    resample_opts = NULL;
677
    sws_dict    = NULL;
678
    swr_opts    = NULL;
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
    init_opts();

    memset(&octx->cur_group, 0, sizeof(octx->cur_group));
}

/*
 * Add an option instance to currently parsed group.
 */
static void add_opt(OptionParseContext *octx, const OptionDef *opt,
                    const char *key, const char *val)
{
    int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET));
    OptionGroup *g = global ? &octx->global_opts : &octx->cur_group;

    GROW_ARRAY(g->opts, g->nb_opts);
    g->opts[g->nb_opts - 1].opt = opt;
    g->opts[g->nb_opts - 1].key = key;
    g->opts[g->nb_opts - 1].val = val;
}

static void init_parse_context(OptionParseContext *octx,
700
                               const OptionGroupDef *groups, int nb_groups)
701 702 703 704 705 706
{
    static const OptionGroupDef global_group = { "global" };
    int i;

    memset(octx, 0, sizeof(*octx));

707
    octx->nb_groups = nb_groups;
708
    octx->groups    = av_mallocz_array(octx->nb_groups, sizeof(*octx->groups));
709
    if (!octx->groups)
710
        exit_program(1);
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731

    for (i = 0; i < octx->nb_groups; i++)
        octx->groups[i].group_def = &groups[i];

    octx->global_opts.group_def = &global_group;
    octx->global_opts.arg       = "";

    init_opts();
}

void uninit_parse_context(OptionParseContext *octx)
{
    int i, j;

    for (i = 0; i < octx->nb_groups; i++) {
        OptionGroupList *l = &octx->groups[i];

        for (j = 0; j < l->nb_groups; j++) {
            av_freep(&l->groups[j].opts);
            av_dict_free(&l->groups[j].codec_opts);
            av_dict_free(&l->groups[j].format_opts);
732
            av_dict_free(&l->groups[j].resample_opts);
733 734

            av_dict_free(&l->groups[j].sws_dict);
735
            av_dict_free(&l->groups[j].swr_opts);
736 737 738 739 740 741 742 743 744 745 746 747 748
        }
        av_freep(&l->groups);
    }
    av_freep(&octx->groups);

    av_freep(&octx->cur_group.opts);
    av_freep(&octx->global_opts.opts);

    uninit_opts();
}

int split_commandline(OptionParseContext *octx, int argc, char *argv[],
                      const OptionDef *options,
749
                      const OptionGroupDef *groups, int nb_groups)
750 751
{
    int optindex = 1;
752
    int dashdash = -2;
753 754 755 756

    /* perform system-dependent conversions for arguments list */
    prepare_app_arguments(&argc, &argv);

757
    init_parse_context(octx, groups, nb_groups);
758 759 760 761 762 763 764 765 766
    av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n");

    while (optindex < argc) {
        const char *opt = argv[optindex++], *arg;
        const OptionDef *po;
        int ret;

        av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt);

767 768 769 770
        if (opt[0] == '-' && opt[1] == '-' && !opt[2]) {
            dashdash = optindex;
            continue;
        }
771
        /* unnamed group separators, e.g. output filename */
772
        if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) {
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
            finish_group(octx, 0, opt);
            av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name);
            continue;
        }
        opt++;

#define GET_ARG(arg)                                                           \
do {                                                                           \
    arg = argv[optindex++];                                                    \
    if (!arg) {                                                                \
        av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\
        return AVERROR(EINVAL);                                                \
    }                                                                          \
} while (0)

        /* named group separators, e.g. -i */
789
        if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) {
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
            GET_ARG(arg);
            finish_group(octx, ret, arg);
            av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n",
                   groups[ret].name, arg);
            continue;
        }

        /* normal options */
        po = find_option(options, opt);
        if (po->name) {
            if (po->flags & OPT_EXIT) {
                /* optional argument, e.g. -h */
                arg = argv[optindex++];
            } else if (po->flags & HAS_ARG) {
                GET_ARG(arg);
            } else {
                arg = "1";
            }

            add_opt(octx, po, opt, arg);
            av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
                   "argument '%s'.\n", po->name, po->help, arg);
            continue;
        }

        /* AVOptions */
        if (argv[optindex]) {
            ret = opt_default(NULL, opt, argv[optindex]);
            if (ret >= 0) {
                av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with "
                       "argument '%s'.\n", opt, argv[optindex]);
                optindex++;
                continue;
            } else if (ret != AVERROR_OPTION_NOT_FOUND) {
                av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' "
                       "with argument '%s'.\n", opt, argv[optindex]);
                return ret;
            }
        }

        /* boolean -nofoo options */
        if (opt[0] == 'n' && opt[1] == 'o' &&
            (po = find_option(options, opt + 2)) &&
            po->name && po->flags & OPT_BOOL) {
            add_opt(octx, po, opt, "0");
            av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
                   "argument 0.\n", po->name, po->help);
            continue;
        }

        av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt);
        return AVERROR_OPTION_NOT_FOUND;
    }

844
    if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts)
845 846 847 848 849 850 851 852
        av_log(NULL, AV_LOG_WARNING, "Trailing options were found on the "
               "commandline.\n");

    av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n");

    return 0;
}

853 854
int opt_cpuflags(void *optctx, const char *opt, const char *arg)
{
855 856
    int ret;
    unsigned flags = av_get_cpu_flags();
857

858 859
    if ((ret = av_parse_cpu_caps(&flags, arg)) < 0)
        return ret;
860

861
    av_force_cpu_flags(flags);
862 863 864
    return 0;
}

865
int opt_loglevel(void *optctx, const char *opt, const char *arg)
866
{
867
    const struct { const char *name; int level; } log_levels[] = {
868 869 870 871 872 873 874 875
        { "quiet"  , AV_LOG_QUIET   },
        { "panic"  , AV_LOG_PANIC   },
        { "fatal"  , AV_LOG_FATAL   },
        { "error"  , AV_LOG_ERROR   },
        { "warning", AV_LOG_WARNING },
        { "info"   , AV_LOG_INFO    },
        { "verbose", AV_LOG_VERBOSE },
        { "debug"  , AV_LOG_DEBUG   },
876
        { "trace"  , AV_LOG_TRACE   },
877 878 879
    };
    char *tail;
    int level;
880
    int flags;
881 882
    int i;

883
    flags = av_log_get_flags();
884
    tail = strstr(arg, "repeat");
885 886 887 888 889 890
    if (tail)
        flags &= ~AV_LOG_SKIP_REPEATED;
    else
        flags |= AV_LOG_SKIP_REPEATED;

    av_log_set_flags(flags);
891 892 893 894 895
    if (tail == arg)
        arg += 6 + (arg[6]=='+');
    if(tail && !*arg)
        return 0;

896 897 898 899 900 901 902 903 904
    for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) {
        if (!strcmp(log_levels[i].name, arg)) {
            av_log_set_level(log_levels[i].level);
            return 0;
        }
    }

    level = strtol(arg, &tail, 10);
    if (*tail) {
905 906
        av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". "
               "Possible levels are numbers or:\n", arg);
907
        for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
908
            av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
909
        exit_program(1);
910 911 912 913 914
    }
    av_log_set_level(level);
    return 0;
}

915 916
static void expand_filename_template(AVBPrint *bp, const char *template,
                                     struct tm *tm)
917
{
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
    int c;

    while ((c = *(template++))) {
        if (c == '%') {
            if (!(c = *(template++)))
                break;
            switch (c) {
            case 'p':
                av_bprintf(bp, "%s", program_name);
                break;
            case 't':
                av_bprintf(bp, "%04d%02d%02d-%02d%02d%02d",
                           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                           tm->tm_hour, tm->tm_min, tm->tm_sec);
                break;
            case '%':
                av_bprint_chars(bp, c, 1);
                break;
            }
        } else {
            av_bprint_chars(bp, c, 1);
        }
    }
}

static int init_report(const char *env)
{
945
    char *filename_template = NULL;
946 947
    char *key, *val;
    int ret, count = 0;
948 949
    time_t now;
    struct tm *tm;
950
    AVBPrint filename;
951 952 953 954 955

    if (report_file) /* already opened */
        return 0;
    time(&now);
    tm = localtime(&now);
956 957 958 959 960 961 962 963 964

    while (env && *env) {
        if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) {
            if (count)
                av_log(NULL, AV_LOG_ERROR,
                       "Failed to parse FFREPORT environment variable: %s\n",
                       av_err2str(ret));
            break;
        }
965 966
        if (*env)
            env++;
967 968
        count++;
        if (!strcmp(key, "file")) {
969
            av_free(filename_template);
970 971
            filename_template = val;
            val = NULL;
972 973 974 975 976 977 978
        } else if (!strcmp(key, "level")) {
            char *tail;
            report_file_level = strtol(val, &tail, 10);
            if (*tail) {
                av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n");
                exit_program(1);
            }
979 980 981 982 983 984 985 986
        } else {
            av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key);
        }
        av_free(val);
        av_free(key);
    }

    av_bprint_init(&filename, 0, 1);
987 988 989
    expand_filename_template(&filename,
                             av_x_if_null(filename_template, "%p-%t.log"), tm);
    av_free(filename_template);
990 991 992 993 994 995
    if (!av_bprint_is_complete(&filename)) {
        av_log(NULL, AV_LOG_ERROR, "Out of memory building report file name\n");
        return AVERROR(ENOMEM);
    }

    report_file = fopen(filename.str, "w");
996
    if (!report_file) {
997
        int ret = AVERROR(errno);
998
        av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
999
               filename.str, strerror(errno));
1000
        return ret;
1001 1002 1003 1004 1005 1006 1007 1008
    }
    av_log_set_callback(log_callback_report);
    av_log(NULL, AV_LOG_INFO,
           "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n"
           "Report written to \"%s\"\n",
           program_name,
           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
           tm->tm_hour, tm->tm_min, tm->tm_sec,
1009 1010
           filename.str);
    av_bprint_finalize(&filename, NULL);
1011 1012 1013
    return 0;
}

1014 1015 1016 1017 1018
int opt_report(const char *opt)
{
    return init_report(NULL);
}

1019
int opt_max_alloc(void *optctx, const char *opt, const char *arg)
1020 1021 1022 1023 1024 1025 1026
{
    char *tail;
    size_t max;

    max = strtol(arg, &tail, 10);
    if (*tail) {
        av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg);
1027
        exit_program(1);
1028 1029 1030 1031 1032
    }
    av_max_alloc(max);
    return 0;
}

1033
int opt_timelimit(void *optctx, const char *opt, const char *arg)
Måns Rullgård's avatar
Måns Rullgård committed
1034
{
Måns Rullgård's avatar
Måns Rullgård committed
1035
#if HAVE_SETRLIMIT
Måns Rullgård's avatar
Måns Rullgård committed
1036 1037 1038 1039 1040
    int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
    struct rlimit rl = { lim, lim + 1 };
    if (setrlimit(RLIMIT_CPU, &rl))
        perror("setrlimit");
#else
1041
    av_log(NULL, AV_LOG_WARNING, "-%s not implemented on this OS\n", opt);
Måns Rullgård's avatar
Måns Rullgård committed
1042 1043 1044 1045
#endif
    return 0;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
1046 1047
void print_error(const char *filename, int err)
{
1048
    char errbuf[128];
1049
    const char *errbuf_ptr = errbuf;
1050

1051 1052
    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
        errbuf_ptr = strerror(AVUNERROR(err));
1053
    av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr);
Fabrice Bellard's avatar
Fabrice Bellard committed
1054
}
1055

1056 1057
static int warned_cfg = 0;

1058 1059
#define INDENT        1
#define SHOW_VERSION  2
1060
#define SHOW_CONFIG   4
1061
#define SHOW_COPYRIGHT 8
1062

1063
#define PRINT_LIB_INFO(libname, LIBNAME, flags, level)                  \
1064
    if (CONFIG_##LIBNAME) {                                             \
1065
        const char *indent = flags & INDENT? "  " : "";                 \
1066
        if (flags & SHOW_VERSION) {                                     \
Stefano Sabatini's avatar
Stefano Sabatini committed
1067
            unsigned int version = libname##_version();                 \
1068
            av_log(NULL, level,                                         \
1069
                   "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",            \
1070 1071 1072 1073
                   indent, #libname,                                    \
                   LIB##LIBNAME##_VERSION_MAJOR,                        \
                   LIB##LIBNAME##_VERSION_MINOR,                        \
                   LIB##LIBNAME##_VERSION_MICRO,                        \
1074 1075
                   AV_VERSION_MAJOR(version), AV_VERSION_MINOR(version),\
                   AV_VERSION_MICRO(version));                          \
1076
        }                                                               \
1077 1078
        if (flags & SHOW_CONFIG) {                                      \
            const char *cfg = libname##_configuration();                \
1079
            if (strcmp(FFMPEG_CONFIGURATION, cfg)) {                    \
1080
                if (!warned_cfg) {                                      \
1081
                    av_log(NULL, level,                                 \
1082
                            "%sWARNING: library configuration mismatch\n", \
1083
                            indent);                                    \
1084 1085
                    warned_cfg = 1;                                     \
                }                                                       \
1086
                av_log(NULL, level, "%s%-11s configuration: %s\n",      \
1087
                        indent, #libname, cfg);                         \
1088 1089
            }                                                           \
        }                                                               \
1090
    }                                                                   \
1091

1092
static void print_all_libs_info(int flags, int level)
1093
{
1094 1095 1096 1097 1098
    PRINT_LIB_INFO(avutil,     AVUTIL,     flags, level);
    PRINT_LIB_INFO(avcodec,    AVCODEC,    flags, level);
    PRINT_LIB_INFO(avformat,   AVFORMAT,   flags, level);
    PRINT_LIB_INFO(avdevice,   AVDEVICE,   flags, level);
    PRINT_LIB_INFO(avfilter,   AVFILTER,   flags, level);
1099
    PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
1100 1101 1102
    PRINT_LIB_INFO(swscale,    SWSCALE,    flags, level);
    PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level);
    PRINT_LIB_INFO(postproc,   POSTPROC,   flags, level);
1103 1104
}

1105 1106 1107 1108 1109 1110 1111
static void print_program_info(int flags, int level)
{
    const char *indent = flags & INDENT? "  " : "";

    av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name);
    if (flags & SHOW_COPYRIGHT)
        av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers",
1112
               program_birth_year, CONFIG_THIS_YEAR);
1113
    av_log(NULL, level, "\n");
1114
    av_log(NULL, level, "%sbuilt with %s\n", indent, CC_IDENT);
1115

1116 1117 1118
    av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent);
}

1119 1120
static void print_buildconf(int flags, int level)
{
1121
    const char *indent = flags & INDENT ? "  " : "";
1122 1123 1124 1125 1126
    char str[] = { FFMPEG_CONFIGURATION };
    char *conflist, *remove_tilde, *splitconf;

    // Change all the ' --' strings to '~--' so that
    // they can be identified as tokens.
1127
    while ((conflist = strstr(str, " --")) != NULL) {
1128 1129 1130 1131 1132
        strncpy(conflist, "~--", 3);
    }

    // Compensate for the weirdness this would cause
    // when passing 'pkg-config --static'.
1133 1134
    while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) {
        strncpy(remove_tilde, "pkg-config ", 11);
1135 1136 1137
    }

    splitconf = strtok(str, "~");
1138
    av_log(NULL, level, "\n%sconfiguration:\n", indent);
1139
    while (splitconf != NULL) {
1140 1141 1142 1143 1144
        av_log(NULL, level, "%s%s%s\n", indent, indent, splitconf);
        splitconf = strtok(NULL, "~");
    }
}

1145
void show_banner(int argc, char **argv, const OptionDef *options)
1146
{
1147
    int idx = locate_option(argc, argv, options, "version");
1148
    if (hide_banner || idx)
1149 1150
        return;

1151
    print_program_info (INDENT|SHOW_COPYRIGHT, AV_LOG_INFO);
1152 1153
    print_all_libs_info(INDENT|SHOW_CONFIG,  AV_LOG_INFO);
    print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_INFO);
1154 1155
}

1156
int show_version(void *optctx, const char *opt, const char *arg)
1157
{
1158
    av_log_set_callback(log_callback_help);
1159
    print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO);
1160
    print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
1161

1162
    return 0;
1163 1164
}

1165 1166 1167 1168 1169 1170 1171 1172
int show_buildconf(void *optctx, const char *opt, const char *arg)
{
    av_log_set_callback(log_callback_help);
    print_buildconf      (INDENT|0, AV_LOG_INFO);

    return 0;
}

1173
int show_license(void *optctx, const char *opt, const char *arg)
1174
{
1175
#if CONFIG_NONFREE
1176
    printf(
1177 1178
    "This version of %s has nonfree parts compiled in.\n"
    "Therefore it is not legally redistributable.\n",
1179
    program_name );
1180
#elif CONFIG_GPLV3
1181
    printf(
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
    "%s is free software; you can redistribute it and/or modify\n"
    "it under the terms of the GNU General Public License as published by\n"
    "the Free Software Foundation; either version 3 of the License, or\n"
    "(at your option) any later version.\n"
    "\n"
    "%s is distributed in the hope that it will be useful,\n"
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
    "GNU General Public License for more details.\n"
    "\n"
    "You should have received a copy of the GNU General Public License\n"
    "along with %s.  If not, see <http://www.gnu.org/licenses/>.\n",
1194
    program_name, program_name, program_name );
1195
#elif CONFIG_GPL
1196
    printf(
1197
    "%s is free software; you can redistribute it and/or modify\n"
1198 1199 1200 1201
    "it under the terms of the GNU General Public License as published by\n"
    "the Free Software Foundation; either version 2 of the License, or\n"
    "(at your option) any later version.\n"
    "\n"
1202
    "%s is distributed in the hope that it will be useful,\n"
1203 1204 1205 1206 1207
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
    "GNU General Public License for more details.\n"
    "\n"
    "You should have received a copy of the GNU General Public License\n"
1208 1209
    "along with %s; if not, write to the Free Software\n"
    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
1210
    program_name, program_name, program_name );
1211
#elif CONFIG_LGPLV3
1212
    printf(
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
    "%s is free software; you can redistribute it and/or modify\n"
    "it under the terms of the GNU Lesser General Public License as published by\n"
    "the Free Software Foundation; either version 3 of the License, or\n"
    "(at your option) any later version.\n"
    "\n"
    "%s is distributed in the hope that it will be useful,\n"
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
    "GNU Lesser General Public License for more details.\n"
    "\n"
    "You should have received a copy of the GNU Lesser General Public License\n"
    "along with %s.  If not, see <http://www.gnu.org/licenses/>.\n",
1225
    program_name, program_name, program_name );
1226
#else
1227
    printf(
1228
    "%s is free software; you can redistribute it and/or\n"
1229 1230 1231 1232
    "modify it under the terms of the GNU Lesser General Public\n"
    "License as published by the Free Software Foundation; either\n"
    "version 2.1 of the License, or (at your option) any later version.\n"
    "\n"
1233
    "%s is distributed in the hope that it will be useful,\n"
1234 1235 1236 1237 1238
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
    "Lesser General Public License for more details.\n"
    "\n"
    "You should have received a copy of the GNU Lesser General Public\n"
1239 1240
    "License along with %s; if not, write to the Free Software\n"
    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
1241
    program_name, program_name, program_name );
1242
#endif
1243

1244
    return 0;
1245
}
1246

1247 1248 1249 1250
static int is_device(const AVClass *avclass)
{
    if (!avclass)
        return 0;
1251
    return AV_IS_INPUT_DEVICE(avclass->category) || AV_IS_OUTPUT_DEVICE(avclass->category);
1252 1253 1254
}

static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only)
1255
{
1256 1257
    AVInputFormat *ifmt  = NULL;
    AVOutputFormat *ofmt = NULL;
1258
    const char *last_name;
1259
    int is_dev;
1260

1261
    printf("%s\n"
1262 1263
           " D. = Demuxing supported\n"
           " .E = Muxing supported\n"
1264
           " --\n", device_only ? "Devices:" : "File formats:");
1265 1266 1267 1268 1269 1270 1271 1272
    last_name = "000";
    for (;;) {
        int decode = 0;
        int encode = 0;
        const char *name      = NULL;
        const char *long_name = NULL;

        while ((ofmt = av_oformat_next(ofmt))) {
1273 1274 1275
            is_dev = is_device(ofmt->priv_class);
            if (!is_dev && device_only)
                continue;