WebM VP8 Codec SDK
vpxdec
1 /*
2  * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  * Use of this source code is governed by a BSD-style license
5  * that can be found in the LICENSE file in the root of the source
6  * tree. An additional intellectual property rights grant can be found
7  * in the file PATENTS. All contributing project authors may
8  * be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 
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.
14  */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include <limits.h>
20 
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_VP8_DECODER || CONFIG_VP9_DECODER
26 #include "vpx/vp8dx.h"
27 #endif
28 #if CONFIG_MD5
29 #include "md5_utils.h"
30 #endif
31 #include "tools_common.h"
32 #include "nestegg/include/nestegg/nestegg.h"
33 #include "third_party/libyuv/include/libyuv/scale.h"
34 
35 #if CONFIG_OS_SUPPORT
36 #if defined(_MSC_VER)
37 #include <io.h>
38 #define snprintf _snprintf
39 #define isatty _isatty
40 #define fileno _fileno
41 #else
42 #include <unistd.h>
43 #endif
44 #endif
45 
46 #ifndef PATH_MAX
47 #define PATH_MAX 256
48 #endif
49 
50 static const char *exec_name;
51 
52 #define VP8_FOURCC (0x00385056)
53 #define VP9_FOURCC (0x00395056)
54 static const struct {
55  char const *name;
56  const vpx_codec_iface_t *(*iface)(void);
57  unsigned int fourcc;
58  unsigned int fourcc_mask;
59 } ifaces[] = {
60 #if CONFIG_VP8_DECODER
61  {"vp8", vpx_codec_vp8_dx, VP8_FOURCC, 0x00FFFFFF},
62 #endif
63 #if CONFIG_VP9_DECODER
64  {"vp9", vpx_codec_vp9_dx, VP9_FOURCC, 0x00FFFFFF},
65 #endif
66 };
67 
68 #include "args.h"
69 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
70  "Codec to use");
71 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
72  "Output raw YV12 frames");
73 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
74  "Output raw I420 frames");
75 static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
76  "Flip the chroma planes in the output");
77 static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
78  "Don't process the decoded frames");
79 static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
80  "Show progress after each frame decodes");
81 static const arg_def_t limitarg = ARG_DEF(NULL, "limit", 1,
82  "Stop decoding after n frames");
83 static const arg_def_t skiparg = ARG_DEF(NULL, "skip", 1,
84  "Skip the first n input frames");
85 static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
86  "Postprocess decoded frames");
87 static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
88  "Show timing summary");
89 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
90  "Output file name pattern (see below)");
91 static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
92  "Max threads to use");
93 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
94  "Show version string");
95 static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0,
96  "Enable decoder error-concealment");
97 static const arg_def_t scalearg = ARG_DEF("S", "scale", 0,
98  "Scale output frames uniformly");
99 
100 
101 #if CONFIG_MD5
102 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
103  "Compute the MD5 sum of the decoded frame");
104 #endif
105 static const arg_def_t *all_args[] = {
106  &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
107  &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
108  &threadsarg, &verbosearg, &scalearg,
109 #if CONFIG_MD5
110  &md5arg,
111 #endif
112  &error_concealment,
113  NULL
114 };
115 
116 #if CONFIG_VP8_DECODER
117 static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1,
118  "Enable VP8 postproc add noise");
119 static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0,
120  "Enable VP8 deblocking");
121 static const arg_def_t demacroblock_level = ARG_DEF(NULL, "demacroblock-level", 1,
122  "Enable VP8 demacroblocking, w/ level");
123 static const arg_def_t pp_debug_info = ARG_DEF(NULL, "pp-debug-info", 1,
124  "Enable VP8 visible debug info");
125 static const arg_def_t pp_disp_ref_frame = ARG_DEF(NULL, "pp-dbg-ref-frame", 1,
126  "Display only selected reference frame per macro block");
127 static const arg_def_t pp_disp_mb_modes = ARG_DEF(NULL, "pp-dbg-mb-modes", 1,
128  "Display only selected macro block modes");
129 static const arg_def_t pp_disp_b_modes = ARG_DEF(NULL, "pp-dbg-b-modes", 1,
130  "Display only selected block modes");
131 static const arg_def_t pp_disp_mvs = ARG_DEF(NULL, "pp-dbg-mvs", 1,
132  "Draw only selected motion vectors");
133 static const arg_def_t mfqe = ARG_DEF(NULL, "mfqe", 0,
134  "Enable multiframe quality enhancement");
135 
136 static const arg_def_t *vp8_pp_args[] = {
137  &addnoise_level, &deblock, &demacroblock_level, &pp_debug_info,
138  &pp_disp_ref_frame, &pp_disp_mb_modes, &pp_disp_b_modes, &pp_disp_mvs, &mfqe,
139  NULL
140 };
141 #endif
142 
143 static void usage_exit() {
144  int i;
145 
146  fprintf(stderr, "Usage: %s <options> filename\n\n"
147  "Options:\n", exec_name);
148  arg_show_usage(stderr, all_args);
149 #if CONFIG_VP8_DECODER
150  fprintf(stderr, "\nVP8 Postprocessing Options:\n");
151  arg_show_usage(stderr, vp8_pp_args);
152 #endif
153  fprintf(stderr,
154  "\nOutput File Patterns:\n\n"
155  " The -o argument specifies the name of the file(s) to "
156  "write to. If the\n argument does not include any escape "
157  "characters, the output will be\n written to a single file. "
158  "Otherwise, the filename will be calculated by\n expanding "
159  "the following escape characters:\n");
160  fprintf(stderr,
161  "\n\t%%w - Frame width"
162  "\n\t%%h - Frame height"
163  "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
164  "\n\n Pattern arguments are only supported in conjunction "
165  "with the --yv12 and\n --i420 options. If the -o option is "
166  "not specified, the output will be\n directed to stdout.\n"
167  );
168  fprintf(stderr, "\nIncluded decoders:\n\n");
169 
170  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
171  fprintf(stderr, " %-6s - %s\n",
172  ifaces[i].name,
173  vpx_codec_iface_name(ifaces[i].iface()));
174 
175  exit(EXIT_FAILURE);
176 }
177 
178 void die(const char *fmt, ...) {
179  va_list ap;
180  va_start(ap, fmt);
181  vfprintf(stderr, fmt, ap);
182  fprintf(stderr, "\n");
183  usage_exit();
184 }
185 
186 static unsigned int mem_get_le16(const void *vmem) {
187  unsigned int val;
188  const unsigned char *mem = (const unsigned char *)vmem;
189 
190  val = mem[1] << 8;
191  val |= mem[0];
192  return val;
193 }
194 
195 static unsigned int mem_get_le32(const void *vmem) {
196  unsigned int val;
197  const unsigned char *mem = (const unsigned char *)vmem;
198 
199  val = mem[3] << 24;
200  val |= mem[2] << 16;
201  val |= mem[1] << 8;
202  val |= mem[0];
203  return val;
204 }
205 
206 enum file_kind {
207  RAW_FILE,
208  IVF_FILE,
209  WEBM_FILE
210 };
211 
212 struct input_ctx {
213  enum file_kind kind;
214  FILE *infile;
215  nestegg *nestegg_ctx;
216  nestegg_packet *pkt;
217  unsigned int chunk;
218  unsigned int chunks;
219  unsigned int video_track;
220 };
221 
222 #define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
223 #define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
224 static int read_frame(struct input_ctx *input,
225  uint8_t **buf,
226  size_t *buf_sz,
227  size_t *buf_alloc_sz) {
228  char raw_hdr[IVF_FRAME_HDR_SZ];
229  size_t new_buf_sz;
230  FILE *infile = input->infile;
231  enum file_kind kind = input->kind;
232  if (kind == WEBM_FILE) {
233  if (input->chunk >= input->chunks) {
234  unsigned int track;
235 
236  do {
237  /* End of this packet, get another. */
238  if (input->pkt)
239  nestegg_free_packet(input->pkt);
240 
241  if (nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
242  || nestegg_packet_track(input->pkt, &track))
243  return 1;
244 
245  } while (track != input->video_track);
246 
247  if (nestegg_packet_count(input->pkt, &input->chunks))
248  return 1;
249  input->chunk = 0;
250  }
251 
252  if (nestegg_packet_data(input->pkt, input->chunk, buf, buf_sz))
253  return 1;
254  input->chunk++;
255 
256  return 0;
257  }
258  /* For both the raw and ivf formats, the frame size is the first 4 bytes
259  * of the frame header. We just need to special case on the header
260  * size.
261  */
262  else if (fread(raw_hdr, kind == IVF_FILE
263  ? IVF_FRAME_HDR_SZ : RAW_FRAME_HDR_SZ, 1, infile) != 1) {
264  if (!feof(infile))
265  fprintf(stderr, "Failed to read frame size\n");
266 
267  new_buf_sz = 0;
268  } else {
269  new_buf_sz = mem_get_le32(raw_hdr);
270 
271  if (new_buf_sz > 256 * 1024 * 1024) {
272  fprintf(stderr, "Error: Read invalid frame size (%u)\n",
273  (unsigned int)new_buf_sz);
274  new_buf_sz = 0;
275  }
276 
277  if (kind == RAW_FILE && new_buf_sz > 256 * 1024)
278  fprintf(stderr, "Warning: Read invalid frame size (%u)"
279  " - not a raw file?\n", (unsigned int)new_buf_sz);
280 
281  if (new_buf_sz > *buf_alloc_sz) {
282  uint8_t *new_buf = realloc(*buf, 2 * new_buf_sz);
283 
284  if (new_buf) {
285  *buf = new_buf;
286  *buf_alloc_sz = 2 * new_buf_sz;
287  } else {
288  fprintf(stderr, "Failed to allocate compressed data buffer\n");
289  new_buf_sz = 0;
290  }
291  }
292  }
293 
294  *buf_sz = new_buf_sz;
295 
296  if (!feof(infile)) {
297  if (fread(*buf, 1, *buf_sz, infile) != *buf_sz) {
298  fprintf(stderr, "Failed to read full frame\n");
299  return 1;
300  }
301 
302  return 0;
303  }
304 
305  return 1;
306 }
307 
308 void *out_open(const char *out_fn, int do_md5) {
309  void *out = NULL;
310 
311  if (do_md5) {
312 #if CONFIG_MD5
313  MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
314  (void)out_fn;
315  MD5Init(md5_ctx);
316 #endif
317  } else {
318  FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb")
319  : set_binary_mode(stdout);
320 
321  if (!outfile) {
322  fprintf(stderr, "Failed to output file");
323  exit(EXIT_FAILURE);
324  }
325  }
326 
327  return out;
328 }
329 
330 void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5) {
331  if (do_md5) {
332 #if CONFIG_MD5
333  MD5Update(out, buf, len);
334 #endif
335  } else {
336  (void) fwrite(buf, 1, len, out);
337  }
338 }
339 
340 void out_close(void *out, const char *out_fn, int do_md5) {
341  if (do_md5) {
342 #if CONFIG_MD5
343  uint8_t md5[16];
344  int i;
345 
346  MD5Final(md5, out);
347  free(out);
348 
349  for (i = 0; i < 16; i++)
350  printf("%02x", md5[i]);
351 
352  printf(" %s\n", out_fn);
353 #endif
354  } else {
355  fclose(out);
356  }
357 }
358 
359 unsigned int file_is_ivf(FILE *infile,
360  unsigned int *fourcc,
361  unsigned int *width,
362  unsigned int *height,
363  unsigned int *fps_den,
364  unsigned int *fps_num) {
365  char raw_hdr[32];
366  int is_ivf = 0;
367 
368  if (fread(raw_hdr, 1, 32, infile) == 32) {
369  if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
370  && raw_hdr[2] == 'I' && raw_hdr[3] == 'F') {
371  is_ivf = 1;
372 
373  if (mem_get_le16(raw_hdr + 4) != 0)
374  fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
375  " decode properly.");
376 
377  *fourcc = mem_get_le32(raw_hdr + 8);
378  *width = mem_get_le16(raw_hdr + 12);
379  *height = mem_get_le16(raw_hdr + 14);
380  *fps_num = mem_get_le32(raw_hdr + 16);
381  *fps_den = mem_get_le32(raw_hdr + 20);
382 
383  /* Some versions of vpxenc used 1/(2*fps) for the timebase, so
384  * we can guess the framerate using only the timebase in this
385  * case. Other files would require reading ahead to guess the
386  * timebase, like we do for webm.
387  */
388  if (*fps_num < 1000) {
389  /* Correct for the factor of 2 applied to the timebase in the
390  * encoder.
391  */
392  if (*fps_num & 1)*fps_den <<= 1;
393  else *fps_num >>= 1;
394  } else {
395  /* Don't know FPS for sure, and don't have readahead code
396  * (yet?), so just default to 30fps.
397  */
398  *fps_num = 30;
399  *fps_den = 1;
400  }
401  }
402  }
403 
404  if (!is_ivf)
405  rewind(infile);
406 
407  return is_ivf;
408 }
409 
410 
411 unsigned int file_is_raw(FILE *infile,
412  unsigned int *fourcc,
413  unsigned int *width,
414  unsigned int *height,
415  unsigned int *fps_den,
416  unsigned int *fps_num) {
417  unsigned char buf[32];
418  int is_raw = 0;
420 
421  si.sz = sizeof(si);
422 
423  if (fread(buf, 1, 32, infile) == 32) {
424  int i;
425 
426  if (mem_get_le32(buf) < 256 * 1024 * 1024)
427  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
428  if (!vpx_codec_peek_stream_info(ifaces[i].iface(),
429  buf + 4, 32 - 4, &si)) {
430  is_raw = 1;
431  *fourcc = ifaces[i].fourcc;
432  *width = si.w;
433  *height = si.h;
434  *fps_num = 30;
435  *fps_den = 1;
436  break;
437  }
438  }
439 
440  rewind(infile);
441  return is_raw;
442 }
443 
444 
445 static int
446 nestegg_read_cb(void *buffer, size_t length, void *userdata) {
447  FILE *f = userdata;
448 
449  if (fread(buffer, 1, length, f) < length) {
450  if (ferror(f))
451  return -1;
452  if (feof(f))
453  return 0;
454  }
455  return 1;
456 }
457 
458 
459 static int
460 nestegg_seek_cb(int64_t offset, int whence, void *userdata) {
461  switch (whence) {
462  case NESTEGG_SEEK_SET:
463  whence = SEEK_SET;
464  break;
465  case NESTEGG_SEEK_CUR:
466  whence = SEEK_CUR;
467  break;
468  case NESTEGG_SEEK_END:
469  whence = SEEK_END;
470  break;
471  };
472  return fseek(userdata, (long)offset, whence) ? -1 : 0;
473 }
474 
475 
476 static int64_t
477 nestegg_tell_cb(void *userdata) {
478  return ftell(userdata);
479 }
480 
481 
482 static void
483 nestegg_log_cb(nestegg *context, unsigned int severity, char const *format,
484  ...) {
485  va_list ap;
486 
487  va_start(ap, format);
488  vfprintf(stderr, format, ap);
489  fprintf(stderr, "\n");
490  va_end(ap);
491 }
492 
493 
494 static int
495 webm_guess_framerate(struct input_ctx *input,
496  unsigned int *fps_den,
497  unsigned int *fps_num) {
498  unsigned int i;
499  uint64_t tstamp = 0;
500 
501  /* Guess the framerate. Read up to 1 second, or 50 video packets,
502  * whichever comes first.
503  */
504  for (i = 0; tstamp < 1000000000 && i < 50;) {
505  nestegg_packet *pkt;
506  unsigned int track;
507 
508  if (nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
509  break;
510 
511  nestegg_packet_track(pkt, &track);
512  if (track == input->video_track) {
513  nestegg_packet_tstamp(pkt, &tstamp);
514  i++;
515  }
516 
517  nestegg_free_packet(pkt);
518  }
519 
520  if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
521  goto fail;
522 
523  *fps_num = (i - 1) * 1000000;
524  *fps_den = (unsigned int)(tstamp / 1000);
525  return 0;
526 fail:
527  nestegg_destroy(input->nestegg_ctx);
528  input->nestegg_ctx = NULL;
529  rewind(input->infile);
530  return 1;
531 }
532 
533 
534 static int
535 file_is_webm(struct input_ctx *input,
536  unsigned int *fourcc,
537  unsigned int *width,
538  unsigned int *height,
539  unsigned int *fps_den,
540  unsigned int *fps_num) {
541  unsigned int i, n;
542  int track_type = -1;
543  int codec_id;
544 
545  nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
546  nestegg_video_params params;
547 
548  io.userdata = input->infile;
549  if (nestegg_init(&input->nestegg_ctx, io, NULL))
550  goto fail;
551 
552  if (nestegg_track_count(input->nestegg_ctx, &n))
553  goto fail;
554 
555  for (i = 0; i < n; i++) {
556  track_type = nestegg_track_type(input->nestegg_ctx, i);
557 
558  if (track_type == NESTEGG_TRACK_VIDEO)
559  break;
560  else if (track_type < 0)
561  goto fail;
562  }
563 
564  codec_id = nestegg_track_codec_id(input->nestegg_ctx, i);
565  if (codec_id == NESTEGG_CODEC_VP8) {
566  *fourcc = VP8_FOURCC;
567  } else if (codec_id == NESTEGG_CODEC_VP9) {
568  *fourcc = VP9_FOURCC;
569  } else {
570  fprintf(stderr, "Not VPx video, quitting.\n");
571  exit(1);
572  }
573 
574  input->video_track = i;
575 
576  if (nestegg_track_video_params(input->nestegg_ctx, i, &params))
577  goto fail;
578 
579  *fps_den = 0;
580  *fps_num = 0;
581  *width = params.width;
582  *height = params.height;
583  return 1;
584 fail:
585  input->nestegg_ctx = NULL;
586  rewind(input->infile);
587  return 0;
588 }
589 
590 
591 void show_progress(int frame_in, int frame_out, unsigned long dx_time) {
592  fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
593  frame_in, frame_out, dx_time,
594  (float)frame_out * 1000000.0 / (float)dx_time);
595 }
596 
597 
598 void generate_filename(const char *pattern, char *out, size_t q_len,
599  unsigned int d_w, unsigned int d_h,
600  unsigned int frame_in) {
601  const char *p = pattern;
602  char *q = out;
603 
604  do {
605  char *next_pat = strchr(p, '%');
606 
607  if (p == next_pat) {
608  size_t pat_len;
609 
610  /* parse the pattern */
611  q[q_len - 1] = '\0';
612  switch (p[1]) {
613  case 'w':
614  snprintf(q, q_len - 1, "%d", d_w);
615  break;
616  case 'h':
617  snprintf(q, q_len - 1, "%d", d_h);
618  break;
619  case '1':
620  snprintf(q, q_len - 1, "%d", frame_in);
621  break;
622  case '2':
623  snprintf(q, q_len - 1, "%02d", frame_in);
624  break;
625  case '3':
626  snprintf(q, q_len - 1, "%03d", frame_in);
627  break;
628  case '4':
629  snprintf(q, q_len - 1, "%04d", frame_in);
630  break;
631  case '5':
632  snprintf(q, q_len - 1, "%05d", frame_in);
633  break;
634  case '6':
635  snprintf(q, q_len - 1, "%06d", frame_in);
636  break;
637  case '7':
638  snprintf(q, q_len - 1, "%07d", frame_in);
639  break;
640  case '8':
641  snprintf(q, q_len - 1, "%08d", frame_in);
642  break;
643  case '9':
644  snprintf(q, q_len - 1, "%09d", frame_in);
645  break;
646  default:
647  die("Unrecognized pattern %%%c\n", p[1]);
648  }
649 
650  pat_len = strlen(q);
651  if (pat_len >= q_len - 1)
652  die("Output filename too long.\n");
653  q += pat_len;
654  p += 2;
655  q_len -= pat_len;
656  } else {
657  size_t copy_len;
658 
659  /* copy the next segment */
660  if (!next_pat)
661  copy_len = strlen(p);
662  else
663  copy_len = next_pat - p;
664 
665  if (copy_len >= q_len - 1)
666  die("Output filename too long.\n");
667 
668  memcpy(q, p, copy_len);
669  q[copy_len] = '\0';
670  q += copy_len;
671  p += copy_len;
672  q_len -= copy_len;
673  }
674  } while (*p);
675 }
676 
677 
678 int main(int argc, const char **argv_) {
679  vpx_codec_ctx_t decoder;
680  char *fn = NULL;
681  int i;
682  uint8_t *buf = NULL;
683  size_t buf_sz = 0, buf_alloc_sz = 0;
684  FILE *infile;
685  int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
686  int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
687  int arg_skip = 0;
688  int ec_enabled = 0;
689  vpx_codec_iface_t *iface = NULL;
690  unsigned int fourcc;
691  unsigned long dx_time = 0;
692  struct arg arg;
693  char **argv, **argi, **argj;
694  const char *outfile_pattern = 0;
695  char outfile[PATH_MAX];
696  int single_file;
697  int use_y4m = 1;
698  unsigned int width;
699  unsigned int height;
700  unsigned int fps_den;
701  unsigned int fps_num;
702  void *out = NULL;
703  vpx_codec_dec_cfg_t cfg = {0};
704 #if CONFIG_VP8_DECODER
705  vp8_postproc_cfg_t vp8_pp_cfg = {0};
706  int vp8_dbg_color_ref_frame = 0;
707  int vp8_dbg_color_mb_modes = 0;
708  int vp8_dbg_color_b_modes = 0;
709  int vp8_dbg_display_mv = 0;
710 #endif
711  struct input_ctx input = {0};
712  int frames_corrupted = 0;
713  int dec_flags = 0;
714  int do_scale = 0;
715  int stream_w = 0, stream_h = 0;
716  vpx_image_t *scaled_img = NULL;
717 
718  /* Parse command line */
719  exec_name = argv_[0];
720  argv = argv_dup(argc - 1, argv_ + 1);
721 
722  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
723  memset(&arg, 0, sizeof(arg));
724  arg.argv_step = 1;
725 
726  if (arg_match(&arg, &codecarg, argi)) {
727  int j, k = -1;
728 
729  for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
730  if (!strcmp(ifaces[j].name, arg.val))
731  k = j;
732 
733  if (k >= 0)
734  iface = ifaces[k].iface();
735  else
736  die("Error: Unrecognized argument (%s) to --codec\n",
737  arg.val);
738  } else if (arg_match(&arg, &outputfile, argi))
739  outfile_pattern = arg.val;
740  else if (arg_match(&arg, &use_yv12, argi)) {
741  use_y4m = 0;
742  flipuv = 1;
743  } else if (arg_match(&arg, &use_i420, argi)) {
744  use_y4m = 0;
745  flipuv = 0;
746  } else if (arg_match(&arg, &flipuvarg, argi))
747  flipuv = 1;
748  else if (arg_match(&arg, &noblitarg, argi))
749  noblit = 1;
750  else if (arg_match(&arg, &progressarg, argi))
751  progress = 1;
752  else if (arg_match(&arg, &limitarg, argi))
753  stop_after = arg_parse_uint(&arg);
754  else if (arg_match(&arg, &skiparg, argi))
755  arg_skip = arg_parse_uint(&arg);
756  else if (arg_match(&arg, &postprocarg, argi))
757  postproc = 1;
758  else if (arg_match(&arg, &md5arg, argi))
759  do_md5 = 1;
760  else if (arg_match(&arg, &summaryarg, argi))
761  summary = 1;
762  else if (arg_match(&arg, &threadsarg, argi))
763  cfg.threads = arg_parse_uint(&arg);
764  else if (arg_match(&arg, &verbosearg, argi))
765  quiet = 0;
766  else if (arg_match(&arg, &scalearg, argi))
767  do_scale = 1;
768 
769 #if CONFIG_VP8_DECODER
770  else if (arg_match(&arg, &addnoise_level, argi)) {
771  postproc = 1;
772  vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE;
773  vp8_pp_cfg.noise_level = arg_parse_uint(&arg);
774  } else if (arg_match(&arg, &demacroblock_level, argi)) {
775  postproc = 1;
776  vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK;
777  vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg);
778  } else if (arg_match(&arg, &deblock, argi)) {
779  postproc = 1;
780  vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK;
781  } else if (arg_match(&arg, &mfqe, argi)) {
782  postproc = 1;
783  vp8_pp_cfg.post_proc_flag |= VP8_MFQE;
784  } else if (arg_match(&arg, &pp_debug_info, argi)) {
785  unsigned int level = arg_parse_uint(&arg);
786 
787  postproc = 1;
788  vp8_pp_cfg.post_proc_flag &= ~0x7;
789 
790  if (level)
791  vp8_pp_cfg.post_proc_flag |= level;
792  } else if (arg_match(&arg, &pp_disp_ref_frame, argi)) {
793  unsigned int flags = arg_parse_int(&arg);
794  if (flags) {
795  postproc = 1;
796  vp8_dbg_color_ref_frame = flags;
797  }
798  } else if (arg_match(&arg, &pp_disp_mb_modes, argi)) {
799  unsigned int flags = arg_parse_int(&arg);
800  if (flags) {
801  postproc = 1;
802  vp8_dbg_color_mb_modes = flags;
803  }
804  } else if (arg_match(&arg, &pp_disp_b_modes, argi)) {
805  unsigned int flags = arg_parse_int(&arg);
806  if (flags) {
807  postproc = 1;
808  vp8_dbg_color_b_modes = flags;
809  }
810  } else if (arg_match(&arg, &pp_disp_mvs, argi)) {
811  unsigned int flags = arg_parse_int(&arg);
812  if (flags) {
813  postproc = 1;
814  vp8_dbg_display_mv = flags;
815  }
816  } else if (arg_match(&arg, &error_concealment, argi)) {
817  ec_enabled = 1;
818  }
819 
820 #endif
821  else
822  argj++;
823  }
824 
825  /* Check for unrecognized options */
826  for (argi = argv; *argi; argi++)
827  if (argi[0][0] == '-' && strlen(argi[0]) > 1)
828  die("Error: Unrecognized option %s\n", *argi);
829 
830  /* Handle non-option arguments */
831  fn = argv[0];
832 
833  if (!fn)
834  usage_exit();
835 
836  /* Open file */
837  infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin);
838 
839  if (!infile) {
840  fprintf(stderr, "Failed to open file '%s'",
841  strcmp(fn, "-") ? fn : "stdin");
842  return EXIT_FAILURE;
843  }
844 #if CONFIG_OS_SUPPORT
845  /* Make sure we don't dump to the terminal, unless forced to with -o - */
846  if (!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit) {
847  fprintf(stderr,
848  "Not dumping raw video to your terminal. Use '-o -' to "
849  "override.\n");
850  return EXIT_FAILURE;
851  }
852 #endif
853  input.infile = infile;
854  if (file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
855  &fps_num))
856  input.kind = IVF_FILE;
857  else if (file_is_webm(&input, &fourcc, &width, &height, &fps_den, &fps_num))
858  input.kind = WEBM_FILE;
859  else if (file_is_raw(infile, &fourcc, &width, &height, &fps_den, &fps_num))
860  input.kind = RAW_FILE;
861  else {
862  fprintf(stderr, "Unrecognized input file type.\n");
863  return EXIT_FAILURE;
864  }
865 
866  /* If the output file is not set or doesn't have a sequence number in
867  * it, then we only open it once.
868  */
869  outfile_pattern = outfile_pattern ? outfile_pattern : "-";
870  single_file = 1;
871  {
872  const char *p = outfile_pattern;
873  do {
874  p = strchr(p, '%');
875  if (p && p[1] >= '1' && p[1] <= '9') {
876  /* pattern contains sequence number, so it's not unique. */
877  single_file = 0;
878  break;
879  }
880  if (p)
881  p++;
882  } while (p);
883  }
884 
885  if (single_file && !noblit) {
886  generate_filename(outfile_pattern, outfile, sizeof(outfile) - 1,
887  width, height, 0);
888  out = out_open(outfile, do_md5);
889  }
890 
891  if (use_y4m && !noblit) {
892  char buffer[128];
893  if (!single_file) {
894  fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
895  " try --i420 or --yv12.\n");
896  return EXIT_FAILURE;
897  }
898 
899  if (input.kind == WEBM_FILE)
900  if (webm_guess_framerate(&input, &fps_den, &fps_num)) {
901  fprintf(stderr, "Failed to guess framerate -- error parsing "
902  "webm file?\n");
903  return EXIT_FAILURE;
904  }
905 
906 
907  /*Note: We can't output an aspect ratio here because IVF doesn't
908  store one, and neither does VP8.
909  That will have to wait until these tools support WebM natively.*/
910  sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
911  "420jpeg", width, height, fps_num, fps_den, 'p');
912  out_put(out, (unsigned char *)buffer,
913  (unsigned int)strlen(buffer), do_md5);
914  }
915 
916  /* Try to determine the codec from the fourcc. */
917  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
918  if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc) {
919  vpx_codec_iface_t *ivf_iface = ifaces[i].iface();
920 
921  if (iface && iface != ivf_iface)
922  fprintf(stderr, "Notice -- IVF header indicates codec: %s\n",
923  ifaces[i].name);
924  else
925  iface = ivf_iface;
926 
927  break;
928  }
929 
930  dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
931  (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
932  if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface(), &cfg,
933  dec_flags)) {
934  fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
935  return EXIT_FAILURE;
936  }
937 
938  if (!quiet)
939  fprintf(stderr, "%s\n", decoder.name);
940 
941 #if CONFIG_VP8_DECODER
942 
943  if (vp8_pp_cfg.post_proc_flag
944  && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) {
945  fprintf(stderr, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder));
946  return EXIT_FAILURE;
947  }
948 
949  if (vp8_dbg_color_ref_frame
950  && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME, vp8_dbg_color_ref_frame)) {
951  fprintf(stderr, "Failed to configure reference block visualizer: %s\n", vpx_codec_error(&decoder));
952  return EXIT_FAILURE;
953  }
954 
955  if (vp8_dbg_color_mb_modes
956  && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES, vp8_dbg_color_mb_modes)) {
957  fprintf(stderr, "Failed to configure macro block visualizer: %s\n", vpx_codec_error(&decoder));
958  return EXIT_FAILURE;
959  }
960 
961  if (vp8_dbg_color_b_modes
962  && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES, vp8_dbg_color_b_modes)) {
963  fprintf(stderr, "Failed to configure block visualizer: %s\n", vpx_codec_error(&decoder));
964  return EXIT_FAILURE;
965  }
966 
967  if (vp8_dbg_display_mv
968  && vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vp8_dbg_display_mv)) {
969  fprintf(stderr, "Failed to configure motion vector visualizer: %s\n", vpx_codec_error(&decoder));
970  return EXIT_FAILURE;
971  }
972 #endif
973 
974 
975  if(arg_skip)
976  fprintf(stderr, "Skiping first %d frames.\n", arg_skip);
977  while (arg_skip) {
978  if (read_frame(&input, &buf, &buf_sz, &buf_alloc_sz))
979  break;
980  arg_skip--;
981  }
982 
983  /* Decode file */
984  while (!read_frame(&input, &buf, &buf_sz, &buf_alloc_sz)) {
985  vpx_codec_iter_t iter = NULL;
986  vpx_image_t *img;
987  struct vpx_usec_timer timer;
988  int corrupted;
989 
990  vpx_usec_timer_start(&timer);
991 
992  if (vpx_codec_decode(&decoder, buf, (unsigned int)buf_sz, NULL, 0)) {
993  const char *detail = vpx_codec_error_detail(&decoder);
994  fprintf(stderr, "Failed to decode frame: %s\n", vpx_codec_error(&decoder));
995 
996  if (detail)
997  fprintf(stderr, " Additional information: %s\n", detail);
998 
999  goto fail;
1000  }
1001 
1002  vpx_usec_timer_mark(&timer);
1003  dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
1004 
1005  ++frame_in;
1006 
1007  if (vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) {
1008  fprintf(stderr, "Failed VP8_GET_FRAME_CORRUPTED: %s\n",
1009  vpx_codec_error(&decoder));
1010  goto fail;
1011  }
1012  frames_corrupted += corrupted;
1013 
1014  vpx_usec_timer_start(&timer);
1015 
1016  if ((img = vpx_codec_get_frame(&decoder, &iter)))
1017  ++frame_out;
1018 
1019  vpx_usec_timer_mark(&timer);
1020  dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
1021 
1022  if (progress)
1023  show_progress(frame_in, frame_out, dx_time);
1024 
1025  if (!noblit) {
1026  if (do_scale) {
1027  if (img && frame_out == 1) {
1028  stream_w = img->d_w;
1029  stream_h = img->d_h;
1030  scaled_img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420,
1031  stream_w, stream_h, 16);
1032  }
1033  if (img && (img->d_w != stream_w || img->d_h != stream_h)) {
1034  I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
1035  img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
1036  img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
1037  img->d_w, img->d_h,
1038  scaled_img->planes[VPX_PLANE_Y],
1039  scaled_img->stride[VPX_PLANE_Y],
1040  scaled_img->planes[VPX_PLANE_U],
1041  scaled_img->stride[VPX_PLANE_U],
1042  scaled_img->planes[VPX_PLANE_V],
1043  scaled_img->stride[VPX_PLANE_V],
1044  stream_w, stream_h,
1045  kFilterBox);
1046  img = scaled_img;
1047  }
1048  }
1049 
1050  if (img) {
1051  unsigned int y;
1052  char out_fn[PATH_MAX];
1053  uint8_t *buf;
1054 
1055  if (!single_file) {
1056  size_t len = sizeof(out_fn) - 1;
1057 
1058  out_fn[len] = '\0';
1059  generate_filename(outfile_pattern, out_fn, len - 1,
1060  img->d_w, img->d_h, frame_in);
1061  out = out_open(out_fn, do_md5);
1062  } else if (use_y4m)
1063  out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
1064 
1065  buf = img->planes[VPX_PLANE_Y];
1066 
1067  for (y = 0; y < img->d_h; y++) {
1068  out_put(out, buf, img->d_w, do_md5);
1069  buf += img->stride[VPX_PLANE_Y];
1070  }
1071 
1072  buf = img->planes[flipuv ? VPX_PLANE_V : VPX_PLANE_U];
1073 
1074  for (y = 0; y < (1 + img->d_h) / 2; y++) {
1075  out_put(out, buf, (1 + img->d_w) / 2, do_md5);
1076  buf += img->stride[VPX_PLANE_U];
1077  }
1078 
1079  buf = img->planes[flipuv ? VPX_PLANE_U : VPX_PLANE_V];
1080 
1081  for (y = 0; y < (1 + img->d_h) / 2; y++) {
1082  out_put(out, buf, (1 + img->d_w) / 2, do_md5);
1083  buf += img->stride[VPX_PLANE_V];
1084  }
1085 
1086  if (!single_file)
1087  out_close(out, out_fn, do_md5);
1088  }
1089  }
1090 
1091  if (stop_after && frame_in >= stop_after)
1092  break;
1093  }
1094 
1095  if (summary || progress) {
1096  show_progress(frame_in, frame_out, dx_time);
1097  fprintf(stderr, "\n");
1098  }
1099 
1100  if (frames_corrupted)
1101  fprintf(stderr, "WARNING: %d frames corrupted.\n", frames_corrupted);
1102 
1103 fail:
1104 
1105  if (vpx_codec_destroy(&decoder)) {
1106  fprintf(stderr, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder));
1107  return EXIT_FAILURE;
1108  }
1109 
1110  if (single_file && !noblit)
1111  out_close(out, outfile, do_md5);
1112 
1113  if (input.nestegg_ctx)
1114  nestegg_destroy(input.nestegg_ctx);
1115  if (input.kind != WEBM_FILE)
1116  free(buf);
1117  fclose(infile);
1118  free(argv);
1119 
1120  return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS;
1121 }
struct vpx_codec_iface vpx_codec_iface_t
Codec interface structure.
Definition: vpx_codec.h:174
Image Descriptor.
Definition: vpx_image.h:97
Describes the decoder algorithm interface to applications.
const char * vpx_codec_iface_name(vpx_codec_iface_t *iface)
Return the name for a given interface.
Definition: vp8.h:43
unsigned int threads
Definition: vpx_decoder.h:113
unsigned int sz
Definition: vpx_decoder.h:94
Stream properties.
Definition: vpx_decoder.h:93
int noise_level
Definition: vp8.h:83
Provides definitions for using the VP8 algorithm within the vpx Decoder interface.
vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, const uint8_t *data, unsigned int data_sz, vpx_codec_stream_info_t *si)
Parse stream info from a buffer.
#define VPX_PLANE_Y
Definition: vpx_image.h:114
const char * name
Definition: vpx_codec.h:201
#define VPX_PLANE_V
Definition: vpx_image.h:116
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.
Definition: vpx_image.h:56
unsigned int d_w
Definition: vpx_image.h:105
#define vpx_codec_dec_init(ctx, iface, cfg, flags)
Convenience macro for vpx_codec_dec_init_ver()
Definition: vpx_decoder.h:155
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.
int stride[4]
Definition: vpx_image.h:126
unsigned char * planes[4]
Definition: vpx_image.h:125
Definition: vp8.h:42
#define VPX_CODEC_USE_POSTPROC
Definition: vpx_decoder.h:74
Definition: vp8dx.h:59
const char * vpx_codec_error_detail(vpx_codec_ctx_t *ctx)
Retrieve detailed error information for codec context.
#define VPX_PLANE_U
Definition: vpx_image.h:115
int deblocking_level
Definition: vp8.h:82
Definition: vp8.h:46
Definition: vp8.h:44
unsigned int w
Definition: vpx_decoder.h:95
Definition: vp8.h:45
#define vpx_codec_control(ctx, id, data)
vpx_codec_control wrapper macro
Definition: vpx_codec.h:397
vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx)
Destroy a codec instance.
unsigned int d_h
Definition: vpx_image.h:106
post process flags
Definition: vp8.h:80
unsigned int h
Definition: vpx_decoder.h:96
const char * vpx_codec_error(vpx_codec_ctx_t *ctx)
Retrieve error synopsis for codec context.
Initialization Configurations.
Definition: vpx_decoder.h:112
const void * vpx_codec_iter_t
Iterator.
Definition: vpx_codec.h:189
vpx_image_t * vpx_codec_get_frame(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter)
Decoded frames iterator.
int post_proc_flag
Definition: vp8.h:81
Codec context structure.
Definition: vpx_codec.h:200