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