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