Home | History | Annotate | Download | only in libvpx
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  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.
      9  */
     10 
     11 #include "./vpx_config.h"
     12 
     13 #if defined(_WIN32) || defined(__OS2__) || !CONFIG_OS_SUPPORT
     14 #define USE_POSIX_MMAP 0
     15 #else
     16 #define USE_POSIX_MMAP 1
     17 #endif
     18 
     19 #include <math.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <stdarg.h>
     23 #include <string.h>
     24 #include <limits.h>
     25 #include <assert.h>
     26 #include "vpx/vpx_encoder.h"
     27 #if CONFIG_DECODERS
     28 #include "vpx/vpx_decoder.h"
     29 #endif
     30 #if USE_POSIX_MMAP
     31 #include <sys/types.h>
     32 #include <sys/stat.h>
     33 #include <sys/mman.h>
     34 #include <fcntl.h>
     35 #include <unistd.h>
     36 #endif
     37 
     38 #include "third_party/libyuv/include/libyuv/scale.h"
     39 
     40 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
     41 #include "vpx/vp8cx.h"
     42 #endif
     43 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
     44 #include "vpx/vp8dx.h"
     45 #endif
     46 
     47 #include "./tools_common.h"
     48 #include "vpx_ports/mem_ops.h"
     49 #include "vpx_ports/vpx_timer.h"
     50 #include "./vpxstats.h"
     51 #include "./webmenc.h"
     52 #include "./y4minput.h"
     53 
     54 /* Swallow warnings about unused results of fread/fwrite */
     55 static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
     56                          FILE *stream) {
     57   return fread(ptr, size, nmemb, stream);
     58 }
     59 #define fread wrap_fread
     60 
     61 static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
     62                           FILE *stream) {
     63   return fwrite(ptr, size, nmemb, stream);
     64 }
     65 #define fwrite wrap_fwrite
     66 
     67 
     68 static const char *exec_name;
     69 
     70 static const struct codec_item {
     71   char const              *name;
     72   const vpx_codec_iface_t *(*iface)(void);
     73   const vpx_codec_iface_t *(*dx_iface)(void);
     74   unsigned int             fourcc;
     75 } codecs[] = {
     76 #if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
     77   {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC},
     78 #elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER
     79   {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC},
     80 #endif
     81 #if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
     82   {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC},
     83 #elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
     84   {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC},
     85 #endif
     86 };
     87 
     88 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
     89                                    const char *s, va_list ap) {
     90   if (ctx->err) {
     91     const char *detail = vpx_codec_error_detail(ctx);
     92 
     93     vfprintf(stderr, s, ap);
     94     fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
     95 
     96     if (detail)
     97       fprintf(stderr, "    %s\n", detail);
     98 
     99     if (fatal)
    100       exit(EXIT_FAILURE);
    101   }
    102 }
    103 
    104 static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
    105   va_list ap;
    106 
    107   va_start(ap, s);
    108   warn_or_exit_on_errorv(ctx, 1, s, ap);
    109   va_end(ap);
    110 }
    111 
    112 static void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal,
    113                                   const char *s, ...) {
    114   va_list ap;
    115 
    116   va_start(ap, s);
    117   warn_or_exit_on_errorv(ctx, fatal, s, ap);
    118   va_end(ap);
    119 }
    120 
    121 enum video_file_type {
    122   FILE_TYPE_RAW,
    123   FILE_TYPE_IVF,
    124   FILE_TYPE_Y4M
    125 };
    126 
    127 struct detect_buffer {
    128   char buf[4];
    129   size_t buf_read;
    130   size_t position;
    131 };
    132 
    133 
    134 struct input_state {
    135   char                 *fn;
    136   FILE                 *file;
    137   off_t                 length;
    138   y4m_input             y4m;
    139   struct detect_buffer  detect;
    140   enum video_file_type  file_type;
    141   unsigned int          w;
    142   unsigned int          h;
    143   struct vpx_rational   framerate;
    144   int                   use_i420;
    145   int                   only_i420;
    146 };
    147 
    148 #define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
    149 static int read_frame(struct input_state *input, vpx_image_t *img) {
    150   FILE *f = input->file;
    151   enum video_file_type file_type = input->file_type;
    152   y4m_input *y4m = &input->y4m;
    153   struct detect_buffer *detect = &input->detect;
    154   int plane = 0;
    155   int shortread = 0;
    156 
    157   if (file_type == FILE_TYPE_Y4M) {
    158     if (y4m_input_fetch_frame(y4m, f, img) < 1)
    159       return 0;
    160   } else {
    161     if (file_type == FILE_TYPE_IVF) {
    162       char junk[IVF_FRAME_HDR_SZ];
    163 
    164       /* Skip the frame header. We know how big the frame should be. See
    165        * write_ivf_frame_header() for documentation on the frame header
    166        * layout.
    167        */
    168       (void) fread(junk, 1, IVF_FRAME_HDR_SZ, f);
    169     }
    170 
    171     for (plane = 0; plane < 3; plane++) {
    172       unsigned char *ptr;
    173       int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
    174       int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
    175       int r;
    176 
    177       /* Determine the correct plane based on the image format. The for-loop
    178        * always counts in Y,U,V order, but this may not match the order of
    179        * the data on disk.
    180        */
    181       switch (plane) {
    182         case 1:
    183           ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V : VPX_PLANE_U];
    184           break;
    185         case 2:
    186           ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U : VPX_PLANE_V];
    187           break;
    188         default:
    189           ptr = img->planes[plane];
    190       }
    191 
    192       for (r = 0; r < h; r++) {
    193         size_t needed = w;
    194         size_t buf_position = 0;
    195         const size_t left = detect->buf_read - detect->position;
    196         if (left > 0) {
    197           const size_t more = (left < needed) ? left : needed;
    198           memcpy(ptr, detect->buf + detect->position, more);
    199           buf_position = more;
    200           needed -= more;
    201           detect->position += more;
    202         }
    203         if (needed > 0) {
    204           shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
    205         }
    206 
    207         ptr += img->stride[plane];
    208       }
    209     }
    210   }
    211 
    212   return !shortread;
    213 }
    214 
    215 
    216 unsigned int file_is_y4m(FILE      *infile,
    217                          y4m_input *y4m,
    218                          char       detect[4]) {
    219   if (memcmp(detect, "YUV4", 4) == 0) {
    220     return 1;
    221   }
    222   return 0;
    223 }
    224 
    225 #define IVF_FILE_HDR_SZ (32)
    226 unsigned int file_is_ivf(struct input_state *input,
    227                          unsigned int *fourcc) {
    228   char raw_hdr[IVF_FILE_HDR_SZ];
    229   int is_ivf = 0;
    230   FILE *infile = input->file;
    231   unsigned int *width = &input->w;
    232   unsigned int *height = &input->h;
    233   struct detect_buffer *detect = &input->detect;
    234 
    235   if (memcmp(detect->buf, "DKIF", 4) != 0)
    236     return 0;
    237 
    238   /* See write_ivf_file_header() for more documentation on the file header
    239    * layout.
    240    */
    241   if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
    242       == IVF_FILE_HDR_SZ - 4) {
    243     {
    244       is_ivf = 1;
    245 
    246       if (mem_get_le16(raw_hdr + 4) != 0)
    247         warn("Unrecognized IVF version! This file may not decode "
    248              "properly.");
    249 
    250       *fourcc = mem_get_le32(raw_hdr + 8);
    251     }
    252   }
    253 
    254   if (is_ivf) {
    255     *width = mem_get_le16(raw_hdr + 12);
    256     *height = mem_get_le16(raw_hdr + 14);
    257     detect->position = 4;
    258   }
    259 
    260   return is_ivf;
    261 }
    262 
    263 
    264 static void write_ivf_file_header(FILE *outfile,
    265                                   const vpx_codec_enc_cfg_t *cfg,
    266                                   unsigned int fourcc,
    267                                   int frame_cnt) {
    268   char header[32];
    269 
    270   if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
    271     return;
    272 
    273   header[0] = 'D';
    274   header[1] = 'K';
    275   header[2] = 'I';
    276   header[3] = 'F';
    277   mem_put_le16(header + 4,  0);                 /* version */
    278   mem_put_le16(header + 6,  32);                /* headersize */
    279   mem_put_le32(header + 8,  fourcc);            /* headersize */
    280   mem_put_le16(header + 12, cfg->g_w);          /* width */
    281   mem_put_le16(header + 14, cfg->g_h);          /* height */
    282   mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
    283   mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
    284   mem_put_le32(header + 24, frame_cnt);         /* length */
    285   mem_put_le32(header + 28, 0);                 /* unused */
    286 
    287   (void) fwrite(header, 1, 32, outfile);
    288 }
    289 
    290 
    291 static void write_ivf_frame_header(FILE *outfile,
    292                                    const vpx_codec_cx_pkt_t *pkt) {
    293   char             header[12];
    294   vpx_codec_pts_t  pts;
    295 
    296   if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
    297     return;
    298 
    299   pts = pkt->data.frame.pts;
    300   mem_put_le32(header, (int)pkt->data.frame.sz);
    301   mem_put_le32(header + 4, pts & 0xFFFFFFFF);
    302   mem_put_le32(header + 8, pts >> 32);
    303 
    304   (void) fwrite(header, 1, 12, outfile);
    305 }
    306 
    307 static void write_ivf_frame_size(FILE *outfile, size_t size) {
    308   char             header[4];
    309   mem_put_le32(header, (int)size);
    310   (void) fwrite(header, 1, 4, outfile);
    311 }
    312 
    313 
    314 
    315 /* Murmur hash derived from public domain reference implementation at
    316  *   http:// sites.google.com/site/murmurhash/
    317  */
    318 static unsigned int murmur(const void *key, int len, unsigned int seed) {
    319   const unsigned int m = 0x5bd1e995;
    320   const int r = 24;
    321 
    322   unsigned int h = seed ^ len;
    323 
    324   const unsigned char *data = (const unsigned char *)key;
    325 
    326   while (len >= 4) {
    327     unsigned int k;
    328 
    329     k  = (unsigned int)data[0];
    330     k |= (unsigned int)data[1] << 8;
    331     k |= (unsigned int)data[2] << 16;
    332     k |= (unsigned int)data[3] << 24;
    333 
    334     k *= m;
    335     k ^= k >> r;
    336     k *= m;
    337 
    338     h *= m;
    339     h ^= k;
    340 
    341     data += 4;
    342     len -= 4;
    343   }
    344 
    345   switch (len) {
    346     case 3:
    347       h ^= data[2] << 16;
    348     case 2:
    349       h ^= data[1] << 8;
    350     case 1:
    351       h ^= data[0];
    352       h *= m;
    353   };
    354 
    355   h ^= h >> 13;
    356   h *= m;
    357   h ^= h >> 15;
    358 
    359   return h;
    360 }
    361 
    362 
    363 #include "args.h"
    364 static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
    365                                            "Debug mode (makes output deterministic)");
    366 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
    367                                             "Output filename");
    368 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
    369                                           "Input file is YV12 ");
    370 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
    371                                           "Input file is I420 (default)");
    372 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
    373                                           "Codec to use");
    374 static const arg_def_t passes           = ARG_DEF("p", "passes", 1,
    375                                                   "Number of passes (1/2)");
    376 static const arg_def_t pass_arg         = ARG_DEF(NULL, "pass", 1,
    377                                                   "Pass to execute (1/2)");
    378 static const arg_def_t fpf_name         = ARG_DEF(NULL, "fpf", 1,
    379                                                   "First pass statistics file name");
    380 static const arg_def_t limit = ARG_DEF(NULL, "limit", 1,
    381                                        "Stop encoding after n input frames");
    382 static const arg_def_t skip = ARG_DEF(NULL, "skip", 1,
    383                                       "Skip the first n input frames");
    384 static const arg_def_t deadline         = ARG_DEF("d", "deadline", 1,
    385                                                   "Deadline per frame (usec)");
    386 static const arg_def_t best_dl          = ARG_DEF(NULL, "best", 0,
    387                                                   "Use Best Quality Deadline");
    388 static const arg_def_t good_dl          = ARG_DEF(NULL, "good", 0,
    389                                                   "Use Good Quality Deadline");
    390 static const arg_def_t rt_dl            = ARG_DEF(NULL, "rt", 0,
    391                                                   "Use Realtime Quality Deadline");
    392 static const arg_def_t quietarg         = ARG_DEF("q", "quiet", 0,
    393                                                   "Do not print encode progress");
    394 static const arg_def_t verbosearg       = ARG_DEF("v", "verbose", 0,
    395                                                   "Show encoder parameters");
    396 static const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
    397                                                   "Show PSNR in status line");
    398 enum TestDecodeFatality {
    399   TEST_DECODE_OFF,
    400   TEST_DECODE_FATAL,
    401   TEST_DECODE_WARN,
    402 };
    403 static const struct arg_enum_list test_decode_enum[] = {
    404   {"off",   TEST_DECODE_OFF},
    405   {"fatal", TEST_DECODE_FATAL},
    406   {"warn",  TEST_DECODE_WARN},
    407   {NULL, 0}
    408 };
    409 static const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1,
    410                                                 "Test encode/decode mismatch",
    411                                                 test_decode_enum);
    412 static const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
    413                                                   "Stream frame rate (rate/scale)");
    414 static const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
    415                                                   "Output IVF (default is WebM)");
    416 static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
    417                                           "Makes encoder output partitions. Requires IVF output!");
    418 static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
    419                                                   "Show quantizer histogram (n-buckets)");
    420 static const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
    421                                                      "Show rate histogram (n-buckets)");
    422 static const arg_def_t *main_args[] = {
    423   &debugmode,
    424   &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip,
    425   &deadline, &best_dl, &good_dl, &rt_dl,
    426   &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
    427   NULL
    428 };
    429 
    430 static const arg_def_t usage            = ARG_DEF("u", "usage", 1,
    431                                                   "Usage profile number to use");
    432 static const arg_def_t threads          = ARG_DEF("t", "threads", 1,
    433                                                   "Max number of threads to use");
    434 static const arg_def_t profile          = ARG_DEF(NULL, "profile", 1,
    435                                                   "Bitstream profile number to use");
    436 static const arg_def_t width            = ARG_DEF("w", "width", 1,
    437                                                   "Frame width");
    438 static const arg_def_t height           = ARG_DEF("h", "height", 1,
    439                                                   "Frame height");
    440 static const struct arg_enum_list stereo_mode_enum[] = {
    441   {"mono", STEREO_FORMAT_MONO},
    442   {"left-right", STEREO_FORMAT_LEFT_RIGHT},
    443   {"bottom-top", STEREO_FORMAT_BOTTOM_TOP},
    444   {"top-bottom", STEREO_FORMAT_TOP_BOTTOM},
    445   {"right-left", STEREO_FORMAT_RIGHT_LEFT},
    446   {NULL, 0}
    447 };
    448 static const arg_def_t stereo_mode      = ARG_DEF_ENUM(NULL, "stereo-mode", 1,
    449                                                        "Stereo 3D video format", stereo_mode_enum);
    450 static const arg_def_t timebase         = ARG_DEF(NULL, "timebase", 1,
    451                                                   "Output timestamp precision (fractional seconds)");
    452 static const arg_def_t error_resilient  = ARG_DEF(NULL, "error-resilient", 1,
    453                                                   "Enable error resiliency features");
    454 static const arg_def_t lag_in_frames    = ARG_DEF(NULL, "lag-in-frames", 1,
    455                                                   "Max number of frames to lag");
    456 
    457 static const arg_def_t *global_args[] = {
    458   &use_yv12, &use_i420, &usage, &threads, &profile,
    459   &width, &height, &stereo_mode, &timebase, &framerate,
    460   &error_resilient,
    461   &lag_in_frames, NULL
    462 };
    463 
    464 static const arg_def_t dropframe_thresh   = ARG_DEF(NULL, "drop-frame", 1,
    465                                                     "Temporal resampling threshold (buf %)");
    466 static const arg_def_t resize_allowed     = ARG_DEF(NULL, "resize-allowed", 1,
    467                                                     "Spatial resampling enabled (bool)");
    468 static const arg_def_t resize_up_thresh   = ARG_DEF(NULL, "resize-up", 1,
    469                                                     "Upscale threshold (buf %)");
    470 static const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1,
    471                                                     "Downscale threshold (buf %)");
    472 static const struct arg_enum_list end_usage_enum[] = {
    473   {"vbr", VPX_VBR},
    474   {"cbr", VPX_CBR},
    475   {"cq",  VPX_CQ},
    476   {"q",   VPX_Q},
    477   {NULL, 0}
    478 };
    479 static const arg_def_t end_usage          = ARG_DEF_ENUM(NULL, "end-usage", 1,
    480                                                          "Rate control mode", end_usage_enum);
    481 static const arg_def_t target_bitrate     = ARG_DEF(NULL, "target-bitrate", 1,
    482                                                     "Bitrate (kbps)");
    483 static const arg_def_t min_quantizer      = ARG_DEF(NULL, "min-q", 1,
    484                                                     "Minimum (best) quantizer");
    485 static const arg_def_t max_quantizer      = ARG_DEF(NULL, "max-q", 1,
    486                                                     "Maximum (worst) quantizer");
    487 static const arg_def_t undershoot_pct     = ARG_DEF(NULL, "undershoot-pct", 1,
    488                                                     "Datarate undershoot (min) target (%)");
    489 static const arg_def_t overshoot_pct      = ARG_DEF(NULL, "overshoot-pct", 1,
    490                                                     "Datarate overshoot (max) target (%)");
    491 static const arg_def_t buf_sz             = ARG_DEF(NULL, "buf-sz", 1,
    492                                                     "Client buffer size (ms)");
    493 static const arg_def_t buf_initial_sz     = ARG_DEF(NULL, "buf-initial-sz", 1,
    494                                                     "Client initial buffer size (ms)");
    495 static const arg_def_t buf_optimal_sz     = ARG_DEF(NULL, "buf-optimal-sz", 1,
    496                                                     "Client optimal buffer size (ms)");
    497 static const arg_def_t *rc_args[] = {
    498   &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh,
    499   &end_usage, &target_bitrate, &min_quantizer, &max_quantizer,
    500   &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz,
    501   NULL
    502 };
    503 
    504 
    505 static const arg_def_t bias_pct = ARG_DEF(NULL, "bias-pct", 1,
    506                                           "CBR/VBR bias (0=CBR, 100=VBR)");
    507 static const arg_def_t minsection_pct = ARG_DEF(NULL, "minsection-pct", 1,
    508                                                 "GOP min bitrate (% of target)");
    509 static const arg_def_t maxsection_pct = ARG_DEF(NULL, "maxsection-pct", 1,
    510                                                 "GOP max bitrate (% of target)");
    511 static const arg_def_t *rc_twopass_args[] = {
    512   &bias_pct, &minsection_pct, &maxsection_pct, NULL
    513 };
    514 
    515 
    516 static const arg_def_t kf_min_dist = ARG_DEF(NULL, "kf-min-dist", 1,
    517                                              "Minimum keyframe interval (frames)");
    518 static const arg_def_t kf_max_dist = ARG_DEF(NULL, "kf-max-dist", 1,
    519                                              "Maximum keyframe interval (frames)");
    520 static const arg_def_t kf_disabled = ARG_DEF(NULL, "disable-kf", 0,
    521                                              "Disable keyframe placement");
    522 static const arg_def_t *kf_args[] = {
    523   &kf_min_dist, &kf_max_dist, &kf_disabled, NULL
    524 };
    525 
    526 
    527 static const arg_def_t noise_sens = ARG_DEF(NULL, "noise-sensitivity", 1,
    528                                             "Noise sensitivity (frames to blur)");
    529 static const arg_def_t sharpness = ARG_DEF(NULL, "sharpness", 1,
    530                                            "Filter sharpness (0-7)");
    531 static const arg_def_t static_thresh = ARG_DEF(NULL, "static-thresh", 1,
    532                                                "Motion detection threshold");
    533 static const arg_def_t cpu_used = ARG_DEF(NULL, "cpu-used", 1,
    534                                           "CPU Used (-16..16)");
    535 static const arg_def_t token_parts = ARG_DEF(NULL, "token-parts", 1,
    536                                      "Number of token partitions to use, log2");
    537 static const arg_def_t tile_cols = ARG_DEF(NULL, "tile-columns", 1,
    538                                          "Number of tile columns to use, log2");
    539 static const arg_def_t tile_rows = ARG_DEF(NULL, "tile-rows", 1,
    540                                            "Number of tile rows to use, log2");
    541 static const arg_def_t auto_altref = ARG_DEF(NULL, "auto-alt-ref", 1,
    542                                              "Enable automatic alt reference frames");
    543 static const arg_def_t arnr_maxframes = ARG_DEF(NULL, "arnr-maxframes", 1,
    544                                                 "AltRef Max Frames");
    545 static const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1,
    546                                                "AltRef Strength");
    547 static const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1,
    548                                            "AltRef Type");
    549 static const struct arg_enum_list tuning_enum[] = {
    550   {"psnr", VP8_TUNE_PSNR},
    551   {"ssim", VP8_TUNE_SSIM},
    552   {NULL, 0}
    553 };
    554 static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
    555                                                 "Material to favor", tuning_enum);
    556 static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
    557                                           "Constant/Constrained Quality level");
    558 static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
    559                                                     "Max I-frame bitrate (pct)");
    560 static const arg_def_t lossless = ARG_DEF(NULL, "lossless", 1, "Lossless mode");
    561 #if CONFIG_VP9_ENCODER
    562 static const arg_def_t frame_parallel_decoding  = ARG_DEF(
    563     NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
    564 #endif
    565 
    566 #if CONFIG_VP8_ENCODER
    567 static const arg_def_t *vp8_args[] = {
    568   &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
    569   &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
    570   &tune_ssim, &cq_level, &max_intra_rate_pct,
    571   NULL
    572 };
    573 static const int vp8_arg_ctrl_map[] = {
    574   VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
    575   VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
    576   VP8E_SET_TOKEN_PARTITIONS,
    577   VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
    578   VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
    579   0
    580 };
    581 #endif
    582 
    583 #if CONFIG_VP9_ENCODER
    584 static const arg_def_t *vp9_args[] = {
    585   &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
    586   &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
    587   &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
    588   &frame_parallel_decoding,
    589   NULL
    590 };
    591 static const int vp9_arg_ctrl_map[] = {
    592   VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
    593   VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
    594   VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
    595   VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
    596   VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
    597   VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING,
    598   0
    599 };
    600 #endif
    601 
    602 static const arg_def_t *no_args[] = { NULL };
    603 
    604 void usage_exit() {
    605   int i;
    606 
    607   fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
    608           exec_name);
    609 
    610   fprintf(stderr, "\nOptions:\n");
    611   arg_show_usage(stderr, main_args);
    612   fprintf(stderr, "\nEncoder Global Options:\n");
    613   arg_show_usage(stderr, global_args);
    614   fprintf(stderr, "\nRate Control Options:\n");
    615   arg_show_usage(stderr, rc_args);
    616   fprintf(stderr, "\nTwopass Rate Control Options:\n");
    617   arg_show_usage(stderr, rc_twopass_args);
    618   fprintf(stderr, "\nKeyframe Placement Options:\n");
    619   arg_show_usage(stderr, kf_args);
    620 #if CONFIG_VP8_ENCODER
    621   fprintf(stderr, "\nVP8 Specific Options:\n");
    622   arg_show_usage(stderr, vp8_args);
    623 #endif
    624 #if CONFIG_VP9_ENCODER
    625   fprintf(stderr, "\nVP9 Specific Options:\n");
    626   arg_show_usage(stderr, vp9_args);
    627 #endif
    628   fprintf(stderr, "\nStream timebase (--timebase):\n"
    629           "  The desired precision of timestamps in the output, expressed\n"
    630           "  in fractional seconds. Default is 1/1000.\n");
    631   fprintf(stderr, "\n"
    632           "Included encoders:\n"
    633           "\n");
    634 
    635   for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
    636     fprintf(stderr, "    %-6s - %s\n",
    637             codecs[i].name,
    638             vpx_codec_iface_name(codecs[i].iface()));
    639 
    640   exit(EXIT_FAILURE);
    641 }
    642 
    643 
    644 #define HIST_BAR_MAX 40
    645 struct hist_bucket {
    646   int low, high, count;
    647 };
    648 
    649 
    650 static int merge_hist_buckets(struct hist_bucket *bucket,
    651                               int *buckets_,
    652                               int max_buckets) {
    653   int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
    654   int buckets = *buckets_;
    655   int i;
    656 
    657   /* Find the extrema for this list of buckets */
    658   big_bucket = small_bucket = 0;
    659   for (i = 0; i < buckets; i++) {
    660     if (bucket[i].count < bucket[small_bucket].count)
    661       small_bucket = i;
    662     if (bucket[i].count > bucket[big_bucket].count)
    663       big_bucket = i;
    664   }
    665 
    666   /* If we have too many buckets, merge the smallest with an adjacent
    667    * bucket.
    668    */
    669   while (buckets > max_buckets) {
    670     int last_bucket = buckets - 1;
    671 
    672     /* merge the small bucket with an adjacent one. */
    673     if (small_bucket == 0)
    674       merge_bucket = 1;
    675     else if (small_bucket == last_bucket)
    676       merge_bucket = last_bucket - 1;
    677     else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
    678       merge_bucket = small_bucket - 1;
    679     else
    680       merge_bucket = small_bucket + 1;
    681 
    682     assert(abs(merge_bucket - small_bucket) <= 1);
    683     assert(small_bucket < buckets);
    684     assert(big_bucket < buckets);
    685     assert(merge_bucket < buckets);
    686 
    687     if (merge_bucket < small_bucket) {
    688       bucket[merge_bucket].high = bucket[small_bucket].high;
    689       bucket[merge_bucket].count += bucket[small_bucket].count;
    690     } else {
    691       bucket[small_bucket].high = bucket[merge_bucket].high;
    692       bucket[small_bucket].count += bucket[merge_bucket].count;
    693       merge_bucket = small_bucket;
    694     }
    695 
    696     assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
    697 
    698     buckets--;
    699 
    700     /* Remove the merge_bucket from the list, and find the new small
    701      * and big buckets while we're at it
    702      */
    703     big_bucket = small_bucket = 0;
    704     for (i = 0; i < buckets; i++) {
    705       if (i > merge_bucket)
    706         bucket[i] = bucket[i + 1];
    707 
    708       if (bucket[i].count < bucket[small_bucket].count)
    709         small_bucket = i;
    710       if (bucket[i].count > bucket[big_bucket].count)
    711         big_bucket = i;
    712     }
    713 
    714   }
    715 
    716   *buckets_ = buckets;
    717   return bucket[big_bucket].count;
    718 }
    719 
    720 
    721 static void show_histogram(const struct hist_bucket *bucket,
    722                            int                       buckets,
    723                            int                       total,
    724                            int                       scale) {
    725   const char *pat1, *pat2;
    726   int i;
    727 
    728   switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
    729     case 1:
    730     case 2:
    731       pat1 = "%4d %2s: ";
    732       pat2 = "%4d-%2d: ";
    733       break;
    734     case 3:
    735       pat1 = "%5d %3s: ";
    736       pat2 = "%5d-%3d: ";
    737       break;
    738     case 4:
    739       pat1 = "%6d %4s: ";
    740       pat2 = "%6d-%4d: ";
    741       break;
    742     case 5:
    743       pat1 = "%7d %5s: ";
    744       pat2 = "%7d-%5d: ";
    745       break;
    746     case 6:
    747       pat1 = "%8d %6s: ";
    748       pat2 = "%8d-%6d: ";
    749       break;
    750     case 7:
    751       pat1 = "%9d %7s: ";
    752       pat2 = "%9d-%7d: ";
    753       break;
    754     default:
    755       pat1 = "%12d %10s: ";
    756       pat2 = "%12d-%10d: ";
    757       break;
    758   }
    759 
    760   for (i = 0; i < buckets; i++) {
    761     int len;
    762     int j;
    763     float pct;
    764 
    765     pct = (float)(100.0 * bucket[i].count / total);
    766     len = HIST_BAR_MAX * bucket[i].count / scale;
    767     if (len < 1)
    768       len = 1;
    769     assert(len <= HIST_BAR_MAX);
    770 
    771     if (bucket[i].low == bucket[i].high)
    772       fprintf(stderr, pat1, bucket[i].low, "");
    773     else
    774       fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
    775 
    776     for (j = 0; j < HIST_BAR_MAX; j++)
    777       fprintf(stderr, j < len ? "=" : " ");
    778     fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
    779   }
    780 }
    781 
    782 
    783 static void show_q_histogram(const int counts[64], int max_buckets) {
    784   struct hist_bucket bucket[64];
    785   int buckets = 0;
    786   int total = 0;
    787   int scale;
    788   int i;
    789 
    790 
    791   for (i = 0; i < 64; i++) {
    792     if (counts[i]) {
    793       bucket[buckets].low = bucket[buckets].high = i;
    794       bucket[buckets].count = counts[i];
    795       buckets++;
    796       total += counts[i];
    797     }
    798   }
    799 
    800   fprintf(stderr, "\nQuantizer Selection:\n");
    801   scale = merge_hist_buckets(bucket, &buckets, max_buckets);
    802   show_histogram(bucket, buckets, total, scale);
    803 }
    804 
    805 
    806 #define RATE_BINS (100)
    807 struct rate_hist {
    808   int64_t            *pts;
    809   int                *sz;
    810   int                 samples;
    811   int                 frames;
    812   struct hist_bucket  bucket[RATE_BINS];
    813   int                 total;
    814 };
    815 
    816 
    817 static void init_rate_histogram(struct rate_hist          *hist,
    818                                 const vpx_codec_enc_cfg_t *cfg,
    819                                 const vpx_rational_t      *fps) {
    820   int i;
    821 
    822   /* Determine the number of samples in the buffer. Use the file's framerate
    823    * to determine the number of frames in rc_buf_sz milliseconds, with an
    824    * adjustment (5/4) to account for alt-refs
    825    */
    826   hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
    827 
    828   /* prevent division by zero */
    829   if (hist->samples == 0)
    830     hist->samples = 1;
    831 
    832   hist->pts = calloc(hist->samples, sizeof(*hist->pts));
    833   hist->sz = calloc(hist->samples, sizeof(*hist->sz));
    834   for (i = 0; i < RATE_BINS; i++) {
    835     hist->bucket[i].low = INT_MAX;
    836     hist->bucket[i].high = 0;
    837     hist->bucket[i].count = 0;
    838   }
    839 }
    840 
    841 
    842 static void destroy_rate_histogram(struct rate_hist *hist) {
    843   free(hist->pts);
    844   free(hist->sz);
    845 }
    846 
    847 
    848 static void update_rate_histogram(struct rate_hist          *hist,
    849                                   const vpx_codec_enc_cfg_t *cfg,
    850                                   const vpx_codec_cx_pkt_t  *pkt) {
    851   int i, idx;
    852   int64_t now, then, sum_sz = 0, avg_bitrate;
    853 
    854   now = pkt->data.frame.pts * 1000
    855         * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
    856 
    857   idx = hist->frames++ % hist->samples;
    858   hist->pts[idx] = now;
    859   hist->sz[idx] = (int)pkt->data.frame.sz;
    860 
    861   if (now < cfg->rc_buf_initial_sz)
    862     return;
    863 
    864   then = now;
    865 
    866   /* Sum the size over the past rc_buf_sz ms */
    867   for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) {
    868     int i_idx = (i - 1) % hist->samples;
    869 
    870     then = hist->pts[i_idx];
    871     if (now - then > cfg->rc_buf_sz)
    872       break;
    873     sum_sz += hist->sz[i_idx];
    874   }
    875 
    876   if (now == then)
    877     return;
    878 
    879   avg_bitrate = sum_sz * 8 * 1000 / (now - then);
    880   idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
    881   if (idx < 0)
    882     idx = 0;
    883   if (idx > RATE_BINS - 1)
    884     idx = RATE_BINS - 1;
    885   if (hist->bucket[idx].low > avg_bitrate)
    886     hist->bucket[idx].low = (int)avg_bitrate;
    887   if (hist->bucket[idx].high < avg_bitrate)
    888     hist->bucket[idx].high = (int)avg_bitrate;
    889   hist->bucket[idx].count++;
    890   hist->total++;
    891 }
    892 
    893 
    894 static void show_rate_histogram(struct rate_hist          *hist,
    895                                 const vpx_codec_enc_cfg_t *cfg,
    896                                 int                        max_buckets) {
    897   int i, scale;
    898   int buckets = 0;
    899 
    900   for (i = 0; i < RATE_BINS; i++) {
    901     if (hist->bucket[i].low == INT_MAX)
    902       continue;
    903     hist->bucket[buckets++] = hist->bucket[i];
    904   }
    905 
    906   fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
    907   scale = merge_hist_buckets(hist->bucket, &buckets, max_buckets);
    908   show_histogram(hist->bucket, buckets, hist->total, scale);
    909 }
    910 
    911 #define mmin(a, b)  ((a) < (b) ? (a) : (b))
    912 static void find_mismatch(vpx_image_t *img1, vpx_image_t *img2,
    913                           int yloc[4], int uloc[4], int vloc[4]) {
    914   const unsigned int bsize = 64;
    915   const unsigned int bsizey = bsize >> img1->y_chroma_shift;
    916   const unsigned int bsizex = bsize >> img1->x_chroma_shift;
    917   const int c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
    918   const int c_h = (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
    919   unsigned int match = 1;
    920   unsigned int i, j;
    921   yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
    922   for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
    923     for (j = 0; match && j < img1->d_w; j += bsize) {
    924       int k, l;
    925       int si = mmin(i + bsize, img1->d_h) - i;
    926       int sj = mmin(j + bsize, img1->d_w) - j;
    927       for (k = 0; match && k < si; k++)
    928         for (l = 0; match && l < sj; l++) {
    929           if (*(img1->planes[VPX_PLANE_Y] +
    930                 (i + k) * img1->stride[VPX_PLANE_Y] + j + l) !=
    931               *(img2->planes[VPX_PLANE_Y] +
    932                 (i + k) * img2->stride[VPX_PLANE_Y] + j + l)) {
    933             yloc[0] = i + k;
    934             yloc[1] = j + l;
    935             yloc[2] = *(img1->planes[VPX_PLANE_Y] +
    936                         (i + k) * img1->stride[VPX_PLANE_Y] + j + l);
    937             yloc[3] = *(img2->planes[VPX_PLANE_Y] +
    938                         (i + k) * img2->stride[VPX_PLANE_Y] + j + l);
    939             match = 0;
    940             break;
    941           }
    942         }
    943     }
    944   }
    945 
    946   uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1;
    947   for (i = 0, match = 1; match && i < c_h; i += bsizey) {
    948     for (j = 0; match && j < c_w; j += bsizex) {
    949       int k, l;
    950       int si = mmin(i + bsizey, c_h - i);
    951       int sj = mmin(j + bsizex, c_w - j);
    952       for (k = 0; match && k < si; k++)
    953         for (l = 0; match && l < sj; l++) {
    954           if (*(img1->planes[VPX_PLANE_U] +
    955                 (i + k) * img1->stride[VPX_PLANE_U] + j + l) !=
    956               *(img2->planes[VPX_PLANE_U] +
    957                 (i + k) * img2->stride[VPX_PLANE_U] + j + l)) {
    958             uloc[0] = i + k;
    959             uloc[1] = j + l;
    960             uloc[2] = *(img1->planes[VPX_PLANE_U] +
    961                         (i + k) * img1->stride[VPX_PLANE_U] + j + l);
    962             uloc[3] = *(img2->planes[VPX_PLANE_U] +
    963                         (i + k) * img2->stride[VPX_PLANE_V] + j + l);
    964             match = 0;
    965             break;
    966           }
    967         }
    968     }
    969   }
    970   vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
    971   for (i = 0, match = 1; match && i < c_h; i += bsizey) {
    972     for (j = 0; match && j < c_w; j += bsizex) {
    973       int k, l;
    974       int si = mmin(i + bsizey, c_h - i);
    975       int sj = mmin(j + bsizex, c_w - j);
    976       for (k = 0; match && k < si; k++)
    977         for (l = 0; match && l < sj; l++) {
    978           if (*(img1->planes[VPX_PLANE_V] +
    979                 (i + k) * img1->stride[VPX_PLANE_V] + j + l) !=
    980               *(img2->planes[VPX_PLANE_V] +
    981                 (i + k) * img2->stride[VPX_PLANE_V] + j + l)) {
    982             vloc[0] = i + k;
    983             vloc[1] = j + l;
    984             vloc[2] = *(img1->planes[VPX_PLANE_V] +
    985                         (i + k) * img1->stride[VPX_PLANE_V] + j + l);
    986             vloc[3] = *(img2->planes[VPX_PLANE_V] +
    987                         (i + k) * img2->stride[VPX_PLANE_V] + j + l);
    988             match = 0;
    989             break;
    990           }
    991         }
    992     }
    993   }
    994 }
    995 
    996 static int compare_img(vpx_image_t *img1, vpx_image_t *img2)
    997 {
    998   const int c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
    999   const int c_h = (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
   1000   int match = 1;
   1001   unsigned int i;
   1002 
   1003   match &= (img1->fmt == img2->fmt);
   1004   match &= (img1->w == img2->w);
   1005   match &= (img1->h == img2->h);
   1006 
   1007   for (i = 0; i < img1->d_h; i++)
   1008     match &= (memcmp(img1->planes[VPX_PLANE_Y]+i*img1->stride[VPX_PLANE_Y],
   1009                      img2->planes[VPX_PLANE_Y]+i*img2->stride[VPX_PLANE_Y],
   1010                      img1->d_w) == 0);
   1011 
   1012   for (i = 0; i < c_h; i++)
   1013     match &= (memcmp(img1->planes[VPX_PLANE_U]+i*img1->stride[VPX_PLANE_U],
   1014                      img2->planes[VPX_PLANE_U]+i*img2->stride[VPX_PLANE_U],
   1015                      c_w) == 0);
   1016 
   1017   for (i = 0; i < c_h; i++)
   1018     match &= (memcmp(img1->planes[VPX_PLANE_V]+i*img1->stride[VPX_PLANE_U],
   1019                      img2->planes[VPX_PLANE_V]+i*img2->stride[VPX_PLANE_U],
   1020                      c_w) == 0);
   1021 
   1022   return match;
   1023 }
   1024 
   1025 
   1026 #define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
   1027 #define MAX(x,y) ((x)>(y)?(x):(y))
   1028 #if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER
   1029 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
   1030 #elif !CONFIG_VP8_ENCODER && CONFIG_VP9_ENCODER
   1031 #define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map)
   1032 #else
   1033 #define ARG_CTRL_CNT_MAX MAX(NELEMENTS(vp8_arg_ctrl_map), \
   1034                              NELEMENTS(vp9_arg_ctrl_map))
   1035 #endif
   1036 
   1037 /* Configuration elements common to all streams */
   1038 struct global_config {
   1039   const struct codec_item  *codec;
   1040   int                       passes;
   1041   int                       pass;
   1042   int                       usage;
   1043   int                       deadline;
   1044   int                       use_i420;
   1045   int                       quiet;
   1046   int                       verbose;
   1047   int                       limit;
   1048   int                       skip_frames;
   1049   int                       show_psnr;
   1050   enum TestDecodeFatality   test_decode;
   1051   int                       have_framerate;
   1052   struct vpx_rational       framerate;
   1053   int                       out_part;
   1054   int                       debug;
   1055   int                       show_q_hist_buckets;
   1056   int                       show_rate_hist_buckets;
   1057 };
   1058 
   1059 
   1060 /* Per-stream configuration */
   1061 struct stream_config {
   1062   struct vpx_codec_enc_cfg  cfg;
   1063   const char               *out_fn;
   1064   const char               *stats_fn;
   1065   stereo_format_t           stereo_fmt;
   1066   int                       arg_ctrls[ARG_CTRL_CNT_MAX][2];
   1067   int                       arg_ctrl_cnt;
   1068   int                       write_webm;
   1069   int                       have_kf_max_dist;
   1070 };
   1071 
   1072 
   1073 struct stream_state {
   1074   int                       index;
   1075   struct stream_state      *next;
   1076   struct stream_config      config;
   1077   FILE                     *file;
   1078   struct rate_hist          rate_hist;
   1079   struct EbmlGlobal         ebml;
   1080   uint32_t                  hash;
   1081   uint64_t                  psnr_sse_total;
   1082   uint64_t                  psnr_samples_total;
   1083   double                    psnr_totals[4];
   1084   int                       psnr_count;
   1085   int                       counts[64];
   1086   vpx_codec_ctx_t           encoder;
   1087   unsigned int              frames_out;
   1088   uint64_t                  cx_time;
   1089   size_t                    nbytes;
   1090   stats_io_t                stats;
   1091   struct vpx_image         *img;
   1092   vpx_codec_ctx_t           decoder;
   1093   int                       mismatch_seen;
   1094 };
   1095 
   1096 
   1097 void validate_positive_rational(const char          *msg,
   1098                                 struct vpx_rational *rat) {
   1099   if (rat->den < 0) {
   1100     rat->num *= -1;
   1101     rat->den *= -1;
   1102   }
   1103 
   1104   if (rat->num < 0)
   1105     die("Error: %s must be positive\n", msg);
   1106 
   1107   if (!rat->den)
   1108     die("Error: %s has zero denominator\n", msg);
   1109 }
   1110 
   1111 
   1112 static void parse_global_config(struct global_config *global, char **argv) {
   1113   char       **argi, **argj;
   1114   struct arg   arg;
   1115 
   1116   /* Initialize default parameters */
   1117   memset(global, 0, sizeof(*global));
   1118   global->codec = codecs;
   1119   global->passes = 0;
   1120   global->use_i420 = 1;
   1121   /* Assign default deadline to good quality */
   1122   global->deadline = VPX_DL_GOOD_QUALITY;
   1123 
   1124   for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
   1125     arg.argv_step = 1;
   1126 
   1127     if (arg_match(&arg, &codecarg, argi)) {
   1128       int j, k = -1;
   1129 
   1130       for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++)
   1131         if (!strcmp(codecs[j].name, arg.val))
   1132           k = j;
   1133 
   1134       if (k >= 0)
   1135         global->codec = codecs + k;
   1136       else
   1137         die("Error: Unrecognized argument (%s) to --codec\n",
   1138             arg.val);
   1139 
   1140     } else if (arg_match(&arg, &passes, argi)) {
   1141       global->passes = arg_parse_uint(&arg);
   1142 
   1143       if (global->passes < 1 || global->passes > 2)
   1144         die("Error: Invalid number of passes (%d)\n", global->passes);
   1145     } else if (arg_match(&arg, &pass_arg, argi)) {
   1146       global->pass = arg_parse_uint(&arg);
   1147 
   1148       if (global->pass < 1 || global->pass > 2)
   1149         die("Error: Invalid pass selected (%d)\n",
   1150             global->pass);
   1151     } else if (arg_match(&arg, &usage, argi))
   1152       global->usage = arg_parse_uint(&arg);
   1153     else if (arg_match(&arg, &deadline, argi))
   1154       global->deadline = arg_parse_uint(&arg);
   1155     else if (arg_match(&arg, &best_dl, argi))
   1156       global->deadline = VPX_DL_BEST_QUALITY;
   1157     else if (arg_match(&arg, &good_dl, argi))
   1158       global->deadline = VPX_DL_GOOD_QUALITY;
   1159     else if (arg_match(&arg, &rt_dl, argi))
   1160       global->deadline = VPX_DL_REALTIME;
   1161     else if (arg_match(&arg, &use_yv12, argi))
   1162       global->use_i420 = 0;
   1163     else if (arg_match(&arg, &use_i420, argi))
   1164       global->use_i420 = 1;
   1165     else if (arg_match(&arg, &quietarg, argi))
   1166       global->quiet = 1;
   1167     else if (arg_match(&arg, &verbosearg, argi))
   1168       global->verbose = 1;
   1169     else if (arg_match(&arg, &limit, argi))
   1170       global->limit = arg_parse_uint(&arg);
   1171     else if (arg_match(&arg, &skip, argi))
   1172       global->skip_frames = arg_parse_uint(&arg);
   1173     else if (arg_match(&arg, &psnrarg, argi))
   1174       global->show_psnr = 1;
   1175     else if (arg_match(&arg, &recontest, argi))
   1176       global->test_decode = arg_parse_enum_or_int(&arg);
   1177     else if (arg_match(&arg, &framerate, argi)) {
   1178       global->framerate = arg_parse_rational(&arg);
   1179       validate_positive_rational(arg.name, &global->framerate);
   1180       global->have_framerate = 1;
   1181     } else if (arg_match(&arg, &out_part, argi))
   1182       global->out_part = 1;
   1183     else if (arg_match(&arg, &debugmode, argi))
   1184       global->debug = 1;
   1185     else if (arg_match(&arg, &q_hist_n, argi))
   1186       global->show_q_hist_buckets = arg_parse_uint(&arg);
   1187     else if (arg_match(&arg, &rate_hist_n, argi))
   1188       global->show_rate_hist_buckets = arg_parse_uint(&arg);
   1189     else
   1190       argj++;
   1191   }
   1192 
   1193   /* Validate global config */
   1194   if (global->passes == 0) {
   1195 #if CONFIG_VP9_ENCODER
   1196     // Make default VP9 passes = 2 until there is a better quality 1-pass
   1197     // encoder
   1198     global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1);
   1199 #else
   1200     global->passes = 1;
   1201 #endif
   1202   }
   1203 
   1204   if (global->pass) {
   1205     /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
   1206     if (global->pass > global->passes) {
   1207       warn("Assuming --pass=%d implies --passes=%d\n",
   1208            global->pass, global->pass);
   1209       global->passes = global->pass;
   1210     }
   1211   }
   1212 }
   1213 
   1214 
   1215 void open_input_file(struct input_state *input) {
   1216   unsigned int fourcc;
   1217 
   1218   /* Parse certain options from the input file, if possible */
   1219   input->file = strcmp(input->fn, "-") ? fopen(input->fn, "rb")
   1220                 : set_binary_mode(stdin);
   1221 
   1222   if (!input->file)
   1223     fatal("Failed to open input file");
   1224 
   1225   if (!fseeko(input->file, 0, SEEK_END)) {
   1226     /* Input file is seekable. Figure out how long it is, so we can get
   1227      * progress info.
   1228      */
   1229     input->length = ftello(input->file);
   1230     rewind(input->file);
   1231   }
   1232 
   1233   /* For RAW input sources, these bytes will applied on the first frame
   1234    *  in read_frame().
   1235    */
   1236   input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file);
   1237   input->detect.position = 0;
   1238 
   1239   if (input->detect.buf_read == 4
   1240       && file_is_y4m(input->file, &input->y4m, input->detect.buf)) {
   1241     if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
   1242                        input->only_i420) >= 0) {
   1243       input->file_type = FILE_TYPE_Y4M;
   1244       input->w = input->y4m.pic_w;
   1245       input->h = input->y4m.pic_h;
   1246       input->framerate.num = input->y4m.fps_n;
   1247       input->framerate.den = input->y4m.fps_d;
   1248       input->use_i420 = 0;
   1249     } else
   1250       fatal("Unsupported Y4M stream.");
   1251   } else if (input->detect.buf_read == 4 && file_is_ivf(input, &fourcc)) {
   1252     fatal("IVF is not supported as input.");
   1253   } else {
   1254     input->file_type = FILE_TYPE_RAW;
   1255   }
   1256 }
   1257 
   1258 
   1259 static void close_input_file(struct input_state *input) {
   1260   fclose(input->file);
   1261   if (input->file_type == FILE_TYPE_Y4M)
   1262     y4m_input_close(&input->y4m);
   1263 }
   1264 
   1265 static struct stream_state *new_stream(struct global_config *global,
   1266                                        struct stream_state *prev) {
   1267   struct stream_state *stream;
   1268 
   1269   stream = calloc(1, sizeof(*stream));
   1270   if (!stream)
   1271     fatal("Failed to allocate new stream.");
   1272   if (prev) {
   1273     memcpy(stream, prev, sizeof(*stream));
   1274     stream->index++;
   1275     prev->next = stream;
   1276   } else {
   1277     vpx_codec_err_t  res;
   1278 
   1279     /* Populate encoder configuration */
   1280     res = vpx_codec_enc_config_default(global->codec->iface(),
   1281                                        &stream->config.cfg,
   1282                                        global->usage);
   1283     if (res)
   1284       fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res));
   1285 
   1286     /* Change the default timebase to a high enough value so that the
   1287      * encoder will always create strictly increasing timestamps.
   1288      */
   1289     stream->config.cfg.g_timebase.den = 1000;
   1290 
   1291     /* Never use the library's default resolution, require it be parsed
   1292      * from the file or set on the command line.
   1293      */
   1294     stream->config.cfg.g_w = 0;
   1295     stream->config.cfg.g_h = 0;
   1296 
   1297     /* Initialize remaining stream parameters */
   1298     stream->config.stereo_fmt = STEREO_FORMAT_MONO;
   1299     stream->config.write_webm = 1;
   1300     stream->ebml.last_pts_ms = -1;
   1301 
   1302     /* Allows removal of the application version from the EBML tags */
   1303     stream->ebml.debug = global->debug;
   1304   }
   1305 
   1306   /* Output files must be specified for each stream */
   1307   stream->config.out_fn = NULL;
   1308 
   1309   stream->next = NULL;
   1310   return stream;
   1311 }
   1312 
   1313 
   1314 static int parse_stream_params(struct global_config *global,
   1315                                struct stream_state  *stream,
   1316                                char **argv) {
   1317   char                   **argi, **argj;
   1318   struct arg               arg;
   1319   static const arg_def_t **ctrl_args = no_args;
   1320   static const int        *ctrl_args_map = NULL;
   1321   struct stream_config    *config = &stream->config;
   1322   int                      eos_mark_found = 0;
   1323 
   1324   /* Handle codec specific options */
   1325   if (0) {
   1326 #if CONFIG_VP8_ENCODER
   1327   } else if (global->codec->iface == vpx_codec_vp8_cx) {
   1328     ctrl_args = vp8_args;
   1329     ctrl_args_map = vp8_arg_ctrl_map;
   1330 #endif
   1331 #if CONFIG_VP9_ENCODER
   1332   } else if (global->codec->iface == vpx_codec_vp9_cx) {
   1333     ctrl_args = vp9_args;
   1334     ctrl_args_map = vp9_arg_ctrl_map;
   1335 #endif
   1336   }
   1337 
   1338   for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
   1339     arg.argv_step = 1;
   1340 
   1341     /* Once we've found an end-of-stream marker (--) we want to continue
   1342      * shifting arguments but not consuming them.
   1343      */
   1344     if (eos_mark_found) {
   1345       argj++;
   1346       continue;
   1347     } else if (!strcmp(*argj, "--")) {
   1348       eos_mark_found = 1;
   1349       continue;
   1350     }
   1351 
   1352     if (0);
   1353     else if (arg_match(&arg, &outputfile, argi))
   1354       config->out_fn = arg.val;
   1355     else if (arg_match(&arg, &fpf_name, argi))
   1356       config->stats_fn = arg.val;
   1357     else if (arg_match(&arg, &use_ivf, argi))
   1358       config->write_webm = 0;
   1359     else if (arg_match(&arg, &threads, argi))
   1360       config->cfg.g_threads = arg_parse_uint(&arg);
   1361     else if (arg_match(&arg, &profile, argi))
   1362       config->cfg.g_profile = arg_parse_uint(&arg);
   1363     else if (arg_match(&arg, &width, argi))
   1364       config->cfg.g_w = arg_parse_uint(&arg);
   1365     else if (arg_match(&arg, &height, argi))
   1366       config->cfg.g_h = arg_parse_uint(&arg);
   1367     else if (arg_match(&arg, &stereo_mode, argi))
   1368       config->stereo_fmt = arg_parse_enum_or_int(&arg);
   1369     else if (arg_match(&arg, &timebase, argi)) {
   1370       config->cfg.g_timebase = arg_parse_rational(&arg);
   1371       validate_positive_rational(arg.name, &config->cfg.g_timebase);
   1372     } else if (arg_match(&arg, &error_resilient, argi))
   1373       config->cfg.g_error_resilient = arg_parse_uint(&arg);
   1374     else if (arg_match(&arg, &lag_in_frames, argi))
   1375       config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
   1376     else if (arg_match(&arg, &dropframe_thresh, argi))
   1377       config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
   1378     else if (arg_match(&arg, &resize_allowed, argi))
   1379       config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
   1380     else if (arg_match(&arg, &resize_up_thresh, argi))
   1381       config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
   1382     else if (arg_match(&arg, &resize_down_thresh, argi))
   1383       config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
   1384     else if (arg_match(&arg, &end_usage, argi))
   1385       config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
   1386     else if (arg_match(&arg, &target_bitrate, argi))
   1387       config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
   1388     else if (arg_match(&arg, &min_quantizer, argi))
   1389       config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
   1390     else if (arg_match(&arg, &max_quantizer, argi))
   1391       config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
   1392     else if (arg_match(&arg, &undershoot_pct, argi))
   1393       config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
   1394     else if (arg_match(&arg, &overshoot_pct, argi))
   1395       config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
   1396     else if (arg_match(&arg, &buf_sz, argi))
   1397       config->cfg.rc_buf_sz = arg_parse_uint(&arg);
   1398     else if (arg_match(&arg, &buf_initial_sz, argi))
   1399       config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
   1400     else if (arg_match(&arg, &buf_optimal_sz, argi))
   1401       config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
   1402     else if (arg_match(&arg, &bias_pct, argi)) {
   1403       config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
   1404 
   1405       if (global->passes < 2)
   1406         warn("option %s ignored in one-pass mode.\n", arg.name);
   1407     } else if (arg_match(&arg, &minsection_pct, argi)) {
   1408       config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
   1409 
   1410       if (global->passes < 2)
   1411         warn("option %s ignored in one-pass mode.\n", arg.name);
   1412     } else if (arg_match(&arg, &maxsection_pct, argi)) {
   1413       config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
   1414 
   1415       if (global->passes < 2)
   1416         warn("option %s ignored in one-pass mode.\n", arg.name);
   1417     } else if (arg_match(&arg, &kf_min_dist, argi))
   1418       config->cfg.kf_min_dist = arg_parse_uint(&arg);
   1419     else if (arg_match(&arg, &kf_max_dist, argi)) {
   1420       config->cfg.kf_max_dist = arg_parse_uint(&arg);
   1421       config->have_kf_max_dist = 1;
   1422     } else if (arg_match(&arg, &kf_disabled, argi))
   1423       config->cfg.kf_mode = VPX_KF_DISABLED;
   1424     else {
   1425       int i, match = 0;
   1426 
   1427       for (i = 0; ctrl_args[i]; i++) {
   1428         if (arg_match(&arg, ctrl_args[i], argi)) {
   1429           int j;
   1430           match = 1;
   1431 
   1432           /* Point either to the next free element or the first
   1433           * instance of this control.
   1434           */
   1435           for (j = 0; j < config->arg_ctrl_cnt; j++)
   1436             if (config->arg_ctrls[j][0] == ctrl_args_map[i])
   1437               break;
   1438 
   1439           /* Update/insert */
   1440           assert(j < ARG_CTRL_CNT_MAX);
   1441           if (j < ARG_CTRL_CNT_MAX) {
   1442             config->arg_ctrls[j][0] = ctrl_args_map[i];
   1443             config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
   1444             if (j == config->arg_ctrl_cnt)
   1445               config->arg_ctrl_cnt++;
   1446           }
   1447 
   1448         }
   1449       }
   1450 
   1451       if (!match)
   1452         argj++;
   1453     }
   1454   }
   1455 
   1456   return eos_mark_found;
   1457 }
   1458 
   1459 
   1460 #define FOREACH_STREAM(func)\
   1461   do\
   1462   {\
   1463     struct stream_state  *stream;\
   1464     \
   1465     for(stream = streams; stream; stream = stream->next)\
   1466       func;\
   1467   }while(0)
   1468 
   1469 
   1470 static void validate_stream_config(struct stream_state *stream) {
   1471   struct stream_state *streami;
   1472 
   1473   if (!stream->config.cfg.g_w || !stream->config.cfg.g_h)
   1474     fatal("Stream %d: Specify stream dimensions with --width (-w) "
   1475           " and --height (-h)", stream->index);
   1476 
   1477   for (streami = stream; streami; streami = streami->next) {
   1478     /* All streams require output files */
   1479     if (!streami->config.out_fn)
   1480       fatal("Stream %d: Output file is required (specify with -o)",
   1481             streami->index);
   1482 
   1483     /* Check for two streams outputting to the same file */
   1484     if (streami != stream) {
   1485       const char *a = stream->config.out_fn;
   1486       const char *b = streami->config.out_fn;
   1487       if (!strcmp(a, b) && strcmp(a, "/dev/null") && strcmp(a, ":nul"))
   1488         fatal("Stream %d: duplicate output file (from stream %d)",
   1489               streami->index, stream->index);
   1490     }
   1491 
   1492     /* Check for two streams sharing a stats file. */
   1493     if (streami != stream) {
   1494       const char *a = stream->config.stats_fn;
   1495       const char *b = streami->config.stats_fn;
   1496       if (a && b && !strcmp(a, b))
   1497         fatal("Stream %d: duplicate stats file (from stream %d)",
   1498               streami->index, stream->index);
   1499     }
   1500   }
   1501 }
   1502 
   1503 
   1504 static void set_stream_dimensions(struct stream_state *stream,
   1505                                   unsigned int w,
   1506                                   unsigned int h) {
   1507   if (!stream->config.cfg.g_w) {
   1508     if (!stream->config.cfg.g_h)
   1509       stream->config.cfg.g_w = w;
   1510     else
   1511       stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
   1512   }
   1513   if (!stream->config.cfg.g_h) {
   1514     stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
   1515   }
   1516 }
   1517 
   1518 
   1519 static void set_default_kf_interval(struct stream_state  *stream,
   1520                                     struct global_config *global) {
   1521   /* Use a max keyframe interval of 5 seconds, if none was
   1522    * specified on the command line.
   1523    */
   1524   if (!stream->config.have_kf_max_dist) {
   1525     double framerate = (double)global->framerate.num / global->framerate.den;
   1526     if (framerate > 0.0)
   1527       stream->config.cfg.kf_max_dist = (unsigned int)(5.0 * framerate);
   1528   }
   1529 }
   1530 
   1531 
   1532 static void show_stream_config(struct stream_state  *stream,
   1533                                struct global_config *global,
   1534                                struct input_state   *input) {
   1535 
   1536 #define SHOW(field) \
   1537   fprintf(stderr, "    %-28s = %d\n", #field, stream->config.cfg.field)
   1538 
   1539   if (stream->index == 0) {
   1540     fprintf(stderr, "Codec: %s\n",
   1541             vpx_codec_iface_name(global->codec->iface()));
   1542     fprintf(stderr, "Source file: %s Format: %s\n", input->fn,
   1543             input->use_i420 ? "I420" : "YV12");
   1544   }
   1545   if (stream->next || stream->index)
   1546     fprintf(stderr, "\nStream Index: %d\n", stream->index);
   1547   fprintf(stderr, "Destination file: %s\n", stream->config.out_fn);
   1548   fprintf(stderr, "Encoder parameters:\n");
   1549 
   1550   SHOW(g_usage);
   1551   SHOW(g_threads);
   1552   SHOW(g_profile);
   1553   SHOW(g_w);
   1554   SHOW(g_h);
   1555   SHOW(g_timebase.num);
   1556   SHOW(g_timebase.den);
   1557   SHOW(g_error_resilient);
   1558   SHOW(g_pass);
   1559   SHOW(g_lag_in_frames);
   1560   SHOW(rc_dropframe_thresh);
   1561   SHOW(rc_resize_allowed);
   1562   SHOW(rc_resize_up_thresh);
   1563   SHOW(rc_resize_down_thresh);
   1564   SHOW(rc_end_usage);
   1565   SHOW(rc_target_bitrate);
   1566   SHOW(rc_min_quantizer);
   1567   SHOW(rc_max_quantizer);
   1568   SHOW(rc_undershoot_pct);
   1569   SHOW(rc_overshoot_pct);
   1570   SHOW(rc_buf_sz);
   1571   SHOW(rc_buf_initial_sz);
   1572   SHOW(rc_buf_optimal_sz);
   1573   SHOW(rc_2pass_vbr_bias_pct);
   1574   SHOW(rc_2pass_vbr_minsection_pct);
   1575   SHOW(rc_2pass_vbr_maxsection_pct);
   1576   SHOW(kf_mode);
   1577   SHOW(kf_min_dist);
   1578   SHOW(kf_max_dist);
   1579 }
   1580 
   1581 
   1582 static void open_output_file(struct stream_state *stream,
   1583                              struct global_config *global) {
   1584   const char *fn = stream->config.out_fn;
   1585 
   1586   stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
   1587 
   1588   if (!stream->file)
   1589     fatal("Failed to open output file");
   1590 
   1591   if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
   1592     fatal("WebM output to pipes not supported.");
   1593 
   1594   if (stream->config.write_webm) {
   1595     stream->ebml.stream = stream->file;
   1596     write_webm_file_header(&stream->ebml, &stream->config.cfg,
   1597                            &global->framerate,
   1598                            stream->config.stereo_fmt,
   1599                            global->codec->fourcc);
   1600   } else
   1601     write_ivf_file_header(stream->file, &stream->config.cfg,
   1602                           global->codec->fourcc, 0);
   1603 }
   1604 
   1605 
   1606 static void close_output_file(struct stream_state *stream,
   1607                               unsigned int         fourcc) {
   1608   if (stream->config.write_webm) {
   1609     write_webm_file_footer(&stream->ebml, stream->hash);
   1610     free(stream->ebml.cue_list);
   1611     stream->ebml.cue_list = NULL;
   1612   } else {
   1613     if (!fseek(stream->file, 0, SEEK_SET))
   1614       write_ivf_file_header(stream->file, &stream->config.cfg,
   1615                             fourcc,
   1616                             stream->frames_out);
   1617   }
   1618 
   1619   fclose(stream->file);
   1620 }
   1621 
   1622 
   1623 static void setup_pass(struct stream_state  *stream,
   1624                        struct global_config *global,
   1625                        int                   pass) {
   1626   if (stream->config.stats_fn) {
   1627     if (!stats_open_file(&stream->stats, stream->config.stats_fn,
   1628                          pass))
   1629       fatal("Failed to open statistics store");
   1630   } else {
   1631     if (!stats_open_mem(&stream->stats, pass))
   1632       fatal("Failed to open statistics store");
   1633   }
   1634 
   1635   stream->config.cfg.g_pass = global->passes == 2
   1636                               ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS
   1637                             : VPX_RC_ONE_PASS;
   1638   if (pass)
   1639     stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
   1640 
   1641   stream->cx_time = 0;
   1642   stream->nbytes = 0;
   1643   stream->frames_out = 0;
   1644 }
   1645 
   1646 
   1647 static void initialize_encoder(struct stream_state  *stream,
   1648                                struct global_config *global) {
   1649   int i;
   1650   int flags = 0;
   1651 
   1652   flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
   1653   flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
   1654 
   1655   /* Construct Encoder Context */
   1656   vpx_codec_enc_init(&stream->encoder, global->codec->iface(),
   1657                      &stream->config.cfg, flags);
   1658   ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
   1659 
   1660   /* Note that we bypass the vpx_codec_control wrapper macro because
   1661    * we're being clever to store the control IDs in an array. Real
   1662    * applications will want to make use of the enumerations directly
   1663    */
   1664   for (i = 0; i < stream->config.arg_ctrl_cnt; i++) {
   1665     int ctrl = stream->config.arg_ctrls[i][0];
   1666     int value = stream->config.arg_ctrls[i][1];
   1667     if (vpx_codec_control_(&stream->encoder, ctrl, value))
   1668       fprintf(stderr, "Error: Tried to set control %d = %d\n",
   1669               ctrl, value);
   1670 
   1671     ctx_exit_on_error(&stream->encoder, "Failed to control codec");
   1672   }
   1673 
   1674 #if CONFIG_DECODERS
   1675   if (global->test_decode != TEST_DECODE_OFF) {
   1676     vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0);
   1677   }
   1678 #endif
   1679 }
   1680 
   1681 
   1682 static void encode_frame(struct stream_state  *stream,
   1683                          struct global_config *global,
   1684                          struct vpx_image     *img,
   1685                          unsigned int          frames_in) {
   1686   vpx_codec_pts_t frame_start, next_frame_start;
   1687   struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
   1688   struct vpx_usec_timer timer;
   1689 
   1690   frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1)
   1691                  * global->framerate.den)
   1692                 / cfg->g_timebase.num / global->framerate.num;
   1693   next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
   1694                       * global->framerate.den)
   1695                      / cfg->g_timebase.num / global->framerate.num;
   1696 
   1697   /* Scale if necessary */
   1698   if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
   1699     if (!stream->img)
   1700       stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420,
   1701                                   cfg->g_w, cfg->g_h, 16);
   1702     I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
   1703               img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
   1704               img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
   1705               img->d_w, img->d_h,
   1706               stream->img->planes[VPX_PLANE_Y],
   1707               stream->img->stride[VPX_PLANE_Y],
   1708               stream->img->planes[VPX_PLANE_U],
   1709               stream->img->stride[VPX_PLANE_U],
   1710               stream->img->planes[VPX_PLANE_V],
   1711               stream->img->stride[VPX_PLANE_V],
   1712               stream->img->d_w, stream->img->d_h,
   1713               kFilterBox);
   1714 
   1715     img = stream->img;
   1716   }
   1717 
   1718   vpx_usec_timer_start(&timer);
   1719   vpx_codec_encode(&stream->encoder, img, frame_start,
   1720                    (unsigned long)(next_frame_start - frame_start),
   1721                    0, global->deadline);
   1722   vpx_usec_timer_mark(&timer);
   1723   stream->cx_time += vpx_usec_timer_elapsed(&timer);
   1724   ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame",
   1725                     stream->index);
   1726 }
   1727 
   1728 
   1729 static void update_quantizer_histogram(struct stream_state *stream) {
   1730   if (stream->config.cfg.g_pass != VPX_RC_FIRST_PASS) {
   1731     int q;
   1732 
   1733     vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
   1734     ctx_exit_on_error(&stream->encoder, "Failed to read quantizer");
   1735     stream->counts[q]++;
   1736   }
   1737 }
   1738 
   1739 
   1740 static void get_cx_data(struct stream_state  *stream,
   1741                         struct global_config *global,
   1742                         int                  *got_data) {
   1743   const vpx_codec_cx_pkt_t *pkt;
   1744   const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
   1745   vpx_codec_iter_t iter = NULL;
   1746 
   1747   *got_data = 0;
   1748   while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) {
   1749     static size_t fsize = 0;
   1750     static off_t ivf_header_pos = 0;
   1751 
   1752     switch (pkt->kind) {
   1753       case VPX_CODEC_CX_FRAME_PKT:
   1754         if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
   1755           stream->frames_out++;
   1756         }
   1757         if (!global->quiet)
   1758           fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz);
   1759 
   1760         update_rate_histogram(&stream->rate_hist, cfg, pkt);
   1761         if (stream->config.write_webm) {
   1762           /* Update the hash */
   1763           if (!stream->ebml.debug)
   1764             stream->hash = murmur(pkt->data.frame.buf,
   1765                                   (int)pkt->data.frame.sz,
   1766                                   stream->hash);
   1767 
   1768           write_webm_block(&stream->ebml, cfg, pkt);
   1769         } else {
   1770           if (pkt->data.frame.partition_id <= 0) {
   1771             ivf_header_pos = ftello(stream->file);
   1772             fsize = pkt->data.frame.sz;
   1773 
   1774             write_ivf_frame_header(stream->file, pkt);
   1775           } else {
   1776             fsize += pkt->data.frame.sz;
   1777 
   1778             if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
   1779               off_t currpos = ftello(stream->file);
   1780               fseeko(stream->file, ivf_header_pos, SEEK_SET);
   1781               write_ivf_frame_size(stream->file, fsize);
   1782               fseeko(stream->file, currpos, SEEK_SET);
   1783             }
   1784           }
   1785 
   1786           (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
   1787                         stream->file);
   1788         }
   1789         stream->nbytes += pkt->data.raw.sz;
   1790 
   1791         *got_data = 1;
   1792 #if CONFIG_DECODERS
   1793         if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
   1794           vpx_codec_decode(&stream->decoder, pkt->data.frame.buf,
   1795                            pkt->data.frame.sz, NULL, 0);
   1796           if (stream->decoder.err) {
   1797             warn_or_exit_on_error(&stream->decoder,
   1798                                   global->test_decode == TEST_DECODE_FATAL,
   1799                                   "Failed to decode frame %d in stream %d",
   1800                                   stream->frames_out + 1, stream->index);
   1801             stream->mismatch_seen = stream->frames_out + 1;
   1802           }
   1803         }
   1804 #endif
   1805         break;
   1806       case VPX_CODEC_STATS_PKT:
   1807         stream->frames_out++;
   1808         stats_write(&stream->stats,
   1809                     pkt->data.twopass_stats.buf,
   1810                     pkt->data.twopass_stats.sz);
   1811         stream->nbytes += pkt->data.raw.sz;
   1812         break;
   1813       case VPX_CODEC_PSNR_PKT:
   1814 
   1815         if (global->show_psnr) {
   1816           int i;
   1817 
   1818           stream->psnr_sse_total += pkt->data.psnr.sse[0];
   1819           stream->psnr_samples_total += pkt->data.psnr.samples[0];
   1820           for (i = 0; i < 4; i++) {
   1821             if (!global->quiet)
   1822               fprintf(stderr, "%.3f ", pkt->data.psnr.psnr[i]);
   1823             stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
   1824           }
   1825           stream->psnr_count++;
   1826         }
   1827 
   1828         break;
   1829       default:
   1830         break;
   1831     }
   1832   }
   1833 }
   1834 
   1835 
   1836 static void show_psnr(struct stream_state  *stream) {
   1837   int i;
   1838   double ovpsnr;
   1839 
   1840   if (!stream->psnr_count)
   1841     return;
   1842 
   1843   fprintf(stderr, "Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
   1844   ovpsnr = vp8_mse2psnr((double)stream->psnr_samples_total, 255.0,
   1845                         (double)stream->psnr_sse_total);
   1846   fprintf(stderr, " %.3f", ovpsnr);
   1847 
   1848   for (i = 0; i < 4; i++) {
   1849     fprintf(stderr, " %.3f", stream->psnr_totals[i] / stream->psnr_count);
   1850   }
   1851   fprintf(stderr, "\n");
   1852 }
   1853 
   1854 
   1855 static float usec_to_fps(uint64_t usec, unsigned int frames) {
   1856   return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
   1857 }
   1858 
   1859 
   1860 static void test_decode(struct stream_state  *stream,
   1861                         enum TestDecodeFatality fatal,
   1862                         const struct codec_item *codec) {
   1863   vpx_image_t enc_img, dec_img;
   1864 
   1865   if (stream->mismatch_seen)
   1866     return;
   1867 
   1868   /* Get the internal reference frame */
   1869   if (codec->fourcc == VP8_FOURCC) {
   1870     struct vpx_ref_frame ref_enc, ref_dec;
   1871     int width, height;
   1872 
   1873     width = (stream->config.cfg.g_w + 15) & ~15;
   1874     height = (stream->config.cfg.g_h + 15) & ~15;
   1875     vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1);
   1876     enc_img = ref_enc.img;
   1877     vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1);
   1878     dec_img = ref_dec.img;
   1879 
   1880     ref_enc.frame_type = VP8_LAST_FRAME;
   1881     ref_dec.frame_type = VP8_LAST_FRAME;
   1882     vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &ref_enc);
   1883     vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &ref_dec);
   1884   } else {
   1885     struct vp9_ref_frame ref;
   1886 
   1887     ref.idx = 0;
   1888     vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref);
   1889     enc_img = ref.img;
   1890     vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref);
   1891     dec_img = ref.img;
   1892   }
   1893   ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame");
   1894   ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame");
   1895 
   1896   if (!compare_img(&enc_img, &dec_img)) {
   1897     int y[4], u[4], v[4];
   1898     find_mismatch(&enc_img, &dec_img, y, u, v);
   1899     stream->decoder.err = 1;
   1900     warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
   1901                           "Stream %d: Encode/decode mismatch on frame %d at"
   1902                           " Y[%d, %d] {%d/%d},"
   1903                           " U[%d, %d] {%d/%d},"
   1904                           " V[%d, %d] {%d/%d}",
   1905                           stream->index, stream->frames_out,
   1906                           y[0], y[1], y[2], y[3],
   1907                           u[0], u[1], u[2], u[3],
   1908                           v[0], v[1], v[2], v[3]);
   1909     stream->mismatch_seen = stream->frames_out;
   1910   }
   1911 
   1912   vpx_img_free(&enc_img);
   1913   vpx_img_free(&dec_img);
   1914 }
   1915 
   1916 
   1917 static void print_time(const char *label, int64_t etl) {
   1918   int hours, mins, secs;
   1919 
   1920   if (etl >= 0) {
   1921     hours = etl / 3600;
   1922     etl -= hours * 3600;
   1923     mins = etl / 60;
   1924     etl -= mins * 60;
   1925     secs = etl;
   1926 
   1927     fprintf(stderr, "[%3s %2d:%02d:%02d] ",
   1928             label, hours, mins, secs);
   1929   } else {
   1930     fprintf(stderr, "[%3s  unknown] ", label);
   1931   }
   1932 }
   1933 
   1934 int main(int argc, const char **argv_) {
   1935   int                    pass;
   1936   vpx_image_t            raw;
   1937   int                    frame_avail, got_data;
   1938 
   1939   struct input_state       input = {0};
   1940   struct global_config     global;
   1941   struct stream_state     *streams = NULL;
   1942   char                   **argv, **argi;
   1943   uint64_t                 cx_time = 0;
   1944   int                      stream_cnt = 0;
   1945   int                      res = 0;
   1946 
   1947   exec_name = argv_[0];
   1948 
   1949   if (argc < 3)
   1950     usage_exit();
   1951 
   1952   /* Setup default input stream settings */
   1953   input.framerate.num = 30;
   1954   input.framerate.den = 1;
   1955   input.use_i420 = 1;
   1956   input.only_i420 = 1;
   1957 
   1958   /* First parse the global configuration values, because we want to apply
   1959    * other parameters on top of the default configuration provided by the
   1960    * codec.
   1961    */
   1962   argv = argv_dup(argc - 1, argv_ + 1);
   1963   parse_global_config(&global, argv);
   1964 
   1965   {
   1966     /* Now parse each stream's parameters. Using a local scope here
   1967      * due to the use of 'stream' as loop variable in FOREACH_STREAM
   1968      * loops
   1969      */
   1970     struct stream_state *stream = NULL;
   1971 
   1972     do {
   1973       stream = new_stream(&global, stream);
   1974       stream_cnt++;
   1975       if (!streams)
   1976         streams = stream;
   1977     } while (parse_stream_params(&global, stream, argv));
   1978   }
   1979 
   1980   /* Check for unrecognized options */
   1981   for (argi = argv; *argi; argi++)
   1982     if (argi[0][0] == '-' && argi[0][1])
   1983       die("Error: Unrecognized option %s\n", *argi);
   1984 
   1985   /* Handle non-option arguments */
   1986   input.fn = argv[0];
   1987 
   1988   if (!input.fn)
   1989     usage_exit();
   1990 
   1991 #if CONFIG_NON420
   1992   /* Decide if other chroma subsamplings than 4:2:0 are supported */
   1993   if (global.codec->fourcc == VP9_FOURCC)
   1994     input.only_i420 = 0;
   1995 #endif
   1996 
   1997   for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
   1998     int frames_in = 0, seen_frames = 0;
   1999     int64_t estimated_time_left = -1;
   2000     int64_t average_rate = -1;
   2001     off_t lagged_count = 0;
   2002 
   2003     open_input_file(&input);
   2004 
   2005     /* If the input file doesn't specify its w/h (raw files), try to get
   2006      * the data from the first stream's configuration.
   2007      */
   2008     if (!input.w || !input.h)
   2009       FOREACH_STREAM( {
   2010       if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
   2011         input.w = stream->config.cfg.g_w;
   2012         input.h = stream->config.cfg.g_h;
   2013         break;
   2014       }
   2015     });
   2016 
   2017     /* Update stream configurations from the input file's parameters */
   2018     if (!input.w || !input.h)
   2019       fatal("Specify stream dimensions with --width (-w) "
   2020             " and --height (-h)");
   2021     FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h));
   2022     FOREACH_STREAM(validate_stream_config(stream));
   2023 
   2024     /* Ensure that --passes and --pass are consistent. If --pass is set and
   2025      * --passes=2, ensure --fpf was set.
   2026      */
   2027     if (global.pass && global.passes == 2)
   2028       FOREACH_STREAM( {
   2029       if (!stream->config.stats_fn)
   2030         die("Stream %d: Must specify --fpf when --pass=%d"
   2031         " and --passes=2\n", stream->index, global.pass);
   2032     });
   2033 
   2034     /* Use the frame rate from the file only if none was specified
   2035      * on the command-line.
   2036      */
   2037     if (!global.have_framerate)
   2038       global.framerate = input.framerate;
   2039 
   2040     FOREACH_STREAM(set_default_kf_interval(stream, &global));
   2041 
   2042     /* Show configuration */
   2043     if (global.verbose && pass == 0)
   2044       FOREACH_STREAM(show_stream_config(stream, &global, &input));
   2045 
   2046     if (pass == (global.pass ? global.pass - 1 : 0)) {
   2047       if (input.file_type == FILE_TYPE_Y4M)
   2048         /*The Y4M reader does its own allocation.
   2049           Just initialize this here to avoid problems if we never read any
   2050            frames.*/
   2051         memset(&raw, 0, sizeof(raw));
   2052       else
   2053         vpx_img_alloc(&raw,
   2054                       input.use_i420 ? VPX_IMG_FMT_I420
   2055                       : VPX_IMG_FMT_YV12,
   2056                       input.w, input.h, 32);
   2057 
   2058       FOREACH_STREAM(init_rate_histogram(&stream->rate_hist,
   2059                                          &stream->config.cfg,
   2060                                          &global.framerate));
   2061     }
   2062 
   2063     FOREACH_STREAM(setup_pass(stream, &global, pass));
   2064     FOREACH_STREAM(open_output_file(stream, &global));
   2065     FOREACH_STREAM(initialize_encoder(stream, &global));
   2066 
   2067     frame_avail = 1;
   2068     got_data = 0;
   2069 
   2070     while (frame_avail || got_data) {
   2071       struct vpx_usec_timer timer;
   2072 
   2073       if (!global.limit || frames_in < global.limit) {
   2074         frame_avail = read_frame(&input, &raw);
   2075 
   2076         if (frame_avail)
   2077           frames_in++;
   2078         seen_frames = frames_in > global.skip_frames ?
   2079                           frames_in - global.skip_frames : 0;
   2080 
   2081         if (!global.quiet) {
   2082           float fps = usec_to_fps(cx_time, seen_frames);
   2083           fprintf(stderr, "\rPass %d/%d ", pass + 1, global.passes);
   2084 
   2085           if (stream_cnt == 1)
   2086             fprintf(stderr,
   2087                     "frame %4d/%-4d %7"PRId64"B ",
   2088                     frames_in, streams->frames_out, (int64_t)streams->nbytes);
   2089           else
   2090             fprintf(stderr, "frame %4d ", frames_in);
   2091 
   2092           fprintf(stderr, "%7"PRId64" %s %.2f %s ",
   2093                   cx_time > 9999999 ? cx_time / 1000 : cx_time,
   2094                   cx_time > 9999999 ? "ms" : "us",
   2095                   fps >= 1.0 ? fps : fps * 60,
   2096                   fps >= 1.0 ? "fps" : "fpm");
   2097           print_time("ETA", estimated_time_left);
   2098           fprintf(stderr, "\033[K");
   2099         }
   2100 
   2101       } else
   2102         frame_avail = 0;
   2103 
   2104       if (frames_in > global.skip_frames) {
   2105         vpx_usec_timer_start(&timer);
   2106         FOREACH_STREAM(encode_frame(stream, &global,
   2107                                     frame_avail ? &raw : NULL,
   2108                                     frames_in));
   2109         vpx_usec_timer_mark(&timer);
   2110         cx_time += vpx_usec_timer_elapsed(&timer);
   2111 
   2112         FOREACH_STREAM(update_quantizer_histogram(stream));
   2113 
   2114         got_data = 0;
   2115         FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
   2116 
   2117         if (!got_data && input.length && !streams->frames_out) {
   2118           lagged_count = global.limit ? seen_frames : ftello(input.file);
   2119         } else if (input.length) {
   2120           int64_t remaining;
   2121           int64_t rate;
   2122 
   2123           if (global.limit) {
   2124             int frame_in_lagged = (seen_frames - lagged_count) * 1000;
   2125 
   2126             rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
   2127             remaining = 1000 * (global.limit - global.skip_frames
   2128                                 - seen_frames + lagged_count);
   2129           } else {
   2130             off_t input_pos = ftello(input.file);
   2131             off_t input_pos_lagged = input_pos - lagged_count;
   2132             int64_t limit = input.length;
   2133 
   2134             rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0;
   2135             remaining = limit - input_pos + lagged_count;
   2136           }
   2137 
   2138           average_rate = (average_rate <= 0)
   2139               ? rate
   2140               : (average_rate * 7 + rate) / 8;
   2141           estimated_time_left = average_rate ? remaining / average_rate : -1;
   2142         }
   2143 
   2144         if (got_data && global.test_decode != TEST_DECODE_OFF)
   2145           FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec));
   2146       }
   2147 
   2148       fflush(stdout);
   2149     }
   2150 
   2151     if (stream_cnt > 1)
   2152       fprintf(stderr, "\n");
   2153 
   2154     if (!global.quiet)
   2155       FOREACH_STREAM(fprintf(
   2156                        stderr,
   2157                        "\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s"
   2158                        " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1,
   2159                        global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes,
   2160                        seen_frames ? (unsigned long)(stream->nbytes * 8 / seen_frames) : 0,
   2161                        seen_frames ? (int64_t)stream->nbytes * 8
   2162                        * (int64_t)global.framerate.num / global.framerate.den
   2163                        / seen_frames
   2164                        : 0,
   2165                        stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
   2166                        stream->cx_time > 9999999 ? "ms" : "us",
   2167                        usec_to_fps(stream->cx_time, seen_frames));
   2168                     );
   2169 
   2170     if (global.show_psnr)
   2171       FOREACH_STREAM(show_psnr(stream));
   2172 
   2173     FOREACH_STREAM(vpx_codec_destroy(&stream->encoder));
   2174 
   2175     if (global.test_decode != TEST_DECODE_OFF) {
   2176       FOREACH_STREAM(vpx_codec_destroy(&stream->decoder));
   2177     }
   2178 
   2179     close_input_file(&input);
   2180 
   2181     if (global.test_decode == TEST_DECODE_FATAL) {
   2182       FOREACH_STREAM(res |= stream->mismatch_seen);
   2183     }
   2184     FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
   2185 
   2186     FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1));
   2187 
   2188     if (global.pass)
   2189       break;
   2190   }
   2191 
   2192   if (global.show_q_hist_buckets)
   2193     FOREACH_STREAM(show_q_histogram(stream->counts,
   2194                                     global.show_q_hist_buckets));
   2195 
   2196   if (global.show_rate_hist_buckets)
   2197     FOREACH_STREAM(show_rate_histogram(&stream->rate_hist,
   2198                                        &stream->config.cfg,
   2199                                        global.show_rate_hist_buckets));
   2200   FOREACH_STREAM(destroy_rate_histogram(&stream->rate_hist));
   2201 
   2202 #if CONFIG_INTERNAL_STATS
   2203   /* TODO(jkoleszar): This doesn't belong in this executable. Do it for now,
   2204    * to match some existing utilities.
   2205    */
   2206   if (!(global.pass == 1 && global.passes == 2))
   2207     FOREACH_STREAM({
   2208       FILE *f = fopen("opsnr.stt", "a");
   2209       if (stream->mismatch_seen) {
   2210         fprintf(f, "First mismatch occurred in frame %d\n",
   2211                 stream->mismatch_seen);
   2212       } else {
   2213         fprintf(f, "No mismatch detected in recon buffers\n");
   2214       }
   2215       fclose(f);
   2216     });
   2217 #endif
   2218 
   2219   vpx_img_free(&raw);
   2220   free(argv);
   2221   free(streams);
   2222   return res ? EXIT_FAILURE : EXIT_SUCCESS;
   2223 }
   2224