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 |
(...skipping 19 matching lines...) Expand all Loading... |
30 #endif | 30 #endif |
31 | 31 |
32 #include "./md5_utils.h" | 32 #include "./md5_utils.h" |
33 | 33 |
34 #include "./tools_common.h" | 34 #include "./tools_common.h" |
35 #include "./webmdec.h" | 35 #include "./webmdec.h" |
36 #include "./y4menc.h" | 36 #include "./y4menc.h" |
37 | 37 |
38 static const char *exec_name; | 38 static const char *exec_name; |
39 | 39 |
40 static const struct { | |
41 char const *name; | |
42 const vpx_codec_iface_t *(*iface)(void); | |
43 uint32_t fourcc; | |
44 } ifaces[] = { | |
45 #if CONFIG_VP8_DECODER | |
46 {"vp8", vpx_codec_vp8_dx, VP8_FOURCC}, | |
47 #endif | |
48 #if CONFIG_VP9_DECODER | |
49 {"vp9", vpx_codec_vp9_dx, VP9_FOURCC}, | |
50 #endif | |
51 }; | |
52 | |
53 struct VpxDecInputContext { | 40 struct VpxDecInputContext { |
54 struct VpxInputContext *vpx_input_ctx; | 41 struct VpxInputContext *vpx_input_ctx; |
55 struct WebmInputContext *webm_ctx; | 42 struct WebmInputContext *webm_ctx; |
56 }; | 43 }; |
57 | 44 |
58 static const arg_def_t looparg = ARG_DEF(NULL, "loops", 1, | 45 static const arg_def_t looparg = ARG_DEF(NULL, "loops", 1, |
59 "Number of times to decode the file"); | 46 "Number of times to decode the file"); |
60 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, | 47 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, |
61 "Codec to use"); | 48 "Codec to use"); |
62 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, | 49 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, |
(...skipping 18 matching lines...) Expand all Loading... |
81 "Output file name pattern (see below
)"); | 68 "Output file name pattern (see below
)"); |
82 static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1, | 69 static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1, |
83 "Max threads to use"); | 70 "Max threads to use"); |
84 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0, | 71 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0, |
85 "Show version string"); | 72 "Show version string"); |
86 static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0, | 73 static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0, |
87 "Enable decoder error-conceal
ment"); | 74 "Enable decoder error-conceal
ment"); |
88 static const arg_def_t scalearg = ARG_DEF("S", "scale", 0, | 75 static const arg_def_t scalearg = ARG_DEF("S", "scale", 0, |
89 "Scale output frames uniformly"); | 76 "Scale output frames uniformly"); |
90 | 77 |
| 78 static const arg_def_t fb_arg = |
| 79 ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use"); |
91 | 80 |
92 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0, | 81 static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0, |
93 "Compute the MD5 sum of the decoded fram
e"); | 82 "Compute the MD5 sum of the decoded fram
e"); |
94 | 83 |
95 static const arg_def_t *all_args[] = { | 84 static const arg_def_t *all_args[] = { |
96 &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg, | 85 &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg, |
97 &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, | 86 &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, |
98 &threadsarg, &verbosearg, &scalearg, | 87 &threadsarg, &verbosearg, &scalearg, &fb_arg, |
99 &md5arg, | 88 &md5arg, |
100 &error_concealment, | 89 &error_concealment, |
101 NULL | 90 NULL |
102 }; | 91 }; |
103 | 92 |
104 #if CONFIG_VP8_DECODER | 93 #if CONFIG_VP8_DECODER |
105 static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1, | 94 static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1, |
106 "Enable VP8 postproc add noise")
; | 95 "Enable VP8 postproc add noise")
; |
107 static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0, | 96 static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0, |
108 "Enable VP8 deblocking"); | 97 "Enable VP8 deblocking"); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 fprintf(stderr, | 152 fprintf(stderr, |
164 "\n\t%%w - Frame width" | 153 "\n\t%%w - Frame width" |
165 "\n\t%%h - Frame height" | 154 "\n\t%%h - Frame height" |
166 "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)" | 155 "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)" |
167 "\n\n Pattern arguments are only supported in conjunction " | 156 "\n\n Pattern arguments are only supported in conjunction " |
168 "with the --yv12 and\n --i420 options. If the -o option is " | 157 "with the --yv12 and\n --i420 options. If the -o option is " |
169 "not specified, the output will be\n directed to stdout.\n" | 158 "not specified, the output will be\n directed to stdout.\n" |
170 ); | 159 ); |
171 fprintf(stderr, "\nIncluded decoders:\n\n"); | 160 fprintf(stderr, "\nIncluded decoders:\n\n"); |
172 | 161 |
173 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) | 162 for (i = 0; i < get_vpx_decoder_count(); ++i) { |
| 163 const VpxInterface *const decoder = get_vpx_decoder_by_index(i); |
174 fprintf(stderr, " %-6s - %s\n", | 164 fprintf(stderr, " %-6s - %s\n", |
175 ifaces[i].name, | 165 decoder->name, vpx_codec_iface_name(decoder->interface())); |
176 vpx_codec_iface_name(ifaces[i].iface())); | 166 } |
177 | 167 |
178 exit(EXIT_FAILURE); | 168 exit(EXIT_FAILURE); |
179 } | 169 } |
180 | 170 |
181 static int raw_read_frame(FILE *infile, uint8_t **buffer, | 171 static int raw_read_frame(FILE *infile, uint8_t **buffer, |
182 size_t *bytes_read, size_t *buffer_size) { | 172 size_t *bytes_read, size_t *buffer_size) { |
183 char raw_hdr[RAW_FRAME_HDR_SZ]; | 173 char raw_hdr[RAW_FRAME_HDR_SZ]; |
184 size_t frame_size = 0; | 174 size_t frame_size = 0; |
185 | 175 |
186 if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) { | 176 if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) { |
187 if (!feof(infile)) | 177 if (!feof(infile)) |
188 warn("Failed to read RAW frame size\n"); | 178 warn("Failed to read RAW frame size\n"); |
189 } else { | 179 } else { |
190 const int kCorruptFrameThreshold = 256 * 1024 * 1024; | 180 const size_t kCorruptFrameThreshold = 256 * 1024 * 1024; |
191 const int kFrameTooSmallThreshold = 256 * 1024; | 181 const size_t kFrameTooSmallThreshold = 256 * 1024; |
192 frame_size = mem_get_le32(raw_hdr); | 182 frame_size = mem_get_le32(raw_hdr); |
193 | 183 |
194 if (frame_size > kCorruptFrameThreshold) { | 184 if (frame_size > kCorruptFrameThreshold) { |
195 warn("Read invalid frame size (%u)\n", (unsigned int)frame_size); | 185 warn("Read invalid frame size (%u)\n", (unsigned int)frame_size); |
196 frame_size = 0; | 186 frame_size = 0; |
197 } | 187 } |
198 | 188 |
199 if (frame_size < kFrameTooSmallThreshold) { | 189 if (frame_size < kFrameTooSmallThreshold) { |
200 warn("Warning: Read invalid frame size (%u) - not a raw file?\n", | 190 warn("Warning: Read invalid frame size (%u) - not a raw file?\n", |
201 (unsigned int)frame_size); | 191 (unsigned int)frame_size); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 return raw_read_frame(input->vpx_input_ctx->file, | 224 return raw_read_frame(input->vpx_input_ctx->file, |
235 buf, bytes_in_buffer, buffer_size); | 225 buf, bytes_in_buffer, buffer_size); |
236 case FILE_TYPE_IVF: | 226 case FILE_TYPE_IVF: |
237 return ivf_read_frame(input->vpx_input_ctx->file, | 227 return ivf_read_frame(input->vpx_input_ctx->file, |
238 buf, bytes_in_buffer, buffer_size); | 228 buf, bytes_in_buffer, buffer_size); |
239 default: | 229 default: |
240 return 1; | 230 return 1; |
241 } | 231 } |
242 } | 232 } |
243 | 233 |
244 static int get_image_plane_width(int plane, const vpx_image_t *img) { | |
245 return (plane > 0 && img->x_chroma_shift > 0) ? | |
246 (img->d_w + 1) >> img->x_chroma_shift : | |
247 img->d_w; | |
248 } | |
249 | |
250 static int get_image_plane_height(int plane, const vpx_image_t *img) { | |
251 return (plane > 0 && img->y_chroma_shift > 0) ? | |
252 (img->d_h + 1) >> img->y_chroma_shift : | |
253 img->d_h; | |
254 } | |
255 | |
256 static void update_image_md5(const vpx_image_t *img, const int planes[3], | 234 static void update_image_md5(const vpx_image_t *img, const int planes[3], |
257 MD5Context *md5) { | 235 MD5Context *md5) { |
258 int i, y; | 236 int i, y; |
259 | 237 |
260 for (i = 0; i < 3; ++i) { | 238 for (i = 0; i < 3; ++i) { |
261 const int plane = planes[i]; | 239 const int plane = planes[i]; |
262 const unsigned char *buf = img->planes[plane]; | 240 const unsigned char *buf = img->planes[plane]; |
263 const int stride = img->stride[plane]; | 241 const int stride = img->stride[plane]; |
264 const int w = get_image_plane_width(plane, img); | 242 const int w = vpx_img_plane_width(img, plane); |
265 const int h = get_image_plane_height(plane, img); | 243 const int h = vpx_img_plane_height(img, plane); |
266 | 244 |
267 for (y = 0; y < h; ++y) { | 245 for (y = 0; y < h; ++y) { |
268 MD5Update(md5, buf, w); | 246 MD5Update(md5, buf, w); |
269 buf += stride; | 247 buf += stride; |
270 } | 248 } |
271 } | 249 } |
272 } | 250 } |
273 | 251 |
274 static void write_image_file(const vpx_image_t *img, const int planes[3], | 252 static void write_image_file(const vpx_image_t *img, const int planes[3], |
275 FILE *file) { | 253 FILE *file) { |
276 int i, y; | 254 int i, y; |
277 | 255 |
278 for (i = 0; i < 3; ++i) { | 256 for (i = 0; i < 3; ++i) { |
279 const int plane = planes[i]; | 257 const int plane = planes[i]; |
280 const unsigned char *buf = img->planes[plane]; | 258 const unsigned char *buf = img->planes[plane]; |
281 const int stride = img->stride[plane]; | 259 const int stride = img->stride[plane]; |
282 const int w = get_image_plane_width(plane, img); | 260 const int w = vpx_img_plane_width(img, plane); |
283 const int h = get_image_plane_height(plane, img); | 261 const int h = vpx_img_plane_height(img, plane); |
284 | 262 |
285 for (y = 0; y < h; ++y) { | 263 for (y = 0; y < h; ++y) { |
286 fwrite(buf, 1, w, file); | 264 fwrite(buf, 1, w, file); |
287 buf += stride; | 265 buf += stride; |
288 } | 266 } |
289 } | 267 } |
290 } | 268 } |
291 | 269 |
292 int file_is_raw(struct VpxInputContext *input) { | 270 int file_is_raw(struct VpxInputContext *input) { |
293 uint8_t buf[32]; | 271 uint8_t buf[32]; |
294 int is_raw = 0; | 272 int is_raw = 0; |
295 vpx_codec_stream_info_t si; | 273 vpx_codec_stream_info_t si; |
296 | 274 |
297 si.sz = sizeof(si); | 275 si.sz = sizeof(si); |
298 | 276 |
299 if (fread(buf, 1, 32, input->file) == 32) { | 277 if (fread(buf, 1, 32, input->file) == 32) { |
300 int i; | 278 int i; |
301 | 279 |
302 if (mem_get_le32(buf) < 256 * 1024 * 1024) { | 280 if (mem_get_le32(buf) < 256 * 1024 * 1024) { |
303 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) { | 281 for (i = 0; i < get_vpx_decoder_count(); ++i) { |
304 if (!vpx_codec_peek_stream_info(ifaces[i].iface(), | 282 const VpxInterface *const decoder = get_vpx_decoder_by_index(i); |
| 283 if (!vpx_codec_peek_stream_info(decoder->interface(), |
305 buf + 4, 32 - 4, &si)) { | 284 buf + 4, 32 - 4, &si)) { |
306 is_raw = 1; | 285 is_raw = 1; |
307 input->fourcc = ifaces[i].fourcc; | 286 input->fourcc = decoder->fourcc; |
308 input->width = si.w; | 287 input->width = si.w; |
309 input->height = si.h; | 288 input->height = si.h; |
310 input->framerate.numerator = 30; | 289 input->framerate.numerator = 30; |
311 input->framerate.denominator = 1; | 290 input->framerate.denominator = 1; |
312 break; | 291 break; |
313 } | 292 } |
314 } | 293 } |
315 } | 294 } |
316 } | 295 } |
317 | 296 |
318 rewind(input->file); | 297 rewind(input->file); |
319 return is_raw; | 298 return is_raw; |
320 } | 299 } |
321 | 300 |
322 void show_progress(int frame_in, int frame_out, unsigned long dx_time) { | 301 void show_progress(int frame_in, int frame_out, unsigned long dx_time) { |
323 fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r", | 302 fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r", |
324 frame_in, frame_out, dx_time, | 303 frame_in, frame_out, dx_time, |
325 (float)frame_out * 1000000.0 / (float)dx_time); | 304 (float)frame_out * 1000000.0 / (float)dx_time); |
326 } | 305 } |
327 | 306 |
| 307 struct ExternalFrameBuffer { |
| 308 uint8_t* data; |
| 309 size_t size; |
| 310 int in_use; |
| 311 }; |
| 312 |
| 313 struct ExternalFrameBufferList { |
| 314 int num_external_frame_buffers; |
| 315 struct ExternalFrameBuffer *ext_fb; |
| 316 }; |
| 317 |
| 318 // Callback used by libvpx to request an external frame buffer. |cb_priv| |
| 319 // Application private data passed into the set function. |min_size| is the |
| 320 // minimum size in bytes needed to decode the next frame. |fb| pointer to the |
| 321 // frame buffer. |
| 322 int get_vp9_frame_buffer(void *cb_priv, size_t min_size, |
| 323 vpx_codec_frame_buffer_t *fb) { |
| 324 int i; |
| 325 struct ExternalFrameBufferList *const ext_fb_list = |
| 326 (struct ExternalFrameBufferList *)cb_priv; |
| 327 if (ext_fb_list == NULL) |
| 328 return -1; |
| 329 |
| 330 // Find a free frame buffer. |
| 331 for (i = 0; i < ext_fb_list->num_external_frame_buffers; ++i) { |
| 332 if (!ext_fb_list->ext_fb[i].in_use) |
| 333 break; |
| 334 } |
| 335 |
| 336 if (i == ext_fb_list->num_external_frame_buffers) |
| 337 return -1; |
| 338 |
| 339 if (ext_fb_list->ext_fb[i].size < min_size) { |
| 340 free(ext_fb_list->ext_fb[i].data); |
| 341 ext_fb_list->ext_fb[i].data = (uint8_t *)malloc(min_size); |
| 342 if (!ext_fb_list->ext_fb[i].data) |
| 343 return -1; |
| 344 |
| 345 ext_fb_list->ext_fb[i].size = min_size; |
| 346 } |
| 347 |
| 348 fb->data = ext_fb_list->ext_fb[i].data; |
| 349 fb->size = ext_fb_list->ext_fb[i].size; |
| 350 ext_fb_list->ext_fb[i].in_use = 1; |
| 351 |
| 352 // Set the frame buffer's private data to point at the external frame buffer. |
| 353 fb->priv = &ext_fb_list->ext_fb[i]; |
| 354 return 0; |
| 355 } |
| 356 |
| 357 // Callback used by libvpx when there are no references to the frame buffer. |
| 358 // |cb_priv| user private data passed into the set function. |fb| pointer |
| 359 // to the frame buffer. |
| 360 int release_vp9_frame_buffer(void *cb_priv, |
| 361 vpx_codec_frame_buffer_t *fb) { |
| 362 struct ExternalFrameBuffer *const ext_fb = |
| 363 (struct ExternalFrameBuffer *)fb->priv; |
| 364 (void)cb_priv; |
| 365 ext_fb->in_use = 0; |
| 366 return 0; |
| 367 } |
| 368 |
328 void generate_filename(const char *pattern, char *out, size_t q_len, | 369 void generate_filename(const char *pattern, char *out, size_t q_len, |
329 unsigned int d_w, unsigned int d_h, | 370 unsigned int d_w, unsigned int d_h, |
330 unsigned int frame_in) { | 371 unsigned int frame_in) { |
331 const char *p = pattern; | 372 const char *p = pattern; |
332 char *q = out; | 373 char *q = out; |
333 | 374 |
334 do { | 375 do { |
335 char *next_pat = strchr(p, '%'); | 376 char *next_pat = strchr(p, '%'); |
336 | 377 |
337 if (p == next_pat) { | 378 if (p == next_pat) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 FILE *file = fopen(name, "wb"); | 475 FILE *file = fopen(name, "wb"); |
435 if (!file) | 476 if (!file) |
436 fatal("Failed to output file %s", name); | 477 fatal("Failed to output file %s", name); |
437 return file; | 478 return file; |
438 } | 479 } |
439 } | 480 } |
440 | 481 |
441 int main_loop(int argc, const char **argv_) { | 482 int main_loop(int argc, const char **argv_) { |
442 vpx_codec_ctx_t decoder; | 483 vpx_codec_ctx_t decoder; |
443 char *fn = NULL; | 484 char *fn = NULL; |
444 int i; | |
445 uint8_t *buf = NULL; | 485 uint8_t *buf = NULL; |
446 size_t bytes_in_buffer = 0, buffer_size = 0; | 486 size_t bytes_in_buffer = 0, buffer_size = 0; |
447 FILE *infile; | 487 FILE *infile; |
448 int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0; | 488 int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0; |
449 int do_md5 = 0, progress = 0; | 489 int do_md5 = 0, progress = 0; |
450 int stop_after = 0, postproc = 0, summary = 0, quiet = 1; | 490 int stop_after = 0, postproc = 0, summary = 0, quiet = 1; |
451 int arg_skip = 0; | 491 int arg_skip = 0; |
452 int ec_enabled = 0; | 492 int ec_enabled = 0; |
453 vpx_codec_iface_t *iface = NULL; | 493 const VpxInterface *interface = NULL; |
| 494 const VpxInterface *fourcc_interface = NULL; |
454 unsigned long dx_time = 0; | 495 unsigned long dx_time = 0; |
455 struct arg arg; | 496 struct arg arg; |
456 char **argv, **argi, **argj; | 497 char **argv, **argi, **argj; |
457 | 498 |
458 int single_file; | 499 int single_file; |
459 int use_y4m = 1; | 500 int use_y4m = 1; |
460 vpx_codec_dec_cfg_t cfg = {0}; | 501 vpx_codec_dec_cfg_t cfg = {0}; |
461 #if CONFIG_VP8_DECODER | 502 #if CONFIG_VP8_DECODER |
462 vp8_postproc_cfg_t vp8_pp_cfg = {0}; | 503 vp8_postproc_cfg_t vp8_pp_cfg = {0}; |
463 int vp8_dbg_color_ref_frame = 0; | 504 int vp8_dbg_color_ref_frame = 0; |
464 int vp8_dbg_color_mb_modes = 0; | 505 int vp8_dbg_color_mb_modes = 0; |
465 int vp8_dbg_color_b_modes = 0; | 506 int vp8_dbg_color_b_modes = 0; |
466 int vp8_dbg_display_mv = 0; | 507 int vp8_dbg_display_mv = 0; |
467 #endif | 508 #endif |
468 int frames_corrupted = 0; | 509 int frames_corrupted = 0; |
469 int dec_flags = 0; | 510 int dec_flags = 0; |
470 int do_scale = 0; | 511 int do_scale = 0; |
471 vpx_image_t *scaled_img = NULL; | 512 vpx_image_t *scaled_img = NULL; |
472 int frame_avail, got_data; | 513 int frame_avail, got_data; |
| 514 int num_external_frame_buffers = 0; |
| 515 struct ExternalFrameBufferList ext_fb_list = {0}; |
473 | 516 |
474 const char *outfile_pattern = NULL; | 517 const char *outfile_pattern = NULL; |
475 char outfile_name[PATH_MAX] = {0}; | 518 char outfile_name[PATH_MAX] = {0}; |
476 FILE *outfile = NULL; | 519 FILE *outfile = NULL; |
477 | 520 |
478 MD5Context md5_ctx; | 521 MD5Context md5_ctx; |
479 unsigned char md5_digest[16]; | 522 unsigned char md5_digest[16]; |
480 | 523 |
481 struct VpxDecInputContext input = {0}; | 524 struct VpxDecInputContext input = {0}; |
482 struct VpxInputContext vpx_input_ctx = {0}; | 525 struct VpxInputContext vpx_input_ctx = {0}; |
483 struct WebmInputContext webm_ctx = {0}; | 526 struct WebmInputContext webm_ctx = {0}; |
484 input.vpx_input_ctx = &vpx_input_ctx; | 527 input.vpx_input_ctx = &vpx_input_ctx; |
485 input.webm_ctx = &webm_ctx; | 528 input.webm_ctx = &webm_ctx; |
486 | 529 |
487 /* Parse command line */ | 530 /* Parse command line */ |
488 exec_name = argv_[0]; | 531 exec_name = argv_[0]; |
489 argv = argv_dup(argc - 1, argv_ + 1); | 532 argv = argv_dup(argc - 1, argv_ + 1); |
490 | 533 |
491 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { | 534 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { |
492 memset(&arg, 0, sizeof(arg)); | 535 memset(&arg, 0, sizeof(arg)); |
493 arg.argv_step = 1; | 536 arg.argv_step = 1; |
494 | 537 |
495 if (arg_match(&arg, &codecarg, argi)) { | 538 if (arg_match(&arg, &codecarg, argi)) { |
496 int j, k = -1; | 539 interface = get_vpx_decoder_by_name(arg.val); |
497 | 540 if (!interface) |
498 for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++) | 541 die("Error: Unrecognized argument (%s) to --codec\n", arg.val); |
499 if (!strcmp(ifaces[j].name, arg.val)) | |
500 k = j; | |
501 | |
502 if (k >= 0) | |
503 iface = ifaces[k].iface(); | |
504 else | |
505 die("Error: Unrecognized argument (%s) to --codec\n", | |
506 arg.val); | |
507 } else if (arg_match(&arg, &looparg, argi)) { | 542 } else if (arg_match(&arg, &looparg, argi)) { |
508 // no-op | 543 // no-op |
509 } else if (arg_match(&arg, &outputfile, argi)) | 544 } else if (arg_match(&arg, &outputfile, argi)) |
510 outfile_pattern = arg.val; | 545 outfile_pattern = arg.val; |
511 else if (arg_match(&arg, &use_yv12, argi)) { | 546 else if (arg_match(&arg, &use_yv12, argi)) { |
512 use_y4m = 0; | 547 use_y4m = 0; |
513 flipuv = 1; | 548 flipuv = 1; |
514 } else if (arg_match(&arg, &use_i420, argi)) { | 549 } else if (arg_match(&arg, &use_i420, argi)) { |
515 use_y4m = 0; | 550 use_y4m = 0; |
516 flipuv = 0; | 551 flipuv = 0; |
(...skipping 12 matching lines...) Expand all Loading... |
529 else if (arg_match(&arg, &md5arg, argi)) | 564 else if (arg_match(&arg, &md5arg, argi)) |
530 do_md5 = 1; | 565 do_md5 = 1; |
531 else if (arg_match(&arg, &summaryarg, argi)) | 566 else if (arg_match(&arg, &summaryarg, argi)) |
532 summary = 1; | 567 summary = 1; |
533 else if (arg_match(&arg, &threadsarg, argi)) | 568 else if (arg_match(&arg, &threadsarg, argi)) |
534 cfg.threads = arg_parse_uint(&arg); | 569 cfg.threads = arg_parse_uint(&arg); |
535 else if (arg_match(&arg, &verbosearg, argi)) | 570 else if (arg_match(&arg, &verbosearg, argi)) |
536 quiet = 0; | 571 quiet = 0; |
537 else if (arg_match(&arg, &scalearg, argi)) | 572 else if (arg_match(&arg, &scalearg, argi)) |
538 do_scale = 1; | 573 do_scale = 1; |
| 574 else if (arg_match(&arg, &fb_arg, argi)) |
| 575 num_external_frame_buffers = arg_parse_uint(&arg); |
539 | 576 |
540 #if CONFIG_VP8_DECODER | 577 #if CONFIG_VP8_DECODER |
541 else if (arg_match(&arg, &addnoise_level, argi)) { | 578 else if (arg_match(&arg, &addnoise_level, argi)) { |
542 postproc = 1; | 579 postproc = 1; |
543 vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE; | 580 vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE; |
544 vp8_pp_cfg.noise_level = arg_parse_uint(&arg); | 581 vp8_pp_cfg.noise_level = arg_parse_uint(&arg); |
545 } else if (arg_match(&arg, &demacroblock_level, argi)) { | 582 } else if (arg_match(&arg, &demacroblock_level, argi)) { |
546 postproc = 1; | 583 postproc = 1; |
547 vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK; | 584 vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK; |
548 vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg); | 585 vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 | 690 |
654 if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) { | 691 if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) { |
655 if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) { | 692 if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) { |
656 fprintf(stderr, "Failed to guess framerate -- error parsing " | 693 fprintf(stderr, "Failed to guess framerate -- error parsing " |
657 "webm file?\n"); | 694 "webm file?\n"); |
658 return EXIT_FAILURE; | 695 return EXIT_FAILURE; |
659 } | 696 } |
660 } | 697 } |
661 } | 698 } |
662 | 699 |
663 /* Try to determine the codec from the fourcc. */ | 700 fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc); |
664 for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) | 701 if (interface && fourcc_interface && interface != fourcc_interface) |
665 if (vpx_input_ctx.fourcc == ifaces[i].fourcc) { | 702 warn("Header indicates codec: %s\n", fourcc_interface->name); |
666 vpx_codec_iface_t *vpx_iface = ifaces[i].iface(); | 703 else |
| 704 interface = fourcc_interface; |
667 | 705 |
668 if (iface && iface != vpx_iface) | 706 if (!interface) |
669 warn("Header indicates codec: %s\n", ifaces[i].name); | 707 interface = get_vpx_decoder_by_index(0); |
670 else | |
671 iface = vpx_iface; | |
672 | |
673 break; | |
674 } | |
675 | 708 |
676 dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) | | 709 dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) | |
677 (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0); | 710 (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0); |
678 if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface(), &cfg, | 711 if (vpx_codec_dec_init(&decoder, interface->interface(), &cfg, dec_flags)) { |
679 dec_flags)) { | 712 fprintf(stderr, "Failed to initialize decoder: %s\n", |
680 fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decod
er)); | 713 vpx_codec_error(&decoder)); |
681 return EXIT_FAILURE; | 714 return EXIT_FAILURE; |
682 } | 715 } |
683 | 716 |
684 if (!quiet) | 717 if (!quiet) |
685 fprintf(stderr, "%s\n", decoder.name); | 718 fprintf(stderr, "%s\n", decoder.name); |
686 | 719 |
687 #if CONFIG_VP8_DECODER | 720 #if CONFIG_VP8_DECODER |
688 | 721 |
689 if (vp8_pp_cfg.post_proc_flag | 722 if (vp8_pp_cfg.post_proc_flag |
690 && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) { | 723 && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) { |
(...skipping 28 matching lines...) Expand all Loading... |
719 | 752 |
720 | 753 |
721 if (arg_skip) | 754 if (arg_skip) |
722 fprintf(stderr, "Skipping first %d frames.\n", arg_skip); | 755 fprintf(stderr, "Skipping first %d frames.\n", arg_skip); |
723 while (arg_skip) { | 756 while (arg_skip) { |
724 if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) | 757 if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) |
725 break; | 758 break; |
726 arg_skip--; | 759 arg_skip--; |
727 } | 760 } |
728 | 761 |
| 762 if (num_external_frame_buffers > 0) { |
| 763 ext_fb_list.num_external_frame_buffers = num_external_frame_buffers; |
| 764 ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc( |
| 765 num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb)); |
| 766 if (vpx_codec_set_frame_buffer_functions( |
| 767 &decoder, get_vp9_frame_buffer, release_vp9_frame_buffer, |
| 768 &ext_fb_list)) { |
| 769 fprintf(stderr, "Failed to configure external frame buffers: %s\n", |
| 770 vpx_codec_error(&decoder)); |
| 771 return EXIT_FAILURE; |
| 772 } |
| 773 } |
| 774 |
729 frame_avail = 1; | 775 frame_avail = 1; |
730 got_data = 0; | 776 got_data = 0; |
731 | 777 |
732 /* Decode file */ | 778 /* Decode file */ |
733 while (frame_avail || got_data) { | 779 while (frame_avail || got_data) { |
734 vpx_codec_iter_t iter = NULL; | 780 vpx_codec_iter_t iter = NULL; |
735 vpx_image_t *img; | 781 vpx_image_t *img; |
736 struct vpx_usec_timer timer; | 782 struct vpx_usec_timer timer; |
737 int corrupted; | 783 int corrupted; |
738 | 784 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 } | 937 } |
892 } | 938 } |
893 | 939 |
894 if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM) | 940 if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM) |
895 webm_free(input.webm_ctx); | 941 webm_free(input.webm_ctx); |
896 else | 942 else |
897 free(buf); | 943 free(buf); |
898 | 944 |
899 if (scaled_img) vpx_img_free(scaled_img); | 945 if (scaled_img) vpx_img_free(scaled_img); |
900 | 946 |
| 947 for (i = 0; i < ext_fb_list.num_external_frame_buffers; ++i) { |
| 948 free(ext_fb_list.ext_fb[i].data); |
| 949 } |
| 950 free(ext_fb_list.ext_fb); |
| 951 |
901 fclose(infile); | 952 fclose(infile); |
902 free(argv); | 953 free(argv); |
903 | 954 |
904 return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS; | 955 return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS; |
905 } | 956 } |
906 | 957 |
907 int main(int argc, const char **argv_) { | 958 int main(int argc, const char **argv_) { |
908 unsigned int loops = 1, i; | 959 unsigned int loops = 1, i; |
909 char **argv, **argi, **argj; | 960 char **argv, **argi, **argj; |
910 struct arg arg; | 961 struct arg arg; |
911 int error = 0; | 962 int error = 0; |
912 | 963 |
913 argv = argv_dup(argc - 1, argv_ + 1); | 964 argv = argv_dup(argc - 1, argv_ + 1); |
914 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { | 965 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { |
915 memset(&arg, 0, sizeof(arg)); | 966 memset(&arg, 0, sizeof(arg)); |
916 arg.argv_step = 1; | 967 arg.argv_step = 1; |
917 | 968 |
918 if (arg_match(&arg, &looparg, argi)) { | 969 if (arg_match(&arg, &looparg, argi)) { |
919 loops = arg_parse_uint(&arg); | 970 loops = arg_parse_uint(&arg); |
920 break; | 971 break; |
921 } | 972 } |
922 } | 973 } |
923 free(argv); | 974 free(argv); |
924 for (i = 0; !error && i < loops; i++) | 975 for (i = 0; !error && i < loops; i++) |
925 error = main_loop(argc, argv_); | 976 error = main_loop(argc, argv_); |
926 return error; | 977 return error; |
927 } | 978 } |
OLD | NEW |