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_nv12 =
99 ARG_DEF(NULL,
"nv12", 0,
"Input file is NV12 ");
100 static const arg_def_t use_yv12 =
101 ARG_DEF(NULL,
"yv12", 0,
"Input file is YV12 ");
102 static const arg_def_t use_i420 =
103 ARG_DEF(NULL,
"i420", 0,
"Input file is I420 (default)");
104 static const arg_def_t use_i422 =
105 ARG_DEF(NULL,
"i422", 0,
"Input file is I422");
106 static const arg_def_t use_i444 =
107 ARG_DEF(NULL,
"i444", 0,
"Input file is I444");
108 static const arg_def_t use_i440 =
109 ARG_DEF(NULL,
"i440", 0,
"Input file is I440");
110 static const arg_def_t codecarg = ARG_DEF(NULL,
"codec", 1,
"Codec to use");
111 static const arg_def_t passes =
112 ARG_DEF(
"p",
"passes", 1,
"Number of passes (1/2)");
113 static const arg_def_t pass_arg =
114 ARG_DEF(NULL,
"pass", 1,
"Pass to execute (1/2)");
115 static const arg_def_t fpf_name =
116 ARG_DEF(NULL,
"fpf", 1,
"First pass statistics file name");
117 #if CONFIG_FP_MB_STATS
118 static const arg_def_t fpmbf_name =
119 ARG_DEF(NULL,
"fpmbf", 1,
"First pass block statistics file name");
121 static const arg_def_t limit =
122 ARG_DEF(NULL,
"limit", 1,
"Stop encoding after n input frames");
123 static const arg_def_t skip =
124 ARG_DEF(NULL,
"skip", 1,
"Skip the first n input frames");
125 static const arg_def_t deadline =
126 ARG_DEF(
"d",
"deadline", 1,
"Deadline per frame (usec)");
127 static const arg_def_t best_dl =
128 ARG_DEF(NULL,
"best", 0,
"Use Best Quality Deadline");
129 static const arg_def_t good_dl =
130 ARG_DEF(NULL,
"good", 0,
"Use Good Quality Deadline");
131 static const arg_def_t rt_dl =
132 ARG_DEF(NULL,
"rt", 0,
"Use Realtime Quality Deadline");
133 static const arg_def_t quietarg =
134 ARG_DEF(
"q",
"quiet", 0,
"Do not print encode progress");
135 static const arg_def_t verbosearg =
136 ARG_DEF(
"v",
"verbose", 0,
"Show encoder parameters");
137 static const arg_def_t psnrarg =
138 ARG_DEF(NULL,
"psnr", 0,
"Show PSNR in status line");
140 static const struct arg_enum_list test_decode_enum[] = {
141 {
"off", TEST_DECODE_OFF },
142 {
"fatal", TEST_DECODE_FATAL },
143 {
"warn", TEST_DECODE_WARN },
146 static const arg_def_t recontest = ARG_DEF_ENUM(
147 NULL,
"test-decode", 1,
"Test encode/decode mismatch", test_decode_enum);
148 static const arg_def_t framerate =
149 ARG_DEF(NULL,
"fps", 1,
"Stream frame rate (rate/scale)");
150 static const arg_def_t use_webm =
151 ARG_DEF(NULL,
"webm", 0,
"Output WebM (default when WebM IO is enabled)");
152 static const arg_def_t use_ivf = ARG_DEF(NULL,
"ivf", 0,
"Output IVF");
153 static const arg_def_t out_part =
154 ARG_DEF(
"P",
"output-partitions", 0,
155 "Makes encoder output partitions. Requires IVF output!");
156 static const arg_def_t q_hist_n =
157 ARG_DEF(NULL,
"q-hist", 1,
"Show quantizer histogram (n-buckets)");
158 static const arg_def_t rate_hist_n =
159 ARG_DEF(NULL,
"rate-hist", 1,
"Show rate histogram (n-buckets)");
160 static const arg_def_t disable_warnings =
161 ARG_DEF(NULL,
"disable-warnings", 0,
162 "Disable warnings about potentially incorrect encode settings.");
163 static const arg_def_t disable_warning_prompt =
164 ARG_DEF(
"y",
"disable-warning-prompt", 0,
165 "Display warnings, but do not prompt user to continue.");
167 #if CONFIG_VP9_HIGHBITDEPTH
168 static const arg_def_t test16bitinternalarg = ARG_DEF(
169 NULL,
"test-16bit-internal", 0,
"Force use of 16 bit internal buffer");
172 static const arg_def_t *main_args[] = { &help,
194 &disable_warning_prompt,
198 static const arg_def_t usage =
199 ARG_DEF(
"u",
"usage", 1,
"Usage profile number to use");
200 static const arg_def_t threads =
201 ARG_DEF(
"t",
"threads", 1,
"Max number of threads to use");
202 static const arg_def_t profile =
203 ARG_DEF(NULL,
"profile", 1,
"Bitstream profile number to use");
204 static const arg_def_t width = ARG_DEF(
"w",
"width", 1,
"Frame width");
205 static const arg_def_t height = ARG_DEF(
"h",
"height", 1,
"Frame height");
207 static const struct arg_enum_list stereo_mode_enum[] = {
208 {
"mono", STEREO_FORMAT_MONO },
209 {
"left-right", STEREO_FORMAT_LEFT_RIGHT },
210 {
"bottom-top", STEREO_FORMAT_BOTTOM_TOP },
211 {
"top-bottom", STEREO_FORMAT_TOP_BOTTOM },
212 {
"right-left", STEREO_FORMAT_RIGHT_LEFT },
215 static const arg_def_t stereo_mode = ARG_DEF_ENUM(
216 NULL,
"stereo-mode", 1,
"Stereo 3D video format", stereo_mode_enum);
218 static const arg_def_t timebase = ARG_DEF(
219 NULL,
"timebase", 1,
"Output timestamp precision (fractional seconds)");
220 static const arg_def_t error_resilient =
221 ARG_DEF(NULL,
"error-resilient", 1,
"Enable error resiliency features");
222 static const arg_def_t lag_in_frames =
223 ARG_DEF(NULL,
"lag-in-frames", 1,
"Max number of frames to lag");
225 static const arg_def_t *global_args[] = { &use_nv12,
242 #if CONFIG_VP9_HIGHBITDEPTH
243 &test16bitinternalarg,
248 static const arg_def_t dropframe_thresh =
249 ARG_DEF(NULL,
"drop-frame", 1,
"Temporal resampling threshold (buf %)");
250 static const arg_def_t resize_allowed =
251 ARG_DEF(NULL,
"resize-allowed", 1,
"Spatial resampling enabled (bool)");
252 static const arg_def_t resize_width =
253 ARG_DEF(NULL,
"resize-width", 1,
"Width of encoded frame");
254 static const arg_def_t resize_height =
255 ARG_DEF(NULL,
"resize-height", 1,
"Height of encoded frame");
256 static const arg_def_t resize_up_thresh =
257 ARG_DEF(NULL,
"resize-up", 1,
"Upscale threshold (buf %)");
258 static const arg_def_t resize_down_thresh =
259 ARG_DEF(NULL,
"resize-down", 1,
"Downscale threshold (buf %)");
260 static const struct arg_enum_list end_usage_enum[] = { {
"vbr",
VPX_VBR },
265 static const arg_def_t end_usage =
266 ARG_DEF_ENUM(NULL,
"end-usage", 1,
"Rate control mode", end_usage_enum);
267 static const arg_def_t target_bitrate =
268 ARG_DEF(NULL,
"target-bitrate", 1,
"Bitrate (kbps)");
269 static const arg_def_t min_quantizer =
270 ARG_DEF(NULL,
"min-q", 1,
"Minimum (best) quantizer");
271 static const arg_def_t max_quantizer =
272 ARG_DEF(NULL,
"max-q", 1,
"Maximum (worst) quantizer");
273 static const arg_def_t undershoot_pct =
274 ARG_DEF(NULL,
"undershoot-pct", 1,
"Datarate undershoot (min) target (%)");
275 static const arg_def_t overshoot_pct =
276 ARG_DEF(NULL,
"overshoot-pct", 1,
"Datarate overshoot (max) target (%)");
277 static const arg_def_t buf_sz =
278 ARG_DEF(NULL,
"buf-sz", 1,
"Client buffer size (ms)");
279 static const arg_def_t buf_initial_sz =
280 ARG_DEF(NULL,
"buf-initial-sz", 1,
"Client initial buffer size (ms)");
281 static const arg_def_t buf_optimal_sz =
282 ARG_DEF(NULL,
"buf-optimal-sz", 1,
"Client optimal buffer size (ms)");
283 static const arg_def_t *rc_args[] = {
284 &dropframe_thresh, &resize_allowed, &resize_width, &resize_height,
285 &resize_up_thresh, &resize_down_thresh, &end_usage, &target_bitrate,
286 &min_quantizer, &max_quantizer, &undershoot_pct, &overshoot_pct,
287 &buf_sz, &buf_initial_sz, &buf_optimal_sz, NULL
290 static const arg_def_t bias_pct =
291 ARG_DEF(NULL,
"bias-pct", 1,
"CBR/VBR bias (0=CBR, 100=VBR)");
292 static const arg_def_t minsection_pct =
293 ARG_DEF(NULL,
"minsection-pct", 1,
"GOP min bitrate (% of target)");
294 static const arg_def_t maxsection_pct =
295 ARG_DEF(NULL,
"maxsection-pct", 1,
"GOP max bitrate (% of target)");
296 static const arg_def_t corpus_complexity =
297 ARG_DEF(NULL,
"corpus-complexity", 1,
"corpus vbr complexity midpoint");
298 static const arg_def_t *rc_twopass_args[] = { &bias_pct, &minsection_pct,
300 &corpus_complexity, NULL };
302 static const arg_def_t kf_min_dist =
303 ARG_DEF(NULL,
"kf-min-dist", 1,
"Minimum keyframe interval (frames)");
304 static const arg_def_t kf_max_dist =
305 ARG_DEF(NULL,
"kf-max-dist", 1,
"Maximum keyframe interval (frames)");
306 static const arg_def_t kf_disabled =
307 ARG_DEF(NULL,
"disable-kf", 0,
"Disable keyframe placement");
308 static const arg_def_t *kf_args[] = { &kf_min_dist, &kf_max_dist, &kf_disabled,
311 static const arg_def_t noise_sens =
312 ARG_DEF(NULL,
"noise-sensitivity", 1,
"Noise sensitivity (frames to blur)");
313 static const arg_def_t sharpness =
314 ARG_DEF(NULL,
"sharpness", 1,
315 "Increase sharpness at the expense of lower PSNR. (0..7)");
316 static const arg_def_t static_thresh =
317 ARG_DEF(NULL,
"static-thresh", 1,
"Motion detection threshold");
318 static const arg_def_t arnr_maxframes =
319 ARG_DEF(NULL,
"arnr-maxframes", 1,
"AltRef max frames (0..15)");
320 static const arg_def_t arnr_strength =
321 ARG_DEF(NULL,
"arnr-strength", 1,
"AltRef filter strength (0..6)");
322 static const arg_def_t arnr_type =
323 ARG_DEF(NULL,
"arnr-type", 1,
"AltRef filter type (1..3)");
324 static const struct arg_enum_list tuning_enum[] = { {
"psnr", VP8_TUNE_PSNR },
325 {
"ssim", VP8_TUNE_SSIM },
327 static const arg_def_t tune_ssim =
328 ARG_DEF_ENUM(NULL,
"tune", 1,
"Material to favor", tuning_enum);
329 static const arg_def_t cq_level =
330 ARG_DEF(NULL,
"cq-level", 1,
"Constant/Constrained Quality level");
331 static const arg_def_t max_intra_rate_pct =
332 ARG_DEF(NULL,
"max-intra-rate", 1,
"Max I-frame bitrate (pct)");
333 static const arg_def_t gf_cbr_boost_pct = ARG_DEF(
334 NULL,
"gf-cbr-boost", 1,
"Boost for Golden Frame in CBR mode (pct)");
336 #if CONFIG_VP8_ENCODER
337 static const arg_def_t cpu_used_vp8 =
338 ARG_DEF(NULL,
"cpu-used", 1,
"CPU Used (-16..16)");
339 static const arg_def_t auto_altref_vp8 = ARG_DEF(
340 NULL,
"auto-alt-ref", 1,
"Enable automatic alt reference frames. (0..1)");
341 static const arg_def_t token_parts =
342 ARG_DEF(NULL,
"token-parts", 1,
"Number of token partitions to use, log2");
343 static const arg_def_t screen_content_mode =
344 ARG_DEF(NULL,
"screen-content-mode", 1,
"Screen content mode");
345 static const arg_def_t *vp8_args[] = { &cpu_used_vp8,
358 &screen_content_mode,
377 #if CONFIG_VP9_ENCODER
378 static const arg_def_t cpu_used_vp9 =
379 ARG_DEF(NULL,
"cpu-used", 1,
"CPU Used (-9..9)");
380 static const arg_def_t auto_altref_vp9 = ARG_DEF(
381 NULL,
"auto-alt-ref", 1,
382 "Enable automatic alt reference frames, 2+ enables multi-layer. (0..6)");
383 static const arg_def_t tile_cols =
384 ARG_DEF(NULL,
"tile-columns", 1,
"Number of tile columns to use, log2");
385 static const arg_def_t tile_rows =
386 ARG_DEF(NULL,
"tile-rows", 1,
387 "Number of tile rows to use, log2 (set to 0 while threads > 1)");
389 static const arg_def_t enable_tpl_model =
390 ARG_DEF(NULL,
"enable-tpl", 1,
"Enable temporal dependency model");
392 static const arg_def_t lossless =
393 ARG_DEF(NULL,
"lossless", 1,
"Lossless mode (0: false (default), 1: true)");
394 static const arg_def_t frame_parallel_decoding = ARG_DEF(
395 NULL,
"frame-parallel", 1,
"Enable frame parallel decodability features");
396 static const arg_def_t aq_mode = ARG_DEF(
398 "Adaptive quantization mode (0: off (default), 1: variance 2: complexity, "
399 "3: cyclic refresh, 4: equator360)");
400 static const arg_def_t alt_ref_aq = ARG_DEF(NULL,
"alt-ref-aq", 1,
401 "Special adaptive quantization for "
402 "the alternate reference frames.");
403 static const arg_def_t frame_periodic_boost =
404 ARG_DEF(NULL,
"frame-boost", 1,
405 "Enable frame periodic boost (0: off (default), 1: on)");
406 static const arg_def_t max_inter_rate_pct =
407 ARG_DEF(NULL,
"max-inter-rate", 1,
"Max P-frame bitrate (pct)");
408 static const arg_def_t min_gf_interval = ARG_DEF(
409 NULL,
"min-gf-interval", 1,
410 "min gf/arf frame interval (default 0, indicating in-built behavior)");
411 static const arg_def_t max_gf_interval = ARG_DEF(
412 NULL,
"max-gf-interval", 1,
413 "max gf/arf frame interval (default 0, indicating in-built behavior)");
415 static const struct arg_enum_list color_space_enum[] = {
427 static const arg_def_t input_color_space =
428 ARG_DEF_ENUM(NULL,
"color-space", 1,
429 "The color space of input content:", color_space_enum);
431 #if CONFIG_VP9_HIGHBITDEPTH
432 static const struct arg_enum_list bitdepth_enum[] = {
436 static const arg_def_t bitdeptharg = ARG_DEF_ENUM(
438 "Bit depth for codec (8 for version <=1, 10 or 12 for version 2)",
440 static const arg_def_t inbitdeptharg =
441 ARG_DEF(NULL,
"input-bit-depth", 1,
"Bit depth of input");
444 static const struct arg_enum_list tune_content_enum[] = {
445 {
"default", VP9E_CONTENT_DEFAULT },
446 {
"screen", VP9E_CONTENT_SCREEN },
447 {
"film", VP9E_CONTENT_FILM },
451 static const arg_def_t tune_content = ARG_DEF_ENUM(
452 NULL,
"tune-content", 1,
"Tune content type", tune_content_enum);
454 static const arg_def_t target_level = ARG_DEF(
455 NULL,
"target-level", 1,
457 " 255: off (default)\n"
458 " 0: only keep level stats\n"
459 " 1: adaptively set alt-ref "
460 "distance and column tile limit based on picture size, and keep"
462 " 10: level 1.0 11: level 1.1 "
463 "... 62: level 6.2");
465 static const arg_def_t row_mt =
466 ARG_DEF(NULL,
"row-mt", 1,
467 "Enable row based non-deterministic multi-threading in VP9");
470 #if CONFIG_VP9_ENCODER
471 static const arg_def_t *vp9_args[] = { &cpu_used_vp9,
487 &frame_parallel_decoding,
490 &frame_periodic_boost,
498 #if CONFIG_VP9_HIGHBITDEPTH
533 static const arg_def_t *no_args[] = { NULL };
535 static void show_help(FILE *fout,
int shorthelp) {
537 const int num_encoder = get_vpx_encoder_count();
539 fprintf(fout,
"Usage: %s <options> -o dst_filename src_filename \n",
543 fprintf(fout,
"Use --help to see the full list of options.\n");
547 fprintf(fout,
"\nOptions:\n");
548 arg_show_usage(fout, main_args);
549 fprintf(fout,
"\nEncoder Global Options:\n");
550 arg_show_usage(fout, global_args);
551 fprintf(fout,
"\nRate Control Options:\n");
552 arg_show_usage(fout, rc_args);
553 fprintf(fout,
"\nTwopass Rate Control Options:\n");
554 arg_show_usage(fout, rc_twopass_args);
555 fprintf(fout,
"\nKeyframe Placement Options:\n");
556 arg_show_usage(fout, kf_args);
557 #if CONFIG_VP8_ENCODER
558 fprintf(fout,
"\nVP8 Specific Options:\n");
559 arg_show_usage(fout, vp8_args);
561 #if CONFIG_VP9_ENCODER
562 fprintf(fout,
"\nVP9 Specific Options:\n");
563 arg_show_usage(fout, vp9_args);
566 "\nStream timebase (--timebase):\n"
567 " The desired precision of timestamps in the output, expressed\n"
568 " in fractional seconds. Default is 1/1000.\n");
569 fprintf(fout,
"\nIncluded encoders:\n\n");
571 for (i = 0; i < num_encoder; ++i) {
572 const VpxInterface *
const encoder = get_vpx_encoder_by_index(i);
573 const char *defstr = (i == (num_encoder - 1)) ?
"(default)" :
"";
574 fprintf(fout,
" %-6s - %s %s\n", encoder->name,
577 fprintf(fout,
"\n ");
578 fprintf(fout,
"Use --codec to switch to a non-default encoder.\n\n");
581 void usage_exit(
void) {
582 show_help(stderr, 1);
586 #define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
587 #if CONFIG_VP9_ENCODER
588 #define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map)
590 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
594 typedef int stereo_format_t;
595 struct WebmOutputContext {
601 struct stream_config {
604 const char *stats_fn;
605 #if CONFIG_FP_MB_STATS
606 const char *fpmb_stats_fn;
608 stereo_format_t stereo_fmt;
609 int arg_ctrls[ARG_CTRL_CNT_MAX][2];
612 #if CONFIG_VP9_HIGHBITDEPTH
614 int use_16bit_internal;
618 struct stream_state {
620 struct stream_state *next;
621 struct stream_config config;
623 struct rate_hist *rate_hist;
624 struct WebmOutputContext webm_ctx;
625 uint64_t psnr_sse_total;
626 uint64_t psnr_samples_total;
627 double psnr_totals[4];
631 unsigned int frames_out;
635 #if CONFIG_FP_MB_STATS
636 stats_io_t fpmb_stats;
643 static void validate_positive_rational(
const char *msg,
650 if (rat->
num < 0) die(
"Error: %s must be positive\n", msg);
652 if (!rat->
den) die(
"Error: %s has zero denominator\n", msg);
655 static void parse_global_config(
struct VpxEncoderConfig *global,
char **argv) {
658 const int num_encoder = get_vpx_encoder_count();
660 if (num_encoder < 1) die(
"Error: no valid encoder available\n");
663 memset(global, 0,
sizeof(*global));
664 global->codec = get_vpx_encoder_by_index(num_encoder - 1);
666 global->color_type = I420;
670 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
673 if (arg_match(&arg, &help, argi)) {
674 show_help(stdout, 0);
676 }
else if (arg_match(&arg, &codecarg, argi)) {
677 global->codec = get_vpx_encoder_by_name(arg.val);
679 die(
"Error: Unrecognized argument (%s) to --codec\n", arg.val);
680 }
else if (arg_match(&arg, &passes, argi)) {
681 global->passes = arg_parse_uint(&arg);
683 if (global->passes < 1 || global->passes > 2)
684 die(
"Error: Invalid number of passes (%d)\n", global->passes);
685 }
else if (arg_match(&arg, &pass_arg, argi)) {
686 global->pass = arg_parse_uint(&arg);
688 if (global->pass < 1 || global->pass > 2)
689 die(
"Error: Invalid pass selected (%d)\n", global->pass);
690 }
else if (arg_match(&arg, &usage, argi))
691 global->usage = arg_parse_uint(&arg);
692 else if (arg_match(&arg, &deadline, argi))
693 global->deadline = arg_parse_uint(&arg);
694 else if (arg_match(&arg, &best_dl, argi))
696 else if (arg_match(&arg, &good_dl, argi))
698 else if (arg_match(&arg, &rt_dl, argi))
700 else if (arg_match(&arg, &use_yv12, argi))
701 global->color_type = YV12;
702 else if (arg_match(&arg, &use_nv12, argi))
703 global->color_type = NV12;
704 else if (arg_match(&arg, &use_i420, argi))
705 global->color_type = I420;
706 else if (arg_match(&arg, &use_i422, argi))
707 global->color_type = I422;
708 else if (arg_match(&arg, &use_i444, argi))
709 global->color_type = I444;
710 else if (arg_match(&arg, &use_i440, argi))
711 global->color_type = I440;
712 else if (arg_match(&arg, &quietarg, argi))
714 else if (arg_match(&arg, &verbosearg, argi))
716 else if (arg_match(&arg, &limit, argi))
717 global->limit = arg_parse_uint(&arg);
718 else if (arg_match(&arg, &skip, argi))
719 global->skip_frames = arg_parse_uint(&arg);
720 else if (arg_match(&arg, &psnrarg, argi))
721 global->show_psnr = 1;
722 else if (arg_match(&arg, &recontest, argi))
723 global->test_decode = arg_parse_enum_or_int(&arg);
724 else if (arg_match(&arg, &framerate, argi)) {
725 global->framerate = arg_parse_rational(&arg);
726 validate_positive_rational(arg.name, &global->framerate);
727 global->have_framerate = 1;
728 }
else if (arg_match(&arg, &out_part, argi))
729 global->out_part = 1;
730 else if (arg_match(&arg, &debugmode, argi))
732 else if (arg_match(&arg, &q_hist_n, argi))
733 global->show_q_hist_buckets = arg_parse_uint(&arg);
734 else if (arg_match(&arg, &rate_hist_n, argi))
735 global->show_rate_hist_buckets = arg_parse_uint(&arg);
736 else if (arg_match(&arg, &disable_warnings, argi))
737 global->disable_warnings = 1;
738 else if (arg_match(&arg, &disable_warning_prompt, argi))
739 global->disable_warning_prompt = 1;
746 if (global->pass > global->passes) {
747 warn(
"Assuming --pass=%d implies --passes=%d\n", global->pass,
749 global->passes = global->pass;
753 if (global->passes == 0) {
754 #if CONFIG_VP9_ENCODER
757 if (global->codec != NULL && global->codec->name != NULL)
758 global->passes = (strcmp(global->codec->name,
"vp9") == 0 &&
768 warn(
"Enforcing one-pass encoding in realtime mode\n");
773 static struct stream_state *new_stream(
struct VpxEncoderConfig *global,
774 struct stream_state *prev) {
775 struct stream_state *stream;
777 stream = calloc(1,
sizeof(*stream));
778 if (stream == NULL) {
779 fatal(
"Failed to allocate new stream.");
783 memcpy(stream, prev,
sizeof(*stream));
791 &stream->config.cfg, global->usage);
797 stream->config.cfg.g_timebase.den = 1000;
802 stream->config.cfg.g_w = 0;
803 stream->config.cfg.g_h = 0;
806 stream->config.write_webm = 1;
808 stream->config.stereo_fmt = STEREO_FORMAT_MONO;
809 stream->webm_ctx.last_pts_ns = -1;
810 stream->webm_ctx.writer = NULL;
811 stream->webm_ctx.segment = NULL;
815 stream->webm_ctx.debug = global->debug;
819 stream->config.cfg.rc_end_usage == 1)
820 stream->config.cfg.g_lag_in_frames = 0;
824 stream->config.out_fn = NULL;
830 static int parse_stream_params(
struct VpxEncoderConfig *global,
831 struct stream_state *stream,
char **argv) {
834 static const arg_def_t **ctrl_args = no_args;
835 static const int *ctrl_args_map = NULL;
836 struct stream_config *config = &stream->config;
837 int eos_mark_found = 0;
838 #if CONFIG_VP9_HIGHBITDEPTH
839 int test_16bit_internal = 0;
844 #if CONFIG_VP8_ENCODER
845 }
else if (strcmp(global->codec->name,
"vp8") == 0) {
846 ctrl_args = vp8_args;
847 ctrl_args_map = vp8_arg_ctrl_map;
849 #if CONFIG_VP9_ENCODER
850 }
else if (strcmp(global->codec->name,
"vp9") == 0) {
851 ctrl_args = vp9_args;
852 ctrl_args_map = vp9_arg_ctrl_map;
856 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
862 if (eos_mark_found) {
865 }
else if (!strcmp(*argj,
"--")) {
870 if (arg_match(&arg, &outputfile, argi)) {
871 config->out_fn = arg.val;
872 }
else if (arg_match(&arg, &fpf_name, argi)) {
873 config->stats_fn = arg.val;
874 #if CONFIG_FP_MB_STATS
875 }
else if (arg_match(&arg, &fpmbf_name, argi)) {
876 config->fpmb_stats_fn = arg.val;
878 }
else if (arg_match(&arg, &use_webm, argi)) {
880 config->write_webm = 1;
882 die(
"Error: --webm specified but webm is disabled.");
884 }
else if (arg_match(&arg, &use_ivf, argi)) {
885 config->write_webm = 0;
886 }
else if (arg_match(&arg, &threads, argi)) {
887 config->cfg.g_threads = arg_parse_uint(&arg);
888 }
else if (arg_match(&arg, &profile, argi)) {
889 config->cfg.g_profile = arg_parse_uint(&arg);
890 }
else if (arg_match(&arg, &width, argi)) {
891 config->cfg.g_w = arg_parse_uint(&arg);
892 }
else if (arg_match(&arg, &height, argi)) {
893 config->cfg.g_h = arg_parse_uint(&arg);
894 #if CONFIG_VP9_HIGHBITDEPTH
895 }
else if (arg_match(&arg, &bitdeptharg, argi)) {
896 config->cfg.g_bit_depth = arg_parse_enum_or_int(&arg);
897 }
else if (arg_match(&arg, &inbitdeptharg, argi)) {
898 config->cfg.g_input_bit_depth = arg_parse_uint(&arg);
901 }
else if (arg_match(&arg, &stereo_mode, argi)) {
902 config->stereo_fmt = arg_parse_enum_or_int(&arg);
904 }
else if (arg_match(&arg, &timebase, argi)) {
905 config->cfg.g_timebase = arg_parse_rational(&arg);
906 validate_positive_rational(arg.name, &config->cfg.g_timebase);
907 }
else if (arg_match(&arg, &error_resilient, argi)) {
908 config->cfg.g_error_resilient = arg_parse_uint(&arg);
909 }
else if (arg_match(&arg, &end_usage, argi)) {
910 config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
911 }
else if (arg_match(&arg, &lag_in_frames, argi)) {
912 config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
914 config->cfg.rc_end_usage ==
VPX_CBR &&
915 config->cfg.g_lag_in_frames != 0) {
916 warn(
"non-zero %s option ignored in realtime CBR mode.\n", arg.name);
917 config->cfg.g_lag_in_frames = 0;
919 }
else if (arg_match(&arg, &dropframe_thresh, argi)) {
920 config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
921 }
else if (arg_match(&arg, &resize_allowed, argi)) {
922 config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
923 }
else if (arg_match(&arg, &resize_width, argi)) {
924 config->cfg.rc_scaled_width = arg_parse_uint(&arg);
925 }
else if (arg_match(&arg, &resize_height, argi)) {
926 config->cfg.rc_scaled_height = arg_parse_uint(&arg);
927 }
else if (arg_match(&arg, &resize_up_thresh, argi)) {
928 config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
929 }
else if (arg_match(&arg, &resize_down_thresh, argi)) {
930 config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
931 }
else if (arg_match(&arg, &end_usage, argi)) {
932 config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
933 }
else if (arg_match(&arg, &target_bitrate, argi)) {
934 config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
935 }
else if (arg_match(&arg, &min_quantizer, argi)) {
936 config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
937 }
else if (arg_match(&arg, &max_quantizer, argi)) {
938 config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
939 }
else if (arg_match(&arg, &undershoot_pct, argi)) {
940 config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
941 }
else if (arg_match(&arg, &overshoot_pct, argi)) {
942 config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
943 }
else if (arg_match(&arg, &buf_sz, argi)) {
944 config->cfg.rc_buf_sz = arg_parse_uint(&arg);
945 }
else if (arg_match(&arg, &buf_initial_sz, argi)) {
946 config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
947 }
else if (arg_match(&arg, &buf_optimal_sz, argi)) {
948 config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
949 }
else if (arg_match(&arg, &bias_pct, argi)) {
950 config->cfg.rc_2pass_vbr_bias_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, &minsection_pct, argi)) {
954 config->cfg.rc_2pass_vbr_minsection_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, &maxsection_pct, argi)) {
959 config->cfg.rc_2pass_vbr_maxsection_pct = 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, &corpus_complexity, argi)) {
964 config->cfg.rc_2pass_vbr_corpus_complexity = arg_parse_uint(&arg);
966 if (global->passes < 2)
967 warn(
"option %s ignored in one-pass mode.\n", arg.name);
968 }
else if (arg_match(&arg, &kf_min_dist, argi)) {
969 config->cfg.kf_min_dist = arg_parse_uint(&arg);
970 }
else if (arg_match(&arg, &kf_max_dist, argi)) {
971 config->cfg.kf_max_dist = arg_parse_uint(&arg);
972 }
else if (arg_match(&arg, &kf_disabled, argi)) {
974 #if CONFIG_VP9_HIGHBITDEPTH
975 }
else if (arg_match(&arg, &test16bitinternalarg, argi)) {
976 if (strcmp(global->codec->name,
"vp9") == 0) {
977 test_16bit_internal = 1;
982 for (i = 0; ctrl_args[i]; i++) {
983 if (arg_match(&arg, ctrl_args[i], argi)) {
990 for (j = 0; j < config->arg_ctrl_cnt; j++)
991 if (ctrl_args_map != NULL &&
992 config->arg_ctrls[j][0] == ctrl_args_map[i])
996 assert(j < (
int)ARG_CTRL_CNT_MAX);
997 if (ctrl_args_map != NULL && j < (
int)ARG_CTRL_CNT_MAX) {
998 config->arg_ctrls[j][0] = ctrl_args_map[i];
999 config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
1000 if (j == config->arg_ctrl_cnt) config->arg_ctrl_cnt++;
1007 #if CONFIG_VP9_HIGHBITDEPTH
1008 if (strcmp(global->codec->name,
"vp9") == 0) {
1009 config->use_16bit_internal =
1010 test_16bit_internal | (config->cfg.g_profile > 1);
1013 return eos_mark_found;
1016 #define FOREACH_STREAM(func) \
1018 struct stream_state *stream; \
1019 for (stream = streams; stream; stream = stream->next) { \
1024 static void validate_stream_config(
const struct stream_state *stream,
1025 const struct VpxEncoderConfig *global) {
1026 const struct stream_state *streami;
1029 if (!stream->config.cfg.g_w || !stream->config.cfg.g_h)
1031 "Stream %d: Specify stream dimensions with --width (-w) "
1032 " and --height (-h)",
1036 if (stream->config.cfg.g_input_bit_depth >
1037 (
unsigned int)stream->config.cfg.g_bit_depth) {
1038 fatal(
"Stream %d: codec bit depth (%d) less than input bit depth (%d)",
1039 stream->index, (
int)stream->config.cfg.g_bit_depth,
1040 stream->config.cfg.g_input_bit_depth);
1043 for (streami = stream; streami; streami = streami->next) {
1045 if (!streami->config.out_fn)
1046 fatal(
"Stream %d: Output file is required (specify with -o)",
1050 if (streami != stream) {
1051 const char *a = stream->config.out_fn;
1052 const char *b = streami->config.out_fn;
1053 if (!strcmp(a, b) && strcmp(a,
"/dev/null") && strcmp(a,
":nul"))
1054 fatal(
"Stream %d: duplicate output file (from stream %d)",
1055 streami->index, stream->index);
1059 if (streami != stream) {
1060 const char *a = stream->config.stats_fn;
1061 const char *b = streami->config.stats_fn;
1062 if (a && b && !strcmp(a, b))
1063 fatal(
"Stream %d: duplicate stats file (from stream %d)",
1064 streami->index, stream->index);
1067 #if CONFIG_FP_MB_STATS
1069 if (streami != stream) {
1070 const char *a = stream->config.fpmb_stats_fn;
1071 const char *b = streami->config.fpmb_stats_fn;
1072 if (a && b && !strcmp(a, b))
1073 fatal(
"Stream %d: duplicate mb stats file (from stream %d)",
1074 streami->index, stream->index);
1080 static void set_stream_dimensions(
struct stream_state *stream,
unsigned int w,
1082 if (!stream->config.cfg.g_w) {
1083 if (!stream->config.cfg.g_h)
1084 stream->config.cfg.g_w = w;
1086 stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
1088 if (!stream->config.cfg.g_h) {
1089 stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
1093 static const char *file_type_to_string(
enum VideoFileType t) {
1095 case FILE_TYPE_RAW:
return "RAW";
1096 case FILE_TYPE_Y4M:
return "Y4M";
1097 default:
return "Other";
1101 static const char *image_format_to_string(
vpx_img_fmt_t f) {
1112 default:
return "Other";
1116 static void show_stream_config(
struct stream_state *stream,
1117 struct VpxEncoderConfig *global,
1118 struct VpxInputContext *input) {
1119 #define SHOW(field) \
1120 fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field)
1122 if (stream->index == 0) {
1123 fprintf(stderr,
"Codec: %s\n",
1125 fprintf(stderr,
"Source file: %s File Type: %s Format: %s\n",
1126 input->filename, file_type_to_string(input->file_type),
1127 image_format_to_string(input->fmt));
1129 if (stream->next || stream->index)
1130 fprintf(stderr,
"\nStream Index: %d\n", stream->index);
1131 fprintf(stderr,
"Destination file: %s\n", stream->config.out_fn);
1132 fprintf(stderr,
"Encoder parameters:\n");
1140 SHOW(g_input_bit_depth);
1141 SHOW(g_timebase.num);
1142 SHOW(g_timebase.den);
1143 SHOW(g_error_resilient);
1145 SHOW(g_lag_in_frames);
1146 SHOW(rc_dropframe_thresh);
1147 SHOW(rc_resize_allowed);
1148 SHOW(rc_scaled_width);
1149 SHOW(rc_scaled_height);
1150 SHOW(rc_resize_up_thresh);
1151 SHOW(rc_resize_down_thresh);
1153 SHOW(rc_target_bitrate);
1154 SHOW(rc_min_quantizer);
1155 SHOW(rc_max_quantizer);
1156 SHOW(rc_undershoot_pct);
1157 SHOW(rc_overshoot_pct);
1159 SHOW(rc_buf_initial_sz);
1160 SHOW(rc_buf_optimal_sz);
1161 SHOW(rc_2pass_vbr_bias_pct);
1162 SHOW(rc_2pass_vbr_minsection_pct);
1163 SHOW(rc_2pass_vbr_maxsection_pct);
1164 SHOW(rc_2pass_vbr_corpus_complexity);
1170 static void open_output_file(
struct stream_state *stream,
1171 struct VpxEncoderConfig *global,
1172 const struct VpxRational *pixel_aspect_ratio) {
1173 const char *fn = stream->config.out_fn;
1178 stream->file = strcmp(fn,
"-") ? fopen(fn,
"wb") : set_binary_mode(stdout);
1180 if (!stream->file) fatal(
"Failed to open output file");
1182 if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
1183 fatal(
"WebM output to pipes not supported.");
1186 if (stream->config.write_webm) {
1187 stream->webm_ctx.stream = stream->file;
1188 write_webm_file_header(&stream->webm_ctx, cfg, stream->config.stereo_fmt,
1189 global->codec->fourcc, pixel_aspect_ratio);
1192 (void)pixel_aspect_ratio;
1195 if (!stream->config.write_webm) {
1196 ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0);
1200 static void close_output_file(
struct stream_state *stream,
1201 unsigned int fourcc) {
1207 if (stream->config.write_webm) {
1208 write_webm_file_footer(&stream->webm_ctx);
1212 if (!stream->config.write_webm) {
1213 if (!fseek(stream->file, 0, SEEK_SET))
1214 ivf_write_file_header(stream->file, &stream->config.cfg, fourcc,
1215 stream->frames_out);
1218 fclose(stream->file);
1221 static void setup_pass(
struct stream_state *stream,
1222 struct VpxEncoderConfig *global,
int pass) {
1223 if (stream->config.stats_fn) {
1224 if (!stats_open_file(&stream->stats, stream->config.stats_fn, pass))
1225 fatal(
"Failed to open statistics store");
1227 if (!stats_open_mem(&stream->stats, pass))
1228 fatal(
"Failed to open statistics store");
1231 #if CONFIG_FP_MB_STATS
1232 if (stream->config.fpmb_stats_fn) {
1233 if (!stats_open_file(&stream->fpmb_stats, stream->config.fpmb_stats_fn,
1235 fatal(
"Failed to open mb statistics store");
1237 if (!stats_open_mem(&stream->fpmb_stats, pass))
1238 fatal(
"Failed to open mb statistics store");
1242 stream->config.cfg.g_pass = global->passes == 2
1246 stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
1247 #if CONFIG_FP_MB_STATS
1248 stream->config.cfg.rc_firstpass_mb_stats_in =
1249 stats_get(&stream->fpmb_stats);
1253 stream->cx_time = 0;
1255 stream->frames_out = 0;
1258 static void initialize_encoder(
struct stream_state *stream,
1259 struct VpxEncoderConfig *global) {
1265 #if CONFIG_VP9_HIGHBITDEPTH
1271 &stream->config.cfg, flags);
1272 ctx_exit_on_error(&stream->encoder,
"Failed to initialize encoder");
1278 for (i = 0; i < stream->config.arg_ctrl_cnt; i++) {
1279 int ctrl = stream->config.arg_ctrls[i][0];
1280 int value = stream->config.arg_ctrls[i][1];
1282 fprintf(stderr,
"Error: Tried to set control %d = %d\n", ctrl, value);
1284 ctx_exit_on_error(&stream->encoder,
"Failed to control codec");
1288 if (global->test_decode != TEST_DECODE_OFF) {
1289 const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
1295 static void encode_frame(
struct stream_state *stream,
1296 struct VpxEncoderConfig *global,
struct vpx_image *img,
1297 unsigned int frames_in) {
1300 struct vpx_usec_timer timer;
1303 (cfg->
g_timebase.
den * (int64_t)(frames_in - 1) * global->framerate.den) /
1306 (cfg->
g_timebase.
den * (int64_t)(frames_in)*global->framerate.den) /
1310 #if CONFIG_VP9_HIGHBITDEPTH
1315 fprintf(stderr,
"%s can only scale 4:2:0 inputs\n", exec_name);
1332 stream->img->stride[
VPX_PLANE_V] / 2, stream->img->d_w,
1333 stream->img->d_h, kFilterBox);
1336 stream->encoder.err = 1;
1337 ctx_exit_on_error(&stream->encoder,
1338 "Stream %d: Failed to encode frame.\n"
1339 "Scaling disabled in this configuration. \n"
1340 "To enable, configure with --enable-libyuv\n",
1346 if (img && (img->
d_w != cfg->
g_w || img->
d_h != cfg->
g_h)) {
1348 fprintf(stderr,
"%s can only scale 4:2:0 8bpp inputs\n", exec_name);
1362 stream->img->d_w, stream->img->d_h, kFilterBox);
1365 stream->encoder.err = 1;
1366 ctx_exit_on_error(&stream->encoder,
1367 "Stream %d: Failed to encode frame.\n"
1368 "Scaling disabled in this configuration. \n"
1369 "To enable, configure with --enable-libyuv\n",
1374 vpx_usec_timer_start(&timer);
1376 (
unsigned long)(next_frame_start - frame_start), 0,
1378 vpx_usec_timer_mark(&timer);
1379 stream->cx_time += vpx_usec_timer_elapsed(&timer);
1380 ctx_exit_on_error(&stream->encoder,
"Stream %d: Failed to encode frame",
1384 static void update_quantizer_histogram(
struct stream_state *stream) {
1389 ctx_exit_on_error(&stream->encoder,
"Failed to read quantizer");
1390 stream->counts[q]++;
1394 static void get_cx_data(
struct stream_state *stream,
1395 struct VpxEncoderConfig *global,
int *got_data) {
1402 static size_t fsize = 0;
1403 static FileOffset ivf_header_pos = 0;
1405 switch (pkt->
kind) {
1408 stream->frames_out++;
1411 fprintf(stderr,
" %6luF", (
unsigned long)pkt->
data.
frame.sz);
1413 update_rate_histogram(stream->rate_hist, cfg, pkt);
1415 if (stream->config.write_webm) {
1416 write_webm_block(&stream->webm_ctx, cfg, pkt);
1419 if (!stream->config.write_webm) {
1420 if (pkt->
data.
frame.partition_id <= 0) {
1421 ivf_header_pos = ftello(stream->file);
1424 ivf_write_frame_header(stream->file, pkt->
data.
frame.pts, fsize);
1429 const FileOffset currpos = ftello(stream->file);
1430 fseeko(stream->file, ivf_header_pos, SEEK_SET);
1431 ivf_write_frame_size(stream->file, fsize);
1432 fseeko(stream->file, currpos, SEEK_SET);
1443 if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
1445 (
unsigned int)pkt->
data.
frame.sz, NULL, 0);
1446 if (stream->decoder.err) {
1447 warn_or_exit_on_error(&stream->decoder,
1448 global->test_decode == TEST_DECODE_FATAL,
1449 "Failed to decode frame %d in stream %d",
1450 stream->frames_out + 1, stream->index);
1451 stream->mismatch_seen = stream->frames_out + 1;
1457 stream->frames_out++;
1462 #if CONFIG_FP_MB_STATS
1471 if (global->show_psnr) {
1474 stream->psnr_sse_total += pkt->
data.
psnr.sse[0];
1475 stream->psnr_samples_total += pkt->
data.
psnr.samples[0];
1476 for (i = 0; i < 4; i++) {
1478 fprintf(stderr,
"%.3f ", pkt->
data.
psnr.psnr[i]);
1479 stream->psnr_totals[i] += pkt->
data.
psnr.psnr[i];
1481 stream->psnr_count++;
1490 static void show_psnr(
struct stream_state *stream,
double peak) {
1494 if (!stream->psnr_count)
return;
1496 fprintf(stderr,
"Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
1497 ovpsnr = sse_to_psnr((
double)stream->psnr_samples_total, peak,
1498 (
double)stream->psnr_sse_total);
1499 fprintf(stderr,
" %.3f", ovpsnr);
1501 for (i = 0; i < 4; i++) {
1502 fprintf(stderr,
" %.3f", stream->psnr_totals[i] / stream->psnr_count);
1504 fprintf(stderr,
"\n");
1507 static float usec_to_fps(uint64_t usec,
unsigned int frames) {
1508 return (
float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
1511 static void test_decode(
struct stream_state *stream,
1512 enum TestDecodeFatality fatal,
1513 const VpxInterface *codec) {
1516 if (stream->mismatch_seen)
return;
1519 if (strcmp(codec->name,
"vp8") == 0) {
1523 width = (stream->config.cfg.g_w + 15) & ~15;
1524 height = (stream->config.cfg.g_h + 15) & ~15;
1526 enc_img = ref_enc.img;
1528 dec_img = ref_dec.img;
1530 ref_enc.frame_type = VP8_LAST_FRAME;
1531 ref_dec.frame_type = VP8_LAST_FRAME;
1540 enc_img = ref_enc.img;
1542 dec_img = ref_dec.img;
1543 #if CONFIG_VP9_HIGHBITDEPTH
1548 enc_img.
d_w, enc_img.
d_h, 16);
1549 vpx_img_truncate_16_to_8(&enc_img, &ref_enc.img);
1553 dec_img.
d_w, dec_img.
d_h, 16);
1554 vpx_img_truncate_16_to_8(&dec_img, &ref_dec.img);
1559 ctx_exit_on_error(&stream->encoder,
"Failed to get encoder reference frame");
1560 ctx_exit_on_error(&stream->decoder,
"Failed to get decoder reference frame");
1562 if (!compare_img(&enc_img, &dec_img)) {
1563 int y[4], u[4], v[4];
1564 #if CONFIG_VP9_HIGHBITDEPTH
1566 find_mismatch_high(&enc_img, &dec_img, y, u, v);
1568 find_mismatch(&enc_img, &dec_img, y, u, v);
1571 find_mismatch(&enc_img, &dec_img, y, u, v);
1573 stream->decoder.err = 1;
1574 warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
1575 "Stream %d: Encode/decode mismatch on frame %d at"
1576 " Y[%d, %d] {%d/%d},"
1577 " U[%d, %d] {%d/%d},"
1578 " V[%d, %d] {%d/%d}",
1579 stream->index, stream->frames_out, y[0], y[1], y[2],
1580 y[3], u[0], u[1], u[2], u[3], v[0], v[1], v[2], v[3]);
1581 stream->mismatch_seen = stream->frames_out;
1588 static void print_time(
const char *label, int64_t etl) {
1595 etl -= hours * 3600;
1600 fprintf(stderr,
"[%3s %2" PRId64
":%02" PRId64
":%02" PRId64
"] ", label,
1603 fprintf(stderr,
"[%3s unknown] ", label);
1607 int main(
int argc,
const char **argv_) {
1610 #if CONFIG_VP9_HIGHBITDEPTH
1612 int allocated_raw_shift = 0;
1613 int use_16bit_internal = 0;
1614 int input_shift = 0;
1616 int frame_avail, got_data;
1618 struct VpxInputContext input;
1619 struct VpxEncoderConfig global;
1620 struct stream_state *streams = NULL;
1621 char **argv, **argi;
1622 uint64_t cx_time = 0;
1626 memset(&input, 0,
sizeof(input));
1627 exec_name = argv_[0];
1630 input.framerate.numerator = 30;
1631 input.framerate.denominator = 1;
1632 input.only_i420 = 1;
1633 input.bit_depth = 0;
1639 argv = argv_dup(argc - 1, argv_ + 1);
1640 parse_global_config(&global, argv);
1642 if (argc < 3) usage_exit();
1644 switch (global.color_type) {
1658 struct stream_state *stream = NULL;
1661 stream = new_stream(&global, stream);
1663 if (!streams) streams = stream;
1664 }
while (parse_stream_params(&global, stream, argv));
1668 for (argi = argv; *argi; argi++)
1669 if (argi[0][0] ==
'-' && argi[0][1])
1670 die(
"Error: Unrecognized option %s\n", *argi);
1672 FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt, &global,
1673 &stream->config.cfg););
1676 input.filename = argv[0];
1678 if (!input.filename) {
1679 fprintf(stderr,
"No input file specified!\n");
1684 if (global.codec->fourcc == VP9_FOURCC) input.only_i420 = 0;
1686 for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
1687 int frames_in = 0, seen_frames = 0;
1688 int64_t estimated_time_left = -1;
1689 int64_t average_rate = -1;
1690 int64_t lagged_count = 0;
1692 open_input_file(&input);
1697 if (!input.width || !input.height) {
1699 if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
1700 input.width = stream->config.cfg.g_w;
1701 input.height = stream->config.cfg.g_h;
1708 if (!input.width || !input.height)
1710 "Specify stream dimensions with --width (-w) "
1711 " and --height (-h)");
1718 if (!input.bit_depth) {
1720 if (stream->config.cfg.g_input_bit_depth)
1721 input.bit_depth = stream->config.cfg.g_input_bit_depth;
1723 input.bit_depth = stream->config.cfg.g_input_bit_depth =
1724 (
int)stream->config.cfg.g_bit_depth;
1729 { stream->config.cfg.g_input_bit_depth = input.bit_depth; });
1732 FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
1733 FOREACH_STREAM(validate_stream_config(stream, &global));
1738 if (global.pass && global.passes == 2)
1740 if (!stream->config.stats_fn)
1741 die(
"Stream %d: Must specify --fpf when --pass=%d"
1742 " and --passes=2\n",
1743 stream->index, global.pass);
1748 if (stream->config.write_webm) {
1749 stream->config.write_webm = 0;
1751 "vpxenc was compiled without WebM container support."
1752 "Producing IVF output");
1760 if (!global.have_framerate) {
1761 global.framerate.num = input.framerate.numerator;
1762 global.framerate.den = input.framerate.denominator;
1763 FOREACH_STREAM(stream->config.cfg.g_timebase.den = global.framerate.num;
1764 stream->config.cfg.g_timebase.num = global.framerate.den);
1768 if (global.verbose && pass == 0)
1769 FOREACH_STREAM(show_stream_config(stream, &global, &input));
1771 if (pass == (global.pass ? global.pass - 1 : 0)) {
1772 if (input.file_type == FILE_TYPE_Y4M)
1776 memset(&raw, 0,
sizeof(raw));
1778 vpx_img_alloc(&raw, input.fmt, input.width, input.height, 32);
1780 FOREACH_STREAM(stream->rate_hist = init_rate_histogram(
1781 &stream->config.cfg, &global.framerate));
1784 FOREACH_STREAM(setup_pass(stream, &global, pass));
1786 open_output_file(stream, &global, &input.pixel_aspect_ratio));
1787 FOREACH_STREAM(initialize_encoder(stream, &global));
1789 #if CONFIG_VP9_HIGHBITDEPTH
1790 if (strcmp(global.codec->name,
"vp9") == 0) {
1795 if (stream->config.use_16bit_internal) {
1796 use_16bit_internal = 1;
1798 if (stream->config.cfg.g_profile == 0) {
1801 input_shift = (int)stream->config.cfg.g_bit_depth -
1802 stream->config.cfg.g_input_bit_depth;
1811 while (frame_avail || got_data) {
1812 struct vpx_usec_timer timer;
1814 if (!global.limit || frames_in < global.limit) {
1815 frame_avail = read_frame(&input, &raw);
1817 if (frame_avail) frames_in++;
1819 frames_in > global.skip_frames ? frames_in - global.skip_frames : 0;
1821 if (!global.quiet) {
1822 float fps = usec_to_fps(cx_time, seen_frames);
1823 fprintf(stderr,
"\rPass %d/%d ", pass + 1, global.passes);
1825 if (stream_cnt == 1)
1826 fprintf(stderr,
"frame %4d/%-4d %7" PRId64
"B ", frames_in,
1827 streams->frames_out, (int64_t)streams->nbytes);
1829 fprintf(stderr,
"frame %4d ", frames_in);
1831 fprintf(stderr,
"%7" PRId64
" %s %.2f %s ",
1832 cx_time > 9999999 ? cx_time / 1000 : cx_time,
1833 cx_time > 9999999 ?
"ms" :
"us", fps >= 1.0 ? fps : fps * 60,
1834 fps >= 1.0 ?
"fps" :
"fpm");
1835 print_time(
"ETA", estimated_time_left);
1841 if (frames_in > global.skip_frames) {
1842 #if CONFIG_VP9_HIGHBITDEPTH
1844 if (input_shift || (use_16bit_internal && input.bit_depth == 8)) {
1845 assert(use_16bit_internal);
1848 if (!allocated_raw_shift) {
1850 input.width, input.height, 32);
1851 allocated_raw_shift = 1;
1853 vpx_img_upshift(&raw_shift, &raw, input_shift);
1854 frame_to_encode = &raw_shift;
1856 frame_to_encode = &raw;
1858 vpx_usec_timer_start(&timer);
1859 if (use_16bit_internal) {
1862 if (stream->config.use_16bit_internal)
1863 encode_frame(stream, &global,
1864 frame_avail ? frame_to_encode : NULL, frames_in);
1870 FOREACH_STREAM(encode_frame(stream, &global,
1871 frame_avail ? frame_to_encode : NULL,
1875 vpx_usec_timer_start(&timer);
1876 FOREACH_STREAM(encode_frame(stream, &global, frame_avail ? &raw : NULL,
1879 vpx_usec_timer_mark(&timer);
1880 cx_time += vpx_usec_timer_elapsed(&timer);
1882 FOREACH_STREAM(update_quantizer_histogram(stream));
1885 FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
1887 if (!got_data && input.length && streams != NULL &&
1888 !streams->frames_out) {
1889 lagged_count = global.limit ? seen_frames : ftello(input.file);
1890 }
else if (input.length) {
1895 const int64_t frame_in_lagged = (seen_frames - lagged_count) * 1000;
1897 rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
1898 remaining = 1000 * (global.limit - global.skip_frames -
1899 seen_frames + lagged_count);
1901 const int64_t input_pos = ftello(input.file);
1902 const int64_t input_pos_lagged = input_pos - lagged_count;
1903 const int64_t limit = input.length;
1905 rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0;
1906 remaining = limit - input_pos + lagged_count;
1910 (average_rate <= 0) ? rate : (average_rate * 7 + rate) / 8;
1911 estimated_time_left = average_rate ? remaining / average_rate : -1;
1914 if (got_data && global.test_decode != TEST_DECODE_OFF)
1915 FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec));
1919 if (!global.quiet) fprintf(stderr,
"\033[K");
1922 if (stream_cnt > 1) fprintf(stderr,
"\n");
1924 if (!global.quiet) {
1925 FOREACH_STREAM(fprintf(
1927 "\rPass %d/%d frame %4d/%-4d %7" PRId64
"B %7" PRId64
"b/f %7" PRId64
1928 "b/s %7" PRId64
" %s (%.2f fps)\033[K\n",
1929 pass + 1, global.passes, frames_in, stream->frames_out,
1930 (int64_t)stream->nbytes,
1931 seen_frames ? (int64_t)(stream->nbytes * 8 / seen_frames) : 0,
1933 ? (int64_t)stream->nbytes * 8 * (int64_t)global.framerate.num /
1934 global.framerate.den / seen_frames
1936 stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
1937 stream->cx_time > 9999999 ?
"ms" :
"us",
1938 usec_to_fps(stream->cx_time, seen_frames)));
1941 if (global.show_psnr) {
1942 if (global.codec->fourcc == VP9_FOURCC) {
1944 show_psnr(stream, (1 << stream->config.cfg.g_input_bit_depth) - 1));
1946 FOREACH_STREAM(show_psnr(stream, 255.0));
1952 if (global.test_decode != TEST_DECODE_OFF) {
1956 close_input_file(&input);
1958 if (global.test_decode == TEST_DECODE_FATAL) {
1959 FOREACH_STREAM(res |= stream->mismatch_seen);
1961 FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
1963 FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1));
1965 #if CONFIG_FP_MB_STATS
1966 FOREACH_STREAM(stats_close(&stream->fpmb_stats, global.passes - 1));
1969 if (global.pass)
break;
1972 if (global.show_q_hist_buckets)
1974 show_q_histogram(stream->counts, global.show_q_hist_buckets));
1976 if (global.show_rate_hist_buckets)
1977 FOREACH_STREAM(show_rate_histogram(stream->rate_hist, &stream->config.cfg,
1978 global.show_rate_hist_buckets));
1979 FOREACH_STREAM(destroy_rate_histogram(stream->rate_hist));
1981 #if CONFIG_INTERNAL_STATS
1985 if (!(global.pass == 1 && global.passes == 2))
1987 FILE *f = fopen(
"opsnr.stt",
"a");
1988 if (stream->mismatch_seen) {
1989 fprintf(f,
"First mismatch occurred in frame %d\n",
1990 stream->mismatch_seen);
1992 fprintf(f,
"No mismatch detected in recon buffers\n");
1998 #if CONFIG_VP9_HIGHBITDEPTH
2004 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:190
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:407
vpx_codec_err_t
Algorithm return codes.
Definition: vpx_codec.h:93
vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx, int ctrl_id,...)
Control algorithm.
@ VPX_BITS_8
Definition: vpx_codec.h:221
@ VPX_BITS_12
Definition: vpx_codec.h:223
@ VPX_BITS_10
Definition: vpx_codec.h:222
vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline)
Decode data.
#define vpx_codec_dec_init(ctx, iface, cfg, flags)
Convenience macro for vpx_codec_dec_init_ver()
Definition: vpx_decoder.h:143
#define VPX_DL_REALTIME
deadline parameter analogous to VPx REALTIME mode.
Definition: vpx_encoder.h: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 / constant 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:200
vpx_codec_err_t err
Definition: vpx_codec.h:203
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:72
vpx_img_fmt_t fmt
Definition: vpx_image.h:73
unsigned int d_h
Definition: vpx_image.h:84
unsigned int d_w
Definition: vpx_image.h:83
unsigned char * planes[4]
Definition: vpx_image.h:100
int stride[4]
Definition: vpx_image.h:101
Rational Number.
Definition: vpx_encoder.h: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:57
@ VPX_CS_SRGB
Definition: vpx_image.h:62
@ VPX_CS_BT_601
Definition: vpx_image.h:56
@ VPX_CS_BT_2020
Definition: vpx_image.h:60
@ VPX_CS_SMPTE_170
Definition: vpx_image.h:58
@ VPX_CS_UNKNOWN
Definition: vpx_image.h:55
@ VPX_CS_SMPTE_240
Definition: vpx_image.h:59
@ VPX_CS_RESERVED
Definition: vpx_image.h:61
#define VPX_PLANE_Y
Definition: vpx_image.h:96
#define VPX_IMG_FMT_HIGHBITDEPTH
Definition: vpx_image.h:35
#define VPX_PLANE_U
Definition: vpx_image.h:97
@ VPX_IMG_FMT_I42216
Definition: vpx_image.h:48
@ VPX_IMG_FMT_I44016
Definition: vpx_image.h:50
@ VPX_IMG_FMT_NV12
Definition: vpx_image.h:46
@ VPX_IMG_FMT_YV12
Definition: vpx_image.h:40
@ VPX_IMG_FMT_I42016
Definition: vpx_image.h:47
@ VPX_IMG_FMT_I444
Definition: vpx_image.h:44
@ VPX_IMG_FMT_I440
Definition: vpx_image.h:45
@ VPX_IMG_FMT_I44416
Definition: vpx_image.h:49
@ VPX_IMG_FMT_I420
Definition: vpx_image.h:42
@ VPX_IMG_FMT_I422
Definition: vpx_image.h:43
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:98
enum vpx_img_fmt vpx_img_fmt_t
List of supported image formats.
void vpx_img_free(vpx_image_t *img)
Close an image descriptor.