00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stdarg.h>
00018 #include <string.h>
00019 #include <limits.h>
00020
00021 #define VPX_CODEC_DISABLE_COMPAT 1
00022 #include "vpx_config.h"
00023 #include "vpx/vpx_decoder.h"
00024 #include "vpx_ports/vpx_timer.h"
00025 #if CONFIG_VP8_DECODER
00026 #include "vpx/vp8dx.h"
00027 #endif
00028 #if CONFIG_MD5
00029 #include "md5_utils.h"
00030 #endif
00031 #include "tools_common.h"
00032 #include "nestegg/include/nestegg/nestegg.h"
00033
00034 #if CONFIG_OS_SUPPORT
00035 #if defined(_MSC_VER)
00036 #include <io.h>
00037 #define snprintf _snprintf
00038 #define isatty _isatty
00039 #define fileno _fileno
00040 #else
00041 #include <unistd.h>
00042 #endif
00043 #endif
00044
00045 #ifndef PATH_MAX
00046 #define PATH_MAX 256
00047 #endif
00048
00049 static const char *exec_name;
00050
00051 #define VP8_FOURCC (0x00385056)
00052 static const struct
00053 {
00054 char const *name;
00055 vpx_codec_iface_t *iface;
00056 unsigned int fourcc;
00057 unsigned int fourcc_mask;
00058 } ifaces[] =
00059 {
00060 #if CONFIG_VP8_DECODER
00061 {"vp8", &vpx_codec_vp8_dx_algo, VP8_FOURCC, 0x00FFFFFF},
00062 #endif
00063 };
00064
00065 #include "args.h"
00066 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
00067 "Codec to use");
00068 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
00069 "Output raw YV12 frames");
00070 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
00071 "Output raw I420 frames");
00072 static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
00073 "Flip the chroma planes in the output");
00074 static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
00075 "Don't process the decoded frames");
00076 static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
00077 "Show progress after each frame decodes");
00078 static const arg_def_t limitarg = ARG_DEF(NULL, "limit", 1,
00079 "Stop decoding after n frames");
00080 static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
00081 "Postprocess decoded frames");
00082 static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
00083 "Show timing summary");
00084 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
00085 "Output file name pattern (see below)");
00086 static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
00087 "Max threads to use");
00088 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
00089 "Show version string");
00090 static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0,
00091 "Enable decoder error-concealment");
00092
00093
00094 #if CONFIG_MD5
00095 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
00096 "Compute the MD5 sum of the decoded frame");
00097 #endif
00098 static const arg_def_t *all_args[] =
00099 {
00100 &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
00101 &progressarg, &limitarg, &postprocarg, &summaryarg, &outputfile,
00102 &threadsarg, &verbosearg,
00103 #if CONFIG_MD5
00104 &md5arg,
00105 #endif
00106 &error_concealment,
00107 NULL
00108 };
00109
00110 #if CONFIG_VP8_DECODER
00111 static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1,
00112 "Enable VP8 postproc add noise");
00113 static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0,
00114 "Enable VP8 deblocking");
00115 static const arg_def_t demacroblock_level = ARG_DEF(NULL, "demacroblock-level", 1,
00116 "Enable VP8 demacroblocking, w/ level");
00117 static const arg_def_t pp_debug_info = ARG_DEF(NULL, "pp-debug-info", 1,
00118 "Enable VP8 visible debug info");
00119 static const arg_def_t pp_disp_ref_frame = ARG_DEF(NULL, "pp-dbg-ref-frame", 1,
00120 "Display only selected reference frame per macro block");
00121 static const arg_def_t pp_disp_mb_modes = ARG_DEF(NULL, "pp-dbg-mb-modes", 1,
00122 "Display only selected macro block modes");
00123 static const arg_def_t pp_disp_b_modes = ARG_DEF(NULL, "pp-dbg-b-modes", 1,
00124 "Display only selected block modes");
00125 static const arg_def_t pp_disp_mvs = ARG_DEF(NULL, "pp-dbg-mvs", 1,
00126 "Draw only selected motion vectors");
00127 static const arg_def_t mfqe = ARG_DEF(NULL, "mfqe", 0,
00128 "Enable multiframe quality enhancement");
00129
00130 static const arg_def_t *vp8_pp_args[] =
00131 {
00132 &addnoise_level, &deblock, &demacroblock_level, &pp_debug_info,
00133 &pp_disp_ref_frame, &pp_disp_mb_modes, &pp_disp_b_modes, &pp_disp_mvs, &mfqe,
00134 NULL
00135 };
00136 #endif
00137
00138 static void usage_exit()
00139 {
00140 int i;
00141
00142 fprintf(stderr, "Usage: %s <options> filename\n\n"
00143 "Options:\n", exec_name);
00144 arg_show_usage(stderr, all_args);
00145 #if CONFIG_VP8_DECODER
00146 fprintf(stderr, "\nVP8 Postprocessing Options:\n");
00147 arg_show_usage(stderr, vp8_pp_args);
00148 #endif
00149 fprintf(stderr,
00150 "\nOutput File Patterns:\n\n"
00151 " The -o argument specifies the name of the file(s) to "
00152 "write to. If the\n argument does not include any escape "
00153 "characters, the output will be\n written to a single file. "
00154 "Otherwise, the filename will be calculated by\n expanding "
00155 "the following escape characters:\n");
00156 fprintf(stderr,
00157 "\n\t%%w - Frame width"
00158 "\n\t%%h - Frame height"
00159 "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
00160 "\n\n Pattern arguments are only supported in conjunction "
00161 "with the --yv12 and\n --i420 options. If the -o option is "
00162 "not specified, the output will be\n directed to stdout.\n"
00163 );
00164 fprintf(stderr, "\nIncluded decoders:\n\n");
00165
00166 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
00167 fprintf(stderr, " %-6s - %s\n",
00168 ifaces[i].name,
00169 vpx_codec_iface_name(ifaces[i].iface));
00170
00171 exit(EXIT_FAILURE);
00172 }
00173
00174 void die(const char *fmt, ...)
00175 {
00176 va_list ap;
00177 va_start(ap, fmt);
00178 vfprintf(stderr, fmt, ap);
00179 fprintf(stderr, "\n");
00180 usage_exit();
00181 }
00182
00183 static unsigned int mem_get_le16(const void *vmem)
00184 {
00185 unsigned int val;
00186 const unsigned char *mem = (const unsigned char *)vmem;
00187
00188 val = mem[1] << 8;
00189 val |= mem[0];
00190 return val;
00191 }
00192
00193 static unsigned int mem_get_le32(const void *vmem)
00194 {
00195 unsigned int val;
00196 const unsigned char *mem = (const unsigned char *)vmem;
00197
00198 val = mem[3] << 24;
00199 val |= mem[2] << 16;
00200 val |= mem[1] << 8;
00201 val |= mem[0];
00202 return val;
00203 }
00204
00205 enum file_kind
00206 {
00207 RAW_FILE,
00208 IVF_FILE,
00209 WEBM_FILE
00210 };
00211
00212 struct input_ctx
00213 {
00214 enum file_kind kind;
00215 FILE *infile;
00216 nestegg *nestegg_ctx;
00217 nestegg_packet *pkt;
00218 unsigned int chunk;
00219 unsigned int chunks;
00220 unsigned int video_track;
00221 };
00222
00223 #define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
00224 #define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
00225 static int read_frame(struct input_ctx *input,
00226 uint8_t **buf,
00227 size_t *buf_sz,
00228 size_t *buf_alloc_sz)
00229 {
00230 char raw_hdr[IVF_FRAME_HDR_SZ];
00231 size_t new_buf_sz;
00232 FILE *infile = input->infile;
00233 enum file_kind kind = input->kind;
00234 if(kind == WEBM_FILE)
00235 {
00236 if(input->chunk >= input->chunks)
00237 {
00238 unsigned int track;
00239
00240 do
00241 {
00242
00243 if(input->pkt)
00244 nestegg_free_packet(input->pkt);
00245
00246 if(nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
00247 || nestegg_packet_track(input->pkt, &track))
00248 return 1;
00249
00250 } while(track != input->video_track);
00251
00252 if(nestegg_packet_count(input->pkt, &input->chunks))
00253 return 1;
00254 input->chunk = 0;
00255 }
00256
00257 if(nestegg_packet_data(input->pkt, input->chunk, buf, buf_sz))
00258 return 1;
00259 input->chunk++;
00260
00261 return 0;
00262 }
00263
00264
00265
00266
00267 else if (fread(raw_hdr, kind==IVF_FILE
00268 ? IVF_FRAME_HDR_SZ : RAW_FRAME_HDR_SZ, 1, infile) != 1)
00269 {
00270 if (!feof(infile))
00271 fprintf(stderr, "Failed to read frame size\n");
00272
00273 new_buf_sz = 0;
00274 }
00275 else
00276 {
00277 new_buf_sz = mem_get_le32(raw_hdr);
00278
00279 if (new_buf_sz > 256 * 1024 * 1024)
00280 {
00281 fprintf(stderr, "Error: Read invalid frame size (%u)\n",
00282 (unsigned int)new_buf_sz);
00283 new_buf_sz = 0;
00284 }
00285
00286 if (kind == RAW_FILE && new_buf_sz > 256 * 1024)
00287 fprintf(stderr, "Warning: Read invalid frame size (%u)"
00288 " - not a raw file?\n", (unsigned int)new_buf_sz);
00289
00290 if (new_buf_sz > *buf_alloc_sz)
00291 {
00292 uint8_t *new_buf = realloc(*buf, 2 * new_buf_sz);
00293
00294 if (new_buf)
00295 {
00296 *buf = new_buf;
00297 *buf_alloc_sz = 2 * new_buf_sz;
00298 }
00299 else
00300 {
00301 fprintf(stderr, "Failed to allocate compressed data buffer\n");
00302 new_buf_sz = 0;
00303 }
00304 }
00305 }
00306
00307 *buf_sz = new_buf_sz;
00308
00309 if (!feof(infile))
00310 {
00311 if (fread(*buf, 1, *buf_sz, infile) != *buf_sz)
00312 {
00313 fprintf(stderr, "Failed to read full frame\n");
00314 return 1;
00315 }
00316
00317 return 0;
00318 }
00319
00320 return 1;
00321 }
00322
00323 void *out_open(const char *out_fn, int do_md5)
00324 {
00325 void *out = NULL;
00326
00327 if (do_md5)
00328 {
00329 #if CONFIG_MD5
00330 MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
00331 (void)out_fn;
00332 MD5Init(md5_ctx);
00333 #endif
00334 }
00335 else
00336 {
00337 FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb")
00338 : set_binary_mode(stdout);
00339
00340 if (!outfile)
00341 {
00342 fprintf(stderr, "Failed to output file");
00343 exit(EXIT_FAILURE);
00344 }
00345 }
00346
00347 return out;
00348 }
00349
00350 void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5)
00351 {
00352 if (do_md5)
00353 {
00354 #if CONFIG_MD5
00355 MD5Update(out, buf, len);
00356 #endif
00357 }
00358 else
00359 {
00360 (void) fwrite(buf, 1, len, out);
00361 }
00362 }
00363
00364 void out_close(void *out, const char *out_fn, int do_md5)
00365 {
00366 if (do_md5)
00367 {
00368 #if CONFIG_MD5
00369 uint8_t md5[16];
00370 int i;
00371
00372 MD5Final(md5, out);
00373 free(out);
00374
00375 for (i = 0; i < 16; i++)
00376 printf("%02x", md5[i]);
00377
00378 printf(" %s\n", out_fn);
00379 #endif
00380 }
00381 else
00382 {
00383 fclose(out);
00384 }
00385 }
00386
00387 unsigned int file_is_ivf(FILE *infile,
00388 unsigned int *fourcc,
00389 unsigned int *width,
00390 unsigned int *height,
00391 unsigned int *fps_den,
00392 unsigned int *fps_num)
00393 {
00394 char raw_hdr[32];
00395 int is_ivf = 0;
00396
00397 if (fread(raw_hdr, 1, 32, infile) == 32)
00398 {
00399 if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
00400 && raw_hdr[2] == 'I' && raw_hdr[3] == 'F')
00401 {
00402 is_ivf = 1;
00403
00404 if (mem_get_le16(raw_hdr + 4) != 0)
00405 fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
00406 " decode properly.");
00407
00408 *fourcc = mem_get_le32(raw_hdr + 8);
00409 *width = mem_get_le16(raw_hdr + 12);
00410 *height = mem_get_le16(raw_hdr + 14);
00411 *fps_num = mem_get_le32(raw_hdr + 16);
00412 *fps_den = mem_get_le32(raw_hdr + 20);
00413
00414
00415
00416
00417
00418
00419 if(*fps_num < 1000)
00420 {
00421
00422
00423
00424 if(*fps_num&1)*fps_den<<=1;
00425 else *fps_num>>=1;
00426 }
00427 else
00428 {
00429
00430
00431
00432 *fps_num = 30;
00433 *fps_den = 1;
00434 }
00435 }
00436 }
00437
00438 if (!is_ivf)
00439 rewind(infile);
00440
00441 return is_ivf;
00442 }
00443
00444
00445 unsigned int file_is_raw(FILE *infile,
00446 unsigned int *fourcc,
00447 unsigned int *width,
00448 unsigned int *height,
00449 unsigned int *fps_den,
00450 unsigned int *fps_num)
00451 {
00452 unsigned char buf[32];
00453 int is_raw = 0;
00454 vpx_codec_stream_info_t si;
00455
00456 si.sz = sizeof(si);
00457
00458 if (fread(buf, 1, 32, infile) == 32)
00459 {
00460 int i;
00461
00462 if(mem_get_le32(buf) < 256 * 1024 * 1024)
00463 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
00464 if(!vpx_codec_peek_stream_info(ifaces[i].iface,
00465 buf + 4, 32 - 4, &si))
00466 {
00467 is_raw = 1;
00468 *fourcc = ifaces[i].fourcc;
00469 *width = si.w;
00470 *height = si.h;
00471 *fps_num = 30;
00472 *fps_den = 1;
00473 break;
00474 }
00475 }
00476
00477 rewind(infile);
00478 return is_raw;
00479 }
00480
00481
00482 static int
00483 nestegg_read_cb(void *buffer, size_t length, void *userdata)
00484 {
00485 FILE *f = userdata;
00486
00487 if(fread(buffer, 1, length, f) < length)
00488 {
00489 if (ferror(f))
00490 return -1;
00491 if (feof(f))
00492 return 0;
00493 }
00494 return 1;
00495 }
00496
00497
00498 static int
00499 nestegg_seek_cb(int64_t offset, int whence, void * userdata)
00500 {
00501 switch(whence) {
00502 case NESTEGG_SEEK_SET: whence = SEEK_SET; break;
00503 case NESTEGG_SEEK_CUR: whence = SEEK_CUR; break;
00504 case NESTEGG_SEEK_END: whence = SEEK_END; break;
00505 };
00506 return fseek(userdata, (long)offset, whence)? -1 : 0;
00507 }
00508
00509
00510 static int64_t
00511 nestegg_tell_cb(void * userdata)
00512 {
00513 return ftell(userdata);
00514 }
00515
00516
00517 static void
00518 nestegg_log_cb(nestegg * context, unsigned int severity, char const * format,
00519 ...)
00520 {
00521 va_list ap;
00522
00523 va_start(ap, format);
00524 vfprintf(stderr, format, ap);
00525 fprintf(stderr, "\n");
00526 va_end(ap);
00527 }
00528
00529
00530 static int
00531 webm_guess_framerate(struct input_ctx *input,
00532 unsigned int *fps_den,
00533 unsigned int *fps_num)
00534 {
00535 unsigned int i;
00536 uint64_t tstamp=0;
00537
00538
00539
00540
00541 for(i=0; tstamp < 1000000000 && i < 50;)
00542 {
00543 nestegg_packet * pkt;
00544 unsigned int track;
00545
00546 if(nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
00547 break;
00548
00549 nestegg_packet_track(pkt, &track);
00550 if(track == input->video_track)
00551 {
00552 nestegg_packet_tstamp(pkt, &tstamp);
00553 i++;
00554 }
00555
00556 nestegg_free_packet(pkt);
00557 }
00558
00559 if(nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
00560 goto fail;
00561
00562 *fps_num = (i - 1) * 1000000;
00563 *fps_den = (unsigned int)(tstamp / 1000);
00564 return 0;
00565 fail:
00566 nestegg_destroy(input->nestegg_ctx);
00567 input->nestegg_ctx = NULL;
00568 rewind(input->infile);
00569 return 1;
00570 }
00571
00572
00573 static int
00574 file_is_webm(struct input_ctx *input,
00575 unsigned int *fourcc,
00576 unsigned int *width,
00577 unsigned int *height,
00578 unsigned int *fps_den,
00579 unsigned int *fps_num)
00580 {
00581 unsigned int i, n;
00582 int track_type = -1;
00583
00584 nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
00585 nestegg_video_params params;
00586
00587 io.userdata = input->infile;
00588 if(nestegg_init(&input->nestegg_ctx, io, NULL))
00589 goto fail;
00590
00591 if(nestegg_track_count(input->nestegg_ctx, &n))
00592 goto fail;
00593
00594 for(i=0; i<n; i++)
00595 {
00596 track_type = nestegg_track_type(input->nestegg_ctx, i);
00597
00598 if(track_type == NESTEGG_TRACK_VIDEO)
00599 break;
00600 else if(track_type < 0)
00601 goto fail;
00602 }
00603
00604 if(nestegg_track_codec_id(input->nestegg_ctx, i) != NESTEGG_CODEC_VP8)
00605 {
00606 fprintf(stderr, "Not VP8 video, quitting.\n");
00607 exit(1);
00608 }
00609
00610 input->video_track = i;
00611
00612 if(nestegg_track_video_params(input->nestegg_ctx, i, ¶ms))
00613 goto fail;
00614
00615 *fps_den = 0;
00616 *fps_num = 0;
00617 *fourcc = VP8_FOURCC;
00618 *width = params.width;
00619 *height = params.height;
00620 return 1;
00621 fail:
00622 input->nestegg_ctx = NULL;
00623 rewind(input->infile);
00624 return 0;
00625 }
00626
00627
00628 void show_progress(int frame_in, int frame_out, unsigned long dx_time)
00629 {
00630 fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
00631 frame_in, frame_out, dx_time,
00632 (float)frame_out * 1000000.0 / (float)dx_time);
00633 }
00634
00635
00636 void generate_filename(const char *pattern, char *out, size_t q_len,
00637 unsigned int d_w, unsigned int d_h,
00638 unsigned int frame_in)
00639 {
00640 const char *p = pattern;
00641 char *q = out;
00642
00643 do
00644 {
00645 char *next_pat = strchr(p, '%');
00646
00647 if(p == next_pat)
00648 {
00649 size_t pat_len;
00650
00651
00652 q[q_len - 1] = '\0';
00653 switch(p[1])
00654 {
00655 case 'w': snprintf(q, q_len - 1, "%d", d_w); break;
00656 case 'h': snprintf(q, q_len - 1, "%d", d_h); break;
00657 case '1': snprintf(q, q_len - 1, "%d", frame_in); break;
00658 case '2': snprintf(q, q_len - 1, "%02d", frame_in); break;
00659 case '3': snprintf(q, q_len - 1, "%03d", frame_in); break;
00660 case '4': snprintf(q, q_len - 1, "%04d", frame_in); break;
00661 case '5': snprintf(q, q_len - 1, "%05d", frame_in); break;
00662 case '6': snprintf(q, q_len - 1, "%06d", frame_in); break;
00663 case '7': snprintf(q, q_len - 1, "%07d", frame_in); break;
00664 case '8': snprintf(q, q_len - 1, "%08d", frame_in); break;
00665 case '9': snprintf(q, q_len - 1, "%09d", frame_in); break;
00666 default:
00667 die("Unrecognized pattern %%%c\n", p[1]);
00668 }
00669
00670 pat_len = strlen(q);
00671 if(pat_len >= q_len - 1)
00672 die("Output filename too long.\n");
00673 q += pat_len;
00674 p += 2;
00675 q_len -= pat_len;
00676 }
00677 else
00678 {
00679 size_t copy_len;
00680
00681
00682 if(!next_pat)
00683 copy_len = strlen(p);
00684 else
00685 copy_len = next_pat - p;
00686
00687 if(copy_len >= q_len - 1)
00688 die("Output filename too long.\n");
00689
00690 memcpy(q, p, copy_len);
00691 q[copy_len] = '\0';
00692 q += copy_len;
00693 p += copy_len;
00694 q_len -= copy_len;
00695 }
00696 } while(*p);
00697 }
00698
00699
00700 int main(int argc, const char **argv_)
00701 {
00702 vpx_codec_ctx_t decoder;
00703 char *fn = NULL;
00704 int i;
00705 uint8_t *buf = NULL;
00706 size_t buf_sz = 0, buf_alloc_sz = 0;
00707 FILE *infile;
00708 int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
00709 int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
00710 int ec_enabled = 0;
00711 vpx_codec_iface_t *iface = NULL;
00712 unsigned int fourcc;
00713 unsigned long dx_time = 0;
00714 struct arg arg;
00715 char **argv, **argi, **argj;
00716 const char *outfile_pattern = 0;
00717 char outfile[PATH_MAX];
00718 int single_file;
00719 int use_y4m = 1;
00720 unsigned int width;
00721 unsigned int height;
00722 unsigned int fps_den;
00723 unsigned int fps_num;
00724 void *out = NULL;
00725 vpx_codec_dec_cfg_t cfg = {0};
00726 #if CONFIG_VP8_DECODER
00727 vp8_postproc_cfg_t vp8_pp_cfg = {0};
00728 int vp8_dbg_color_ref_frame = 0;
00729 int vp8_dbg_color_mb_modes = 0;
00730 int vp8_dbg_color_b_modes = 0;
00731 int vp8_dbg_display_mv = 0;
00732 #endif
00733 struct input_ctx input = {0};
00734 int frames_corrupted = 0;
00735 int dec_flags = 0;
00736
00737
00738 exec_name = argv_[0];
00739 argv = argv_dup(argc - 1, argv_ + 1);
00740
00741 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
00742 {
00743 memset(&arg, 0, sizeof(arg));
00744 arg.argv_step = 1;
00745
00746 if (arg_match(&arg, &codecarg, argi))
00747 {
00748 int j, k = -1;
00749
00750 for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
00751 if (!strcmp(ifaces[j].name, arg.val))
00752 k = j;
00753
00754 if (k >= 0)
00755 iface = ifaces[k].iface;
00756 else
00757 die("Error: Unrecognized argument (%s) to --codec\n",
00758 arg.val);
00759 }
00760 else if (arg_match(&arg, &outputfile, argi))
00761 outfile_pattern = arg.val;
00762 else if (arg_match(&arg, &use_yv12, argi))
00763 {
00764 use_y4m = 0;
00765 flipuv = 1;
00766 }
00767 else if (arg_match(&arg, &use_i420, argi))
00768 {
00769 use_y4m = 0;
00770 flipuv = 0;
00771 }
00772 else if (arg_match(&arg, &flipuvarg, argi))
00773 flipuv = 1;
00774 else if (arg_match(&arg, &noblitarg, argi))
00775 noblit = 1;
00776 else if (arg_match(&arg, &progressarg, argi))
00777 progress = 1;
00778 else if (arg_match(&arg, &limitarg, argi))
00779 stop_after = arg_parse_uint(&arg);
00780 else if (arg_match(&arg, &postprocarg, argi))
00781 postproc = 1;
00782 else if (arg_match(&arg, &md5arg, argi))
00783 do_md5 = 1;
00784 else if (arg_match(&arg, &summaryarg, argi))
00785 summary = 1;
00786 else if (arg_match(&arg, &threadsarg, argi))
00787 cfg.threads = arg_parse_uint(&arg);
00788 else if (arg_match(&arg, &verbosearg, argi))
00789 quiet = 0;
00790
00791 #if CONFIG_VP8_DECODER
00792 else if (arg_match(&arg, &addnoise_level, argi))
00793 {
00794 postproc = 1;
00795 vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE;
00796 vp8_pp_cfg.noise_level = arg_parse_uint(&arg);
00797 }
00798 else if (arg_match(&arg, &demacroblock_level, argi))
00799 {
00800 postproc = 1;
00801 vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK;
00802 vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg);
00803 }
00804 else if (arg_match(&arg, &deblock, argi))
00805 {
00806 postproc = 1;
00807 vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK;
00808 }
00809 else if (arg_match(&arg, &mfqe, argi))
00810 {
00811 postproc = 1;
00812 vp8_pp_cfg.post_proc_flag |= VP8_MFQE;
00813 }
00814 else if (arg_match(&arg, &pp_debug_info, argi))
00815 {
00816 unsigned int level = arg_parse_uint(&arg);
00817
00818 postproc = 1;
00819 vp8_pp_cfg.post_proc_flag &= ~0x7;
00820
00821 if (level)
00822 vp8_pp_cfg.post_proc_flag |= level;
00823 }
00824 else if (arg_match(&arg, &pp_disp_ref_frame, argi))
00825 {
00826 unsigned int flags = arg_parse_int(&arg);
00827 if (flags)
00828 {
00829 postproc = 1;
00830 vp8_dbg_color_ref_frame = flags;
00831 }
00832 }
00833 else if (arg_match(&arg, &pp_disp_mb_modes, argi))
00834 {
00835 unsigned int flags = arg_parse_int(&arg);
00836 if (flags)
00837 {
00838 postproc = 1;
00839 vp8_dbg_color_mb_modes = flags;
00840 }
00841 }
00842 else if (arg_match(&arg, &pp_disp_b_modes, argi))
00843 {
00844 unsigned int flags = arg_parse_int(&arg);
00845 if (flags)
00846 {
00847 postproc = 1;
00848 vp8_dbg_color_b_modes = flags;
00849 }
00850 }
00851 else if (arg_match(&arg, &pp_disp_mvs, argi))
00852 {
00853 unsigned int flags = arg_parse_int(&arg);
00854 if (flags)
00855 {
00856 postproc = 1;
00857 vp8_dbg_display_mv = flags;
00858 }
00859 }
00860 else if (arg_match(&arg, &error_concealment, argi))
00861 {
00862 ec_enabled = 1;
00863 }
00864
00865 #endif
00866 else
00867 argj++;
00868 }
00869
00870
00871 for (argi = argv; *argi; argi++)
00872 if (argi[0][0] == '-' && strlen(argi[0]) > 1)
00873 die("Error: Unrecognized option %s\n", *argi);
00874
00875
00876 fn = argv[0];
00877
00878 if (!fn)
00879 usage_exit();
00880
00881
00882 infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin);
00883
00884 if (!infile)
00885 {
00886 fprintf(stderr, "Failed to open file '%s'",
00887 strcmp(fn, "-") ? fn : "stdin");
00888 return EXIT_FAILURE;
00889 }
00890 #if CONFIG_OS_SUPPORT
00891
00892 if(!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit)
00893 {
00894 fprintf(stderr,
00895 "Not dumping raw video to your terminal. Use '-o -' to "
00896 "override.\n");
00897 return EXIT_FAILURE;
00898 }
00899 #endif
00900 input.infile = infile;
00901 if(file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
00902 &fps_num))
00903 input.kind = IVF_FILE;
00904 else if(file_is_webm(&input, &fourcc, &width, &height, &fps_den, &fps_num))
00905 input.kind = WEBM_FILE;
00906 else if(file_is_raw(infile, &fourcc, &width, &height, &fps_den, &fps_num))
00907 input.kind = RAW_FILE;
00908 else
00909 {
00910 fprintf(stderr, "Unrecognized input file type.\n");
00911 return EXIT_FAILURE;
00912 }
00913
00914
00915
00916
00917 outfile_pattern = outfile_pattern ? outfile_pattern : "-";
00918 single_file = 1;
00919 {
00920 const char *p = outfile_pattern;
00921 do
00922 {
00923 p = strchr(p, '%');
00924 if(p && p[1] >= '1' && p[1] <= '9')
00925 {
00926
00927 single_file = 0;
00928 break;
00929 }
00930 if(p)
00931 p++;
00932 } while(p);
00933 }
00934
00935 if(single_file && !noblit)
00936 {
00937 generate_filename(outfile_pattern, outfile, sizeof(outfile)-1,
00938 width, height, 0);
00939 out = out_open(outfile, do_md5);
00940 }
00941
00942 if (use_y4m && !noblit)
00943 {
00944 char buffer[128];
00945 if (!single_file)
00946 {
00947 fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
00948 " try --i420 or --yv12.\n");
00949 return EXIT_FAILURE;
00950 }
00951
00952 if(input.kind == WEBM_FILE)
00953 if(webm_guess_framerate(&input, &fps_den, &fps_num))
00954 {
00955 fprintf(stderr, "Failed to guess framerate -- error parsing "
00956 "webm file?\n");
00957 return EXIT_FAILURE;
00958 }
00959
00960
00961
00962
00963
00964 sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
00965 "420jpeg", width, height, fps_num, fps_den, 'p');
00966 out_put(out, (unsigned char *)buffer,
00967 (unsigned int)strlen(buffer), do_md5);
00968 }
00969
00970
00971 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
00972 if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc)
00973 {
00974 vpx_codec_iface_t *ivf_iface = ifaces[i].iface;
00975
00976 if (iface && iface != ivf_iface)
00977 fprintf(stderr, "Notice -- IVF header indicates codec: %s\n",
00978 ifaces[i].name);
00979 else
00980 iface = ivf_iface;
00981
00982 break;
00983 }
00984
00985 dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
00986 (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
00987 if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface, &cfg,
00988 dec_flags))
00989 {
00990 fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
00991 return EXIT_FAILURE;
00992 }
00993
00994 if (!quiet)
00995 fprintf(stderr, "%s\n", decoder.name);
00996
00997 #if CONFIG_VP8_DECODER
00998
00999 if (vp8_pp_cfg.post_proc_flag
01000 && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg))
01001 {
01002 fprintf(stderr, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder));
01003 return EXIT_FAILURE;
01004 }
01005
01006 if (vp8_dbg_color_ref_frame
01007 && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME, vp8_dbg_color_ref_frame))
01008 {
01009 fprintf(stderr, "Failed to configure reference block visualizer: %s\n", vpx_codec_error(&decoder));
01010 return EXIT_FAILURE;
01011 }
01012
01013 if (vp8_dbg_color_mb_modes
01014 && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES, vp8_dbg_color_mb_modes))
01015 {
01016 fprintf(stderr, "Failed to configure macro block visualizer: %s\n", vpx_codec_error(&decoder));
01017 return EXIT_FAILURE;
01018 }
01019
01020 if (vp8_dbg_color_b_modes
01021 && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES, vp8_dbg_color_b_modes))
01022 {
01023 fprintf(stderr, "Failed to configure block visualizer: %s\n", vpx_codec_error(&decoder));
01024 return EXIT_FAILURE;
01025 }
01026
01027 if (vp8_dbg_display_mv
01028 && vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vp8_dbg_display_mv))
01029 {
01030 fprintf(stderr, "Failed to configure motion vector visualizer: %s\n", vpx_codec_error(&decoder));
01031 return EXIT_FAILURE;
01032 }
01033 #endif
01034
01035
01036 while (!read_frame(&input, &buf, &buf_sz, &buf_alloc_sz))
01037 {
01038 vpx_codec_iter_t iter = NULL;
01039 vpx_image_t *img;
01040 struct vpx_usec_timer timer;
01041 int corrupted;
01042
01043 vpx_usec_timer_start(&timer);
01044
01045 if (vpx_codec_decode(&decoder, buf, (unsigned int)buf_sz, NULL, 0))
01046 {
01047 const char *detail = vpx_codec_error_detail(&decoder);
01048 fprintf(stderr, "Failed to decode frame: %s\n", vpx_codec_error(&decoder));
01049
01050 if (detail)
01051 fprintf(stderr, " Additional information: %s\n", detail);
01052
01053 goto fail;
01054 }
01055
01056 vpx_usec_timer_mark(&timer);
01057 dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
01058
01059 ++frame_in;
01060
01061 if (vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted))
01062 {
01063 fprintf(stderr, "Failed VP8_GET_FRAME_CORRUPTED: %s\n",
01064 vpx_codec_error(&decoder));
01065 goto fail;
01066 }
01067 frames_corrupted += corrupted;
01068
01069 vpx_usec_timer_start(&timer);
01070
01071 if ((img = vpx_codec_get_frame(&decoder, &iter)))
01072 ++frame_out;
01073
01074 vpx_usec_timer_mark(&timer);
01075 dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer);
01076
01077 if (progress)
01078 show_progress(frame_in, frame_out, dx_time);
01079
01080 if (!noblit)
01081 {
01082 if (img)
01083 {
01084 unsigned int y;
01085 char out_fn[PATH_MAX];
01086 uint8_t *buf;
01087
01088 if (!single_file)
01089 {
01090 size_t len = sizeof(out_fn)-1;
01091
01092 out_fn[len] = '\0';
01093 generate_filename(outfile_pattern, out_fn, len-1,
01094 img->d_w, img->d_h, frame_in);
01095 out = out_open(out_fn, do_md5);
01096 }
01097 else if(use_y4m)
01098 out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
01099
01100 buf = img->planes[VPX_PLANE_Y];
01101
01102 for (y = 0; y < img->d_h; y++)
01103 {
01104 out_put(out, buf, img->d_w, do_md5);
01105 buf += img->stride[VPX_PLANE_Y];
01106 }
01107
01108 buf = img->planes[flipuv?VPX_PLANE_V:VPX_PLANE_U];
01109
01110 for (y = 0; y < (1 + img->d_h) / 2; y++)
01111 {
01112 out_put(out, buf, (1 + img->d_w) / 2, do_md5);
01113 buf += img->stride[VPX_PLANE_U];
01114 }
01115
01116 buf = img->planes[flipuv?VPX_PLANE_U:VPX_PLANE_V];
01117
01118 for (y = 0; y < (1 + img->d_h) / 2; y++)
01119 {
01120 out_put(out, buf, (1 + img->d_w) / 2, do_md5);
01121 buf += img->stride[VPX_PLANE_V];
01122 }
01123
01124 if (!single_file)
01125 out_close(out, out_fn, do_md5);
01126 }
01127 }
01128
01129 if (stop_after && frame_in >= stop_after)
01130 break;
01131 }
01132
01133 if (summary || progress)
01134 {
01135 show_progress(frame_in, frame_out, dx_time);
01136 fprintf(stderr, "\n");
01137 }
01138
01139 if (frames_corrupted)
01140 fprintf(stderr, "WARNING: %d frames corrupted.\n",frames_corrupted);
01141
01142 fail:
01143
01144 if (vpx_codec_destroy(&decoder))
01145 {
01146 fprintf(stderr, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder));
01147 return EXIT_FAILURE;
01148 }
01149
01150 if (single_file && !noblit)
01151 out_close(out, outfile, do_md5);
01152
01153 if(input.nestegg_ctx)
01154 nestegg_destroy(input.nestegg_ctx);
01155 if(input.kind != WEBM_FILE)
01156 free(buf);
01157 fclose(infile);
01158 free(argv);
01159
01160 return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS;
01161 }