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