vpxenc.c 78 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9 10
 */

Christian Duvivier's avatar
Christian Duvivier committed
11
#include "vpx_config.h"
John Koleszar's avatar
John Koleszar committed
12

13
#if defined(_WIN32) || !CONFIG_OS_SUPPORT
14 15 16 17
#define USE_POSIX_MMAP 0
#else
#define USE_POSIX_MMAP 1
#endif
John Koleszar's avatar
John Koleszar committed
18 19 20 21 22

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
John Koleszar's avatar
John Koleszar committed
23
#include <limits.h>
24
#include <assert.h>
25
#include "vpx/vpx_encoder.h"
John Koleszar's avatar
John Koleszar committed
26
#include "vpx/vpx_decoder.h"
John Koleszar's avatar
John Koleszar committed
27 28 29 30 31 32 33
#if USE_POSIX_MMAP
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#endif
John Koleszar's avatar
John Koleszar committed
34

35
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
36
#include "vpx/vp8cx.h"
John Koleszar's avatar
John Koleszar committed
37
#endif
38
#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
39
#include "vpx/vp8dx.h"
John Koleszar's avatar
John Koleszar committed
40 41
#endif

John Koleszar's avatar
John Koleszar committed
42 43
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/vpx_timer.h"
John Koleszar's avatar
John Koleszar committed
44
#include "tools_common.h"
45
#include "y4minput.h"
John Koleszar's avatar
John Koleszar committed
46 47 48 49 50 51 52 53 54 55
#include "libmkv/EbmlWriter.h"
#include "libmkv/EbmlIDs.h"

/* Need special handling of these functions on Windows */
#if defined(_MSC_VER)
/* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
typedef __int64 off_t;
#define fseeko _fseeki64
#define ftello _ftelli64
#elif defined(_WIN32)
John Koleszar's avatar
John Koleszar committed
56 57
/* MinGW defines off_t as long
   and uses f{seek,tell}o64/off64_t for large files */
John Koleszar's avatar
John Koleszar committed
58 59
#define fseeko fseeko64
#define ftello ftello64
John Koleszar's avatar
John Koleszar committed
60
#define off_t off64_t
John Koleszar's avatar
John Koleszar committed
61 62
#endif

John Koleszar's avatar
John Koleszar committed
63
#define LITERALU64(hi,lo) ((((uint64_t)hi)<<32)|lo)
John Koleszar's avatar
John Koleszar committed
64

65 66 67 68 69 70 71 72
/* We should use 32-bit file operations in WebM file format
 * when building ARM executable file (.axf) with RVCT */
#if !CONFIG_OS_SUPPORT
typedef long off_t;
#define fseeko fseek
#define ftello ftell
#endif

John Koleszar's avatar
John Koleszar committed
73 74 75 76 77 78
/* Swallow warnings about unused results of fread/fwrite */
static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
                         FILE *stream) {
  return fread(ptr, size, nmemb, stream);
}
#define fread wrap_fread
John Koleszar's avatar
John Koleszar committed
79

John Koleszar's avatar
John Koleszar committed
80 81 82 83 84
static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
                          FILE *stream) {
  return fwrite(ptr, size, nmemb, stream);
}
#define fwrite wrap_fwrite
John Koleszar's avatar
John Koleszar committed
85

Jim Bankoski's avatar
Jim Bankoski committed
86

John Koleszar's avatar
John Koleszar committed
87
static const char *exec_name;
Jim Bankoski's avatar
Jim Bankoski committed
88 89

static const struct codec_item {
John Koleszar's avatar
John Koleszar committed
90
  char const              *name;
Jim Bankoski's avatar
Jim Bankoski committed
91
  const vpx_codec_iface_t *(*iface)(void);
John Koleszar's avatar
John Koleszar committed
92
  const vpx_codec_iface_t *(*dx_iface)(void);
Jim Bankoski's avatar
Jim Bankoski committed
93 94
  unsigned int             fourcc;
} codecs[] = {
95 96 97 98 99
#if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
  {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, 0x30385056},
#elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
  {"vp8", &vpx_codec_vp8_cx, NULL, 0x30385056},
#endif
John Koleszar's avatar
John Koleszar committed
100 101
#if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
  {"vp9", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, 0x30385056},
102
#elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
John Koleszar's avatar
John Koleszar committed
103
  {"vp9", &vpx_codec_vp8_cx, NULL, 0x30385056},
104 105 106
#endif
};

John Koleszar's avatar
John Koleszar committed
107 108
static void usage_exit();

John Koleszar's avatar
John Koleszar committed
109 110 111 112 113 114 115 116 117 118 119 120
#define LOG_ERROR(label) do \
  {\
    const char *l=label;\
    va_list ap;\
    va_start(ap, fmt);\
    if(l)\
      fprintf(stderr, "%s: ", l);\
    vfprintf(stderr, fmt, ap);\
    fprintf(stderr, "\n");\
    va_end(ap);\
  } while(0)

John Koleszar's avatar
John Koleszar committed
121
void die(const char *fmt, ...) {
John Koleszar's avatar
John Koleszar committed
122
  LOG_ERROR(NULL);
John Koleszar's avatar
John Koleszar committed
123
  usage_exit();
John Koleszar's avatar
John Koleszar committed
124 125
}

John Koleszar's avatar
John Koleszar committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

void fatal(const char *fmt, ...) {
  LOG_ERROR("Fatal");
  exit(EXIT_FAILURE);
}


void warn(const char *fmt, ...) {
  LOG_ERROR("Warning");
}


static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
  va_list ap;

  va_start(ap, s);
John Koleszar's avatar
John Koleszar committed
142 143
  if (ctx->err) {
    const char *detail = vpx_codec_error_detail(ctx);
John Koleszar's avatar
John Koleszar committed
144

John Koleszar's avatar
John Koleszar committed
145 146
    vfprintf(stderr, s, ap);
    fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
John Koleszar's avatar
John Koleszar committed
147

John Koleszar's avatar
John Koleszar committed
148 149
    if (detail)
      fprintf(stderr, "    %s\n", detail);
John Koleszar's avatar
John Koleszar committed
150

John Koleszar's avatar
John Koleszar committed
151 152
    exit(EXIT_FAILURE);
  }
John Koleszar's avatar
John Koleszar committed
153 154 155 156 157
}

/* This structure is used to abstract the different ways of handling
 * first pass statistics.
 */
John Koleszar's avatar
John Koleszar committed
158 159 160 161 162 163
typedef struct {
  vpx_fixed_buf_t buf;
  int             pass;
  FILE           *file;
  char           *buf_ptr;
  size_t          buf_alloc_sz;
John Koleszar's avatar
John Koleszar committed
164 165
} stats_io_t;

John Koleszar's avatar
John Koleszar committed
166 167
int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
  int res;
John Koleszar's avatar
John Koleszar committed
168

John Koleszar's avatar
John Koleszar committed
169
  stats->pass = pass;
John Koleszar's avatar
John Koleszar committed
170

John Koleszar's avatar
John Koleszar committed
171 172 173 174 175 176
  if (pass == 0) {
    stats->file = fopen(fpf, "wb");
    stats->buf.sz = 0;
    stats->buf.buf = NULL,
               res = (stats->file != NULL);
  } else {
John Koleszar's avatar
John Koleszar committed
177 178
#if 0
#elif USE_POSIX_MMAP
John Koleszar's avatar
John Koleszar committed
179 180 181 182 183 184 185 186 187 188
    struct stat stat_buf;
    int fd;

    fd = open(fpf, O_RDONLY);
    stats->file = fdopen(fd, "rb");
    fstat(fd, &stat_buf);
    stats->buf.sz = stat_buf.st_size;
    stats->buf.buf = mmap(NULL, stats->buf.sz, PROT_READ, MAP_PRIVATE,
                          fd, 0);
    res = (stats->buf.buf != NULL);
John Koleszar's avatar
John Koleszar committed
189
#else
John Koleszar's avatar
John Koleszar committed
190
    size_t nbytes;
John Koleszar's avatar
John Koleszar committed
191

John Koleszar's avatar
John Koleszar committed
192
    stats->file = fopen(fpf, "rb");
John Koleszar's avatar
John Koleszar committed
193

John Koleszar's avatar
John Koleszar committed
194 195
    if (fseek(stats->file, 0, SEEK_END))
      fatal("First-pass stats file must be seekable!");
John Koleszar's avatar
John Koleszar committed
196

John Koleszar's avatar
John Koleszar committed
197 198
    stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
    rewind(stats->file);
John Koleszar's avatar
John Koleszar committed
199

John Koleszar's avatar
John Koleszar committed
200
    stats->buf.buf = malloc(stats->buf_alloc_sz);
John Koleszar's avatar
John Koleszar committed
201

John Koleszar's avatar
John Koleszar committed
202 203 204
    if (!stats->buf.buf)
      fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
            (unsigned long)stats->buf_alloc_sz);
John Koleszar's avatar
John Koleszar committed
205

John Koleszar's avatar
John Koleszar committed
206 207
    nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
    res = (nbytes == stats->buf.sz);
John Koleszar's avatar
John Koleszar committed
208
#endif
John Koleszar's avatar
John Koleszar committed
209
  }
John Koleszar's avatar
John Koleszar committed
210

John Koleszar's avatar
John Koleszar committed
211
  return res;
John Koleszar's avatar
John Koleszar committed
212 213
}

John Koleszar's avatar
John Koleszar committed
214 215 216
int stats_open_mem(stats_io_t *stats, int pass) {
  int res;
  stats->pass = pass;
John Koleszar's avatar
John Koleszar committed
217

John Koleszar's avatar
John Koleszar committed
218 219 220 221 222
  if (!pass) {
    stats->buf.sz = 0;
    stats->buf_alloc_sz = 64 * 1024;
    stats->buf.buf = malloc(stats->buf_alloc_sz);
  }
John Koleszar's avatar
John Koleszar committed
223

John Koleszar's avatar
John Koleszar committed
224 225 226
  stats->buf_ptr = stats->buf.buf;
  res = (stats->buf.buf != NULL);
  return res;
John Koleszar's avatar
John Koleszar committed
227 228 229
}


John Koleszar's avatar
John Koleszar committed
230 231 232
void stats_close(stats_io_t *stats, int last_pass) {
  if (stats->file) {
    if (stats->pass == last_pass) {
John Koleszar's avatar
John Koleszar committed
233 234
#if 0
#elif USE_POSIX_MMAP
John Koleszar's avatar
John Koleszar committed
235
      munmap(stats->buf.buf, stats->buf.sz);
John Koleszar's avatar
John Koleszar committed
236
#else
John Koleszar's avatar
John Koleszar committed
237
      free(stats->buf.buf);
John Koleszar's avatar
John Koleszar committed
238 239
#endif
    }
John Koleszar's avatar
John Koleszar committed
240 241 242 243 244 245 246

    fclose(stats->file);
    stats->file = NULL;
  } else {
    if (stats->pass == last_pass)
      free(stats->buf.buf);
  }
John Koleszar's avatar
John Koleszar committed
247 248
}

John Koleszar's avatar
John Koleszar committed
249 250
void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
  if (stats->file) {
John Koleszar's avatar
John Koleszar committed
251
    (void) fwrite(pkt, 1, len, stats->file);
John Koleszar's avatar
John Koleszar committed
252 253 254 255 256 257 258 259 260
  } else {
    if (stats->buf.sz + len > stats->buf_alloc_sz) {
      size_t  new_sz = stats->buf_alloc_sz + 64 * 1024;
      char   *new_ptr = realloc(stats->buf.buf, new_sz);

      if (new_ptr) {
        stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
        stats->buf.buf = new_ptr;
        stats->buf_alloc_sz = new_sz;
John Koleszar's avatar
John Koleszar committed
261 262
      } else
        fatal("Failed to realloc firstpass stats buffer.");
John Koleszar's avatar
John Koleszar committed
263 264
    }

John Koleszar's avatar
John Koleszar committed
265 266 267 268
    memcpy(stats->buf_ptr, pkt, len);
    stats->buf.sz += len;
    stats->buf_ptr += len;
  }
John Koleszar's avatar
John Koleszar committed
269 270
}

John Koleszar's avatar
John Koleszar committed
271 272
vpx_fixed_buf_t stats_get(stats_io_t *stats) {
  return stats->buf;
John Koleszar's avatar
John Koleszar committed
273 274
}

275
/* Stereo 3D packed frame format */
John Koleszar's avatar
John Koleszar committed
276 277 278 279 280 281
typedef enum stereo_format {
  STEREO_FORMAT_MONO       = 0,
  STEREO_FORMAT_LEFT_RIGHT = 1,
  STEREO_FORMAT_BOTTOM_TOP = 2,
  STEREO_FORMAT_TOP_BOTTOM = 3,
  STEREO_FORMAT_RIGHT_LEFT = 11
282 283
} stereo_format_t;

John Koleszar's avatar
John Koleszar committed
284 285 286 287
enum video_file_type {
  FILE_TYPE_RAW,
  FILE_TYPE_IVF,
  FILE_TYPE_Y4M
288 289
};

290
struct detect_buffer {
John Koleszar's avatar
John Koleszar committed
291 292 293
  char buf[4];
  size_t buf_read;
  size_t position;
294 295 296
};


John Koleszar's avatar
John Koleszar committed
297 298 299 300 301 302 303 304 305 306 307 308 309
struct input_state {
  char                 *fn;
  FILE                 *file;
  y4m_input             y4m;
  struct detect_buffer  detect;
  enum video_file_type  file_type;
  unsigned int          w;
  unsigned int          h;
  struct vpx_rational   framerate;
  int                   use_i420;
};


John Koleszar's avatar
John Koleszar committed
310
#define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
John Koleszar's avatar
John Koleszar committed
311 312 313 314 315
static int read_frame(struct input_state *input, vpx_image_t *img) {
  FILE *f = input->file;
  enum video_file_type file_type = input->file_type;
  y4m_input *y4m = &input->y4m;
  struct detect_buffer *detect = &input->detect;
John Koleszar's avatar
John Koleszar committed
316 317 318 319 320 321 322 323 324 325 326 327 328 329
  int plane = 0;
  int shortread = 0;

  if (file_type == FILE_TYPE_Y4M) {
    if (y4m_input_fetch_frame(y4m, f, img) < 1)
      return 0;
  } else {
    if (file_type == FILE_TYPE_IVF) {
      char junk[IVF_FRAME_HDR_SZ];

      /* Skip the frame header. We know how big the frame should be. See
       * write_ivf_frame_header() for documentation on the frame header
       * layout.
       */
John Koleszar's avatar
John Koleszar committed
330
      (void) fread(junk, 1, IVF_FRAME_HDR_SZ, f);
John Koleszar's avatar
John Koleszar committed
331
    }
332

John Koleszar's avatar
John Koleszar committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
    for (plane = 0; plane < 3; plane++) {
      unsigned char *ptr;
      int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
      int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
      int r;

      /* Determine the correct plane based on the image format. The for-loop
       * always counts in Y,U,V order, but this may not match the order of
       * the data on disk.
       */
      switch (plane) {
        case 1:
          ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V : VPX_PLANE_U];
          break;
        case 2:
          ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U : VPX_PLANE_V];
          break;
        default:
          ptr = img->planes[plane];
      }

      for (r = 0; r < h; r++) {
        size_t needed = w;
        size_t buf_position = 0;
        const size_t left = detect->buf_read - detect->position;
        if (left > 0) {
          const size_t more = (left < needed) ? left : needed;
          memcpy(ptr, detect->buf + detect->position, more);
          buf_position = more;
          needed -= more;
          detect->position += more;
John Koleszar's avatar
John Koleszar committed
364
        }
John Koleszar's avatar
John Koleszar committed
365 366
        if (needed > 0) {
          shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
John Koleszar's avatar
John Koleszar committed
367
        }
John Koleszar's avatar
John Koleszar committed
368 369 370

        ptr += img->stride[plane];
      }
John Koleszar's avatar
John Koleszar committed
371
    }
John Koleszar's avatar
John Koleszar committed
372
  }
John Koleszar's avatar
John Koleszar committed
373

John Koleszar's avatar
John Koleszar committed
374
  return !shortread;
John Koleszar's avatar
John Koleszar committed
375 376 377
}


378
unsigned int file_is_y4m(FILE      *infile,
379
                         y4m_input *y4m,
John Koleszar's avatar
John Koleszar committed
380 381 382 383 384
                         char       detect[4]) {
  if (memcmp(detect, "YUV4", 4) == 0) {
    return 1;
  }
  return 0;
385 386
}

John Koleszar's avatar
John Koleszar committed
387
#define IVF_FILE_HDR_SZ (32)
John Koleszar's avatar
John Koleszar committed
388 389
unsigned int file_is_ivf(struct input_state *input,
                         unsigned int *fourcc) {
John Koleszar's avatar
John Koleszar committed
390 391
  char raw_hdr[IVF_FILE_HDR_SZ];
  int is_ivf = 0;
John Koleszar's avatar
John Koleszar committed
392 393 394 395
  FILE *infile = input->file;
  unsigned int *width = &input->w;
  unsigned int *height = &input->h;
  struct detect_buffer *detect = &input->detect;
John Koleszar's avatar
John Koleszar committed
396

John Koleszar's avatar
John Koleszar committed
397 398
  if (memcmp(detect->buf, "DKIF", 4) != 0)
    return 0;
399

John Koleszar's avatar
John Koleszar committed
400 401 402 403 404
  /* See write_ivf_file_header() for more documentation on the file header
   * layout.
   */
  if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
      == IVF_FILE_HDR_SZ - 4) {
John Koleszar's avatar
John Koleszar committed
405
    {
John Koleszar's avatar
John Koleszar committed
406
      is_ivf = 1;
John Koleszar's avatar
John Koleszar committed
407

John Koleszar's avatar
John Koleszar committed
408
      if (mem_get_le16(raw_hdr + 4) != 0)
John Koleszar's avatar
John Koleszar committed
409 410
        warn("Unrecognized IVF version! This file may not decode "
             "properly.");
John Koleszar's avatar
John Koleszar committed
411

John Koleszar's avatar
John Koleszar committed
412
      *fourcc = mem_get_le32(raw_hdr + 8);
John Koleszar's avatar
John Koleszar committed
413
    }
John Koleszar's avatar
John Koleszar committed
414
  }
John Koleszar's avatar
John Koleszar committed
415

John Koleszar's avatar
John Koleszar committed
416 417 418 419 420
  if (is_ivf) {
    *width = mem_get_le16(raw_hdr + 12);
    *height = mem_get_le16(raw_hdr + 14);
    detect->position = 4;
  }
John Koleszar's avatar
John Koleszar committed
421

John Koleszar's avatar
John Koleszar committed
422
  return is_ivf;
John Koleszar's avatar
John Koleszar committed
423 424 425 426 427 428
}


static void write_ivf_file_header(FILE *outfile,
                                  const vpx_codec_enc_cfg_t *cfg,
                                  unsigned int fourcc,
John Koleszar's avatar
John Koleszar committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
                                  int frame_cnt) {
  char header[32];

  if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
    return;

  header[0] = 'D';
  header[1] = 'K';
  header[2] = 'I';
  header[3] = 'F';
  mem_put_le16(header + 4,  0);                 /* version */
  mem_put_le16(header + 6,  32);                /* headersize */
  mem_put_le32(header + 8,  fourcc);            /* headersize */
  mem_put_le16(header + 12, cfg->g_w);          /* width */
  mem_put_le16(header + 14, cfg->g_h);          /* height */
  mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
  mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
  mem_put_le32(header + 24, frame_cnt);         /* length */
  mem_put_le32(header + 28, 0);                 /* unused */

John Koleszar's avatar
John Koleszar committed
449
  (void) fwrite(header, 1, 32, outfile);
John Koleszar's avatar
John Koleszar committed
450 451 452 453
}


static void write_ivf_frame_header(FILE *outfile,
John Koleszar's avatar
John Koleszar committed
454 455 456
                                   const vpx_codec_cx_pkt_t *pkt) {
  char             header[12];
  vpx_codec_pts_t  pts;
John Koleszar's avatar
John Koleszar committed
457

John Koleszar's avatar
John Koleszar committed
458 459
  if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
    return;
John Koleszar's avatar
John Koleszar committed
460

John Koleszar's avatar
John Koleszar committed
461
  pts = pkt->data.frame.pts;
John Koleszar's avatar
John Koleszar committed
462
  mem_put_le32(header, (int)pkt->data.frame.sz);
John Koleszar's avatar
John Koleszar committed
463 464
  mem_put_le32(header + 4, pts & 0xFFFFFFFF);
  mem_put_le32(header + 8, pts >> 32);
John Koleszar's avatar
John Koleszar committed
465

John Koleszar's avatar
John Koleszar committed
466 467 468 469 470 471 472
  (void) fwrite(header, 1, 12, outfile);
}

static void write_ivf_frame_size(FILE *outfile, size_t size) {
  char             header[4];
  mem_put_le32(header, (int)size);
  (void) fwrite(header, 1, 4, outfile);
John Koleszar's avatar
John Koleszar committed
473 474
}

John Koleszar's avatar
John Koleszar committed
475 476 477 478

typedef off_t EbmlLoc;


John Koleszar's avatar
John Koleszar committed
479 480 481
struct cue_entry {
  unsigned int time;
  uint64_t     loc;
John Koleszar's avatar
John Koleszar committed
482 483 484
};


John Koleszar's avatar
John Koleszar committed
485 486
struct EbmlGlobal {
  int debug;
487

John Koleszar's avatar
John Koleszar committed
488 489 490
  FILE    *stream;
  int64_t last_pts_ms;
  vpx_rational_t  framerate;
John Koleszar's avatar
John Koleszar committed
491

John Koleszar's avatar
John Koleszar committed
492 493 494 495 496 497 498
  /* These pointers are to the start of an element */
  off_t    position_reference;
  off_t    seek_info_pos;
  off_t    segment_info_pos;
  off_t    track_pos;
  off_t    cue_pos;
  off_t    cluster_pos;
John Koleszar's avatar
John Koleszar committed
499

John Koleszar's avatar
John Koleszar committed
500 501
  /* This pointer is to a specific element to be serialized */
  off_t    track_id_pos;
John Koleszar's avatar
John Koleszar committed
502

John Koleszar's avatar
John Koleszar committed
503 504 505
  /* These pointers are to the size field of the element */
  EbmlLoc  startSegment;
  EbmlLoc  startCluster;
John Koleszar's avatar
John Koleszar committed
506

John Koleszar's avatar
John Koleszar committed
507 508
  uint32_t cluster_timecode;
  int      cluster_open;
John Koleszar's avatar
John Koleszar committed
509

John Koleszar's avatar
John Koleszar committed
510 511
  struct cue_entry *cue_list;
  unsigned int      cues;
John Koleszar's avatar
John Koleszar committed
512 513 514 515

};


John Koleszar's avatar
John Koleszar committed
516
void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
John Koleszar's avatar
John Koleszar committed
517
  (void) fwrite(buffer_in, 1, len, glob->stream);
John Koleszar's avatar
John Koleszar committed
518 519
}

520
#define WRITE_BUFFER(s) \
John Koleszar's avatar
John Koleszar committed
521 522
  for(i = len-1; i>=0; i--)\
  { \
John Koleszar's avatar
John Koleszar committed
523
    x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
524
    Ebml_Write(glob, &x, 1); \
John Koleszar's avatar
John Koleszar committed
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
  }
void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len) {
  char x;
  int i;

  /* buffer_size:
   * 1 - int8_t;
   * 2 - int16_t;
   * 3 - int32_t;
   * 4 - int64_t;
   */
  switch (buffer_size) {
    case 1:
      WRITE_BUFFER(int8_t)
      break;
    case 2:
      WRITE_BUFFER(int16_t)
      break;
    case 4:
      WRITE_BUFFER(int32_t)
      break;
    case 8:
      WRITE_BUFFER(int64_t)
      break;
    default:
      break;
  }
John Koleszar's avatar
John Koleszar committed
552
}
553
#undef WRITE_BUFFER
John Koleszar's avatar
John Koleszar committed
554

555
/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
John Koleszar's avatar
John Koleszar committed
556 557
 * one, but not a 32 bit one.
 */
John Koleszar's avatar
John Koleszar committed
558 559 560 561 562
static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
  unsigned char sizeSerialized = 4 | 0x80;
  Ebml_WriteID(glob, class_id);
  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
  Ebml_Serialize(glob, &ui, sizeof(ui), 4);
John Koleszar's avatar
John Koleszar committed
563 564 565
}


John Koleszar's avatar
John Koleszar committed
566 567
static void
Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
John Koleszar's avatar
John Koleszar committed
568
                     unsigned long class_id) {
John Koleszar's avatar
John Koleszar committed
569 570 571
  /* todo this is always taking 8 bytes, this may need later optimization */
  /* this is a key that says length unknown */
  uint64_t unknownLen = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
John Koleszar's avatar
John Koleszar committed
572 573 574 575

  Ebml_WriteID(glob, class_id);
  *ebmlLoc = ftello(glob->stream);
  Ebml_Serialize(glob, &unknownLen, sizeof(unknownLen), 8);
John Koleszar's avatar
John Koleszar committed
576 577 578
}

static void
John Koleszar's avatar
John Koleszar committed
579 580 581
Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
  off_t pos;
  uint64_t size;
John Koleszar's avatar
John Koleszar committed
582

John Koleszar's avatar
John Koleszar committed
583 584
  /* Save the current stream pointer */
  pos = ftello(glob->stream);
John Koleszar's avatar
John Koleszar committed
585

John Koleszar's avatar
John Koleszar committed
586 587
  /* Calculate the size of this element */
  size = pos - *ebmlLoc - 8;
John Koleszar's avatar
John Koleszar committed
588
  size |= LITERALU64(0x01000000, 0x00000000);
John Koleszar's avatar
John Koleszar committed
589

John Koleszar's avatar
John Koleszar committed
590 591 592
  /* Seek back to the beginning of the element and write the new size */
  fseeko(glob->stream, *ebmlLoc, SEEK_SET);
  Ebml_Serialize(glob, &size, sizeof(size), 8);
John Koleszar's avatar
John Koleszar committed
593

John Koleszar's avatar
John Koleszar committed
594 595
  /* Reset the stream pointer */
  fseeko(glob->stream, pos, SEEK_SET);
John Koleszar's avatar
John Koleszar committed
596 597
}

John Koleszar's avatar
John Koleszar committed
598 599

static void
John Koleszar's avatar
John Koleszar committed
600 601 602 603 604 605 606
write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos) {
  uint64_t offset = pos - ebml->position_reference;
  EbmlLoc start;
  Ebml_StartSubElement(ebml, &start, Seek);
  Ebml_SerializeBinary(ebml, SeekID, id);
  Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
  Ebml_EndSubElement(ebml, &start);
John Koleszar's avatar
John Koleszar committed
607 608 609 610
}


static void
John Koleszar's avatar
John Koleszar committed
611
write_webm_seek_info(EbmlGlobal *ebml) {
John Koleszar's avatar
John Koleszar committed
612

John Koleszar's avatar
John Koleszar committed
613
  off_t pos;
John Koleszar's avatar
John Koleszar committed
614

John Koleszar's avatar
John Koleszar committed
615 616
  /* Save the current stream pointer */
  pos = ftello(ebml->stream);
John Koleszar's avatar
John Koleszar committed
617

John Koleszar's avatar
John Koleszar committed
618 619 620 621
  if (ebml->seek_info_pos)
    fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
  else
    ebml->seek_info_pos = pos;
John Koleszar's avatar
John Koleszar committed
622

John Koleszar's avatar
John Koleszar committed
623 624
  {
    EbmlLoc start;
John Koleszar's avatar
John Koleszar committed
625

John Koleszar's avatar
John Koleszar committed
626 627 628 629 630 631 632
    Ebml_StartSubElement(ebml, &start, SeekHead);
    write_webm_seek_element(ebml, Tracks, ebml->track_pos);
    write_webm_seek_element(ebml, Cues,   ebml->cue_pos);
    write_webm_seek_element(ebml, Info,   ebml->segment_info_pos);
    Ebml_EndSubElement(ebml, &start);
  }
  {
John Koleszar's avatar
John Koleszar committed
633
    /* segment info */
John Koleszar's avatar
John Koleszar committed
634 635
    EbmlLoc startInfo;
    uint64_t frame_time;
John Koleszar's avatar
John Koleszar committed
636 637 638 639 640 641 642 643 644 645 646
    char version_string[64];

    /* Assemble version string */
    if (ebml->debug)
      strcpy(version_string, "vpxenc");
    else {
      strcpy(version_string, "vpxenc ");
      strncat(version_string,
              vpx_codec_version_str(),
              sizeof(version_string) - 1 - strlen(version_string));
    }
John Koleszar's avatar
John Koleszar committed
647 648 649 650 651 652 653

    frame_time = (uint64_t)1000 * ebml->framerate.den
                 / ebml->framerate.num;
    ebml->segment_info_pos = ftello(ebml->stream);
    Ebml_StartSubElement(ebml, &startInfo, Info);
    Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
    Ebml_SerializeFloat(ebml, Segment_Duration,
John Koleszar's avatar
John Koleszar committed
654 655 656
                        (double)(ebml->last_pts_ms + frame_time));
    Ebml_SerializeString(ebml, 0x4D80, version_string);
    Ebml_SerializeString(ebml, 0x5741, version_string);
John Koleszar's avatar
John Koleszar committed
657 658
    Ebml_EndSubElement(ebml, &startInfo);
  }
John Koleszar's avatar
John Koleszar committed
659 660 661 662 663 664
}


static void
write_webm_file_header(EbmlGlobal                *glob,
                       const vpx_codec_enc_cfg_t *cfg,
665
                       const struct vpx_rational *fps,
John Koleszar's avatar
John Koleszar committed
666 667 668 669 670
                       stereo_format_t            stereo_fmt) {
  {
    EbmlLoc start;
    Ebml_StartSubElement(glob, &start, EBML);
    Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
John Koleszar's avatar
John Koleszar committed
671 672 673 674 675 676
    Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
    Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
    Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
    Ebml_SerializeString(glob, DocType, "webm");
    Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
    Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
John Koleszar's avatar
John Koleszar committed
677 678 679
    Ebml_EndSubElement(glob, &start);
  }
  {
John Koleszar's avatar
John Koleszar committed
680
    Ebml_StartSubElement(glob, &glob->startSegment, Segment);
John Koleszar's avatar
John Koleszar committed
681 682 683 684
    glob->position_reference = ftello(glob->stream);
    glob->framerate = *fps;
    write_webm_seek_info(glob);

John Koleszar's avatar
John Koleszar committed
685
    {
John Koleszar's avatar
John Koleszar committed
686 687 688 689 690 691
      EbmlLoc trackStart;
      glob->track_pos = ftello(glob->stream);
      Ebml_StartSubElement(glob, &trackStart, Tracks);
      {
        unsigned int trackNumber = 1;
        uint64_t     trackID = 0;
John Koleszar's avatar
John Koleszar committed
692

John Koleszar's avatar
John Koleszar committed
693 694 695 696 697
        EbmlLoc start;
        Ebml_StartSubElement(glob, &start, TrackEntry);
        Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
        glob->track_id_pos = ftello(glob->stream);
        Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
John Koleszar's avatar
John Koleszar committed
698
        Ebml_SerializeUnsigned(glob, TrackType, 1);
John Koleszar's avatar
John Koleszar committed
699
        Ebml_SerializeString(glob, CodecID, "V_VP8");
John Koleszar's avatar
John Koleszar committed
700
        {
John Koleszar's avatar
John Koleszar committed
701 702 703 704 705 706 707 708 709 710
          unsigned int pixelWidth = cfg->g_w;
          unsigned int pixelHeight = cfg->g_h;
          float        frameRate   = (float)fps->num / (float)fps->den;

          EbmlLoc videoStart;
          Ebml_StartSubElement(glob, &videoStart, Video);
          Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
          Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
          Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
          Ebml_SerializeFloat(glob, FrameRate, frameRate);
John Koleszar's avatar
John Koleszar committed
711
          Ebml_EndSubElement(glob, &videoStart);
John Koleszar's avatar
John Koleszar committed
712
        }
John Koleszar's avatar
John Koleszar committed
713
        Ebml_EndSubElement(glob, &start); /* Track Entry */
John Koleszar's avatar
John Koleszar committed
714 715
      }
      Ebml_EndSubElement(glob, &trackStart);
John Koleszar's avatar
John Koleszar committed
716
    }
John Koleszar's avatar
John Koleszar committed
717
    /* segment element is open */
John Koleszar's avatar
John Koleszar committed
718
  }
John Koleszar's avatar
John Koleszar committed
719 720 721 722 723 724
}


static void
write_webm_block(EbmlGlobal                *glob,
                 const vpx_codec_enc_cfg_t *cfg,
John Koleszar's avatar
John Koleszar committed
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
                 const vpx_codec_cx_pkt_t  *pkt) {
  unsigned long  block_length;
  unsigned char  track_number;
  unsigned short block_timecode = 0;
  unsigned char  flags;
  int64_t        pts_ms;
  int            start_cluster = 0, is_keyframe;

  /* Calculate the PTS of this frame in milliseconds */
  pts_ms = pkt->data.frame.pts * 1000
           * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
  if (pts_ms <= glob->last_pts_ms)
    pts_ms = glob->last_pts_ms + 1;
  glob->last_pts_ms = pts_ms;

  /* Calculate the relative time of this block */
  if (pts_ms - glob->cluster_timecode > SHRT_MAX)
    start_cluster = 1;
  else
John Koleszar's avatar
John Koleszar committed
744
    block_timecode = (unsigned short)pts_ms - glob->cluster_timecode;
John Koleszar's avatar
John Koleszar committed
745 746 747 748 749 750 751 752 753

  is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
  if (start_cluster || is_keyframe) {
    if (glob->cluster_open)
      Ebml_EndSubElement(glob, &glob->startCluster);

    /* Open the new cluster */
    block_timecode = 0;
    glob->cluster_open = 1;
John Koleszar's avatar
John Koleszar committed
754
    glob->cluster_timecode = (uint32_t)pts_ms;
John Koleszar's avatar
John Koleszar committed
755
    glob->cluster_pos = ftello(glob->stream);
John Koleszar's avatar
John Koleszar committed
756
    Ebml_StartSubElement(glob, &glob->startCluster, Cluster); /* cluster */
John Koleszar's avatar
John Koleszar committed
757 758 759 760 761 762 763 764 765 766
    Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);

    /* Save a cue point if this is a keyframe. */
    if (is_keyframe) {
      struct cue_entry *cue, *new_cue_list;

      new_cue_list = realloc(glob->cue_list,
                             (glob->cues + 1) * sizeof(struct cue_entry));
      if (new_cue_list)
        glob->cue_list = new_cue_list;
John Koleszar's avatar
John Koleszar committed
767 768
      else
        fatal("Failed to realloc cue list.");
John Koleszar's avatar
John Koleszar committed
769

John Koleszar's avatar
John Koleszar committed
770 771 772 773
      cue = &glob->cue_list[glob->cues];
      cue->time = glob->cluster_timecode;
      cue->loc = glob->cluster_pos;
      glob->cues++;
John Koleszar's avatar
John Koleszar committed
774
    }
John Koleszar's avatar
John Koleszar committed
775
  }
John Koleszar's avatar
John Koleszar committed
776

John Koleszar's avatar
John Koleszar committed
777 778
  /* Write the Simple Block */
  Ebml_WriteID(glob, SimpleBlock);
John Koleszar's avatar
John Koleszar committed
779

John Koleszar's avatar
John Koleszar committed
780
  block_length = (unsigned long)pkt->data.frame.sz + 4;
John Koleszar's avatar
John Koleszar committed
781 782
  block_length |= 0x10000000;
  Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
John Koleszar's avatar
John Koleszar committed
783

John Koleszar's avatar
John Koleszar committed
784 785 786
  track_number = 1;
  track_number |= 0x80;
  Ebml_Write(glob, &track_number, 1);
John Koleszar's avatar
John Koleszar committed
787

John Koleszar's avatar
John Koleszar committed
788
  Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
John Koleszar's avatar
John Koleszar committed
789

John Koleszar's avatar
John Koleszar committed
790 791 792 793 794 795
  flags = 0;
  if (is_keyframe)
    flags |= 0x80;
  if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
    flags |= 0x08;
  Ebml_Write(glob, &flags, 1);
John Koleszar's avatar
John Koleszar committed
796

John Koleszar's avatar
John Koleszar committed
797
  Ebml_Write(glob, pkt->data.frame.buf, (unsigned long)pkt->data.frame.sz);
John Koleszar's avatar
John Koleszar committed
798 799 800 801
}


static void
John Koleszar's avatar
John Koleszar committed
802
write_webm_file_footer(EbmlGlobal *glob, long hash) {
John Koleszar's avatar
John Koleszar committed
803

John Koleszar's avatar
John Koleszar committed
804 805
  if (glob->cluster_open)
    Ebml_EndSubElement(glob, &glob->startCluster);
John Koleszar's avatar
John Koleszar committed
806

John Koleszar's avatar
John Koleszar committed
807 808
  {
    EbmlLoc start;
John Koleszar's avatar
John Koleszar committed
809
    unsigned int i;
John Koleszar's avatar
John Koleszar committed
810

John Koleszar's avatar
John Koleszar committed
811 812 813 814 815
    glob->cue_pos = ftello(glob->stream);
    Ebml_StartSubElement(glob, &start, Cues);
    for (i = 0; i < glob->cues; i++) {
      struct cue_entry *cue = &glob->cue_list[i];
      EbmlLoc start;
John Koleszar's avatar
John Koleszar committed
816

John Koleszar's avatar
John Koleszar committed
817 818 819
      Ebml_StartSubElement(glob, &start, CuePoint);
      {
        EbmlLoc start;
John Koleszar's avatar
John Koleszar committed
820

John Koleszar's avatar
John Koleszar committed
821
        Ebml_SerializeUnsigned(glob, CueTime, cue->time);
John Koleszar's avatar
John Koleszar committed
822

John Koleszar's avatar
John Koleszar committed
823 824 825 826
        Ebml_StartSubElement(glob, &start, CueTrackPositions);
        Ebml_SerializeUnsigned(glob, CueTrack, 1);
        Ebml_SerializeUnsigned64(glob, CueClusterPosition,
                                 cue->loc - glob->position_reference);
John Koleszar's avatar
John Koleszar committed
827
        Ebml_EndSubElement(glob, &start);
John Koleszar's avatar
John Koleszar committed
828 829
      }
      Ebml_EndSubElement(glob, &start);
John Koleszar's avatar
John Koleszar committed
830
    }
John Koleszar's avatar
John Koleszar committed
831 832
    Ebml_EndSubElement(glob, &start);
  }
John Koleszar's avatar
John Koleszar committed
833

John Koleszar's avatar
John Koleszar committed
834
  Ebml_EndSubElement(glob, &glob->startSegment);
John Koleszar's avatar
John Koleszar committed
835

John Koleszar's avatar
John Koleszar committed
836 837
  /* Patch up the seek info block */
  write_webm_seek_info(glob);
John Koleszar's avatar
John Koleszar committed
838

John Koleszar's avatar
John Koleszar committed
839 840 841
  /* Patch up the track id */
  fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
  Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
John Koleszar's avatar
John Koleszar committed
842

John Koleszar's avatar
John Koleszar committed
843
  fseeko(glob->stream, 0, SEEK_END);
John Koleszar's avatar
John Koleszar committed
844 845 846
}


John Koleszar's avatar
John Koleszar committed
847
/* Murmur hash derived from public domain reference implementation at
John Koleszar's avatar
John Koleszar committed
848
 *   http:// sites.google.com/site/murmurhash/
John Koleszar's avatar
John Koleszar committed
849
 */
John Koleszar's avatar
John Koleszar committed
850 851 852
static unsigned int murmur(const void *key, int len, unsigned int seed) {
  const unsigned int m = 0x5bd1e995;
  const int r = 24;
John Koleszar's avatar
John Koleszar committed
853

John Koleszar's avatar
John Koleszar committed
854
  unsigned int h = seed ^ len;
John Koleszar's avatar
John Koleszar committed
855

John Koleszar's avatar
John Koleszar committed
856
  const unsigned char *data = (const unsigned char *)key;
John Koleszar's avatar
John Koleszar committed
857

John Koleszar's avatar
John Koleszar committed
858 859
  while (len >= 4) {
    unsigned int k;
John Koleszar's avatar
John Koleszar committed
860

John Koleszar's avatar
John Koleszar committed
861 862 863 864
    k  = data[0];
    k |= data[1] << 8;
    k |= data[2] << 16;
    k |= data[3] << 24;
John Koleszar's avatar
John Koleszar committed
865

John Koleszar's avatar
John Koleszar committed
866 867 868
    k *= m;
    k ^= k >> r;
    k *= m;
John Koleszar's avatar
John Koleszar committed
869 870

    h *= m;
John Koleszar's avatar
John Koleszar committed
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
    h ^= k;

    data += 4;
    len -= 4;
  }

  switch (len) {
    case 3:
      h ^= data[2] << 16;
    case 2:
      h ^= data[1] << 8;
    case 1:
      h ^= data[0];
      h *= m;
  };

  h ^= h >> 13;
  h *= m;
  h ^= h >> 15;

  return h;
John Koleszar's avatar
John Koleszar committed
892 893
}

894
#include "math.h"
895
#define MAX_PSNR 100
John Koleszar's avatar
John Koleszar committed
896 897
static double vp8_mse2psnr(double Samples, double Peak, double Mse) {
  double psnr;
898

John Koleszar's avatar
John Koleszar committed
899 900 901
  if ((double)Mse > 0.0)
    psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
  else
John Koleszar's avatar
John Koleszar committed
902
    psnr = MAX_PSNR;      /* Limit to prevent / 0 */
903

John Koleszar's avatar
John Koleszar committed
904 905
  if (psnr > MAX_PSNR)
    psnr = MAX_PSNR;
906

John Koleszar's avatar
John Koleszar committed
907
  return psnr;
908 909
}

John Koleszar's avatar
John Koleszar committed
910

John Koleszar's avatar
John Koleszar committed
911
#include "args.h"
912
static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
John Koleszar's avatar
John Koleszar committed
913
                                           "Debug mode (makes output deterministic)");
914
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
John Koleszar's avatar
John Koleszar committed
915
                                            "Output filename");
John Koleszar's avatar
John Koleszar committed
916
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
John Koleszar's avatar
John Koleszar committed
917
                                          "Input file is YV12 ");
John Koleszar's avatar
John Koleszar committed
918
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
John Koleszar's avatar
John Koleszar committed
919
                                          "Input file is I420 (default)");
John Koleszar's avatar
John Koleszar committed
920
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
John Koleszar's avatar
John Koleszar committed
921
                                          "Codec to use");
John Koleszar's avatar
John Koleszar committed
922
static const arg_def_t passes           = ARG_DEF("p", "passes", 1,
John Koleszar's avatar
John Koleszar committed
923
                                                  "Number of passes (1/2)");
John Koleszar's avatar
John Koleszar committed
924
static const arg_def_t pass_arg         = ARG_DEF(NULL, "pass", 1,
John Koleszar's avatar
John Koleszar committed
925
                                                  "Pass to execute (1/2)");
John Koleszar's avatar
John Koleszar committed
926
static const arg_def_t fpf_name         = ARG_DEF(NULL, "fpf", 1,
John Koleszar's avatar
John Koleszar committed
927
                                                  "First pass statistics file name");
John Koleszar's avatar
John Koleszar committed
928 929
static const arg_def_t limit = ARG_DEF(NULL, "limit", 1,
                                       "Stop encoding after n input frames");
930
static const arg_def_t skip = ARG_DEF(NULL, "skip", 1,
John Koleszar's avatar
John Koleszar committed
931
                                      "Skip the first n input frames");
John Koleszar's avatar
John Koleszar committed
932
static const arg_def_t deadline         = ARG_DEF("d", "deadline", 1,
John Koleszar's avatar
John Koleszar committed
933
                                                  "Deadline per frame (usec)");
John Koleszar's avatar
John Koleszar committed
934
static const arg_def_t best_dl          = ARG_DEF(NULL, "best", 0,
John Koleszar's avatar
John Koleszar committed
935
                                                  "Use Best Quality Deadline");
John Koleszar's avatar
John Koleszar committed
936
static const arg_def_t good_dl          = ARG_DEF(NULL, "good", 0,
John Koleszar's avatar
John Koleszar committed
937
                                                  "Use Good Quality Deadline");
John Koleszar's avatar
John Koleszar committed
938
static const arg_def_t rt_dl            = ARG_DEF(NULL, "rt", 0,
John Koleszar's avatar
John Koleszar committed
939
                                                  "Use Realtime Quality Deadline");
John Koleszar's avatar
John Koleszar committed
940 941
static const arg_def_t quietarg         = ARG_DEF("q", "quiet", 0,
                                                  "Do not print encode progress");
John Koleszar's avatar
John Koleszar committed
942
static const arg_def_t verbosearg       = ARG_DEF("v", "verbose", 0,
John Koleszar's avatar
John Koleszar committed
943
                                                  "Show encoder parameters");
John Koleszar's avatar
John Koleszar committed
944
static const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
John Koleszar's avatar
John Koleszar committed
945
                                                  "Show PSNR in status line");
946
static const arg_def_t recontest        = ARG_DEF(NULL, "test-decode", 0,
John Koleszar's avatar
John Koleszar committed
947
                                                  "Test encode/decode mismatch");
948
static const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
John Koleszar's avatar
John Koleszar committed
949
                                                  "Stream frame rate (rate/scale)");
John Koleszar's avatar
John Koleszar committed
950
static const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
John Koleszar's avatar
John Koleszar committed
951
                                                  "Output IVF (default is WebM)");
John Koleszar's avatar
John Koleszar committed
952 953
static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
                                          "Makes encoder output partitions. Requires IVF output!");
954
static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
John Koleszar's avatar
John Koleszar committed
955
                                                  "Show quantizer histogram (n-buckets)");