cmdutils.c 52.7 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"
Luca Barbato's avatar
Luca Barbato committed
46
#include "libavutil/cpu.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
47
#include "cmdutils.h"
48
#include "version.h"
Ramiro Polla's avatar
Ramiro Polla committed
49
#if CONFIG_NETWORK
50
#include "libavformat/network.h"
Ramiro Polla's avatar
Ramiro Polla committed
51
#endif
Måns Rullgård's avatar
Måns Rullgård committed
52
#if HAVE_SYS_RESOURCE_H
53
#include <sys/time.h>
Måns Rullgård's avatar
Måns Rullgård committed
54 55
#include <sys/resource.h>
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
56

57
struct SwsContext *sws_opts;
58
AVDictionary *format_opts, *codec_opts, *resample_opts;
Michael Niedermayer's avatar
Michael Niedermayer committed
59

60
static const int this_year = 2013;
61

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

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

81
void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
82 83 84 85
{
    vfprintf(stdout, fmt, vl);
}

Luca Barbato's avatar
Luca Barbato committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
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);
}

101 102
double parse_number_or_die(const char *context, const char *numstr, int type,
                           double min, double max)
Michael Niedermayer's avatar
Michael Niedermayer committed
103 104 105
{
    char *tail;
    const char *error;
106
    double d = av_strtod(numstr, &tail);
Michael Niedermayer's avatar
Michael Niedermayer committed
107
    if (*tail)
108
        error = "Expected number for %s but found: %s\n";
Michael Niedermayer's avatar
Michael Niedermayer committed
109
    else if (d < min || d > max)
110 111 112
        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";
113
    else if (type == OPT_INT && (int)d != d)
114
        error = "Expected int for %s but found %s\n";
Michael Niedermayer's avatar
Michael Niedermayer committed
115 116
    else
        return d;
117
    av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
Luca Barbato's avatar
Luca Barbato committed
118
    exit_program(1);
119
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
120 121
}

122 123
int64_t parse_time_or_die(const char *context, const char *timestr,
                          int is_duration)
124
{
125 126
    int64_t us;
    if (av_parse_time(&us, timestr, is_duration) < 0) {
127 128
        av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n",
               is_duration ? "duration" : "date", context, timestr);
Luca Barbato's avatar
Luca Barbato committed
129
        exit_program(1);
130 131 132 133
    }
    return us;
}

134
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
135
                       int rej_flags, int alt_flags)
Fabrice Bellard's avatar
Fabrice Bellard committed
136 137
{
    const OptionDef *po;
138
    int first;
Fabrice Bellard's avatar
Fabrice Bellard committed
139

140
    first = 1;
141
    for (po = options; po->name != NULL; po++) {
142
        char buf[64];
143 144

        if (((po->flags & req_flags) != req_flags) ||
145
            (alt_flags && !(po->flags & alt_flags)) ||
146 147 148 149 150 151 152 153
            (po->flags & rej_flags))
            continue;

        if (first) {
            printf("%s\n", msg);
            first = 0;
        }
        av_strlcpy(buf, po->name, sizeof(buf));
154
        if (po->argname) {
155 156
            av_strlcat(buf, " ", sizeof(buf));
            av_strlcat(buf, po->argname, sizeof(buf));
Fabrice Bellard's avatar
Fabrice Bellard committed
157
        }
158
        printf("-%-17s  %s\n", buf, po->help);
Fabrice Bellard's avatar
Fabrice Bellard committed
159
    }
160
    printf("\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
161 162
}

163 164 165 166 167 168 169 170 171 172
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);
}

173 174
static const OptionDef *find_option(const OptionDef *po, const char *name)
{
175 176 177
    const char *p = strchr(name, ':');
    int len = p ? p - name : strlen(name);

Michael Niedermayer's avatar
Michael Niedermayer committed
178
    while (po->name != NULL) {
179
        if (!strncmp(name, po->name, len) && strlen(po->name) == len)
Michael Niedermayer's avatar
Michael Niedermayer committed
180 181 182 183 184 185
            break;
        po++;
    }
    return po;
}

186 187 188 189
/* _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)
190
#include <windows.h>
191
#include <shellapi.h>
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
/* 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);

225 226
    win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize);
    argstr_flat     = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1);
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
    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 */
}
249
#endif /* HAVE_COMMANDLINETOARGVW */
250

251 252
static int write_option(void *optctx, const OptionDef *po, const char *opt,
                        const char *arg)
253 254 255
{
    /* new-style options contain an offset into optctx, old-style address of
     * a global var*/
256 257 258
    void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ?
                (uint8_t *)optctx + po->u.off : po->u.dst_ptr;
    int *dstcount;
259 260 261 262 263

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

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

    if (po->flags & OPT_STRING) {
        char *str;
        str = av_strdup(arg);
273
        av_freep(dst);
274
        *(char **)dst = str;
275
    } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) {
276
        *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
277
    } else if (po->flags & OPT_INT64) {
278
        *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
279
    } else if (po->flags & OPT_TIME) {
280
        *(int64_t *)dst = parse_time_or_die(opt, arg, 1);
281
    } else if (po->flags & OPT_FLOAT) {
282
        *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
283
    } else if (po->flags & OPT_DOUBLE) {
284
        *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY);
285
    } else if (po->u.func_arg) {
286
        int ret = po->u.func_arg(optctx, opt, arg);
287
        if (ret < 0) {
288 289
            av_log(NULL, AV_LOG_ERROR,
                   "Failed to set value '%s' for option '%s'\n", arg, opt);
290 291 292 293
            return ret;
        }
    }
    if (po->flags & OPT_EXIT)
Luca Barbato's avatar
Luca Barbato committed
294
        exit_program(0);
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328

    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;

329 330 331
    return !!(po->flags & HAS_ARG);
}

332
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
333
                   void (*parse_arg_function)(void *, const char*))
Fabrice Bellard's avatar
Fabrice Bellard committed
334
{
335 336
    const char *opt;
    int optindex, handleoptions = 1, ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
337

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

Fabrice Bellard's avatar
Fabrice Bellard committed
341 342 343 344
    /* parse options */
    optindex = 1;
    while (optindex < argc) {
        opt = argv[optindex++];
345

346
        if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
Stefano Sabatini's avatar
Stefano Sabatini committed
347 348 349 350
            if (opt[1] == '-' && opt[2] == '\0') {
                handleoptions = 0;
                continue;
            }
351
            opt++;
352 353

            if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
Luca Barbato's avatar
Luca Barbato committed
354
                exit_program(1);
355
            optindex += ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
356
        } else {
357
            if (parse_arg_function)
358
                parse_arg_function(optctx, opt);
Fabrice Bellard's avatar
Fabrice Bellard committed
359 360 361 362
        }
    }
}

363 364 365 366 367 368 369 370 371 372
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];

373 374 375 376 377 378 379 380 381 382
        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);
        }

383 384 385 386 387 388 389 390 391 392 393 394 395
        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;
}

396 397
int locate_option(int argc, char **argv, const OptionDef *options,
                  const char *optname)
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
{
    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");
425 426
    if (!idx)
        idx = locate_option(argc, argv, options, "v");
427
    if (idx && argv[idx + 1])
428
        opt_loglevel(NULL, "loglevel", argv[idx + 1]);
429 430
}

431
#define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
432
int opt_default(void *optctx, const char *opt, const char *arg)
Anton Khirnov's avatar
Anton Khirnov committed
433 434
{
    const AVOption *o;
435 436
    char opt_stripped[128];
    const char *p;
437
    const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class();
438
#if CONFIG_AVRESAMPLE
439
    const AVClass *rc = avresample_get_class();
440
#endif
441 442 443
#if CONFIG_SWSCALE
    const AVClass *sc = sws_get_class();
#endif
444 445 446 447 448

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

449 450 451 452
    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))))
453
        av_dict_set(&codec_opts, opt, arg, FLAGS);
454 455
    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
456
        av_dict_set(&format_opts, opt, arg, FLAGS);
457
#if CONFIG_AVRESAMPLE
458 459 460
    else if ((o = av_opt_find(&rc, opt, NULL, 0,
                              AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)))
        av_dict_set(&resample_opts, opt, arg, FLAGS);
461
#endif
462
#if CONFIG_SWSCALE
463 464
    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
465
        // XXX we only support sws_flags, not arbitrary sws options
466
        int ret = av_opt_set(sws_opts, opt, arg, 0);
Anton Khirnov's avatar
Anton Khirnov committed
467 468 469 470 471
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
            return ret;
        }
    }
472
#endif
Anton Khirnov's avatar
Anton Khirnov committed
473 474 475 476 477 478

    if (o)
        return 0;
    return AVERROR_OPTION_NOT_FOUND;
}

479 480 481 482 483
/*
 * Check whether given option is a group separator.
 *
 * @return index of the group definition that matched or -1 if none
 */
484 485
static int match_group_separator(const OptionGroupDef *groups, int nb_groups,
                                 const char *opt)
486
{
487
    int i;
488

489 490
    for (i = 0; i < nb_groups; i++) {
        const OptionGroupDef *p = &groups[i];
491
        if (p->sep && !strcmp(p->sep, opt))
492
            return i;
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    }

    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;
#if CONFIG_SWSCALE
    g->sws_opts    = sws_opts;
#endif
    g->codec_opts  = codec_opts;
    g->format_opts = format_opts;
521
    g->resample_opts = resample_opts;
522 523 524

    codec_opts  = NULL;
    format_opts = NULL;
525
    resample_opts = NULL;
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
#if CONFIG_SWSCALE
    sws_opts    = NULL;
#endif
    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,
550
                               const OptionGroupDef *groups, int nb_groups)
551 552 553 554 555 556
{
    static const OptionGroupDef global_group = { "global" };
    int i;

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

557
    octx->nb_groups = nb_groups;
558 559
    octx->groups    = av_mallocz(sizeof(*octx->groups) * octx->nb_groups);
    if (!octx->groups)
Luca Barbato's avatar
Luca Barbato committed
560
        exit_program(1);
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

    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);
582
            av_dict_free(&l->groups[j].resample_opts);
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
#if CONFIG_SWSCALE
            sws_freeContext(l->groups[j].sws_opts);
#endif
        }
        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,
599
                      const OptionGroupDef *groups, int nb_groups)
600 601 602 603 604 605
{
    int optindex = 1;

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

606
    init_parse_context(octx, groups, nb_groups);
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
    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);

        /* unnamed group separators, e.g. output filename */
        if (opt[0] != '-' || !opt[1]) {
            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 */
634
        if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) {
635 636 637 638 639 640 641 642 643 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
            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;
    }

689
    if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts)
690 691 692 693 694 695 696 697
        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;
}

Luca Barbato's avatar
Luca Barbato committed
698 699 700 701 702 703 704 705 706 707 708
int opt_cpuflags(void *optctx, const char *opt, const char *arg)
{
    int flags = av_parse_cpu_flags(arg);

    if (flags < 0)
        return flags;

    av_set_cpu_flags_mask(flags);
    return 0;
}

709
int opt_loglevel(void *optctx, const char *opt, const char *arg)
710
{
Carl Eugen Hoyos's avatar
Carl Eugen Hoyos committed
711
    const struct { const char *name; int level; } log_levels[] = {
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
        { "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) {
734 735
        av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". "
               "Possible levels are numbers or:\n", arg);
736
        for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
737
            av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
Luca Barbato's avatar
Luca Barbato committed
738
        exit_program(1);
739 740 741 742 743
    }
    av_log_set_level(level);
    return 0;
}

744
int opt_timelimit(void *optctx, const char *opt, const char *arg)
Måns Rullgård's avatar
Måns Rullgård committed
745
{
Måns Rullgård's avatar
Måns Rullgård committed
746
#if HAVE_SETRLIMIT
Måns Rullgård's avatar
Måns Rullgård committed
747 748 749 750 751
    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
752
    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
753 754 755 756
#endif
    return 0;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
757 758
void print_error(const char *filename, int err)
{
759
    char errbuf[128];
760
    const char *errbuf_ptr = errbuf;
761

762 763
    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
        errbuf_ptr = strerror(AVUNERROR(err));
764
    av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr);
Fabrice Bellard's avatar
Fabrice Bellard committed
765
}
766

767 768
static int warned_cfg = 0;

769 770
#define INDENT        1
#define SHOW_VERSION  2
771
#define SHOW_CONFIG   4
772

773
#define PRINT_LIB_INFO(libname, LIBNAME, flags, level)                  \
774
    if (CONFIG_##LIBNAME) {                                             \
775
        const char *indent = flags & INDENT? "  " : "";                 \
776
        if (flags & SHOW_VERSION) {                                     \
Stefano Sabatini's avatar
Stefano Sabatini committed
777
            unsigned int version = libname##_version();                 \
Justin Ruggles's avatar
Justin Ruggles committed
778 779
            av_log(NULL, level,                                         \
                   "%slib%-10s %2d.%3d.%2d / %2d.%3d.%2d\n",            \
780 781 782 783 784
                   indent, #libname,                                    \
                   LIB##LIBNAME##_VERSION_MAJOR,                        \
                   LIB##LIBNAME##_VERSION_MINOR,                        \
                   LIB##LIBNAME##_VERSION_MICRO,                        \
                   version >> 16, version >> 8 & 0xff, version & 0xff); \
785
        }                                                               \
786 787
        if (flags & SHOW_CONFIG) {                                      \
            const char *cfg = libname##_configuration();                \
788
            if (strcmp(LIBAV_CONFIGURATION, cfg)) {                     \
789
                if (!warned_cfg) {                                      \
790
                    av_log(NULL, level,                                 \
791
                            "%sWARNING: library configuration mismatch\n", \
792
                            indent);                                    \
793 794
                    warned_cfg = 1;                                     \
                }                                                       \
795
                av_log(NULL, level, "%s%-11s configuration: %s\n",      \
796
                        indent, #libname, cfg);                         \
797 798
            }                                                           \
        }                                                               \
799
    }                                                                   \
800

801
static void print_all_libs_info(int flags, int level)
802
{
803 804 805 806 807
    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
808
    PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
809
    PRINT_LIB_INFO(swscale,  SWSCALE,  flags, level);
810 811
}

812
void show_banner(void)
813
{
814 815
    av_log(NULL, AV_LOG_INFO,
           "%s version " LIBAV_VERSION ", Copyright (c) %d-%d the Libav developers\n",
816
           program_name, program_birth_year, this_year);
817 818
    av_log(NULL, AV_LOG_INFO, "  built on %s %s with %s\n",
           __DATE__, __TIME__, CC_IDENT);
819 820 821
    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);
822 823
}

824
int show_version(void *optctx, const char *opt, const char *arg)
825
{
826
    av_log_set_callback(log_callback_help);
827
    printf("%s " LIBAV_VERSION "\n", program_name);
828
    print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
829 830

    return 0;
831 832
}

833
int show_license(void *optctx, const char *opt, const char *arg)
834
{
835
    printf(
836
#if CONFIG_NONFREE
837 838 839
    "This version of %s has nonfree parts compiled in.\n"
    "Therefore it is not legally redistributable.\n",
    program_name
840 841 842 843 844 845 846 847 848 849 850 851 852 853
#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
854
#elif CONFIG_GPL
855
    "%s is free software; you can redistribute it and/or modify\n"
856 857 858 859
    "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"
860
    "%s is distributed in the hope that it will be useful,\n"
861 862 863 864 865
    "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"
866 867 868
    "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
869 870 871 872 873 874 875 876 877 878 879 880 881 882
#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
883
#else
884
    "%s is free software; you can redistribute it and/or\n"
885 886 887 888
    "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"
889
    "%s is distributed in the hope that it will be useful,\n"
890 891 892 893 894
    "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"
895 896 897
    "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
898
#endif
899
    );
900 901

    return 0;
902
}
903

904
int show_formats(void *optctx, const char *opt, const char *arg)
905
{
906 907
    AVInputFormat *ifmt  = NULL;
    AVOutputFormat *ofmt = NULL;
908 909
    const char *last_name;

910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
    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;
927 928
            }
        }
929 930 931 932 933 934
        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;
935
            }
936 937
            if (name && strcmp(ifmt->name, name) == 0)
                decode = 1;
938
        }
939
        if (name == NULL)
940
            break;
941
        last_name = name;
942

943 944 945 946
        printf(" %s%s %-15s %s\n",
               decode ? "D" : " ",
               encode ? "E" : " ",
               name,
947 948
            long_name ? long_name:" ");
    }
949
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
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
#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");
    }
995