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