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