12 #include "./vpx_config.h"
23 #include "third_party/libyuv/include/libyuv/scale.h"
33 #include "./tools_common.h"
35 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
38 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
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"
49 #include "./webmenc.h"
51 #include "./y4minput.h"
53 static size_t wrap_fwrite(
const void *ptr,
size_t size,
size_t nmemb,
55 return fwrite(ptr, size, nmemb, stream);
57 #define fwrite wrap_fwrite
59 static const char *exec_name;
62 const char *s, va_list ap) {
66 vfprintf(stderr, s, ap);
69 if (detail) fprintf(stderr,
" %s\n", detail);
71 if (fatal) exit(EXIT_FAILURE);
75 static void ctx_exit_on_error(
vpx_codec_ctx_t *ctx,
const char *s, ...) {
79 warn_or_exit_on_errorv(ctx, 1, s, ap);
88 warn_or_exit_on_errorv(ctx, fatal, s, ap);
92 static const arg_def_t help =
93 ARG_DEF(NULL,
"help", 0,
"Show usage options and exit");
94 static const arg_def_t debugmode =
95 ARG_DEF(
"D",
"debug", 0,
"Debug mode (makes output deterministic)");
96 static const arg_def_t outputfile =
97 ARG_DEF(
"o",
"output", 1,
"Output filename");
98 static const arg_def_t use_yv12 =
99 ARG_DEF(NULL,
"yv12", 0,
"Input file is YV12 ");
100 static const arg_def_t use_i420 =
101 ARG_DEF(NULL,
"i420", 0,
"Input file is I420 (default)");
102 static const arg_def_t use_i422 =
103 ARG_DEF(NULL,
"i422", 0,
"Input file is I422");
104 static const arg_def_t use_i444 =
105 ARG_DEF(NULL,
"i444", 0,
"Input file is I444");
106 static const arg_def_t use_i440 =
107 ARG_DEF(NULL,
"i440", 0,
"Input file is I440");
108 static const arg_def_t codecarg = ARG_DEF(NULL,
"codec", 1,
"Codec to use");
109 static const arg_def_t passes =
110 ARG_DEF(
"p",
"passes", 1,
"Number of passes (1/2)");
111 static const arg_def_t pass_arg =
112 ARG_DEF(NULL,
"pass", 1,
"Pass to execute (1/2)");
113 static const arg_def_t fpf_name =
114 ARG_DEF(NULL,
"fpf", 1,
"First pass statistics file name");
115 #if CONFIG_FP_MB_STATS
116 static const arg_def_t fpmbf_name =
117 ARG_DEF(NULL,
"fpmbf", 1,
"First pass block statistics file name");
119 static const arg_def_t limit =
120 ARG_DEF(NULL,
"limit", 1,
"Stop encoding after n input frames");
121 static const arg_def_t skip =
122 ARG_DEF(NULL,
"skip", 1,
"Skip the first n input frames");
123 static const arg_def_t deadline =
124 ARG_DEF(
"d",
"deadline", 1,
"Deadline per frame (usec)");
125 static const arg_def_t best_dl =
126 ARG_DEF(NULL,
"best", 0,
"Use Best Quality Deadline");
127 static const arg_def_t good_dl =
128 ARG_DEF(NULL,
"good", 0,
"Use Good Quality Deadline");
129 static const arg_def_t rt_dl =
130 ARG_DEF(NULL,
"rt", 0,
"Use Realtime Quality Deadline");
131 static const arg_def_t quietarg =
132 ARG_DEF(
"q",
"quiet", 0,
"Do not print encode progress");
133 static const arg_def_t verbosearg =
134 ARG_DEF(
"v",
"verbose", 0,
"Show encoder parameters");
135 static const arg_def_t psnrarg =
136 ARG_DEF(NULL,
"psnr", 0,
"Show PSNR in status line");
138 static const struct arg_enum_list test_decode_enum[] = {
139 {
"off", TEST_DECODE_OFF },
140 {
"fatal", TEST_DECODE_FATAL },
141 {
"warn", TEST_DECODE_WARN },
144 static const arg_def_t recontest = ARG_DEF_ENUM(
145 NULL,
"test-decode", 1,
"Test encode/decode mismatch", test_decode_enum);
146 static const arg_def_t framerate =
147 ARG_DEF(NULL,
"fps", 1,
"Stream frame rate (rate/scale)");
148 static const arg_def_t use_webm =
149 ARG_DEF(NULL,
"webm", 0,
"Output WebM (default when WebM IO is enabled)");
150 static const arg_def_t use_ivf = ARG_DEF(NULL,
"ivf", 0,
"Output IVF");
151 static const arg_def_t out_part =
152 ARG_DEF(
"P",
"output-partitions", 0,
153 "Makes encoder output partitions. Requires IVF output!");
154 static const arg_def_t q_hist_n =
155 ARG_DEF(NULL,
"q-hist", 1,
"Show quantizer histogram (n-buckets)");
156 static const arg_def_t rate_hist_n =
157 ARG_DEF(NULL,
"rate-hist", 1,
"Show rate histogram (n-buckets)");
158 static const arg_def_t disable_warnings =
159 ARG_DEF(NULL,
"disable-warnings", 0,
160 "Disable warnings about potentially incorrect encode settings.");
161 static 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.");
165 #if CONFIG_VP9_HIGHBITDEPTH
166 static const arg_def_t test16bitinternalarg = ARG_DEF(
167 NULL,
"test-16bit-internal", 0,
"Force use of 16 bit internal buffer");
170 static const arg_def_t *main_args[] = { &help,
192 &disable_warning_prompt,
196 static const arg_def_t usage =
197 ARG_DEF(
"u",
"usage", 1,
"Usage profile number to use");
198 static const arg_def_t threads =
199 ARG_DEF(
"t",
"threads", 1,
"Max number of threads to use");
200 static const arg_def_t profile =
201 ARG_DEF(NULL,
"profile", 1,
"Bitstream profile number to use");
202 static const arg_def_t width = ARG_DEF(
"w",
"width", 1,
"Frame width");
203 static const arg_def_t height = ARG_DEF(
"h",
"height", 1,
"Frame height");
205 static 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 },
213 static const arg_def_t stereo_mode = ARG_DEF_ENUM(
214 NULL,
"stereo-mode", 1,
"Stereo 3D video format", stereo_mode_enum);
216 static const arg_def_t timebase = ARG_DEF(
217 NULL,
"timebase", 1,
"Output timestamp precision (fractional seconds)");
218 static const arg_def_t error_resilient =
219 ARG_DEF(NULL,
"error-resilient", 1,
"Enable error resiliency features");
220 static const arg_def_t lag_in_frames =
221 ARG_DEF(NULL,
"lag-in-frames", 1,
"Max number of frames to lag");
223 static const arg_def_t *global_args[] = { &use_yv12,
239 #if CONFIG_VP9_HIGHBITDEPTH
240 &test16bitinternalarg,
245 static const arg_def_t dropframe_thresh =
246 ARG_DEF(NULL,
"drop-frame", 1,
"Temporal resampling threshold (buf %)");
247 static const arg_def_t resize_allowed =
248 ARG_DEF(NULL,
"resize-allowed", 1,
"Spatial resampling enabled (bool)");
249 static const arg_def_t resize_width =
250 ARG_DEF(NULL,
"resize-width", 1,
"Width of encoded frame");
251 static const arg_def_t resize_height =
252 ARG_DEF(NULL,
"resize-height", 1,
"Height of encoded frame");
253 static const arg_def_t resize_up_thresh =
254 ARG_DEF(NULL,
"resize-up", 1,
"Upscale threshold (buf %)");
255 static const arg_def_t resize_down_thresh =
256 ARG_DEF(NULL,
"resize-down", 1,
"Downscale threshold (buf %)");
257 static const struct arg_enum_list end_usage_enum[] = { {
"vbr",
VPX_VBR },
262 static const arg_def_t end_usage =
263 ARG_DEF_ENUM(NULL,
"end-usage", 1,
"Rate control mode", end_usage_enum);
264 static const arg_def_t target_bitrate =
265 ARG_DEF(NULL,
"target-bitrate", 1,
"Bitrate (kbps)");
266 static const arg_def_t min_quantizer =
267 ARG_DEF(NULL,
"min-q", 1,
"Minimum (best) quantizer");
268 static const arg_def_t max_quantizer =
269 ARG_DEF(NULL,
"max-q", 1,
"Maximum (worst) quantizer");
270 static const arg_def_t undershoot_pct =
271 ARG_DEF(NULL,
"undershoot-pct", 1,
"Datarate undershoot (min) target (%)");
272 static const arg_def_t overshoot_pct =
273 ARG_DEF(NULL,
"overshoot-pct", 1,
"Datarate overshoot (max) target (%)");
274 static const arg_def_t buf_sz =
275 ARG_DEF(NULL,
"buf-sz", 1,
"Client buffer size (ms)");
276 static const arg_def_t buf_initial_sz =
277 ARG_DEF(NULL,
"buf-initial-sz", 1,
"Client initial buffer size (ms)");
278 static const arg_def_t buf_optimal_sz =
279 ARG_DEF(NULL,
"buf-optimal-sz", 1,
"Client optimal buffer size (ms)");
280 static const arg_def_t *rc_args[] = {
281 &dropframe_thresh, &resize_allowed, &resize_width, &resize_height,
282 &resize_up_thresh, &resize_down_thresh, &end_usage, &target_bitrate,
283 &min_quantizer, &max_quantizer, &undershoot_pct, &overshoot_pct,
284 &buf_sz, &buf_initial_sz, &buf_optimal_sz, NULL
287 static const arg_def_t bias_pct =
288 ARG_DEF(NULL,
"bias-pct", 1,
"CBR/VBR bias (0=CBR, 100=VBR)");
289 static const arg_def_t minsection_pct =
290 ARG_DEF(NULL,
"minsection-pct", 1,
"GOP min bitrate (% of target)");
291 static const arg_def_t maxsection_pct =
292 ARG_DEF(NULL,
"maxsection-pct", 1,
"GOP max bitrate (% of target)");
293 static const arg_def_t corpus_complexity =
294 ARG_DEF(NULL,
"corpus-complexity", 1,
"corpus vbr complexity midpoint");
295 static const arg_def_t *rc_twopass_args[] = { &bias_pct, &minsection_pct,
297 &corpus_complexity, NULL };
299 static const arg_def_t kf_min_dist =
300 ARG_DEF(NULL,
"kf-min-dist", 1,
"Minimum keyframe interval (frames)");
301 static const arg_def_t kf_max_dist =
302 ARG_DEF(NULL,
"kf-max-dist", 1,
"Maximum keyframe interval (frames)");
303 static const arg_def_t kf_disabled =
304 ARG_DEF(NULL,
"disable-kf", 0,
"Disable keyframe placement");
305 static const arg_def_t *kf_args[] = { &kf_min_dist, &kf_max_dist, &kf_disabled,
308 static const arg_def_t noise_sens =
309 ARG_DEF(NULL,
"noise-sensitivity", 1,
"Noise sensitivity (frames to blur)");
310 static const arg_def_t sharpness =
311 ARG_DEF(NULL,
"sharpness", 1,
312 "Increase sharpness at the expense of lower PSNR. (0..7)");
313 static const arg_def_t static_thresh =
314 ARG_DEF(NULL,
"static-thresh", 1,
"Motion detection threshold");
315 static const arg_def_t arnr_maxframes =
316 ARG_DEF(NULL,
"arnr-maxframes", 1,
"AltRef max frames (0..15)");
317 static const arg_def_t arnr_strength =
318 ARG_DEF(NULL,
"arnr-strength", 1,
"AltRef filter strength (0..6)");
319 static const arg_def_t arnr_type =
320 ARG_DEF(NULL,
"arnr-type", 1,
"AltRef filter type (1..3)");
321 static const struct arg_enum_list tuning_enum[] = { {
"psnr", VP8_TUNE_PSNR },
322 {
"ssim", VP8_TUNE_SSIM },
324 static const arg_def_t tune_ssim =
325 ARG_DEF_ENUM(NULL,
"tune", 1,
"Material to favor", tuning_enum);
326 static const arg_def_t cq_level =
327 ARG_DEF(NULL,
"cq-level", 1,
"Constant/Constrained Quality level");
328 static const arg_def_t max_intra_rate_pct =
329 ARG_DEF(NULL,
"max-intra-rate", 1,
"Max I-frame bitrate (pct)");
330 static const arg_def_t gf_cbr_boost_pct = ARG_DEF(
331 NULL,
"gf-cbr-boost", 1,
"Boost for Golden Frame in CBR mode (pct)");
333 #if CONFIG_VP8_ENCODER
334 static const arg_def_t cpu_used_vp8 =
335 ARG_DEF(NULL,
"cpu-used", 1,
"CPU Used (-16..16)");
336 static const arg_def_t auto_altref_vp8 = ARG_DEF(
337 NULL,
"auto-alt-ref", 1,
"Enable automatic alt reference frames. (0..1)");
338 static const arg_def_t token_parts =
339 ARG_DEF(NULL,
"token-parts", 1,
"Number of token partitions to use, log2");
340 static const arg_def_t screen_content_mode =
341 ARG_DEF(NULL,
"screen-content-mode", 1,
"Screen content mode");
342 static const arg_def_t *vp8_args[] = { &cpu_used_vp8,
355 &screen_content_mode,
374 #if CONFIG_VP9_ENCODER
375 static const arg_def_t cpu_used_vp9 =
376 ARG_DEF(NULL,
"cpu-used", 1,
"CPU Used (-9..9)");
377 static const arg_def_t auto_altref_vp9 = ARG_DEF(
378 NULL,
"auto-alt-ref", 1,
379 "Enable automatic alt reference frames, 2+ enables multi-layer. (0..6)");
380 static const arg_def_t tile_cols =
381 ARG_DEF(NULL,
"tile-columns", 1,
"Number of tile columns to use, log2");
382 static const arg_def_t tile_rows =
383 ARG_DEF(NULL,
"tile-rows", 1,
384 "Number of tile rows to use, log2 (set to 0 while threads > 1)");
386 static const arg_def_t enable_tpl_model =
387 ARG_DEF(NULL,
"enable-tpl", 1,
"Enable temporal dependency model");
389 static const arg_def_t lossless =
390 ARG_DEF(NULL,
"lossless", 1,
"Lossless mode (0: false (default), 1: true)");
391 static const arg_def_t frame_parallel_decoding = ARG_DEF(
392 NULL,
"frame-parallel", 1,
"Enable frame parallel decodability features");
393 static const arg_def_t aq_mode = ARG_DEF(
395 "Adaptive quantization mode (0: off (default), 1: variance 2: complexity, "
396 "3: cyclic refresh, 4: equator360)");
397 static const arg_def_t alt_ref_aq = ARG_DEF(NULL,
"alt-ref-aq", 1,
398 "Special adaptive quantization for "
399 "the alternate reference frames.");
400 static const arg_def_t frame_periodic_boost =
401 ARG_DEF(NULL,
"frame-boost", 1,
402 "Enable frame periodic boost (0: off (default), 1: on)");
403 static const arg_def_t max_inter_rate_pct =
404 ARG_DEF(NULL,
"max-inter-rate", 1,
"Max P-frame bitrate (pct)");
405 static const arg_def_t min_gf_interval = ARG_DEF(
406 NULL,
"min-gf-interval", 1,
407 "min gf/arf frame interval (default 0, indicating in-built behavior)");
408 static const arg_def_t max_gf_interval = ARG_DEF(
409 NULL,
"max-gf-interval", 1,
410 "max gf/arf frame interval (default 0, indicating in-built behavior)");
412 static const struct arg_enum_list color_space_enum[] = {
424 static const arg_def_t input_color_space =
425 ARG_DEF_ENUM(NULL,
"color-space", 1,
426 "The color space of input content:", color_space_enum);
428 #if CONFIG_VP9_HIGHBITDEPTH
429 static const struct arg_enum_list bitdepth_enum[] = {
433 static const arg_def_t bitdeptharg = ARG_DEF_ENUM(
435 "Bit depth for codec (8 for version <=1, 10 or 12 for version 2)",
437 static const arg_def_t inbitdeptharg =
438 ARG_DEF(NULL,
"input-bit-depth", 1,
"Bit depth of input");
441 static const struct arg_enum_list tune_content_enum[] = {
442 {
"default", VP9E_CONTENT_DEFAULT },
443 {
"screen", VP9E_CONTENT_SCREEN },
444 {
"film", VP9E_CONTENT_FILM },
448 static const arg_def_t tune_content = ARG_DEF_ENUM(
449 NULL,
"tune-content", 1,
"Tune content type", tune_content_enum);
451 static const arg_def_t target_level = ARG_DEF(
452 NULL,
"target-level", 1,
454 " 255: off (default)\n"
455 " 0: only keep level stats\n"
456 " 1: adaptively set alt-ref "
457 "distance and column tile limit based on picture size, and keep"
459 " 10: level 1.0 11: level 1.1 "
460 "... 62: level 6.2");
462 static const arg_def_t row_mt =
463 ARG_DEF(NULL,
"row-mt", 1,
464 "Enable row based non-deterministic multi-threading in VP9");
467 #if CONFIG_VP9_ENCODER
468 static const arg_def_t *vp9_args[] = { &cpu_used_vp9,
484 &frame_parallel_decoding,
487 &frame_periodic_boost,
495 #if CONFIG_VP9_HIGHBITDEPTH
530 static const arg_def_t *no_args[] = { NULL };
532 static void show_help(FILE *fout,
int shorthelp) {
534 const int num_encoder = get_vpx_encoder_count();
536 fprintf(fout,
"Usage: %s <options> -o dst_filename src_filename \n",
540 fprintf(fout,
"Use --help to see the full list of options.\n");
544 fprintf(fout,
"\nOptions:\n");
545 arg_show_usage(fout, main_args);
546 fprintf(fout,
"\nEncoder Global Options:\n");
547 arg_show_usage(fout, global_args);
548 fprintf(fout,
"\nRate Control Options:\n");
549 arg_show_usage(fout, rc_args);
550 fprintf(fout,
"\nTwopass Rate Control Options:\n");
551 arg_show_usage(fout, rc_twopass_args);
552 fprintf(fout,
"\nKeyframe Placement Options:\n");
553 arg_show_usage(fout, kf_args);
554 #if CONFIG_VP8_ENCODER
555 fprintf(fout,
"\nVP8 Specific Options:\n");
556 arg_show_usage(fout, vp8_args);
558 #if CONFIG_VP9_ENCODER
559 fprintf(fout,
"\nVP9 Specific Options:\n");
560 arg_show_usage(fout, vp9_args);
563 "\nStream timebase (--timebase):\n"
564 " The desired precision of timestamps in the output, expressed\n"
565 " in fractional seconds. Default is 1/1000.\n");
566 fprintf(fout,
"\nIncluded encoders:\n\n");
568 for (i = 0; i < num_encoder; ++i) {
569 const VpxInterface *
const encoder = get_vpx_encoder_by_index(i);
570 const char *defstr = (i == (num_encoder - 1)) ?
"(default)" :
"";
571 fprintf(fout,
" %-6s - %s %s\n", encoder->name,
574 fprintf(fout,
"\n ");
575 fprintf(fout,
"Use --codec to switch to a non-default encoder.\n\n");
578 void usage_exit(
void) {
579 show_help(stderr, 1);
583 #define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
584 #if CONFIG_VP9_ENCODER
585 #define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map)
587 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
591 typedef int stereo_format_t;
592 struct WebmOutputContext {
598 struct stream_config {
601 const char *stats_fn;
602 #if CONFIG_FP_MB_STATS
603 const char *fpmb_stats_fn;
605 stereo_format_t stereo_fmt;
606 int arg_ctrls[ARG_CTRL_CNT_MAX][2];
609 #if CONFIG_VP9_HIGHBITDEPTH
611 int use_16bit_internal;
615 struct stream_state {
617 struct stream_state *next;
618 struct stream_config config;
620 struct rate_hist *rate_hist;
621 struct WebmOutputContext webm_ctx;
622 uint64_t psnr_sse_total;
623 uint64_t psnr_samples_total;
624 double psnr_totals[4];
628 unsigned int frames_out;
632 #if CONFIG_FP_MB_STATS
633 stats_io_t fpmb_stats;
640 static void validate_positive_rational(
const char *msg,
647 if (rat->
num < 0) die(
"Error: %s must be positive\n", msg);
649 if (!rat->
den) die(
"Error: %s has zero denominator\n", msg);
652 static void parse_global_config(
struct VpxEncoderConfig *global,
char **argv) {
655 const int num_encoder = get_vpx_encoder_count();
657 if (num_encoder < 1) die(
"Error: no valid encoder available\n");
660 memset(global, 0,
sizeof(*global));
661 global->codec = get_vpx_encoder_by_index(num_encoder - 1);
663 global->color_type = I420;
667 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
670 if (arg_match(&arg, &help, argi)) {
671 show_help(stdout, 0);
673 }
else if (arg_match(&arg, &codecarg, argi)) {
674 global->codec = get_vpx_encoder_by_name(arg.val);
676 die(
"Error: Unrecognized argument (%s) to --codec\n", arg.val);
677 }
else if (arg_match(&arg, &passes, argi)) {
678 global->passes = arg_parse_uint(&arg);
680 if (global->passes < 1 || global->passes > 2)
681 die(
"Error: Invalid number of passes (%d)\n", global->passes);
682 }
else if (arg_match(&arg, &pass_arg, argi)) {
683 global->pass = arg_parse_uint(&arg);
685 if (global->pass < 1 || global->pass > 2)
686 die(
"Error: Invalid pass selected (%d)\n", global->pass);
687 }
else if (arg_match(&arg, &usage, argi))
688 global->usage = arg_parse_uint(&arg);
689 else if (arg_match(&arg, &deadline, argi))
690 global->deadline = arg_parse_uint(&arg);
691 else if (arg_match(&arg, &best_dl, argi))
693 else if (arg_match(&arg, &good_dl, argi))
695 else if (arg_match(&arg, &rt_dl, argi))
697 else if (arg_match(&arg, &use_yv12, argi))
698 global->color_type = YV12;
699 else if (arg_match(&arg, &use_i420, argi))
700 global->color_type = I420;
701 else if (arg_match(&arg, &use_i422, argi))
702 global->color_type = I422;
703 else if (arg_match(&arg, &use_i444, argi))
704 global->color_type = I444;
705 else if (arg_match(&arg, &use_i440, argi))
706 global->color_type = I440;
707 else if (arg_match(&arg, &quietarg, argi))
709 else if (arg_match(&arg, &verbosearg, argi))
711 else if (arg_match(&arg, &limit, argi))
712 global->limit = arg_parse_uint(&arg);
713 else if (arg_match(&arg, &skip, argi))
714 global->skip_frames = arg_parse_uint(&arg);
715 else if (arg_match(&arg, &psnrarg, argi))
716 global->show_psnr = 1;
717 else if (arg_match(&arg, &recontest, argi))
718 global->test_decode = arg_parse_enum_or_int(&arg);
719 else if (arg_match(&arg, &framerate, argi)) {
720 global->framerate = arg_parse_rational(&arg);
721 validate_positive_rational(arg.name, &global->framerate);
722 global->have_framerate = 1;
723 }
else if (arg_match(&arg, &out_part, argi))
724 global->out_part = 1;
725 else if (arg_match(&arg, &debugmode, argi))
727 else if (arg_match(&arg, &q_hist_n, argi))
728 global->show_q_hist_buckets = arg_parse_uint(&arg);
729 else if (arg_match(&arg, &rate_hist_n, argi))
730 global->show_rate_hist_buckets = arg_parse_uint(&arg);
731 else if (arg_match(&arg, &disable_warnings, argi))
732 global->disable_warnings = 1;
733 else if (arg_match(&arg, &disable_warning_prompt, argi))
734 global->disable_warning_prompt = 1;
741 if (global->pass > global->passes) {
742 warn(
"Assuming --pass=%d implies --passes=%d\n", global->pass,
744 global->passes = global->pass;
748 if (global->passes == 0) {
749 #if CONFIG_VP9_ENCODER
752 if (global->codec != NULL && global->codec->name != NULL)
753 global->passes = (strcmp(global->codec->name,
"vp9") == 0 &&
763 warn(
"Enforcing one-pass encoding in realtime mode\n");
768 static struct stream_state *new_stream(
struct VpxEncoderConfig *global,
769 struct stream_state *prev) {
770 struct stream_state *stream;
772 stream = calloc(1,
sizeof(*stream));
773 if (stream == NULL) {
774 fatal(
"Failed to allocate new stream.");
778 memcpy(stream, prev,
sizeof(*stream));
786 &stream->config.cfg, global->usage);
792 stream->config.cfg.g_timebase.den = 1000;
797 stream->config.cfg.g_w = 0;
798 stream->config.cfg.g_h = 0;
801 stream->config.write_webm = 1;
803 stream->config.stereo_fmt = STEREO_FORMAT_MONO;
804 stream->webm_ctx.last_pts_ns = -1;
805 stream->webm_ctx.writer = NULL;
806 stream->webm_ctx.segment = NULL;
810 stream->webm_ctx.debug = global->debug;
814 stream->config.cfg.rc_end_usage == 1)
815 stream->config.cfg.g_lag_in_frames = 0;
819 stream->config.out_fn = NULL;
825 static int parse_stream_params(
struct VpxEncoderConfig *global,
826 struct stream_state *stream,
char **argv) {
829 static const arg_def_t **ctrl_args = no_args;
830 static const int *ctrl_args_map = NULL;
831 struct stream_config *config = &stream->config;
832 int eos_mark_found = 0;
833 #if CONFIG_VP9_HIGHBITDEPTH
834 int test_16bit_internal = 0;
839 #if CONFIG_VP8_ENCODER
840 }
else if (strcmp(global->codec->name,
"vp8") == 0) {
841 ctrl_args = vp8_args;
842 ctrl_args_map = vp8_arg_ctrl_map;
844 #if CONFIG_VP9_ENCODER
845 }
else if (strcmp(global->codec->name,
"vp9") == 0) {
846 ctrl_args = vp9_args;
847 ctrl_args_map = vp9_arg_ctrl_map;
851 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
857 if (eos_mark_found) {
860 }
else if (!strcmp(*argj,
"--")) {
865 if (arg_match(&arg, &outputfile, argi)) {
866 config->out_fn = arg.val;
867 }
else if (arg_match(&arg, &fpf_name, argi)) {
868 config->stats_fn = arg.val;
869 #if CONFIG_FP_MB_STATS
870 }
else if (arg_match(&arg, &fpmbf_name, argi)) {
871 config->fpmb_stats_fn = arg.val;
873 }
else if (arg_match(&arg, &use_webm, argi)) {
875 config->write_webm = 1;
877 die(
"Error: --webm specified but webm is disabled.");
879 }
else if (arg_match(&arg, &use_ivf, argi)) {
880 config->write_webm = 0;
881 }
else if (arg_match(&arg, &threads, argi)) {
882 config->cfg.g_threads = arg_parse_uint(&arg);
883 }
else if (arg_match(&arg, &profile, argi)) {
884 config->cfg.g_profile = arg_parse_uint(&arg);
885 }
else if (arg_match(&arg, &width, argi)) {
886 config->cfg.g_w = arg_parse_uint(&arg);
887 }
else if (arg_match(&arg, &height, argi)) {
888 config->cfg.g_h = arg_parse_uint(&arg);
889 #if CONFIG_VP9_HIGHBITDEPTH
890 }
else if (arg_match(&arg, &bitdeptharg, argi)) {
891 config->cfg.g_bit_depth = arg_parse_enum_or_int(&arg);
892 }
else if (arg_match(&arg, &inbitdeptharg, argi)) {
893 config->cfg.g_input_bit_depth = arg_parse_uint(&arg);
896 }
else if (arg_match(&arg, &stereo_mode, argi)) {
897 config->stereo_fmt = arg_parse_enum_or_int(&arg);
899 }
else if (arg_match(&arg, &timebase, argi)) {
900 config->cfg.g_timebase = arg_parse_rational(&arg);
901 validate_positive_rational(arg.name, &config->cfg.g_timebase);
902 }
else if (arg_match(&arg, &error_resilient, argi)) {
903 config->cfg.g_error_resilient = arg_parse_uint(&arg);
904 }
else if (arg_match(&arg, &end_usage, argi)) {
905 config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
906 }
else if (arg_match(&arg, &lag_in_frames, argi)) {
907 config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
909 config->cfg.rc_end_usage ==
VPX_CBR &&
910 config->cfg.g_lag_in_frames != 0) {
911 warn(
"non-zero %s option ignored in realtime CBR mode.\n", arg.name);
912 config->cfg.g_lag_in_frames = 0;
914 }
else if (arg_match(&arg, &dropframe_thresh, argi)) {
915 config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
916 }
else if (arg_match(&arg, &resize_allowed, argi)) {
917 config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
918 }
else if (arg_match(&arg, &resize_width, argi)) {
919 config->cfg.rc_scaled_width = arg_parse_uint(&arg);
920 }
else if (arg_match(&arg, &resize_height, argi)) {
921 config->cfg.rc_scaled_height = arg_parse_uint(&arg);
922 }
else if (arg_match(&arg, &resize_up_thresh, argi)) {
923 config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
924 }
else if (arg_match(&arg, &resize_down_thresh, argi)) {
925 config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
926 }
else if (arg_match(&arg, &end_usage, argi)) {
927 config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
928 }
else if (arg_match(&arg, &target_bitrate, argi)) {
929 config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
930 }
else if (arg_match(&arg, &min_quantizer, argi)) {
931 config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
932 }
else if (arg_match(&arg, &max_quantizer, argi)) {
933 config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
934 }
else if (arg_match(&arg, &undershoot_pct, argi)) {
935 config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
936 }
else if (arg_match(&arg, &overshoot_pct, argi)) {
937 config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
938 }
else if (arg_match(&arg, &buf_sz, argi)) {
939 config->cfg.rc_buf_sz = arg_parse_uint(&arg);
940 }
else if (arg_match(&arg, &buf_initial_sz, argi)) {
941 config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
942 }
else if (arg_match(&arg, &buf_optimal_sz, argi)) {
943 config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
944 }
else if (arg_match(&arg, &bias_pct, argi)) {
945 config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
946 if (global->passes < 2)
947 warn(
"option %s ignored in one-pass mode.\n", arg.name);
948 }
else if (arg_match(&arg, &minsection_pct, argi)) {
949 config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
951 if (global->passes < 2)
952 warn(
"option %s ignored in one-pass mode.\n", arg.name);
953 }
else if (arg_match(&arg, &maxsection_pct, argi)) {
954 config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
956 if (global->passes < 2)
957 warn(
"option %s ignored in one-pass mode.\n", arg.name);
958 }
else if (arg_match(&arg, &corpus_complexity, argi)) {
959 config->cfg.rc_2pass_vbr_corpus_complexity = arg_parse_uint(&arg);
961 if (global->passes < 2)
962 warn(
"option %s ignored in one-pass mode.\n", arg.name);
963 }
else if (arg_match(&arg, &kf_min_dist, argi)) {
964 config->cfg.kf_min_dist = arg_parse_uint(&arg);
965 }
else if (arg_match(&arg, &kf_max_dist, argi)) {
966 config->cfg.kf_max_dist = arg_parse_uint(&arg);
967 }
else if (arg_match(&arg, &kf_disabled, argi)) {
969 #if CONFIG_VP9_HIGHBITDEPTH
970 }
else if (arg_match(&arg, &test16bitinternalarg, argi)) {
971 if (strcmp(global->codec->name,
"vp9") == 0) {
972 test_16bit_internal = 1;
977 for (i = 0; ctrl_args[i]; i++) {
978 if (arg_match(&arg, ctrl_args[i], argi)) {
985 for (j = 0; j < config->arg_ctrl_cnt; j++)
986 if (ctrl_args_map != NULL &&
987 config->arg_ctrls[j][0] == ctrl_args_map[i])
991 assert(j < (
int)ARG_CTRL_CNT_MAX);
992 if (ctrl_args_map != NULL && j < (
int)ARG_CTRL_CNT_MAX) {
993 config->arg_ctrls[j][0] = ctrl_args_map[i];
994 config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
995 if (j == config->arg_ctrl_cnt) config->arg_ctrl_cnt++;
1002 #if CONFIG_VP9_HIGHBITDEPTH
1003 if (strcmp(global->codec->name,
"vp9") == 0) {
1004 config->use_16bit_internal =
1005 test_16bit_internal | (config->cfg.g_profile > 1);
1008 return eos_mark_found;
1011 #define FOREACH_STREAM(func) \
1013 struct stream_state *stream; \
1014 for (stream = streams; stream; stream = stream->next) { \
1019 static void validate_stream_config(
const struct stream_state *stream,
1020 const struct VpxEncoderConfig *global) {
1021 const struct stream_state *streami;
1024 if (!stream->config.cfg.g_w || !stream->config.cfg.g_h)
1026 "Stream %d: Specify stream dimensions with --width (-w) "
1027 " and --height (-h)",
1031 if (stream->config.cfg.g_input_bit_depth >
1032 (
unsigned int)stream->config.cfg.g_bit_depth) {
1033 fatal(
"Stream %d: codec bit depth (%d) less than input bit depth (%d)",
1034 stream->index, (
int)stream->config.cfg.g_bit_depth,
1035 stream->config.cfg.g_input_bit_depth);
1038 for (streami = stream; streami; streami = streami->next) {
1040 if (!streami->config.out_fn)
1041 fatal(
"Stream %d: Output file is required (specify with -o)",
1045 if (streami != stream) {
1046 const char *a = stream->config.out_fn;
1047 const char *b = streami->config.out_fn;
1048 if (!strcmp(a, b) && strcmp(a,
"/dev/null") && strcmp(a,
":nul"))
1049 fatal(
"Stream %d: duplicate output file (from stream %d)",
1050 streami->index, stream->index);
1054 if (streami != stream) {
1055 const char *a = stream->config.stats_fn;
1056 const char *b = streami->config.stats_fn;
1057 if (a && b && !strcmp(a, b))
1058 fatal(
"Stream %d: duplicate stats file (from stream %d)",
1059 streami->index, stream->index);
1062 #if CONFIG_FP_MB_STATS
1064 if (streami != stream) {
1065 const char *a = stream->config.fpmb_stats_fn;
1066 const char *b = streami->config.fpmb_stats_fn;
1067 if (a && b && !strcmp(a, b))
1068 fatal(
"Stream %d: duplicate mb stats file (from stream %d)",
1069 streami->index, stream->index);
1075 static void set_stream_dimensions(
struct stream_state *stream,
unsigned int w,
1077 if (!stream->config.cfg.g_w) {
1078 if (!stream->config.cfg.g_h)
1079 stream->config.cfg.g_w = w;
1081 stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
1083 if (!stream->config.cfg.g_h) {
1084 stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
1088 static const char *file_type_to_string(
enum VideoFileType t) {
1090 case FILE_TYPE_RAW:
return "RAW";
1091 case FILE_TYPE_Y4M:
return "Y4M";
1092 default:
return "Other";
1096 static const char *image_format_to_string(
vpx_img_fmt_t f) {
1107 default:
return "Other";
1111 static void show_stream_config(
struct stream_state *stream,
1112 struct VpxEncoderConfig *global,
1113 struct VpxInputContext *input) {
1114 #define SHOW(field) \
1115 fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field)
1117 if (stream->index == 0) {
1118 fprintf(stderr,
"Codec: %s\n",
1120 fprintf(stderr,
"Source file: %s File Type: %s Format: %s\n",
1121 input->filename, file_type_to_string(input->file_type),
1122 image_format_to_string(input->fmt));
1124 if (stream->next || stream->index)
1125 fprintf(stderr,
"\nStream Index: %d\n", stream->index);
1126 fprintf(stderr,
"Destination file: %s\n", stream->config.out_fn);
1127 fprintf(stderr,
"Encoder parameters:\n");
1135 SHOW(g_input_bit_depth);
1136 SHOW(g_timebase.num);
1137 SHOW(g_timebase.den);
1138 SHOW(g_error_resilient);
1140 SHOW(g_lag_in_frames);
1141 SHOW(rc_dropframe_thresh);
1142 SHOW(rc_resize_allowed);
1143 SHOW(rc_scaled_width);
1144 SHOW(rc_scaled_height);
1145 SHOW(rc_resize_up_thresh);
1146 SHOW(rc_resize_down_thresh);
1148 SHOW(rc_target_bitrate);
1149 SHOW(rc_min_quantizer);
1150 SHOW(rc_max_quantizer);
1151 SHOW(rc_undershoot_pct);
1152 SHOW(rc_overshoot_pct);
1154 SHOW(rc_buf_initial_sz);
1155 SHOW(rc_buf_optimal_sz);
1156 SHOW(rc_2pass_vbr_bias_pct);
1157 SHOW(rc_2pass_vbr_minsection_pct);
1158 SHOW(rc_2pass_vbr_maxsection_pct);
1159 SHOW(rc_2pass_vbr_corpus_complexity);
1165 static void open_output_file(
struct stream_state *stream,
1166 struct VpxEncoderConfig *global,
1167 const struct VpxRational *pixel_aspect_ratio) {
1168 const char *fn = stream->config.out_fn;
1173 stream->file = strcmp(fn,
"-") ? fopen(fn,
"wb") : set_binary_mode(stdout);
1175 if (!stream->file) fatal(
"Failed to open output file");
1177 if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
1178 fatal(
"WebM output to pipes not supported.");
1181 if (stream->config.write_webm) {
1182 stream->webm_ctx.stream = stream->file;
1183 write_webm_file_header(&stream->webm_ctx, cfg, stream->config.stereo_fmt,
1184 global->codec->fourcc, pixel_aspect_ratio);
1187 (void)pixel_aspect_ratio;
1190 if (!stream->config.write_webm) {
1191 ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0);
1195 static void close_output_file(
struct stream_state *stream,
1196 unsigned int fourcc) {
1202 if (stream->config.write_webm) {
1203 write_webm_file_footer(&stream->webm_ctx);
1207 if (!stream->config.write_webm) {
1208 if (!fseek(stream->file, 0, SEEK_SET))
1209 ivf_write_file_header(stream->file, &stream->config.cfg, fourcc,
1210 stream->frames_out);
1213 fclose(stream->file);
1216 static void setup_pass(
struct stream_state *stream,
1217 struct VpxEncoderConfig *global,
int pass) {
1218 if (stream->config.stats_fn) {
1219 if (!stats_open_file(&stream->stats, stream->config.stats_fn, pass))
1220 fatal(
"Failed to open statistics store");
1222 if (!stats_open_mem(&stream->stats, pass))
1223 fatal(
"Failed to open statistics store");
1226 #if CONFIG_FP_MB_STATS
1227 if (stream->config.fpmb_stats_fn) {
1228 if (!stats_open_file(&stream->fpmb_stats, stream->config.fpmb_stats_fn,
1230 fatal(
"Failed to open mb statistics store");
1232 if (!stats_open_mem(&stream->fpmb_stats, pass))
1233 fatal(
"Failed to open mb statistics store");
1237 stream->config.cfg.g_pass = global->passes == 2
1241 stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
1242 #if CONFIG_FP_MB_STATS
1243 stream->config.cfg.rc_firstpass_mb_stats_in =
1244 stats_get(&stream->fpmb_stats);
1248 stream->cx_time = 0;
1250 stream->frames_out = 0;
1253 static void initialize_encoder(
struct stream_state *stream,
1254 struct VpxEncoderConfig *global) {
1260 #if CONFIG_VP9_HIGHBITDEPTH
1266 &stream->config.cfg, flags);
1267 ctx_exit_on_error(&stream->encoder,
"Failed to initialize encoder");
1273 for (i = 0; i < stream->config.arg_ctrl_cnt; i++) {
1274 int ctrl = stream->config.arg_ctrls[i][0];
1275 int value = stream->config.arg_ctrls[i][1];
1277 fprintf(stderr,
"Error: Tried to set control %d = %d\n", ctrl, value);
1279 ctx_exit_on_error(&stream->encoder,
"Failed to control codec");
1283 if (global->test_decode != TEST_DECODE_OFF) {
1284 const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
1290 static void encode_frame(
struct stream_state *stream,
1291 struct VpxEncoderConfig *global,
struct vpx_image *img,
1292 unsigned int frames_in) {
1295 struct vpx_usec_timer timer;
1298 (cfg->
g_timebase.
den * (int64_t)(frames_in - 1) * global->framerate.den) /
1301 (cfg->
g_timebase.
den * (int64_t)(frames_in)*global->framerate.den) /
1305 #if CONFIG_VP9_HIGHBITDEPTH
1310 fprintf(stderr,
"%s can only scale 4:2:0 inputs\n", exec_name);
1327 stream->img->stride[
VPX_PLANE_V] / 2, stream->img->d_w,
1328 stream->img->d_h, kFilterBox);
1331 stream->encoder.err = 1;
1332 ctx_exit_on_error(&stream->encoder,
1333 "Stream %d: Failed to encode frame.\n"
1334 "Scaling disabled in this configuration. \n"
1335 "To enable, configure with --enable-libyuv\n",
1341 if (img && (img->
d_w != cfg->
g_w || img->
d_h != cfg->
g_h)) {
1343 fprintf(stderr,
"%s can only scale 4:2:0 8bpp inputs\n", exec_name);
1357 stream->img->d_w, stream->img->d_h, kFilterBox);
1360 stream->encoder.err = 1;
1361 ctx_exit_on_error(&stream->encoder,
1362 "Stream %d: Failed to encode frame.\n"
1363 "Scaling disabled in this configuration. \n"
1364 "To enable, configure with --enable-libyuv\n",
1369 vpx_usec_timer_start(&timer);
1371 (
unsigned long)(next_frame_start - frame_start), 0,
1373 vpx_usec_timer_mark(&timer);
1374 stream->cx_time += vpx_usec_timer_elapsed(&timer);
1375 ctx_exit_on_error(&stream->encoder,
"Stream %d: Failed to encode frame",
1379 static void update_quantizer_histogram(
struct stream_state *stream) {
1384 ctx_exit_on_error(&stream->encoder,
"Failed to read quantizer");
1385 stream->counts[q]++;
1389 static void get_cx_data(
struct stream_state *stream,
1390 struct VpxEncoderConfig *global,
int *got_data) {
1397 static size_t fsize = 0;
1398 static FileOffset ivf_header_pos = 0;
1400 switch (pkt->
kind) {
1403 stream->frames_out++;
1406 fprintf(stderr,
" %6luF", (
unsigned long)pkt->
data.
frame.sz);
1408 update_rate_histogram(stream->rate_hist, cfg, pkt);
1410 if (stream->config.write_webm) {
1411 write_webm_block(&stream->webm_ctx, cfg, pkt);
1414 if (!stream->config.write_webm) {
1415 if (pkt->
data.
frame.partition_id <= 0) {
1416 ivf_header_pos = ftello(stream->file);
1419 ivf_write_frame_header(stream->file, pkt->
data.
frame.pts, fsize);
1424 const FileOffset currpos = ftello(stream->file);
1425 fseeko(stream->file, ivf_header_pos, SEEK_SET);
1426 ivf_write_frame_size(stream->file, fsize);
1427 fseeko(stream->file, currpos, SEEK_SET);
1438 if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
1440 (
unsigned int)pkt->
data.
frame.sz, NULL, 0);
1441 if (stream->decoder.err) {
1442 warn_or_exit_on_error(&stream->decoder,
1443 global->test_decode == TEST_DECODE_FATAL,
1444 "Failed to decode frame %d in stream %d",
1445 stream->frames_out + 1, stream->index);
1446 stream->mismatch_seen = stream->frames_out + 1;
1452 stream->frames_out++;
1457 #if CONFIG_FP_MB_STATS
1466 if (global->show_psnr) {
1469 stream->psnr_sse_total += pkt->
data.
psnr.sse[0];
1470 stream->psnr_samples_total += pkt->
data.
psnr.samples[0];
1471 for (i = 0; i < 4; i++) {
1473 fprintf(stderr,
"%.3f ", pkt->
data.
psnr.psnr[i]);
1474 stream->psnr_totals[i] += pkt->
data.
psnr.psnr[i];
1476 stream->psnr_count++;
1485 static void show_psnr(
struct stream_state *stream,
double peak) {
1489 if (!stream->psnr_count)
return;
1491 fprintf(stderr,
"Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
1492 ovpsnr = sse_to_psnr((
double)stream->psnr_samples_total, peak,
1493 (
double)stream->psnr_sse_total);
1494 fprintf(stderr,
" %.3f", ovpsnr);
1496 for (i = 0; i < 4; i++) {
1497 fprintf(stderr,
" %.3f", stream->psnr_totals[i] / stream->psnr_count);
1499 fprintf(stderr,
"\n");
1502 static float usec_to_fps(uint64_t usec,
unsigned int frames) {
1503 return (
float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
1506 static void test_decode(
struct stream_state *stream,
1507 enum TestDecodeFatality fatal,
1508 const VpxInterface *codec) {
1511 if (stream->mismatch_seen)
return;
1514 if (strcmp(codec->name,
"vp8") == 0) {
1518 width = (stream->config.cfg.g_w + 15) & ~15;
1519 height = (stream->config.cfg.g_h + 15) & ~15;
1521 enc_img = ref_enc.img;
1523 dec_img = ref_dec.img;
1525 ref_enc.frame_type = VP8_LAST_FRAME;
1526 ref_dec.frame_type = VP8_LAST_FRAME;
1535 enc_img = ref_enc.img;
1537 dec_img = ref_dec.img;
1538 #if CONFIG_VP9_HIGHBITDEPTH
1543 enc_img.
d_w, enc_img.
d_h, 16);
1544 vpx_img_truncate_16_to_8(&enc_img, &ref_enc.img);
1548 dec_img.
d_w, dec_img.
d_h, 16);
1549 vpx_img_truncate_16_to_8(&dec_img, &ref_dec.img);
1554 ctx_exit_on_error(&stream->encoder,
"Failed to get encoder reference frame");
1555 ctx_exit_on_error(&stream->decoder,
"Failed to get decoder reference frame");
1557 if (!compare_img(&enc_img, &dec_img)) {
1558 int y[4], u[4], v[4];
1559 #if CONFIG_VP9_HIGHBITDEPTH
1561 find_mismatch_high(&enc_img, &dec_img, y, u, v);
1563 find_mismatch(&enc_img, &dec_img, y, u, v);
1566 find_mismatch(&enc_img, &dec_img, y, u, v);
1568 stream->decoder.err = 1;
1569 warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
1570 "Stream %d: Encode/decode mismatch on frame %d at"
1571 " Y[%d, %d] {%d/%d},"
1572 " U[%d, %d] {%d/%d},"
1573 " V[%d, %d] {%d/%d}",
1574 stream->index, stream->frames_out, y[0], y[1], y[2],
1575 y[3], u[0], u[1], u[2], u[3], v[0], v[1], v[2], v[3]);
1576 stream->mismatch_seen = stream->frames_out;
1583 static void print_time(
const char *label, int64_t etl) {
1590 etl -= hours * 3600;
1595 fprintf(stderr,
"[%3s %2" PRId64
":%02" PRId64
":%02" PRId64
"] ", label,
1598 fprintf(stderr,
"[%3s unknown] ", label);
1602 int main(
int argc,
const char **argv_) {
1605 #if CONFIG_VP9_HIGHBITDEPTH
1607 int allocated_raw_shift = 0;
1608 int use_16bit_internal = 0;
1609 int input_shift = 0;
1611 int frame_avail, got_data;
1613 struct VpxInputContext input;
1614 struct VpxEncoderConfig global;
1615 struct stream_state *streams = NULL;
1616 char **argv, **argi;
1617 uint64_t cx_time = 0;
1621 memset(&input, 0,
sizeof(input));
1622 exec_name = argv_[0];
1625 input.framerate.numerator = 30;
1626 input.framerate.denominator = 1;
1627 input.only_i420 = 1;
1628 input.bit_depth = 0;
1634 argv = argv_dup(argc - 1, argv_ + 1);
1635 parse_global_config(&global, argv);
1637 if (argc < 3) usage_exit();
1639 switch (global.color_type) {
1652 struct stream_state *stream = NULL;
1655 stream = new_stream(&global, stream);
1657 if (!streams) streams = stream;
1658 }
while (parse_stream_params(&global, stream, argv));
1662 for (argi = argv; *argi; argi++)
1663 if (argi[0][0] ==
'-' && argi[0][1])
1664 die(
"Error: Unrecognized option %s\n", *argi);
1666 FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt, &global,
1667 &stream->config.cfg););
1670 input.filename = argv[0];
1672 if (!input.filename) {
1673 fprintf(stderr,
"No input file specified!\n");
1678 if (global.codec->fourcc == VP9_FOURCC) input.only_i420 = 0;
1680 for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
1681 int frames_in = 0, seen_frames = 0;
1682 int64_t estimated_time_left = -1;
1683 int64_t average_rate = -1;
1684 int64_t lagged_count = 0;
1686 open_input_file(&input);
1691 if (!input.width || !input.height) {
1693 if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
1694 input.width = stream->config.cfg.g_w;
1695 input.height = stream->config.cfg.g_h;
1702 if (!input.width || !input.height)
1704 "Specify stream dimensions with --width (-w) "
1705 " and --height (-h)");
1712 if (!input.bit_depth) {
1714 if (stream->config.cfg.g_input_bit_depth)
1715 input.bit_depth = stream->config.cfg.g_input_bit_depth;
1717 input.bit_depth = stream->config.cfg.g_input_bit_depth =
1718 (
int)stream->config.cfg.g_bit_depth;
1723 { stream->config.cfg.g_input_bit_depth = input.bit_depth; });
1726 FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
1727 FOREACH_STREAM(validate_stream_config(stream, &global));
1732 if (global.pass && global.passes == 2)
1734 if (!stream->config.stats_fn)
1735 die(
"Stream %d: Must specify --fpf when --pass=%d"
1736 " and --passes=2\n",
1737 stream->index, global.pass);
1742 if (stream->config.write_webm) {
1743 stream->config.write_webm = 0;
1745 "vpxenc was compiled without WebM container support."
1746 "Producing IVF output");
1754 if (!global.have_framerate) {
1755 global.framerate.num = input.framerate.numerator;
1756 global.framerate.den = input.framerate.denominator;
1757 FOREACH_STREAM(stream->config.cfg.g_timebase.den = global.framerate.num;
1758 stream->config.cfg.g_timebase.num = global.framerate.den);
1762 if (global.verbose && pass == 0)
1763 FOREACH_STREAM(show_stream_config(stream, &global, &input));
1765 if (pass == (global.pass ? global.pass - 1 : 0)) {
1766 if (input.file_type == FILE_TYPE_Y4M)
1770 memset(&raw, 0,
sizeof(raw));
1772 vpx_img_alloc(&raw, input.fmt, input.width, input.height, 32);
1774 FOREACH_STREAM(stream->rate_hist = init_rate_histogram(
1775 &stream->config.cfg, &global.framerate));
1778 FOREACH_STREAM(setup_pass(stream, &global, pass));
1780 open_output_file(stream, &global, &input.pixel_aspect_ratio));
1781 FOREACH_STREAM(initialize_encoder(stream, &global));
1783 #if CONFIG_VP9_HIGHBITDEPTH
1784 if (strcmp(global.codec->name,
"vp9") == 0) {
1789 if (stream->config.use_16bit_internal) {
1790 use_16bit_internal = 1;
1792 if (stream->config.cfg.g_profile == 0) {
1795 input_shift = (int)stream->config.cfg.g_bit_depth -
1796 stream->config.cfg.g_input_bit_depth;
1805 while (frame_avail || got_data) {
1806 struct vpx_usec_timer timer;
1808 if (!global.limit || frames_in < global.limit) {
1809 frame_avail = read_frame(&input, &raw);
1811 if (frame_avail) frames_in++;
1813 frames_in > global.skip_frames ? frames_in - global.skip_frames : 0;
1815 if (!global.quiet) {
1816 float fps = usec_to_fps(cx_time, seen_frames);
1817 fprintf(stderr,
"\rPass %d/%d ", pass + 1, global.passes);
1819 if (stream_cnt == 1)
1820 fprintf(stderr,
"frame %4d/%-4d %7" PRId64
"B ", frames_in,
1821 streams->frames_out, (int64_t)streams->nbytes);
1823 fprintf(stderr,
"frame %4d ", frames_in);
1825 fprintf(stderr,
"%7" PRId64
" %s %.2f %s ",
1826 cx_time > 9999999 ? cx_time / 1000 : cx_time,
1827 cx_time > 9999999 ?
"ms" :
"us", fps >= 1.0 ? fps : fps * 60,
1828 fps >= 1.0 ?
"fps" :
"fpm");
1829 print_time(
"ETA", estimated_time_left);
1835 if (frames_in > global.skip_frames) {
1836 #if CONFIG_VP9_HIGHBITDEPTH
1838 if (input_shift || (use_16bit_internal && input.bit_depth == 8)) {
1839 assert(use_16bit_internal);
1842 if (!allocated_raw_shift) {
1844 input.width, input.height, 32);
1845 allocated_raw_shift = 1;
1847 vpx_img_upshift(&raw_shift, &raw, input_shift);
1848 frame_to_encode = &raw_shift;
1850 frame_to_encode = &raw;
1852 vpx_usec_timer_start(&timer);
1853 if (use_16bit_internal) {
1856 if (stream->config.use_16bit_internal)
1857 encode_frame(stream, &global,
1858 frame_avail ? frame_to_encode : NULL, frames_in);
1864 FOREACH_STREAM(encode_frame(stream, &global,
1865 frame_avail ? frame_to_encode : NULL,
1869 vpx_usec_timer_start(&timer);
1870 FOREACH_STREAM(encode_frame(stream, &global, frame_avail ? &raw : NULL,
1873 vpx_usec_timer_mark(&timer);
1874 cx_time += vpx_usec_timer_elapsed(&timer);
1876 FOREACH_STREAM(update_quantizer_histogram(stream));
1879 FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
1881 if (!got_data && input.length && streams != NULL &&
1882 !streams->frames_out) {
1883 lagged_count = global.limit ? seen_frames : ftello(input.file);
1884 }
else if (input.length) {
1889 const int64_t frame_in_lagged = (seen_frames - lagged_count) * 1000;
1891 rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
1892 remaining = 1000 * (global.limit - global.skip_frames -
1893 seen_frames + lagged_count);
1895 const int64_t input_pos = ftello(input.file);
1896 const int64_t input_pos_lagged = input_pos - lagged_count;
1897 const int64_t limit = input.length;
1899 rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0;
1900 remaining = limit - input_pos + lagged_count;
1904 (average_rate <= 0) ? rate : (average_rate * 7 + rate) / 8;
1905 estimated_time_left = average_rate ? remaining / average_rate : -1;
1908 if (got_data && global.test_decode != TEST_DECODE_OFF)
1909 FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec));
1913 if (!global.quiet) fprintf(stderr,
"\033[K");
1916 if (stream_cnt > 1) fprintf(stderr,
"\n");
1918 if (!global.quiet) {
1919 FOREACH_STREAM(fprintf(
1921 "\rPass %d/%d frame %4d/%-4d %7" PRId64
"B %7" PRId64
"b/f %7" PRId64
1922 "b/s %7" PRId64
" %s (%.2f fps)\033[K\n",
1923 pass + 1, global.passes, frames_in, stream->frames_out,
1924 (int64_t)stream->nbytes,
1925 seen_frames ? (int64_t)(stream->nbytes * 8 / seen_frames) : 0,
1927 ? (int64_t)stream->nbytes * 8 * (int64_t)global.framerate.num /
1928 global.framerate.den / seen_frames
1930 stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
1931 stream->cx_time > 9999999 ?
"ms" :
"us",
1932 usec_to_fps(stream->cx_time, seen_frames)));
1935 if (global.show_psnr) {
1936 if (global.codec->fourcc == VP9_FOURCC) {
1938 show_psnr(stream, (1 << stream->config.cfg.g_input_bit_depth) - 1));
1940 FOREACH_STREAM(show_psnr(stream, 255.0));
1946 if (global.test_decode != TEST_DECODE_OFF) {
1950 close_input_file(&input);
1952 if (global.test_decode == TEST_DECODE_FATAL) {
1953 FOREACH_STREAM(res |= stream->mismatch_seen);
1955 FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
1957 FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1));
1959 #if CONFIG_FP_MB_STATS
1960 FOREACH_STREAM(stats_close(&stream->fpmb_stats, global.passes - 1));
1963 if (global.pass)
break;
1966 if (global.show_q_hist_buckets)
1968 show_q_histogram(stream->counts, global.show_q_hist_buckets));
1970 if (global.show_rate_hist_buckets)
1971 FOREACH_STREAM(show_rate_histogram(stream->rate_hist, &stream->config.cfg,
1972 global.show_rate_hist_buckets));
1973 FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist));
1975 #if CONFIG_INTERNAL_STATS
1979 if (!(global.pass == 1 && global.passes == 2))
1981 FILE *f = fopen(
"opsnr.stt",
"a");
1982 if (stream->mismatch_seen) {
1983 fprintf(f,
"First mismatch occurred in frame %d\n",
1984 stream->mismatch_seen);
1986 fprintf(f,
"No mismatch detected in recon buffers\n");
1992 #if CONFIG_VP9_HIGHBITDEPTH
1998 return res ? EXIT_FAILURE : EXIT_SUCCESS;
const char * vpx_codec_error_detail(vpx_codec_ctx_t *ctx)
Retrieve detailed error information for codec context.
const char * vpx_codec_error(vpx_codec_ctx_t *ctx)
Retrieve error synopsis 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.
const char * vpx_codec_err_to_string(vpx_codec_err_t err)
Convert error number to printable string.
#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
vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx, int ctrl_id,...)
Control algorithm.
@ VPX_BITS_8
Definition: vpx_codec.h:218
@ VPX_BITS_12
Definition: vpx_codec.h:220
@ VPX_BITS_10
Definition: vpx_codec.h:219
vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline)
Decode data.
#define vpx_codec_dec_init(ctx, iface, cfg, flags)
Convenience macro for vpx_codec_dec_init_ver()
Definition: vpx_decoder.h:144
#define VPX_DL_REALTIME
deadline parameter analogous to VPx REALTIME mode.
Definition: vpx_encoder.h:830
#define vpx_codec_enc_init(ctx, iface, cfg, flags)
Convenience macro for vpx_codec_enc_init_ver()
Definition: vpx_encoder.h:741
#define VPX_CODEC_USE_PSNR
Initialization-time Feature Enabling.
Definition: vpx_encoder.h:87
#define VPX_DL_GOOD_QUALITY
deadline parameter analogous to VPx GOOD QUALITY mode.
Definition: vpx_encoder.h:832
#define VPX_CODEC_USE_HIGHBITDEPTH
Definition: vpx_encoder.h:90
int64_t vpx_codec_pts_t
Time Stamp Type.
Definition: vpx_encoder.h:106
vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface, vpx_codec_enc_cfg_t *cfg, unsigned int usage)
Get a default configuration.
#define VPX_DL_BEST_QUALITY
deadline parameter analogous to VPx BEST QUALITY mode.
Definition: vpx_encoder.h:834
#define VPX_CODEC_USE_OUTPUT_PARTITION
Make the encoder output one partition at a time.
Definition: vpx_encoder.h:89
const vpx_codec_cx_pkt_t * vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter)
Encoded data iterator.
vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx, const vpx_image_t *img, vpx_codec_pts_t pts, unsigned long duration, vpx_enc_frame_flags_t flags, unsigned long deadline)
Encode a frame.
#define VPX_FRAME_IS_FRAGMENT
this is a fragment of the encoded frame
Definition: vpx_encoder.h:123
@ VPX_CODEC_PSNR_PKT
Definition: vpx_encoder.h:150
@ VPX_CODEC_CX_FRAME_PKT
Definition: vpx_encoder.h:147
@ VPX_CODEC_STATS_PKT
Definition: vpx_encoder.h:148
@ VPX_CODEC_FPMB_STATS_PKT
Definition: vpx_encoder.h:149
@ VPX_RC_LAST_PASS
Definition: vpx_encoder.h:227
@ VPX_RC_ONE_PASS
Definition: vpx_encoder.h:225
@ VPX_RC_FIRST_PASS
Definition: vpx_encoder.h:226
@ VPX_KF_DISABLED
Definition: vpx_encoder.h:249
@ VPX_Q
Definition: vpx_encoder.h:235
@ VPX_CQ
Definition: vpx_encoder.h:234
@ VPX_CBR
Definition: vpx_encoder.h:233
@ VPX_VBR
Definition: vpx_encoder.h:232
@ VP9E_SET_MIN_GF_INTERVAL
Codec control function to set minimum interval between GF/ARF frames.
Definition: vp8cx.h:514
@ VP9E_SET_MAX_INTER_BITRATE_PCT
Codec control function to set max data rate for Inter frames.
Definition: vp8cx.h:278
@ VP9E_SET_FRAME_PERIODIC_BOOST
Codec control function to enable/disable periodic Q boost.
Definition: vp8cx.h:413
@ VP8E_SET_MAX_INTRA_BITRATE_PCT
Codec control function to set Max data rate for Intra frames.
Definition: vp8cx.h:257
@ VP8E_SET_ARNR_STRENGTH
Codec control function to set the filter strength for the arf.
Definition: vp8cx.h:223
@ VP8E_SET_TUNING
Codec control function to set visual tuning.
Definition: vp8cx.h:232
@ VP8E_SET_ENABLEAUTOALTREF
Codec control function to enable automatic use of arf frames.
Definition: vp8cx.h:164
@ VP9E_SET_TARGET_LEVEL
Codec control function to set target level.
Definition: vp8cx.h:562
@ VP9E_SET_AQ_MODE
Codec control function to set adaptive quantization mode.
Definition: vp8cx.h:398
@ VP8E_SET_NOISE_SENSITIVITY
control function to set noise sensitivity
Definition: vp8cx.h:173
@ VP8E_SET_TOKEN_PARTITIONS
Codec control function to set the number of token partitions.
Definition: vp8cx.h:194
@ VP8E_SET_ARNR_TYPE
Definition: vp8cx.h:226
@ VP9E_SET_TILE_ROWS
Codec control function to set number of tile rows.
Definition: vp8cx.h:371
@ VP8E_SET_ARNR_MAXFRAMES
Codec control function to set the max no of frames to create arf.
Definition: vp8cx.h:217
@ VP9E_SET_LOSSLESS
Codec control function to set lossless encoding mode.
Definition: vp8cx.h:327
@ VP9E_SET_FRAME_PARALLEL_DECODING
Codec control function to enable frame parallel decoding feature.
Definition: vp8cx.h:385
@ VP8E_SET_SHARPNESS
Codec control function to set higher sharpness at the expense of a lower PSNR.
Definition: vp8cx.h:182
@ VP8E_SET_GF_CBR_BOOST_PCT
Boost percentage for Golden Frame in CBR mode.
Definition: vp8cx.h:601
@ VP9E_SET_TUNE_CONTENT
Codec control function to set content type.
Definition: vp8cx.h:463
@ VP9E_SET_TPL
Codec control function to enable temporal dependency model.
Definition: vp8cx.h:668
@ VP9E_SET_ROW_MT
Codec control function to set row level multi-threading.
Definition: vp8cx.h:570
@ VP8E_SET_CPUUSED
Codec control function to set encoder internal speed settings.
Definition: vp8cx.h:155
@ VP9E_SET_TILE_COLUMNS
Codec control function to set number of tile columns.
Definition: vp8cx.h:351
@ VP8E_SET_STATIC_THRESHOLD
Codec control function to set the threshold for MBs treated static.
Definition: vp8cx.h:188
@ VP9E_SET_COLOR_SPACE
Codec control function to set color space info.
Definition: vp8cx.h:494
@ VP8E_SET_SCREEN_CONTENT_MODE
Codec control function to set encoder screen content mode.
Definition: vp8cx.h:312
@ VP8E_SET_CQ_LEVEL
Codec control function to set constrained quality level.
Definition: vp8cx.h:242
@ VP9E_SET_NOISE_SENSITIVITY
Codec control function to set noise sensitivity.
Definition: vp8cx.h:421
@ VP8E_GET_LAST_QUANTIZER_64
Codec control function to get last quantizer chosen by the encoder.
Definition: vp8cx.h:211
@ VP9E_SET_GF_CBR_BOOST_PCT
Boost percentage for Golden Frame in CBR mode.
Definition: vp8cx.h:293
@ VP9E_SET_MAX_GF_INTERVAL
Codec control function to set minimum interval between GF/ARF frames.
Definition: vp8cx.h:522
@ VP9E_SET_ALT_REF_AQ
Codec control function to enable/disable special mode for altref adaptive quantization....
Definition: vp8cx.h:586
@ VP8_COPY_REFERENCE
Definition: vp8.h:48
@ VP9_GET_REFERENCE
Definition: vp8.h:55
VP9 specific reference frame data struct.
Definition: vp8.h:110
int idx
Definition: vp8.h:111
Codec context structure.
Definition: vpx_codec.h:197
vpx_codec_err_t err
Definition: vpx_codec.h:200
Encoder output packet.
Definition: vpx_encoder.h:159
vpx_fixed_buf_t twopass_stats
Definition: vpx_encoder.h:182
enum vpx_codec_cx_pkt_kind kind
Definition: vpx_encoder.h:160
double psnr[4]
Definition: vpx_encoder.h:187
struct vpx_codec_cx_pkt::@1::@2 frame
vpx_fixed_buf_t firstpass_mb_stats
Definition: vpx_encoder.h:183
vpx_fixed_buf_t raw
Definition: vpx_encoder.h:189
union vpx_codec_cx_pkt::@1 data
Encoder configuration structure.
Definition: vpx_encoder.h:268
unsigned int g_h
Height of the frame.
Definition: vpx_encoder.h:313
unsigned int g_w
Width of the frame.
Definition: vpx_encoder.h:304
struct vpx_rational g_timebase
Stream timebase units.
Definition: vpx_encoder.h:343
enum vpx_enc_pass g_pass
Multi-pass Encoding Mode.
Definition: vpx_encoder.h:358
size_t sz
Definition: vpx_encoder.h:98
void * buf
Definition: vpx_encoder.h:97
Image Descriptor.
Definition: vpx_image.h:71
vpx_img_fmt_t fmt
Definition: vpx_image.h:72
unsigned int d_h
Definition: vpx_image.h:83
unsigned int d_w
Definition: vpx_image.h:82
unsigned char * planes[4]
Definition: vpx_image.h:99
int stride[4]
Definition: vpx_image.h:100
Rational Number.
Definition: vpx_encoder.h:218
int den
Definition: vpx_encoder.h:220
int num
Definition: vpx_encoder.h:219
reference frame data struct
Definition: vp8.h:101
Provides definitions for using VP8 or VP9 encoder algorithm within the vpx Codec Interface.
Provides definitions for using VP8 or VP9 within the vpx Decoder interface.
Describes the decoder algorithm interface to applications.
Describes the encoder algorithm interface to applications.
@ VPX_CS_BT_709
Definition: vpx_image.h:56
@ VPX_CS_SRGB
Definition: vpx_image.h:61
@ VPX_CS_BT_601
Definition: vpx_image.h:55
@ VPX_CS_BT_2020
Definition: vpx_image.h:59
@ VPX_CS_SMPTE_170
Definition: vpx_image.h:57
@ VPX_CS_UNKNOWN
Definition: vpx_image.h:54
@ VPX_CS_SMPTE_240
Definition: vpx_image.h:58
@ VPX_CS_RESERVED
Definition: vpx_image.h:60
#define VPX_PLANE_Y
Definition: vpx_image.h:95
#define VPX_IMG_FMT_HIGHBITDEPTH
Definition: vpx_image.h:35
#define VPX_PLANE_U
Definition: vpx_image.h:96
@ VPX_IMG_FMT_I42216
Definition: vpx_image.h:47
@ VPX_IMG_FMT_I44016
Definition: vpx_image.h:49
@ VPX_IMG_FMT_YV12
Definition: vpx_image.h:40
@ VPX_IMG_FMT_I42016
Definition: vpx_image.h:46
@ VPX_IMG_FMT_I444
Definition: vpx_image.h:44
@ VPX_IMG_FMT_I440
Definition: vpx_image.h:45
@ VPX_IMG_FMT_I44416
Definition: vpx_image.h:48
@ VPX_IMG_FMT_I420
Definition: vpx_image.h:42
@ VPX_IMG_FMT_I422
Definition: vpx_image.h:43
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_PLANE_V
Definition: vpx_image.h:97
enum vpx_img_fmt vpx_img_fmt_t
List of supported image formats.
void vpx_img_free(vpx_image_t *img)
Close an image descriptor.