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