22 #define VPX_CODEC_DISABLE_COMPAT 1
23 #include "vpx_config.h"
25 #include "vpx_ports/vpx_timer.h"
26 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
30 #include "md5_utils.h"
32 #include "tools_common.h"
33 #include "nestegg/include/nestegg/nestegg.h"
34 #include "third_party/libyuv/include/libyuv/scale.h"
36 static const char *exec_name;
42 unsigned int fourcc_mask;
44 #if CONFIG_VP8_DECODER
45 {
"vp8", vpx_codec_vp8_dx, VP8_FOURCC_MASK, 0x00FFFFFF},
47 #if CONFIG_VP9_DECODER
48 {
"vp9", vpx_codec_vp9_dx, VP9_FOURCC_MASK, 0x00FFFFFF},
53 static const arg_def_t looparg = ARG_DEF(NULL,
"loops", 1,
54 "Number of times to decode the file");
55 static const arg_def_t codecarg = ARG_DEF(NULL,
"codec", 1,
57 static const arg_def_t use_yv12 = ARG_DEF(NULL,
"yv12", 0,
58 "Output raw YV12 frames");
59 static const arg_def_t use_i420 = ARG_DEF(NULL,
"i420", 0,
60 "Output raw I420 frames");
61 static const arg_def_t flipuvarg = ARG_DEF(NULL,
"flipuv", 0,
62 "Flip the chroma planes in the output");
63 static const arg_def_t noblitarg = ARG_DEF(NULL,
"noblit", 0,
64 "Don't process the decoded frames");
65 static const arg_def_t progressarg = ARG_DEF(NULL,
"progress", 0,
66 "Show progress after each frame decodes");
67 static const arg_def_t limitarg = ARG_DEF(NULL,
"limit", 1,
68 "Stop decoding after n frames");
69 static const arg_def_t skiparg = ARG_DEF(NULL,
"skip", 1,
70 "Skip the first n input frames");
71 static const arg_def_t postprocarg = ARG_DEF(NULL,
"postproc", 0,
72 "Postprocess decoded frames");
73 static const arg_def_t summaryarg = ARG_DEF(NULL,
"summary", 0,
74 "Show timing summary");
75 static const arg_def_t outputfile = ARG_DEF(
"o",
"output", 1,
76 "Output file name pattern (see below)");
77 static const arg_def_t threadsarg = ARG_DEF(
"t",
"threads", 1,
78 "Max threads to use");
79 static const arg_def_t verbosearg = ARG_DEF(
"v",
"verbose", 0,
80 "Show version string");
81 static const arg_def_t error_concealment = ARG_DEF(NULL,
"error-concealment", 0,
82 "Enable decoder error-concealment");
83 static const arg_def_t scalearg = ARG_DEF(
"S",
"scale", 0,
84 "Scale output frames uniformly");
88 static const arg_def_t md5arg = ARG_DEF(NULL,
"md5", 0,
89 "Compute the MD5 sum of the decoded frame");
91 static const arg_def_t *all_args[] = {
92 &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
93 &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
94 &threadsarg, &verbosearg, &scalearg,
102 #if CONFIG_VP8_DECODER
103 static const arg_def_t addnoise_level = ARG_DEF(NULL,
"noise-level", 1,
104 "Enable VP8 postproc add noise");
105 static const arg_def_t deblock = ARG_DEF(NULL,
"deblock", 0,
106 "Enable VP8 deblocking");
107 static const arg_def_t demacroblock_level = ARG_DEF(NULL,
"demacroblock-level", 1,
108 "Enable VP8 demacroblocking, w/ level");
109 static const arg_def_t pp_debug_info = ARG_DEF(NULL,
"pp-debug-info", 1,
110 "Enable VP8 visible debug info");
111 static const arg_def_t pp_disp_ref_frame = ARG_DEF(NULL,
"pp-dbg-ref-frame", 1,
112 "Display only selected reference frame per macro block");
113 static const arg_def_t pp_disp_mb_modes = ARG_DEF(NULL,
"pp-dbg-mb-modes", 1,
114 "Display only selected macro block modes");
115 static const arg_def_t pp_disp_b_modes = ARG_DEF(NULL,
"pp-dbg-b-modes", 1,
116 "Display only selected block modes");
117 static const arg_def_t pp_disp_mvs = ARG_DEF(NULL,
"pp-dbg-mvs", 1,
118 "Draw only selected motion vectors");
119 static const arg_def_t mfqe = ARG_DEF(NULL,
"mfqe", 0,
120 "Enable multiframe quality enhancement");
122 static const arg_def_t *vp8_pp_args[] = {
123 &addnoise_level, &deblock, &demacroblock_level, &pp_debug_info,
124 &pp_disp_ref_frame, &pp_disp_mb_modes, &pp_disp_b_modes, &pp_disp_mvs, &mfqe,
132 fprintf(stderr,
"Usage: %s <options> filename\n\n"
133 "Options:\n", exec_name);
134 arg_show_usage(stderr, all_args);
135 #if CONFIG_VP8_DECODER
136 fprintf(stderr,
"\nVP8 Postprocessing Options:\n");
137 arg_show_usage(stderr, vp8_pp_args);
140 "\nOutput File Patterns:\n\n"
141 " The -o argument specifies the name of the file(s) to "
142 "write to. If the\n argument does not include any escape "
143 "characters, the output will be\n written to a single file. "
144 "Otherwise, the filename will be calculated by\n expanding "
145 "the following escape characters:\n");
147 "\n\t%%w - Frame width"
148 "\n\t%%h - Frame height"
149 "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
150 "\n\n Pattern arguments are only supported in conjunction "
151 "with the --yv12 and\n --i420 options. If the -o option is "
152 "not specified, the output will be\n directed to stdout.\n"
154 fprintf(stderr,
"\nIncluded decoders:\n\n");
156 for (i = 0; i <
sizeof(ifaces) /
sizeof(ifaces[0]); i++)
157 fprintf(stderr,
" %-6s - %s\n",
164 static unsigned int mem_get_le16(
const void *vmem) {
166 const unsigned char *mem = (
const unsigned char *)vmem;
173 static unsigned int mem_get_le32(
const void *vmem) {
175 const unsigned char *mem = (
const unsigned char *)vmem;
193 nestegg *nestegg_ctx;
197 unsigned int video_track;
200 #define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
201 #define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
202 static int read_frame(
struct input_ctx *input,
205 size_t *buf_alloc_sz) {
206 char raw_hdr[IVF_FRAME_HDR_SZ];
208 FILE *infile = input->infile;
209 enum file_kind kind = input->kind;
210 if (kind == WEBM_FILE) {
211 if (input->chunk >= input->chunks) {
217 nestegg_free_packet(input->pkt);
219 if (nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
220 || nestegg_packet_track(input->pkt, &track))
223 }
while (track != input->video_track);
225 if (nestegg_packet_count(input->pkt, &input->chunks))
230 if (nestegg_packet_data(input->pkt, input->chunk, buf, buf_sz))
240 else if (fread(raw_hdr, kind == IVF_FILE
241 ? IVF_FRAME_HDR_SZ : RAW_FRAME_HDR_SZ, 1, infile) != 1) {
243 fprintf(stderr,
"Failed to read frame size\n");
247 new_buf_sz = mem_get_le32(raw_hdr);
249 if (new_buf_sz > 256 * 1024 * 1024) {
250 fprintf(stderr,
"Error: Read invalid frame size (%u)\n",
251 (
unsigned int)new_buf_sz);
255 if (kind == RAW_FILE && new_buf_sz > 256 * 1024)
256 fprintf(stderr,
"Warning: Read invalid frame size (%u)"
257 " - not a raw file?\n", (
unsigned int)new_buf_sz);
259 if (new_buf_sz > *buf_alloc_sz) {
260 uint8_t *new_buf = realloc(*buf, 2 * new_buf_sz);
264 *buf_alloc_sz = 2 * new_buf_sz;
266 fprintf(stderr,
"Failed to allocate compressed data buffer\n");
272 *buf_sz = new_buf_sz;
275 if (fread(*buf, 1, *buf_sz, infile) != *buf_sz) {
276 fprintf(stderr,
"Failed to read full frame\n");
286 void *out_open(
const char *out_fn,
int do_md5) {
291 MD5Context *md5_ctx = out = malloc(
sizeof(MD5Context));
296 FILE *outfile = out = strcmp(
"-", out_fn) ? fopen(out_fn,
"wb")
297 : set_binary_mode(stdout);
300 fprintf(stderr,
"Failed to output file");
308 void out_put(
void *out,
const uint8_t *buf,
unsigned int len,
int do_md5) {
311 MD5Update(out, buf, len);
314 (void) fwrite(buf, 1, len, out);
318 void out_close(
void *out,
const char *out_fn,
int do_md5) {
327 for (i = 0; i < 16; i++)
328 printf(
"%02x", md5[i]);
330 printf(
" %s\n", out_fn);
337 unsigned int file_is_ivf(FILE *infile,
338 unsigned int *fourcc,
340 unsigned int *height,
341 unsigned int *fps_den,
342 unsigned int *fps_num) {
346 if (fread(raw_hdr, 1, 32, infile) == 32) {
347 if (raw_hdr[0] ==
'D' && raw_hdr[1] ==
'K'
348 && raw_hdr[2] ==
'I' && raw_hdr[3] ==
'F') {
351 if (mem_get_le16(raw_hdr + 4) != 0)
352 fprintf(stderr,
"Error: Unrecognized IVF version! This file may not"
353 " decode properly.");
355 *fourcc = mem_get_le32(raw_hdr + 8);
356 *width = mem_get_le16(raw_hdr + 12);
357 *height = mem_get_le16(raw_hdr + 14);
358 *fps_num = mem_get_le32(raw_hdr + 16);
359 *fps_den = mem_get_le32(raw_hdr + 20);
366 if (*fps_num < 1000) {
370 if (*fps_num & 1)*fps_den <<= 1;
389 unsigned int file_is_raw(FILE *infile,
390 unsigned int *fourcc,
392 unsigned int *height,
393 unsigned int *fps_den,
394 unsigned int *fps_num) {
395 unsigned char buf[32];
401 if (fread(buf, 1, 32, infile) == 32) {
404 if (mem_get_le32(buf) < 256 * 1024 * 1024)
405 for (i = 0; i <
sizeof(ifaces) /
sizeof(ifaces[0]); i++)
407 buf + 4, 32 - 4, &si)) {
409 *fourcc = ifaces[i].fourcc;
424 nestegg_read_cb(
void *buffer,
size_t length,
void *userdata) {
427 if (fread(buffer, 1, length, f) < length) {
438 nestegg_seek_cb(int64_t offset,
int whence,
void *userdata) {
440 case NESTEGG_SEEK_SET:
443 case NESTEGG_SEEK_CUR:
446 case NESTEGG_SEEK_END:
450 return fseek(userdata, (
long)offset, whence) ? -1 : 0;
455 nestegg_tell_cb(
void *userdata) {
456 return ftell(userdata);
461 nestegg_log_cb(nestegg *context,
unsigned int severity,
char const *format,
465 va_start(ap, format);
466 vfprintf(stderr, format, ap);
467 fprintf(stderr,
"\n");
473 webm_guess_framerate(
struct input_ctx *input,
474 unsigned int *fps_den,
475 unsigned int *fps_num) {
480 if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0)) {
482 "WARNING: Failed to guess framerate (no Cues), set to 30fps.\n");
491 for (i = 0; tstamp < 1000000000 && i < 50;) {
495 if (nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
498 nestegg_packet_track(pkt, &track);
499 if (track == input->video_track) {
500 nestegg_packet_tstamp(pkt, &tstamp);
504 nestegg_free_packet(pkt);
507 if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
510 *fps_num = (i - 1) * 1000000;
511 *fps_den = (
unsigned int)(tstamp / 1000);
514 nestegg_destroy(input->nestegg_ctx);
515 input->nestegg_ctx = NULL;
516 rewind(input->infile);
522 file_is_webm(
struct input_ctx *input,
523 unsigned int *fourcc,
525 unsigned int *height,
526 unsigned int *fps_den,
527 unsigned int *fps_num) {
532 nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
533 nestegg_video_params params;
535 io.userdata = input->infile;
536 if (nestegg_init(&input->nestegg_ctx, io, NULL))
539 if (nestegg_track_count(input->nestegg_ctx, &n))
542 for (i = 0; i < n; i++) {
543 track_type = nestegg_track_type(input->nestegg_ctx, i);
545 if (track_type == NESTEGG_TRACK_VIDEO)
547 else if (track_type < 0)
551 codec_id = nestegg_track_codec_id(input->nestegg_ctx, i);
552 if (codec_id == NESTEGG_CODEC_VP8) {
553 *fourcc = VP8_FOURCC_MASK;
554 }
else if (codec_id == NESTEGG_CODEC_VP9) {
555 *fourcc = VP9_FOURCC_MASK;
557 fprintf(stderr,
"Not VPx video, quitting.\n");
561 input->video_track = i;
563 if (nestegg_track_video_params(input->nestegg_ctx, i, ¶ms))
568 *width = params.width;
569 *height = params.height;
572 input->nestegg_ctx = NULL;
573 rewind(input->infile);
578 void show_progress(
int frame_in,
int frame_out,
unsigned long dx_time) {
579 fprintf(stderr,
"%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
580 frame_in, frame_out, dx_time,
581 (
float)frame_out * 1000000.0 / (
float)dx_time);
585 void generate_filename(
const char *pattern,
char *out,
size_t q_len,
586 unsigned int d_w,
unsigned int d_h,
587 unsigned int frame_in) {
588 const char *p = pattern;
592 char *next_pat = strchr(p,
'%');
601 snprintf(q, q_len - 1,
"%d", d_w);
604 snprintf(q, q_len - 1,
"%d", d_h);
607 snprintf(q, q_len - 1,
"%d", frame_in);
610 snprintf(q, q_len - 1,
"%02d", frame_in);
613 snprintf(q, q_len - 1,
"%03d", frame_in);
616 snprintf(q, q_len - 1,
"%04d", frame_in);
619 snprintf(q, q_len - 1,
"%05d", frame_in);
622 snprintf(q, q_len - 1,
"%06d", frame_in);
625 snprintf(q, q_len - 1,
"%07d", frame_in);
628 snprintf(q, q_len - 1,
"%08d", frame_in);
631 snprintf(q, q_len - 1,
"%09d", frame_in);
634 die(
"Unrecognized pattern %%%c\n", p[1]);
638 if (pat_len >= q_len - 1)
639 die(
"Output filename too long.\n");
648 copy_len = strlen(p);
650 copy_len = next_pat - p;
652 if (copy_len >= q_len - 1)
653 die(
"Output filename too long.\n");
655 memcpy(q, p, copy_len);
665 int main_loop(
int argc,
const char **argv_) {
670 size_t buf_sz = 0, buf_alloc_sz = 0;
672 int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
673 int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
678 unsigned long dx_time = 0;
680 char **argv, **argi, **argj;
681 const char *outfile_pattern = 0;
682 char outfile[PATH_MAX];
687 unsigned int fps_den;
688 unsigned int fps_num;
691 #if CONFIG_VP8_DECODER
693 int vp8_dbg_color_ref_frame = 0;
694 int vp8_dbg_color_mb_modes = 0;
695 int vp8_dbg_color_b_modes = 0;
696 int vp8_dbg_display_mv = 0;
698 struct input_ctx input = {0};
699 int frames_corrupted = 0;
702 int stream_w = 0, stream_h = 0;
704 int frame_avail, got_data;
707 exec_name = argv_[0];
708 argv = argv_dup(argc - 1, argv_ + 1);
710 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
711 memset(&arg, 0,
sizeof(arg));
714 if (arg_match(&arg, &codecarg, argi)) {
717 for (j = 0; j <
sizeof(ifaces) /
sizeof(ifaces[0]); j++)
718 if (!strcmp(ifaces[j].name, arg.val))
722 iface = ifaces[k].iface();
724 die(
"Error: Unrecognized argument (%s) to --codec\n",
726 }
else if (arg_match(&arg, &looparg, argi)) {
728 }
else if (arg_match(&arg, &outputfile, argi))
729 outfile_pattern = arg.val;
730 else if (arg_match(&arg, &use_yv12, argi)) {
733 }
else if (arg_match(&arg, &use_i420, argi)) {
736 }
else if (arg_match(&arg, &flipuvarg, argi))
738 else if (arg_match(&arg, &noblitarg, argi))
740 else if (arg_match(&arg, &progressarg, argi))
742 else if (arg_match(&arg, &limitarg, argi))
743 stop_after = arg_parse_uint(&arg);
744 else if (arg_match(&arg, &skiparg, argi))
745 arg_skip = arg_parse_uint(&arg);
746 else if (arg_match(&arg, &postprocarg, argi))
748 else if (arg_match(&arg, &md5arg, argi))
750 else if (arg_match(&arg, &summaryarg, argi))
752 else if (arg_match(&arg, &threadsarg, argi))
753 cfg.
threads = arg_parse_uint(&arg);
754 else if (arg_match(&arg, &verbosearg, argi))
756 else if (arg_match(&arg, &scalearg, argi))
759 #if CONFIG_VP8_DECODER
760 else if (arg_match(&arg, &addnoise_level, argi)) {
764 }
else if (arg_match(&arg, &demacroblock_level, argi)) {
768 }
else if (arg_match(&arg, &deblock, argi)) {
771 }
else if (arg_match(&arg, &mfqe, argi)) {
774 }
else if (arg_match(&arg, &pp_debug_info, argi)) {
775 unsigned int level = arg_parse_uint(&arg);
782 }
else if (arg_match(&arg, &pp_disp_ref_frame, argi)) {
783 unsigned int flags = arg_parse_int(&arg);
786 vp8_dbg_color_ref_frame = flags;
788 }
else if (arg_match(&arg, &pp_disp_mb_modes, argi)) {
789 unsigned int flags = arg_parse_int(&arg);
792 vp8_dbg_color_mb_modes = flags;
794 }
else if (arg_match(&arg, &pp_disp_b_modes, argi)) {
795 unsigned int flags = arg_parse_int(&arg);
798 vp8_dbg_color_b_modes = flags;
800 }
else if (arg_match(&arg, &pp_disp_mvs, argi)) {
801 unsigned int flags = arg_parse_int(&arg);
804 vp8_dbg_display_mv = flags;
806 }
else if (arg_match(&arg, &error_concealment, argi)) {
816 for (argi = argv; *argi; argi++)
817 if (argi[0][0] ==
'-' && strlen(argi[0]) > 1)
818 die(
"Error: Unrecognized option %s\n", *argi);
827 infile = strcmp(fn,
"-") ? fopen(fn,
"rb") : set_binary_mode(stdin);
830 fprintf(stderr,
"Failed to open file '%s'",
831 strcmp(fn,
"-") ? fn :
"stdin");
834 #if CONFIG_OS_SUPPORT
836 if (!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit) {
838 "Not dumping raw video to your terminal. Use '-o -' to "
843 input.infile = infile;
844 if (file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
846 input.kind = IVF_FILE;
847 else if (file_is_webm(&input, &fourcc, &width, &height, &fps_den, &fps_num))
848 input.kind = WEBM_FILE;
849 else if (file_is_raw(infile, &fourcc, &width, &height, &fps_den, &fps_num))
850 input.kind = RAW_FILE;
852 fprintf(stderr,
"Unrecognized input file type.\n");
859 outfile_pattern = outfile_pattern ? outfile_pattern :
"-";
862 const char *p = outfile_pattern;
865 if (p && p[1] >=
'1' && p[1] <=
'9') {
875 if (single_file && !noblit) {
876 generate_filename(outfile_pattern, outfile,
sizeof(outfile) - 1,
878 out = out_open(outfile, do_md5);
881 if (use_y4m && !noblit) {
885 fprintf(stderr,
"YUV4MPEG2 not supported with output patterns,"
886 " try --i420 or --yv12.\n");
890 if (input.kind == WEBM_FILE)
891 if (webm_guess_framerate(&input, &fps_den, &fps_num)) {
892 fprintf(stderr,
"Failed to guess framerate -- error parsing "
901 snprintf(buffer,
sizeof(buffer),
"YUV4MPEG2 W%u H%u F%u:%u I%c ",
902 width, height, fps_num, fps_den,
'p');
903 out_put(out, (
unsigned char *)buffer,
904 (
unsigned int)strlen(buffer), do_md5);
908 for (i = 0; i <
sizeof(ifaces) /
sizeof(ifaces[0]); i++)
909 if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc) {
912 if (iface && iface != ivf_iface)
913 fprintf(stderr,
"Notice -- IVF header indicates codec: %s\n",
922 (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
925 fprintf(stderr,
"Failed to initialize decoder: %s\n",
vpx_codec_error(&decoder));
930 fprintf(stderr,
"%s\n", decoder.
name);
932 #if CONFIG_VP8_DECODER
936 fprintf(stderr,
"Failed to configure postproc: %s\n",
vpx_codec_error(&decoder));
940 if (vp8_dbg_color_ref_frame
942 fprintf(stderr,
"Failed to configure reference block visualizer: %s\n",
vpx_codec_error(&decoder));
946 if (vp8_dbg_color_mb_modes
948 fprintf(stderr,
"Failed to configure macro block visualizer: %s\n",
vpx_codec_error(&decoder));
952 if (vp8_dbg_color_b_modes
954 fprintf(stderr,
"Failed to configure block visualizer: %s\n",
vpx_codec_error(&decoder));
958 if (vp8_dbg_display_mv
960 fprintf(stderr,
"Failed to configure motion vector visualizer: %s\n",
vpx_codec_error(&decoder));
967 fprintf(stderr,
"Skiping first %d frames.\n", arg_skip);
969 if (read_frame(&input, &buf, &buf_sz, &buf_alloc_sz))
978 while (frame_avail || got_data) {
981 struct vpx_usec_timer timer;
985 if (!stop_after || frame_in < stop_after) {
986 if(!read_frame(&input, &buf, &buf_sz, &buf_alloc_sz)) {
990 vpx_usec_timer_start(&timer);
994 fprintf(stderr,
"Failed to decode frame: %s\n",
998 fprintf(stderr,
" Additional information: %s\n", detail);
1002 vpx_usec_timer_mark(&timer);
1003 dx_time += (
unsigned int)vpx_usec_timer_elapsed(&timer);
1007 vpx_usec_timer_start(&timer);
1015 vpx_usec_timer_mark(&timer);
1016 dx_time += (
unsigned int)vpx_usec_timer_elapsed(&timer);
1019 fprintf(stderr,
"Failed VP8_GET_FRAME_CORRUPTED: %s\n",
1023 frames_corrupted += corrupted;
1026 show_progress(frame_in, frame_out, dx_time);
1029 if (frame_out == 1 && img && use_y4m) {
1037 out_put(out, (
const unsigned char*)color, strlen(color), do_md5);
1041 if (img && frame_out == 1) {
1042 stream_w = img->
d_w;
1043 stream_h = img->
d_h;
1045 stream_w, stream_h, 16);
1047 if (img && (img->
d_w != stream_w || img->
d_h != stream_h)) {
1049 I420Scale(img->
planes[VPX_PLANE_Y], img->
stride[VPX_PLANE_Y],
1053 scaled_img->
planes[VPX_PLANE_Y],
1054 scaled_img->
stride[VPX_PLANE_Y],
1055 scaled_img->
planes[VPX_PLANE_U],
1056 scaled_img->
stride[VPX_PLANE_U],
1067 char out_fn[PATH_MAX];
1077 size_t len =
sizeof(out_fn) - 1;
1080 generate_filename(outfile_pattern, out_fn, len - 1,
1081 img->
d_w, img->
d_h, frame_in);
1082 out = out_open(out_fn, do_md5);
1084 out_put(out, (
unsigned char *)
"FRAME\n", 6, do_md5);
1088 for (y = 0; y < img->
d_h; y++) {
1089 out_put(out, buf, img->
d_w, do_md5);
1095 for (y = 0; y < c_h; y++) {
1096 out_put(out, buf, c_w, do_md5);
1102 for (y = 0; y < c_h; y++) {
1103 out_put(out, buf, c_w, do_md5);
1108 out_close(out, out_fn, do_md5);
1112 if (stop_after && frame_in >= stop_after)
1116 if (summary || progress) {
1117 show_progress(frame_in, frame_out, dx_time);
1118 fprintf(stderr,
"\n");
1121 if (frames_corrupted)
1122 fprintf(stderr,
"WARNING: %d frames corrupted.\n", frames_corrupted);
1127 fprintf(stderr,
"Failed to destroy decoder: %s\n",
1129 return EXIT_FAILURE;
1132 if (single_file && !noblit)
1133 out_close(out, outfile, do_md5);
1135 if (input.nestegg_ctx)
1136 nestegg_destroy(input.nestegg_ctx);
1137 if (input.kind != WEBM_FILE)
1145 return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS;
1148 int main(
int argc,
const char **argv_) {
1149 unsigned int loops = 1, i;
1150 char **argv, **argi, **argj;
1154 argv = argv_dup(argc - 1, argv_ + 1);
1155 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
1156 memset(&arg, 0,
sizeof(arg));
1159 if (arg_match(&arg, &looparg, argi)) {
1160 loops = arg_parse_uint(&arg);
1165 for (i = 0; !error && i < loops; i++)
1166 error = main_loop(argc, argv_);