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