cmdutils.c 45.4 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
 * This file is part of Libav.
6
 *
7
 * Libav 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
 * Libav 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 Libav; 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 23 24
#include <string.h>
#include <stdlib.h>
#include <errno.h>
25
#include <math.h>
26

27 28 29 30
/* 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. */

31
#include "config.h"
32 33 34
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavdevice/avdevice.h"
Justin Ruggles's avatar
Justin Ruggles committed
35
#include "libavresample/avresample.h"
36
#include "libswscale/swscale.h"
37
#include "libavutil/avassert.h"
38
#include "libavutil/avstring.h"
39
#include "libavutil/mathematics.h"
40
#include "libavutil/imgutils.h"
41
#include "libavutil/parseutils.h"
42
#include "libavutil/pixdesc.h"
43
#include "libavutil/eval.h"
Anton Khirnov's avatar
Anton Khirnov committed
44
#include "libavutil/dict.h"
45
#include "libavutil/opt.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
46
#include "cmdutils.h"
47
#include "version.h"
Ramiro Polla's avatar
Ramiro Polla committed
48
#if CONFIG_NETWORK
49
#include "libavformat/network.h"
Ramiro Polla's avatar
Ramiro Polla committed
50
#endif
Måns Rullgård's avatar
Måns Rullgård committed
51 52 53
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
54

55
struct SwsContext *sws_opts;
56
AVDictionary *format_opts, *codec_opts;
Michael Niedermayer's avatar
Michael Niedermayer committed
57

58
static const int this_year = 2012;
59

60 61
void init_opts(void)
{
62
#if CONFIG_SWSCALE
63 64
    sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC,
                              NULL, NULL, NULL);
65
#endif
66 67 68 69
}

void uninit_opts(void)
{
70
#if CONFIG_SWSCALE
71 72
    sws_freeContext(sws_opts);
    sws_opts = NULL;
73
#endif
Anton Khirnov's avatar
Anton Khirnov committed
74
    av_dict_free(&format_opts);
75
    av_dict_free(&codec_opts);
76 77
}

78
void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
79 80 81 82
{
    vfprintf(stdout, fmt, vl);
}

83 84
double parse_number_or_die(const char *context, const char *numstr, int type,
                           double min, double max)
Michael Niedermayer's avatar
Michael Niedermayer committed
85 86 87
{
    char *tail;
    const char *error;
88
    double d = av_strtod(numstr, &tail);
Michael Niedermayer's avatar
Michael Niedermayer committed
89
    if (*tail)
90
        error = "Expected number for %s but found: %s\n";
Michael Niedermayer's avatar
Michael Niedermayer committed
91
    else if (d < min || d > max)
92 93 94
        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";
95
    else if (type == OPT_INT && (int)d != d)
96
        error = "Expected int for %s but found %s\n";
Michael Niedermayer's avatar
Michael Niedermayer committed
97 98
    else
        return d;
99
    av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
100 101
    exit_program(1);
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
102 103
}

104 105
int64_t parse_time_or_die(const char *context, const char *timestr,
                          int is_duration)
106
{
107 108
    int64_t us;
    if (av_parse_time(&us, timestr, is_duration) < 0) {
109 110
        av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n",
               is_duration ? "duration" : "date", context, timestr);
111
        exit_program(1);
112 113 114 115
    }
    return us;
}

116
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
117
                       int rej_flags, int alt_flags)
Fabrice Bellard's avatar
Fabrice Bellard committed
118 119
{
    const OptionDef *po;
120
    int first;
Fabrice Bellard's avatar
Fabrice Bellard committed
121

122
    first = 1;
123
    for (po = options; po->name != NULL; po++) {
124
        char buf[64];
125 126

        if (((po->flags & req_flags) != req_flags) ||
127
            (alt_flags && !(po->flags & alt_flags)) ||
128 129 130 131 132 133 134 135
            (po->flags & rej_flags))
            continue;

        if (first) {
            printf("%s\n", msg);
            first = 0;
        }
        av_strlcpy(buf, po->name, sizeof(buf));
136
        if (po->argname) {
137 138
            av_strlcat(buf, " ", sizeof(buf));
            av_strlcat(buf, po->argname, sizeof(buf));
Fabrice Bellard's avatar
Fabrice Bellard committed
139
        }
140
        printf("-%-17s  %s\n", buf, po->help);
Fabrice Bellard's avatar
Fabrice Bellard committed
141
    }
142
    printf("\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
143 144
}

145 146 147 148 149 150 151 152 153 154
void show_help_children(const AVClass *class, int flags)
{
    const AVClass *child = NULL;
    av_opt_show2(&class, NULL, flags, 0);
    printf("\n");

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

155 156
static const OptionDef *find_option(const OptionDef *po, const char *name)
{
157 158 159
    const char *p = strchr(name, ':');
    int len = p ? p - name : strlen(name);

Michael Niedermayer's avatar
Michael Niedermayer committed
160
    while (po->name != NULL) {
161
        if (!strncmp(name, po->name, len) && strlen(po->name) == len)
Michael Niedermayer's avatar
Michael Niedermayer committed
162 163 164 165 166 167
            break;
        po++;
    }
    return po;
}

168
#if defined(_WIN32) && !defined(__MINGW32CE__)
169
#include <windows.h>
170
#include <shellapi.h>
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
/* 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);

204 205
    win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize);
    argstr_flat     = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1);
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
    if (win32_argv_utf8 == NULL) {
        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 */
}
#endif /* WIN32 && !__MINGW32CE__ */

230 231
int parse_option(void *optctx, const char *opt, const char *arg,
                 const OptionDef *options)
232 233 234
{
    const OptionDef *po;
    int bool_val = 1;
235
    int *dstcount;
236 237 238 239 240 241
    void *dst;

    po = find_option(options, opt);
    if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
        /* handle 'no' bool option */
        po = find_option(options, opt + 2);
242 243
        if ((po->name && (po->flags & OPT_BOOL)))
            bool_val = 0;
244 245 246 247 248 249 250 251 252 253 254 255 256 257
    }
    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);
    }

    /* new-style options contain an offset into optctx, old-style address of
     * a global var*/
258 259
    dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? (uint8_t *)optctx + po->u.off
                                              : po->u.dst_ptr;
260 261 262 263 264

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

265
        dstcount = (int *)(so + 1);
266 267 268 269
        *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1);
        (*so)[*dstcount - 1].specifier = av_strdup(p ? p + 1 : "");
        dst = &(*so)[*dstcount - 1].u;
    }
270 271 272 273

    if (po->flags & OPT_STRING) {
        char *str;
        str = av_strdup(arg);
274
        av_freep(dst);
275
        *(char **)dst = str;
276
    } else if (po->flags & OPT_BOOL) {
277
        *(int *)dst = bool_val;
278
    } else if (po->flags & OPT_INT) {
279
        *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
280
    } else if (po->flags & OPT_INT64) {
281
        *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
282
    } else if (po->flags & OPT_TIME) {
283
        *(int64_t *)dst = parse_time_or_die(opt, arg, 1);
284
    } else if (po->flags & OPT_FLOAT) {
285
        *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
286
    } else if (po->flags & OPT_DOUBLE) {
287
        *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY);
288
    } else if (po->u.func_arg) {
289
        int ret = po->u.func_arg(optctx, opt, arg);
290
        if (ret < 0) {
291 292
            av_log(NULL, AV_LOG_ERROR,
                   "Failed to set value '%s' for option '%s'\n", arg, opt);
293 294 295 296 297 298 299 300
            return ret;
        }
    }
    if (po->flags & OPT_EXIT)
        exit_program(0);
    return !!(po->flags & HAS_ARG);
}

301
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
302
                   void (*parse_arg_function)(void *, const char*))
Fabrice Bellard's avatar
Fabrice Bellard committed
303
{
304 305
    const char *opt;
    int optindex, handleoptions = 1, ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
306

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

Fabrice Bellard's avatar
Fabrice Bellard committed
310 311 312 313
    /* parse options */
    optindex = 1;
    while (optindex < argc) {
        opt = argv[optindex++];
314

315
        if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
Stefano Sabatini's avatar
Stefano Sabatini committed
316 317 318 319
            if (opt[1] == '-' && opt[2] == '\0') {
                handleoptions = 0;
                continue;
            }
320
            opt++;
321 322

            if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
323
                exit_program(1);
324
            optindex += ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
325
        } else {
326
            if (parse_arg_function)
327
                parse_arg_function(optctx, opt);
Fabrice Bellard's avatar
Fabrice Bellard committed
328 329 330 331
        }
    }
}

332 333
int locate_option(int argc, char **argv, const OptionDef *options,
                  const char *optname)
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
{
    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;

        if (!po || po->flags & HAS_ARG)
            i++;
    }
    return 0;
}

void parse_loglevel(int argc, char **argv, const OptionDef *options)
{
    int idx = locate_option(argc, argv, options, "loglevel");
361 362
    if (!idx)
        idx = locate_option(argc, argv, options, "v");
363
    if (idx && argv[idx + 1])
364
        opt_loglevel(NULL, "loglevel", argv[idx + 1]);
365 366
}

367
#define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
368
int opt_default(void *optctx, const char *opt, const char *arg)
Anton Khirnov's avatar
Anton Khirnov committed
369 370
{
    const AVOption *o;
371 372
    char opt_stripped[128];
    const char *p;
373
    const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(), *sc = sws_get_class();
374 375 376 377 378

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

379 380 381 382
    if ((o = av_opt_find(&cc, opt_stripped, NULL, 0,
                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) ||
        ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&
         (o = av_opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ))))
383
        av_dict_set(&codec_opts, opt, arg, FLAGS);
384 385
    else if ((o = av_opt_find(&fc, opt, NULL, 0,
                              AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)))
Anton Khirnov's avatar
Anton Khirnov committed
386
        av_dict_set(&format_opts, opt, arg, FLAGS);
387 388
    else if ((o = av_opt_find(&sc, opt, NULL, 0,
                              AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
Anton Khirnov's avatar
Anton Khirnov committed
389
        // XXX we only support sws_flags, not arbitrary sws options
390
        int ret = av_opt_set(sws_opts, opt, arg, 0);
Anton Khirnov's avatar
Anton Khirnov committed
391 392 393 394 395 396 397 398
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
            return ret;
        }
    }

    if (o)
        return 0;
399
    av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
Anton Khirnov's avatar
Anton Khirnov committed
400 401 402
    return AVERROR_OPTION_NOT_FOUND;
}

403
int opt_loglevel(void *optctx, const char *opt, const char *arg)
404
{
Carl Eugen Hoyos's avatar
Carl Eugen Hoyos committed
405
    const struct { const char *name; int level; } log_levels[] = {
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
        { "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   },
    };
    char *tail;
    int level;
    int i;

    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) {
428 429
        av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". "
               "Possible levels are numbers or:\n", arg);
430
        for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
431
            av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
432
        exit_program(1);
433 434 435 436 437
    }
    av_log_set_level(level);
    return 0;
}

438
int opt_timelimit(void *optctx, const char *opt, const char *arg)
Måns Rullgård's avatar
Måns Rullgård committed
439
{
Måns Rullgård's avatar
Måns Rullgård committed
440
#if HAVE_SETRLIMIT
Måns Rullgård's avatar
Måns Rullgård committed
441 442 443 444 445
    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
446
    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
447 448 449 450
#endif
    return 0;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
451 452
void print_error(const char *filename, int err)
{
453
    char errbuf[128];
454
    const char *errbuf_ptr = errbuf;
455

456 457
    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
        errbuf_ptr = strerror(AVUNERROR(err));
458
    av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr);
Fabrice Bellard's avatar
Fabrice Bellard committed
459
}
460

461 462
static int warned_cfg = 0;

463 464
#define INDENT        1
#define SHOW_VERSION  2
465
#define SHOW_CONFIG   4
466

467
#define PRINT_LIB_INFO(libname, LIBNAME, flags, level)                  \
468
    if (CONFIG_##LIBNAME) {                                             \
469
        const char *indent = flags & INDENT? "  " : "";                 \
470
        if (flags & SHOW_VERSION) {                                     \
Stefano Sabatini's avatar
Stefano Sabatini committed
471
            unsigned int version = libname##_version();                 \
Justin Ruggles's avatar
Justin Ruggles committed
472 473
            av_log(NULL, level,                                         \
                   "%slib%-10s %2d.%3d.%2d / %2d.%3d.%2d\n",            \
474 475 476 477 478
                   indent, #libname,                                    \
                   LIB##LIBNAME##_VERSION_MAJOR,                        \
                   LIB##LIBNAME##_VERSION_MINOR,                        \
                   LIB##LIBNAME##_VERSION_MICRO,                        \
                   version >> 16, version >> 8 & 0xff, version & 0xff); \
479
        }                                                               \
480 481
        if (flags & SHOW_CONFIG) {                                      \
            const char *cfg = libname##_configuration();                \
482
            if (strcmp(LIBAV_CONFIGURATION, cfg)) {                     \
483
                if (!warned_cfg) {                                      \
484
                    av_log(NULL, level,                                 \
485
                            "%sWARNING: library configuration mismatch\n", \
486
                            indent);                                    \
487 488
                    warned_cfg = 1;                                     \
                }                                                       \
489
                av_log(NULL, level, "%s%-11s configuration: %s\n",      \
490
                        indent, #libname, cfg);                         \
491 492
            }                                                           \
        }                                                               \
493
    }                                                                   \
494

495
static void print_all_libs_info(int flags, int level)
496
{
497 498 499 500 501
    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);
Justin Ruggles's avatar
Justin Ruggles committed
502
    PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
503
    PRINT_LIB_INFO(swscale,  SWSCALE,  flags, level);
504 505
}

506
void show_banner(void)
507
{
508 509
    av_log(NULL, AV_LOG_INFO,
           "%s version " LIBAV_VERSION ", Copyright (c) %d-%d the Libav developers\n",
510
           program_name, program_birth_year, this_year);
511 512
    av_log(NULL, AV_LOG_INFO, "  built on %s %s with %s\n",
           __DATE__, __TIME__, CC_IDENT);
513 514 515
    av_log(NULL, AV_LOG_VERBOSE, "  configuration: " LIBAV_CONFIGURATION "\n");
    print_all_libs_info(INDENT|SHOW_CONFIG,  AV_LOG_VERBOSE);
    print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_VERBOSE);
516 517
}

518
int show_version(void *optctx, const char *opt, const char *arg)
519
{
520
    av_log_set_callback(log_callback_help);
521
    printf("%s " LIBAV_VERSION "\n", program_name);
522
    print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
523 524

    return 0;
525 526
}

527
int show_license(void *optctx, const char *opt, const char *arg)
528
{
529
    printf(
530
#if CONFIG_NONFREE
531 532 533
    "This version of %s has nonfree parts compiled in.\n"
    "Therefore it is not legally redistributable.\n",
    program_name
534 535 536 537 538 539 540 541 542 543 544 545 546 547
#elif CONFIG_GPLV3
    "%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",
    program_name, program_name, program_name
548
#elif CONFIG_GPL
549
    "%s is free software; you can redistribute it and/or modify\n"
550 551 552 553
    "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"
554
    "%s is distributed in the hope that it will be useful,\n"
555 556 557 558 559
    "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"
560 561 562
    "along with %s; if not, write to the Free Software\n"
    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
    program_name, program_name, program_name
563 564 565 566 567 568 569 570 571 572 573 574 575 576
#elif CONFIG_LGPLV3
    "%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",
    program_name, program_name, program_name
577
#else
578
    "%s is free software; you can redistribute it and/or\n"
579 580 581 582
    "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"
583
    "%s is distributed in the hope that it will be useful,\n"
584 585 586 587 588
    "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"
589 590 591
    "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",
    program_name, program_name, program_name
592
#endif
593
    );
594 595

    return 0;
596
}
597

598
int show_formats(void *optctx, const char *opt, const char *arg)
599
{
600 601
    AVInputFormat *ifmt  = NULL;
    AVOutputFormat *ofmt = NULL;
602 603
    const char *last_name;

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
    printf("File formats:\n"
           " D. = Demuxing supported\n"
           " .E = Muxing supported\n"
           " --\n");
    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))) {
            if ((name == NULL || strcmp(ofmt->name, name) < 0) &&
                strcmp(ofmt->name, last_name) > 0) {
                name      = ofmt->name;
                long_name = ofmt->long_name;
                encode    = 1;
621 622
            }
        }
623 624 625 626 627 628
        while ((ifmt = av_iformat_next(ifmt))) {
            if ((name == NULL || strcmp(ifmt->name, name) < 0) &&
                strcmp(ifmt->name, last_name) > 0) {
                name      = ifmt->name;
                long_name = ifmt->long_name;
                encode    = 0;
629
            }
630 631
            if (name && strcmp(ifmt->name, name) == 0)
                decode = 1;
632
        }
633
        if (name == NULL)
634
            break;
635
        last_name = name;
636

637 638 639 640
        printf(" %s%s %-15s %s\n",
               decode ? "D" : " ",
               encode ? "E" : " ",
               name,
641 642
            long_name ? long_name:" ");
    }
643
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
644
}
645

646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \
    if (codec->field) {                                                      \
        const type *p = c->field;                                            \
                                                                             \
        printf("    Supported " list_name ":");                              \
        while (*p != term) {                                                 \
            get_name(*p);                                                    \
            printf(" %s", name);                                             \
            p++;                                                             \
        }                                                                    \
        printf("\n");                                                        \
    }                                                                        \

static void print_codec(const AVCodec *c)
{
    int encoder = av_codec_is_encoder(c);

    printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
           c->long_name ? c->long_name : "");

    if (c->type == AVMEDIA_TYPE_VIDEO) {
        printf("    Threading capabilities: ");
        switch (c->capabilities & (CODEC_CAP_FRAME_THREADS |
                                   CODEC_CAP_SLICE_THREADS)) {
        case CODEC_CAP_FRAME_THREADS |
             CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break;
        case CODEC_CAP_FRAME_THREADS: printf("frame");           break;
        case CODEC_CAP_SLICE_THREADS: printf("slice");           break;
        default:                      printf("no");              break;
        }
        printf("\n");
    }

    if (c->supported_framerates) {
        const AVRational *fps = c->supported_framerates;

        printf("    Supported framerates:");
        while (fps->num) {
            printf(" %d/%d", fps->num, fps->den);
            fps++;
        }
        printf("\n");
    }
    PRINT_CODEC_SUPPORTED(c, pix_fmts, enum PixelFormat, "pixel formats",
                          PIX_FMT_NONE, GET_PIX_FMT_NAME);
    PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0,
                          GET_SAMPLE_RATE_NAME);
    PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats",
                          AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME);
    PRINT_CODEC_SUPPORTED(c, channel_layouts, uint64_t, "channel layouts",
                          0, GET_CH_LAYOUT_DESC);

    if (c->priv_class) {
        show_help_children(c->priv_class,
                           AV_OPT_FLAG_ENCODING_PARAM |
                           AV_OPT_FLAG_DECODING_PARAM);
    }
}

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
static char get_media_type_char(enum AVMediaType type)
{
    switch (type) {
        case AVMEDIA_TYPE_VIDEO:    return 'V';
        case AVMEDIA_TYPE_AUDIO:    return 'A';
        case AVMEDIA_TYPE_SUBTITLE: return 'S';
        default:                    return '?';
    }
}

static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev,
                                        int encoder)
{
    while ((prev = av_codec_next(prev))) {
        if (prev->id == id &&
            (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev)))
            return prev;
    }
    return NULL;
}

static void print_codecs_for_id(enum AVCodecID id, int encoder)
{
    const AVCodec *codec = NULL;

    printf(" (%s: ", encoder ? "encoders" : "decoders");

    while ((codec = next_codec_for_id(id, codec, encoder)))
        printf("%s ", codec->name);

    printf(")");
}

738
int show_codecs(void *optctx, const char *opt, const char *arg)
Michael Niedermayer's avatar
Michael Niedermayer committed
739
{
740 741
    const AVCodecDescriptor *desc = NULL;

742
    printf("Codecs:\n"
743 744 745 746 747 748 749 750 751
           " D..... = Decoding supported\n"
           " .E.... = Encoding supported\n"
           " ..V... = Video codec\n"
           " ..A... = Audio codec\n"
           " ..S... = Subtitle codec\n"
           " ...I.. = Intra frame-only codec\n"
           " ....L. = Lossy compression\n"
           " .....S = Lossless compression\n"
           " -------\n");
752 753 754 755 756 757 758 759
    while ((desc = avcodec_descriptor_next(desc))) {
        const AVCodec *codec = NULL;

        printf(avcodec_find_decoder(desc->id) ? "D" : ".");
        printf(avcodec_find_encoder(desc->id) ? "E" : ".");

        printf("%c", get_media_type_char(desc->type));
        printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : ".");
760 761
        printf((desc->props & AV_CODEC_PROP_LOSSY)      ? "L" : ".");
        printf((desc->props & AV_CODEC_PROP_LOSSLESS)   ? "S" : ".");
762 763 764 765 766 767 768 769 770

        printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : "");

        /* print decoders/encoders when there's more than one or their
         * names are different from codec name */
        while ((codec = next_codec_for_id(desc->id, codec, 0))) {
            if (strcmp(codec->name, desc->name)) {
                print_codecs_for_id(desc->id, 0);
                break;
771
            }
772 773 774 775 776 777
        }
        codec = NULL;
        while ((codec = next_codec_for_id(desc->id, codec, 1))) {
            if (strcmp(codec->name, desc->name)) {
                print_codecs_for_id(desc->id, 1);
                break;
778 779 780 781 782
            }
        }

        printf("\n");
    }
783
    return 0;
784 785 786 787 788 789 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
}

static void print_codecs(int encoder)
{
    const AVCodecDescriptor *desc = NULL;

    printf("%s:\n"
           " V... = Video\n"
           " A... = Audio\n"
           " S... = Subtitle\n"
           " .F.. = Frame-level multithreading\n"
           " ..S. = Slice-level multithreading\n"
           " ...X = Codec is experimental\n"
           " ---\n",
           encoder ? "Encoders" : "Decoders");
    while ((desc = avcodec_descriptor_next(desc))) {
        const AVCodec *codec = NULL;

        while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
            printf("%c", get_media_type_char(desc->type));
            printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : ".");
            printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : ".");
            printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL)  ? "X" : ".");

            printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
            if (strcmp(codec->name, desc->name))
                printf(" (codec %s)", desc->name);

            printf("\n");
        }
    }
}

817
int show_decoders(void *optctx, const char *opt, const char *arg)
818 819 820 821 822
{
    print_codecs(0);
    return 0;
}

823
int show_encoders(void *optctx, const char *opt, const char *arg)
824 825 826
{
    print_codecs(1);
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
827 828
}

829
int show_bsfs(void *optctx, const char *opt, const char *arg)
Michael Niedermayer's avatar
Michael Niedermayer committed
830
{
831
    AVBitStreamFilter *bsf = NULL;
832 833

    printf("Bitstream filters:\n");
834
    while ((bsf = av_bitstream_filter_next(bsf)))
835
        printf("%s\n", bsf->name);
836
    printf("\n");
837
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
838 839
}

840
int show_protocols(void *optctx, const char *opt, const char *arg)
Michael Niedermayer's avatar
Michael Niedermayer committed
841
{
842 843
    void *opaque = NULL;
    const char *name;
844

845
    printf("Supported file protocols:\n"
846 847 848 849 850 851
           "Input:\n");
    while ((name = avio_enum_protocols(&opaque, 0)))
        printf("%s\n", name);
    printf("Output:\n");
    while ((name = avio_enum_protocols(&opaque, 1)))
        printf("%s\n", name);
852
    return 0;
853
}
Stefano Sabatini's avatar
Stefano Sabatini committed
854

855
int show_filters(void *optctx, const char *opt, const char *arg)
856
{
857
    AVFilter av_unused(**filter) = NULL;
858 859

    printf("Filters:\n");
860
#if CONFIG_AVFILTER
861 862
    while ((filter = av_filter_next(filter)) && *filter)
        printf("%-16s %s\n", (*filter)->name, (*filter)->description);
863
#endif
864
    return 0;
865 866
}

867
int show_pix_fmts(void *optctx, const char *opt, const char *arg)
868
{
869 870
    enum PixelFormat pix_fmt;

871 872 873 874 875 876 877 878
    printf("Pixel formats:\n"
           "I.... = Supported Input  format for conversion\n"
           ".O... = Supported Output format for conversion\n"
           "..H.. = Hardware accelerated format\n"
           "...P. = Paletted format\n"
           "....B = Bitstream format\n"
           "FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL\n"
           "-----\n");
879

880 881 882 883 884
#if !CONFIG_SWSCALE
#   define sws_isSupportedInput(x)  0
#   define sws_isSupportedOutput(x) 0
#endif

885 886 887 888 889 890 891 892 893 894 895 896
    for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) {
        const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt];
        printf("%c%c%c%c%c %-16s       %d            %2d\n",
               sws_isSupportedInput (pix_fmt)      ? 'I' : '.',
               sws_isSupportedOutput(pix_fmt)      ? 'O' : '.',
               pix_desc->flags & PIX_FMT_HWACCEL   ? 'H' : '.',
               pix_desc->flags & PIX_FMT_PAL       ? 'P' : '.',
               pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.',
               pix_desc->name,
               pix_desc->nb_components,
               av_get_bits_per_pixel(pix_desc));
    }
897
    return 0;
898 899
}

900
int show_sample_fmts(void *optctx, const char *opt, const char *arg)
901 902 903 904 905 906 907 908
{
    int i;
    char fmt_str[128];
    for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
        printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
    return 0;
}

909 910 911 912 913 914 915 916 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
static void show_help_codec(const char *name, int encoder)
{
    const AVCodecDescriptor *desc;
    const AVCodec *codec;

    if (!name) {
        av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n");
        return;
    }

    codec = encoder ? avcodec_find_encoder_by_name(name) :
                      avcodec_find_decoder_by_name(name);

    if (codec)
        print_codec(codec);
    else if ((desc = avcodec_descriptor_get_by_name(name))) {
        int printed = 0;

        while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
            printed = 1;
            print_codec(codec);
        }

        if (!printed) {
            av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to Libav, "
                   "but no %s for it are available. Libav might need to be "
                   "recompiled with additional external libraries.\n",
                   name, encoder ? "encoders" : "decoders");
        }
    } else {
        av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by Libav.\n",
               name);
    }
}

Anton Khirnov's avatar
Anton Khirnov committed
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
static void show_help_demuxer(const char *name)
{
    const AVInputFormat *fmt = av_find_input_format(name);

    if (!fmt) {
        av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
        return;
    }

    printf("Demuxer %s [%s]:\n", fmt->name, fmt->long_name);

    if (fmt->extensions)
        printf("    Common extensions: %s.\n", fmt->extensions);

    if (fmt->priv_class)
        show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM);
}

static void show_help_muxer(const char *name)
{
    const AVCodecDescriptor *desc;
    const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL);

    if (!fmt) {
        av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
        return;
    }

    printf("Muxer %s [%s]:\n", fmt->name, fmt->long_name);

    if (fmt->extensions)
        printf("    Common extensions: %s.\n", fmt->extensions);
    if (fmt->mime_type)
        printf("    Mime type: %s.\n", fmt->mime_type);
    if (fmt->video_codec != AV_CODEC_ID_NONE &&
        (desc = avcodec_descriptor_get(fmt->video_codec))) {
        printf("    Default video codec: %s.\n", desc->name);
    }
    if (fmt->audio_codec != AV_CODEC_ID_NONE &&
        (desc = avcodec_descriptor_get(fmt->audio_codec))) {
        printf("    Default audio codec: %s.\n", desc->name);
    }
    if (fmt->subtitle_codec != AV_CODEC_ID_NONE &&
        (desc = avcodec_descriptor_get(fmt->subtitle_codec))) {
        printf("    Default subtitle codec: %s.\n", desc->name);
    }

    if (fmt->priv_class)
        show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM);
}

995
int show_help(void *optctx, const char *opt, const char *arg)
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
{
    char *topic, *par;
    av_log_set_callback(log_callback_help);

    topic = av_strdup(arg ? arg : "");
    par = strchr(topic, '=');
    if (par)
        *par++ = 0;

    if (!*topic) {
        show_help_default(topic, par);
    } else if (!strcmp(topic, "decoder")) {
        show_help_codec(par, 0);
    } else if (!strcmp(topic, "encoder")) {
        show_help_codec(par, 1);
Anton Khirnov's avatar
Anton Khirnov committed
1011 1012 1013 1014
    } else if (!strcmp(topic, "demuxer")) {
        show_help_demuxer(par);
    } else if (!strcmp(topic, "muxer")) {
        show_help_muxer(par);
1015 1016 1017 1018 1019 1020 1021 1022
    } else {
        show_help_default(topic, par);
    }

    av_freep(&topic);
    return 0;
}