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 
469 static const arg_def_t disable_loopfilter =
470  ARG_DEF(NULL, "disable-loopfilter", 1,
471  "Control Loopfilter in VP9\n"
472  "0: Loopfilter on for all frames (default)\n"
473  "1: Loopfilter off for non reference frames\n"
474  "2: Loopfilter off for all frames");
475 #endif
476 
477 #if CONFIG_VP9_ENCODER
478 static const arg_def_t *vp9_args[] = { &cpu_used_vp9,
479  &auto_altref_vp9,
480  &sharpness,
481  &static_thresh,
482  &tile_cols,
483  &tile_rows,
484  &enable_tpl_model,
485  &arnr_maxframes,
486  &arnr_strength,
487  &arnr_type,
488  &tune_ssim,
489  &cq_level,
490  &max_intra_rate_pct,
491  &max_inter_rate_pct,
492  &gf_cbr_boost_pct,
493  &lossless,
494  &frame_parallel_decoding,
495  &aq_mode,
496  &alt_ref_aq,
497  &frame_periodic_boost,
498  &noise_sens,
499  &tune_content,
500  &input_color_space,
501  &min_gf_interval,
502  &max_gf_interval,
503  &target_level,
504  &row_mt,
505  &disable_loopfilter,
506 // NOTE: The entries above have a corresponding entry in vp9_arg_ctrl_map. The
507 // entries below do not have a corresponding entry in vp9_arg_ctrl_map. They
508 // must be listed at the end of vp9_args.
509 #if CONFIG_VP9_HIGHBITDEPTH
510  &bitdeptharg,
511  &inbitdeptharg,
512 #endif // CONFIG_VP9_HIGHBITDEPTH
513  NULL };
514 static const int vp9_arg_ctrl_map[] = { VP8E_SET_CPUUSED,
520  VP9E_SET_TPL,
542  0 };
543 #endif
544 
545 static const arg_def_t *no_args[] = { NULL };
546 
547 static void show_help(FILE *fout, int shorthelp) {
548  int i;
549  const int num_encoder = get_vpx_encoder_count();
550 
551  fprintf(fout, "Usage: %s <options> -o dst_filename src_filename \n",
552  exec_name);
553 
554  if (shorthelp) {
555  fprintf(fout, "Use --help to see the full list of options.\n");
556  return;
557  }
558 
559  fprintf(fout, "\nOptions:\n");
560  arg_show_usage(fout, main_args);
561  fprintf(fout, "\nEncoder Global Options:\n");
562  arg_show_usage(fout, global_args);
563  fprintf(fout, "\nRate Control Options:\n");
564  arg_show_usage(fout, rc_args);
565  fprintf(fout, "\nTwopass Rate Control Options:\n");
566  arg_show_usage(fout, rc_twopass_args);
567  fprintf(fout, "\nKeyframe Placement Options:\n");
568  arg_show_usage(fout, kf_args);
569 #if CONFIG_VP8_ENCODER
570  fprintf(fout, "\nVP8 Specific Options:\n");
571  arg_show_usage(fout, vp8_args);
572 #endif
573 #if CONFIG_VP9_ENCODER
574  fprintf(fout, "\nVP9 Specific Options:\n");
575  arg_show_usage(fout, vp9_args);
576 #endif
577  fprintf(fout,
578  "\nStream timebase (--timebase):\n"
579  " The desired precision of timestamps in the output, expressed\n"
580  " in fractional seconds. Default is 1/1000.\n");
581  fprintf(fout, "\nIncluded encoders:\n\n");
582 
583  for (i = 0; i < num_encoder; ++i) {
584  const VpxInterface *const encoder = get_vpx_encoder_by_index(i);
585  const char *defstr = (i == (num_encoder - 1)) ? "(default)" : "";
586  fprintf(fout, " %-6s - %s %s\n", encoder->name,
587  vpx_codec_iface_name(encoder->codec_interface()), defstr);
588  }
589  fprintf(fout, "\n ");
590  fprintf(fout, "Use --codec to switch to a non-default encoder.\n\n");
591 }
592 
593 void usage_exit(void) {
594  show_help(stderr, 1);
595  exit(EXIT_FAILURE);
596 }
597 
598 #define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
599 #if CONFIG_VP9_ENCODER
600 #define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map)
601 #else
602 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
603 #endif
604 
605 #if !CONFIG_WEBM_IO
606 typedef int stereo_format_t;
607 struct WebmOutputContext {
608  int debug;
609 };
610 #endif
611 
612 /* Per-stream configuration */
613 struct stream_config {
614  struct vpx_codec_enc_cfg cfg;
615  const char *out_fn;
616  const char *stats_fn;
617 #if CONFIG_FP_MB_STATS
618  const char *fpmb_stats_fn;
619 #endif
620  stereo_format_t stereo_fmt;
621  int arg_ctrls[ARG_CTRL_CNT_MAX][2];
622  int arg_ctrl_cnt;
623  int write_webm;
624 #if CONFIG_VP9_HIGHBITDEPTH
625  // whether to use 16bit internal buffers
626  int use_16bit_internal;
627 #endif
628 };
629 
630 struct stream_state {
631  int index;
632  struct stream_state *next;
633  struct stream_config config;
634  FILE *file;
635  struct rate_hist *rate_hist;
636  struct WebmOutputContext webm_ctx;
637  uint64_t psnr_sse_total;
638  uint64_t psnr_samples_total;
639  double psnr_totals[4];
640  int psnr_count;
641  int counts[64];
642  vpx_codec_ctx_t encoder;
643  unsigned int frames_out;
644  uint64_t cx_time;
645  size_t nbytes;
646  stats_io_t stats;
647 #if CONFIG_FP_MB_STATS
648  stats_io_t fpmb_stats;
649 #endif
650  struct vpx_image *img;
651  vpx_codec_ctx_t decoder;
652  int mismatch_seen;
653 };
654 
655 static void validate_positive_rational(const char *msg,
656  struct vpx_rational *rat) {
657  if (rat->den < 0) {
658  rat->num *= -1;
659  rat->den *= -1;
660  }
661 
662  if (rat->num < 0) die("Error: %s must be positive\n", msg);
663 
664  if (!rat->den) die("Error: %s has zero denominator\n", msg);
665 }
666 
667 static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
668  char **argi, **argj;
669  struct arg arg;
670  const int num_encoder = get_vpx_encoder_count();
671 
672  if (num_encoder < 1) die("Error: no valid encoder available\n");
673 
674  /* Initialize default parameters */
675  memset(global, 0, sizeof(*global));
676  global->codec = get_vpx_encoder_by_index(num_encoder - 1);
677  global->passes = 0;
678  global->color_type = I420;
679  /* Assign default deadline to good quality */
680  global->deadline = VPX_DL_GOOD_QUALITY;
681 
682  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
683  arg.argv_step = 1;
684 
685  if (arg_match(&arg, &help, argi)) {
686  show_help(stdout, 0);
687  exit(EXIT_SUCCESS);
688  } else if (arg_match(&arg, &codecarg, argi)) {
689  global->codec = get_vpx_encoder_by_name(arg.val);
690  if (!global->codec)
691  die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
692  } else if (arg_match(&arg, &passes, argi)) {
693  global->passes = arg_parse_uint(&arg);
694 
695  if (global->passes < 1 || global->passes > 2)
696  die("Error: Invalid number of passes (%d)\n", global->passes);
697  } else if (arg_match(&arg, &pass_arg, argi)) {
698  global->pass = arg_parse_uint(&arg);
699 
700  if (global->pass < 1 || global->pass > 2)
701  die("Error: Invalid pass selected (%d)\n", global->pass);
702  } else if (arg_match(&arg, &usage, argi))
703  global->usage = arg_parse_uint(&arg);
704  else if (arg_match(&arg, &deadline, argi))
705  global->deadline = arg_parse_uint(&arg);
706  else if (arg_match(&arg, &best_dl, argi))
707  global->deadline = VPX_DL_BEST_QUALITY;
708  else if (arg_match(&arg, &good_dl, argi))
709  global->deadline = VPX_DL_GOOD_QUALITY;
710  else if (arg_match(&arg, &rt_dl, argi))
711  global->deadline = VPX_DL_REALTIME;
712  else if (arg_match(&arg, &use_yv12, argi))
713  global->color_type = YV12;
714  else if (arg_match(&arg, &use_nv12, argi))
715  global->color_type = NV12;
716  else if (arg_match(&arg, &use_i420, argi))
717  global->color_type = I420;
718  else if (arg_match(&arg, &use_i422, argi))
719  global->color_type = I422;
720  else if (arg_match(&arg, &use_i444, argi))
721  global->color_type = I444;
722  else if (arg_match(&arg, &use_i440, argi))
723  global->color_type = I440;
724  else if (arg_match(&arg, &quietarg, argi))
725  global->quiet = 1;
726  else if (arg_match(&arg, &verbosearg, argi))
727  global->verbose = 1;
728  else if (arg_match(&arg, &limit, argi))
729  global->limit = arg_parse_uint(&arg);
730  else if (arg_match(&arg, &skip, argi))
731  global->skip_frames = arg_parse_uint(&arg);
732  else if (arg_match(&arg, &psnrarg, argi))
733  global->show_psnr = 1;
734  else if (arg_match(&arg, &recontest, argi))
735  global->test_decode = arg_parse_enum_or_int(&arg);
736  else if (arg_match(&arg, &framerate, argi)) {
737  global->framerate = arg_parse_rational(&arg);
738  validate_positive_rational(arg.name, &global->framerate);
739  global->have_framerate = 1;
740  } else if (arg_match(&arg, &out_part, argi))
741  global->out_part = 1;
742  else if (arg_match(&arg, &debugmode, argi))
743  global->debug = 1;
744  else if (arg_match(&arg, &q_hist_n, argi))
745  global->show_q_hist_buckets = arg_parse_uint(&arg);
746  else if (arg_match(&arg, &rate_hist_n, argi))
747  global->show_rate_hist_buckets = arg_parse_uint(&arg);
748  else if (arg_match(&arg, &disable_warnings, argi))
749  global->disable_warnings = 1;
750  else if (arg_match(&arg, &disable_warning_prompt, argi))
751  global->disable_warning_prompt = 1;
752  else
753  argj++;
754  }
755 
756  if (global->pass) {
757  /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
758  if (global->pass > global->passes) {
759  warn("Assuming --pass=%d implies --passes=%d\n", global->pass,
760  global->pass);
761  global->passes = global->pass;
762  }
763  }
764  /* Validate global config */
765  if (global->passes == 0) {
766 #if CONFIG_VP9_ENCODER
767  // Make default VP9 passes = 2 until there is a better quality 1-pass
768  // encoder
769  if (global->codec != NULL && global->codec->name != NULL)
770  global->passes = (strcmp(global->codec->name, "vp9") == 0 &&
771  global->deadline != VPX_DL_REALTIME)
772  ? 2
773  : 1;
774 #else
775  global->passes = 1;
776 #endif
777  }
778 
779  if (global->deadline == VPX_DL_REALTIME && global->passes > 1) {
780  warn("Enforcing one-pass encoding in realtime mode\n");
781  global->passes = 1;
782  }
783 }
784 
785 static struct stream_state *new_stream(struct VpxEncoderConfig *global,
786  struct stream_state *prev) {
787  struct stream_state *stream;
788 
789  stream = calloc(1, sizeof(*stream));
790  if (stream == NULL) {
791  fatal("Failed to allocate new stream.");
792  }
793 
794  if (prev) {
795  memcpy(stream, prev, sizeof(*stream));
796  stream->index++;
797  prev->next = stream;
798  } else {
799  vpx_codec_err_t res;
800 
801  /* Populate encoder configuration */
802  res = vpx_codec_enc_config_default(global->codec->codec_interface(),
803  &stream->config.cfg, global->usage);
804  if (res) fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res));
805 
806  /* Change the default timebase to a high enough value so that the
807  * encoder will always create strictly increasing timestamps.
808  */
809  stream->config.cfg.g_timebase.den = 1000;
810 
811  /* Never use the library's default resolution, require it be parsed
812  * from the file or set on the command line.
813  */
814  stream->config.cfg.g_w = 0;
815  stream->config.cfg.g_h = 0;
816 
817  /* Initialize remaining stream parameters */
818  stream->config.write_webm = 1;
819 #if CONFIG_WEBM_IO
820  stream->config.stereo_fmt = STEREO_FORMAT_MONO;
821  stream->webm_ctx.last_pts_ns = -1;
822  stream->webm_ctx.writer = NULL;
823  stream->webm_ctx.segment = NULL;
824 #endif
825 
826  /* Allows removal of the application version from the EBML tags */
827  stream->webm_ctx.debug = global->debug;
828 
829  /* Default lag_in_frames is 0 in realtime mode CBR mode*/
830  if (global->deadline == VPX_DL_REALTIME &&
831  stream->config.cfg.rc_end_usage == 1)
832  stream->config.cfg.g_lag_in_frames = 0;
833  }
834 
835  /* Output files must be specified for each stream */
836  stream->config.out_fn = NULL;
837 
838  stream->next = NULL;
839  return stream;
840 }
841 
842 static int parse_stream_params(struct VpxEncoderConfig *global,
843  struct stream_state *stream, char **argv) {
844  char **argi, **argj;
845  struct arg arg;
846  static const arg_def_t **ctrl_args = no_args;
847  static const int *ctrl_args_map = NULL;
848  struct stream_config *config = &stream->config;
849  int eos_mark_found = 0;
850 #if CONFIG_VP9_HIGHBITDEPTH
851  int test_16bit_internal = 0;
852 #endif
853 
854  // Handle codec specific options
855  if (0) {
856 #if CONFIG_VP8_ENCODER
857  } else if (strcmp(global->codec->name, "vp8") == 0) {
858  ctrl_args = vp8_args;
859  ctrl_args_map = vp8_arg_ctrl_map;
860 #endif
861 #if CONFIG_VP9_ENCODER
862  } else if (strcmp(global->codec->name, "vp9") == 0) {
863  ctrl_args = vp9_args;
864  ctrl_args_map = vp9_arg_ctrl_map;
865 #endif
866  }
867 
868  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
869  arg.argv_step = 1;
870 
871  /* Once we've found an end-of-stream marker (--) we want to continue
872  * shifting arguments but not consuming them.
873  */
874  if (eos_mark_found) {
875  argj++;
876  continue;
877  } else if (!strcmp(*argj, "--")) {
878  eos_mark_found = 1;
879  continue;
880  }
881 
882  if (arg_match(&arg, &outputfile, argi)) {
883  config->out_fn = arg.val;
884  } else if (arg_match(&arg, &fpf_name, argi)) {
885  config->stats_fn = arg.val;
886 #if CONFIG_FP_MB_STATS
887  } else if (arg_match(&arg, &fpmbf_name, argi)) {
888  config->fpmb_stats_fn = arg.val;
889 #endif
890  } else if (arg_match(&arg, &use_webm, argi)) {
891 #if CONFIG_WEBM_IO
892  config->write_webm = 1;
893 #else
894  die("Error: --webm specified but webm is disabled.");
895 #endif
896  } else if (arg_match(&arg, &use_ivf, argi)) {
897  config->write_webm = 0;
898  } else if (arg_match(&arg, &threads, argi)) {
899  config->cfg.g_threads = arg_parse_uint(&arg);
900  } else if (arg_match(&arg, &profile, argi)) {
901  config->cfg.g_profile = arg_parse_uint(&arg);
902  } else if (arg_match(&arg, &width, argi)) {
903  config->cfg.g_w = arg_parse_uint(&arg);
904  } else if (arg_match(&arg, &height, argi)) {
905  config->cfg.g_h = arg_parse_uint(&arg);
906 #if CONFIG_VP9_HIGHBITDEPTH
907  } else if (arg_match(&arg, &bitdeptharg, argi)) {
908  config->cfg.g_bit_depth = arg_parse_enum_or_int(&arg);
909  } else if (arg_match(&arg, &inbitdeptharg, argi)) {
910  config->cfg.g_input_bit_depth = arg_parse_uint(&arg);
911 #endif
912 #if CONFIG_WEBM_IO
913  } else if (arg_match(&arg, &stereo_mode, argi)) {
914  config->stereo_fmt = arg_parse_enum_or_int(&arg);
915 #endif
916  } else if (arg_match(&arg, &timebase, argi)) {
917  config->cfg.g_timebase = arg_parse_rational(&arg);
918  validate_positive_rational(arg.name, &config->cfg.g_timebase);
919  } else if (arg_match(&arg, &error_resilient, argi)) {
920  config->cfg.g_error_resilient = arg_parse_uint(&arg);
921  } else if (arg_match(&arg, &end_usage, argi)) {
922  config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
923  } else if (arg_match(&arg, &lag_in_frames, argi)) {
924  config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
925  if (global->deadline == VPX_DL_REALTIME &&
926  config->cfg.rc_end_usage == VPX_CBR &&
927  config->cfg.g_lag_in_frames != 0) {
928  warn("non-zero %s option ignored in realtime CBR mode.\n", arg.name);
929  config->cfg.g_lag_in_frames = 0;
930  }
931  } else if (arg_match(&arg, &dropframe_thresh, argi)) {
932  config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
933  } else if (arg_match(&arg, &resize_allowed, argi)) {
934  config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
935  } else if (arg_match(&arg, &resize_width, argi)) {
936  config->cfg.rc_scaled_width = arg_parse_uint(&arg);
937  } else if (arg_match(&arg, &resize_height, argi)) {
938  config->cfg.rc_scaled_height = arg_parse_uint(&arg);
939  } else if (arg_match(&arg, &resize_up_thresh, argi)) {
940  config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
941  } else if (arg_match(&arg, &resize_down_thresh, argi)) {
942  config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
943  } else if (arg_match(&arg, &end_usage, argi)) {
944  config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
945  } else if (arg_match(&arg, &target_bitrate, argi)) {
946  config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
947  } else if (arg_match(&arg, &min_quantizer, argi)) {
948  config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
949  } else if (arg_match(&arg, &max_quantizer, argi)) {
950  config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
951  } else if (arg_match(&arg, &undershoot_pct, argi)) {
952  config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
953  } else if (arg_match(&arg, &overshoot_pct, argi)) {
954  config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
955  } else if (arg_match(&arg, &buf_sz, argi)) {
956  config->cfg.rc_buf_sz = arg_parse_uint(&arg);
957  } else if (arg_match(&arg, &buf_initial_sz, argi)) {
958  config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
959  } else if (arg_match(&arg, &buf_optimal_sz, argi)) {
960  config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
961  } else if (arg_match(&arg, &bias_pct, argi)) {
962  config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
963  if (global->passes < 2)
964  warn("option %s ignored in one-pass mode.\n", arg.name);
965  } else if (arg_match(&arg, &minsection_pct, argi)) {
966  config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
967 
968  if (global->passes < 2)
969  warn("option %s ignored in one-pass mode.\n", arg.name);
970  } else if (arg_match(&arg, &maxsection_pct, argi)) {
971  config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
972 
973  if (global->passes < 2)
974  warn("option %s ignored in one-pass mode.\n", arg.name);
975  } else if (arg_match(&arg, &corpus_complexity, argi)) {
976  config->cfg.rc_2pass_vbr_corpus_complexity = arg_parse_uint(&arg);
977 
978  if (global->passes < 2)
979  warn("option %s ignored in one-pass mode.\n", arg.name);
980  } else if (arg_match(&arg, &kf_min_dist, argi)) {
981  config->cfg.kf_min_dist = arg_parse_uint(&arg);
982  } else if (arg_match(&arg, &kf_max_dist, argi)) {
983  config->cfg.kf_max_dist = arg_parse_uint(&arg);
984  } else if (arg_match(&arg, &kf_disabled, argi)) {
985  config->cfg.kf_mode = VPX_KF_DISABLED;
986 #if CONFIG_VP9_HIGHBITDEPTH
987  } else if (arg_match(&arg, &test16bitinternalarg, argi)) {
988  if (strcmp(global->codec->name, "vp9") == 0) {
989  test_16bit_internal = 1;
990  }
991 #endif
992  } else {
993  int i, match = 0;
994  for (i = 0; ctrl_args[i]; i++) {
995  if (arg_match(&arg, ctrl_args[i], argi)) {
996  int j;
997  match = 1;
998 
999  /* Point either to the next free element or the first
1000  * instance of this control.
1001  */
1002  for (j = 0; j < config->arg_ctrl_cnt; j++)
1003  if (ctrl_args_map != NULL &&
1004  config->arg_ctrls[j][0] == ctrl_args_map[i])
1005  break;
1006 
1007  /* Update/insert */
1008  assert(j < (int)ARG_CTRL_CNT_MAX);
1009  if (ctrl_args_map != NULL && j < (int)ARG_CTRL_CNT_MAX) {
1010  config->arg_ctrls[j][0] = ctrl_args_map[i];
1011  config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
1012  if (j == config->arg_ctrl_cnt) config->arg_ctrl_cnt++;
1013  }
1014  }
1015  }
1016  if (!match) argj++;
1017  }
1018  }
1019 #if CONFIG_VP9_HIGHBITDEPTH
1020  if (strcmp(global->codec->name, "vp9") == 0) {
1021  config->use_16bit_internal =
1022  test_16bit_internal | (config->cfg.g_profile > 1);
1023  }
1024 #endif
1025  return eos_mark_found;
1026 }
1027 
1028 #define FOREACH_STREAM(func) \
1029  do { \
1030  struct stream_state *stream; \
1031  for (stream = streams; stream; stream = stream->next) { \
1032  func; \
1033  } \
1034  } while (0)
1035 
1036 static void validate_stream_config(const struct stream_state *stream,
1037  const struct VpxEncoderConfig *global) {
1038  const struct stream_state *streami;
1039  (void)global;
1040 
1041  if (!stream->config.cfg.g_w || !stream->config.cfg.g_h)
1042  fatal(
1043  "Stream %d: Specify stream dimensions with --width (-w) "
1044  " and --height (-h)",
1045  stream->index);
1046 
1047  // Check that the codec bit depth is greater than the input bit depth.
1048  if (stream->config.cfg.g_input_bit_depth >
1049  (unsigned int)stream->config.cfg.g_bit_depth) {
1050  fatal("Stream %d: codec bit depth (%d) less than input bit depth (%d)",
1051  stream->index, (int)stream->config.cfg.g_bit_depth,
1052  stream->config.cfg.g_input_bit_depth);
1053  }
1054 
1055  for (streami = stream; streami; streami = streami->next) {
1056  /* All streams require output files */
1057  if (!streami->config.out_fn)
1058  fatal("Stream %d: Output file is required (specify with -o)",
1059  streami->index);
1060 
1061  /* Check for two streams outputting to the same file */
1062  if (streami != stream) {
1063  const char *a = stream->config.out_fn;
1064  const char *b = streami->config.out_fn;
1065  if (!strcmp(a, b) && strcmp(a, "/dev/null") && strcmp(a, ":nul"))
1066  fatal("Stream %d: duplicate output file (from stream %d)",
1067  streami->index, stream->index);
1068  }
1069 
1070  /* Check for two streams sharing a stats file. */
1071  if (streami != stream) {
1072  const char *a = stream->config.stats_fn;
1073  const char *b = streami->config.stats_fn;
1074  if (a && b && !strcmp(a, b))
1075  fatal("Stream %d: duplicate stats file (from stream %d)",
1076  streami->index, stream->index);
1077  }
1078 
1079 #if CONFIG_FP_MB_STATS
1080  /* Check for two streams sharing a mb stats file. */
1081  if (streami != stream) {
1082  const char *a = stream->config.fpmb_stats_fn;
1083  const char *b = streami->config.fpmb_stats_fn;
1084  if (a && b && !strcmp(a, b))
1085  fatal("Stream %d: duplicate mb stats file (from stream %d)",
1086  streami->index, stream->index);
1087  }
1088 #endif
1089  }
1090 }
1091 
1092 static void set_stream_dimensions(struct stream_state *stream, unsigned int w,
1093  unsigned int h) {
1094  if (!stream->config.cfg.g_w) {
1095  if (!stream->config.cfg.g_h)
1096  stream->config.cfg.g_w = w;
1097  else
1098  stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
1099  }
1100  if (!stream->config.cfg.g_h) {
1101  stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
1102  }
1103 }
1104 
1105 static const char *file_type_to_string(enum VideoFileType t) {
1106  switch (t) {
1107  case FILE_TYPE_RAW: return "RAW";
1108  case FILE_TYPE_Y4M: return "Y4M";
1109  default: return "Other";
1110  }
1111 }
1112 
1113 static const char *image_format_to_string(vpx_img_fmt_t f) {
1114  switch (f) {
1115  case VPX_IMG_FMT_I420: return "I420";
1116  case VPX_IMG_FMT_I422: return "I422";
1117  case VPX_IMG_FMT_I444: return "I444";
1118  case VPX_IMG_FMT_I440: return "I440";
1119  case VPX_IMG_FMT_YV12: return "YV12";
1120  case VPX_IMG_FMT_I42016: return "I42016";
1121  case VPX_IMG_FMT_I42216: return "I42216";
1122  case VPX_IMG_FMT_I44416: return "I44416";
1123  case VPX_IMG_FMT_I44016: return "I44016";
1124  default: return "Other";
1125  }
1126 }
1127 
1128 static void show_stream_config(struct stream_state *stream,
1129  struct VpxEncoderConfig *global,
1130  struct VpxInputContext *input) {
1131 #define SHOW(field) \
1132  fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field)
1133 
1134  if (stream->index == 0) {
1135  fprintf(stderr, "Codec: %s\n",
1136  vpx_codec_iface_name(global->codec->codec_interface()));
1137  fprintf(stderr, "Source file: %s File Type: %s Format: %s\n",
1138  input->filename, file_type_to_string(input->file_type),
1139  image_format_to_string(input->fmt));
1140  }
1141  if (stream->next || stream->index)
1142  fprintf(stderr, "\nStream Index: %d\n", stream->index);
1143  fprintf(stderr, "Destination file: %s\n", stream->config.out_fn);
1144  fprintf(stderr, "Encoder parameters:\n");
1145 
1146  SHOW(g_usage);
1147  SHOW(g_threads);
1148  SHOW(g_profile);
1149  SHOW(g_w);
1150  SHOW(g_h);
1151  SHOW(g_bit_depth);
1152  SHOW(g_input_bit_depth);
1153  SHOW(g_timebase.num);
1154  SHOW(g_timebase.den);
1155  SHOW(g_error_resilient);
1156  SHOW(g_pass);
1157  SHOW(g_lag_in_frames);
1158  SHOW(rc_dropframe_thresh);
1159  SHOW(rc_resize_allowed);
1160  SHOW(rc_scaled_width);
1161  SHOW(rc_scaled_height);
1162  SHOW(rc_resize_up_thresh);
1163  SHOW(rc_resize_down_thresh);
1164  SHOW(rc_end_usage);
1165  SHOW(rc_target_bitrate);
1166  SHOW(rc_min_quantizer);
1167  SHOW(rc_max_quantizer);
1168  SHOW(rc_undershoot_pct);
1169  SHOW(rc_overshoot_pct);
1170  SHOW(rc_buf_sz);
1171  SHOW(rc_buf_initial_sz);
1172  SHOW(rc_buf_optimal_sz);
1173  SHOW(rc_2pass_vbr_bias_pct);
1174  SHOW(rc_2pass_vbr_minsection_pct);
1175  SHOW(rc_2pass_vbr_maxsection_pct);
1176  SHOW(rc_2pass_vbr_corpus_complexity);
1177  SHOW(kf_mode);
1178  SHOW(kf_min_dist);
1179  SHOW(kf_max_dist);
1180 }
1181 
1182 static void open_output_file(struct stream_state *stream,
1183  struct VpxEncoderConfig *global,
1184  const struct VpxRational *pixel_aspect_ratio) {
1185  const char *fn = stream->config.out_fn;
1186  const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg;
1187 
1188  if (cfg->g_pass == VPX_RC_FIRST_PASS) return;
1189 
1190  stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
1191 
1192  if (!stream->file) fatal("Failed to open output file");
1193 
1194  if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
1195  fatal("WebM output to pipes not supported.");
1196 
1197 #if CONFIG_WEBM_IO
1198  if (stream->config.write_webm) {
1199  stream->webm_ctx.stream = stream->file;
1200  write_webm_file_header(&stream->webm_ctx, cfg, stream->config.stereo_fmt,
1201  global->codec->fourcc, pixel_aspect_ratio);
1202  }
1203 #else
1204  (void)pixel_aspect_ratio;
1205 #endif
1206 
1207  if (!stream->config.write_webm) {
1208  ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0);
1209  }
1210 }
1211 
1212 static void close_output_file(struct stream_state *stream,
1213  unsigned int fourcc) {
1214  const struct vpx_codec_enc_cfg *const cfg = &stream->config.cfg;
1215 
1216  if (cfg->g_pass == VPX_RC_FIRST_PASS) return;
1217 
1218 #if CONFIG_WEBM_IO
1219  if (stream->config.write_webm) {
1220  write_webm_file_footer(&stream->webm_ctx);
1221  }
1222 #endif
1223 
1224  if (!stream->config.write_webm) {
1225  if (!fseek(stream->file, 0, SEEK_SET))
1226  ivf_write_file_header(stream->file, &stream->config.cfg, fourcc,
1227  stream->frames_out);
1228  }
1229 
1230  fclose(stream->file);
1231 }
1232 
1233 static void setup_pass(struct stream_state *stream,
1234  struct VpxEncoderConfig *global, int pass) {
1235  if (stream->config.stats_fn) {
1236  if (!stats_open_file(&stream->stats, stream->config.stats_fn, pass))
1237  fatal("Failed to open statistics store");
1238  } else {
1239  if (!stats_open_mem(&stream->stats, pass))
1240  fatal("Failed to open statistics store");
1241  }
1242 
1243 #if CONFIG_FP_MB_STATS
1244  if (stream->config.fpmb_stats_fn) {
1245  if (!stats_open_file(&stream->fpmb_stats, stream->config.fpmb_stats_fn,
1246  pass))
1247  fatal("Failed to open mb statistics store");
1248  } else {
1249  if (!stats_open_mem(&stream->fpmb_stats, pass))
1250  fatal("Failed to open mb statistics store");
1251  }
1252 #endif
1253 
1254  stream->config.cfg.g_pass = global->passes == 2
1256  : VPX_RC_ONE_PASS;
1257  if (pass) {
1258  stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
1259 #if CONFIG_FP_MB_STATS
1260  stream->config.cfg.rc_firstpass_mb_stats_in =
1261  stats_get(&stream->fpmb_stats);
1262 #endif
1263  }
1264 
1265  stream->cx_time = 0;
1266  stream->nbytes = 0;
1267  stream->frames_out = 0;
1268 }
1269 
1270 static void initialize_encoder(struct stream_state *stream,
1271  struct VpxEncoderConfig *global) {
1272  int i;
1273  int flags = 0;
1274 
1275  flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
1276  flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
1277 #if CONFIG_VP9_HIGHBITDEPTH
1278  flags |= stream->config.use_16bit_internal ? VPX_CODEC_USE_HIGHBITDEPTH : 0;
1279 #endif
1280 
1281  /* Construct Encoder Context */
1282  vpx_codec_enc_init(&stream->encoder, global->codec->codec_interface(),
1283  &stream->config.cfg, flags);
1284  ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
1285 
1286  /* Note that we bypass the vpx_codec_control wrapper macro because
1287  * we're being clever to store the control IDs in an array. Real
1288  * applications will want to make use of the enumerations directly
1289  */
1290  for (i = 0; i < stream->config.arg_ctrl_cnt; i++) {
1291  int ctrl = stream->config.arg_ctrls[i][0];
1292  int value = stream->config.arg_ctrls[i][1];
1293  if (vpx_codec_control_(&stream->encoder, ctrl, value))
1294  fprintf(stderr, "Error: Tried to set control %d = %d\n", ctrl, value);
1295 
1296  ctx_exit_on_error(&stream->encoder, "Failed to control codec");
1297  }
1298 
1299 #if CONFIG_DECODERS
1300  if (global->test_decode != TEST_DECODE_OFF) {
1301  const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
1302  vpx_codec_dec_init(&stream->decoder, decoder->codec_interface(), NULL, 0);
1303  }
1304 #endif
1305 }
1306 
1307 static void encode_frame(struct stream_state *stream,
1308  struct VpxEncoderConfig *global, struct vpx_image *img,
1309  unsigned int frames_in) {
1310  vpx_codec_pts_t frame_start, next_frame_start;
1311  struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
1312  struct vpx_usec_timer timer;
1313 
1314  frame_start =
1315  (cfg->g_timebase.den * (int64_t)(frames_in - 1) * global->framerate.den) /
1316  cfg->g_timebase.num / global->framerate.num;
1317  next_frame_start =
1318  (cfg->g_timebase.den * (int64_t)(frames_in)*global->framerate.den) /
1319  cfg->g_timebase.num / global->framerate.num;
1320 
1321 /* Scale if necessary */
1322 #if CONFIG_VP9_HIGHBITDEPTH
1323  if (img) {
1324  if ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) &&
1325  (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
1326  if (img->fmt != VPX_IMG_FMT_I42016) {
1327  fprintf(stderr, "%s can only scale 4:2:0 inputs\n", exec_name);
1328  exit(EXIT_FAILURE);
1329  }
1330 #if CONFIG_LIBYUV
1331  if (!stream->img) {
1332  stream->img =
1333  vpx_img_alloc(NULL, VPX_IMG_FMT_I42016, cfg->g_w, cfg->g_h, 16);
1334  }
1335  I420Scale_16(
1336  (uint16_t *)img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y] / 2,
1337  (uint16_t *)img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U] / 2,
1338  (uint16_t *)img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V] / 2,
1339  img->d_w, img->d_h, (uint16_t *)stream->img->planes[VPX_PLANE_Y],
1340  stream->img->stride[VPX_PLANE_Y] / 2,
1341  (uint16_t *)stream->img->planes[VPX_PLANE_U],
1342  stream->img->stride[VPX_PLANE_U] / 2,
1343  (uint16_t *)stream->img->planes[VPX_PLANE_V],
1344  stream->img->stride[VPX_PLANE_V] / 2, stream->img->d_w,
1345  stream->img->d_h, kFilterBox);
1346  img = stream->img;
1347 #else
1348  stream->encoder.err = 1;
1349  ctx_exit_on_error(&stream->encoder,
1350  "Stream %d: Failed to encode frame.\n"
1351  "Scaling disabled in this configuration. \n"
1352  "To enable, configure with --enable-libyuv\n",
1353  stream->index);
1354 #endif
1355  }
1356  }
1357 #endif
1358  if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
1359  if (img->fmt != VPX_IMG_FMT_I420 && img->fmt != VPX_IMG_FMT_YV12) {
1360  fprintf(stderr, "%s can only scale 4:2:0 8bpp inputs\n", exec_name);
1361  exit(EXIT_FAILURE);
1362  }
1363 #if CONFIG_LIBYUV
1364  if (!stream->img)
1365  stream->img =
1366  vpx_img_alloc(NULL, VPX_IMG_FMT_I420, cfg->g_w, cfg->g_h, 16);
1367  I420Scale(
1368  img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
1369  img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
1370  img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V], img->d_w, img->d_h,
1371  stream->img->planes[VPX_PLANE_Y], stream->img->stride[VPX_PLANE_Y],
1372  stream->img->planes[VPX_PLANE_U], stream->img->stride[VPX_PLANE_U],
1373  stream->img->planes[VPX_PLANE_V], stream->img->stride[VPX_PLANE_V],
1374  stream->img->d_w, stream->img->d_h, kFilterBox);
1375  img = stream->img;
1376 #else
1377  stream->encoder.err = 1;
1378  ctx_exit_on_error(&stream->encoder,
1379  "Stream %d: Failed to encode frame.\n"
1380  "Scaling disabled in this configuration. \n"
1381  "To enable, configure with --enable-libyuv\n",
1382  stream->index);
1383 #endif
1384  }
1385 
1386  vpx_usec_timer_start(&timer);
1387  vpx_codec_encode(&stream->encoder, img, frame_start,
1388  (unsigned long)(next_frame_start - frame_start), 0,
1389  global->deadline);
1390  vpx_usec_timer_mark(&timer);
1391  stream->cx_time += vpx_usec_timer_elapsed(&timer);
1392  ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame",
1393  stream->index);
1394 }
1395 
1396 static void update_quantizer_histogram(struct stream_state *stream) {
1397  if (stream->config.cfg.g_pass != VPX_RC_FIRST_PASS) {
1398  int q;
1399 
1400  vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
1401  ctx_exit_on_error(&stream->encoder, "Failed to read quantizer");
1402  stream->counts[q]++;
1403  }
1404 }
1405 
1406 static void get_cx_data(struct stream_state *stream,
1407  struct VpxEncoderConfig *global, int *got_data) {
1408  const vpx_codec_cx_pkt_t *pkt;
1409  const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
1410  vpx_codec_iter_t iter = NULL;
1411 
1412  *got_data = 0;
1413  while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) {
1414  static size_t fsize = 0;
1415  static FileOffset ivf_header_pos = 0;
1416 
1417  switch (pkt->kind) {
1419  if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
1420  stream->frames_out++;
1421  }
1422  if (!global->quiet)
1423  fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz);
1424 
1425  update_rate_histogram(stream->rate_hist, cfg, pkt);
1426 #if CONFIG_WEBM_IO
1427  if (stream->config.write_webm) {
1428  write_webm_block(&stream->webm_ctx, cfg, pkt);
1429  }
1430 #endif
1431  if (!stream->config.write_webm) {
1432  if (pkt->data.frame.partition_id <= 0) {
1433  ivf_header_pos = ftello(stream->file);
1434  fsize = pkt->data.frame.sz;
1435 
1436  ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize);
1437  } else {
1438  fsize += pkt->data.frame.sz;
1439 
1440  if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
1441  const FileOffset currpos = ftello(stream->file);
1442  fseeko(stream->file, ivf_header_pos, SEEK_SET);
1443  ivf_write_frame_size(stream->file, fsize);
1444  fseeko(stream->file, currpos, SEEK_SET);
1445  }
1446  }
1447 
1448  (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
1449  stream->file);
1450  }
1451  stream->nbytes += pkt->data.raw.sz;
1452 
1453  *got_data = 1;
1454 #if CONFIG_DECODERS
1455  if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
1456  vpx_codec_decode(&stream->decoder, pkt->data.frame.buf,
1457  (unsigned int)pkt->data.frame.sz, NULL, 0);
1458  if (stream->decoder.err) {
1459  warn_or_exit_on_error(&stream->decoder,
1460  global->test_decode == TEST_DECODE_FATAL,
1461  "Failed to decode frame %d in stream %d",
1462  stream->frames_out + 1, stream->index);
1463  stream->mismatch_seen = stream->frames_out + 1;
1464  }
1465  }
1466 #endif
1467  break;
1468  case VPX_CODEC_STATS_PKT:
1469  stream->frames_out++;
1470  stats_write(&stream->stats, pkt->data.twopass_stats.buf,
1471  pkt->data.twopass_stats.sz);
1472  stream->nbytes += pkt->data.raw.sz;
1473  break;
1474 #if CONFIG_FP_MB_STATS
1476  stats_write(&stream->fpmb_stats, pkt->data.firstpass_mb_stats.buf,
1477  pkt->data.firstpass_mb_stats.sz);
1478  stream->nbytes += pkt->data.raw.sz;
1479  break;
1480 #endif
1481  case VPX_CODEC_PSNR_PKT:
1482 
1483  if (global->show_psnr) {
1484  int i;
1485 
1486  stream->psnr_sse_total += pkt->data.psnr.sse[0];
1487  stream->psnr_samples_total += pkt->data.psnr.samples[0];
1488  for (i = 0; i < 4; i++) {
1489  if (!global->quiet)
1490  fprintf(stderr, "%.3f ", pkt->data.psnr.psnr[i]);
1491  stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
1492  }
1493  stream->psnr_count++;
1494  }
1495 
1496  break;
1497  default: break;
1498  }
1499  }
1500 }
1501 
1502 static void show_psnr(struct stream_state *stream, double peak) {
1503  int i;
1504  double ovpsnr;
1505 
1506  if (!stream->psnr_count) return;
1507 
1508  fprintf(stderr, "Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
1509  ovpsnr = sse_to_psnr((double)stream->psnr_samples_total, peak,
1510  (double)stream->psnr_sse_total);
1511  fprintf(stderr, " %.3f", ovpsnr);
1512 
1513  for (i = 0; i < 4; i++) {
1514  fprintf(stderr, " %.3f", stream->psnr_totals[i] / stream->psnr_count);
1515  }
1516  fprintf(stderr, "\n");
1517 }
1518 
1519 static float usec_to_fps(uint64_t usec, unsigned int frames) {
1520  return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
1521 }
1522 
1523 static void test_decode(struct stream_state *stream,
1524  enum TestDecodeFatality fatal,
1525  const VpxInterface *codec) {
1526  vpx_image_t enc_img, dec_img;
1527 
1528  if (stream->mismatch_seen) return;
1529 
1530  /* Get the internal reference frame */
1531  if (strcmp(codec->name, "vp8") == 0) {
1532  struct vpx_ref_frame ref_enc, ref_dec;
1533  int width, height;
1534 
1535  width = (stream->config.cfg.g_w + 15) & ~15;
1536  height = (stream->config.cfg.g_h + 15) & ~15;
1537  vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1);
1538  enc_img = ref_enc.img;
1539  vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1);
1540  dec_img = ref_dec.img;
1541 
1542  ref_enc.frame_type = VP8_LAST_FRAME;
1543  ref_dec.frame_type = VP8_LAST_FRAME;
1544  vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &ref_enc);
1545  vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &ref_dec);
1546  } else {
1547  struct vp9_ref_frame ref_enc, ref_dec;
1548 
1549  ref_enc.idx = 0;
1550  ref_dec.idx = 0;
1551  vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref_enc);
1552  enc_img = ref_enc.img;
1553  vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref_dec);
1554  dec_img = ref_dec.img;
1555 #if CONFIG_VP9_HIGHBITDEPTH
1556  if ((enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) !=
1557  (dec_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH)) {
1558  if (enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
1559  vpx_img_alloc(&enc_img, enc_img.fmt - VPX_IMG_FMT_HIGHBITDEPTH,
1560  enc_img.d_w, enc_img.d_h, 16);
1561  vpx_img_truncate_16_to_8(&enc_img, &ref_enc.img);
1562  }
1563  if (dec_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
1564  vpx_img_alloc(&dec_img, dec_img.fmt - VPX_IMG_FMT_HIGHBITDEPTH,
1565  dec_img.d_w, dec_img.d_h, 16);
1566  vpx_img_truncate_16_to_8(&dec_img, &ref_dec.img);
1567  }
1568  }
1569 #endif
1570  }
1571  ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame");
1572  ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame");
1573 
1574  if (!compare_img(&enc_img, &dec_img)) {
1575  int y[4], u[4], v[4];
1576 #if CONFIG_VP9_HIGHBITDEPTH
1577  if (enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
1578  find_mismatch_high(&enc_img, &dec_img, y, u, v);
1579  } else {
1580  find_mismatch(&enc_img, &dec_img, y, u, v);
1581  }
1582 #else
1583  find_mismatch(&enc_img, &dec_img, y, u, v);
1584 #endif
1585  stream->decoder.err = 1;
1586  warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
1587  "Stream %d: Encode/decode mismatch on frame %d at"
1588  " Y[%d, %d] {%d/%d},"
1589  " U[%d, %d] {%d/%d},"
1590  " V[%d, %d] {%d/%d}",
1591  stream->index, stream->frames_out, y[0], y[1], y[2],
1592  y[3], u[0], u[1], u[2], u[3], v[0], v[1], v[2], v[3]);
1593  stream->mismatch_seen = stream->frames_out;
1594  }
1595 
1596  vpx_img_free(&enc_img);
1597  vpx_img_free(&dec_img);
1598 }
1599 
1600 static void print_time(const char *label, int64_t etl) {
1601  int64_t hours;
1602  int64_t mins;
1603  int64_t secs;
1604 
1605  if (etl >= 0) {
1606  hours = etl / 3600;
1607  etl -= hours * 3600;
1608  mins = etl / 60;
1609  etl -= mins * 60;
1610  secs = etl;
1611 
1612  fprintf(stderr, "[%3s %2" PRId64 ":%02" PRId64 ":%02" PRId64 "] ", label,
1613  hours, mins, secs);
1614  } else {
1615  fprintf(stderr, "[%3s unknown] ", label);
1616  }
1617 }
1618 
1619 int main(int argc, const char **argv_) {
1620  int pass;
1621  vpx_image_t raw;
1622 #if CONFIG_VP9_HIGHBITDEPTH
1623  vpx_image_t raw_shift;
1624  int allocated_raw_shift = 0;
1625  int use_16bit_internal = 0;
1626  int input_shift = 0;
1627 #endif
1628  int frame_avail, got_data;
1629 
1630  struct VpxInputContext input;
1631  struct VpxEncoderConfig global;
1632  struct stream_state *streams = NULL;
1633  char **argv, **argi;
1634  uint64_t cx_time = 0;
1635  int stream_cnt = 0;
1636  int res = 0;
1637 
1638  memset(&input, 0, sizeof(input));
1639  memset(&raw, 0, sizeof(raw));
1640  exec_name = argv_[0];
1641 
1642  /* Setup default input stream settings */
1643  input.framerate.numerator = 30;
1644  input.framerate.denominator = 1;
1645  input.only_i420 = 1;
1646  input.bit_depth = 0;
1647 
1648  /* First parse the global configuration values, because we want to apply
1649  * other parameters on top of the default configuration provided by the
1650  * codec.
1651  */
1652  argv = argv_dup(argc - 1, argv_ + 1);
1653  parse_global_config(&global, argv);
1654 
1655  if (argc < 3) usage_exit();
1656 
1657  switch (global.color_type) {
1658  case I420: input.fmt = VPX_IMG_FMT_I420; break;
1659  case I422: input.fmt = VPX_IMG_FMT_I422; break;
1660  case I444: input.fmt = VPX_IMG_FMT_I444; break;
1661  case I440: input.fmt = VPX_IMG_FMT_I440; break;
1662  case YV12: input.fmt = VPX_IMG_FMT_YV12; break;
1663  case NV12: input.fmt = VPX_IMG_FMT_NV12; break;
1664  }
1665 
1666  {
1667  /* Now parse each stream's parameters. Using a local scope here
1668  * due to the use of 'stream' as loop variable in FOREACH_STREAM
1669  * loops
1670  */
1671  struct stream_state *stream = NULL;
1672 
1673  do {
1674  stream = new_stream(&global, stream);
1675  stream_cnt++;
1676  if (!streams) streams = stream;
1677  } while (parse_stream_params(&global, stream, argv));
1678  }
1679 
1680  /* Check for unrecognized options */
1681  for (argi = argv; *argi; argi++)
1682  if (argi[0][0] == '-' && argi[0][1])
1683  die("Error: Unrecognized option %s\n", *argi);
1684 
1685  FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt, &global,
1686  &stream->config.cfg););
1687 
1688  /* Handle non-option arguments */
1689  input.filename = argv[0];
1690 
1691  if (!input.filename) {
1692  fprintf(stderr, "No input file specified!\n");
1693  usage_exit();
1694  }
1695 
1696  /* Decide if other chroma subsamplings than 4:2:0 are supported */
1697  if (global.codec->fourcc == VP9_FOURCC) input.only_i420 = 0;
1698 
1699  for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
1700  int frames_in = 0, seen_frames = 0;
1701  int64_t estimated_time_left = -1;
1702  int64_t average_rate = -1;
1703  int64_t lagged_count = 0;
1704 
1705  open_input_file(&input);
1706 
1707  /* If the input file doesn't specify its w/h (raw files), try to get
1708  * the data from the first stream's configuration.
1709  */
1710  if (!input.width || !input.height) {
1711  FOREACH_STREAM({
1712  if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
1713  input.width = stream->config.cfg.g_w;
1714  input.height = stream->config.cfg.g_h;
1715  break;
1716  }
1717  });
1718  }
1719 
1720  /* Update stream configurations from the input file's parameters */
1721  if (!input.width || !input.height)
1722  fatal(
1723  "Specify stream dimensions with --width (-w) "
1724  " and --height (-h)");
1725 
1726  /* If input file does not specify bit-depth but input-bit-depth parameter
1727  * exists, assume that to be the input bit-depth. However, if the
1728  * input-bit-depth paramter does not exist, assume the input bit-depth
1729  * to be the same as the codec bit-depth.
1730  */
1731  if (!input.bit_depth) {
1732  FOREACH_STREAM({
1733  if (stream->config.cfg.g_input_bit_depth)
1734  input.bit_depth = stream->config.cfg.g_input_bit_depth;
1735  else
1736  input.bit_depth = stream->config.cfg.g_input_bit_depth =
1737  (int)stream->config.cfg.g_bit_depth;
1738  });
1739  if (input.bit_depth > 8) input.fmt |= VPX_IMG_FMT_HIGHBITDEPTH;
1740  } else {
1741  FOREACH_STREAM(
1742  { stream->config.cfg.g_input_bit_depth = input.bit_depth; });
1743  }
1744 
1745  FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
1746  FOREACH_STREAM(validate_stream_config(stream, &global));
1747 
1748  /* Ensure that --passes and --pass are consistent. If --pass is set and
1749  * --passes=2, ensure --fpf was set.
1750  */
1751  if (global.pass && global.passes == 2)
1752  FOREACH_STREAM({
1753  if (!stream->config.stats_fn)
1754  die("Stream %d: Must specify --fpf when --pass=%d"
1755  " and --passes=2\n",
1756  stream->index, global.pass);
1757  });
1758 
1759 #if !CONFIG_WEBM_IO
1760  FOREACH_STREAM({
1761  if (stream->config.write_webm) {
1762  stream->config.write_webm = 0;
1763  warn(
1764  "vpxenc was compiled without WebM container support."
1765  "Producing IVF output");
1766  }
1767  });
1768 #endif
1769 
1770  /* Use the frame rate from the file only if none was specified
1771  * on the command-line.
1772  */
1773  if (!global.have_framerate) {
1774  global.framerate.num = input.framerate.numerator;
1775  global.framerate.den = input.framerate.denominator;
1776  FOREACH_STREAM(stream->config.cfg.g_timebase.den = global.framerate.num;
1777  stream->config.cfg.g_timebase.num = global.framerate.den);
1778  }
1779 
1780  /* Show configuration */
1781  if (global.verbose && pass == 0)
1782  FOREACH_STREAM(show_stream_config(stream, &global, &input));
1783 
1784  if (pass == (global.pass ? global.pass - 1 : 0)) {
1785  // The Y4M reader does its own allocation.
1786  if (input.file_type != FILE_TYPE_Y4M) {
1787  vpx_img_alloc(&raw, input.fmt, input.width, input.height, 32);
1788  }
1789  FOREACH_STREAM(stream->rate_hist = init_rate_histogram(
1790  &stream->config.cfg, &global.framerate));
1791  }
1792 
1793  FOREACH_STREAM(setup_pass(stream, &global, pass));
1794  FOREACH_STREAM(
1795  open_output_file(stream, &global, &input.pixel_aspect_ratio));
1796  FOREACH_STREAM(initialize_encoder(stream, &global));
1797 
1798 #if CONFIG_VP9_HIGHBITDEPTH
1799  if (strcmp(global.codec->name, "vp9") == 0) {
1800  // Check to see if at least one stream uses 16 bit internal.
1801  // Currently assume that the bit_depths for all streams using
1802  // highbitdepth are the same.
1803  FOREACH_STREAM({
1804  if (stream->config.use_16bit_internal) {
1805  use_16bit_internal = 1;
1806  }
1807  if (stream->config.cfg.g_profile == 0) {
1808  input_shift = 0;
1809  } else {
1810  input_shift = (int)stream->config.cfg.g_bit_depth -
1811  stream->config.cfg.g_input_bit_depth;
1812  }
1813  });
1814  }
1815 #endif
1816 
1817  frame_avail = 1;
1818  got_data = 0;
1819 
1820  while (frame_avail || got_data) {
1821  struct vpx_usec_timer timer;
1822 
1823  if (!global.limit || frames_in < global.limit) {
1824  frame_avail = read_frame(&input, &raw);
1825 
1826  if (frame_avail) frames_in++;
1827  seen_frames =
1828  frames_in > global.skip_frames ? frames_in - global.skip_frames : 0;
1829 
1830  if (!global.quiet) {
1831  float fps = usec_to_fps(cx_time, seen_frames);
1832  fprintf(stderr, "\rPass %d/%d ", pass + 1, global.passes);
1833 
1834  if (stream_cnt == 1)
1835  fprintf(stderr, "frame %4d/%-4d %7" PRId64 "B ", frames_in,
1836  streams->frames_out, (int64_t)streams->nbytes);
1837  else
1838  fprintf(stderr, "frame %4d ", frames_in);
1839 
1840  fprintf(stderr, "%7" PRId64 " %s %.2f %s ",
1841  cx_time > 9999999 ? cx_time / 1000 : cx_time,
1842  cx_time > 9999999 ? "ms" : "us", fps >= 1.0 ? fps : fps * 60,
1843  fps >= 1.0 ? "fps" : "fpm");
1844  print_time("ETA", estimated_time_left);
1845  }
1846 
1847  } else
1848  frame_avail = 0;
1849 
1850  if (frames_in > global.skip_frames) {
1851 #if CONFIG_VP9_HIGHBITDEPTH
1852  vpx_image_t *frame_to_encode;
1853  if (input_shift || (use_16bit_internal && input.bit_depth == 8)) {
1854  assert(use_16bit_internal);
1855  // Input bit depth and stream bit depth do not match, so up
1856  // shift frame to stream bit depth
1857  if (!allocated_raw_shift) {
1858  vpx_img_alloc(&raw_shift, raw.fmt | VPX_IMG_FMT_HIGHBITDEPTH,
1859  input.width, input.height, 32);
1860  allocated_raw_shift = 1;
1861  }
1862  vpx_img_upshift(&raw_shift, &raw, input_shift);
1863  frame_to_encode = &raw_shift;
1864  } else {
1865  frame_to_encode = &raw;
1866  }
1867  vpx_usec_timer_start(&timer);
1868  if (use_16bit_internal) {
1869  assert(frame_to_encode->fmt & VPX_IMG_FMT_HIGHBITDEPTH);
1870  FOREACH_STREAM({
1871  if (stream->config.use_16bit_internal)
1872  encode_frame(stream, &global,
1873  frame_avail ? frame_to_encode : NULL, frames_in);
1874  else
1875  assert(0);
1876  });
1877  } else {
1878  assert((frame_to_encode->fmt & VPX_IMG_FMT_HIGHBITDEPTH) == 0);
1879  FOREACH_STREAM(encode_frame(stream, &global,
1880  frame_avail ? frame_to_encode : NULL,
1881  frames_in));
1882  }
1883 #else
1884  vpx_usec_timer_start(&timer);
1885  FOREACH_STREAM(encode_frame(stream, &global, frame_avail ? &raw : NULL,
1886  frames_in));
1887 #endif
1888  vpx_usec_timer_mark(&timer);
1889  cx_time += vpx_usec_timer_elapsed(&timer);
1890 
1891  FOREACH_STREAM(update_quantizer_histogram(stream));
1892 
1893  got_data = 0;
1894  FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
1895 
1896  if (!got_data && input.length && streams != NULL &&
1897  !streams->frames_out) {
1898  lagged_count = global.limit ? seen_frames : ftello(input.file);
1899  } else if (input.length) {
1900  int64_t remaining;
1901  int64_t rate;
1902 
1903  if (global.limit) {
1904  const int64_t frame_in_lagged = (seen_frames - lagged_count) * 1000;
1905 
1906  rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
1907  remaining = 1000 * (global.limit - global.skip_frames -
1908  seen_frames + lagged_count);
1909  } else {
1910  const int64_t input_pos = ftello(input.file);
1911  const int64_t input_pos_lagged = input_pos - lagged_count;
1912  const int64_t limit = input.length;
1913 
1914  rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0;
1915  remaining = limit - input_pos + lagged_count;
1916  }
1917 
1918  average_rate =
1919  (average_rate <= 0) ? rate : (average_rate * 7 + rate) / 8;
1920  estimated_time_left = average_rate ? remaining / average_rate : -1;
1921  }
1922 
1923  if (got_data && global.test_decode != TEST_DECODE_OFF)
1924  FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec));
1925  }
1926 
1927  fflush(stdout);
1928  if (!global.quiet) fprintf(stderr, "\033[K");
1929  }
1930 
1931  if (stream_cnt > 1) fprintf(stderr, "\n");
1932 
1933  if (!global.quiet) {
1934  FOREACH_STREAM(fprintf(
1935  stderr,
1936  "\rPass %d/%d frame %4d/%-4d %7" PRId64 "B %7" PRId64 "b/f %7" PRId64
1937  "b/s %7" PRId64 " %s (%.2f fps)\033[K\n",
1938  pass + 1, global.passes, frames_in, stream->frames_out,
1939  (int64_t)stream->nbytes,
1940  seen_frames ? (int64_t)(stream->nbytes * 8 / seen_frames) : 0,
1941  seen_frames
1942  ? (int64_t)stream->nbytes * 8 * (int64_t)global.framerate.num /
1943  global.framerate.den / seen_frames
1944  : 0,
1945  stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
1946  stream->cx_time > 9999999 ? "ms" : "us",
1947  usec_to_fps(stream->cx_time, seen_frames)));
1948  }
1949 
1950  if (global.show_psnr) {
1951  if (global.codec->fourcc == VP9_FOURCC) {
1952  FOREACH_STREAM(
1953  show_psnr(stream, (1 << stream->config.cfg.g_input_bit_depth) - 1));
1954  } else {
1955  FOREACH_STREAM(show_psnr(stream, 255.0));
1956  }
1957  }
1958 
1959  FOREACH_STREAM(vpx_codec_destroy(&stream->encoder));
1960 
1961  if (global.test_decode != TEST_DECODE_OFF) {
1962  FOREACH_STREAM(vpx_codec_destroy(&stream->decoder));
1963  }
1964 
1965  close_input_file(&input);
1966 
1967  if (global.test_decode == TEST_DECODE_FATAL) {
1968  FOREACH_STREAM(res |= stream->mismatch_seen);
1969  }
1970  FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
1971 
1972  FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1));
1973 
1974 #if CONFIG_FP_MB_STATS
1975  FOREACH_STREAM(stats_close(&stream->fpmb_stats, global.passes - 1));
1976 #endif
1977 
1978  if (global.pass) break;
1979  }
1980 
1981  if (global.show_q_hist_buckets)
1982  FOREACH_STREAM(
1983  show_q_histogram(stream->counts, global.show_q_hist_buckets));
1984 
1985  if (global.show_rate_hist_buckets)
1986  FOREACH_STREAM(show_rate_histogram(stream->rate_hist, &stream->config.cfg,
1987  global.show_rate_hist_buckets));
1988  FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist));
1989 
1990 #if CONFIG_INTERNAL_STATS
1991  /* TODO(jkoleszar): This doesn't belong in this executable. Do it for now,
1992  * to match some existing utilities.
1993  */
1994  if (!(global.pass == 1 && global.passes == 2))
1995  FOREACH_STREAM({
1996  FILE *f = fopen("opsnr.stt", "a");
1997  if (stream->mismatch_seen) {
1998  fprintf(f, "First mismatch occurred in frame %d\n",
1999  stream->mismatch_seen);
2000  } else {
2001  fprintf(f, "No mismatch detected in recon buffers\n");
2002  }
2003  fclose(f);
2004  });
2005 #endif
2006 
2007 #if CONFIG_VP9_HIGHBITDEPTH
2008  if (allocated_raw_shift) vpx_img_free(&raw_shift);
2009 #endif
2010  vpx_img_free(&raw);
2011  free(argv);
2012  free(streams);
2013  return res ? EXIT_FAILURE : EXIT_SUCCESS;
2014 }
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:833
#define vpx_codec_enc_init(ctx, iface, cfg, flags)
Convenience macro for vpx_codec_enc_init_ver()
Definition: vpx_encoder.h:744
#define VPX_CODEC_USE_PSNR
Initialization-time Feature Enabling.
Definition: vpx_encoder.h:89
#define VPX_DL_GOOD_QUALITY
deadline parameter analogous to VPx GOOD QUALITY mode.
Definition: vpx_encoder.h:835
#define VPX_CODEC_USE_HIGHBITDEPTH
Definition: vpx_encoder.h:92
int64_t vpx_codec_pts_t
Time Stamp Type.
Definition: vpx_encoder.h:108
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:837
#define VPX_CODEC_USE_OUTPUT_PARTITION
Make the encoder output one partition at a time.
Definition: vpx_encoder.h:91
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:125
@ VPX_CODEC_PSNR_PKT
Definition: vpx_encoder.h:152
@ VPX_CODEC_CX_FRAME_PKT
Definition: vpx_encoder.h:149
@ VPX_CODEC_STATS_PKT
Definition: vpx_encoder.h:150
@ VPX_CODEC_FPMB_STATS_PKT
Definition: vpx_encoder.h:151
@ VPX_RC_LAST_PASS
Definition: vpx_encoder.h:229
@ VPX_RC_ONE_PASS
Definition: vpx_encoder.h:227
@ VPX_RC_FIRST_PASS
Definition: vpx_encoder.h:228
@ VPX_KF_DISABLED
Definition: vpx_encoder.h:251
@ VPX_Q
Definition: vpx_encoder.h:237
@ VPX_CQ
Definition: vpx_encoder.h:236
@ VPX_CBR
Definition: vpx_encoder.h:235
@ VPX_VBR
Definition: vpx_encoder.h:234
@ VP9E_SET_MIN_GF_INTERVAL
Codec control function to set minimum interval between GF/ARF frames.
Definition: vp8cx.h:515
@ VP9E_SET_MAX_INTER_BITRATE_PCT
Codec control function to set max data rate for Inter frames.
Definition: vp8cx.h:279
@ VP9E_SET_FRAME_PERIODIC_BOOST
Codec control function to enable/disable periodic Q boost.
Definition: vp8cx.h:414
@ VP8E_SET_MAX_INTRA_BITRATE_PCT
Codec control function to set Max data rate for Intra frames.
Definition: vp8cx.h:258
@ VP8E_SET_ARNR_STRENGTH
Codec control function to set the filter strength for the arf.
Definition: vp8cx.h:224
@ VP8E_SET_TUNING
Codec control function to set visual tuning.
Definition: vp8cx.h:233
@ VP8E_SET_ENABLEAUTOALTREF
Codec control function to enable automatic use of arf frames.
Definition: vp8cx.h:165
@ VP9E_SET_TARGET_LEVEL
Codec control function to set target level.
Definition: vp8cx.h:563
@ VP9E_SET_AQ_MODE
Codec control function to set adaptive quantization mode.
Definition: vp8cx.h:399
@ VP8E_SET_NOISE_SENSITIVITY
control function to set noise sensitivity
Definition: vp8cx.h:174
@ VP8E_SET_TOKEN_PARTITIONS
Codec control function to set the number of token partitions.
Definition: vp8cx.h:195
@ VP8E_SET_ARNR_TYPE
Definition: vp8cx.h:227
@ VP9E_SET_TILE_ROWS
Codec control function to set number of tile rows.
Definition: vp8cx.h:372
@ VP8E_SET_ARNR_MAXFRAMES
Codec control function to set the max no of frames to create arf.
Definition: vp8cx.h:218
@ VP9E_SET_LOSSLESS
Codec control function to set lossless encoding mode.
Definition: vp8cx.h:328
@ VP9E_SET_FRAME_PARALLEL_DECODING
Codec control function to enable frame parallel decoding feature.
Definition: vp8cx.h:386
@ VP8E_SET_SHARPNESS
Codec control function to set higher sharpness at the expense of a lower PSNR.
Definition: vp8cx.h:183
@ VP8E_SET_GF_CBR_BOOST_PCT
Boost percentage for Golden Frame in CBR mode.
Definition: vp8cx.h:602
@ VP9E_SET_TUNE_CONTENT
Codec control function to set content type.
Definition: vp8cx.h:464
@ VP9E_SET_TPL
Codec control function to enable temporal dependency model.
Definition: vp8cx.h:669
@ VP9E_SET_ROW_MT
Codec control function to set row level multi-threading.
Definition: vp8cx.h:571
@ VP8E_SET_CPUUSED
Codec control function to set encoder internal speed settings.
Definition: vp8cx.h:156
@ VP9E_SET_TILE_COLUMNS
Codec control function to set number of tile columns.
Definition: vp8cx.h:352
@ VP8E_SET_STATIC_THRESHOLD
Codec control function to set the threshold for MBs treated static.
Definition: vp8cx.h:189
@ VP9E_SET_COLOR_SPACE
Codec control function to set color space info.
Definition: vp8cx.h:495
@ VP8E_SET_SCREEN_CONTENT_MODE
Codec control function to set encoder screen content mode.
Definition: vp8cx.h:313
@ VP9E_SET_DISABLE_LOOPFILTER
Codec control function to disable loopfilter.
Definition: vp8cx.h:704
@ VP8E_SET_CQ_LEVEL
Codec control function to set constrained / constant quality level.
Definition: vp8cx.h:243
@ VP9E_SET_NOISE_SENSITIVITY
Codec control function to set noise sensitivity.
Definition: vp8cx.h:422
@ VP8E_GET_LAST_QUANTIZER_64
Codec control function to get last quantizer chosen by the encoder.
Definition: vp8cx.h:212
@ VP9E_SET_GF_CBR_BOOST_PCT
Boost percentage for Golden Frame in CBR mode.
Definition: vp8cx.h:294
@ VP9E_SET_MAX_GF_INTERVAL
Codec control function to set minimum interval between GF/ARF frames.
Definition: vp8cx.h:523
@ VP9E_SET_ALT_REF_AQ
Codec control function to enable/disable special mode for altref adaptive quantization....
Definition: vp8cx.h:587
@ 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:161
vpx_fixed_buf_t twopass_stats
Definition: vpx_encoder.h:184
enum vpx_codec_cx_pkt_kind kind
Definition: vpx_encoder.h:162
double psnr[4]
Definition: vpx_encoder.h:189
struct vpx_codec_cx_pkt::@1::@2 frame
vpx_fixed_buf_t firstpass_mb_stats
Definition: vpx_encoder.h:185
vpx_fixed_buf_t raw
Definition: vpx_encoder.h:191
union vpx_codec_cx_pkt::@1 data
Encoder configuration structure.
Definition: vpx_encoder.h:270
unsigned int g_h
Height of the frame.
Definition: vpx_encoder.h:315
unsigned int g_w
Width of the frame.
Definition: vpx_encoder.h:306
struct vpx_rational g_timebase
Stream timebase units.
Definition: vpx_encoder.h:345
enum vpx_enc_pass g_pass
Multi-pass Encoding Mode.
Definition: vpx_encoder.h:360
size_t sz
Definition: vpx_encoder.h:100
void * buf
Definition: vpx_encoder.h:99
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:220
int den
Definition: vpx_encoder.h:222
int num
Definition: vpx_encoder.h:221
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.