x264.c 66.1 KB
Newer Older
1
/*****************************************************************************
2
 * x264: h264 encoder testing program.
3
 *****************************************************************************
4
 * Copyright (C) 2003-2008 x264 project
5
 *
6 7
 * Authors: Loren Merritt <lorenm@u.washington.edu>
 *          Laurent Aimar <fenrir@via.ecp.fr>
8 9
 *          Steven Walters <kemuri9@gmail.com>
 *          Kieran Kunhya <kieran@kunhya.com>
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
24 25 26 27 28 29 30 31 32
 *****************************************************************************/

#include <stdlib.h>
#include <math.h>

#include <signal.h>
#define _GNU_SOURCE
#include <getopt.h>

33
#include "common/common.h"
34
#include "common/cpu.h"
35 36
#include "x264.h"
#include "muxers.h"
Loren Merritt's avatar
Loren Merritt committed
37

38 39 40 41 42 43
#ifdef _WIN32
#include <windows.h>
#else
#define SetConsoleTitle(t)
#endif

44
/* Ctrl-C handler */
Loren Merritt's avatar
Loren Merritt committed
45 46
static int     b_ctrl_c = 0;
static int     b_exit_on_ctrl_c = 0;
47 48
static void    SigIntHandler( int a )
{
Loren Merritt's avatar
Loren Merritt committed
49 50 51
    if( b_exit_on_ctrl_c )
        exit(0);
    b_ctrl_c = 1;
52 53
}

Loren Merritt's avatar
Loren Merritt committed
54 55 56 57 58
typedef struct {
    int b_progress;
    int i_seek;
    hnd_t hin;
    hnd_t hout;
59
    FILE *qpfile;
Yusuke Nakamura's avatar
Yusuke Nakamura committed
60 61
    FILE *tcfile_out;
    double timebase_convert_multiplier;
62
    int i_pulldown;
Loren Merritt's avatar
Loren Merritt committed
63 64
} cli_opt_t;

65 66 67
/* i/o file operation function pointer structs */
cli_input_t input;
static cli_output_t output;
Loren Merritt's avatar
Loren Merritt committed
68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
static const char * const demuxer_names[] =
{
    "auto",
    "yuv",
    "y4m",
#ifdef AVS_INPUT
    "avs",
#endif
#ifdef LAVF_INPUT
    "lavf",
#endif
#ifdef FFMS_INPUT
    "ffms",
#endif
    0
};

static const char * const muxer_names[] =
{
    "auto",
    "raw",
    "mkv",
    "flv",
#ifdef MP4_OUTPUT
    "mp4",
#endif
    0
};
97

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };

typedef struct{
    int mod;
    uint8_t pattern[24];
    float fps_factor;
} cli_pulldown_t;

enum pulldown_type_e
{
    X264_PULLDOWN_22 = 1,
    X264_PULLDOWN_32,
    X264_PULLDOWN_64,
    X264_PULLDOWN_DOUBLE,
    X264_PULLDOWN_TRIPLE,
    X264_PULLDOWN_EURO
};

#define TB  PIC_STRUCT_TOP_BOTTOM
#define BT  PIC_STRUCT_BOTTOM_TOP
#define TBT PIC_STRUCT_TOP_BOTTOM_TOP
#define BTB PIC_STRUCT_BOTTOM_TOP_BOTTOM

static const cli_pulldown_t pulldown_values[] =
{
    [X264_PULLDOWN_22]     = {1,  {TB},                                   2.0},
    [X264_PULLDOWN_32]     = {4,  {TBT, BT, BTB, TB},                     1.25},
    [X264_PULLDOWN_64]     = {2,  {PIC_STRUCT_DOUBLE, PIC_STRUCT_TRIPLE}, 1.0},
    [X264_PULLDOWN_DOUBLE] = {1,  {PIC_STRUCT_DOUBLE},                    2.0},
    [X264_PULLDOWN_TRIPLE] = {1,  {PIC_STRUCT_TRIPLE},                    3.0},
    [X264_PULLDOWN_EURO]   = {24, {TBT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT,
                                   BTB, TB, TB, TB, TB, TB, TB, TB, TB, TB, TB, TB}, 25.0/24.0}
};

#undef TB
#undef BT
#undef TBT
#undef BTB

// indexed by pic_struct enum
static const float pulldown_frame_duration[10] = { 0.0, 1, 0.5, 0.5, 1, 1, 1.5, 1.5, 2, 3 };

Fiona Glaser's avatar
Fiona Glaser committed
140
static void Help( x264_param_t *defaults, int longhelp );
Loren Merritt's avatar
Loren Merritt committed
141 142
static int  Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt );
static int  Encode( x264_param_t *param, cli_opt_t *opt );
143 144 145 146 147 148 149

/****************************************************************************
 * main:
 ****************************************************************************/
int main( int argc, char **argv )
{
    x264_param_t param;
Loren Merritt's avatar
Loren Merritt committed
150
    cli_opt_t opt;
151 152 153 154 155 156
    int ret;

#ifdef PTW32_STATIC_LIB
    pthread_win32_process_attach_np();
    pthread_win32_thread_attach_np();
#endif
157

158
#ifdef _WIN32
159
    _setmode(_fileno(stdin), _O_BINARY);
160 161 162 163
    _setmode(_fileno(stdout), _O_BINARY);
#endif

    /* Parse command line */
Loren Merritt's avatar
Loren Merritt committed
164
    if( Parse( argc, argv, &param, &opt ) < 0 )
165 166 167 168 169
        return -1;

    /* Control-C handler */
    signal( SIGINT, SigIntHandler );

170 171 172 173 174 175 176 177
    ret = Encode( &param, &opt );

#ifdef PTW32_STATIC_LIB
    pthread_win32_thread_detach_np();
    pthread_win32_process_detach_np();
#endif

    return ret;
178 179
}

180
static char const *strtable_lookup( const char * const table[], int index )
181 182 183 184 185
{
    int i = 0; while( table[i] ) i++;
    return ( ( index >= 0 && index < i ) ? table[ index ] : "???" );
}

186 187 188 189 190 191 192 193 194 195 196 197 198
static char *stringify_names( char *buf, const char * const names[] )
{
    int i = 0;
    char *p = buf;
    for( p[0] = 0; names[i]; i++ )
    {
        p += sprintf( p, "%s", names[i] );
        if( names[i+1] )
            p += sprintf( p, ", " );
    }
    return buf;
}

199 200 201
/*****************************************************************************
 * Help:
 *****************************************************************************/
Fiona Glaser's avatar
Fiona Glaser committed
202
static void Help( x264_param_t *defaults, int longhelp )
203
{
204
    char buf[50];
205
#define H0 printf
Fiona Glaser's avatar
Fiona Glaser committed
206 207
#define H1 if(longhelp>=1) printf
#define H2 if(longhelp==2) printf
208 209 210 211 212
    H0( "x264 core:%d%s\n"
        "Syntax: x264 [options] -o outfile infile [widthxheight]\n"
        "\n"
        "Infile can be raw YUV 4:2:0 (in which case resolution is required),\n"
        "  or YUV4MPEG 4:2:0 (*.y4m),\n"
213
        "  or Avisynth if compiled with support (%s).\n"
214
        "  or libav* formats if compiled with lavf support (%s) or ffms support (%s).\n"
215 216 217
        "Outfile type is selected by filename:\n"
        " .264 -> Raw bytestream\n"
        " .mkv -> Matroska\n"
Kieran Kunhya's avatar
Kieran Kunhya committed
218
        " .flv -> Flash Video\n"
219 220 221 222
        " .mp4 -> MP4 if compiled with GPAC support (%s)\n"
        "\n"
        "Options:\n"
        "\n"
Fiona Glaser's avatar
Fiona Glaser committed
223 224 225
        "  -h, --help                  List basic options\n"
        "      --longhelp              List more options\n"
        "      --fullhelp              List all options\n"
226 227
        "\n",
        X264_BUILD, X264_VERSION,
228
#ifdef AVS_INPUT
229 230 231 232 233 234 235 236 237 238 239
        "yes",
#else
        "no",
#endif
#ifdef LAVF_INPUT
        "yes",
#else
        "no",
#endif
#ifdef FFMS_INPUT
        "yes",
Loren Merritt's avatar
Loren Merritt committed
240
#else
241
        "no",
Loren Merritt's avatar
Loren Merritt committed
242 243
#endif
#ifdef MP4_OUTPUT
244
        "yes"
Loren Merritt's avatar
Loren Merritt committed
245
#else
246
        "no"
Loren Merritt's avatar
Loren Merritt committed
247
#endif
248
      );
Fiona Glaser's avatar
Fiona Glaser committed
249 250 251
    H0( "Example usage:\n" );
    H0( "\n" );
    H0( "      Constant quality mode:\n" );
252
    H0( "            x264 --crf 24 -o <output> <input>\n" );
Fiona Glaser's avatar
Fiona Glaser committed
253 254
    H0( "\n" );
    H0( "      Two-pass with a bitrate of 1000kbps:\n" );
255 256
    H0( "            x264 --pass 1 --bitrate 1000 -o <output> <input>\n" );
    H0( "            x264 --pass 2 --bitrate 1000 -o <output> <input>\n" );
Fiona Glaser's avatar
Fiona Glaser committed
257 258
    H0( "\n" );
    H0( "      Lossless:\n" );
259
    H0( "            x264 --crf 0 -o <output> <input>\n" );
Fiona Glaser's avatar
Fiona Glaser committed
260 261
    H0( "\n" );
    H0( "      Maximum PSNR at the cost of speed and visual quality:\n" );
262
    H0( "            x264 --preset placebo --tune psnr -o <output> <input>\n" );
Fiona Glaser's avatar
Fiona Glaser committed
263 264
    H0( "\n" );
    H0( "      Constant bitrate at 1000kbps with a 2 second-buffer:\n");
265
    H0( "            x264 --vbv-bufsize 2000 --bitrate 1000 -o <output> <input>\n" );
Fiona Glaser's avatar
Fiona Glaser committed
266
    H0( "\n" );
267 268
    H0( "Presets:\n" );
    H0( "\n" );
269 270
    H0( "      --profile               Force the limits of an H.264 profile [high]\n"
        "                                  Overrides all settings.\n" );
271 272
    H2( "                                  - baseline:\n"
        "                                    --no-8x8dct --bframes 0 --no-cabac\n"
273 274 275
        "                                    --cqm flat --weightp 0\n"
        "                                    No interlaced.\n"
        "                                    No lossless.\n"
276
        "                                  - main:\n"
277 278
        "                                    --no-8x8dct --cqm flat\n"
        "                                    No lossless.\n"
279
        "                                  - high:\n"
280
        "                                    No lossless.\n" );
281
        else H0( "                                  - baseline,main,high\n" );
282 283
    H0( "      --preset                Use a preset to select encoding settings [medium]\n"
        "                                  Overridden by user settings.\n" );
284
    H2( "                                  - ultrafast:\n"
285
        "                                    --no-8x8dct --aq-mode 0 --b-adapt 0\n"
286 287 288
        "                                    --bframes 0 --no-cabac --no-deblock\n"
        "                                    --no-mbtree --me dia --no-mixed-refs\n"
        "                                    --partitions none --ref 1 --scenecut 0\n"
289 290
        "                                    --subme 0 --trellis 0 --no-weightb\n"
        "                                    --weightp 0\n"
291
        "                                  - superfast:\n"
292
        "                                    --no-mbtree --me dia --no-mixed-refs\n"
293
        "                                    --partitions i8x8,i4x4 --ref 1\n"
294
        "                                    --subme 1 --trellis 0 --weightp 0\n"
295 296 297
        "                                  - veryfast:\n"
        "                                    --no-mbtree --no-mixed-refs --ref 1\n"
        "                                    --subme 2 --trellis 0 --weightp 0\n"
298
        "                                  - faster:\n"
299 300
        "                                    --no-mixed-refs --rc-lookahead 20\n"
        "                                    --ref 2 --subme 4 --weightp 1\n"
301
        "                                  - fast:\n"
302
        "                                    --rc-lookahead 30 --ref 2 --subme 6\n"
303
        "                                  - medium:\n"
304
        "                                    Default settings apply.\n"
305
        "                                  - slow:\n"
306 307
        "                                    --b-adapt 2 --direct auto --me umh\n"
        "                                    --rc-lookahead 50 --ref 5 --subme 8\n"
308
        "                                  - slower:\n"
309 310 311
        "                                    --b-adapt 2 --direct auto --me umh\n"
        "                                    --partitions all --rc-lookahead 60\n"
        "                                    --ref 8 --subme 9 --trellis 2\n"
312
        "                                  - veryslow:\n"
313
        "                                    --b-adapt 2 --bframes 8 --direct auto\n"
Fiona Glaser's avatar
Fiona Glaser committed
314
        "                                    --me umh --merange 24 --partitions all\n"
315 316
        "                                    --ref 16 --subme 10 --trellis 2\n"
        "                                    --rc-lookahead 60\n"
317
        "                                  - placebo:\n"
318 319
        "                                    --bframes 16 --b-adapt 2 --direct auto\n"
        "                                    --slow-firstpass --no-fast-pskip\n"
Fiona Glaser's avatar
Fiona Glaser committed
320
        "                                    --me tesa --merange 24 --partitions all\n"
321 322
        "                                    --rc-lookahead 60 --ref 16 --subme 10\n"
        "                                    --trellis 2\n" );
323 324
    else H0( "                                  - ultrafast,superfast,veryfast,faster,fast\n"
             "                                  - medium,slow,slower,veryslow,placebo\n" );
325 326 327 328 329 330
    H0( "      --tune                  Tune the settings for a particular type of source\n"
        "                              or situation\n"
        "                                  Overridden by user settings.\n"
        "                                  Multiple tunings are separated by commas.\n"
        "                                  Only one psy tuning can be used at a time.\n" );
    H2( "                                  - film (psy tuning):\n"
331
        "                                    --deblock -1:-1 --psy-rd <unset>:0.15\n"
332
        "                                  - animation (psy tuning):\n"
333
        "                                    --bframes {+2} --deblock 1:1\n"
334
        "                                    --psy-rd 0.4:<unset> --aq-strength 0.6\n"
335
        "                                    --ref {Double if >1 else 1}\n"
336
        "                                  - grain (psy tuning):\n"
337
        "                                    --aq-strength 0.5 --no-dct-decimate\n"
338
        "                                    --deadzone-inter 6 --deadzone-intra 6\n"
339 340 341
        "                                    --deblock -2:-2 --ipratio 1.1 \n"
        "                                    --pbratio 1.1 --psy-rd <unset>:0.25\n"
        "                                    --qcomp 0.8\n"
342 343 344
        "                                  - stillimage (psy tuning):\n"
        "                                    --aq-strength 1.2 --deblock -3:-3\n"
        "                                    --psy-rd 2.0:0.7\n"
345
        "                                  - psnr (psy tuning):\n"
346
        "                                    --aq-mode 0 --no-psy\n"
347
        "                                  - ssim (psy tuning):\n"
348 349 350 351
        "                                    --aq-mode 2 --no-psy\n"
        "                                  - fastdecode:\n"
        "                                    --no-cabac --no-deblock --no-weightb\n"
        "                                    --weightp 0\n"
352
        "                                  - zerolatency:\n"
353
        "                                    --bframes 0 --force-cfr --rc-lookahead 0\n"
354
        "                                    --sync-lookahead 0 --sliced-threads\n" );
355 356
    else H0( "                                  - psy tunings: film,animation,grain,\n"
             "                                                 stillimage,psnr,ssim\n"
357
             "                                  - other tunings: fastdecode,zerolatency\n" );
358 359 360 361
    H2( "      --slow-firstpass        Don't force these faster settings with --pass 1:\n"
        "                                  --no-8x8dct --me dia --partitions none --ref 1\n"
        "                                  --subme {2 if >2 else unchanged} --trellis 0\n" );
    else H1( "      --slow-firstpass        Don't force faster settings with --pass 1\n" );
362
    H0( "\n" );
363 364 365
    H0( "Frame-type options:\n" );
    H0( "\n" );
    H0( "  -I, --keyint <integer>      Maximum GOP size [%d]\n", defaults->i_keyint_max );
366
    H2( "  -i, --min-keyint <integer>  Minimum GOP size [auto]\n" );
Fiona Glaser's avatar
Fiona Glaser committed
367 368
    H2( "      --no-scenecut           Disable adaptive I-frame decision\n" );
    H2( "      --scenecut <integer>    How aggressively to insert extra I-frames [%d]\n", defaults->i_scenecut_threshold );
Fiona Glaser's avatar
Fiona Glaser committed
369
    H2( "      --intra-refresh         Use Periodic Intra Refresh instead of IDR frames\n" );
Fiona Glaser's avatar
Fiona Glaser committed
370
    H1( "  -b, --bframes <integer>     Number of B-frames between I and P [%d]\n", defaults->i_bframe );
Fiona Glaser's avatar
Fiona Glaser committed
371
    H1( "      --b-adapt <integer>     Adaptive B-frame decision method [%d]\n"
372 373 374 375
        "                                  Higher values may lower threading efficiency.\n"
        "                                  - 0: Disabled\n"
        "                                  - 1: Fast\n"
        "                                  - 2: Optimal (slow with high --bframes)\n", defaults->i_bframe_adaptive );
Fiona Glaser's avatar
Fiona Glaser committed
376
    H2( "      --b-bias <integer>      Influences how often B-frames are used [%d]\n", defaults->i_bframe_bias );
377 378
    H1( "      --b-pyramid <string>    Keep some B-frames as references [%s]\n"
        "                                  - none: Disabled\n"
379
        "                                  - strict: Strictly hierarchical pyramid\n"
380 381
        "                                  - normal: Non-strict (not Blu-ray compatible)\n",
        strtable_lookup( x264_b_pyramid_names, defaults->i_bframe_pyramid ) );
Fiona Glaser's avatar
Fiona Glaser committed
382 383
    H1( "      --no-cabac              Disable CABAC\n" );
    H1( "  -r, --ref <integer>         Number of reference frames [%d]\n", defaults->i_frame_reference );
384
    H1( "      --no-deblock            Disable loop filter\n" );
Fiona Glaser's avatar
Fiona Glaser committed
385
    H1( "  -f, --deblock <alpha:beta>  Loop filter parameters [%d:%d]\n",
386
                                       defaults->i_deblocking_filter_alphac0, defaults->i_deblocking_filter_beta );
Fiona Glaser's avatar
Fiona Glaser committed
387
    H2( "      --slices <integer>      Number of slices per frame; forces rectangular\n"
388
        "                              slices and is overridden by other slicing options\n" );
Fiona Glaser's avatar
Fiona Glaser committed
389 390 391
    else H1( "      --slices <integer>      Number of slices per frame\n" );
    H2( "      --slice-max-size <integer> Limit the size of each slice in bytes\n");
    H2( "      --slice-max-mbs <integer> Limit the size of each slice in macroblocks\n");
392 393
    H0( "      --tff                   Enable interlaced mode (top field first)\n" );
    H0( "      --bff                   Enable interlaced mode (bottom field first)\n" );
394
    H2( "      --constrained-intra     Enable constrained intra prediction.\n" );
395 396 397
    H0( "\n" );
    H0( "Ratecontrol:\n" );
    H0( "\n" );
Fiona Glaser's avatar
Fiona Glaser committed
398
    H1( "  -q, --qp <integer>          Force constant QP (0-51, 0=lossless)\n" );
399
    H0( "  -B, --bitrate <integer>     Set bitrate (kbit/s)\n" );
400
    H0( "      --crf <float>           Quality-based VBR (0-51, 0=lossless) [%.1f]\n", defaults->rc.f_rf_constant );
Fiona Glaser's avatar
Fiona Glaser committed
401
    H1( "      --rc-lookahead <integer> Number of frames for frametype lookahead [%d]\n", defaults->rc.i_lookahead );
402 403
    H0( "      --vbv-maxrate <integer> Max local bitrate (kbit/s) [%d]\n", defaults->rc.i_vbv_max_bitrate );
    H0( "      --vbv-bufsize <integer> Set size of the VBV buffer (kbit) [%d]\n", defaults->rc.i_vbv_buffer_size );
Fiona Glaser's avatar
Fiona Glaser committed
404
    H2( "      --vbv-init <float>      Initial VBV buffer occupancy [%.1f]\n", defaults->rc.f_vbv_buffer_init );
405 406
    H2( "      --crf-max <float>       With CRF+VBV, limit RF to this value\n"
        "                                  May cause VBV underflows!\n" );
Fiona Glaser's avatar
Fiona Glaser committed
407 408 409
    H2( "      --qpmin <integer>       Set min QP [%d]\n", defaults->rc.i_qp_min );
    H2( "      --qpmax <integer>       Set max QP [%d]\n", defaults->rc.i_qp_max );
    H2( "      --qpstep <integer>      Set max QP step [%d]\n", defaults->rc.i_qp_step );
410
    H2( "      --ratetol <float>       Tolerance of ABR ratecontrol and VBV [%.1f]\n", defaults->rc.f_rate_tolerance );
Fiona Glaser's avatar
Fiona Glaser committed
411 412 413 414
    H2( "      --ipratio <float>       QP factor between I and P [%.2f]\n", defaults->rc.f_ip_factor );
    H2( "      --pbratio <float>       QP factor between P and B [%.2f]\n", defaults->rc.f_pb_factor );
    H2( "      --chroma-qp-offset <integer>  QP difference between chroma and luma [%d]\n", defaults->analyse.i_chroma_qp_offset );
    H2( "      --aq-mode <integer>     AQ method [%d]\n"
415
        "                                  - 0: Disabled\n"
416 417
        "                                  - 1: Variance AQ (complexity mask)\n"
        "                                  - 2: Auto-variance AQ (experimental)\n", defaults->rc.i_aq_mode );
Fiona Glaser's avatar
Fiona Glaser committed
418 419 420
    H1( "      --aq-strength <float>   Reduces blocking and blurring in flat and\n"
        "                              textured areas. [%.1f]\n", defaults->rc.f_aq_strength );
    H1( "\n" );
Fiona Glaser's avatar
Fiona Glaser committed
421 422
    H0( "  -p, --pass <integer>        Enable multipass ratecontrol\n"
        "                                  - 1: First pass, creates stats file\n"
Fiona Glaser's avatar
Fiona Glaser committed
423 424 425 426 427 428 429 430 431
        "                                  - 2: Last pass, does not overwrite stats file\n" );
    H2( "                                  - 3: Nth pass, overwrites stats file\n" );
    H1( "      --stats <string>        Filename for 2 pass stats [\"%s\"]\n", defaults->rc.psz_stat_out );
    H2( "      --no-mbtree             Disable mb-tree ratecontrol.\n");
    H2( "      --qcomp <float>         QP curve compression [%.2f]\n", defaults->rc.f_qcompress );
    H2( "      --cplxblur <float>      Reduce fluctuations in QP (before curve compression) [%.1f]\n", defaults->rc.f_complexity_blur );
    H2( "      --qblur <float>         Reduce fluctuations in QP (after curve compression) [%.1f]\n", defaults->rc.f_qblur );
    H2( "      --zones <zone0>/<zone1>/...  Tweak the bitrate of regions of the video\n" );
    H2( "                              Each zone is of the form\n"
432 433 434 435
        "                                  <start frame>,<end frame>,<option>\n"
        "                                  where <option> is either\n"
        "                                      q=<integer> (force QP)\n"
        "                                  or  b=<float> (bitrate multiplier)\n" );
436
    H2( "      --qpfile <string>       Force frametypes and QPs for some or all frames\n"
437
        "                              Format of each line: framenumber frametype QP\n"
438 439
        "                              QP of -1 lets x264 choose. Frametypes: I,i,P,B,b.\n"
        "                              QPs are restricted by qpmin/qpmax.\n" );
Fiona Glaser's avatar
Fiona Glaser committed
440 441 442 443
    H1( "\n" );
    H1( "Analysis:\n" );
    H1( "\n" );
    H1( "  -A, --partitions <string>   Partitions to consider [\"p8x8,b8x8,i8x8,i4x4\"]\n"
444 445 446
        "                                  - p8x8, p4x4, b8x8, i8x8, i4x4\n"
        "                                  - none, all\n"
        "                                  (p4x4 requires p8x8. i8x8 requires --8x8dct.)\n" );
Fiona Glaser's avatar
Fiona Glaser committed
447
    H1( "      --direct <string>       Direct MV prediction mode [\"%s\"]\n"
448 449
        "                                  - none, spatial, temporal, auto\n",
                                       strtable_lookup( x264_direct_pred_names, defaults->analyse.i_direct_mv_pred ) );
Fiona Glaser's avatar
Fiona Glaser committed
450
    H2( "      --no-weightb            Disable weighted prediction for B-frames\n" );
Fiona Glaser's avatar
Fiona Glaser committed
451
    H1( "      --weightp <integer>     Weighted prediction for P-frames [%d]\n"
Fiona Glaser's avatar
Fiona Glaser committed
452 453 454
        "                                  - 0: Disabled\n"
        "                                  - 1: Blind offset\n"
        "                                  - 2: Smart analysis\n", defaults->analyse.i_weighted_pred );
Fiona Glaser's avatar
Fiona Glaser committed
455
    H1( "      --me <string>           Integer pixel motion estimation method [\"%s\"]\n",
456
                                       strtable_lookup( x264_motion_est_names, defaults->analyse.i_me_method ) );
Fiona Glaser's avatar
Fiona Glaser committed
457
    H2( "                                  - dia: diamond search, radius 1 (fast)\n"
458 459
        "                                  - hex: hexagonal search, radius 2\n"
        "                                  - umh: uneven multi-hexagon search\n"
460 461
        "                                  - esa: exhaustive search\n"
        "                                  - tesa: hadamard exhaustive search (slow)\n" );
Fiona Glaser's avatar
Fiona Glaser committed
462 463 464 465 466 467
    else H1( "                                  - dia, hex, umh\n" );
    H2( "      --merange <integer>     Maximum motion vector search range [%d]\n", defaults->analyse.i_me_range );
    H2( "      --mvrange <integer>     Maximum motion vector length [-1 (auto)]\n" );
    H2( "      --mvrange-thread <int>  Minimum buffer between threads [-1 (auto)]\n" );
    H1( "  -m, --subme <integer>       Subpixel motion estimation and mode decision [%d]\n", defaults->analyse.i_subpel_refine );
    H2( "                                  - 0: fullpel only (not recommended)\n"
468
        "                                  - 1: SAD mode decision, one qpel iteration\n"
469 470 471 472 473
        "                                  - 2: SATD mode decision\n"
        "                                  - 3-5: Progressively more qpel\n"
        "                                  - 6: RD mode decision for I/P-frames\n"
        "                                  - 7: RD mode decision for all frames\n"
        "                                  - 8: RD refinement for I/P-frames\n"
474 475
        "                                  - 9: RD refinement for all frames\n"
        "                                  - 10: QP-RD - requires trellis=2, aq-mode>0\n" );
Fiona Glaser's avatar
Fiona Glaser committed
476 477
    else H1( "                                  decision quality: 1=fast, 10=best.\n"  );
    H1( "      --psy-rd                Strength of psychovisual optimization [\"%.1f:%.1f\"]\n"
478
        "                                  #1: RD (requires subme>=6)\n"
479
        "                                  #2: Trellis (requires trellis, experimental)\n",
Loren Merritt's avatar
Loren Merritt committed
480
                                       defaults->analyse.f_psy_rd, defaults->analyse.f_psy_trellis );
Fiona Glaser's avatar
Fiona Glaser committed
481
    H2( "      --no-psy                Disable all visual optimizations that worsen\n"
482
        "                              both PSNR and SSIM.\n" );
Fiona Glaser's avatar
Fiona Glaser committed
483 484 485 486
    H2( "      --no-mixed-refs         Don't decide references on a per partition basis\n" );
    H2( "      --no-chroma-me          Ignore chroma in motion estimation\n" );
    H1( "      --no-8x8dct             Disable adaptive spatial transform size\n" );
    H1( "  -t, --trellis <integer>     Trellis RD quantization. Requires CABAC. [%d]\n"
487 488 489
        "                                  - 0: disabled\n"
        "                                  - 1: enabled only on the final encode of a MB\n"
        "                                  - 2: enabled on all mode decisions\n", defaults->analyse.i_trellis );
Fiona Glaser's avatar
Fiona Glaser committed
490 491 492 493 494 495 496 497
    H2( "      --no-fast-pskip         Disables early SKIP detection on P-frames\n" );
    H2( "      --no-dct-decimate       Disables coefficient thresholding on P-frames\n" );
    H1( "      --nr <integer>          Noise reduction [%d]\n", defaults->analyse.i_noise_reduction );
    H2( "\n" );
    H2( "      --deadzone-inter <int>  Set the size of the inter luma quantization deadzone [%d]\n", defaults->analyse.i_luma_deadzone[0] );
    H2( "      --deadzone-intra <int>  Set the size of the intra luma quantization deadzone [%d]\n", defaults->analyse.i_luma_deadzone[1] );
    H2( "                                  Deadzones should be in the range 0 - 32.\n" );
    H2( "      --cqm <string>          Preset quant matrices [\"flat\"]\n"
498
        "                                  - jvt, flat\n" );
Fiona Glaser's avatar
Fiona Glaser committed
499 500 501
    H1( "      --cqmfile <string>      Read custom quant matrices from a JM-compatible file\n" );
    H2( "                                  Overrides any other --cqm* options.\n" );
    H2( "      --cqm4 <list>           Set all 4x4 quant matrices\n"
502
        "                                  Takes a comma-separated list of 16 integers.\n" );
Fiona Glaser's avatar
Fiona Glaser committed
503
    H2( "      --cqm8 <list>           Set all 8x8 quant matrices\n"
504
        "                                  Takes a comma-separated list of 64 integers.\n" );
Fiona Glaser's avatar
Fiona Glaser committed
505
    H2( "      --cqm4i, --cqm4p, --cqm8i, --cqm8p\n"
506
        "                              Set both luma and chroma quant matrices\n" );
Fiona Glaser's avatar
Fiona Glaser committed
507
    H2( "      --cqm4iy, --cqm4ic, --cqm4py, --cqm4pc\n"
508
        "                              Set individual quant matrices\n" );
Fiona Glaser's avatar
Fiona Glaser committed
509 510 511 512 513 514
    H2( "\n" );
    H2( "Video Usability Info (Annex E):\n" );
    H2( "The VUI settings are not used by the encoder but are merely suggestions to\n" );
    H2( "the playback equipment. See doc/vui.txt for details. Use at your own risk.\n" );
    H2( "\n" );
    H2( "      --overscan <string>     Specify crop overscan setting [\"%s\"]\n"
515 516
        "                                  - undef, show, crop\n",
                                       strtable_lookup( x264_overscan_names, defaults->vui.i_overscan ) );
Fiona Glaser's avatar
Fiona Glaser committed
517
    H2( "      --videoformat <string>  Specify video format [\"%s\"]\n"
518 519
        "                                  - component, pal, ntsc, secam, mac, undef\n",
                                       strtable_lookup( x264_vidformat_names, defaults->vui.i_vidformat ) );
Fiona Glaser's avatar
Fiona Glaser committed
520
    H2( "      --fullrange <string>    Specify full range samples setting [\"%s\"]\n"
521 522
        "                                  - off, on\n",
                                       strtable_lookup( x264_fullrange_names, defaults->vui.b_fullrange ) );
Fiona Glaser's avatar
Fiona Glaser committed
523
    H2( "      --colorprim <string>    Specify color primaries [\"%s\"]\n"
524 525 526
        "                                  - undef, bt709, bt470m, bt470bg\n"
        "                                    smpte170m, smpte240m, film\n",
                                       strtable_lookup( x264_colorprim_names, defaults->vui.i_colorprim ) );
Fiona Glaser's avatar
Fiona Glaser committed
527
    H2( "      --transfer <string>     Specify transfer characteristics [\"%s\"]\n"
528 529 530
        "                                  - undef, bt709, bt470m, bt470bg, linear,\n"
        "                                    log100, log316, smpte170m, smpte240m\n",
                                       strtable_lookup( x264_transfer_names, defaults->vui.i_transfer ) );
Fiona Glaser's avatar
Fiona Glaser committed
531
    H2( "      --colormatrix <string>  Specify color matrix setting [\"%s\"]\n"
532 533 534
        "                                  - undef, bt709, fcc, bt470bg\n"
        "                                    smpte170m, smpte240m, GBR, YCgCo\n",
                                       strtable_lookup( x264_colmatrix_names, defaults->vui.i_colmatrix ) );
Fiona Glaser's avatar
Fiona Glaser committed
535
    H2( "      --chromaloc <integer>   Specify chroma sample location (0 to 5) [%d]\n",
536
                                       defaults->vui.i_chroma_loc );
537 538 539 540 541

    H2( "      --nal-hrd <string>      Signal HRD information (requires vbv-bufsize)\n"
        "                                  - none, vbr, cbr (cbr not allowed in .mp4)\n" );
    H2( "      --pic-struct            Force pic_struct in Picture Timing SEI\n" );

542 543 544 545
    H0( "\n" );
    H0( "Input/Output:\n" );
    H0( "\n" );
    H0( "  -o, --output                Specify output file\n" );
546 547 548 549 550
    H1( "      --muxer <string>        Specify output container format [\"%s\"]\n"
        "                                  - %s\n", muxer_names[0], stringify_names( buf, muxer_names ) );
    H1( "      --demuxer <string>      Specify input container format [\"%s\"]\n"
        "                                  - %s\n", demuxer_names[0], stringify_names( buf, demuxer_names ) );
    H1( "      --index <string>        Filename for input index file\n" );
551 552 553 554 555
    H0( "      --sar width:height      Specify Sample Aspect Ratio\n" );
    H0( "      --fps <float|rational>  Specify framerate\n" );
    H0( "      --seek <integer>        First frame to encode\n" );
    H0( "      --frames <integer>      Maximum number of frames to encode\n" );
    H0( "      --level <string>        Specify level (as defined by Annex A)\n" );
Fiona Glaser's avatar
Fiona Glaser committed
556 557 558
    H1( "\n" );
    H1( "  -v, --verbose               Print stats for each frame\n" );
    H1( "      --no-progress           Don't show the progress indicator while encoding\n" );
559
    H0( "      --quiet                 Quiet Mode\n" );
Fiona Glaser's avatar
Fiona Glaser committed
560 561 562
    H1( "      --psnr                  Enable PSNR computation\n" );
    H1( "      --ssim                  Enable SSIM computation\n" );
    H1( "      --threads <integer>     Force a specific number of threads\n" );
563
    H2( "      --sliced-threads        Low-latency but lower-efficiency threading\n" );
Fiona Glaser's avatar
Fiona Glaser committed
564 565 566 567 568 569 570 571 572
    H2( "      --thread-input          Run Avisynth in its own thread\n" );
    H2( "      --sync-lookahead <integer> Number of buffer frames for threaded lookahead\n" );
    H2( "      --non-deterministic     Slightly improve quality of SMP, at the cost of repeatability\n" );
    H2( "      --asm <integer>         Override CPU detection\n" );
    H2( "      --no-asm                Disable all CPU optimizations\n" );
    H2( "      --visualize             Show MB types overlayed on the encoded video\n" );
    H2( "      --dump-yuv <string>     Save reconstructed frames\n" );
    H2( "      --sps-id <integer>      Set SPS and PPS id numbers [%d]\n", defaults->i_sps_id );
    H2( "      --aud                   Use access unit delimiters\n" );
573
    H2( "      --force-cfr             Force constant framerate timestamp generation\n" );
Yusuke Nakamura's avatar
Yusuke Nakamura committed
574 575 576 577 578
    H2( "      --tcfile-in <string>    Force timestamp generation with timecode file\n" );
    H2( "      --tcfile-out <string>   Output timecode v2 file from input timestamps\n" );
    H2( "      --timebase <int/int>    Specify timebase numerator and denominator\n"
        "                 <integer>    Specify timebase numerator for input timecode file\n"
        "                              or specify timebase denominator for other input\n" );
579 580
    H0( "      --pulldown <string>     Use soft pulldown to change frame rate\n"
        "                                  - none, 22, 32, 64, double, triple, euro (requires cfr input)\n" );
581
    H0( "\n" );
582 583
}

584 585 586 587 588 589 590 591 592 593 594 595
#define OPT_FRAMES 256
#define OPT_SEEK 257
#define OPT_QPFILE 258
#define OPT_THREAD_INPUT 259
#define OPT_QUIET 260
#define OPT_NOPROGRESS 261
#define OPT_VISUALIZE 262
#define OPT_LONGHELP 263
#define OPT_PROFILE 264
#define OPT_PRESET 265
#define OPT_TUNE 266
#define OPT_SLOWFIRSTPASS 267
Fiona Glaser's avatar
Fiona Glaser committed
596
#define OPT_FULLHELP 268
597
#define OPT_FPS 269
598 599 600 601
#define OPT_MUXER 270
#define OPT_DEMUXER 271
#define OPT_INDEX 272
#define OPT_INTERLACED 273
Yusuke Nakamura's avatar
Yusuke Nakamura committed
602 603 604
#define OPT_TCFILE_IN 274
#define OPT_TCFILE_OUT 275
#define OPT_TIMEBASE 276
605
#define OPT_PULLDOWN 277
606 607 608 609 610 611

static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
static struct option long_options[] =
{
    { "help",              no_argument, NULL, 'h' },
    { "longhelp",          no_argument, NULL, OPT_LONGHELP },
Fiona Glaser's avatar
Fiona Glaser committed
612
    { "fullhelp",          no_argument, NULL, OPT_FULLHELP },
613 614 615 616 617 618 619 620 621 622
    { "version",           no_argument, NULL, 'V' },
    { "profile",     required_argument, NULL, OPT_PROFILE },
    { "preset",      required_argument, NULL, OPT_PRESET },
    { "tune",        required_argument, NULL, OPT_TUNE },
    { "slow-firstpass",    no_argument, NULL, OPT_SLOWFIRSTPASS },
    { "bitrate",     required_argument, NULL, 'B' },
    { "bframes",     required_argument, NULL, 'b' },
    { "b-adapt",     required_argument, NULL, 0 },
    { "no-b-adapt",        no_argument, NULL, 0 },
    { "b-bias",      required_argument, NULL, 0 },
623
    { "b-pyramid",   required_argument, NULL, 0 },
624 625
    { "min-keyint",  required_argument, NULL, 'i' },
    { "keyint",      required_argument, NULL, 'I' },
Fiona Glaser's avatar
Fiona Glaser committed
626
    { "intra-refresh",     no_argument, NULL, 0 },
627 628 629 630 631 632
    { "scenecut",    required_argument, NULL, 0 },
    { "no-scenecut",       no_argument, NULL, 0 },
    { "nf",                no_argument, NULL, 0 },
    { "no-deblock",        no_argument, NULL, 0 },
    { "filter",      required_argument, NULL, 0 },
    { "deblock",     required_argument, NULL, 'f' },
633
    { "interlaced",        no_argument, NULL, OPT_INTERLACED },
634 635
    { "tff",               no_argument, NULL, OPT_INTERLACED },
    { "bff",               no_argument, NULL, OPT_INTERLACED },
636
    { "no-interlaced",     no_argument, NULL, OPT_INTERLACED },
637
    { "constrained-intra", no_argument, NULL, 0 },
638 639 640 641 642 643 644
    { "cabac",             no_argument, NULL, 0 },
    { "no-cabac",          no_argument, NULL, 0 },
    { "qp",          required_argument, NULL, 'q' },
    { "qpmin",       required_argument, NULL, 0 },
    { "qpmax",       required_argument, NULL, 0 },
    { "qpstep",      required_argument, NULL, 0 },
    { "crf",         required_argument, NULL, 0 },
645
    { "rc-lookahead",required_argument, NULL, 0 },
646 647 648 649
    { "ref",         required_argument, NULL, 'r' },
    { "asm",         required_argument, NULL, 0 },
    { "no-asm",            no_argument, NULL, 0 },
    { "sar",         required_argument, NULL, 0 },
650
    { "fps",         required_argument, NULL, OPT_FPS },
651 652 653
    { "frames",      required_argument, NULL, OPT_FRAMES },
    { "seek",        required_argument, NULL, OPT_SEEK },
    { "output",      required_argument, NULL, 'o' },
654 655 656 657 658
    { "muxer",       required_argument, NULL, OPT_MUXER },
    { "demuxer",     required_argument, NULL, OPT_DEMUXER },
    { "stdout",      required_argument, NULL, OPT_MUXER },
    { "stdin",       required_argument, NULL, OPT_DEMUXER },
    { "index",       required_argument, NULL, OPT_INDEX },
659 660 661 662 663
    { "analyse",     required_argument, NULL, 0 },
    { "partitions",  required_argument, NULL, 'A' },
    { "direct",      required_argument, NULL, 0 },
    { "weightb",           no_argument, NULL, 'w' },
    { "no-weightb",        no_argument, NULL, 0 },
664
    { "weightp",     required_argument, NULL, 0 },
665 666 667 668 669 670
    { "me",          required_argument, NULL, 0 },
    { "merange",     required_argument, NULL, 0 },
    { "mvrange",     required_argument, NULL, 0 },
    { "mvrange-thread", required_argument, NULL, 0 },
    { "subme",       required_argument, NULL, 'm' },
    { "psy-rd",      required_argument, NULL, 0 },
671 672
    { "no-psy",            no_argument, NULL, 0 },
    { "psy",               no_argument, NULL, 0 },
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
    { "mixed-refs",        no_argument, NULL, 0 },
    { "no-mixed-refs",     no_argument, NULL, 0 },
    { "no-chroma-me",      no_argument, NULL, 0 },
    { "8x8dct",            no_argument, NULL, 0 },
    { "no-8x8dct",         no_argument, NULL, 0 },
    { "trellis",     required_argument, NULL, 't' },
    { "fast-pskip",        no_argument, NULL, 0 },
    { "no-fast-pskip",     no_argument, NULL, 0 },
    { "no-dct-decimate",   no_argument, NULL, 0 },
    { "aq-strength", required_argument, NULL, 0 },
    { "aq-mode",     required_argument, NULL, 0 },
    { "deadzone-inter", required_argument, NULL, '0' },
    { "deadzone-intra", required_argument, NULL, '0' },
    { "level",       required_argument, NULL, 0 },
    { "ratetol",     required_argument, NULL, 0 },
    { "vbv-maxrate", required_argument, NULL, 0 },
    { "vbv-bufsize", required_argument, NULL, 0 },
690 691
    { "vbv-init",    required_argument, NULL, 0 },
    { "crf-max",     required_argument, NULL, 0 },
692 693 694 695 696 697
    { "ipratio",     required_argument, NULL, 0 },
    { "pbratio",     required_argument, NULL, 0 },
    { "chroma-qp-offset", required_argument, NULL, 0 },
    { "pass",        required_argument, NULL, 'p' },
    { "stats",       required_argument, NULL, 0 },
    { "qcomp",       required_argument, NULL, 0 },
698 699
    { "mbtree",            no_argument, NULL, 0 },
    { "no-mbtree",         no_argument, NULL, 0 },
700 701 702 703 704
    { "qblur",       required_argument, NULL, 0 },
    { "cplxblur",    required_argument, NULL, 0 },
    { "zones",       required_argument, NULL, 0 },
    { "qpfile",      required_argument, NULL, OPT_QPFILE },
    { "threads",     required_argument, NULL, 0 },
705 706
    { "sliced-threads",    no_argument, NULL, 0 },
    { "no-sliced-threads", no_argument, NULL, 0 },
707 708 709
    { "slice-max-size",    required_argument, NULL, 0 },
    { "slice-max-mbs",     required_argument, NULL, 0 },
    { "slices",            required_argument, NULL, 0 },
710
    { "thread-input",      no_argument, NULL, OPT_THREAD_INPUT },
Steven Walters's avatar
Steven Walters committed
711
    { "sync-lookahead",    required_argument, NULL, 0 },
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 738 739 740 741
    { "non-deterministic", no_argument, NULL, 0 },
    { "psnr",              no_argument, NULL, 0 },
    { "ssim",              no_argument, NULL, 0 },
    { "quiet",             no_argument, NULL, OPT_QUIET },
    { "verbose",           no_argument, NULL, 'v' },
    { "no-progress",       no_argument, NULL, OPT_NOPROGRESS },
    { "visualize",         no_argument, NULL, OPT_VISUALIZE },
    { "dump-yuv",    required_argument, NULL, 0 },
    { "sps-id",      required_argument, NULL, 0 },
    { "aud",               no_argument, NULL, 0 },
    { "nr",          required_argument, NULL, 0 },
    { "cqm",         required_argument, NULL, 0 },
    { "cqmfile",     required_argument, NULL, 0 },
    { "cqm4",        required_argument, NULL, 0 },
    { "cqm4i",       required_argument, NULL, 0 },
    { "cqm4iy",      required_argument, NULL, 0 },
    { "cqm4ic",      required_argument, NULL, 0 },
    { "cqm4p",       required_argument, NULL, 0 },
    { "cqm4py",      required_argument, NULL, 0 },
    { "cqm4pc",      required_argument, NULL, 0 },
    { "cqm8",        required_argument, NULL, 0 },
    { "cqm8i",       required_argument, NULL, 0 },
    { "cqm8p",       required_argument, NULL, 0 },
    { "overscan",    required_argument, NULL, 0 },
    { "videoformat", required_argument, NULL, 0 },
    { "fullrange",   required_argument, NULL, 0 },
    { "colorprim",   required_argument, NULL, 0 },
    { "transfer",    required_argument, NULL, 0 },
    { "colormatrix", required_argument, NULL, 0 },
    { "chromaloc",   required_argument, NULL, 0 },
742
    { "force-cfr",         no_argument, NULL, 0 },
Yusuke Nakamura's avatar
Yusuke Nakamura committed
743 744 745
    { "tcfile-in",   required_argument, NULL, OPT_TCFILE_IN },
    { "tcfile-out",  required_argument, NULL, OPT_TCFILE_OUT },
    { "timebase",    required_argument, NULL, OPT_TIMEBASE },
746 747 748
    { "pic-struct",        no_argument, NULL, 0 },
    { "nal-hrd",     required_argument, NULL, 0 },
    { "pulldown",    required_argument, NULL, OPT_PULLDOWN },
749 750 751
    {0, 0, 0, 0}
};

752
static int select_output( const char *muxer, char *filename, x264_param_t *param )
753
{
754
    const char *ext = get_filename_extension( filename );
755 756
    if( !strcmp( filename, "-" ) || strcasecmp( muxer, "auto" ) )
        ext = muxer;
757

Fiona Glaser's avatar
Fiona Glaser committed
758
    if( !strcasecmp( ext, "mp4" ) )
759 760
    {
#ifdef MP4_OUTPUT
761 762
        output = mp4_output;
        param->b_annexb = 0;
763
        param->b_dts_compress = 0;
764
        param->b_repeat_headers = 0;
765 766 767 768 769
        if( param->i_nal_hrd == X264_NAL_HRD_CBR )
        {
            fprintf( stderr, "x264 [warning]: cbr nal-hrd is not compatible with mp4\n" );
            param->i_nal_hrd = X264_NAL_HRD_VBR;
        }
770 771 772 773 774
#else
        fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
        return -1;
#endif
    }
775
    else if( !strcasecmp( ext, "mkv" ) )
776 777 778
    {
        output = mkv_output;
        param->b_annexb = 0;
779
        param->b_dts_compress = 0;
780 781
        param->b_repeat_headers = 0;
    }
782
    else if( !strcasecmp( ext, "flv" ) )
Kieran Kunhya's avatar
Kieran Kunhya committed
783 784 785
    {
        output = flv_output;
        param->b_annexb = 0;
786
        param->b_dts_compress = 1;
787
        param->b_repeat_headers = 0;
Kieran Kunhya's avatar
Kieran Kunhya committed
788
    }
789 790 791 792 793
    else
        output = raw_output;
    return 0;
}

794 795
static int select_input( const char *demuxer, char *used_demuxer, char *filename,
                         hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
796
{
797
    const char *ext = get_filename_extension( filename );
798 799 800 801 802 803 804
    int b_regular = strcmp( filename, "-" );
    int b_auto = !strcasecmp( demuxer, "auto" );
    if( !b_regular && b_auto )
        ext = "yuv";
    if( b_regular )
    {
        FILE *f = fopen( filename, "r" );
805
        if( f )
806
        {
807 808
            b_regular = x264_is_regular_file( f );
            fclose( f );
809 810 811
        }
    }
    const char *module = b_auto ? ext : demuxer;
812

813
    if( !strcasecmp( module, "avs" ) || !strcasecmp( ext, "d2v" ) || !strcasecmp( ext, "dga" ) )
814
    {
815
#ifdef AVS_INPUT
816
        input = avs_input;
817
        module = "avs";
818
#else
819
        fprintf( stderr, "x264 [error]: not compiled with AVS input support\n" );
820 821 822
        return -1;
#endif
    }
823
    else if( !strcasecmp( module, "y4m" ) )
824
        input = y4m_input;
825 826 827
    else if( !strcasecmp( module, "yuv" ) )
        input = yuv_input;
    else
828
    {
829 830 831
#ifdef FFMS_INPUT
        if( b_regular && (b_auto || !strcasecmp( demuxer, "ffms" )) &&
            !ffms_input.open_file( filename, p_handle, info, opt ) )
832
        {
833 834 835
            module = "ffms";
            b_auto = 0;
            input = ffms_input;
836
        }
837 838 839
#endif
#ifdef LAVF_INPUT
        if( (b_auto || !strcasecmp( demuxer, "lavf" )) &&
840
            !lavf_input.open_file( filename, p_handle, info, opt ) )
841
        {
842 843 844
            module = "lavf";
            b_auto = 0;
            input = lavf_input;
845
        }
846 847 848 849
#endif
#ifdef AVS_INPUT
        if( b_regular && (b_auto || !strcasecmp( demuxer, "avs" )) &&
            !avs_input.open_file( filename, p_handle, info, opt ) )
850
        {
851 852 853
            module = "avs";
            b_auto = 0;
            input = avs_input;
854
        }
855
#endif
856 857 858 859 860 861 862 863 864 865 866 867
        if( b_auto && !yuv_input.open_file( filename, p_handle, info, opt ) )
        {
            module = "yuv";
            b_auto = 0;
            input = yuv_input;
        }

        if( !(*p_handle) )
        {
            fprintf( stderr, "x264 [error]: could not open input file `%s' via any method!\n", filename );
            return -1;
        }
868
    }
869
    strcpy( used_demuxer, module );
870 871 872 873

    return 0;
}

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
static int parse_enum_name( const char *arg, const char * const *names, const char **dst )
{
    for( int i = 0; names[i]; i++ )
        if( !strcasecmp( arg, names[i] ) )
        {
            *dst = names[i];
            return 0;
        }
    return -1;
}

static int parse_enum_value( const char *arg, const char * const *names, int *dst )
{
    for( int i = 0; names[i]; i++ )
        if( !strcasecmp( arg, names[i] ) )
        {
            *dst = i;
            return 0;
        }
    return -1;
}

896 897 898
/*****************************************************************************
 * Parse:
 *****************************************************************************/
899
static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
900
{
901
    char *input_filename = NULL;
902
    const char *demuxer = demuxer_names[0];
903
    char *output_filename = NULL;
904
    const char *muxer = muxer_names[0];
Yusuke Nakamura's avatar
Yusuke Nakamura committed
905
    char *tcfile_name = NULL;
906
    x264_param_t defaults;
907
    char *profile = NULL;
908
    int b_thread_input = 0;
909 910
    int b_turbo = 1;
    int b_user_ref = 0;
911
    int b_user_fps = 0;
912 913
    int b_user_interlaced = 0;
    cli_input_opt_t input_opt;
914 915
    char *preset = NULL;
    char *tune = NULL;
916

917 918
    x264_param_default( &defaults );

Loren Merritt's avatar
Loren Merritt committed
919
    memset( opt, 0, sizeof(cli_opt_t) );
920
    memset( &input_opt, 0, sizeof(cli_input_opt_t) );
921
    opt->b_progress = 1;
922

923 924 925 926 927 928 929
    /* Presets are applied before all other options. */
    for( optind = 0;; )
    {
        int c = getopt_long( argc, argv, short_options, long_options, NULL );
        if( c == -1 )
            break;
        if( c == OPT_PRESET )
930
            preset = optarg;
931
        if( c == OPT_TUNE )
932
            tune = optarg;
933 934 935 936
        else if( c == '?' )
            return -1;
    }

Fiona Glaser's avatar
Fiona Glaser committed
937
    if( preset && !strcasecmp( preset, "placebo" ) )
Fiona Glaser's avatar
Fiona Glaser committed
938 939
        b_turbo = 0;

940 941
    if( x264_param_default_preset( param, preset, tune ) < 0 )
        return -1;
942

943
    /* Parse command line options */
944
    for( optind = 0;; )
945
    {
Loren Merritt's avatar
Loren Merritt committed
946
        int b_error = 0;
947 948
        int long_options_index = -1;

949
        int c = getopt_long( argc, argv, short_options, long_options, &long_options_index );
950 951 952 953 954 955 956 957 958

        if( c == -1 )
        {
            break;
        }

        switch( c )
        {
            case 'h':
959 960 961 962 963
                Help( &defaults, 0 );
                exit(0);
            case OPT_LONGHELP:
                Help( &defaults, 1 );
                exit(0);
Fiona Glaser's avatar
Fiona Glaser committed
964 965 966
            case OPT_FULLHELP:
                Help( &defaults, 2 );
                exit(0);
967 968 969 970 971
            case 'V':
#ifdef X264_POINTVER
                printf( "x264 "X264_POINTVER"\n" );
#else
                printf( "x264 0.%d.X\n", X264_BUILD );
972 973 974 975 976 977
#endif
                printf( "built on " __DATE__ ", " );
#ifdef __GNUC__
                printf( "gcc: " __VERSION__ "\n" );
#else
                printf( "using a non-gcc compiler\n" );
978 979
#endif
                exit(0);
980
            case OPT_FRAMES:
981
                param->i_frame_total = X264_MAX( atoi( optarg ), 0 );
Loren Merritt's avatar
Loren Merritt committed
982 983
                break;
            case OPT_SEEK:
984
                opt->i_seek = input_opt.seek = X264_MAX( atoi( optarg ), 0 );
985
                break;
Loren Merritt's avatar
Loren Merritt committed
986
            case 'o':
987 988
                output_filename = optarg;
                break;
989
            case OPT_MUXER:
990
                if( parse_enum_name( optarg, muxer_names, &muxer ) < 0 )
991
                    return -1;
992
                break;
993
            case OPT_DEMUXER:
994
                if( parse_enum_name( optarg, demuxer_names, &demuxer ) < 0 )
995
                    return -1;
996 997 998
                break;
            case OPT_INDEX:
                input_opt.index = optarg;
999
                break;
1000
            case OPT_QPFILE:
1001
                opt->qpfile = fopen( optarg, "rb" );
1002 1003
                if( !opt->qpfile )
                {
1004
                    fprintf( stderr, "x264 [error]: can't open qpfile `%s'\n", optarg );
1005 1006
                    return -1;
                }
1007 1008 1009 1010 1011 1012
                else if( !x264_is_regular_file( opt->qpfile ) )
                {
                    fprintf( stderr, "x264 [error]: qpfile incompatible with non-regular file `%s'\n", optarg );
                    fclose( opt->qpfile );
                    return -1;
                }
1013
                break;
1014 1015 1016
            case OPT_THREAD_INPUT:
                b_thread_input = 1;
                break;
1017 1018 1019
            case OPT_QUIET:
                param->i_log_level = X264_LOG_NONE;
                break;
1020 1021 1022
            case 'v':
                param->i_log_level = X264_LOG_DEBUG;
                break;
1023 1024
            case OPT_NOPROGRESS:
                opt->b_progress = 0;
Loren Merritt's avatar
Loren Merritt committed
1025
                break;
Loren Merritt's avatar
Loren Merritt committed
1026
            case OPT_VISUALIZE:
1027
#ifdef HAVE_VISUALIZE
Loren Merritt's avatar
Loren Merritt committed
1028
                param->b_visualize = 1;
Loren Merritt's avatar
Loren Merritt committed
1029
                b_exit_on_ctrl_c = 1;
Loren Merritt's avatar
Loren Merritt committed
1030
#else
1031
                fprintf( stderr, "x264 [warning]: not compiled with visualization support\n" );
Loren Merritt's avatar
Loren Merritt committed
1032
#endif
Loren Merritt's avatar
Loren Merritt committed
1033
                break;
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
            case OPT_TUNE:
            case OPT_PRESET:
                break;
            case OPT_PROFILE:
                profile = optarg;
                break;
            case OPT_SLOWFIRSTPASS:
                b_turbo = 0;
                break;
            case 'r':
                b_user_ref = 1;
                goto generic_option;
1046 1047
            case OPT_FPS:
                b_user_fps = 1;
Fiona Glaser's avatar
Fiona Glaser committed
1048
                param->b_vfr_input = 0;
1049
                goto generic_option;
1050 1051 1052
            case OPT_INTERLACED:
                b_user_interlaced = 1;
                goto generic_option;
Yusuke Nakamura's avatar
Yusuke Nakamura committed
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
            case OPT_TCFILE_IN:
                tcfile_name = optarg;
                break;
            case OPT_TCFILE_OUT:
                opt->tcfile_out = fopen( optarg, "wb" );
                if( !opt->tcfile_out )
                {
                    fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg );
                    return -1;
                }
                break;
            case OPT_TIMEBASE:
                input_opt.timebase = optarg;
                break;
1067
            case OPT_PULLDOWN:
1068
                if( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ) < 0 )
1069 1070
                    return -1;
                break;
1071
            default:
1072
generic_option:
1073 1074
            {
                if( long_options_index < 0 )
Loren Merritt's avatar
Loren Merritt committed
1075
                {
1076
                    for( int i = 0; long_options[i].name; i++ )
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
                        if( long_options[i].val == c )
                        {
                            long_options_index = i;
                            break;
                        }
                    if( long_options_index < 0 )
                    {
                        /* getopt_long already printed an error message */
                        return -1;
                    }
Loren Merritt's avatar
Loren Merritt committed
1087
                }
1088

1089
                b_error |= x264_param_parse( param, long_options[long_options_index].name, optarg );
1090
            }
1091
        }
Loren Merritt's avatar
Loren Merritt committed
1092 1093 1094

        if( b_error )
        {
1095 1096
            const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind-2];
            fprintf( stderr, "x264 [error]: invalid argument: %s = %s\n", name, optarg );
Loren Merritt's avatar
Loren Merritt committed
1097 1098
            return -1;
        }
1099 1100
    }

1101 1102 1103
    /* If first pass mode is used, apply faster settings. */
    if( b_turbo )
        x264_param_apply_fastfirstpass( param );
1104 1105

    /* Apply profile restrictions. */
1106 1107
    if( x264_param_apply_profile( param, profile ) < 0 )
        return -1;
1108

1109
    /* Get the file name */
1110
    if( optind > argc - 1 || !output_filename )
1111
    {
1112 1113
        fprintf( stderr, "x264 [error]: No %s file. Run x264 --help for a list of options.\n",
                 optind > argc - 1 ? "input" : "output" );
1114 1115
        return -1;
    }
1116

1117
    if( select_output( muxer, output_filename, param ) )
1118 1119
        return -1;
    if( output.open_file( output_filename, &opt->hout ) )
1120
    {
1121 1122
        fprintf( stderr, "x264 [error]: could not open output file `%s'\n", output_filename );
        return -1;
1123
    }
Loren Merritt's avatar
Loren Merritt committed
1124

1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
    input_filename = argv[optind++];
    input_opt.resolution = optind < argc ? argv[optind++] : NULL;
    video_info_t info = {0};
    char demuxername[5];

    /* set info flags to param flags to be overwritten by demuxer as necessary. */
    info.csp        = param->i_csp;
    info.fps_num    = param->i_fps_num;
    info.fps_den    = param->i_fps_den;
    info.interlaced = param->b_interlaced;
    info.sar_width  = param->vui.i_sar_width;
    info.sar_height = param->vui.i_sar_height;
1137
    info.tff        = param->b_tff;
1138 1139 1140
    info.vfr        = param->b_vfr_input;

    if( select_input( demuxer, demuxername, input_filename, &opt->hin, &info, &input_opt ) )
1141
        return -1;
1142

1143
    if( !opt->hin && input.open_file( input_filename, &opt->hin, &info, &input_opt ) )
1144
    {
1145 1146 1147
        fprintf( stderr, "x264 [error]: could not open input file `%s'\n", input_filename );
        return -1;
    }
1148

1149 1150 1151 1152 1153 1154 1155
    x264_reduce_fraction( &info.sar_width, &info.sar_height );
    x264_reduce_fraction( &info.fps_num, &info.fps_den );
    if( param->i_log_level >= X264_LOG_INFO )
        fprintf( stderr, "%s [info]: %dx%d%c %d:%d @ %d/%d fps (%cfr)\n", demuxername, info.width,
                 info.height, info.interlaced ? 'i' : 'p', info.sar_width, info.sar_height,
                 info.fps_num, info.fps_den, info.vfr ? 'v' : 'c' );

Yusuke Nakamura's avatar
Yusuke Nakamura committed
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
    if( tcfile_name )
    {
        if( b_user_fps )
        {
            fprintf( stderr, "x264 [error]: --fps + --tcfile-in is incompatible.\n" );
            return -1;
        }
        if( timecode_input.open_file( tcfile_name, &opt->hin, &info, &input_opt ) )
        {
            fprintf( stderr, "x264 [error]: timecode input failed\n" );
            return -1;
        }
        else
            input = timecode_input;
    }
    else if( !info.vfr && input_opt.timebase )
    {
        fprintf( stderr, "x264 [error]: --timebase is incompatible with cfr input\n" );
        return -1;
    }

1177 1178 1179 1180 1181 1182 1183
    /* set param flags from the info flags as necessary */
    param->i_csp       = info.csp;
    param->i_height    = info.height;
    param->b_vfr_input = info.vfr;
    param->i_width     = info.width;
    if( !b_user_interlaced && info.interlaced )
    {
1184 1185 1186
        fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling %cff interlaced mode.\n"
                         "                If you want otherwise, use --no-interlaced or --%cff\n",
                 info.tff ? 't' : 'b', info.tff ? 'b' : 't' );
1187
        param->b_interlaced = 1;
1188
        param->b_tff = !!info.tff;
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
    }
    if( !b_user_fps )
    {
        param->i_fps_num = info.fps_num;
        param->i_fps_den = info.fps_den;
    }
    if( param->b_vfr_input )
    {
        param->i_timebase_num = info.timebase_num;
        param->i_timebase_den = info.timebase_den;
    }
    else
    {
        param->i_timebase_num = param->i_fps_den;
Yusuke Nakamura's avatar
Yusuke Nakamura committed
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
        param->i_timebase_den = param->i_fps_num;
    }
    if( !tcfile_name && input_opt.timebase )
    {
        int i_user_timebase_num;
        int i_user_timebase_den;
        int ret = sscanf( input_opt.timebase, "%d/%d", &i_user_timebase_num, &i_user_timebase_den );
        if( !ret )
        {
            fprintf( stderr, "x264 [error]: invalid argument: timebase = %s\n", input_opt.timebase );
            return -1;
        }
        else if( ret == 1 )
        {
            i_user_timebase_num = param->i_timebase_num;
            i_user_timebase_den = atoi( input_opt.timebase );
        }
        opt->timebase_convert_multiplier = ((double)i_user_timebase_den / param->i_timebase_den)
                                         * ((double)param->i_timebase_num / i_user_timebase_num);
        param->i_timebase_num = i_user_timebase_num;
        param->i_timebase_den = i_user_timebase_den;
        param->b_vfr_input = 1;
1225 1226 1227 1228 1229
    }
    if( !param->vui.i_sar_width || !param->vui.i_sar_height )
    {
        param->vui.i_sar_width  = info.sar_width;
        param->vui.i_sar_height = info.sar_height;
1230 1231
    }

1232
#ifdef HAVE_PTHREAD
1233
    if( b_thread_input || param->i_threads > 1
Steven Walters's avatar
Steven Walters committed
1234
        || (param->i_threads == X264_THREADS_AUTO && x264_cpu_num_processors() > 1) )
1235
    {
1236
        if( thread_input.open_file( NULL, &opt->hin, &info, NULL ) )
1237
        {
1238 1239
            fprintf( stderr, "x264 [error]: threaded input failed\n" );
            return -1;
1240 1241
        }
        else
1242
            input = thread_input;
1243 1244 1245
    }
#endif

1246 1247 1248 1249 1250 1251

    /* Automatically reduce reference frame count to match the user's target level
     * if the user didn't explicitly set a reference frame count. */
    if( !b_user_ref )
    {
        int mbs = (((param->i_width)+15)>>4) * (((param->i_height)+15)>>4);
1252
        for( int i = 0; x264_levels[i].level_idc != 0; i++ )
1253 1254
            if( param->i_level_idc == x264_levels[i].level_idc )
            {
1255 1256
                while( mbs * 384 * param->i_frame_reference > x264_levels[i].dpb &&
                       param->i_frame_reference > 1 )
1257 1258 1259 1260