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