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
53static 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
59static const char *exec_name;
60
61static 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
75static 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
83static 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
92static const arg_def_t help =
93 ARG_DEF(NULL, "help", 0, "Show usage options and exit");
94static const arg_def_t debugmode =
95 ARG_DEF("D", "debug", 0, "Debug mode (makes output deterministic)");
96static const arg_def_t outputfile =
97 ARG_DEF("o", "output", 1, "Output filename");
98static const arg_def_t use_nv12 =
99 ARG_DEF(NULL, "nv12", 0, "Input file is NV12 ");
100static const arg_def_t use_yv12 =
101 ARG_DEF(NULL, "yv12", 0, "Input file is YV12 ");
102static const arg_def_t use_i420 =
103 ARG_DEF(NULL, "i420", 0, "Input file is I420 (default)");
104static const arg_def_t use_i422 =
105 ARG_DEF(NULL, "i422", 0, "Input file is I422");
106static const arg_def_t use_i444 =
107 ARG_DEF(NULL, "i444", 0, "Input file is I444");
108static const arg_def_t use_i440 =
109 ARG_DEF(NULL, "i440", 0, "Input file is I440");
110static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, "Codec to use");
111static const arg_def_t passes =
112 ARG_DEF("p", "passes", 1, "Number of passes (1/2)");
113static const arg_def_t pass_arg =
114 ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)");
115static const arg_def_t fpf_name =
116 ARG_DEF(NULL, "fpf", 1, "First pass statistics file name");
117#if CONFIG_FP_MB_STATS
118static const arg_def_t fpmbf_name =
119 ARG_DEF(NULL, "fpmbf", 1, "First pass block statistics file name");
120#endif
121static const arg_def_t limit =
122 ARG_DEF(NULL, "limit", 1, "Stop encoding after n input frames");
123static const arg_def_t skip =
124 ARG_DEF(NULL, "skip", 1, "Skip the first n input frames");
125static const arg_def_t deadline =
126 ARG_DEF("d", "deadline", 1, "Deadline per frame (usec)");
127static const arg_def_t best_dl =
128 ARG_DEF(NULL, "best", 0, "Use Best Quality Deadline");
129static const arg_def_t good_dl =
130 ARG_DEF(NULL, "good", 0, "Use Good Quality Deadline");
131static const arg_def_t rt_dl =
132 ARG_DEF(NULL, "rt", 0, "Use Realtime Quality Deadline");
133static const arg_def_t quietarg =
134 ARG_DEF("q", "quiet", 0, "Do not print encode progress");
135static const arg_def_t verbosearg =
136 ARG_DEF("v", "verbose", 0, "Show encoder parameters");
137static const arg_def_t psnrarg =
138 ARG_DEF(NULL, "psnr", 0, "Show PSNR in status line");
139
140static 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};
146static const arg_def_t recontest = ARG_DEF_ENUM(
147 NULL, "test-decode", 1, "Test encode/decode mismatch", test_decode_enum);
148static const arg_def_t framerate =
149 ARG_DEF(NULL, "fps", 1, "Stream frame rate (rate/scale)");
150static const arg_def_t use_webm =
151 ARG_DEF(NULL, "webm", 0, "Output WebM (default when WebM IO is enabled)");
152static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0, "Output IVF");
153static const arg_def_t out_part =
154 ARG_DEF("P", "output-partitions", 0,
155 "Makes encoder output partitions. Requires IVF output!");
156static const arg_def_t q_hist_n =
157 ARG_DEF(NULL, "q-hist", 1, "Show quantizer histogram (n-buckets)");
158static const arg_def_t rate_hist_n =
159 ARG_DEF(NULL, "rate-hist", 1, "Show rate histogram (n-buckets)");
160static const arg_def_t disable_warnings =
161 ARG_DEF(NULL, "disable-warnings", 0,
162 "Disable warnings about potentially incorrect encode settings.");
163static 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
168static const arg_def_t test16bitinternalarg = ARG_DEF(
169 NULL, "test-16bit-internal", 0, "Force use of 16 bit internal buffer");
170#endif
171
172static 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
198static const arg_def_t usage =
199 ARG_DEF("u", "usage", 1, "Usage profile number to use");
200static const arg_def_t threads =
201 ARG_DEF("t", "threads", 1, "Max number of threads to use");
202static const arg_def_t profile =
203 ARG_DEF(NULL, "profile", 1, "Bitstream profile number to use");
204static const arg_def_t width = ARG_DEF("w", "width", 1, "Frame width");
205static const arg_def_t height = ARG_DEF("h", "height", 1, "Frame height");
206#if CONFIG_WEBM_IO
207static 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};
215static const arg_def_t stereo_mode = ARG_DEF_ENUM(
216 NULL, "stereo-mode", 1, "Stereo 3D video format", stereo_mode_enum);
217#endif
218static const arg_def_t timebase = ARG_DEF(
219 NULL, "timebase", 1, "Output timestamp precision (fractional seconds)");
220static const arg_def_t error_resilient =
221 ARG_DEF(NULL, "error-resilient", 1, "Enable error resiliency features");
222static const arg_def_t lag_in_frames =
223 ARG_DEF(NULL, "lag-in-frames", 1, "Max number of frames to lag");
224
225static 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
248static const arg_def_t dropframe_thresh =
249 ARG_DEF(NULL, "drop-frame", 1, "Temporal resampling threshold (buf %)");
250static const arg_def_t resize_allowed =
251 ARG_DEF(NULL, "resize-allowed", 1, "Spatial resampling enabled (bool)");
252static const arg_def_t resize_width =
253 ARG_DEF(NULL, "resize-width", 1, "Width of encoded frame");
254static const arg_def_t resize_height =
255 ARG_DEF(NULL, "resize-height", 1, "Height of encoded frame");
256static const arg_def_t resize_up_thresh =
257 ARG_DEF(NULL, "resize-up", 1, "Upscale threshold (buf %)");
258static const arg_def_t resize_down_thresh =
259 ARG_DEF(NULL, "resize-down", 1, "Downscale threshold (buf %)");
260static 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 } };
265static const arg_def_t end_usage =
266 ARG_DEF_ENUM(NULL, "end-usage", 1, "Rate control mode", end_usage_enum);
267static const arg_def_t target_bitrate =
268 ARG_DEF(NULL, "target-bitrate", 1, "Bitrate (kbps)");
269static const arg_def_t min_quantizer =
270 ARG_DEF(NULL, "min-q", 1, "Minimum (best) quantizer");
271static const arg_def_t max_quantizer =
272 ARG_DEF(NULL, "max-q", 1, "Maximum (worst) quantizer");
273static const arg_def_t undershoot_pct =
274 ARG_DEF(NULL, "undershoot-pct", 1, "Datarate undershoot (min) target (%)");
275static const arg_def_t overshoot_pct =
276 ARG_DEF(NULL, "overshoot-pct", 1, "Datarate overshoot (max) target (%)");
277static const arg_def_t buf_sz =
278 ARG_DEF(NULL, "buf-sz", 1, "Client buffer size (ms)");
279static const arg_def_t buf_initial_sz =
280 ARG_DEF(NULL, "buf-initial-sz", 1, "Client initial buffer size (ms)");
281static const arg_def_t buf_optimal_sz =
282 ARG_DEF(NULL, "buf-optimal-sz", 1, "Client optimal buffer size (ms)");
283static 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
290static const arg_def_t bias_pct =
291 ARG_DEF(NULL, "bias-pct", 1, "CBR/VBR bias (0=CBR, 100=VBR)");
292static const arg_def_t minsection_pct =
293 ARG_DEF(NULL, "minsection-pct", 1, "GOP min bitrate (% of target)");
294static const arg_def_t maxsection_pct =
295 ARG_DEF(NULL, "maxsection-pct", 1, "GOP max bitrate (% of target)");
296static const arg_def_t corpus_complexity =
297 ARG_DEF(NULL, "corpus-complexity", 1, "corpus vbr complexity midpoint");
298static const arg_def_t *rc_twopass_args[] = { &bias_pct, &minsection_pct,
299 &maxsection_pct,
300 &corpus_complexity, NULL };
301
302static const arg_def_t kf_min_dist =
303 ARG_DEF(NULL, "kf-min-dist", 1, "Minimum keyframe interval (frames)");
304static const arg_def_t kf_max_dist =
305 ARG_DEF(NULL, "kf-max-dist", 1, "Maximum keyframe interval (frames)");
306static const arg_def_t kf_disabled =
307 ARG_DEF(NULL, "disable-kf", 0, "Disable keyframe placement");
308static const arg_def_t *kf_args[] = { &kf_min_dist, &kf_max_dist, &kf_disabled,
309 NULL };
310
311static const arg_def_t noise_sens =
312 ARG_DEF(NULL, "noise-sensitivity", 1, "Noise sensitivity (frames to blur)");
313static const arg_def_t sharpness =
314 ARG_DEF(NULL, "sharpness", 1,
315 "Increase sharpness at the expense of lower PSNR. (0..7)");
316static const arg_def_t static_thresh =
317 ARG_DEF(NULL, "static-thresh", 1, "Motion detection threshold");
318static const arg_def_t arnr_maxframes =
319 ARG_DEF(NULL, "arnr-maxframes", 1, "AltRef max frames (0..15)");
320static const arg_def_t arnr_strength =
321 ARG_DEF(NULL, "arnr-strength", 1, "AltRef filter strength (0..6)");
322static const arg_def_t arnr_type =
323 ARG_DEF(NULL, "arnr-type", 1, "AltRef filter type (1..3)");
324static const struct arg_enum_list tuning_enum[] = { { "psnr", VP8_TUNE_PSNR },
325 { "ssim", VP8_TUNE_SSIM },
326 { NULL, 0 } };
327static const arg_def_t tune_ssim =
328 ARG_DEF_ENUM(NULL, "tune", 1, "Material to favor", tuning_enum);
329static const arg_def_t cq_level =
330 ARG_DEF(NULL, "cq-level", 1, "Constant/Constrained Quality level");
331static const arg_def_t max_intra_rate_pct =
332 ARG_DEF(NULL, "max-intra-rate", 1, "Max I-frame bitrate (pct)");
333static 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
337static const arg_def_t cpu_used_vp8 =
338 ARG_DEF(NULL, "cpu-used", 1, "CPU Used (-16..16)");
339static const arg_def_t auto_altref_vp8 = ARG_DEF(
340 NULL, "auto-alt-ref", 1, "Enable automatic alt reference frames. (0..1)");
341static const arg_def_t token_parts =
342 ARG_DEF(NULL, "token-parts", 1, "Number of token partitions to use, log2");
343static const arg_def_t screen_content_mode =
344 ARG_DEF(NULL, "screen-content-mode", 1, "Screen content mode");
345static 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 };
360static const int vp8_arg_ctrl_map[] = { VP8E_SET_CPUUSED,
374 0 };
375#endif
376
377#if CONFIG_VP9_ENCODER
378static const arg_def_t cpu_used_vp9 =
379 ARG_DEF(NULL, "cpu-used", 1, "CPU Used (-9..9)");
380static 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)");
383static const arg_def_t tile_cols =
384 ARG_DEF(NULL, "tile-columns", 1, "Number of tile columns to use, log2");
385static 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
389static const arg_def_t enable_tpl_model =
390 ARG_DEF(NULL, "enable-tpl", 1, "Enable temporal dependency model");
391
392static const arg_def_t lossless =
393 ARG_DEF(NULL, "lossless", 1, "Lossless mode (0: false (default), 1: true)");
394static const arg_def_t frame_parallel_decoding = ARG_DEF(
395 NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
396static 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)");
400static const arg_def_t alt_ref_aq = ARG_DEF(NULL, "alt-ref-aq", 1,
401 "Special adaptive quantization for "
402 "the alternate reference frames.");
403static const arg_def_t frame_periodic_boost =
404 ARG_DEF(NULL, "frame-boost", 1,
405 "Enable frame periodic boost (0: off (default), 1: on)");
406static const arg_def_t max_inter_rate_pct =
407 ARG_DEF(NULL, "max-inter-rate", 1, "Max P-frame bitrate (pct)");
408static 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)");
411static 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
415static 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
427static 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
432static const struct arg_enum_list bitdepth_enum[] = {
433 { "8", VPX_BITS_8 }, { "10", VPX_BITS_10 }, { "12", VPX_BITS_12 }, { NULL, 0 }
434};
435
436static 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);
440static const arg_def_t inbitdeptharg =
441 ARG_DEF(NULL, "input-bit-depth", 1, "Bit depth of input");
442#endif
443
444static 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
451static const arg_def_t tune_content = ARG_DEF_ENUM(
452 NULL, "tune-content", 1, "Tune content type", tune_content_enum);
453
454static 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
465static const arg_def_t row_mt =
466 ARG_DEF(NULL, "row-mt", 1,
467 "Enable row based non-deterministic multi-threading in VP9");
468
469static 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
478static 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 };
514static const int vp9_arg_ctrl_map[] = { VP8E_SET_CPUUSED,
542 0 };
543#endif
544
545static const arg_def_t *no_args[] = { NULL };
546
547static 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
593void 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
606typedef int stereo_format_t;
607struct WebmOutputContext {
608 int debug;
609};
610#endif
611
612/* Per-stream configuration */
613struct 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
630struct 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
655static 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
667static 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
785static 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
842static 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
1036static 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
1092static 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
1105static 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
1113static 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
1128static 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
1182static 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
1212static 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
1233static 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
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
1270static 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
1307static 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
1396static 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
1406static 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;
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,
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
1502static 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
1519static float usec_to_fps(uint64_t usec, unsigned int frames) {
1520 return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
1521}
1522
1523static 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
1600static 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
1619int 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_err_to_string(vpx_codec_err_t err)
Convert error number to printable string.
const char * vpx_codec_error_detail(vpx_codec_ctx_t *ctx)
Retrieve detailed error information 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.
#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
const char * vpx_codec_error(vpx_codec_ctx_t *ctx)
Retrieve error synopsis for codec context.
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
const vpx_codec_cx_pkt_t * vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter)
Encoded data iterator.
#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
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_codec_frame_flags_t flags
Definition: vpx_encoder.h:171
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
size_t sz
Definition: vpx_encoder.h:166
void * buf
Definition: vpx_encoder.h:165
vpx_codec_pts_t pts
time stamp to show frame (in timebase units)
Definition: vpx_encoder.h:168
vpx_fixed_buf_t raw
Definition: vpx_encoder.h:191
int partition_id
the partition id defines the decoding order of the partitions. Only applicable when "output partition...
Definition: vpx_encoder.h:175
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
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_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
#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.