cmdutils.c 52.2 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
#if HAVE_SYS_RESOURCE_H
52
#include <sys/time.h>
Måns Rullgård's avatar
Måns Rullgård committed
53 54
#include <sys/resource.h>
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
55

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

59
static const int this_year = 2013;
60

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

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

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

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

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

121 122
int64_t parse_time_or_die(const char *context, const char *timestr,
                          int is_duration)
123
{
124 125
    int64_t us;
    if (av_parse_time(&us, timestr, is_duration) < 0) {
126 127
        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
128
        exit_program(1);
129 130 131 132
    }
    return us;
}

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

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

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

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

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

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

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

185
#if HAVE_COMMANDLINETOARGVW
186
#include <windows.h>
187
#include <shellapi.h>
188 189 190 191 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
/* 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);

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

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

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

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

    if (po->flags & OPT_STRING) {
        char *str;
        str = av_strdup(arg);
269
        av_freep(dst);
270
        *(char **)dst = str;
271
    } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) {
272
        *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
273
    } else if (po->flags & OPT_INT64) {
274
        *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
275
    } else if (po->flags & OPT_TIME) {
276
        *(int64_t *)dst = parse_time_or_die(opt, arg, 1);
277
    } else if (po->flags & OPT_FLOAT) {
278
        *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
279
    } else if (po->flags & OPT_DOUBLE) {
280
        *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY);
281
    } else if (po->u.func_arg) {
282
        int ret = po->u.func_arg(optctx, opt, arg);
283
        if (ret < 0) {
284 285
            av_log(NULL, AV_LOG_ERROR,
                   "Failed to set value '%s' for option '%s'\n", arg, opt);
286 287 288 289
            return ret;
        }
    }
    if (po->flags & OPT_EXIT)
Luca Barbato's avatar
Luca Barbato committed
290
        exit_program(0);
291 292 293 294 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

    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;

325 326 327
    return !!(po->flags & HAS_ARG);
}

328
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
329
                   void (*parse_arg_function)(void *, const char*))
Fabrice Bellard's avatar
Fabrice Bellard committed
330
{
331 332
    const char *opt;
    int optindex, handleoptions = 1, ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
333

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

Fabrice Bellard's avatar
Fabrice Bellard committed
337 338 339 340
    /* parse options */
    optindex = 1;
    while (optindex < argc) {
        opt = argv[optindex++];
341

342
        if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
Stefano Sabatini's avatar
Stefano Sabatini committed
343 344 345 346
            if (opt[1] == '-' && opt[2] == '\0') {
                handleoptions = 0;
                continue;
            }
347
            opt++;
348 349

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

359 360 361 362 363 364 365 366 367 368
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];

369 370 371 372 373 374 375 376 377 378
        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);
        }

379 380 381 382 383 384 385 386 387 388 389 390 391
        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;
}

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

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

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

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

    if (o)
        return 0;
    return AVERROR_OPTION_NOT_FOUND;
}

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

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

    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;
517
    g->resample_opts = resample_opts;
518 519 520

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

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

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

    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);
578
            av_dict_free(&l->groups[j].resample_opts);
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
#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,
595
                      const OptionGroupDef *groups, int nb_groups)
596 597 598 599 600 601
{
    int optindex = 1;

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

602
    init_parse_context(octx, groups, nb_groups);
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
    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 */
630
        if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) {
631 632 633 634 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
            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;
    }

685
    if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts)
686 687 688 689 690 691 692 693
        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;
}

694
int opt_loglevel(void *optctx, const char *opt, const char *arg)
695
{
Carl Eugen Hoyos's avatar
Carl Eugen Hoyos committed
696
    const struct { const char *name; int level; } log_levels[] = {
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
        { "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) {
719 720
        av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". "
               "Possible levels are numbers or:\n", arg);
721
        for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
722
            av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
Luca Barbato's avatar
Luca Barbato committed
723
        exit_program(1);
724 725 726 727 728
    }
    av_log_set_level(level);
    return 0;
}

729
int opt_timelimit(void *optctx, const char *opt, const char *arg)
Måns Rullgård's avatar
Måns Rullgård committed
730
{
Måns Rullgård's avatar
Måns Rullgård committed
731
#if HAVE_SETRLIMIT
Måns Rullgård's avatar
Måns Rullgård committed
732 733 734 735 736
    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
737
    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
738 739 740 741
#endif
    return 0;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
742 743
void print_error(const char *filename, int err)
{
744
    char errbuf[128];
745
    const char *errbuf_ptr = errbuf;
746

747 748
    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
        errbuf_ptr = strerror(AVUNERROR(err));
749
    av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr);
Fabrice Bellard's avatar
Fabrice Bellard committed
750
}
751

752 753
static int warned_cfg = 0;

754 755
#define INDENT        1
#define SHOW_VERSION  2
756
#define SHOW_CONFIG   4
757

758
#define PRINT_LIB_INFO(libname, LIBNAME, flags, level)                  \
759
    if (CONFIG_##LIBNAME) {                                             \
760
        const char *indent = flags & INDENT? "  " : "";                 \
761
        if (flags & SHOW_VERSION) {                                     \
Stefano Sabatini's avatar
Stefano Sabatini committed
762
            unsigned int version = libname##_version();                 \
Justin Ruggles's avatar
Justin Ruggles committed
763 764
            av_log(NULL, level,                                         \
                   "%slib%-10s %2d.%3d.%2d / %2d.%3d.%2d\n",            \
765 766 767 768 769
                   indent, #libname,                                    \
                   LIB##LIBNAME##_VERSION_MAJOR,                        \
                   LIB##LIBNAME##_VERSION_MINOR,                        \
                   LIB##LIBNAME##_VERSION_MICRO,                        \
                   version >> 16, version >> 8 & 0xff, version & 0xff); \
770
        }                                                               \
771 772
        if (flags & SHOW_CONFIG) {                                      \
            const char *cfg = libname##_configuration();                \
773
            if (strcmp(LIBAV_CONFIGURATION, cfg)) {                     \
774
                if (!warned_cfg) {                                      \
775
                    av_log(NULL, level,                                 \
776
                            "%sWARNING: library configuration mismatch\n", \
777
                            indent);                                    \
778 779
                    warned_cfg = 1;                                     \
                }                                                       \
780
                av_log(NULL, level, "%s%-11s configuration: %s\n",      \
781
                        indent, #libname, cfg);                         \
782 783
            }                                                           \
        }                                                               \
784
    }                                                                   \
785

786
static void print_all_libs_info(int flags, int level)
787
{
788 789 790 791 792
    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
793
    PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
794
    PRINT_LIB_INFO(swscale,  SWSCALE,  flags, level);
795 796
}

797
void show_banner(void)
798
{
799 800
    av_log(NULL, AV_LOG_INFO,
           "%s version " LIBAV_VERSION ", Copyright (c) %d-%d the Libav developers\n",
801
           program_name, program_birth_year, this_year);
802 803
    av_log(NULL, AV_LOG_INFO, "  built on %s %s with %s\n",
           __DATE__, __TIME__, CC_IDENT);
804 805 806
    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);
807 808
}

809
int show_version(void *optctx, const char *opt, const char *arg)
810
{
811
    av_log_set_callback(log_callback_help);
812
    printf("%s " LIBAV_VERSION "\n", program_name);
813
    print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
814 815

    return 0;
816 817
}

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

    return 0;
887
}
888

889
int show_formats(void *optctx, const char *opt, const char *arg)
890
{
891 892
    AVInputFormat *ifmt  = NULL;
    AVOutputFormat *ofmt = NULL;
893 894
    const char *last_name;

895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
    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;
912 913
            }
        }
914 915 916 917 918 919
        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;
920
            }
921 922
            if (name && strcmp(ifmt->name, name) == 0)
                decode = 1;
923
        }
924
        if (name == NULL)
925
            break;
926
        last_name = name;
927

928 929 930 931
        printf(" %s%s %-15s %s\n",
               decode ? "D" : " ",
               encode ? "E" : " ",
               name,
932 933
            long_name ? long_name:" ");
    }
934
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
935
}
936

937 938 939 940 941 942 943 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
#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");
    }
980 981
    PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats",
                          AV_PIX_FMT_NONE, GET_PIX_FMT_NAME);
982 983 984 985 986 987 988 989 990 991 992 993 994 995
    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);
    }
}

Anton Khirnov's avatar