2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
12 /* This is a simple program that reads ivf files and decodes them
13 * using the new interface. Decoded frames are output as YV12 raw.
21 #define VPX_CODEC_DISABLE_COMPAT 1
22 #include "vpx_config.h"
23 #include "vpx/vpx_decoder.h"
24 #include "vpx_ports/vpx_timer.h"
25 #if CONFIG_VP9_DECODER
26 #include "vpx/vp8dx.h"
29 #include "md5_utils.h"
31 #include "tools_common.h"
32 #include "nestegg/include/nestegg/nestegg.h"
37 #define snprintf _snprintf
38 #define isatty _isatty
39 #define fileno _fileno
49 static const char *exec_name;
51 #define VP8_FOURCC (0x00385056)
54 const vpx_codec_iface_t *(*iface)(void);
56 unsigned int fourcc_mask;
58 #if CONFIG_VP9_DECODER
59 {"vp9", vpx_codec_vp8_dx, VP8_FOURCC, 0x00FFFFFF},
64 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
66 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
67 "Output raw YV12 frames");
68 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
69 "Output raw I420 frames");
70 static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
71 "Flip the chroma planes in the output");
72 static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
73 "Don't process the decoded frames");
74 static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
75 "Show progress after each frame decodes");
76 static const arg_def_t limitarg = ARG_DEF(NULL, "limit", 1,
77 "Stop decoding after n frames");
78 static const arg_def_t skiparg = ARG_DEF(NULL, "skip", 1,
79 "Skip the first n input frames");
80 static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
81 "Postprocess decoded frames");
82 static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
83 "Show timing summary");
84 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
85 "Output file name pattern (see below)");
86 static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
87 "Max threads to use");
88 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
89 "Show version string");
90 static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0,
91 "Enable decoder error-concealment");
95 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
96 "Compute the MD5 sum of the decoded frame");
98 static const arg_def_t *all_args[] = {
99 &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
100 &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
101 &threadsarg, &verbosearg,
109 #if CONFIG_VP9_DECODER
110 static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1,
111 "Enable VP8 postproc add noise");
112 static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0,
113 "Enable VP8 deblocking");
114 static const arg_def_t demacroblock_level = ARG_DEF(NULL, "demacroblock-level", 1,
115 "Enable VP8 demacroblocking, w/ level");
116 static const arg_def_t pp_debug_info = ARG_DEF(NULL, "pp-debug-info", 1,
117 "Enable VP8 visible debug info");
118 static const arg_def_t pp_disp_ref_frame = ARG_DEF(NULL, "pp-dbg-ref-frame", 1,
119 "Display only selected reference frame per macro block");
120 static const arg_def_t pp_disp_mb_modes = ARG_DEF(NULL, "pp-dbg-mb-modes", 1,
121 "Display only selected macro block modes");
122 static const arg_def_t pp_disp_b_modes = ARG_DEF(NULL, "pp-dbg-b-modes", 1,
123 "Display only selected block modes");
124 static const arg_def_t pp_disp_mvs = ARG_DEF(NULL, "pp-dbg-mvs", 1,
125 "Draw only selected motion vectors");
126 static const arg_def_t mfqe = ARG_DEF(NULL, "mfqe", 0,
127 "Enable multiframe quality enhancement");
129 static const arg_def_t *vp8_pp_args[] = {
130 &addnoise_level, &deblock, &demacroblock_level, &pp_debug_info,
131 &pp_disp_ref_frame, &pp_disp_mb_modes, &pp_disp_b_modes, &pp_disp_mvs, &mfqe,
136 static void usage_exit() {
139 fprintf(stderr, "Usage: %s <options> filename\n\n"
140 "Options:\n", exec_name);
141 arg_show_usage(stderr, all_args);
142 #if CONFIG_VP9_DECODER
143 fprintf(stderr, "\nVP8 Postprocessing Options:\n");
144 arg_show_usage(stderr, vp8_pp_args);
147 "\nOutput File Patterns:\n\n"
148 " The -o argument specifies the name of the file(s) to "
149 "write to. If the\n argument does not include any escape "
150 "characters, the output will be\n written to a single file. "
151 "Otherwise, the filename will be calculated by\n expanding "
152 "the following escape characters:\n");
154 "\n\t%%w - Frame width"
155 "\n\t%%h - Frame height"
156 "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
157 "\n\n Pattern arguments are only supported in conjunction "
158 "with the --yv12 and\n --i420 options. If the -o option is "
159 "not specified, the output will be\n directed to stdout.\n"
161 fprintf(stderr, "\nIncluded decoders:\n\n");
163 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
164 fprintf(stderr, " %-6s - %s\n",
166 vpx_codec_iface_name(ifaces[i].iface()));
171 void die(const char *fmt, ...) {
174 vfprintf(stderr, fmt, ap);
175 fprintf(stderr, "\n");
179 static unsigned int mem_get_le16(const void *vmem) {
181 const unsigned char *mem = (const unsigned char *)vmem;
188 static unsigned int mem_get_le32(const void *vmem) {
190 const unsigned char *mem = (const unsigned char *)vmem;
208 nestegg *nestegg_ctx;
212 unsigned int video_track;
215 #define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
216 #define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
217 static int read_frame(struct input_ctx *input,
220 size_t *buf_alloc_sz) {
221 char raw_hdr[IVF_FRAME_HDR_SZ];
223 FILE *infile = input->infile;
224 enum file_kind kind = input->kind;
225 if (kind == WEBM_FILE) {
226 if (input->chunk >= input->chunks) {
230 /* End of this packet, get another. */
232 nestegg_free_packet(input->pkt);
234 if (nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
235 || nestegg_packet_track(input->pkt, &track))
238 } while (track != input->video_track);
240 if (nestegg_packet_count(input->pkt, &input->chunks))
245 if (nestegg_packet_data(input->pkt, input->chunk, buf, buf_sz))
251 /* For both the raw and ivf formats, the frame size is the first 4 bytes
252 * of the frame header. We just need to special case on the header
255 else if (fread(raw_hdr, kind == IVF_FILE
256 ? IVF_FRAME_HDR_SZ : RAW_FRAME_HDR_SZ, 1, infile) != 1) {
258 fprintf(stderr, "Failed to read frame size\n");
262 new_buf_sz = mem_get_le32(raw_hdr);
264 if (new_buf_sz > 256 * 1024 * 1024) {
265 fprintf(stderr, "Error: Read invalid frame size (%u)\n",
266 (unsigned int)new_buf_sz);
270 if (kind == RAW_FILE && new_buf_sz > 256 * 1024)
271 fprintf(stderr, "Warning: Read invalid frame size (%u)"
272 " - not a raw file?\n", (unsigned int)new_buf_sz);
274 if (new_buf_sz > *buf_alloc_sz) {
275 uint8_t *new_buf = realloc(*buf, 2 * new_buf_sz);
279 *buf_alloc_sz = 2 * new_buf_sz;
281 fprintf(stderr, "Failed to allocate compressed data buffer\n");
287 *buf_sz = new_buf_sz;
290 if (fread(*buf, 1, *buf_sz, infile) != *buf_sz) {
291 fprintf(stderr, "Failed to read full frame\n");
301 void *out_open(const char *out_fn, int do_md5) {
306 MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
311 FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb")
312 : set_binary_mode(stdout);
315 fprintf(stderr, "Failed to output file");
323 void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5) {
326 MD5Update(out, buf, len);
329 (void) fwrite(buf, 1, len, out);
333 void out_close(void *out, const char *out_fn, int do_md5) {
342 for (i = 0; i < 16; i++)
343 printf("%02x", md5[i]);
345 printf(" %s\n", out_fn);
352 unsigned int file_is_ivf(FILE *infile,
353 unsigned int *fourcc,
355 unsigned int *height,
356 unsigned int *fps_den,
357 unsigned int *fps_num) {
361 if (fread(raw_hdr, 1, 32, infile) == 32) {
362 if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
363 && raw_hdr[2] == 'I' && raw_hdr[3] == 'F') {
366 if (mem_get_le16(raw_hdr + 4) != 0)
367 fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
368 " decode properly.");
370 *fourcc = mem_get_le32(raw_hdr + 8);
371 *width = mem_get_le16(raw_hdr + 12);
372 *height = mem_get_le16(raw_hdr + 14);
373 *fps_num = mem_get_le32(raw_hdr + 16);
374 *fps_den = mem_get_le32(raw_hdr + 20);
376 /* Some versions of vpxenc used 1/(2*fps) for the timebase, so
377 * we can guess the framerate using only the timebase in this
378 * case. Other files would require reading ahead to guess the
379 * timebase, like we do for webm.
381 if (*fps_num < 1000) {
382 /* Correct for the factor of 2 applied to the timebase in the
385 if (*fps_num & 1)*fps_den <<= 1;
388 /* Don't know FPS for sure, and don't have readahead code
389 * (yet?), so just default to 30fps.
404 unsigned int file_is_raw(FILE *infile,
405 unsigned int *fourcc,
407 unsigned int *height,
408 unsigned int *fps_den,
409 unsigned int *fps_num) {
410 unsigned char buf[32];
412 vpx_codec_stream_info_t si;
416 if (fread(buf, 1, 32, infile) == 32) {
419 if (mem_get_le32(buf) < 256 * 1024 * 1024)
420 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
421 if (!vpx_codec_peek_stream_info(ifaces[i].iface(),
422 buf + 4, 32 - 4, &si)) {
424 *fourcc = ifaces[i].fourcc;
439 nestegg_read_cb(void *buffer, size_t length, void *userdata) {
442 if (fread(buffer, 1, length, f) < length) {
453 nestegg_seek_cb(int64_t offset, int whence, void *userdata) {
455 case NESTEGG_SEEK_SET:
458 case NESTEGG_SEEK_CUR:
461 case NESTEGG_SEEK_END:
465 return fseek(userdata, (long)offset, whence) ? -1 : 0;
470 nestegg_tell_cb(void *userdata) {
471 return ftell(userdata);
476 nestegg_log_cb(nestegg *context, unsigned int severity, char const *format,
480 va_start(ap, format);
481 vfprintf(stderr, format, ap);
482 fprintf(stderr, "\n");
488 webm_guess_framerate(struct input_ctx *input,
489 unsigned int *fps_den,
490 unsigned int *fps_num) {
494 /* Guess the framerate. Read up to 1 second, or 50 video packets,
495 * whichever comes first.
497 for (i = 0; tstamp < 1000000000 && i < 50;) {
501 if (nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
504 nestegg_packet_track(pkt, &track);
505 if (track == input->video_track) {
506 nestegg_packet_tstamp(pkt, &tstamp);
510 nestegg_free_packet(pkt);
513 if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
516 *fps_num = (i - 1) * 1000000;
517 *fps_den = (unsigned int)(tstamp / 1000);
520 nestegg_destroy(input->nestegg_ctx);
521 input->nestegg_ctx = NULL;
522 rewind(input->infile);
528 file_is_webm(struct input_ctx *input,
529 unsigned int *fourcc,
531 unsigned int *height,
532 unsigned int *fps_den,
533 unsigned int *fps_num) {
537 nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
538 nestegg_video_params params;
540 io.userdata = input->infile;
541 if (nestegg_init(&input->nestegg_ctx, io, NULL))
544 if (nestegg_track_count(input->nestegg_ctx, &n))
547 for (i = 0; i < n; i++) {
548 track_type = nestegg_track_type(input->nestegg_ctx, i);
550 if (track_type == NESTEGG_TRACK_VIDEO)
552 else if (track_type < 0)
556 if (nestegg_track_codec_id(input->nestegg_ctx, i) != NESTEGG_CODEC_VP8) {
557 fprintf(stderr, "Not VP8 video, quitting.\n");
561 input->video_track = i;
563 if (nestegg_track_video_params(input->nestegg_ctx, i, ¶ms))
568 *fourcc = VP8_FOURCC;
569 *width = params.width;
570 *height = params.height;
573 input->nestegg_ctx = NULL;
574 rewind(input->infile);
579 void show_progress(int frame_in, int frame_out, unsigned long dx_time) {
580 fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
581 frame_in, frame_out, dx_time,
582 (float)frame_out * 1000000.0 / (float)dx_time);
586 void generate_filename(const char *pattern, char *out, size_t q_len,
587 unsigned int d_w, unsigned int d_h,
588 unsigned int frame_in) {
589 const char *p = pattern;
593 char *next_pat = strchr(p, '%');
598 /* parse the pattern */
602 snprintf(q, q_len - 1, "%d", d_w);
605 snprintf(q, q_len - 1, "%d", d_h);
608 snprintf(q, q_len - 1, "%d", frame_in);
611 snprintf(q, q_len - 1, "%02d", frame_in);
614 snprintf(q, q_len - 1, "%03d", frame_in);
617 snprintf(q, q_len - 1, "%04d", frame_in);
620 snprintf(q, q_len - 1, "%05d", frame_in);
623 snprintf(q, q_len - 1, "%06d", frame_in);
626 snprintf(q, q_len - 1, "%07d", frame_in);
629 snprintf(q, q_len - 1, "%08d", frame_in);
632 snprintf(q, q_len - 1, "%09d", frame_in);
635 die("Unrecognized pattern %%%c\n", p[1]);
639 if (pat_len >= q_len - 1)
640 die("Output filename too long.\n");
647 /* copy the next segment */
649 copy_len = strlen(p);
651 copy_len = next_pat - p;
653 if (copy_len >= q_len - 1)
654 die("Output filename too long.\n");
656 memcpy(q, p, copy_len);
666 int main(int argc, const char **argv_) {
667 vpx_codec_ctx_t decoder;
671 size_t buf_sz = 0, buf_alloc_sz = 0;
673 int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
674 int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
677 vpx_codec_iface_t *iface = NULL;
679 unsigned long dx_time = 0;
681 char **argv, **argi, **argj;
682 const char *outfile_pattern = 0;
683 char outfile[PATH_MAX];
688 unsigned int fps_den;
689 unsigned int fps_num;
691 vpx_codec_dec_cfg_t cfg = {0};
692 #if CONFIG_VP9_DECODER
693 vp8_postproc_cfg_t vp8_pp_cfg = {0};
694 int vp8_dbg_color_ref_frame = 0;
695 int vp8_dbg_color_mb_modes = 0;
696 int vp8_dbg_color_b_modes = 0;
697 int vp8_dbg_display_mv = 0;
699 struct input_ctx input = {0};
700 int frames_corrupted = 0;
703 /* Parse command line */
704 exec_name = argv_[0];
705 argv = argv_dup(argc - 1, argv_ + 1);
707 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
708 memset(&arg, 0, sizeof(arg));
711 if (arg_match(&arg, &codecarg, argi)) {
714 for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
715 if (!strcmp(ifaces[j].name, arg.val))
719 iface = ifaces[k].iface();
721 die("Error: Unrecognized argument (%s) to --codec\n",
723 } else if (arg_match(&arg, &outputfile, argi))
724 outfile_pattern = arg.val;
725 else if (arg_match(&arg, &use_yv12, argi)) {
728 } else if (arg_match(&arg, &use_i420, argi)) {
731 } else if (arg_match(&arg, &flipuvarg, argi))
733 else if (arg_match(&arg, &noblitarg, argi))
735 else if (arg_match(&arg, &progressarg, argi))
737 else if (arg_match(&arg, &limitarg, argi))
738 stop_after = arg_parse_uint(&arg);
739 else if (arg_match(&arg, &skiparg, argi))
740 arg_skip = arg_parse_uint(&arg);
741 else if (arg_match(&arg, &postprocarg, argi))
743 else if (arg_match(&arg, &md5arg, argi))
745 else if (arg_match(&arg, &summaryarg, argi))
747 else if (arg_match(&arg, &threadsarg, argi))
748 cfg.threads = arg_parse_uint(&arg);
749 else if (arg_match(&arg, &verbosearg, argi))
752 #if CONFIG_VP9_DECODER
753 else if (arg_match(&arg, &addnoise_level, argi)) {
755 vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE;
756 vp8_pp_cfg.noise_level = arg_parse_uint(&arg);
757 } else if (arg_match(&arg, &demacroblock_level, argi)) {
759 vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK;
760 vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg);
761 } else if (arg_match(&arg, &deblock, argi)) {
763 vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK;
764 } else if (arg_match(&arg, &mfqe, argi)) {
766 vp8_pp_cfg.post_proc_flag |= VP8_MFQE;
767 } else if (arg_match(&arg, &pp_debug_info, argi)) {
768 unsigned int level = arg_parse_uint(&arg);
771 vp8_pp_cfg.post_proc_flag &= ~0x7;
774 vp8_pp_cfg.post_proc_flag |= level;
775 } else if (arg_match(&arg, &pp_disp_ref_frame, argi)) {
776 unsigned int flags = arg_parse_int(&arg);
779 vp8_dbg_color_ref_frame = flags;
781 } else if (arg_match(&arg, &pp_disp_mb_modes, argi)) {
782 unsigned int flags = arg_parse_int(&arg);
785 vp8_dbg_color_mb_modes = flags;
787 } else if (arg_match(&arg, &pp_disp_b_modes, argi)) {
788 unsigned int flags = arg_parse_int(&arg);
791 vp8_dbg_color_b_modes = flags;
793 } else if (arg_match(&arg, &pp_disp_mvs, argi)) {
794 unsigned int flags = arg_parse_int(&arg);
797 vp8_dbg_display_mv = flags;
799 } else if (arg_match(&arg, &error_concealment, argi)) {
808 /* Check for unrecognized options */
809 for (argi = argv; *argi; argi++)
810 if (argi[0][0] == '-' && strlen(argi[0]) > 1)
811 die("Error: Unrecognized option %s\n", *argi);
813 /* Handle non-option arguments */
820 infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin);
823 fprintf(stderr, "Failed to open file '%s'",
824 strcmp(fn, "-") ? fn : "stdin");
827 #if CONFIG_OS_SUPPORT
828 /* Make sure we don't dump to the terminal, unless forced to with -o - */
829 if (!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit) {
831 "Not dumping raw video to your terminal. Use '-o -' to "
836 input.infile = infile;
837 if (file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
839 input.kind = IVF_FILE;
840 else if (file_is_webm(&input, &fourcc, &width, &height, &fps_den, &fps_num))
841 input.kind = WEBM_FILE;
842 else if (file_is_raw(infile, &fourcc, &width, &height, &fps_den, &fps_num))
843 input.kind = RAW_FILE;
845 fprintf(stderr, "Unrecognized input file type.\n");
849 /* If the output file is not set or doesn't have a sequence number in
850 * it, then we only open it once.
852 outfile_pattern = outfile_pattern ? outfile_pattern : "-";
855 const char *p = outfile_pattern;
858 if (p && p[1] >= '1' && p[1] <= '9') {
859 /* pattern contains sequence number, so it's not unique. */
868 if (single_file && !noblit) {
869 generate_filename(outfile_pattern, outfile, sizeof(outfile) - 1,
871 out = out_open(outfile, do_md5);
874 if (use_y4m && !noblit) {
877 fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
878 " try --i420 or --yv12.\n");
882 if (input.kind == WEBM_FILE)
883 if (webm_guess_framerate(&input, &fps_den, &fps_num)) {
884 fprintf(stderr, "Failed to guess framerate -- error parsing "
890 /*Note: We can't output an aspect ratio here because IVF doesn't
891 store one, and neither does VP8.
892 That will have to wait until these tools support WebM natively.*/
893 sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
894 "420jpeg", width, height, fps_num, fps_den, 'p');
895 out_put(out, (unsigned char *)buffer,
896 (unsigned int)strlen(buffer), do_md5);
899 /* Try to determine the codec from the fourcc. */
900 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
901 if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc) {
902 vpx_codec_iface_t *ivf_iface = ifaces[i].iface();
904 if (iface && iface != ivf_iface)
905 fprintf(stderr, "Notice -- IVF header indicates codec: %s\n",
913 dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
914 (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
915 if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface(), &cfg,
917 fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
922 fprintf(stderr, "%s\n", decoder.name);
924 #if CONFIG_VP9_DECODER
926 if (vp8_pp_cfg.post_proc_flag
927 && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) {
928 fprintf(stderr, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder));
932 if (vp8_dbg_color_ref_frame
933 && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME, vp8_dbg_color_ref_frame)) {
934 fprintf(stderr, "Failed to configure reference block visualizer: %s\n", vpx_codec_error(&decoder));
938 if (vp8_dbg_color_mb_modes
939 && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES, vp8_dbg_color_mb_modes)) {
940 fprintf(stderr, "Failed to configure macro block visualizer: %s\n", vpx_codec_error(&decoder));
944 if (vp8_dbg_color_b_modes
945 && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES, vp8_dbg_color_b_modes)) {
946 fprintf(stderr, "Failed to configure block visualizer: %s\n", vpx_codec_error(&decoder));
950 if (vp8_dbg_display_mv
951 && vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vp8_dbg_display_mv)) {
952 fprintf(stderr, "Failed to configure motion vector visualizer: %s\n", vpx_codec_error(&decoder));
959 fprintf(stderr, "Skiping first %d frames.\n", arg_skip);
961 if (read_frame(&input, &buf, &buf_sz, &buf_alloc_sz))
967 while (!read_frame(&input, &buf, &buf_sz, &buf_alloc_sz)) {
968 vpx_codec_iter_t iter = NULL;
970 struct vpx_usec_timer timer;
973 vpx_usec_timer_start(&timer);
975 if (vpx_codec_decode(&decoder, buf, (unsigned int)buf_sz, NULL, 0)) {
976 const char *detail = vpx_codec_error_detail(&decoder);
977 fprintf(stderr, "Failed to decode frame: %s\n", vpx_codec_error(&decoder));
980 fprintf(stderr, " Additional information: %s\n", detail);
985 vpx_usec_timer_mark(&timer);
986 dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
990 if (vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) {
991 fprintf(stderr, "Failed VP8_GET_FRAME_CORRUPTED: %s\n",
992 vpx_codec_error(&decoder));
995 frames_corrupted += corrupted;
997 vpx_usec_timer_start(&timer);
999 if ((img = vpx_codec_get_frame(&decoder, &iter)))
1002 vpx_usec_timer_mark(&timer);
1003 dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
1006 show_progress(frame_in, frame_out, dx_time);
1011 char out_fn[PATH_MAX];
1015 size_t len = sizeof(out_fn) - 1;
1018 generate_filename(outfile_pattern, out_fn, len - 1,
1019 img->d_w, img->d_h, frame_in);
1020 out = out_open(out_fn, do_md5);
1022 out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
1024 buf = img->planes[VPX_PLANE_Y];
1026 for (y = 0; y < img->d_h; y++) {
1027 out_put(out, buf, img->d_w, do_md5);
1028 buf += img->stride[VPX_PLANE_Y];
1031 buf = img->planes[flipuv ? VPX_PLANE_V : VPX_PLANE_U];
1033 for (y = 0; y < (1 + img->d_h) / 2; y++) {
1034 out_put(out, buf, (1 + img->d_w) / 2, do_md5);
1035 buf += img->stride[VPX_PLANE_U];
1038 buf = img->planes[flipuv ? VPX_PLANE_U : VPX_PLANE_V];
1040 for (y = 0; y < (1 + img->d_h) / 2; y++) {
1041 out_put(out, buf, (1 + img->d_w) / 2, do_md5);
1042 buf += img->stride[VPX_PLANE_V];
1046 out_close(out, out_fn, do_md5);
1050 if (stop_after && frame_in >= stop_after)
1054 if (summary || progress) {
1055 show_progress(frame_in, frame_out, dx_time);
1056 fprintf(stderr, "\n");
1059 if (frames_corrupted)
1060 fprintf(stderr, "WARNING: %d frames corrupted.\n", frames_corrupted);
1064 if (vpx_codec_destroy(&decoder)) {
1065 fprintf(stderr, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder));
1066 return EXIT_FAILURE;
1069 if (single_file && !noblit)
1070 out_close(out, outfile, do_md5);
1072 if (input.nestegg_ctx)
1073 nestegg_destroy(input.nestegg_ctx);
1074 if (input.kind != WEBM_FILE)
1079 return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS;