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