2 * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license and patent
5 * grant that can be found in the LICENSE file in the root of the source
6 * tree. All contributing project authors may be found in the AUTHORS
7 * file in the root of the source tree.
11 /* This is a simple program that reads ivf files and decodes them
12 * using the new interface. Decoded frames are output as YV12 raw.
18 #define VPX_CODEC_DISABLE_COMPAT 1
19 #include "vpx_config.h"
20 #include "vpx/vpx_decoder.h"
21 #include "vpx_ports/vpx_timer.h"
22 #if CONFIG_VP8_DECODER
23 #include "vpx/vp8dx.h"
26 #include "md5_utils.h"
29 static const char *exec_name
;
34 const vpx_codec_iface_t
*iface
;
36 unsigned int fourcc_mask
;
39 #if CONFIG_VP8_DECODER
40 {"vp8", &vpx_codec_vp8_dx_algo
, 0x00385056, 0x00FFFFFF},
45 static const arg_def_t codecarg
= ARG_DEF(NULL
, "codec", 1,
47 static const arg_def_t prefixarg
= ARG_DEF("p", "prefix", 1,
48 "Prefix to use when saving frames");
49 static const arg_def_t use_yv12
= ARG_DEF(NULL
, "yv12", 0,
50 "Output file is YV12 ");
51 static const arg_def_t use_i420
= ARG_DEF(NULL
, "i420", 0,
52 "Output file is I420 (default)");
53 static const arg_def_t flipuvarg
= ARG_DEF(NULL
, "flipuv", 0,
54 "Synonym for --yv12");
55 static const arg_def_t noblitarg
= ARG_DEF(NULL
, "noblit", 0,
56 "Don't process the decoded frames");
57 static const arg_def_t progressarg
= ARG_DEF(NULL
, "progress", 0,
58 "Show progress after each frame decodes");
59 static const arg_def_t limitarg
= ARG_DEF(NULL
, "limit", 1,
60 "Stop decoding after n frames");
61 static const arg_def_t postprocarg
= ARG_DEF(NULL
, "postproc", 0,
62 "Postprocess decoded frames");
63 static const arg_def_t summaryarg
= ARG_DEF(NULL
, "summary", 0,
64 "Show timing summary");
65 static const arg_def_t outputfile
= ARG_DEF("o", "output-raw-file", 1,
66 "Output raw yv12 file instead of images");
67 static const arg_def_t threadsarg
= ARG_DEF("t", "threads", 1,
68 "Max threads to use");
69 static const arg_def_t quietarg
= ARG_DEF("q", "quiet", 0,
70 "Suppress version string");
73 static const arg_def_t md5arg
= ARG_DEF(NULL
, "md5", 0,
74 "Compute the MD5 sum of the decoded frame");
76 static const arg_def_t
*all_args
[] =
78 &codecarg
, &prefixarg
, &use_yv12
, &use_i420
, &flipuvarg
, &noblitarg
,
79 &progressarg
, &limitarg
, &postprocarg
, &summaryarg
, &outputfile
,
80 &threadsarg
, &quietarg
,
87 #if CONFIG_VP8_DECODER
88 static const arg_def_t addnoise_level
= ARG_DEF(NULL
, "noise-level", 1,
89 "Enable VP8 postproc add noise");
90 static const arg_def_t deblock
= ARG_DEF(NULL
, "deblock", 0,
91 "Enable VP8 deblocking");
92 static const arg_def_t demacroblock_level
= ARG_DEF(NULL
, "demacroblock-level", 1,
93 "Enable VP8 demacroblocking, w/ level");
94 static const arg_def_t pp_debug_info
= ARG_DEF(NULL
, "pp-debug-info", 1,
95 "Enable VP8 visible debug info");
98 static const arg_def_t
*vp8_pp_args
[] =
100 &addnoise_level
, &deblock
, &demacroblock_level
, &pp_debug_info
,
105 static void usage_exit()
109 fprintf(stderr
, "Usage: %s <options> filename\n\n"
110 "Options:\n", exec_name
);
111 arg_show_usage(stderr
, all_args
);
112 #if CONFIG_VP8_DECODER
113 fprintf(stderr
, "\nvp8 Postprocessing Options:\n");
114 arg_show_usage(stderr
, vp8_pp_args
);
116 fprintf(stderr
, "\nIncluded decoders:\n\n");
118 for (i
= 0; i
< sizeof(ifaces
) / sizeof(ifaces
[0]); i
++)
119 fprintf(stderr
, " %-6s - %s\n",
121 vpx_codec_iface_name(ifaces
[i
].iface
));
126 void die(const char *fmt
, ...)
130 vfprintf(stderr
, fmt
, ap
);
131 fprintf(stderr
, "\n");
135 static unsigned int mem_get_le16(const void *vmem
)
138 const unsigned char *mem
= (const unsigned char *)vmem
;
145 static unsigned int mem_get_le32(const void *vmem
)
148 const unsigned char *mem
= (const unsigned char *)vmem
;
157 #define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
158 #define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
159 static int read_frame(FILE *infile
,
162 uint32_t *buf_alloc_sz
,
165 char raw_hdr
[IVF_FRAME_HDR_SZ
];
168 /* For both the raw and ivf formats, the frame size is the first 4 bytes
169 * of the frame header. We just need to special case on the header
172 if (fread(raw_hdr
, is_ivf
? IVF_FRAME_HDR_SZ
: RAW_FRAME_HDR_SZ
, 1,
176 fprintf(stderr
, "Failed to read frame size\n");
182 new_buf_sz
= mem_get_le32(raw_hdr
);
184 if (new_buf_sz
> 256 * 1024 * 1024)
186 fprintf(stderr
, "Error: Read invalid frame size (%u)\n",
191 if (!is_ivf
&& new_buf_sz
> 256 * 1024)
192 fprintf(stderr
, "Warning: Read invalid frame size (%u)"
193 " - not a raw file?\n", new_buf_sz
);
195 if (new_buf_sz
> *buf_alloc_sz
)
197 uint8_t *new_buf
= realloc(*buf
, 2 * new_buf_sz
);
202 *buf_alloc_sz
= 2 * new_buf_sz
;
206 fprintf(stderr
, "Failed to allocate compressed data buffer\n");
212 *buf_sz
= new_buf_sz
;
216 if (fread(*buf
, 1, *buf_sz
, infile
) != *buf_sz
)
218 fprintf(stderr
, "Failed to read full frame\n");
228 void *out_open(const char *out_fn
, int do_md5
)
235 md5_ctx_t
*md5_ctx
= out
= malloc(sizeof(md5_ctx_t
));
242 FILE *outfile
= out
= strcmp("-", out_fn
) ? fopen(out_fn
, "wb") : stdout
;
246 fprintf(stderr
, "Failed to output file");
254 void out_put(void *out
, const uint8_t *buf
, unsigned int len
, int do_md5
)
259 md5_update(out
, buf
, len
);
264 fwrite(buf
, 1, len
, out
);
268 void out_close(void *out
, const char *out_fn
, int do_md5
)
276 md5_finalize(out
, md5
);
279 for (i
= 0; i
< 16; i
++)
280 printf("%02x", md5
[i
]);
282 printf(" %s\n", out_fn
);
291 unsigned int file_is_ivf(FILE *infile
, unsigned int *fourcc
)
296 if (fread(raw_hdr
, 1, 32, infile
) == 32)
298 if (raw_hdr
[0] == 'D' && raw_hdr
[1] == 'K'
299 && raw_hdr
[2] == 'I' && raw_hdr
[3] == 'F')
303 if (mem_get_le16(raw_hdr
+ 4) != 0)
304 fprintf(stderr
, "Error: Unrecognized IVF version! This file may not"
305 " decode properly.");
307 *fourcc
= mem_get_le32(raw_hdr
+ 8);
317 int main(int argc
, const char **argv_
)
319 vpx_codec_ctx_t decoder
;
320 char *prefix
= NULL
, *fn
= NULL
;
323 uint32_t buf_sz
= 0, buf_alloc_sz
= 0;
325 int frame_in
= 0, frame_out
= 0, flipuv
= 0, noblit
= 0, do_md5
= 0, progress
= 0;
326 int stop_after
= 0, postproc
= 0, summary
= 0, quiet
= 0;
327 vpx_codec_iface_t
*iface
= NULL
;
328 unsigned int is_ivf
, fourcc
;
329 unsigned long dx_time
= 0;
331 char **argv
, **argi
, **argj
;
334 vpx_codec_dec_cfg_t cfg
= {0};
335 #if CONFIG_VP8_DECODER
336 vp8_postproc_cfg_t vp8_pp_cfg
= {0};
339 /* Parse command line */
340 exec_name
= argv_
[0];
341 argv
= argv_dup(argc
- 1, argv_
+ 1);
343 for (argi
= argj
= argv
; (*argj
= *argi
); argi
+= arg
.argv_step
)
345 memset(&arg
, 0, sizeof(arg
));
348 if (arg_match(&arg
, &codecarg
, argi
))
352 for (j
= 0; j
< sizeof(ifaces
) / sizeof(ifaces
[0]); j
++)
353 if (!strcmp(ifaces
[j
].name
, arg
.val
))
357 iface
= ifaces
[k
].iface
;
359 die("Error: Unrecognized argument (%s) to --codec\n",
362 else if (arg_match(&arg
, &outputfile
, argi
))
364 else if (arg_match(&arg
, &prefixarg
, argi
))
365 prefix
= strdup(arg
.val
);
366 else if (arg_match(&arg
, &use_yv12
, argi
))
368 else if (arg_match(&arg
, &use_i420
, argi
))
370 else if (arg_match(&arg
, &flipuvarg
, argi
))
372 else if (arg_match(&arg
, &noblitarg
, argi
))
374 else if (arg_match(&arg
, &progressarg
, argi
))
376 else if (arg_match(&arg
, &limitarg
, argi
))
377 stop_after
= arg_parse_uint(&arg
);
378 else if (arg_match(&arg
, &postprocarg
, argi
))
380 else if (arg_match(&arg
, &md5arg
, argi
))
382 else if (arg_match(&arg
, &summaryarg
, argi
))
384 else if (arg_match(&arg
, &threadsarg
, argi
))
385 cfg
.threads
= arg_parse_uint(&arg
);
386 else if (arg_match(&arg
, &quietarg
, argi
))
389 #if CONFIG_VP8_DECODER
390 else if (arg_match(&arg
, &addnoise_level
, argi
))
393 vp8_pp_cfg
.post_proc_flag
|= VP8_ADDNOISE
;
394 vp8_pp_cfg
.noise_level
= arg_parse_uint(&arg
);
396 else if (arg_match(&arg
, &demacroblock_level
, argi
))
399 vp8_pp_cfg
.post_proc_flag
|= VP8_DEMACROBLOCK
;
400 vp8_pp_cfg
.deblocking_level
= arg_parse_uint(&arg
);
402 else if (arg_match(&arg
, &deblock
, argi
))
405 vp8_pp_cfg
.post_proc_flag
|= VP8_DEBLOCK
;
407 else if (arg_match(&arg
, &pp_debug_info
, argi
))
409 unsigned int level
= arg_parse_uint(&arg
);
412 vp8_pp_cfg
.post_proc_flag
&= ~0x7;
415 vp8_pp_cfg
.post_proc_flag
|= 8 << (level
- 1);
423 /* Check for unrecognized options */
424 for (argi
= argv
; *argi
; argi
++)
425 if (argi
[0][0] == '-' && strlen(argi
[0]) > 1)
426 die("Error: Unrecognized option %s\n", *argi
);
428 /* Handle non-option arguments */
435 prefix
= strdup("img");
438 infile
= strcmp(fn
, "-") ? fopen(fn
, "rb") : stdin
;
442 fprintf(stderr
, "Failed to open file");
447 out
= out_open(fn2
, do_md5
);
449 is_ivf
= file_is_ivf(infile
, &fourcc
);
453 /* Try to determine the codec from the fourcc. */
454 for (i
= 0; i
< sizeof(ifaces
) / sizeof(ifaces
[0]); i
++)
455 if ((fourcc
& ifaces
[i
].fourcc_mask
) == ifaces
[i
].fourcc
)
457 vpx_codec_iface_t
*ivf_iface
= ifaces
[i
].iface
;
459 if (iface
&& iface
!= ivf_iface
)
460 fprintf(stderr
, "Notice -- IVF header indicates codec: %s\n",
469 if (vpx_codec_dec_init(&decoder
, iface
? iface
: ifaces
[0].iface
, &cfg
,
470 postproc
? VPX_CODEC_USE_POSTPROC
: 0))
472 fprintf(stderr
, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder
));
477 fprintf(stderr
, "%s\n", decoder
.name
);
479 #if CONFIG_VP8_DECODER
481 if (vp8_pp_cfg
.post_proc_flag
482 && vpx_codec_control(&decoder
, VP8_SET_POSTPROC
, &vp8_pp_cfg
))
484 fprintf(stderr
, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder
));
491 while (!read_frame(infile
, &buf
, &buf_sz
, &buf_alloc_sz
, is_ivf
))
493 vpx_codec_iter_t iter
= NULL
;
495 struct vpx_usec_timer timer
;
497 vpx_usec_timer_start(&timer
);
499 if (vpx_codec_decode(&decoder
, buf
, buf_sz
, NULL
, 0))
501 const char *detail
= vpx_codec_error_detail(&decoder
);
502 fprintf(stderr
, "Failed to decode frame: %s\n", vpx_codec_error(&decoder
));
505 fprintf(stderr
, " Additional information: %s\n", detail
);
510 vpx_usec_timer_mark(&timer
);
511 dx_time
+= vpx_usec_timer_elapsed(&timer
);
516 fprintf(stderr
, "decoded frame %d.\n", frame_in
);
518 if ((img
= vpx_codec_get_frame(&decoder
, &iter
)))
528 const char *sfx
= flipuv
? "yv12" : "i420";
532 sprintf(out_fn
, "%s-%dx%d-%04d.%s",
533 prefix
, img
->d_w
, img
->d_h
, frame_in
, sfx
);
534 out
= out_open(out_fn
, do_md5
);
537 buf
= img
->planes
[PLANE_Y
];
539 for (y
= 0; y
< img
->d_h
; y
++)
541 out_put(out
, buf
, img
->d_w
, do_md5
);
542 buf
+= img
->stride
[PLANE_Y
];
545 buf
= img
->planes
[flipuv
?PLANE_V
:PLANE_U
];
547 for (y
= 0; y
< (1 + img
->d_h
) / 2; y
++)
549 out_put(out
, buf
, (1 + img
->d_w
) / 2, do_md5
);
550 buf
+= img
->stride
[PLANE_U
];
553 buf
= img
->planes
[flipuv
?PLANE_U
:PLANE_V
];
555 for (y
= 0; y
< (1 + img
->d_h
) / 2; y
++)
557 out_put(out
, buf
, (1 + img
->d_w
) / 2, do_md5
);
558 buf
+= img
->stride
[PLANE_V
];
562 out_close(out
, out_fn
, do_md5
);
566 if (stop_after
&& frame_in
>= stop_after
)
572 fprintf(stderr
, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\n",
573 frame_in
, frame_out
, dx_time
, (float)frame_out
* 1000000.0 / (float)dx_time
);
578 if (vpx_codec_destroy(&decoder
))
580 fprintf(stderr
, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder
));
585 out_close(out
, fn2
, do_md5
);