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