1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpxenc.h"
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h"
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <assert.h>
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <limits.h>
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <math.h>
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdarg.h>
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdio.h>
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h>
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_encoder.h"
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_DECODERS
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_decoder.h"
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/libyuv/include/libyuv/scale.h"
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./args.h"
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./ivfenc.h"
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./tools_common.h"
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8cx.h"
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8dx.h"
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_integer.h"
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/mem_ops.h"
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/vpx_timer.h"
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./rate_hist.h"
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpxstats.h"
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./warnings.h"
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./webmenc.h"
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./y4minput.h"
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Swallow warnings about unused results of fread/fwrite */
49233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         FILE *stream) {
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return fread(ptr, size, nmemb, stream);
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define fread wrap_fread
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan
55233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          FILE *stream) {
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return fwrite(ptr, size, nmemb, stream);
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define fwrite wrap_fwrite
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan
62233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const char *exec_name;
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan
64233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   const char *s, va_list ap) {
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx->err) {
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const char *detail = vpx_codec_error_detail(ctx);
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vfprintf(stderr, s, ap);
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (detail)
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fprintf(stderr, "    %s\n", detail);
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (fatal)
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan      exit(EXIT_FAILURE);
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan
80233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_list ap;
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_start(ap, s);
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan  warn_or_exit_on_errorv(ctx, 1, s, ap);
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_end(ap);
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan
88233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal,
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  const char *s, ...) {
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_list ap;
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_start(ap, s);
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan  warn_or_exit_on_errorv(ctx, fatal, s, ap);
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan  va_end(ap);
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan
97233d2500723e5594f3e7c70896ffeeef32b9c950ywanint read_frame(struct VpxInputContext *input_ctx, vpx_image_t *img) {
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FILE *f = input_ctx->file;
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan  y4m_input *y4m = &input_ctx->y4m;
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int shortread = 0;
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (input_ctx->file_type == FILE_TYPE_Y4M) {
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (y4m_input_fetch_frame(y4m, f, img) < 1)
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    shortread = read_yuv_frame(input_ctx, img);
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return !shortread;
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan
112233d2500723e5594f3e7c70896ffeeef32b9c950ywanint file_is_y4m(const char detect[4]) {
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (memcmp(detect, "YUV4", 4) == 0) {
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywanint fourcc_is_ivf(const char detect[4]) {
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (memcmp(detect, "DKIF", 4) == 0) {
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Murmur hash derived from public domain reference implementation at
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan *   http:// sites.google.com/site/murmurhash/
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
130233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int murmur(const void *key, int len, unsigned int seed) {
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const unsigned int m = 0x5bd1e995;
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int r = 24;
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int h = seed ^ len;
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const unsigned char *data = (const unsigned char *)key;
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (len >= 4) {
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int k;
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k  = (unsigned int)data[0];
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k |= (unsigned int)data[1] << 8;
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k |= (unsigned int)data[2] << 16;
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k |= (unsigned int)data[3] << 24;
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k *= m;
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k ^= k >> r;
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    k *= m;
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan    h *= m;
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    h ^= k;
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan    data += 4;
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan    len -= 4;
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (len) {
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case 3:
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan      h ^= data[2] << 16;
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case 2:
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan      h ^= data[1] << 8;
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case 1:
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan      h ^= data[0];
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan      h *= m;
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  };
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  h ^= h >> 13;
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  h *= m;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  h ^= h >> 15;
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return h;
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif  // CONFIG_WEBM_IO
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
175233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           "Debug mode (makes output deterministic)");
177233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t outputfile = ARG_DEF("o", "output", 1,
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            "Output filename");
179233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "Input file is YV12 ");
181233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "Input file is I420 (default)");
183233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "Codec to use");
185233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t passes           = ARG_DEF("p", "passes", 1,
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Number of passes (1/2)");
187233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t pass_arg         = ARG_DEF(NULL, "pass", 1,
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Pass to execute (1/2)");
189233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t fpf_name         = ARG_DEF(NULL, "fpf", 1,
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "First pass statistics file name");
191233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t limit = ARG_DEF(NULL, "limit", 1,
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       "Stop encoding after n input frames");
193233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t skip = ARG_DEF(NULL, "skip", 1,
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      "Skip the first n input frames");
195233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t deadline         = ARG_DEF("d", "deadline", 1,
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Deadline per frame (usec)");
197233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t best_dl          = ARG_DEF(NULL, "best", 0,
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Use Best Quality Deadline");
199233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t good_dl          = ARG_DEF(NULL, "good", 0,
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Use Good Quality Deadline");
201233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t rt_dl            = ARG_DEF(NULL, "rt", 0,
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Use Realtime Quality Deadline");
203233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t quietarg         = ARG_DEF("q", "quiet", 0,
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Do not print encode progress");
205233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t verbosearg       = ARG_DEF("v", "verbose", 0,
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Show encoder parameters");
207233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Show PSNR in status line");
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
210233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list test_decode_enum[] = {
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"off",   TEST_DECODE_OFF},
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"fatal", TEST_DECODE_FATAL},
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"warn",  TEST_DECODE_WARN},
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {NULL, 0}
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
216233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1,
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                "Test encode/decode mismatch",
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                test_decode_enum);
219233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Stream frame rate (rate/scale)");
221233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Output IVF (default is WebM if WebM IO is enabled)");
223233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "Makes encoder output partitions. Requires IVF output!");
225233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Show quantizer histogram (n-buckets)");
227233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                     "Show rate histogram (n-buckets)");
229233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t disable_warnings =
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ARG_DEF(NULL, "disable-warnings", 0,
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan            "Disable warnings about potentially incorrect encode settings.");
232233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t disable_warning_prompt =
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ARG_DEF("y", "disable-warning-prompt", 0,
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan            "Display warnings, but do not prompt user to continue.");
235233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t experimental_bitstream =
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ARG_DEF(NULL, "experimental-bitstream", 0,
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan            "Allow experimental bitstream features.");
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan
240233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *main_args[] = {
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &debugmode,
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip,
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &deadline, &best_dl, &good_dl, &rt_dl,
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n,
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &rate_hist_n, &disable_warnings, &disable_warning_prompt,
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan  NULL
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan
249233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t usage            = ARG_DEF("u", "usage", 1,
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Usage profile number to use");
251233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t threads          = ARG_DEF("t", "threads", 1,
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Max number of threads to use");
253233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t profile          = ARG_DEF(NULL, "profile", 1,
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Bitstream profile number to use");
255233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t width            = ARG_DEF("w", "width", 1,
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Frame width");
257233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t height           = ARG_DEF("h", "height", 1,
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Frame height");
259233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list stereo_mode_enum[] = {
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"mono", STEREO_FORMAT_MONO},
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"left-right", STEREO_FORMAT_LEFT_RIGHT},
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"bottom-top", STEREO_FORMAT_BOTTOM_TOP},
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"top-bottom", STEREO_FORMAT_TOP_BOTTOM},
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"right-left", STEREO_FORMAT_RIGHT_LEFT},
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {NULL, 0}
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
267233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t stereo_mode      = ARG_DEF_ENUM(NULL, "stereo-mode", 1,
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                       "Stereo 3D video format", stereo_mode_enum);
269233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t timebase         = ARG_DEF(NULL, "timebase", 1,
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Output timestamp precision (fractional seconds)");
271233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t error_resilient  = ARG_DEF(NULL, "error-resilient", 1,
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Enable error resiliency features");
273233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t lag_in_frames    = ARG_DEF(NULL, "lag-in-frames", 1,
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  "Max number of frames to lag");
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
276233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *global_args[] = {
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &use_yv12, &use_i420, &usage, &threads, &profile,
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &width, &height, &stereo_mode, &timebase, &framerate,
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &error_resilient,
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &lag_in_frames, NULL
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
283233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t dropframe_thresh   = ARG_DEF(NULL, "drop-frame", 1,
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Temporal resampling threshold (buf %)");
285233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t resize_allowed     = ARG_DEF(NULL, "resize-allowed", 1,
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Spatial resampling enabled (bool)");
287233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t resize_up_thresh   = ARG_DEF(NULL, "resize-up", 1,
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Upscale threshold (buf %)");
289233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1,
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Downscale threshold (buf %)");
291233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list end_usage_enum[] = {
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"vbr", VPX_VBR},
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"cbr", VPX_CBR},
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"cq",  VPX_CQ},
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"q",   VPX_Q},
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {NULL, 0}
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
298233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t end_usage          = ARG_DEF_ENUM(NULL, "end-usage", 1,
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                         "Rate control mode", end_usage_enum);
300233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t target_bitrate     = ARG_DEF(NULL, "target-bitrate", 1,
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Bitrate (kbps)");
302233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t min_quantizer      = ARG_DEF(NULL, "min-q", 1,
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Minimum (best) quantizer");
304233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t max_quantizer      = ARG_DEF(NULL, "max-q", 1,
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Maximum (worst) quantizer");
306233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t undershoot_pct     = ARG_DEF(NULL, "undershoot-pct", 1,
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Datarate undershoot (min) target (%)");
308233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t overshoot_pct      = ARG_DEF(NULL, "overshoot-pct", 1,
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Datarate overshoot (max) target (%)");
310233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t buf_sz             = ARG_DEF(NULL, "buf-sz", 1,
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Client buffer size (ms)");
312233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t buf_initial_sz     = ARG_DEF(NULL, "buf-initial-sz", 1,
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Client initial buffer size (ms)");
314233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t buf_optimal_sz     = ARG_DEF(NULL, "buf-optimal-sz", 1,
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Client optimal buffer size (ms)");
316233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *rc_args[] = {
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh,
318233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &end_usage, &target_bitrate, &min_quantizer, &max_quantizer,
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz,
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan  NULL
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
324233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t bias_pct = ARG_DEF(NULL, "bias-pct", 1,
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "CBR/VBR bias (0=CBR, 100=VBR)");
326233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t minsection_pct = ARG_DEF(NULL, "minsection-pct", 1,
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                "GOP min bitrate (% of target)");
328233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t maxsection_pct = ARG_DEF(NULL, "maxsection-pct", 1,
329233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                "GOP max bitrate (% of target)");
330233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *rc_twopass_args[] = {
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &bias_pct, &minsection_pct, &maxsection_pct, NULL
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan
334233d2500723e5594f3e7c70896ffeeef32b9c950ywan
335233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t kf_min_dist = ARG_DEF(NULL, "kf-min-dist", 1,
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             "Minimum keyframe interval (frames)");
337233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t kf_max_dist = ARG_DEF(NULL, "kf-max-dist", 1,
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             "Maximum keyframe interval (frames)");
339233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t kf_disabled = ARG_DEF(NULL, "disable-kf", 0,
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             "Disable keyframe placement");
341233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *kf_args[] = {
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &kf_min_dist, &kf_max_dist, &kf_disabled, NULL
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
344233d2500723e5594f3e7c70896ffeeef32b9c950ywan
345233d2500723e5594f3e7c70896ffeeef32b9c950ywan
346233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t noise_sens = ARG_DEF(NULL, "noise-sensitivity", 1,
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            "Noise sensitivity (frames to blur)");
348233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t sharpness = ARG_DEF(NULL, "sharpness", 1,
349233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           "Filter sharpness (0-7)");
350233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t static_thresh = ARG_DEF(NULL, "static-thresh", 1,
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               "Motion detection threshold");
352233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t cpu_used = ARG_DEF(NULL, "cpu-used", 1,
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "CPU Used (-16..16)");
354233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t auto_altref = ARG_DEF(NULL, "auto-alt-ref", 1,
355233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             "Enable automatic alt reference frames");
356233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t arnr_maxframes = ARG_DEF(NULL, "arnr-maxframes", 1,
357233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                "AltRef Max Frames");
358233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1,
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               "AltRef Strength");
360233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1,
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           "AltRef Type");
362233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const struct arg_enum_list tuning_enum[] = {
363233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"psnr", VP8_TUNE_PSNR},
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {"ssim", VP8_TUNE_SSIM},
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {NULL, 0}
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
367233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
368233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                "Material to favor", tuning_enum);
369233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          "Constant/Constrained Quality level");
371233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    "Max I-frame bitrate (pct)");
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
374233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER
375233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t token_parts =
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ARG_DEF(NULL, "token-parts", 1, "Number of token partitions to use, log2");
377233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *vp8_args[] = {
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &tune_ssim, &cq_level, &max_intra_rate_pct,
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan  NULL
382233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
383233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const int vp8_arg_ctrl_map[] = {
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_TOKEN_PARTITIONS,
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
389233d2500723e5594f3e7c70896ffeeef32b9c950ywan  0
390233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan
393233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER
394233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t tile_cols =
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ARG_DEF(NULL, "tile-columns", 1, "Number of tile columns to use, log2");
396233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t tile_rows =
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ARG_DEF(NULL, "tile-rows", 1, "Number of tile rows to use, log2");
398233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t lossless = ARG_DEF(NULL, "lossless", 1, "Lossless mode");
399233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t frame_parallel_decoding = ARG_DEF(
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan    NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
401233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t aq_mode = ARG_DEF(
402233d2500723e5594f3e7c70896ffeeef32b9c950ywan    NULL, "aq-mode", 1,
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    "Adaptive q mode (0: off (by default), 1: variance 2: complexity, "
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan    "3: cyclic refresh)");
405233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t frame_periodic_boost = ARG_DEF(
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    NULL, "frame_boost", 1,
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan    "Enable frame periodic boost (0: off (by default), 1: on)");
408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
409233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *vp9_args[] = {
410233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
411233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
412233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  &frame_parallel_decoding, &aq_mode, &frame_periodic_boost,
414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  NULL
415233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
416233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const int vp9_arg_ctrl_map[] = {
417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
421233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
422233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9E_SET_FRAME_PERIODIC_BOOST,
424233d2500723e5594f3e7c70896ffeeef32b9c950ywan  0
425233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
426233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
427233d2500723e5594f3e7c70896ffeeef32b9c950ywan
428233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const arg_def_t *no_args[] = { NULL };
429233d2500723e5594f3e7c70896ffeeef32b9c950ywan
430233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid usage_exit() {
431233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
432233d2500723e5594f3e7c70896ffeeef32b9c950ywan
433233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
434233d2500723e5594f3e7c70896ffeeef32b9c950ywan          exec_name);
435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
436233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nOptions:\n");
437233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, main_args);
438233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nEncoder Global Options:\n");
439233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, global_args);
440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nRate Control Options:\n");
441233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, rc_args);
442233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nTwopass Rate Control Options:\n");
443233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, rc_twopass_args);
444233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nKeyframe Placement Options:\n");
445233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, kf_args);
446233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER
447233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nVP8 Specific Options:\n");
448233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, vp8_args);
449233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
450233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER
451233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nVP9 Specific Options:\n");
452233d2500723e5594f3e7c70896ffeeef32b9c950ywan  arg_show_usage(stderr, vp9_args);
453233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
454233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nStream timebase (--timebase):\n"
455233d2500723e5594f3e7c70896ffeeef32b9c950ywan          "  The desired precision of timestamps in the output, expressed\n"
456233d2500723e5594f3e7c70896ffeeef32b9c950ywan          "  in fractional seconds. Default is 1/1000.\n");
457233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\nIncluded encoders:\n\n");
458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
459233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < get_vpx_encoder_count(); ++i) {
460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const VpxInterface *const encoder = get_vpx_encoder_by_index(i);
461233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, "    %-6s - %s\n",
462233d2500723e5594f3e7c70896ffeeef32b9c950ywan            encoder->name, vpx_codec_iface_name(encoder->interface()));
463233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
465233d2500723e5594f3e7c70896ffeeef32b9c950ywan  exit(EXIT_FAILURE);
466233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
467233d2500723e5594f3e7c70896ffeeef32b9c950ywan
468233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define mmin(a, b)  ((a) < (b) ? (a) : (b))
469233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void find_mismatch(const vpx_image_t *const img1,
470233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          const vpx_image_t *const img2,
471233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          int yloc[4], int uloc[4], int vloc[4]) {
472233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t bsize = 64;
473233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t bsizey = bsize >> img1->y_chroma_shift;
474233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t bsizex = bsize >> img1->x_chroma_shift;
475233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t c_w =
476233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
477233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t c_h =
478233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
479233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int match = 1;
480233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint32_t i, j;
481233d2500723e5594f3e7c70896ffeeef32b9c950ywan  yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
482233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; match && j < img1->d_w; j += bsize) {
484233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int k, l;
485233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int si = mmin(i + bsize, img1->d_h) - i;
486233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int sj = mmin(j + bsize, img1->d_w) - j;
487233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (k = 0; match && k < si; ++k) {
488233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (l = 0; match && l < sj; ++l) {
489233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (*(img1->planes[VPX_PLANE_Y] +
490233d2500723e5594f3e7c70896ffeeef32b9c950ywan                (i + k) * img1->stride[VPX_PLANE_Y] + j + l) !=
491233d2500723e5594f3e7c70896ffeeef32b9c950ywan              *(img2->planes[VPX_PLANE_Y] +
492233d2500723e5594f3e7c70896ffeeef32b9c950ywan                (i + k) * img2->stride[VPX_PLANE_Y] + j + l)) {
493233d2500723e5594f3e7c70896ffeeef32b9c950ywan            yloc[0] = i + k;
494233d2500723e5594f3e7c70896ffeeef32b9c950ywan            yloc[1] = j + l;
495233d2500723e5594f3e7c70896ffeeef32b9c950ywan            yloc[2] = *(img1->planes[VPX_PLANE_Y] +
496233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (i + k) * img1->stride[VPX_PLANE_Y] + j + l);
497233d2500723e5594f3e7c70896ffeeef32b9c950ywan            yloc[3] = *(img2->planes[VPX_PLANE_Y] +
498233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (i + k) * img2->stride[VPX_PLANE_Y] + j + l);
499233d2500723e5594f3e7c70896ffeeef32b9c950ywan            match = 0;
500233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
501233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
502233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
503233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
505233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
506233d2500723e5594f3e7c70896ffeeef32b9c950ywan
507233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1;
508233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0, match = 1; match && i < c_h; i += bsizey) {
509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; match && j < c_w; j += bsizex) {
510233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int k, l;
511233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int si = mmin(i + bsizey, c_h - i);
512233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int sj = mmin(j + bsizex, c_w - j);
513233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (k = 0; match && k < si; ++k) {
514233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (l = 0; match && l < sj; ++l) {
515233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (*(img1->planes[VPX_PLANE_U] +
516233d2500723e5594f3e7c70896ffeeef32b9c950ywan                (i + k) * img1->stride[VPX_PLANE_U] + j + l) !=
517233d2500723e5594f3e7c70896ffeeef32b9c950ywan              *(img2->planes[VPX_PLANE_U] +
518233d2500723e5594f3e7c70896ffeeef32b9c950ywan                (i + k) * img2->stride[VPX_PLANE_U] + j + l)) {
519233d2500723e5594f3e7c70896ffeeef32b9c950ywan            uloc[0] = i + k;
520233d2500723e5594f3e7c70896ffeeef32b9c950ywan            uloc[1] = j + l;
521233d2500723e5594f3e7c70896ffeeef32b9c950ywan            uloc[2] = *(img1->planes[VPX_PLANE_U] +
522233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (i + k) * img1->stride[VPX_PLANE_U] + j + l);
523233d2500723e5594f3e7c70896ffeeef32b9c950ywan            uloc[3] = *(img2->planes[VPX_PLANE_U] +
524233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (i + k) * img2->stride[VPX_PLANE_U] + j + l);
525233d2500723e5594f3e7c70896ffeeef32b9c950ywan            match = 0;
526233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
527233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
528233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
529233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
531233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
532233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
533233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0, match = 1; match && i < c_h; i += bsizey) {
534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (j = 0; match && j < c_w; j += bsizex) {
535233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int k, l;
536233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int si = mmin(i + bsizey, c_h - i);
537233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int sj = mmin(j + bsizex, c_w - j);
538233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (k = 0; match && k < si; ++k) {
539233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (l = 0; match && l < sj; ++l) {
540233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (*(img1->planes[VPX_PLANE_V] +
541233d2500723e5594f3e7c70896ffeeef32b9c950ywan                (i + k) * img1->stride[VPX_PLANE_V] + j + l) !=
542233d2500723e5594f3e7c70896ffeeef32b9c950ywan              *(img2->planes[VPX_PLANE_V] +
543233d2500723e5594f3e7c70896ffeeef32b9c950ywan                (i + k) * img2->stride[VPX_PLANE_V] + j + l)) {
544233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vloc[0] = i + k;
545233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vloc[1] = j + l;
546233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vloc[2] = *(img1->planes[VPX_PLANE_V] +
547233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (i + k) * img1->stride[VPX_PLANE_V] + j + l);
548233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vloc[3] = *(img2->planes[VPX_PLANE_V] +
549233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        (i + k) * img2->stride[VPX_PLANE_V] + j + l);
550233d2500723e5594f3e7c70896ffeeef32b9c950ywan            match = 0;
551233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
552233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
553233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
554233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
555233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
556233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
557233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
558233d2500723e5594f3e7c70896ffeeef32b9c950ywan
559233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int compare_img(const vpx_image_t *const img1,
560233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       const vpx_image_t *const img2) {
561233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t c_w =
562233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
563233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32_t c_h =
564233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
565233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint32_t i;
566233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int match = 1;
567233d2500723e5594f3e7c70896ffeeef32b9c950ywan
568233d2500723e5594f3e7c70896ffeeef32b9c950ywan  match &= (img1->fmt == img2->fmt);
569233d2500723e5594f3e7c70896ffeeef32b9c950ywan  match &= (img1->d_w == img2->d_w);
570233d2500723e5594f3e7c70896ffeeef32b9c950ywan  match &= (img1->d_h == img2->d_h);
571233d2500723e5594f3e7c70896ffeeef32b9c950ywan
572233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < img1->d_h; ++i)
573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    match &= (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
574233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
575233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     img1->d_w) == 0);
576233d2500723e5594f3e7c70896ffeeef32b9c950ywan
577233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < c_h; ++i)
578233d2500723e5594f3e7c70896ffeeef32b9c950ywan    match &= (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
579233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
580233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     c_w) == 0);
581233d2500723e5594f3e7c70896ffeeef32b9c950ywan
582233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < c_h; ++i)
583233d2500723e5594f3e7c70896ffeeef32b9c950ywan    match &= (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
584233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
585233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     c_w) == 0);
586233d2500723e5594f3e7c70896ffeeef32b9c950ywan
587233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return match;
588233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
590233d2500723e5594f3e7c70896ffeeef32b9c950ywan
591233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
592233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define MAX(x,y) ((x)>(y)?(x):(y))
593233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER
594233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
595233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif !CONFIG_VP8_ENCODER && CONFIG_VP9_ENCODER
596233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map)
597233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
598233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ARG_CTRL_CNT_MAX MAX(NELEMENTS(vp8_arg_ctrl_map), \
599233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             NELEMENTS(vp9_arg_ctrl_map))
600233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
602233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Per-stream configuration */
603233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct stream_config {
604233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct vpx_codec_enc_cfg  cfg;
605233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const char               *out_fn;
606233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const char               *stats_fn;
607233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stereo_format_t           stereo_fmt;
608233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       arg_ctrls[ARG_CTRL_CNT_MAX][2];
609233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       arg_ctrl_cnt;
610233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       write_webm;
611233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       have_kf_max_dist;
612233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
613233d2500723e5594f3e7c70896ffeeef32b9c950ywan
614233d2500723e5594f3e7c70896ffeeef32b9c950ywan
615233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct stream_state {
616233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       index;
617233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct stream_state      *next;
618233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct stream_config      config;
619233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FILE                     *file;
620233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct rate_hist         *rate_hist;
621233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct EbmlGlobal         ebml;
622233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint32_t                  hash;
623233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t                  psnr_sse_total;
624233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t                  psnr_samples_total;
625233d2500723e5594f3e7c70896ffeeef32b9c950ywan  double                    psnr_totals[4];
626233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       psnr_count;
627233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       counts[64];
628233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_ctx_t           encoder;
629233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int              frames_out;
630233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t                  cx_time;
631233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t                    nbytes;
632233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stats_io_t                stats;
633233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct vpx_image         *img;
634233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_ctx_t           decoder;
635233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                       mismatch_seen;
636233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
637233d2500723e5594f3e7c70896ffeeef32b9c950ywan
638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
639233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid validate_positive_rational(const char          *msg,
640233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                struct vpx_rational *rat) {
641233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rat->den < 0) {
642233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rat->num *= -1;
643233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rat->den *= -1;
644233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
645233d2500723e5594f3e7c70896ffeeef32b9c950ywan
646233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rat->num < 0)
647233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Error: %s must be positive\n", msg);
648233d2500723e5594f3e7c70896ffeeef32b9c950ywan
649233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!rat->den)
650233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Error: %s has zero denominator\n", msg);
651233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
653233d2500723e5594f3e7c70896ffeeef32b9c950ywan
654233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
655233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char       **argi, **argj;
656233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct arg   arg;
657233d2500723e5594f3e7c70896ffeeef32b9c950ywan
658233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Initialize default parameters */
659233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memset(global, 0, sizeof(*global));
660233d2500723e5594f3e7c70896ffeeef32b9c950ywan  global->codec = get_vpx_encoder_by_index(0);
661233d2500723e5594f3e7c70896ffeeef32b9c950ywan  global->passes = 0;
662233d2500723e5594f3e7c70896ffeeef32b9c950ywan  global->use_i420 = 1;
663233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Assign default deadline to good quality */
664233d2500723e5594f3e7c70896ffeeef32b9c950ywan  global->deadline = VPX_DL_GOOD_QUALITY;
665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
666233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
667233d2500723e5594f3e7c70896ffeeef32b9c950ywan    arg.argv_step = 1;
668233d2500723e5594f3e7c70896ffeeef32b9c950ywan
669233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (arg_match(&arg, &codecarg, argi)) {
670233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->codec = get_vpx_encoder_by_name(arg.val);
671233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!global->codec)
672233d2500723e5594f3e7c70896ffeeef32b9c950ywan        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
673233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &passes, argi)) {
674233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->passes = arg_parse_uint(&arg);
675233d2500723e5594f3e7c70896ffeeef32b9c950ywan
676233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (global->passes < 1 || global->passes > 2)
677233d2500723e5594f3e7c70896ffeeef32b9c950ywan        die("Error: Invalid number of passes (%d)\n", global->passes);
678233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &pass_arg, argi)) {
679233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->pass = arg_parse_uint(&arg);
680233d2500723e5594f3e7c70896ffeeef32b9c950ywan
681233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (global->pass < 1 || global->pass > 2)
682233d2500723e5594f3e7c70896ffeeef32b9c950ywan        die("Error: Invalid pass selected (%d)\n",
683233d2500723e5594f3e7c70896ffeeef32b9c950ywan            global->pass);
684233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &usage, argi))
685233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->usage = arg_parse_uint(&arg);
686233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &deadline, argi))
687233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->deadline = arg_parse_uint(&arg);
688233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &best_dl, argi))
689233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->deadline = VPX_DL_BEST_QUALITY;
690233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &good_dl, argi))
691233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->deadline = VPX_DL_GOOD_QUALITY;
692233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &rt_dl, argi))
693233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->deadline = VPX_DL_REALTIME;
694233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &use_yv12, argi))
695233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->use_i420 = 0;
696233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &use_i420, argi))
697233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->use_i420 = 1;
698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &quietarg, argi))
699233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->quiet = 1;
700233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &verbosearg, argi))
701233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->verbose = 1;
702233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &limit, argi))
703233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->limit = arg_parse_uint(&arg);
704233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &skip, argi))
705233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->skip_frames = arg_parse_uint(&arg);
706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &psnrarg, argi))
707233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->show_psnr = 1;
708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &recontest, argi))
709233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->test_decode = arg_parse_enum_or_int(&arg);
710233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &framerate, argi)) {
711233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->framerate = arg_parse_rational(&arg);
712233d2500723e5594f3e7c70896ffeeef32b9c950ywan      validate_positive_rational(arg.name, &global->framerate);
713233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->have_framerate = 1;
714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &out_part, argi))
715233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->out_part = 1;
716233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &debugmode, argi))
717233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->debug = 1;
718233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &q_hist_n, argi))
719233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->show_q_hist_buckets = arg_parse_uint(&arg);
720233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &rate_hist_n, argi))
721233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->show_rate_hist_buckets = arg_parse_uint(&arg);
722233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &disable_warnings, argi))
723233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->disable_warnings = 1;
724233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &disable_warning_prompt, argi))
725233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->disable_warning_prompt = 1;
726233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (arg_match(&arg, &experimental_bitstream, argi))
727233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->experimental_bitstream = 1;
728233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
729233d2500723e5594f3e7c70896ffeeef32b9c950ywan      argj++;
730233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
731233d2500723e5594f3e7c70896ffeeef32b9c950ywan
732233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global->pass) {
733233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
734233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global->pass > global->passes) {
735233d2500723e5594f3e7c70896ffeeef32b9c950ywan      warn("Assuming --pass=%d implies --passes=%d\n",
736233d2500723e5594f3e7c70896ffeeef32b9c950ywan           global->pass, global->pass);
737233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->passes = global->pass;
738233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
739233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
740233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Validate global config */
741233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global->passes == 0) {
742233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER
743233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Make default VP9 passes = 2 until there is a better quality 1-pass
744233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // encoder
745233d2500723e5594f3e7c70896ffeeef32b9c950ywan    global->passes = (strcmp(global->codec->name, "vp9") == 0 &&
746233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      global->deadline != VPX_DL_REALTIME) ? 2 : 1;
747233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
748233d2500723e5594f3e7c70896ffeeef32b9c950ywan    global->passes = 1;
749233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
750233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
751233d2500723e5594f3e7c70896ffeeef32b9c950ywan
752233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global->deadline == VPX_DL_REALTIME &&
753233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global->passes > 1) {
754233d2500723e5594f3e7c70896ffeeef32b9c950ywan    warn("Enforcing one-pass encoding in realtime mode\n");
755233d2500723e5594f3e7c70896ffeeef32b9c950ywan    global->passes = 1;
756233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
757233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
758233d2500723e5594f3e7c70896ffeeef32b9c950ywan
759233d2500723e5594f3e7c70896ffeeef32b9c950ywan
760233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid open_input_file(struct VpxInputContext *input) {
761233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Parse certain options from the input file, if possible */
762233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input->file = strcmp(input->filename, "-")
763233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ? fopen(input->filename, "rb") : set_binary_mode(stdin);
764233d2500723e5594f3e7c70896ffeeef32b9c950ywan
765233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!input->file)
766233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("Failed to open input file");
767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
768233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!fseeko(input->file, 0, SEEK_END)) {
769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Input file is seekable. Figure out how long it is, so we can get
770233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * progress info.
771233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    input->length = ftello(input->file);
773233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rewind(input->file);
774233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
776233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* For RAW input sources, these bytes will applied on the first frame
777233d2500723e5594f3e7c70896ffeeef32b9c950ywan   *  in read_frame().
778233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
779233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file);
780233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input->detect.position = 0;
781233d2500723e5594f3e7c70896ffeeef32b9c950ywan
782233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (input->detect.buf_read == 4
783233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && file_is_y4m(input->detect.buf)) {
784233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
785233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       input->only_i420) >= 0) {
786233d2500723e5594f3e7c70896ffeeef32b9c950ywan      input->file_type = FILE_TYPE_Y4M;
787233d2500723e5594f3e7c70896ffeeef32b9c950ywan      input->width = input->y4m.pic_w;
788233d2500723e5594f3e7c70896ffeeef32b9c950ywan      input->height = input->y4m.pic_h;
789233d2500723e5594f3e7c70896ffeeef32b9c950ywan      input->framerate.numerator = input->y4m.fps_n;
790233d2500723e5594f3e7c70896ffeeef32b9c950ywan      input->framerate.denominator = input->y4m.fps_d;
791233d2500723e5594f3e7c70896ffeeef32b9c950ywan      input->use_i420 = 0;
792233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else
793233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fatal("Unsupported Y4M stream.");
794233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (input->detect.buf_read == 4 && fourcc_is_ivf(input->detect.buf)) {
795233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("IVF is not supported as input.");
796233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
797233d2500723e5594f3e7c70896ffeeef32b9c950ywan    input->file_type = FILE_TYPE_RAW;
798233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
799233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
800233d2500723e5594f3e7c70896ffeeef32b9c950ywan
801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
802233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void close_input_file(struct VpxInputContext *input) {
803233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fclose(input->file);
804233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (input->file_type == FILE_TYPE_Y4M)
805233d2500723e5594f3e7c70896ffeeef32b9c950ywan    y4m_input_close(&input->y4m);
806233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
808233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct stream_state *new_stream(struct VpxEncoderConfig *global,
809233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       struct stream_state *prev) {
810233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct stream_state *stream;
811233d2500723e5594f3e7c70896ffeeef32b9c950ywan
812233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream = calloc(1, sizeof(*stream));
813233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream)
814233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("Failed to allocate new stream.");
815233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (prev) {
816233d2500723e5594f3e7c70896ffeeef32b9c950ywan    memcpy(stream, prev, sizeof(*stream));
817233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->index++;
818233d2500723e5594f3e7c70896ffeeef32b9c950ywan    prev->next = stream;
819233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
820233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_err_t  res;
821233d2500723e5594f3e7c70896ffeeef32b9c950ywan
822233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Populate encoder configuration */
823233d2500723e5594f3e7c70896ffeeef32b9c950ywan    res = vpx_codec_enc_config_default(global->codec->interface(),
824233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       &stream->config.cfg,
825233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       global->usage);
826233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (res)
827233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res));
828233d2500723e5594f3e7c70896ffeeef32b9c950ywan
829233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Change the default timebase to a high enough value so that the
830233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * encoder will always create strictly increasing timestamps.
831233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
832233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.cfg.g_timebase.den = 1000;
833233d2500723e5594f3e7c70896ffeeef32b9c950ywan
834233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Never use the library's default resolution, require it be parsed
835233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * from the file or set on the command line.
836233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
837233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.cfg.g_w = 0;
838233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.cfg.g_h = 0;
839233d2500723e5594f3e7c70896ffeeef32b9c950ywan
840233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Initialize remaining stream parameters */
841233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.stereo_fmt = STEREO_FORMAT_MONO;
842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.write_webm = 1;
843233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO
844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->ebml.last_pts_ms = -1;
845233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
846233d2500723e5594f3e7c70896ffeeef32b9c950ywan
847233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Allows removal of the application version from the EBML tags */
848233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->ebml.debug = global->debug;
849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
850233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Default lag_in_frames is 0 in realtime mode */
851233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global->deadline == VPX_DL_REALTIME)
852233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream->config.cfg.g_lag_in_frames = 0;
853233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
854233d2500723e5594f3e7c70896ffeeef32b9c950ywan
855233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Output files must be specified for each stream */
856233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->config.out_fn = NULL;
857233d2500723e5594f3e7c70896ffeeef32b9c950ywan
858233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->next = NULL;
859233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return stream;
860233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
861233d2500723e5594f3e7c70896ffeeef32b9c950ywan
862233d2500723e5594f3e7c70896ffeeef32b9c950ywan
863233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int parse_stream_params(struct VpxEncoderConfig *global,
864233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               struct stream_state  *stream,
865233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               char **argv) {
866233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char                   **argi, **argj;
867233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct arg               arg;
868233d2500723e5594f3e7c70896ffeeef32b9c950ywan  static const arg_def_t **ctrl_args = no_args;
869233d2500723e5594f3e7c70896ffeeef32b9c950ywan  static const int        *ctrl_args_map = NULL;
870233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct stream_config    *config = &stream->config;
871233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int                      eos_mark_found = 0;
872233d2500723e5594f3e7c70896ffeeef32b9c950ywan
873233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Handle codec specific options
874233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (0) {
875233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_ENCODER
876233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (strcmp(global->codec->name, "vp8") == 0) {
877233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctrl_args = vp8_args;
878233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctrl_args_map = vp8_arg_ctrl_map;
879233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
880233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP9_ENCODER
881233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (strcmp(global->codec->name, "vp9") == 0) {
882233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctrl_args = vp9_args;
883233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctrl_args_map = vp9_arg_ctrl_map;
884233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
885233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
886233d2500723e5594f3e7c70896ffeeef32b9c950ywan
887233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
888233d2500723e5594f3e7c70896ffeeef32b9c950ywan    arg.argv_step = 1;
889233d2500723e5594f3e7c70896ffeeef32b9c950ywan
890233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Once we've found an end-of-stream marker (--) we want to continue
891233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * shifting arguments but not consuming them.
892233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (eos_mark_found) {
894233d2500723e5594f3e7c70896ffeeef32b9c950ywan      argj++;
895233d2500723e5594f3e7c70896ffeeef32b9c950ywan      continue;
896233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (!strcmp(*argj, "--")) {
897233d2500723e5594f3e7c70896ffeeef32b9c950ywan      eos_mark_found = 1;
898233d2500723e5594f3e7c70896ffeeef32b9c950ywan      continue;
899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
900233d2500723e5594f3e7c70896ffeeef32b9c950ywan
901233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (0) {
902233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &outputfile, argi)) {
903233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->out_fn = arg.val;
904233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &fpf_name, argi)) {
905233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->stats_fn = arg.val;
906233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &use_ivf, argi)) {
907233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->write_webm = 0;
908233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &threads, argi)) {
909233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_threads = arg_parse_uint(&arg);
910233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &profile, argi)) {
911233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_profile = arg_parse_uint(&arg);
912233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &width, argi)) {
913233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_w = arg_parse_uint(&arg);
914233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &height, argi)) {
915233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_h = arg_parse_uint(&arg);
916233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &stereo_mode, argi)) {
917233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->stereo_fmt = arg_parse_enum_or_int(&arg);
918233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &timebase, argi)) {
919233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_timebase = arg_parse_rational(&arg);
920233d2500723e5594f3e7c70896ffeeef32b9c950ywan      validate_positive_rational(arg.name, &config->cfg.g_timebase);
921233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &error_resilient, argi)) {
922233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_error_resilient = arg_parse_uint(&arg);
923233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &lag_in_frames, argi)) {
924233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
925233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (global->deadline == VPX_DL_REALTIME &&
926233d2500723e5594f3e7c70896ffeeef32b9c950ywan          config->cfg.g_lag_in_frames != 0) {
927233d2500723e5594f3e7c70896ffeeef32b9c950ywan        warn("non-zero %s option ignored in realtime mode.\n", arg.name);
928233d2500723e5594f3e7c70896ffeeef32b9c950ywan        config->cfg.g_lag_in_frames = 0;
929233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
930233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &dropframe_thresh, argi)) {
931233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &resize_allowed, argi)) {
933233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
934233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &resize_up_thresh, argi)) {
935233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
936233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &resize_down_thresh, argi)) {
937233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
938233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &end_usage, argi)) {
939233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
940233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &target_bitrate, argi)) {
941233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
942233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &min_quantizer, argi)) {
943233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
944233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &max_quantizer, argi)) {
945233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &undershoot_pct, argi)) {
947233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
948233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &overshoot_pct, argi)) {
949233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
950233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &buf_sz, argi)) {
951233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_buf_sz = arg_parse_uint(&arg);
952233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &buf_initial_sz, argi)) {
953233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
954233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &buf_optimal_sz, argi)) {
955233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
956233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &bias_pct, argi)) {
957233d2500723e5594f3e7c70896ffeeef32b9c950ywan        config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
958233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (global->passes < 2)
959233d2500723e5594f3e7c70896ffeeef32b9c950ywan        warn("option %s ignored in one-pass mode.\n", arg.name);
960233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &minsection_pct, argi)) {
961233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
962233d2500723e5594f3e7c70896ffeeef32b9c950ywan
963233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (global->passes < 2)
964233d2500723e5594f3e7c70896ffeeef32b9c950ywan        warn("option %s ignored in one-pass mode.\n", arg.name);
965233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &maxsection_pct, argi)) {
966233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
968233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (global->passes < 2)
969233d2500723e5594f3e7c70896ffeeef32b9c950ywan        warn("option %s ignored in one-pass mode.\n", arg.name);
970233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &kf_min_dist, argi)) {
971233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.kf_min_dist = arg_parse_uint(&arg);
972233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &kf_max_dist, argi)) {
973233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.kf_max_dist = arg_parse_uint(&arg);
974233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->have_kf_max_dist = 1;
975233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (arg_match(&arg, &kf_disabled, argi)) {
976233d2500723e5594f3e7c70896ffeeef32b9c950ywan      config->cfg.kf_mode = VPX_KF_DISABLED;
977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
978233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int i, match = 0;
979233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; ctrl_args[i]; i++) {
980233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (arg_match(&arg, ctrl_args[i], argi)) {
981233d2500723e5594f3e7c70896ffeeef32b9c950ywan          int j;
982233d2500723e5594f3e7c70896ffeeef32b9c950ywan          match = 1;
983233d2500723e5594f3e7c70896ffeeef32b9c950ywan
984233d2500723e5594f3e7c70896ffeeef32b9c950ywan          /* Point either to the next free element or the first
985233d2500723e5594f3e7c70896ffeeef32b9c950ywan          * instance of this control.
986233d2500723e5594f3e7c70896ffeeef32b9c950ywan          */
987233d2500723e5594f3e7c70896ffeeef32b9c950ywan          for (j = 0; j < config->arg_ctrl_cnt; j++)
988233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (config->arg_ctrls[j][0] == ctrl_args_map[i])
989233d2500723e5594f3e7c70896ffeeef32b9c950ywan              break;
990233d2500723e5594f3e7c70896ffeeef32b9c950ywan
991233d2500723e5594f3e7c70896ffeeef32b9c950ywan          /* Update/insert */
992233d2500723e5594f3e7c70896ffeeef32b9c950ywan          assert(j < ARG_CTRL_CNT_MAX);
993233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (j < ARG_CTRL_CNT_MAX) {
994233d2500723e5594f3e7c70896ffeeef32b9c950ywan            config->arg_ctrls[j][0] = ctrl_args_map[i];
995233d2500723e5594f3e7c70896ffeeef32b9c950ywan            config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
996233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (j == config->arg_ctrl_cnt)
997233d2500723e5594f3e7c70896ffeeef32b9c950ywan              config->arg_ctrl_cnt++;
998233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
999233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!match)
1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan        argj++;
1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return eos_mark_found;
1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define FOREACH_STREAM(func) \
1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan  do { \
1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct stream_state *stream; \
1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (stream = streams; stream; stream = stream->next) { \
1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan      func; \
1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } \
1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } while (0)
1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1019233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void validate_stream_config(const struct stream_state *stream,
1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   const struct VpxEncoderConfig *global) {
1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct stream_state *streami;
1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->config.cfg.g_w || !stream->config.cfg.g_h)
1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("Stream %d: Specify stream dimensions with --width (-w) "
1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan          " and --height (-h)", stream->index);
1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->config.cfg.g_profile != 0 && !global->experimental_bitstream) {
1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("Stream %d: profile %d is experimental and requires the --%s flag",
1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan          stream->index, stream->config.cfg.g_profile,
1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan          experimental_bitstream.long_name);
1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (streami = stream; streami; streami = streami->next) {
1034233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* All streams require output files */
1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!streami->config.out_fn)
1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fatal("Stream %d: Output file is required (specify with -o)",
1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan            streami->index);
1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Check for two streams outputting to the same file */
1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (streami != stream) {
1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const char *a = stream->config.out_fn;
1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const char *b = streami->config.out_fn;
1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!strcmp(a, b) && strcmp(a, "/dev/null") && strcmp(a, ":nul"))
1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan        fatal("Stream %d: duplicate output file (from stream %d)",
1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan              streami->index, stream->index);
1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Check for two streams sharing a stats file. */
1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (streami != stream) {
1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const char *a = stream->config.stats_fn;
1051233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const char *b = streami->config.stats_fn;
1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (a && b && !strcmp(a, b))
1053233d2500723e5594f3e7c70896ffeeef32b9c950ywan        fatal("Stream %d: duplicate stats file (from stream %d)",
1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan              streami->index, stream->index);
1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1060233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_stream_dimensions(struct stream_state *stream,
1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  unsigned int w,
1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  unsigned int h) {
1063233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->config.cfg.g_w) {
1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!stream->config.cfg.g_h)
1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream->config.cfg.g_w = w;
1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->config.cfg.g_h) {
1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1072233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1073233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1075233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void set_default_kf_interval(struct stream_state *stream,
1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    struct VpxEncoderConfig *global) {
1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Use a max keyframe interval of 5 seconds, if none was
1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * specified on the command line.
1079233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
1080233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->config.have_kf_max_dist) {
1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan    double framerate = (double)global->framerate.num / global->framerate.den;
1082233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (framerate > 0.0)
1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream->config.cfg.kf_max_dist = (unsigned int)(5.0 * framerate);
1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1086233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1088233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void show_stream_config(struct stream_state *stream,
1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               struct VpxEncoderConfig *global,
1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               struct VpxInputContext *input) {
1091233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define SHOW(field) \
1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "    %-28s = %d\n", #field, stream->config.cfg.field)
1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->index == 0) {
1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, "Codec: %s\n",
1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan            vpx_codec_iface_name(global->codec->interface()));
1098233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, "Source file: %s Format: %s\n", input->filename,
1099233d2500723e5594f3e7c70896ffeeef32b9c950ywan            input->use_i420 ? "I420" : "YV12");
1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->next || stream->index)
1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, "\nStream Index: %d\n", stream->index);
1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "Destination file: %s\n", stream->config.out_fn);
1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "Encoder parameters:\n");
1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_usage);
1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_threads);
1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_profile);
1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_w);
1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_h);
1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_timebase.num);
1112233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_timebase.den);
1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_error_resilient);
1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_pass);
1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(g_lag_in_frames);
1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_dropframe_thresh);
1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_resize_allowed);
1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_resize_up_thresh);
1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_resize_down_thresh);
1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_end_usage);
1121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_target_bitrate);
1122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_min_quantizer);
1123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_max_quantizer);
1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_undershoot_pct);
1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_overshoot_pct);
1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_buf_sz);
1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_buf_initial_sz);
1128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_buf_optimal_sz);
1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_2pass_vbr_bias_pct);
1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_2pass_vbr_minsection_pct);
1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(rc_2pass_vbr_maxsection_pct);
1132233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(kf_mode);
1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(kf_min_dist);
1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  SHOW(kf_max_dist);
1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1138233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void open_output_file(struct stream_state *stream,
1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             struct VpxEncoderConfig *global) {
1140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const char *fn = stream->config.out_fn;
1141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg;
1142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cfg->g_pass == VPX_RC_FIRST_PASS)
1144233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->file)
1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("Failed to open output file");
1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fatal("WebM output to pipes not supported.");
1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO
1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->config.write_webm) {
1156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->ebml.stream = stream->file;
1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    write_webm_file_header(&stream->ebml, cfg,
1158233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           &global->framerate,
1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           stream->config.stereo_fmt,
1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           global->codec->fourcc);
1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1162233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->config.write_webm) {
1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0);
1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1170233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void close_output_file(struct stream_state *stream,
1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              unsigned int fourcc) {
1172233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg;
1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cfg->g_pass == VPX_RC_FIRST_PASS)
1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1177233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO
1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->config.write_webm) {
1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    write_webm_file_footer(&stream->ebml, stream->hash);
1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan    free(stream->ebml.cue_list);
1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->ebml.cue_list = NULL;
1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1183233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1185233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->config.write_webm) {
1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!fseek(stream->file, 0, SEEK_SET))
1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ivf_write_file_header(stream->file, &stream->config.cfg,
1188233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            fourcc,
1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            stream->frames_out);
1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fclose(stream->file);
1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1195233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1196233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void setup_pass(struct stream_state *stream,
1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       struct VpxEncoderConfig *global,
1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       int pass) {
1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->config.stats_fn) {
1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!stats_open_file(&stream->stats, stream->config.stats_fn,
1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         pass))
1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fatal("Failed to open statistics store");
1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!stats_open_mem(&stream->stats, pass))
1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fatal("Failed to open statistics store");
1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->config.cfg.g_pass = global->passes == 2
1209233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS
1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            : VPX_RC_ONE_PASS;
1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (pass)
1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->cx_time = 0;
1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->nbytes = 0;
1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->frames_out = 0;
1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1219233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1220233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void initialize_encoder(struct stream_state *stream,
1221233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               struct VpxEncoderConfig *global) {
1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int flags = 0;
1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1225233d2500723e5594f3e7c70896ffeeef32b9c950ywan  flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
1226233d2500723e5594f3e7c70896ffeeef32b9c950ywan  flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Construct Encoder Context */
1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_enc_init(&stream->encoder, global->codec->interface(),
1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     &stream->config.cfg, flags);
1231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Note that we bypass the vpx_codec_control wrapper macro because
1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * we're being clever to store the control IDs in an array. Real
1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * applications will want to make use of the enumerations directly
1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < stream->config.arg_ctrl_cnt; i++) {
1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int ctrl = stream->config.arg_ctrls[i][0];
1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int value = stream->config.arg_ctrls[i][1];
1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (vpx_codec_control_(&stream->encoder, ctrl, value))
1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fprintf(stderr, "Error: Tried to set control %d = %d\n",
1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan              ctrl, value);
1243233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx_exit_on_error(&stream->encoder, "Failed to control codec");
1245233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_DECODERS
1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global->test_decode != TEST_DECODE_OFF) {
1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0);
1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1256233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void encode_frame(struct stream_state *stream,
1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         struct VpxEncoderConfig *global,
1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         struct vpx_image *img,
1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         unsigned int frames_in) {
1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_pts_t frame_start, next_frame_start;
1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct vpx_usec_timer timer;
1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan  frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1)
1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 * global->framerate.den)
1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan                / cfg->g_timebase.num / global->framerate.num;
1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan  next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      * global->framerate.den)
1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     / cfg->g_timebase.num / global->framerate.num;
1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Scale if necessary */
1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!stream->img)
1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420,
1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  cfg->g_w, cfg->g_h, 16);
1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan              img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan              img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan              img->d_w, img->d_h,
1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->planes[VPX_PLANE_Y],
1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->stride[VPX_PLANE_Y],
1282233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->planes[VPX_PLANE_U],
1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->stride[VPX_PLANE_U],
1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->planes[VPX_PLANE_V],
1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->stride[VPX_PLANE_V],
1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan              stream->img->d_w, stream->img->d_h,
1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan              kFilterBox);
1288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    img = stream->img;
1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_usec_timer_start(&timer);
1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_encode(&stream->encoder, img, frame_start,
1294233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   (unsigned long)(next_frame_start - frame_start),
1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   0, global->deadline);
1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_usec_timer_mark(&timer);
1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stream->cx_time += vpx_usec_timer_elapsed(&timer);
1298233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame",
1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    stream->index);
1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1302233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1303233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void update_quantizer_histogram(struct stream_state *stream) {
1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->config.cfg.g_pass != VPX_RC_FIRST_PASS) {
1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int q;
1306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx_exit_on_error(&stream->encoder, "Failed to read quantizer");
1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->counts[q]++;
1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1314233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void get_cx_data(struct stream_state *stream,
1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        struct VpxEncoderConfig *global,
1316233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        int *got_data) {
1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const vpx_codec_cx_pkt_t *pkt;
1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_iter_t iter = NULL;
1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *got_data = 0;
1322233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) {
1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan    static size_t fsize = 0;
1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan    static off_t ivf_header_pos = 0;
1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    switch (pkt->kind) {
1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case VPX_CODEC_CX_FRAME_PKT:
1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan          stream->frames_out++;
1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!global->quiet)
1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan          fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz);
1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        update_rate_histogram(stream->rate_hist, cfg, pkt);
1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_WEBM_IO
1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (stream->config.write_webm) {
1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan          /* Update the hash */
1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (!stream->ebml.debug)
1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan            stream->hash = murmur(pkt->data.frame.buf,
1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  (int)pkt->data.frame.sz,
1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  stream->hash);
1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan          write_webm_block(&stream->ebml, cfg, pkt);
1344233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!stream->config.write_webm) {
1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (pkt->data.frame.partition_id <= 0) {
1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ivf_header_pos = ftello(stream->file);
1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan            fsize = pkt->data.frame.sz;
1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize);
1352233d2500723e5594f3e7c70896ffeeef32b9c950ywan          } else {
1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan            fsize += pkt->data.frame.sz;
1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan              off_t currpos = ftello(stream->file);
1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan              fseeko(stream->file, ivf_header_pos, SEEK_SET);
1358233d2500723e5594f3e7c70896ffeeef32b9c950ywan              ivf_write_frame_size(stream->file, fsize);
1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan              fseeko(stream->file, currpos, SEEK_SET);
1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1361233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan          (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        stream->file);
1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stream->nbytes += pkt->data.raw.sz;
1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1368233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *got_data = 1;
1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_DECODERS
1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan          vpx_codec_decode(&stream->decoder, pkt->data.frame.buf,
1372233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           (unsigned int)pkt->data.frame.sz, NULL, 0);
1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (stream->decoder.err) {
1374233d2500723e5594f3e7c70896ffeeef32b9c950ywan            warn_or_exit_on_error(&stream->decoder,
1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  global->test_decode == TEST_DECODE_FATAL,
1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  "Failed to decode frame %d in stream %d",
1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  stream->frames_out + 1, stream->index);
1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan            stream->mismatch_seen = stream->frames_out + 1;
1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1382233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case VPX_CODEC_STATS_PKT:
1384233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stream->frames_out++;
1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stats_write(&stream->stats,
1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    pkt->data.twopass_stats.buf,
1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    pkt->data.twopass_stats.sz);
1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stream->nbytes += pkt->data.raw.sz;
1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan      case VPX_CODEC_PSNR_PKT:
1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (global->show_psnr) {
1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan          int i;
1394233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1395233d2500723e5594f3e7c70896ffeeef32b9c950ywan          stream->psnr_sse_total += pkt->data.psnr.sse[0];
1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan          stream->psnr_samples_total += pkt->data.psnr.samples[0];
1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan          for (i = 0; i < 4; i++) {
1398233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (!global->quiet)
1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan              fprintf(stderr, "%.3f ", pkt->data.psnr.psnr[i]);
1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan            stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan          stream->psnr_count++;
1403233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan      default:
1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1413233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void show_psnr(struct stream_state  *stream) {
1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int i;
1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan  double ovpsnr;
1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!stream->psnr_count)
1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ovpsnr = sse_to_psnr((double)stream->psnr_samples_total, 255.0,
1422233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       (double)stream->psnr_sse_total);
1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, " %.3f", ovpsnr);
1424233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1425233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < 4; i++) {
1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, " %.3f", stream->psnr_totals[i] / stream->psnr_count);
1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1428233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "\n");
1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1432233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic float usec_to_fps(uint64_t usec, unsigned int frames) {
1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1437233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void test_decode(struct stream_state  *stream,
1438233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        enum TestDecodeFatality fatal,
1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        const VpxInterface *codec) {
1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_image_t enc_img, dec_img;
1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stream->mismatch_seen)
1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Get the internal reference frame */
1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (strcmp(codec->name, "vp8") == 0) {
1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct vpx_ref_frame ref_enc, ref_dec;
1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int width, height;
1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan    width = (stream->config.cfg.g_w + 15) & ~15;
1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    height = (stream->config.cfg.g_h + 15) & ~15;
1452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1);
1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan    enc_img = ref_enc.img;
1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1);
1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dec_img = ref_dec.img;
1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ref_enc.frame_type = VP8_LAST_FRAME;
1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ref_dec.frame_type = VP8_LAST_FRAME;
1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &ref_enc);
1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &ref_dec);
1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct vp9_ref_frame ref;
1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ref.idx = 0;
1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref);
1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan    enc_img = ref.img;
1467233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref);
1468233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dec_img = ref.img;
1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame");
1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame");
1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1473233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!compare_img(&enc_img, &dec_img)) {
1474233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int y[4], u[4], v[4];
1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    find_mismatch(&enc_img, &dec_img, y, u, v);
1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->decoder.err = 1;
1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan    warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          "Stream %d: Encode/decode mismatch on frame %d at"
1479233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          " Y[%d, %d] {%d/%d},"
1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          " U[%d, %d] {%d/%d},"
1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          " V[%d, %d] {%d/%d}",
1482233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          stream->index, stream->frames_out,
1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          y[0], y[1], y[2], y[3],
1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          u[0], u[1], u[2], u[3],
1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          v[0], v[1], v[2], v[3]);
1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    stream->mismatch_seen = stream->frames_out;
1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_img_free(&enc_img);
1490233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_img_free(&dec_img);
1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1492233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1493233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1494233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void print_time(const char *label, int64_t etl) {
1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t hours;
1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t mins;
1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t secs;
1498233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (etl >= 0) {
1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan    hours = etl / 3600;
1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan    etl -= hours * 3600;
1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mins = etl / 60;
1503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    etl -= mins * 60;
1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    secs = etl;
1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, "[%3s %2"PRId64":%02"PRId64": % 02"PRId64"] ",
1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan            label, hours, mins, secs);
1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fprintf(stderr, "[%3s  unknown] ", label);
1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1514233d2500723e5594f3e7c70896ffeeef32b9c950ywanint main(int argc, const char **argv_) {
1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int pass;
1516233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_image_t raw;
1517233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int frame_avail, got_data;
1518233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct VpxInputContext input = {0};
1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct VpxEncoderConfig global;
1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct stream_state *streams = NULL;
1522233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char **argv, **argi;
1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t cx_time = 0;
1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int stream_cnt = 0;
1525233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int res = 0;
1526233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan  exec_name = argv_[0];
1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (argc < 3)
1530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    usage_exit();
1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1532233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Setup default input stream settings */
1533233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input.framerate.numerator = 30;
1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input.framerate.denominator = 1;
1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input.use_i420 = 1;
1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input.only_i420 = 1;
1537233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* First parse the global configuration values, because we want to apply
1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * other parameters on top of the default configuration provided by the
1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * codec.
1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan  argv = argv_dup(argc - 1, argv_ + 1);
1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan  parse_global_config(&global, argv);
1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan  {
1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Now parse each stream's parameters. Using a local scope here
1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * due to the use of 'stream' as loop variable in FOREACH_STREAM
1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * loops
1550233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct stream_state *stream = NULL;
1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do {
1554233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream = new_stream(&global, stream);
1555233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream_cnt++;
1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!streams)
1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan        streams = stream;
1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } while (parse_stream_params(&global, stream, argv));
1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Check for unrecognized options */
1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (argi = argv; *argi; argi++)
1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (argi[0][0] == '-' && argi[0][1])
1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan      die("Error: Unrecognized option %s\n", *argi);
1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt,
1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      &global, &stream->config.cfg););
1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Handle non-option arguments */
1570233d2500723e5594f3e7c70896ffeeef32b9c950ywan  input.filename = argv[0];
1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!input.filename)
1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    usage_exit();
1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Decide if other chroma subsamplings than 4:2:0 are supported */
1576233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global.codec->fourcc == VP9_FOURCC)
1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan    input.only_i420 = 0;
1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int frames_in = 0, seen_frames = 0;
1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64_t estimated_time_left = -1;
1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64_t average_rate = -1;
1583233d2500723e5594f3e7c70896ffeeef32b9c950ywan    off_t lagged_count = 0;
1584233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan    open_input_file(&input);
1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* If the input file doesn't specify its w/h (raw files), try to get
1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * the data from the first stream's configuration.
1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!input.width || !input.height)
1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM( {
1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan        input.width = stream->config.cfg.g_w;
1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan        input.height = stream->config.cfg.g_h;
1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1596233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    });
1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1599233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Update stream configurations from the input file's parameters */
1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!input.width || !input.height)
1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fatal("Specify stream dimensions with --width (-w) "
1602233d2500723e5594f3e7c70896ffeeef32b9c950ywan            " and --height (-h)");
1603233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
1604233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(validate_stream_config(stream, &global));
1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Ensure that --passes and --pass are consistent. If --pass is set and
1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * --passes=2, ensure --fpf was set.
1608233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global.pass && global.passes == 2)
1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM( {
1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!stream->config.stats_fn)
1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan        die("Stream %d: Must specify --fpf when --pass=%d"
1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan        " and --passes=2\n", stream->index, global.pass);
1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan    });
1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if !CONFIG_WEBM_IO
1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM({
1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stream->config.write_webm = 0;
1619233d2500723e5594f3e7c70896ffeeef32b9c950ywan      warn("vpxenc was compiled without WebM container support."
1620233d2500723e5594f3e7c70896ffeeef32b9c950ywan           "Producing IVF output");
1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan    });
1622233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Use the frame rate from the file only if none was specified
1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * on the command-line.
1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!global.have_framerate) {
1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global.framerate.num = input.framerate.numerator;
1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan      global.framerate.den = input.framerate.denominator;
1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(set_default_kf_interval(stream, &global));
1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Show configuration */
1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global.verbose && pass == 0)
1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM(show_stream_config(stream, &global, &input));
1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pass == (global.pass ? global.pass - 1 : 0)) {
1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (input.file_type == FILE_TYPE_Y4M)
1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan        /*The Y4M reader does its own allocation.
1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan          Just initialize this here to avoid problems if we never read any
1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan           frames.*/
1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan        memset(&raw, 0, sizeof(raw));
1644233d2500723e5594f3e7c70896ffeeef32b9c950ywan      else
1645233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vpx_img_alloc(&raw,
1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      input.use_i420 ? VPX_IMG_FMT_I420
1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      : VPX_IMG_FMT_YV12,
1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      input.width, input.height, 32);
1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM(stream->rate_hist =
1651233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         init_rate_histogram(&stream->config.cfg,
1652233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             &global.framerate));
1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(setup_pass(stream, &global, pass));
1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(open_output_file(stream, &global));
1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(initialize_encoder(stream, &global));
1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frame_avail = 1;
1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan    got_data = 0;
1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (frame_avail || got_data) {
1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan      struct vpx_usec_timer timer;
1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!global.limit || frames_in < global.limit) {
1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan        frame_avail = read_frame(&input, &raw);
1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (frame_avail)
1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan          frames_in++;
1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan        seen_frames = frames_in > global.skip_frames ?
1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          frames_in - global.skip_frames : 0;
1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!global.quiet) {
1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan          float fps = usec_to_fps(cx_time, seen_frames);
1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan          fprintf(stderr, "\rPass %d/%d ", pass + 1, global.passes);
1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (stream_cnt == 1)
1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan            fprintf(stderr,
1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    "frame %4d/%-4d %7"PRId64"B ",
1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    frames_in, streams->frames_out, (int64_t)streams->nbytes);
1681233d2500723e5594f3e7c70896ffeeef32b9c950ywan          else
1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan            fprintf(stderr, "frame %4d ", frames_in);
1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan          fprintf(stderr, "%7"PRId64" %s %.2f %s ",
1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  cx_time > 9999999 ? cx_time / 1000 : cx_time,
1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  cx_time > 9999999 ? "ms" : "us",
1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  fps >= 1.0 ? fps : fps * 60,
1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  fps >= 1.0 ? "fps" : "fpm");
1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan          print_time("ETA", estimated_time_left);
1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan          fprintf(stderr, "\033[K");
1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1692233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else
1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan        frame_avail = 0;
1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (frames_in > global.skip_frames) {
1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vpx_usec_timer_start(&timer);
1698233d2500723e5594f3e7c70896ffeeef32b9c950ywan        FOREACH_STREAM(encode_frame(stream, &global,
1699233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    frame_avail ? &raw : NULL,
1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    frames_in));
1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vpx_usec_timer_mark(&timer);
1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cx_time += vpx_usec_timer_elapsed(&timer);
1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan        FOREACH_STREAM(update_quantizer_histogram(stream));
1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan        got_data = 0;
1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan        FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!got_data && input.length && !streams->frames_out) {
1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan          lagged_count = global.limit ? seen_frames : ftello(input.file);
1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan        } else if (input.length) {
1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan          int64_t remaining;
1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan          int64_t rate;
1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1715233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (global.limit) {
1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan            off_t frame_in_lagged = (seen_frames - lagged_count) * 1000;
1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan            rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan            remaining = 1000 * (global.limit - global.skip_frames
1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                - seen_frames + lagged_count);
1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan          } else {
1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan            off_t input_pos = ftello(input.file);
1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan            off_t input_pos_lagged = input_pos - lagged_count;
1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan            int64_t limit = input.length;
1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan            rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0;
1727233d2500723e5594f3e7c70896ffeeef32b9c950ywan            remaining = limit - input_pos + lagged_count;
1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan          average_rate = (average_rate <= 0)
1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan              ? rate
1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan              : (average_rate * 7 + rate) / 8;
1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan          estimated_time_left = average_rate ? remaining / average_rate : -1;
1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (got_data && global.test_decode != TEST_DECODE_OFF)
1737233d2500723e5594f3e7c70896ffeeef32b9c950ywan          FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec));
1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fflush(stdout);
1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (stream_cnt > 1)
1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fprintf(stderr, "\n");
1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!global.quiet)
1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM(fprintf(
1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       stderr,
1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       "\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s"
1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1,
1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes,
1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       seen_frames ? (unsigned long)(stream->nbytes * 8 / seen_frames) : 0,
1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       seen_frames ? (int64_t)stream->nbytes * 8
1754233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       * (int64_t)global.framerate.num / global.framerate.den
1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       / seen_frames
1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       : 0,
1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       stream->cx_time > 9999999 ? "ms" : "us",
1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       usec_to_fps(stream->cx_time, seen_frames));
1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    );
1761233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global.show_psnr)
1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM(show_psnr(stream));
1764233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(vpx_codec_destroy(&stream->encoder));
1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global.test_decode != TEST_DECODE_OFF) {
1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM(vpx_codec_destroy(&stream->decoder));
1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan    close_input_file(&input);
1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global.test_decode == TEST_DECODE_FATAL) {
1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FOREACH_STREAM(res |= stream->mismatch_seen);
1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1776233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1));
1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (global.pass)
1781233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1782233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global.show_q_hist_buckets)
1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(show_q_histogram(stream->counts,
1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    global.show_q_hist_buckets));
1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (global.show_rate_hist_buckets)
1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM(show_rate_histogram(stream->rate_hist,
1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       &stream->config.cfg,
1791233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       global.show_rate_hist_buckets));
1792233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist));
1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_INTERNAL_STATS
1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* TODO(jkoleszar): This doesn't belong in this executable. Do it for now,
1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * to match some existing utilities.
1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan   */
1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!(global.pass == 1 && global.passes == 2))
1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan    FOREACH_STREAM({
1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan      FILE *f = fopen("opsnr.stt", "a");
1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (stream->mismatch_seen) {
1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan        fprintf(f, "First mismatch occurred in frame %d\n",
1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan                stream->mismatch_seen);
1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
1805233d2500723e5594f3e7c70896ffeeef32b9c950ywan        fprintf(f, "No mismatch detected in recon buffers\n");
1806233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1807233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fclose(f);
1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan    });
1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_img_free(&raw);
1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan  free(argv);
1813233d2500723e5594f3e7c70896ffeeef32b9c950ywan  free(streams);
1814233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return res ? EXIT_FAILURE : EXIT_SUCCESS;
1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1816