vpxenc.c 77.5 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

KO Myung-Hun's avatar
KO Myung-Hun committed
13
#if defined(_WIN32) || defined(__OS2__) || !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"
26
#if CONFIG_DECODERS
John Koleszar's avatar
John Koleszar committed
27
#include "vpx/vpx_decoder.h"
28
#endif
John Koleszar's avatar
John Koleszar committed
29 30 31 32 33 34 35
#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
36

37 38
#include "third_party/libyuv/include/libyuv/scale.h"

39
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
40
#include "vpx/vp8cx.h"
John Koleszar's avatar
John Koleszar committed
41
#endif
42
#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
43
#include "vpx/vp8dx.h"
John Koleszar's avatar
John Koleszar committed
44 45
#endif

John Koleszar's avatar
John Koleszar committed
46 47
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/vpx_timer.h"
John Koleszar's avatar
John Koleszar committed
48
#include "tools_common.h"
49
#include "webmenc.h"
50
#include "y4minput.h"
51

John Koleszar's avatar
John Koleszar committed
52 53 54 55 56 57 58 59

/* 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)
James Zern's avatar
James Zern committed
60 61
/* MinGW defines off_t as long
   and uses f{seek,tell}o64/off64_t for large files */
John Koleszar's avatar
John Koleszar committed
62 63
#define fseeko fseeko64
#define ftello ftello64
James Zern's avatar
James Zern committed
64
#define off_t off64_t
John Koleszar's avatar
John Koleszar committed
65 66
#endif

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

69 70 71 72 73 74 75 76
/* 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
77 78
/* Swallow warnings about unused results of fread/fwrite */
static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
John Koleszar's avatar
John Koleszar committed
79 80
                         FILE *stream) {
  return fread(ptr, size, nmemb, stream);
John Koleszar's avatar
John Koleszar committed
81 82 83 84
}
#define fread wrap_fread

static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
John Koleszar's avatar
John Koleszar committed
85 86
                          FILE *stream) {
  return fwrite(ptr, size, nmemb, stream);
John Koleszar's avatar
John Koleszar committed
87 88 89 90
}
#define fwrite wrap_fwrite


John Koleszar's avatar
John Koleszar committed
91 92
static const char *exec_name;

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

111 112
static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
                                   const char *s, va_list ap) {
John Koleszar's avatar
John Koleszar committed
113 114
  if (ctx->err) {
    const char *detail = vpx_codec_error_detail(ctx);
John Koleszar's avatar
John Koleszar committed
115

John Koleszar's avatar
John Koleszar committed
116 117
    vfprintf(stderr, s, ap);
    fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
John Koleszar's avatar
John Koleszar committed
118

John Koleszar's avatar
John Koleszar committed
119 120
    if (detail)
      fprintf(stderr, "    %s\n", detail);
John Koleszar's avatar
John Koleszar committed
121

122 123
    if (fatal)
      exit(EXIT_FAILURE);
John Koleszar's avatar
John Koleszar committed
124
  }
John Koleszar's avatar
John Koleszar committed
125 126
}

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
  va_list ap;

  va_start(ap, s);
  warn_or_exit_on_errorv(ctx, 1, s, ap);
  va_end(ap);
}

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

  va_start(ap, s);
  warn_or_exit_on_errorv(ctx, fatal, s, ap);
  va_end(ap);
}

John Koleszar's avatar
John Koleszar committed
144 145 146
/* This structure is used to abstract the different ways of handling
 * first pass statistics.
 */
John Koleszar's avatar
John Koleszar committed
147 148 149 150 151 152
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
153 154
} stats_io_t;

John Koleszar's avatar
John Koleszar committed
155 156
int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
  int res;
John Koleszar's avatar
John Koleszar committed
157

John Koleszar's avatar
John Koleszar committed
158
  stats->pass = pass;
John Koleszar's avatar
John Koleszar committed
159

John Koleszar's avatar
John Koleszar committed
160 161 162 163 164 165
  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
166 167
#if 0
#elif USE_POSIX_MMAP
John Koleszar's avatar
John Koleszar committed
168 169 170 171 172 173 174 175 176 177
    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
178
#else
John Koleszar's avatar
John Koleszar committed
179
    size_t nbytes;
John Koleszar's avatar
John Koleszar committed
180

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

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

John Koleszar's avatar
John Koleszar committed
186 187
    stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
    rewind(stats->file);
John Koleszar's avatar
John Koleszar committed
188

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

John Koleszar's avatar
John Koleszar committed
191 192 193
    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
194

John Koleszar's avatar
John Koleszar committed
195 196
    nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
    res = (nbytes == stats->buf.sz);
John Koleszar's avatar
John Koleszar committed
197
#endif
John Koleszar's avatar
John Koleszar committed
198
  }
John Koleszar's avatar
John Koleszar committed
199

John Koleszar's avatar
John Koleszar committed
200
  return res;
John Koleszar's avatar
John Koleszar committed
201 202
}

John Koleszar's avatar
John Koleszar committed
203 204 205
int stats_open_mem(stats_io_t *stats, int pass) {
  int res;
  stats->pass = pass;
John Koleszar's avatar
John Koleszar committed
206

John Koleszar's avatar
John Koleszar committed
207 208 209 210 211
  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
212

John Koleszar's avatar
John Koleszar committed
213 214 215
  stats->buf_ptr = stats->buf.buf;
  res = (stats->buf.buf != NULL);
  return res;
John Koleszar's avatar
John Koleszar committed
216 217 218
}


John Koleszar's avatar
John Koleszar committed
219 220 221
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
222 223
#if 0
#elif USE_POSIX_MMAP
John Koleszar's avatar
John Koleszar committed
224
      munmap(stats->buf.buf, stats->buf.sz);
John Koleszar's avatar
John Koleszar committed
225
#else
John Koleszar's avatar
John Koleszar committed
226
      free(stats->buf.buf);
John Koleszar's avatar
John Koleszar committed
227 228
#endif
    }
John Koleszar's avatar
John Koleszar committed
229 230 231 232 233 234 235

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

John Koleszar's avatar
John Koleszar committed
238 239
void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
  if (stats->file) {
John Koleszar's avatar
John Koleszar committed
240
    (void) fwrite(pkt, 1, len, stats->file);
John Koleszar's avatar
John Koleszar committed
241 242 243 244 245 246 247 248 249
  } 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
250 251
      } else
        fatal("Failed to realloc firstpass stats buffer.");
John Koleszar's avatar
John Koleszar committed
252 253
    }

John Koleszar's avatar
John Koleszar committed
254 255 256 257
    memcpy(stats->buf_ptr, pkt, len);
    stats->buf.sz += len;
    stats->buf_ptr += len;
  }
John Koleszar's avatar
John Koleszar committed
258 259
}

John Koleszar's avatar
John Koleszar committed
260 261
vpx_fixed_buf_t stats_get(stats_io_t *stats) {
  return stats->buf;
John Koleszar's avatar
John Koleszar committed
262 263
}

John Koleszar's avatar
John Koleszar committed
264 265 266 267
enum video_file_type {
  FILE_TYPE_RAW,
  FILE_TYPE_IVF,
  FILE_TYPE_Y4M
268 269
};

270
struct detect_buffer {
John Koleszar's avatar
John Koleszar committed
271 272 273
  char buf[4];
  size_t buf_read;
  size_t position;
274 275 276
};


John Koleszar's avatar
John Koleszar committed
277 278 279
struct input_state {
  char                 *fn;
  FILE                 *file;
280
  off_t                 length;
John Koleszar's avatar
John Koleszar committed
281 282 283 284 285 286 287
  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;
288
  int                   only_i420;
289 290 291
};


John Koleszar's avatar
John Koleszar committed
292
#define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
John Koleszar's avatar
John Koleszar committed
293 294 295 296 297
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
298 299 300 301 302 303 304 305 306 307 308 309 310 311
  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
312
      (void) fread(junk, 1, IVF_FRAME_HDR_SZ, f);
John Koleszar's avatar
John Koleszar committed
313
    }
314

John Koleszar's avatar
John Koleszar committed
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    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
346
        }
John Koleszar's avatar
John Koleszar committed
347 348
        if (needed > 0) {
          shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
John Koleszar's avatar
John Koleszar committed
349
        }
John Koleszar's avatar
John Koleszar committed
350 351 352

        ptr += img->stride[plane];
      }
John Koleszar's avatar
John Koleszar committed
353
    }
John Koleszar's avatar
John Koleszar committed
354
  }
John Koleszar's avatar
John Koleszar committed
355

John Koleszar's avatar
John Koleszar committed
356
  return !shortread;
John Koleszar's avatar
John Koleszar committed
357 358 359
}


360
unsigned int file_is_y4m(FILE      *infile,
361
                         y4m_input *y4m,
John Koleszar's avatar
John Koleszar committed
362 363 364 365 366
                         char       detect[4]) {
  if (memcmp(detect, "YUV4", 4) == 0) {
    return 1;
  }
  return 0;
367 368
}

John Koleszar's avatar
John Koleszar committed
369
#define IVF_FILE_HDR_SZ (32)
370
unsigned int file_is_ivf(struct input_state *input,
John Koleszar's avatar
John Koleszar committed
371
                         unsigned int *fourcc) {
John Koleszar's avatar
John Koleszar committed
372 373
  char raw_hdr[IVF_FILE_HDR_SZ];
  int is_ivf = 0;
John Koleszar's avatar
John Koleszar committed
374 375 376 377
  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
378

John Koleszar's avatar
John Koleszar committed
379 380
  if (memcmp(detect->buf, "DKIF", 4) != 0)
    return 0;
381

John Koleszar's avatar
John Koleszar committed
382 383 384 385 386
  /* 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
387
    {
John Koleszar's avatar
John Koleszar committed
388
      is_ivf = 1;
John Koleszar's avatar
John Koleszar committed
389

John Koleszar's avatar
John Koleszar committed
390
      if (mem_get_le16(raw_hdr + 4) != 0)
John Koleszar's avatar
John Koleszar committed
391 392
        warn("Unrecognized IVF version! This file may not decode "
             "properly.");
John Koleszar's avatar
John Koleszar committed
393

John Koleszar's avatar
John Koleszar committed
394
      *fourcc = mem_get_le32(raw_hdr + 8);
John Koleszar's avatar
John Koleszar committed
395
    }
John Koleszar's avatar
John Koleszar committed
396
  }
John Koleszar's avatar
John Koleszar committed
397

John Koleszar's avatar
John Koleszar committed
398 399 400 401 402
  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
403

John Koleszar's avatar
John Koleszar committed
404
  return is_ivf;
John Koleszar's avatar
John Koleszar committed
405 406 407 408 409 410
}


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
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
                                  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
431
  (void) fwrite(header, 1, 32, outfile);
John Koleszar's avatar
John Koleszar committed
432 433 434 435
}


static void write_ivf_frame_header(FILE *outfile,
John Koleszar's avatar
John Koleszar committed
436 437 438
                                   const vpx_codec_cx_pkt_t *pkt) {
  char             header[12];
  vpx_codec_pts_t  pts;
John Koleszar's avatar
John Koleszar committed
439

John Koleszar's avatar
John Koleszar committed
440 441
  if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
    return;
John Koleszar's avatar
John Koleszar committed
442

John Koleszar's avatar
John Koleszar committed
443
  pts = pkt->data.frame.pts;
John Koleszar's avatar
John Koleszar committed
444
  mem_put_le32(header, (int)pkt->data.frame.sz);
John Koleszar's avatar
John Koleszar committed
445 446
  mem_put_le32(header + 4, pts & 0xFFFFFFFF);
  mem_put_le32(header + 8, pts >> 32);
John Koleszar's avatar
John Koleszar committed
447

John Koleszar's avatar
John Koleszar committed
448
  (void) fwrite(header, 1, 12, outfile);
John Koleszar's avatar
John Koleszar committed
449 450
}

John Koleszar's avatar
John Koleszar committed
451 452 453 454
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);
455 456
}

John Koleszar's avatar
John Koleszar committed
457 458


John Koleszar's avatar
John Koleszar committed
459
/* Murmur hash derived from public domain reference implementation at
John Koleszar's avatar
John Koleszar committed
460
 *   http:// sites.google.com/site/murmurhash/
John Koleszar's avatar
John Koleszar committed
461
 */
John Koleszar's avatar
John Koleszar committed
462 463 464
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
465

John Koleszar's avatar
John Koleszar committed
466
  unsigned int h = seed ^ len;
John Koleszar's avatar
John Koleszar committed
467

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

John Koleszar's avatar
John Koleszar committed
470 471
  while (len >= 4) {
    unsigned int k;
John Koleszar's avatar
John Koleszar committed
472

Yaowu Xu's avatar
Yaowu Xu committed
473 474 475 476
    k  = (unsigned int)data[0];
    k |= (unsigned int)data[1] << 8;
    k |= (unsigned int)data[2] << 16;
    k |= (unsigned int)data[3] << 24;
John Koleszar's avatar
John Koleszar committed
477

John Koleszar's avatar
John Koleszar committed
478 479 480
    k *= m;
    k ^= k >> r;
    k *= m;
John Koleszar's avatar
John Koleszar committed
481 482

    h *= m;
John Koleszar's avatar
John Koleszar committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    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
504 505
}

506
#include "math.h"
507
#define MAX_PSNR 100
John Koleszar's avatar
John Koleszar committed
508 509
static double vp8_mse2psnr(double Samples, double Peak, double Mse) {
  double psnr;
510

John Koleszar's avatar
John Koleszar committed
511 512 513
  if ((double)Mse > 0.0)
    psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
  else
John Koleszar's avatar
John Koleszar committed
514
    psnr = MAX_PSNR;      /* Limit to prevent / 0 */
515

John Koleszar's avatar
John Koleszar committed
516 517
  if (psnr > MAX_PSNR)
    psnr = MAX_PSNR;
518

John Koleszar's avatar
John Koleszar committed
519
  return psnr;
520 521
}

John Koleszar's avatar
John Koleszar committed
522

John Koleszar's avatar
John Koleszar committed
523
#include "args.h"
524
static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
John Koleszar's avatar
John Koleszar committed
525
                                           "Debug mode (makes output deterministic)");
526
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
John Koleszar's avatar
John Koleszar committed
527
                                            "Output filename");
John Koleszar's avatar
John Koleszar committed
528
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
John Koleszar's avatar
John Koleszar committed
529
                                          "Input file is YV12 ");
John Koleszar's avatar
John Koleszar committed
530
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
John Koleszar's avatar
John Koleszar committed
531
                                          "Input file is I420 (default)");
John Koleszar's avatar
John Koleszar committed
532
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
John Koleszar's avatar
John Koleszar committed
533
                                          "Codec to use");
John Koleszar's avatar
John Koleszar committed
534
static const arg_def_t passes           = ARG_DEF("p", "passes", 1,
John Koleszar's avatar
John Koleszar committed
535
                                                  "Number of passes (1/2)");
John Koleszar's avatar
John Koleszar committed
536
static const arg_def_t pass_arg         = ARG_DEF(NULL, "pass", 1,
John Koleszar's avatar
John Koleszar committed
537
                                                  "Pass to execute (1/2)");
John Koleszar's avatar
John Koleszar committed
538
static const arg_def_t fpf_name         = ARG_DEF(NULL, "fpf", 1,
John Koleszar's avatar
John Koleszar committed
539
                                                  "First pass statistics file name");
John Koleszar's avatar
John Koleszar committed
540 541
static const arg_def_t limit = ARG_DEF(NULL, "limit", 1,
                                       "Stop encoding after n input frames");
542
static const arg_def_t skip = ARG_DEF(NULL, "skip", 1,
John Koleszar's avatar
John Koleszar committed
543
                                      "Skip the first n input frames");
John Koleszar's avatar
John Koleszar committed
544
static const arg_def_t deadline         = ARG_DEF("d", "deadline", 1,
John Koleszar's avatar
John Koleszar committed
545
                                                  "Deadline per frame (usec)");
John Koleszar's avatar
John Koleszar committed
546
static const arg_def_t best_dl          = ARG_DEF(NULL, "best", 0,
John Koleszar's avatar
John Koleszar committed
547
                                                  "Use Best Quality Deadline");
John Koleszar's avatar
John Koleszar committed
548
static const arg_def_t good_dl          = ARG_DEF(NULL, "good", 0,
John Koleszar's avatar
John Koleszar committed
549
                                                  "Use Good Quality Deadline");
John Koleszar's avatar
John Koleszar committed
550
static const arg_def_t rt_dl            = ARG_DEF(NULL, "rt", 0,
John Koleszar's avatar
John Koleszar committed
551
                                                  "Use Realtime Quality Deadline");
James Zern's avatar
James Zern committed
552
static const arg_def_t quietarg         = ARG_DEF("q", "quiet", 0,
John Koleszar's avatar
John Koleszar committed
553
                                                  "Do not print encode progress");
John Koleszar's avatar
John Koleszar committed
554
static const arg_def_t verbosearg       = ARG_DEF("v", "verbose", 0,
John Koleszar's avatar
John Koleszar committed
555
                                                  "Show encoder parameters");
John Koleszar's avatar
John Koleszar committed
556
static const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
John Koleszar's avatar
John Koleszar committed
557
                                                  "Show PSNR in status line");
558 559 560 561 562 563 564 565 566 567 568 569 570 571
enum TestDecodeFatality {
  TEST_DECODE_OFF,
  TEST_DECODE_FATAL,
  TEST_DECODE_WARN,
};
static const struct arg_enum_list test_decode_enum[] = {
  {"off",   TEST_DECODE_OFF},
  {"fatal", TEST_DECODE_FATAL},
  {"warn",  TEST_DECODE_WARN},
  {NULL, 0}
};
static const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1,
                                                "Test encode/decode mismatch",
                                                test_decode_enum);
572
static const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
John Koleszar's avatar
John Koleszar committed
573
                                                  "Stream frame rate (rate/scale)");
John Koleszar's avatar
John Koleszar committed
574
static const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
John Koleszar's avatar
John Koleszar committed
575
                                                  "Output IVF (default is WebM)");
576
static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
John Koleszar's avatar
John Koleszar committed
577
                                          "Makes encoder output partitions. Requires IVF output!");
578
static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
John Koleszar's avatar
John Koleszar committed
579
                                                  "Show quantizer histogram (n-buckets)");
580
static const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
John Koleszar's avatar
John Koleszar committed
581 582 583 584
                                                     "Show rate histogram (n-buckets)");
static const arg_def_t *main_args[] = {
  &debugmode,
  &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip,
John Koleszar's avatar
John Koleszar committed
585 586
  &deadline, &best_dl, &good_dl, &rt_dl,
  &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
John Koleszar's avatar
John Koleszar committed
587
  NULL
John Koleszar's avatar
John Koleszar committed
588 589 590
};

static const arg_def_t usage            = ARG_DEF("u", "usage", 1,
John Koleszar's avatar
John Koleszar committed
591
                                                  "Usage profile number to use");
John Koleszar's avatar
John Koleszar committed
592
static const arg_def_t threads          = ARG_DEF("t", "threads", 1,
John Koleszar's avatar
John Koleszar committed
593
                                                  "Max number of threads to use");
John Koleszar's avatar
John Koleszar committed
594
static const arg_def_t profile          = ARG_DEF(NULL, "profile", 1,
John Koleszar's avatar
John Koleszar committed
595
                                                  "Bitstream profile number to use");
John Koleszar's avatar
John Koleszar committed
596
static const arg_def_t width            = ARG_DEF("w", "width", 1,
John Koleszar's avatar
John Koleszar committed
597
                                                  "Frame width");
John Koleszar's avatar
John Koleszar committed
598
static const arg_def_t height           = ARG_DEF("h", "height", 1,
John Koleszar's avatar
John Koleszar committed
599
                                                  "Frame height");
600
static const struct arg_enum_list stereo_mode_enum[] = {
John Koleszar's avatar
John Koleszar committed
601 602 603 604 605 606
  {"mono", STEREO_FORMAT_MONO},
  {"left-right", STEREO_FORMAT_LEFT_RIGHT},
  {"bottom-top", STEREO_FORMAT_BOTTOM_TOP},
  {"top-bottom", STEREO_FORMAT_TOP_BOTTOM},
  {"right-left", STEREO_FORMAT_RIGHT_LEFT},
  {NULL, 0}
607 608
};
static const arg_def_t stereo_mode      = ARG_DEF_ENUM(NULL, "stereo-mode", 1,
John Koleszar's avatar
John Koleszar committed
609
                                                       "Stereo 3D video format", stereo_mode_enum);
John Koleszar's avatar
John Koleszar committed
610
static const arg_def_t timebase         = ARG_DEF(NULL, "timebase", 1,
John Koleszar's avatar
John Koleszar committed
611
                                                  "Output timestamp precision (fractional seconds)");
John Koleszar's avatar
John Koleszar committed
612
static const arg_def_t error_resilient  = ARG_DEF(NULL, "error-resilient", 1,
John Koleszar's avatar
John Koleszar committed
613
                                                  "Enable error resiliency features");
John Koleszar's avatar
John Koleszar committed
614
static const arg_def_t lag_in_frames    = ARG_DEF(NULL, "lag-in-frames", 1,
John Koleszar's avatar
John Koleszar committed
615
                                                  "Max number of frames to lag");
John Koleszar's avatar
John Koleszar committed
616

John Koleszar's avatar
John Koleszar committed
617 618
static const arg_def_t *global_args[] = {
  &use_yv12, &use_i420, &usage, &threads, &profile,
619 620
  &width, &height, &stereo_mode, &timebase, &framerate,
  &error_resilient,
John Koleszar's avatar
John Koleszar committed
621
  &lag_in_frames, NULL
John Koleszar's avatar
John Koleszar committed
622 623 624
};

static const arg_def_t dropframe_thresh   = ARG_DEF(NULL, "drop-frame", 1,
John Koleszar's avatar
John Koleszar committed
625
                                                    "Temporal resampling threshold (buf %)");
John Koleszar's avatar
John Koleszar committed
626
static const arg_def_t resize_allowed     = ARG_DEF(NULL, "resize-allowed", 1,
John Koleszar's avatar
John Koleszar committed
627
                                                    "Spatial resampling enabled (bool)");
John Koleszar's avatar
John Koleszar committed
628
static const arg_def_t resize_up_thresh   = ARG_DEF(NULL, "resize-up", 1,
John Koleszar's avatar
John Koleszar committed
629
                                                    "Upscale threshold (buf %)");
John Koleszar's avatar
John Koleszar committed
630
static const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1,
John Koleszar's avatar
John Koleszar committed
631
                                                    "Downscale threshold (buf %)");
632
static const struct arg_enum_list end_usage_enum[] = {
John Koleszar's avatar
John Koleszar committed
633 634 635
  {"vbr", VPX_VBR},
  {"cbr", VPX_CBR},
  {"cq",  VPX_CQ},
636
  {"q",   VPX_Q},
John Koleszar's avatar
John Koleszar committed
637
  {NULL, 0}
638 639
};
static const arg_def_t end_usage          = ARG_DEF_ENUM(NULL, "end-usage", 1,
John Koleszar's avatar
John Koleszar committed
640
                                                         "Rate control mode", end_usage_enum);
John Koleszar's avatar
John Koleszar committed
641
static const arg_def_t target_bitrate     = ARG_DEF(NULL, "target-bitrate", 1,
John Koleszar's avatar
John Koleszar committed
642
                                                    "Bitrate (kbps)");
John Koleszar's avatar
John Koleszar committed
643
static const arg_def_t min_quantizer      = ARG_DEF(NULL, "min-q", 1,
John Koleszar's avatar
John Koleszar committed
644
                                                    "Minimum (best) quantizer");
John Koleszar's avatar
John Koleszar committed
645
static const arg_def_t max_quantizer      = ARG_DEF(NULL, "max-q", 1,
John Koleszar's avatar
John Koleszar committed
646
                                                    "Maximum (worst) quantizer");
John Koleszar's avatar
John Koleszar committed
647
static const arg_def_t undershoot_pct     = ARG_DEF(NULL, "undershoot-pct", 1,
John Koleszar's avatar
John Koleszar committed
648
                                                    "Datarate undershoot (min) target (%)");
John Koleszar's avatar
John Koleszar committed
649
static const arg_def_t overshoot_pct      = ARG_DEF(NULL, "overshoot-pct", 1,
John Koleszar's avatar
John Koleszar committed
650
                                                    "Datarate overshoot (max) target (%)");
John Koleszar's avatar
John Koleszar committed
651
static const arg_def_t buf_sz             = ARG_DEF(NULL, "buf-sz", 1,
John Koleszar's avatar
John Koleszar committed
652
                                                    "Client buffer size (ms)");
John Koleszar's avatar
John Koleszar committed
653
static const arg_def_t buf_initial_sz     = ARG_DEF(NULL, "buf-initial-sz", 1,
John Koleszar's avatar
John Koleszar committed
654
                                                    "Client initial buffer size (ms)");
John Koleszar's avatar
John Koleszar committed
655
static const arg_def_t buf_optimal_sz     = ARG_DEF(NULL, "buf-optimal-sz", 1,
John Koleszar's avatar
John Koleszar committed
656 657 658 659 660 661
                                                    "Client optimal buffer size (ms)");
static const arg_def_t *rc_args[] = {
  &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh,
  &end_usage, &target_bitrate, &min_quantizer, &max_quantizer,
  &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz,
  NULL
John Koleszar's avatar
John Koleszar committed
662 663 664 665
};


static const arg_def_t bias_pct = ARG_DEF(NULL, "bias-pct", 1,
John Koleszar's avatar
John Koleszar committed
666
                                          "CBR/VBR bias (0=CBR, 100=VBR)");
John Koleszar's avatar
John Koleszar committed
667
static const arg_def_t minsection_pct = ARG_DEF(NULL, "minsection-pct", 1,
John Koleszar's avatar
John Koleszar committed
668
                                                "GOP min bitrate (% of target)");
John Koleszar's avatar
John Koleszar committed
669
static const arg_def_t maxsection_pct = ARG_DEF(NULL, "maxsection-pct", 1,
John Koleszar's avatar
John Koleszar committed
670 671 672
                                                "GOP max bitrate (% of target)");
static const arg_def_t *rc_twopass_args[] = {
  &bias_pct, &minsection_pct, &maxsection_pct, NULL
John Koleszar's avatar
John Koleszar committed
673 674 675 676
};


static const arg_def_t kf_min_dist = ARG_DEF(NULL, "kf-min-dist", 1,
John Koleszar's avatar
John Koleszar committed
677
                                             "Minimum keyframe interval (frames)");
John Koleszar's avatar
John Koleszar committed
678
static const arg_def_t kf_max_dist = ARG_DEF(NULL, "kf-max-dist", 1,
John Koleszar's avatar
John Koleszar committed
679
                                             "Maximum keyframe interval (frames)");
680
static const arg_def_t kf_disabled = ARG_DEF(NULL, "disable-kf", 0,
John Koleszar's avatar
John Koleszar committed
681 682 683
                                             "Disable keyframe placement");
static const arg_def_t *kf_args[] = {
  &kf_min_dist, &kf_max_dist, &kf_disabled, NULL
John Koleszar's avatar
John Koleszar committed
684 685 686 687
};


static const arg_def_t noise_sens = ARG_DEF(NULL, "noise-sensitivity", 1,
John Koleszar's avatar
John Koleszar committed
688
                                            "Noise sensitivity (frames to blur)");
John Koleszar's avatar
John Koleszar committed
689
static const arg_def_t sharpness = ARG_DEF(NULL, "sharpness", 1,
John Koleszar's avatar
John Koleszar committed
690
                                           "Filter sharpness (0-7)");
John Koleszar's avatar
John Koleszar committed
691
static const arg_def_t static_thresh = ARG_DEF(NULL, "static-thresh", 1,
John Koleszar's avatar
John Koleszar committed
692
                                               "Motion detection threshold");
John Koleszar's avatar
John Koleszar committed
693
static const arg_def_t cpu_used = ARG_DEF(NULL, "cpu-used", 1,
John Koleszar's avatar
John Koleszar committed
694
                                          "CPU Used (-16..16)");
John Koleszar's avatar
John Koleszar committed
695
static const arg_def_t token_parts = ARG_DEF(NULL, "token-parts", 1,
696 697 698
                                     "Number of token partitions to use, log2");
static const arg_def_t tile_cols = ARG_DEF(NULL, "tile-columns", 1,
                                         "Number of tile columns to use, log2");
Ronald S. Bultje's avatar
Ronald S. Bultje committed
699 700
static const arg_def_t tile_rows = ARG_DEF(NULL, "tile-rows", 1,
                                           "Number of tile rows to use, log2");
John Koleszar's avatar
John Koleszar committed
701
static const arg_def_t auto_altref = ARG_DEF(NULL, "auto-alt-ref", 1,
John Koleszar's avatar
John Koleszar committed
702
                                             "Enable automatic alt reference frames");
John Koleszar's avatar
John Koleszar committed
703
static const arg_def_t arnr_maxframes = ARG_DEF(NULL, "arnr-maxframes", 1,
John Koleszar's avatar
John Koleszar committed
704
                                                "AltRef Max Frames");
John Koleszar's avatar
John Koleszar committed
705
static const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1,
John Koleszar's avatar
John Koleszar committed
706
                                               "AltRef Strength");
John Koleszar's avatar
John Koleszar committed
707
static const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1,
John Koleszar's avatar
John Koleszar committed
708
                                           "AltRef Type");
John Koleszar's avatar
John Koleszar committed
709
static const struct arg_enum_list tuning_enum[] = {
John Koleszar's avatar
John Koleszar committed
710 711 712
  {"psnr", VP8_TUNE_PSNR},
  {"ssim", VP8_TUNE_SSIM},
  {NULL, 0}
John Koleszar's avatar
John Koleszar committed
713 714
};
static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
John Koleszar's avatar
John Koleszar committed
715
                                                "Material to favor", tuning_enum);
Paul Wilkins's avatar
CQ Mode  
Paul Wilkins committed
716
static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
717
                                          "Constant/Constrained Quality level");
718
static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
John Koleszar's avatar
John Koleszar committed
719
                                                    "Max I-frame bitrate (pct)");
John Koleszar's avatar
John Koleszar committed
720
static const arg_def_t lossless = ARG_DEF(NULL, "lossless", 1, "Lossless mode");
721 722 723 724
#if CONFIG_VP9_ENCODER
static const arg_def_t frame_parallel_decoding  = ARG_DEF(
    NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
#endif
John Koleszar's avatar
John Koleszar committed
725

726
#if CONFIG_VP8_ENCODER
John Koleszar's avatar
John Koleszar committed
727 728 729
static const arg_def_t *vp8_args[] = {
  &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
  &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
John Koleszar's avatar
John Koleszar committed
730
  &tune_ssim, &cq_level, &max_intra_rate_pct,
731
  NULL
John Koleszar's avatar
John Koleszar committed
732
};
733 734 735 736 737 738 739 740 741 742 743 744 745
static const int vp8_arg_ctrl_map[] = {
  VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
  VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
  VP8E_SET_TOKEN_PARTITIONS,
  VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
  VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
  0
};
#endif

#if CONFIG_VP9_ENCODER
static const arg_def_t *vp9_args[] = {
  &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
746
  &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
Yaowu Xu's avatar
Yaowu Xu committed
747
  &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
748
  &frame_parallel_decoding,
John Koleszar's avatar
John Koleszar committed
749
  NULL
John Koleszar's avatar
John Koleszar committed
750
};
751
static const int vp9_arg_ctrl_map[] = {
John Koleszar's avatar
John Koleszar committed
752 753
  VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
  VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
754
  VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
John Koleszar's avatar
John Koleszar committed
755
  VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
John Koleszar's avatar
John Koleszar committed
756
  VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
757
  VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING,
John Koleszar's avatar
John Koleszar committed
758
  0
John Koleszar's avatar
John Koleszar committed
759 760 761 762 763
};
#endif

static const arg_def_t *no_args[] = { NULL };

764
void usage_exit() {
John Koleszar's avatar
John Koleszar committed
765 766 767 768 769 770
  int i;

  fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
          exec_name);

  fprintf(stderr, "\nOptions:\n");
John Koleszar's avatar
John Koleszar committed
771
  arg_show_usage(stderr, main_args);
John Koleszar's avatar
John Koleszar committed
772
  fprintf(stderr, "\nEncoder Global Options:\n");
John Koleszar's avatar
John Koleszar committed
773
  arg_show_usage(stderr, global_args);
John Koleszar's avatar
John Koleszar committed
774
  fprintf(stderr, "\nRate Control Options:\n");
John Koleszar's avatar
John Koleszar committed
775
  arg_show_usage(stderr, rc_args);
John Koleszar's avatar
John Koleszar committed
776
  fprintf(stderr, "\nTwopass Rate Control Options:\n");
John Koleszar's avatar
John Koleszar committed
777
  arg_show_usage(stderr, rc_twopass_args);
John Koleszar's avatar
John Koleszar committed
778
  fprintf(stderr, "\nKeyframe Placement Options:\n");
John Koleszar's avatar
John Koleszar committed
779
  arg_show_usage(stderr, kf_args);
John Koleszar's avatar
John Koleszar committed
780
#if CONFIG_VP8_ENCODER
John Koleszar's avatar
John Koleszar committed
781
  fprintf(stderr, "\nVP8 Specific Options:\n");
John Koleszar's avatar
John Koleszar committed
782
  arg_show_usage(stderr, vp8_args);
John Koleszar's avatar
John Koleszar committed
783
#endif
784 785
#if CONFIG_VP9_ENCODER
  fprintf(stderr, "\nVP9 Specific Options:\n");
John Koleszar's avatar
John Koleszar committed
786
  arg_show_usage(stderr, vp9_args);
John Koleszar's avatar
John Koleszar committed
787
#endif
John Koleszar's avatar
John Koleszar committed
788 789 790 791 792 793 794 795 796 797
  fprintf(stderr, "\nStream timebase (--timebase):\n"
          "  The desired precision of timestamps in the output, expressed\n"
          "  in fractional seconds. Default is 1/1000.\n");
  fprintf(stderr, "\n"
          "Included encoders:\n"
          "\n");

  for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
    fprintf(stderr, "    %-6s - %s\n",
            codecs[i].name,
Jim Bankoski's avatar
Jim Bankoski committed
798
            vpx_codec_iface_name(codecs[i].iface()));
John Koleszar's avatar
John Koleszar committed
799 800

  exit(EXIT_FAILURE);
John Koleszar's avatar
John Koleszar committed
801 802
}

803 804

#define HIST_BAR_MAX 40
John Koleszar's avatar
John Koleszar committed
805 806
struct hist_bucket {
  int low, high, count;
807 808 809 810 811
};


static int merge_hist_buckets(struct hist_bucket *bucket,
                              int *buckets_,
John Koleszar's avatar
John Koleszar committed
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
                              int max_buckets) {
  int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
  int buckets = *buckets_;
  int i;

  /* Find the extrema for this list of buckets */
  big_bucket = small_bucket = 0;
  for (i = 0; i < buckets; i++) {
    if (bucket[i].count < bucket[small_bucket].count)
      small_bucket = i;
    if (bucket[i].count > bucket[big_bucket].count)
      big_bucket = i;
  }

  /* If we have too many buckets, merge the smallest with an adjacent
   * bucket.
   */
  while (buckets > max_buckets) {
    int last_bucket = buckets - 1;

John Koleszar's avatar
John Koleszar committed
832
    /* merge the small bucket with an adjacent one. */
John Koleszar's avatar
John Koleszar committed
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
    if (small_bucket == 0)
      merge_bucket = 1;
    else if (small_bucket == last_bucket)
      merge_bucket = last_bucket - 1;
    else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
      merge_bucket = small_bucket - 1;
    else
      merge_bucket = small_bucket + 1;

    assert(abs(merge_bucket - small_bucket) <= 1);
    assert(small_bucket < buckets);
    assert(big_bucket < buckets);
    assert(merge_bucket < buckets);

    if (merge_bucket < small_bucket) {
      bucket[merge_bucket].high = bucket[small_bucket].high;
      bucket[merge_bucket].count += bucket[small_bucket].count;
    } else {
      bucket[small_bucket].high = bucket[merge_bucket].high;
      bucket[small_bucket].count += bucket[merge_bucket].count;
      merge_bucket = small_bucket;
854 855
    }

John Koleszar's avatar
John Koleszar committed
856
    assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
857

John Koleszar's avatar
John Koleszar committed
858
    buckets--;
859

John Koleszar's avatar
John Koleszar committed
860 861 862 863 864 865 866 867 868 869 870 871
    /* Remove the merge_bucket from the list, and find the new small
     * and big buckets while we're at it
     */
    big_bucket = small_bucket = 0;
    for (i = 0; i < buckets; i++) {
      if (i > merge_bucket)
        bucket[i] = bucket[i + 1];

      if (bucket[i].count < bucket[small_bucket].count)
        small_bucket = i;
      if (bucket[i].count > bucket[big_bucket].count)
        big_bucket = i;
872 873
    }

John Koleszar's avatar
John Koleszar committed
874 875 876 877
  }

  *buckets_ = buckets;
  return bucket[big_bucket].count;
878 879 880 881 882 883
}


static void show_histogram(const struct hist_bucket *bucket,
                           int                       buckets,
                           int                       total,
John Koleszar's avatar
John Koleszar committed
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
                           int                       scale) {
  const char *pat1, *pat2;
  int i;

  switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
    case 1:
    case 2:
      pat1 = "%4d %2s: ";
      pat2 = "%4d-%2d: ";
      break;
    case 3:
      pat1 = "%5d %3s: ";
      pat2 = "%5d-%3d: ";
      break;
    case 4:
      pat1 = "%6d %4s: ";
      pat2 = "%6d-%4d: ";
      break;
    case 5:
      pat1 = "%7d %5s: ";
      pat2 = "%7d-%5d: ";
      break;
    case 6:
      pat1 = "%8d %6s: ";
      pat2 = "%8d-%6d: ";
      break;
    case 7:
      pat1 = "%9d %7s: ";
      pat2 = "%9d-%7d: ";
      break;
    default:
      pat1 = "%12d %10s: ";
      pat2 = "%12d-%10d: ";
      break;
  }

  for (i = 0; i < buckets; i++) {
    int len;
    int j;
    float pct;

John Koleszar's avatar
John Koleszar committed
925
    pct = (float)(100.0 * bucket[i].count / total);
John Koleszar's avatar
John Koleszar committed
926 927 928 929 930 931 932 933 934
    len = HIST_BAR_MAX * bucket[i].count / scale;
    if (len < 1)
      len = 1;
    assert(len <= HIST_BAR_MAX);

    if (bucket[i].low == bucket[i].high)
      fprintf(stderr, pat1, bucket[i].low, "");
    else
      fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
935

John Koleszar's avatar
John Koleszar committed
936 937 938 939
    for (j = 0; j < HIST_BAR_MAX; j++)
      fprintf(stderr, j < len ? "=" : " ");
    fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
  }
940 941 942
}


John Koleszar's avatar
John Koleszar committed
943 944 945 946 947 948
static void show_q_histogram(const int counts[64], int max_buckets) {
  struct hist_bucket bucket[64];
  int buckets = 0;
  int total = 0;
  int scale;
  int i;
949 950


John Koleszar's avatar
John Koleszar committed
951 952 953 954 955 956
  for (i = 0; i < 64; i++) {
    if (counts[i]) {
      bucket[buckets].low = bucket[buckets].high = i;
      bucket[buckets].count = counts[i];
      buckets++;
      total += counts[i];
957
    }
John Koleszar's avatar
John Koleszar committed
958
  }
959

John Koleszar's avatar
John Koleszar committed
960 961 962
  fprintf(stderr, "\nQuantizer Selection:\n");
  scale = merge_hist_buckets(bucket, &buckets, max_buckets);
  show_histogram(bucket, buckets, total, scale);
963 964 965
}


966
#define RATE_BINS (100)
John Koleszar's avatar
John Koleszar committed
967 968 969 970 971 972 973
struct rate_hist {
  int64_t            *pts;
  int                *sz;
  int                 samples;
  int                 frames;
  struct hist_bucket  bucket[RATE_BINS];
  int                 total;
974 975 976 977
};


static void init_rate_histogram(struct rate_hist          *hist,
978
                                const vpx_codec_enc_cfg_t *cfg,
John Koleszar's avatar
John Koleszar committed
979 980 981 982 983 984 985 986 987
                                const vpx_rational_t      *fps) {
  int i;

  /* Determine the number of samples in the buffer. Use the file's framerate
   * to determine the number of frames in rc_buf_sz milliseconds, with an
   * adjustment (5/4) to account for alt-refs
   */
  hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;