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