Mercurial > libavformat.hg
comparison mov.c @ 121:b9bd706c1ac3 libavformat
* simplified parameters for parse routines
author | kabi |
---|---|
date | Wed, 23 Apr 2003 08:58:42 +0000 |
parents | 79d651162d35 |
children | a1ad0f8b75bf |
comparison
equal
deleted
inserted
replaced
120:c720ddf380df | 121:b9bd706c1ac3 |
---|---|
77 (tag >> 24) & 0xff, | 77 (tag >> 24) & 0xff, |
78 (unsigned int)offset, | 78 (unsigned int)offset, |
79 (unsigned int)size); | 79 (unsigned int)size); |
80 assert((unsigned int)size < 0x7fffffff);// catching errors | 80 assert((unsigned int)size < 0x7fffffff);// catching errors |
81 } | 81 } |
82 #else | |
83 #define print_atom(a,b,c,d) | |
82 #endif | 84 #endif |
83 | 85 |
84 /* some streams in QT (and in MP4 mostly) aren't either video nor audio */ | 86 /* some streams in QT (and in MP4 mostly) aren't either video nor audio */ |
85 /* so we first list them as this, then clean up the list of streams we give back, */ | 87 /* so we first list them as this, then clean up the list of streams we give back, */ |
86 /* getting rid of these */ | 88 /* getting rid of these */ |
87 #define CODEC_TYPE_MOV_OTHER 2 | 89 #define CODEC_TYPE_MOV_OTHER (enum CodecType) 2 |
88 | 90 |
89 static const CodecTag mov_video_tags[] = { | 91 static const CodecTag mov_video_tags[] = { |
90 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */ | 92 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */ |
91 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */ | 93 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */ |
92 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */ | 94 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */ |
195 /* 0x06 SLConfigDescrTag */ | 197 /* 0x06 SLConfigDescrTag */ |
196 uint8_t sl_config_len; | 198 uint8_t sl_config_len; |
197 uint8_t *sl_config; | 199 uint8_t *sl_config; |
198 } MOV_esds_t; | 200 } MOV_esds_t; |
199 | 201 |
202 struct MOVParseTableEntry; | |
203 | |
200 typedef struct MOVStreamContext { | 204 typedef struct MOVStreamContext { |
201 int ffindex; /* the ffmpeg stream id */ | 205 int ffindex; /* the ffmpeg stream id */ |
202 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */ | 206 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */ |
203 long next_chunk; | 207 long next_chunk; |
204 long chunk_count; | 208 long chunk_count; |
233 */ | 237 */ |
234 MOVStreamContext *streams[MAX_STREAMS]; | 238 MOVStreamContext *streams[MAX_STREAMS]; |
235 | 239 |
236 int64_t next_chunk_offset; | 240 int64_t next_chunk_offset; |
237 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */ | 241 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */ |
242 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */ | |
243 /* NOTE: for recursion save to/ restore from local variable! */ | |
238 } MOVContext; | 244 } MOVContext; |
239 | 245 |
240 | |
241 struct MOVParseTableEntry; | |
242 | 246 |
243 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */ | 247 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */ |
244 | 248 |
245 /* those functions parse an atom */ | 249 /* those functions parse an atom */ |
246 /* return code: | 250 /* return code: |
247 1: found what I wanted, exit | 251 1: found what I wanted, exit |
248 0: continue to parse next atom | 252 0: continue to parse next atom |
249 -1: error occured, exit | 253 -1: error occured, exit |
250 */ | 254 */ |
251 typedef int (*mov_parse_function)(const struct MOVParseTableEntry *parse_table, | 255 typedef int (*mov_parse_function)(MOVContext *ctx, |
252 ByteIOContext *pb, | 256 ByteIOContext *pb, |
253 uint32_t atom_type, | 257 uint32_t atom_type, |
254 int64_t atom_offset, /* after the size and type field (and eventually the extended size) */ | 258 int64_t atom_offset, /* after the size and type field (and eventually the extended size) */ |
255 int64_t atom_size, /* total size (excluding the size and type fields) */ | 259 int64_t atom_size); /* total size (excluding the size and type fields) */ |
256 void *param); | |
257 | 260 |
258 /* links atom IDs to parse functions */ | 261 /* links atom IDs to parse functions */ |
259 typedef struct MOVParseTableEntry { | 262 typedef struct MOVParseTableEntry { |
260 uint32_t type; | 263 uint32_t type; |
261 mov_parse_function func; | 264 mov_parse_function func; |
262 } MOVParseTableEntry; | 265 } MOVParseTableEntry; |
263 static const MOVParseTableEntry mov_default_parse_table[]; | 266 |
264 | 267 static int parse_leaf(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
265 static int parse_leaf(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 268 { |
266 { | |
267 #ifdef DEBUG | |
268 print_atom("leaf", atom_type, atom_offset, atom_size); | 269 print_atom("leaf", atom_type, atom_offset, atom_size); |
269 #endif | 270 |
270 if(atom_size>1) | 271 if(atom_size>1) |
271 url_fskip(pb, atom_size); | 272 url_fskip(pb, atom_size); |
272 /* url_seek(pb, atom_offset+atom_size, SEEK_SET); */ | 273 /* url_seek(pb, atom_offset+atom_size, SEEK_SET); */ |
273 return 0; | 274 return 0; |
274 } | 275 } |
275 | 276 |
276 | 277 static int parse_default(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
277 static int parse_default(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | |
278 { | 278 { |
279 uint32_t type, foo=0; | 279 uint32_t type, foo=0; |
280 uint64_t offset, size; | 280 uint64_t offset, size; |
281 uint64_t total_size = 0; | 281 int64_t total_size = 0; |
282 int i; | 282 int i; |
283 int err = 0; | 283 int err = 0; |
284 foo=0; | 284 foo=0; |
285 #ifdef DEBUG | 285 #ifdef DEBUG |
286 print_atom("default", atom_type, atom_offset, atom_size); | 286 print_atom("default", atom_type, atom_offset, atom_size); |
309 if(size == 0) { | 309 if(size == 0) { |
310 size = atom_size - total_size; | 310 size = atom_size - total_size; |
311 if (size <= 8) | 311 if (size <= 8) |
312 break; | 312 break; |
313 } | 313 } |
314 for (i=0; parse_table[i].type != 0L && parse_table[i].type != type; i++) | 314 for (i=0; c->parse_table[i].type != 0L && c->parse_table[i].type != type; i++) |
315 /* empty */; | 315 /* empty */; |
316 | 316 |
317 size -= 8; | 317 size -= 8; |
318 // printf(" i=%ld\n", i); | 318 // printf(" i=%ld\n", i); |
319 if (parse_table[i].type == 0) { /* skip leaf atoms data */ | 319 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */ |
320 // url_seek(pb, atom_offset+atom_size, SEEK_SET); | 320 // url_seek(pb, atom_offset+atom_size, SEEK_SET); |
321 #ifdef DEBUG | 321 #ifdef DEBUG |
322 print_atom("unknown", type, offset, size); | 322 print_atom("unknown", type, offset, size); |
323 #endif | 323 #endif |
324 url_fskip(pb, size); | 324 url_fskip(pb, size); |
325 } else | 325 } else { |
326 err = (parse_table[i].func)(parse_table, pb, type, offset, size, param); | 326 #ifdef DEBUG |
327 //char b[5] = { type & 0xff, (type >> 8) & 0xff, (type >> 16) & 0xff, (type >> 24) & 0xff, 0 }; | |
328 //print_atom(b, type, offset, size); | |
329 #endif | |
330 err = (c->parse_table[i].func)(c, pb, type, offset, size); | |
331 } | |
327 | 332 |
328 offset+=size; | 333 offset+=size; |
329 total_size+=size; | 334 total_size+=size; |
330 } | 335 } |
331 | 336 |
338 debug_indent--; | 343 debug_indent--; |
339 #endif | 344 #endif |
340 return err; | 345 return err; |
341 } | 346 } |
342 | 347 |
343 static int parse_ctab(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 348 static int parse_ctab(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
344 { | 349 { |
345 url_fskip(pb, atom_size); // for now | 350 url_fskip(pb, atom_size); // for now |
346 return 0; | 351 return 0; |
347 } | 352 } |
348 | 353 |
349 static int parse_mvhd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 354 static int parse_mvhd(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
350 { | 355 { |
351 MOVContext *c; | |
352 #ifdef DEBUG | |
353 print_atom("mvhd", atom_type, atom_offset, atom_size); | 356 print_atom("mvhd", atom_type, atom_offset, atom_size); |
354 #endif | |
355 c = (MOVContext *)param; | |
356 | 357 |
357 get_byte(pb); /* version */ | 358 get_byte(pb); /* version */ |
358 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 359 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
359 | 360 |
360 get_be32(pb); /* creation time */ | 361 get_be32(pb); /* creation time */ |
382 | 383 |
383 return 0; | 384 return 0; |
384 } | 385 } |
385 | 386 |
386 /* this atom should contain all header atoms */ | 387 /* this atom should contain all header atoms */ |
387 static int parse_moov(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 388 static int parse_moov(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
388 { | 389 { |
389 int err; | 390 int err; |
390 MOVContext *c; | 391 |
391 #ifdef DEBUG | |
392 print_atom("moov", atom_type, atom_offset, atom_size); | 392 print_atom("moov", atom_type, atom_offset, atom_size); |
393 #endif | 393 |
394 c = (MOVContext *)param; | 394 err = parse_default(c, pb, atom_type, atom_offset, atom_size); |
395 | |
396 err = parse_default(parse_table, pb, atom_type, atom_offset, atom_size, param); | |
397 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */ | 395 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */ |
398 /* so we don't parse the whole file if over a network */ | 396 /* so we don't parse the whole file if over a network */ |
399 c->found_moov=1; | 397 c->found_moov=1; |
400 if(c->found_mdat) | 398 if(c->found_mdat) |
401 return 1; /* found both, just go */ | 399 return 1; /* found both, just go */ |
402 return 0; /* now go for mdat */ | 400 return 0; /* now go for mdat */ |
403 } | 401 } |
404 | 402 |
405 /* this atom contains actual media data */ | 403 /* this atom contains actual media data */ |
406 static int parse_mdat(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 404 static int parse_mdat(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
407 { | 405 { |
408 MOVContext *c; | |
409 #ifdef DEBUG | |
410 print_atom("mdat", atom_type, atom_offset, atom_size); | 406 print_atom("mdat", atom_type, atom_offset, atom_size); |
411 #endif | |
412 c = (MOVContext *)param; | |
413 | 407 |
414 if(atom_size == 0) /* wrong one (MP4) */ | 408 if(atom_size == 0) /* wrong one (MP4) */ |
415 return 0; | 409 return 0; |
416 c->found_mdat=1; | 410 c->found_mdat=1; |
417 c->mdat_offset = atom_offset; | 411 c->mdat_offset = atom_offset; |
423 } | 417 } |
424 | 418 |
425 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */ | 419 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */ |
426 /* like the files created with Adobe Premiere 5.0, for samples see */ | 420 /* like the files created with Adobe Premiere 5.0, for samples see */ |
427 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */ | 421 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */ |
428 static int parse_wide(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 422 static int parse_wide(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
429 { | 423 { |
430 int err; | 424 int err; |
431 uint32_t type; | 425 uint32_t type; |
426 | |
432 #ifdef DEBUG | 427 #ifdef DEBUG |
433 print_atom("wide", atom_type, atom_offset, atom_size); | 428 print_atom("wide", atom_type, atom_offset, atom_size); |
434 debug_indent++; | 429 debug_indent++; |
435 #endif | 430 #endif |
436 if (atom_size < 8) | 431 if (atom_size < 8) |
442 type = get_le32(pb); | 437 type = get_le32(pb); |
443 if (type != MKTAG('m', 'd', 'a', 't')) { | 438 if (type != MKTAG('m', 'd', 'a', 't')) { |
444 url_fskip(pb, atom_size - 8); | 439 url_fskip(pb, atom_size - 8); |
445 return 0; | 440 return 0; |
446 } | 441 } |
447 err = parse_mdat(parse_table, pb, type, atom_offset + 8, atom_size - 8, param); | 442 err = parse_mdat(c, pb, type, atom_offset + 8, atom_size - 8); |
448 #ifdef DEBUG | 443 #ifdef DEBUG |
449 debug_indent--; | 444 debug_indent--; |
450 #endif | 445 #endif |
451 return err; | 446 return err; |
452 } | 447 } |
453 | 448 |
454 static int parse_trak(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 449 static int parse_trak(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
455 { | 450 { |
456 MOVContext *c; | |
457 AVStream *st; | 451 AVStream *st; |
458 MOVStreamContext *sc; | 452 MOVStreamContext *sc; |
459 #ifdef DEBUG | 453 |
460 print_atom("trak", atom_type, atom_offset, atom_size); | 454 print_atom("trak", atom_type, atom_offset, atom_size); |
461 #endif | 455 |
462 | |
463 c = (MOVContext *)param; | |
464 st = av_new_stream(c->fc, c->fc->nb_streams); | 456 st = av_new_stream(c->fc, c->fc->nb_streams); |
465 if (!st) return -2; | 457 if (!st) return -2; |
466 sc = av_malloc(sizeof(MOVStreamContext)); | 458 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext)); |
467 memset(sc, 0, sizeof(MOVStreamContext)); | 459 if (!sc) { |
460 av_free(st); | |
461 return -1; | |
462 } | |
463 | |
468 sc->sample_to_chunk_index = -1; | 464 sc->sample_to_chunk_index = -1; |
469 st->priv_data = sc; | 465 st->priv_data = sc; |
470 st->codec.codec_type = CODEC_TYPE_MOV_OTHER; | 466 st->codec.codec_type = CODEC_TYPE_MOV_OTHER; |
471 st->time_length = (c->duration * 1000) / c->time_scale; // time in miliseconds | 467 st->time_length = (c->duration * 1000) / c->time_scale; // time in miliseconds |
472 c->streams[c->fc->nb_streams-1] = sc; | 468 c->streams[c->fc->nb_streams-1] = sc; |
473 return parse_default(parse_table, pb, atom_type, atom_offset, atom_size, param); | 469 return parse_default(c, pb, atom_type, atom_offset, atom_size); |
474 } | 470 } |
475 | 471 |
476 static int parse_tkhd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 472 static int parse_tkhd(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
477 { | 473 { |
478 MOVContext *c; | |
479 AVStream *st; | 474 AVStream *st; |
480 #ifdef DEBUG | 475 |
481 print_atom("tkhd", atom_type, atom_offset, atom_size); | 476 print_atom("tkhd", atom_type, atom_offset, atom_size); |
482 #endif | 477 |
483 | |
484 c = (MOVContext *)param; | |
485 st = c->fc->streams[c->fc->nb_streams-1]; | 478 st = c->fc->streams[c->fc->nb_streams-1]; |
486 | 479 |
487 get_byte(pb); /* version */ | 480 get_byte(pb); /* version */ |
488 | 481 |
489 get_byte(pb); get_byte(pb); | 482 get_byte(pb); get_byte(pb); |
515 st->codec.height = get_be32(pb) >> 16; /* track height */ | 508 st->codec.height = get_be32(pb) >> 16; /* track height */ |
516 | 509 |
517 return 0; | 510 return 0; |
518 } | 511 } |
519 | 512 |
520 static int parse_mdhd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 513 static int parse_mdhd(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
521 { | 514 { |
522 MOVContext *c; | |
523 AVStream *st; | 515 AVStream *st; |
524 #ifdef DEBUG | 516 |
525 print_atom("mdhd", atom_type, atom_offset, atom_size); | 517 print_atom("mdhd", atom_type, atom_offset, atom_size); |
526 #endif | 518 |
527 | |
528 c = (MOVContext *)param; | |
529 st = c->fc->streams[c->fc->nb_streams-1]; | 519 st = c->fc->streams[c->fc->nb_streams-1]; |
530 | 520 |
531 get_byte(pb); /* version */ | 521 get_byte(pb); /* version */ |
532 | 522 |
533 get_byte(pb); get_byte(pb); | 523 get_byte(pb); get_byte(pb); |
547 get_be16(pb); /* quality */ | 537 get_be16(pb); /* quality */ |
548 | 538 |
549 return 0; | 539 return 0; |
550 } | 540 } |
551 | 541 |
552 static int parse_hdlr(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 542 static int parse_hdlr(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
553 { | 543 { |
554 MOVContext *c; | |
555 int len = 0; | 544 int len = 0; |
556 char *buf; | 545 uint8_t *buf; |
557 uint32_t type; | 546 uint32_t type; |
558 AVStream *st; | 547 AVStream *st; |
559 uint32_t ctype; | 548 uint32_t ctype; |
560 #ifdef DEBUG | 549 |
561 print_atom("hdlr", atom_type, atom_offset, atom_size); | 550 print_atom("hdlr", atom_type, atom_offset, atom_size); |
562 #endif | 551 |
563 c = (MOVContext *)param; | |
564 st = c->fc->streams[c->fc->nb_streams-1]; | 552 st = c->fc->streams[c->fc->nb_streams-1]; |
565 | 553 |
566 get_byte(pb); /* version */ | 554 get_byte(pb); /* version */ |
567 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 555 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
568 | 556 |
621 /* .mp4: C string */ | 609 /* .mp4: C string */ |
622 while(get_byte(pb) && (++len < (atom_size - 24))); | 610 while(get_byte(pb) && (++len < (atom_size - 24))); |
623 } else { | 611 } else { |
624 /* .mov: PASCAL string */ | 612 /* .mov: PASCAL string */ |
625 len = get_byte(pb); | 613 len = get_byte(pb); |
626 buf = av_malloc(len+1); | 614 buf = (uint8_t*) av_malloc(len+1); |
627 get_buffer(pb, buf, len); | 615 if (buf) { |
628 buf[len] = '\0'; | 616 get_buffer(pb, buf, len); |
629 #ifdef DEBUG | 617 #ifdef DEBUG |
630 printf("**buf='%s'\n", buf); | 618 buf[len] = '\0'; |
631 #endif | 619 printf("**buf='%s'\n", buf); |
632 av_free(buf); | 620 #endif |
621 av_free(buf); | |
622 } else | |
623 url_fskip(pb, len); | |
633 } | 624 } |
634 #if 0 | 625 #if 0 |
635 len = get_byte(pb); | 626 len = get_byte(pb); |
636 /* XXX: use a better heuristic */ | 627 /* XXX: use a better heuristic */ |
637 if(len < 32) { | 628 if(len < 32) { |
638 /* assume that it is a Pascal like string */ | 629 /* assume that it is a Pascal like string */ |
639 buf = av_malloc(len+1); | 630 buf = av_malloc(len+1); |
640 get_buffer(pb, buf, len); | 631 if (buf) { |
641 buf[len] = '\0'; | 632 get_buffer(pb, buf, len); |
642 #ifdef DEBUG | 633 buf[len] = '\0'; |
643 printf("**buf='%s'\n", buf); | 634 #ifdef DEBUG |
644 #endif | 635 printf("**buf='%s'\n", buf); |
645 av_free(buf); | 636 #endif |
637 av_free(buf); | |
638 } else | |
639 url_fskip(pb, len)l | |
646 } else { | 640 } else { |
647 /* MP4 string */ | 641 /* MP4 string */ |
648 for(;;) { | 642 for(;;) { |
649 if (len == 0) | 643 if (len == 0) |
650 break; | 644 break; |
689 val |= get_byte(s) << 8; | 683 val |= get_byte(s) << 8; |
690 val |= get_byte(s); | 684 val |= get_byte(s); |
691 return val; | 685 return val; |
692 } | 686 } |
693 | 687 |
694 static int parse_esds(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 688 static int parse_esds(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
695 { | 689 { |
696 | 690 |
697 int64_t start_pos = url_ftell(pb); | 691 int64_t start_pos = url_ftell(pb); |
698 MOVContext *c = (MOVContext *)param; | |
699 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | 692 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; |
700 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data; | 693 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data; |
701 int tag, len; | 694 int tag, len; |
702 #ifdef DEBUG | 695 |
703 print_atom("esds", atom_type, atom_offset, atom_size); | 696 print_atom("esds", atom_type, atom_offset, atom_size); |
704 #endif | |
705 | 697 |
706 /* Well, broken but suffisant for some MP4 streams */ | 698 /* Well, broken but suffisant for some MP4 streams */ |
707 get_be32(pb); /* version + flags */ | 699 get_be32(pb); /* version + flags */ |
708 len = mp4_read_descr(pb, &tag); | 700 len = mp4_read_descr(pb, &tag); |
709 if (tag == MP4ESDescrTag) { | 701 if (tag == MP4ESDescrTag) { |
723 printf("LEN %d TAG %d m:%d a:%d\n", len, tag, sc->esds.max_bitrate, sc->esds.avg_bitrate); | 715 printf("LEN %d TAG %d m:%d a:%d\n", len, tag, sc->esds.max_bitrate, sc->esds.avg_bitrate); |
724 if (tag == MP4DecSpecificDescrTag) { | 716 if (tag == MP4DecSpecificDescrTag) { |
725 #ifdef DEBUG | 717 #ifdef DEBUG |
726 printf("Specific MPEG4 header len=%d\n", len); | 718 printf("Specific MPEG4 header len=%d\n", len); |
727 #endif | 719 #endif |
728 sc->header_data = av_mallocz(len); | 720 sc->header_data = (uint8_t*) av_mallocz(len); |
729 if (sc->header_data) { | 721 if (sc->header_data) { |
730 get_buffer(pb, sc->header_data, len); | 722 get_buffer(pb, sc->header_data, len); |
731 sc->header_len = len; | 723 sc->header_len = len; |
732 } | 724 } |
733 } | 725 } |
735 /* in any case, skip garbage */ | 727 /* in any case, skip garbage */ |
736 url_fskip(pb, (atom_size - 8) - ((url_ftell(pb) - start_pos))); | 728 url_fskip(pb, (atom_size - 8) - ((url_ftell(pb) - start_pos))); |
737 return 0; | 729 return 0; |
738 } | 730 } |
739 | 731 |
740 static int parse_stsd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 732 static int parse_stsd(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
741 { | 733 { |
742 MOVContext *c; | 734 int entries, size, frames_per_sample; |
743 int entries, size, frames_per_sample, id; | |
744 uint32_t format; | 735 uint32_t format; |
745 AVStream *st; | 736 AVStream *st; |
746 MOVStreamContext *sc; | 737 MOVStreamContext *sc; |
747 #ifdef DEBUG | 738 |
748 print_atom("stsd", atom_type, atom_offset, atom_size); | 739 print_atom("stsd", atom_type, atom_offset, atom_size); |
749 #endif | 740 |
750 c = (MOVContext *)param; | |
751 st = c->fc->streams[c->fc->nb_streams-1]; | 741 st = c->fc->streams[c->fc->nb_streams-1]; |
752 sc = (MOVStreamContext *)st->priv_data; | 742 sc = (MOVStreamContext *)st->priv_data; |
753 | 743 |
754 get_byte(pb); /* version */ | 744 get_byte(pb); /* version */ |
755 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 745 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
756 | 746 |
757 entries = get_be32(pb); | 747 entries = get_be32(pb); |
758 | 748 |
759 while(entries--) { | 749 while(entries--) { |
750 enum CodecID id; | |
760 size = get_be32(pb); /* size */ | 751 size = get_be32(pb); /* size */ |
761 format = get_le32(pb); /* data format */ | 752 format = get_le32(pb); /* data format */ |
762 | 753 |
763 get_be32(pb); /* reserved */ | 754 get_be32(pb); /* reserved */ |
764 get_be16(pb); /* reserved */ | 755 get_be16(pb); /* reserved */ |
766 | 757 |
767 /* for MPEG4: set codec type by looking for it */ | 758 /* for MPEG4: set codec type by looking for it */ |
768 id = codec_get_id(mov_video_tags, format); | 759 id = codec_get_id(mov_video_tags, format); |
769 if (id >= 0) { | 760 if (id >= 0) { |
770 AVCodec *codec; | 761 AVCodec *codec; |
771 codec = avcodec_find_decoder(id); | 762 codec = avcodec_find_decoder(id); |
772 if (codec) | 763 if (codec) |
773 st->codec.codec_type = codec->type; | 764 st->codec.codec_type = codec->type; |
774 } | 765 } |
775 #ifdef DEBUG | 766 #ifdef DEBUG |
776 printf("size=%d 4CC= %c%c%c%c codec_type=%d\n", | 767 printf("size=%d 4CC= %c%c%c%c codec_type=%d\n", |
777 size, | 768 size, |
778 (format >> 0) & 0xff, | 769 (format >> 0) & 0xff, |
804 get_be32(pb); /* data size, always 0 */ | 795 get_be32(pb); /* data size, always 0 */ |
805 frames_per_sample = get_be16(pb); /* frames per samples */ | 796 frames_per_sample = get_be16(pb); /* frames per samples */ |
806 #ifdef DEBUG | 797 #ifdef DEBUG |
807 printf("frames/samples = %d\n", frames_per_sample); | 798 printf("frames/samples = %d\n", frames_per_sample); |
808 #endif | 799 #endif |
809 get_buffer(pb, st->codec.codec_name, 32); /* codec name */ | 800 get_buffer(pb, (uint8_t *)st->codec.codec_name, 32); /* codec name */ |
810 | 801 |
811 st->codec.bits_per_sample = get_be16(pb); /* depth */ | 802 st->codec.bits_per_sample = get_be16(pb); /* depth */ |
812 st->codec.color_table_id = get_be16(pb); /* colortable id */ | 803 st->codec.color_table_id = get_be16(pb); /* colortable id */ |
813 | 804 |
814 st->codec.frame_rate = 25; | 805 st->codec.frame_rate = 25; |
884 if (size > 0) { | 875 if (size > 0) { |
885 /* unknown extension */ | 876 /* unknown extension */ |
886 url_fskip(pb, size); | 877 url_fskip(pb, size); |
887 } | 878 } |
888 #else | 879 #else |
889 parse_default(mov_default_parse_table, pb, 0L, 0LL, size, param); | 880 parse_default(c, pb, 0L, 0LL, size); |
890 #endif | 881 #endif |
891 } else { | 882 } else { |
892 get_be16(pb); /* version */ | 883 get_be16(pb); /* version */ |
893 get_be16(pb); /* revision level */ | 884 get_be16(pb); /* revision level */ |
894 get_be32(pb); /* vendor */ | 885 get_be32(pb); /* vendor */ |
900 /* handle specific s8 codec */ | 891 /* handle specific s8 codec */ |
901 get_be16(pb); /* compression id = 0*/ | 892 get_be16(pb); /* compression id = 0*/ |
902 get_be16(pb); /* packet size = 0 */ | 893 get_be16(pb); /* packet size = 0 */ |
903 | 894 |
904 st->codec.sample_rate = ((get_be32(pb) >> 16)); | 895 st->codec.sample_rate = ((get_be32(pb) >> 16)); |
905 | 896 printf("CODECID %d %d %.4s\n", st->codec.codec_id, CODEC_ID_PCM_S16BE, (char*)&format); |
906 if (st->codec.codec_id == CODEC_ID_PCM_S16BE) { | 897 |
898 switch (st->codec.codec_id) { | |
899 case CODEC_ID_PCM_S16BE: | |
907 if (st->codec.bits_per_sample == 8) | 900 if (st->codec.bits_per_sample == 8) |
908 st->codec.codec_id = CODEC_ID_PCM_S8; | 901 st->codec.codec_id = CODEC_ID_PCM_S8; |
909 st->codec.bit_rate = st->codec.sample_rate; | 902 /* fall */ |
903 case CODEC_ID_PCM_U8: | |
904 st->codec.bit_rate = st->codec.sample_rate * 8; | |
905 break; | |
906 default: | |
907 ; | |
910 } | 908 } |
911 get_be32(pb); /* samples per packet */ | 909 get_be32(pb); /* samples per packet */ |
912 get_be32(pb); /* bytes per packet */ | 910 get_be32(pb); /* bytes per packet */ |
913 get_be32(pb); /* bytes per frame */ | 911 get_be32(pb); /* bytes per frame */ |
914 get_be32(pb); /* bytes per sample */ | 912 get_be32(pb); /* bytes per sample */ |
919 int fcc; | 917 int fcc; |
920 st->codec.extradata_size = get_be32(pb) - 8; | 918 st->codec.extradata_size = get_be32(pb) - 8; |
921 fcc = get_le32(pb); // evaw | 919 fcc = get_le32(pb); // evaw |
922 //printf("%x %.4s %d\n", fcc, (char*)&fcc, st->codec.extradata_size); | 920 //printf("%x %.4s %d\n", fcc, (char*)&fcc, st->codec.extradata_size); |
923 st->codec.extradata = av_mallocz(st->codec.extradata_size); | 921 st->codec.extradata = av_mallocz(st->codec.extradata_size); |
924 get_buffer(pb, st->codec.extradata, st->codec.extradata_size); | 922 if (st->codec.extradata) |
923 get_buffer(pb, st->codec.extradata, st->codec.extradata_size); // FIXME url_fskip | |
925 url_fskip(pb, size-(16 + 20 + 16 + 8 + st->codec.extradata_size)); | 924 url_fskip(pb, size-(16 + 20 + 16 + 8 + st->codec.extradata_size)); |
926 } | 925 } |
927 else | 926 else |
928 url_fskip(pb, size-(16 + 20 + 16)); | 927 url_fskip(pb, size-(16 + 20 + 16)); |
929 #else | 928 #else |
930 parse_default(mov_default_parse_table, pb, 0L, 0LL, size - (16 + 20 + 16 + 8), param); | 929 parse_default(c, pb, 0L, 0LL, size - (16 + 20 + 16 + 8)); |
931 #endif | 930 #endif |
932 } | 931 } |
933 } | 932 } |
934 /* | 933 /* |
935 if(len) { | 934 if(len) { |
941 } | 940 } |
942 */ | 941 */ |
943 return 0; | 942 return 0; |
944 } | 943 } |
945 | 944 |
946 static int parse_stco(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 945 static int parse_stco(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
947 { | 946 { |
948 MOVContext *c; | |
949 int entries, i; | 947 int entries, i; |
950 AVStream *st; | 948 AVStream *st; |
951 MOVStreamContext *sc; | 949 MOVStreamContext *sc; |
952 #ifdef DEBUG | 950 |
953 print_atom("stco", atom_type, atom_offset, atom_size); | 951 print_atom("stco", atom_type, atom_offset, atom_size); |
954 #endif | 952 |
955 c = (MOVContext *)param; | |
956 st = c->fc->streams[c->fc->nb_streams-1]; | 953 st = c->fc->streams[c->fc->nb_streams-1]; |
957 sc = (MOVStreamContext *)st->priv_data; | 954 sc = (MOVStreamContext *)st->priv_data; |
958 | 955 |
959 get_byte(pb); /* version */ | 956 get_byte(pb); /* version */ |
960 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 957 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
961 | 958 |
962 entries = get_be32(pb); | 959 entries = get_be32(pb); |
963 sc->chunk_count = entries; | 960 sc->chunk_count = entries; |
964 sc->chunk_offsets = av_malloc(entries * sizeof(int64_t)); | 961 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t)); |
962 if (!sc->chunk_offsets) | |
963 return -1; | |
965 if(atom_type == MKTAG('s', 't', 'c', 'o')) { | 964 if(atom_type == MKTAG('s', 't', 'c', 'o')) { |
966 for(i=0; i<entries; i++) { | 965 for(i=0; i<entries; i++) { |
967 sc->chunk_offsets[i] = get_be32(pb); | 966 sc->chunk_offsets[i] = get_be32(pb); |
968 } | 967 } |
969 } else if(atom_type == MKTAG('c', 'o', '6', '4')) { | 968 } else if(atom_type == MKTAG('c', 'o', '6', '4')) { |
980 */ | 979 */ |
981 #endif | 980 #endif |
982 return 0; | 981 return 0; |
983 } | 982 } |
984 | 983 |
985 static int parse_stsc(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 984 static int parse_stsc(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
986 { | 985 { |
987 MOVContext *c; | |
988 int entries, i; | 986 int entries, i; |
989 AVStream *st; | 987 AVStream *st; |
990 MOVStreamContext *sc; | 988 MOVStreamContext *sc; |
991 #ifdef DEBUG | 989 |
992 print_atom("stsc", atom_type, atom_offset, atom_size); | 990 print_atom("stsc", atom_type, atom_offset, atom_size); |
993 #endif | 991 |
994 c = (MOVContext *)param; | |
995 st = c->fc->streams[c->fc->nb_streams-1]; | 992 st = c->fc->streams[c->fc->nb_streams-1]; |
996 sc = (MOVStreamContext *)st->priv_data; | 993 sc = (MOVStreamContext *)st->priv_data; |
997 | 994 |
998 get_byte(pb); /* version */ | 995 get_byte(pb); /* version */ |
999 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 996 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
1001 entries = get_be32(pb); | 998 entries = get_be32(pb); |
1002 #ifdef DEBUG | 999 #ifdef DEBUG |
1003 printf("track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); | 1000 printf("track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); |
1004 #endif | 1001 #endif |
1005 sc->sample_to_chunk_sz = entries; | 1002 sc->sample_to_chunk_sz = entries; |
1006 sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl)); | 1003 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl)); |
1004 if (!sc->sample_to_chunk) | |
1005 return -1; | |
1007 for(i=0; i<entries; i++) { | 1006 for(i=0; i<entries; i++) { |
1008 sc->sample_to_chunk[i].first = get_be32(pb); | 1007 sc->sample_to_chunk[i].first = get_be32(pb); |
1009 sc->sample_to_chunk[i].count = get_be32(pb); | 1008 sc->sample_to_chunk[i].count = get_be32(pb); |
1010 sc->sample_to_chunk[i].id = get_be32(pb); | 1009 sc->sample_to_chunk[i].id = get_be32(pb); |
1011 #ifdef DEBUG | 1010 #ifdef DEBUG |
1013 #endif | 1012 #endif |
1014 } | 1013 } |
1015 return 0; | 1014 return 0; |
1016 } | 1015 } |
1017 | 1016 |
1018 static int parse_stsz(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 1017 static int parse_stsz(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
1019 { | 1018 { |
1020 MOVContext *c; | |
1021 int entries, i; | 1019 int entries, i; |
1022 AVStream *st; | 1020 AVStream *st; |
1023 MOVStreamContext *sc; | 1021 MOVStreamContext *sc; |
1024 #ifdef DEBUG | 1022 |
1025 print_atom("stsz", atom_type, atom_offset, atom_size); | 1023 print_atom("stsz", atom_type, atom_offset, atom_size); |
1026 #endif | 1024 |
1027 c = (MOVContext *)param; | |
1028 st = c->fc->streams[c->fc->nb_streams-1]; | 1025 st = c->fc->streams[c->fc->nb_streams-1]; |
1029 sc = (MOVStreamContext *)st->priv_data; | 1026 sc = (MOVStreamContext *)st->priv_data; |
1030 | 1027 |
1031 get_byte(pb); /* version */ | 1028 get_byte(pb); /* version */ |
1032 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 1029 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
1037 #ifdef DEBUG | 1034 #ifdef DEBUG |
1038 printf("sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count); | 1035 printf("sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count); |
1039 #endif | 1036 #endif |
1040 if(sc->sample_size) | 1037 if(sc->sample_size) |
1041 return 0; /* there isn't any table following */ | 1038 return 0; /* there isn't any table following */ |
1042 sc->sample_sizes = av_malloc(entries * sizeof(long)); | 1039 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long)); |
1040 if (!sc->sample_sizes) | |
1041 return -1; | |
1043 for(i=0; i<entries; i++) { | 1042 for(i=0; i<entries; i++) { |
1044 sc->sample_sizes[i] = get_be32(pb); | 1043 sc->sample_sizes[i] = get_be32(pb); |
1045 #ifdef DEBUG | 1044 #ifdef DEBUG |
1046 /* printf("sample_sizes[]=%ld\n", sc->sample_sizes[i]); */ | 1045 /* printf("sample_sizes[]=%ld\n", sc->sample_sizes[i]); */ |
1047 #endif | 1046 #endif |
1048 } | 1047 } |
1049 return 0; | 1048 return 0; |
1050 } | 1049 } |
1051 | 1050 |
1052 static int parse_stts(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 1051 static int parse_stts(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
1053 { | 1052 { |
1054 MOVContext *c; | |
1055 int entries, i; | 1053 int entries, i; |
1056 AVStream *st; | 1054 AVStream *st; |
1057 MOVStreamContext *sc; | 1055 MOVStreamContext *sc; |
1058 #ifdef DEBUG | 1056 |
1059 print_atom("stts", atom_type, atom_offset, atom_size); | 1057 print_atom("stts", atom_type, atom_offset, atom_size); |
1060 #endif | 1058 |
1061 c = (MOVContext *)param; | |
1062 st = c->fc->streams[c->fc->nb_streams-1]; | 1059 st = c->fc->streams[c->fc->nb_streams-1]; |
1063 sc = (MOVStreamContext *)st->priv_data; | 1060 sc = (MOVStreamContext *)st->priv_data; |
1064 | 1061 |
1065 get_byte(pb); /* version */ | 1062 get_byte(pb); /* version */ |
1066 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ | 1063 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ |
1089 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size) | 1086 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size) |
1090 { | 1087 { |
1091 return -1; | 1088 return -1; |
1092 } | 1089 } |
1093 | 1090 |
1094 static int parse_cmov(const MOVParseTableEntry *parse_table, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size, void *param) | 1091 static int parse_cmov(MOVContext *c, ByteIOContext *pb, uint32_t atom_type, int64_t atom_offset, int64_t atom_size) |
1095 { | 1092 { |
1096 MOVContext *c; | |
1097 ByteIOContext ctx; | 1093 ByteIOContext ctx; |
1098 char *cmov_data; | 1094 uint8_t *cmov_data; |
1099 unsigned char *moov_data; /* uncompressed data */ | 1095 uint8_t *moov_data; /* uncompressed data */ |
1100 long cmov_len, moov_len; | 1096 long cmov_len, moov_len; |
1101 int ret; | 1097 int ret; |
1102 #ifdef DEBUG | 1098 |
1103 print_atom("cmov", atom_type, atom_offset, atom_size); | 1099 print_atom("cmov", atom_type, atom_offset, atom_size); |
1104 #endif | |
1105 c = (MOVContext *)param; | |
1106 | 1100 |
1107 get_be32(pb); /* dcom atom */ | 1101 get_be32(pb); /* dcom atom */ |
1108 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' )) | 1102 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' )) |
1109 return -1; | 1103 return -1; |
1110 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) { | 1104 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) { |
1115 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' )) | 1109 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' )) |
1116 return -1; | 1110 return -1; |
1117 moov_len = get_be32(pb); /* uncompressed size */ | 1111 moov_len = get_be32(pb); /* uncompressed size */ |
1118 cmov_len = atom_size - 6 * 4; | 1112 cmov_len = atom_size - 6 * 4; |
1119 | 1113 |
1120 cmov_data = av_malloc(cmov_len); | 1114 cmov_data = (uint8_t *) av_malloc(cmov_len); |
1121 if (!cmov_data) | 1115 if (!cmov_data) |
1122 return -1; | 1116 return -1; |
1123 moov_data = av_malloc(moov_len); | 1117 moov_data = (uint8_t *) av_malloc(moov_len); |
1124 if (!moov_data) { | 1118 if (!moov_data) { |
1125 av_free(cmov_data); | 1119 av_free(cmov_data); |
1126 return -1; | 1120 return -1; |
1127 } | 1121 } |
1128 get_buffer(pb, cmov_data, cmov_len); | 1122 get_buffer(pb, cmov_data, cmov_len); |
1129 if(uncompress (moov_data, &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) | 1123 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) |
1130 return -1; | 1124 return -1; |
1131 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0) | 1125 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0) |
1132 return -1; | 1126 return -1; |
1133 ctx.buf_end = ctx.buffer + moov_len; | 1127 ctx.buf_end = ctx.buffer + moov_len; |
1134 ret = parse_default(parse_table, &ctx, MKTAG( 'm', 'o', 'o', 'v' ), 0, moov_len, param); | 1128 ret = parse_default(c, &ctx, MKTAG( 'm', 'o', 'o', 'v' ), 0, moov_len); |
1135 av_free(moov_data); | 1129 av_free(moov_data); |
1136 av_free(cmov_data); | 1130 av_free(cmov_data); |
1137 return ret; | 1131 return ret; |
1138 } | 1132 } |
1139 #endif | 1133 #endif |
1233 static inline uint32_t to_be32(uint8_t *buf) | 1227 static inline uint32_t to_be32(uint8_t *buf) |
1234 { | 1228 { |
1235 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; | 1229 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; |
1236 } | 1230 } |
1237 | 1231 |
1238 /* XXX: is it suffisant ? */ | 1232 /* XXX: is it sufficient ? */ |
1239 static int mov_probe(AVProbeData *p) | 1233 static int mov_probe(AVProbeData *p) |
1240 { | 1234 { |
1241 unsigned int offset; | 1235 unsigned int offset; |
1242 uint32_t tag; | 1236 uint32_t tag; |
1243 | 1237 |
1269 return 0; | 1263 return 0; |
1270 } | 1264 } |
1271 | 1265 |
1272 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) | 1266 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) |
1273 { | 1267 { |
1274 MOVContext *mov = s->priv_data; | 1268 MOVContext *mov = (MOVContext *) s->priv_data; |
1275 ByteIOContext *pb = &s->pb; | 1269 ByteIOContext *pb = &s->pb; |
1276 int i, j, nb, err; | 1270 int i, j, nb, err; |
1277 int64_t size; | 1271 int64_t size; |
1278 | 1272 |
1279 mov->fc = s; | 1273 mov->fc = s; |
1274 mov->parse_table = mov_default_parse_table; | |
1280 #if 0 | 1275 #if 0 |
1281 /* XXX: I think we should auto detect */ | 1276 /* XXX: I think we should auto detect */ |
1282 if(s->iformat->name[1] == 'p') | 1277 if(s->iformat->name[1] == 'p') |
1283 mov->mp4 = 1; | 1278 mov->mp4 = 1; |
1284 #endif | 1279 #endif |
1290 #ifdef DEBUG | 1285 #ifdef DEBUG |
1291 printf("filesz=%Ld\n", size); | 1286 printf("filesz=%Ld\n", size); |
1292 #endif | 1287 #endif |
1293 | 1288 |
1294 /* check MOV header */ | 1289 /* check MOV header */ |
1295 err = parse_default(mov_default_parse_table, pb, 0L, 0LL, size, mov); | 1290 err = parse_default(mov, pb, 0L, 0LL, size); |
1296 if(err<0 || (!mov->found_moov || !mov->found_mdat)) { | 1291 if(err<0 || (!mov->found_moov || !mov->found_mdat)) { |
1297 puts("header not found !!!"); | 1292 puts("header not found !!!"); |
1298 exit(1); | 1293 exit(1); |
1299 } | 1294 } |
1300 #ifdef DEBUG | 1295 #ifdef DEBUG |
1340 | 1335 |
1341 /* Yes, this is ugly... I didn't write the specs of QT :p */ | 1336 /* Yes, this is ugly... I didn't write the specs of QT :p */ |
1342 /* XXX:remove useless commented code sometime */ | 1337 /* XXX:remove useless commented code sometime */ |
1343 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) | 1338 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) |
1344 { | 1339 { |
1345 MOVContext *mov = s->priv_data; | 1340 MOVContext *mov = (MOVContext *) s->priv_data; |
1346 MOVStreamContext *sc; | 1341 MOVStreamContext *sc; |
1347 int64_t offset = 0x0FFFFFFFFFFFFFFF; | 1342 int64_t offset = 0x0FFFFFFFFFFFFFFF; |
1348 int i; | 1343 int i; |
1349 int size; | 1344 int size; |
1350 size = 0x0FFFFFFF; | 1345 size = 0x0FFFFFFF; |
1470 } | 1465 } |
1471 | 1466 |
1472 static int mov_read_close(AVFormatContext *s) | 1467 static int mov_read_close(AVFormatContext *s) |
1473 { | 1468 { |
1474 int i; | 1469 int i; |
1475 MOVContext *mov = s->priv_data; | 1470 MOVContext *mov = (MOVContext *) s->priv_data; |
1476 for(i=0; i<mov->total_streams; i++) | 1471 for(i=0; i<mov->total_streams; i++) |
1477 mov_free_stream_context(mov->streams[i]); | 1472 mov_free_stream_context(mov->streams[i]); |
1478 for(i=0; i<s->nb_streams; i++) | 1473 for(i=0; i<s->nb_streams; i++) |
1479 av_freep(&s->streams[i]); | 1474 av_freep(&s->streams[i]); |
1480 return 0; | 1475 return 0; |