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