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