comparison mov.c @ 491:4cf46e9a1bb8 libavformat

Seeking in .mov/.mp4 files printf->av_log patch by (Gael Chardon <gael.ffmpeg at 4now dot net>)
author michael
date Tue, 06 Jul 2004 02:35:39 +0000
parents aeb69a5f3756
children 0ed5d359f63a
comparison
equal deleted inserted replaced
490:c0849ef998e7 491:4cf46e9a1bb8
26 #include <zlib.h> 26 #include <zlib.h>
27 #endif 27 #endif
28 28
29 /* 29 /*
30 * First version by Francois Revol revol@free.fr 30 * First version by Francois Revol revol@free.fr
31 * Seek function by Gael Chardon gael.dev@4now.net
31 * 32 *
32 * Features and limitations: 33 * Features and limitations:
33 * - reads most of the QT files I have (at least the structure), 34 * - reads most of the QT files I have (at least the structure),
34 * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement. 35 * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
35 * FIXED, Francois Revol, 07/17/2002 36 * FIXED, Francois Revol, 07/17/2002
38 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html 39 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
39 * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes 40 * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
40 * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at 41 * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
41 * http://mpeg.telecomitalialab.com/faq.htm 42 * http://mpeg.telecomitalialab.com/faq.htm
42 * - the code is quite ugly... maybe I won't do it recursive next time :-) 43 * - the code is quite ugly... maybe I won't do it recursive next time :-)
44 * - seek is not supported with files that contain edit list
43 * 45 *
44 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/ 46 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
45 * when coding this :) (it's a writer anyway) 47 * when coding this :) (it's a writer anyway)
46 * 48 *
47 * Reference documents: 49 * Reference documents:
48 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt 50 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
49 * Apple: 51 * Apple:
50 * http://developer.apple.com/techpubs/quicktime/qtdevdocs/QTFF/qtff.html 52 * http://developer.apple.com/documentation/QuickTime/QTFF/
51 * http://developer.apple.com/techpubs/quicktime/qtdevdocs/PDF/QTFileFormat.pdf 53 * http://developer.apple.com/documentation/QuickTime/PDF/QTFileFormat.pdf
52 * QuickTime is a trademark of Apple (AFAIK :)) 54 * QuickTime is a trademark of Apple (AFAIK :))
53 */ 55 */
54 56
55 //#define DEBUG 57 //#define DEBUG
56 #ifdef DEBUG 58 #ifdef DEBUG
57 #include <stdio.h> 59 #include <stdio.h>
58 #include <fcntl.h> 60 #include <fcntl.h>
59 #endif 61 #endif
60 62
61 #include "qtpalette.h" 63 #include "qtpalette.h"
64
65
66 /* Allows seeking (MOV_SPLIT_CHUNKS should also be defined) */
67 #define MOV_SEEK
62 68
63 /* allows chunk splitting - should work now... */ 69 /* allows chunk splitting - should work now... */
64 /* in case you can't read a file, try commenting */ 70 /* in case you can't read a file, try commenting */
65 #define MOV_SPLIT_CHUNKS 71 #define MOV_SPLIT_CHUNKS
66 72
215 int ffindex; /* the ffmpeg stream id */ 221 int ffindex; /* the ffmpeg stream id */
216 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */ 222 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
217 long next_chunk; 223 long next_chunk;
218 long chunk_count; 224 long chunk_count;
219 int64_t *chunk_offsets; 225 int64_t *chunk_offsets;
226 int32_t stts_count;
227 uint64_t *stts_data; /* concatenated data from the time-to-sample atom (count|duration) */
228 int32_t edit_count; /* number of 'edit' (elst atom) */
220 long sample_to_chunk_sz; 229 long sample_to_chunk_sz;
221 MOV_sample_to_chunk_tbl *sample_to_chunk; 230 MOV_sample_to_chunk_tbl *sample_to_chunk;
222 long sample_to_chunk_index; 231 long sample_to_chunk_index;
223 long sample_size; 232 long sample_size;
224 long sample_count; 233 long sample_count;
287 unsigned int tag, i; 296 unsigned int tag, i;
288 tag = (unsigned int) atom.type; 297 tag = (unsigned int) atom.type;
289 i=debug_indent; 298 i=debug_indent;
290 if(tag == 0) tag = MKTAG('N', 'U', 'L', 'L'); 299 if(tag == 0) tag = MKTAG('N', 'U', 'L', 'L');
291 while(i--) 300 while(i--)
292 printf("|"); 301 av_log(NULL, AV_LOG_DEBUG, "|");
293 printf("parse:"); 302 av_log(NULL, AV_LOG_DEBUG, "parse:");
294 printf(" %s: tag=%c%c%c%c offset=0x%x size=0x%x\n", 303 av_log(NULL, AV_LOG_DEBUG, " %s: tag=%c%c%c%c offset=0x%x size=0x%x\n",
295 str, tag & 0xff, 304 str, tag & 0xff,
296 (tag >> 8) & 0xff, 305 (tag >> 8) & 0xff,
297 (tag >> 16) & 0xff, 306 (tag >> 16) & 0xff,
298 (tag >> 24) & 0xff, 307 (tag >> 24) & 0xff,
299 (unsigned int)atom.offset, 308 (unsigned int)atom.offset,
338 a.size = get_be32(pb); 347 a.size = get_be32(pb);
339 a.type = get_le32(pb); 348 a.type = get_le32(pb);
340 } 349 }
341 total_size += 8; 350 total_size += 8;
342 a.offset += 8; 351 a.offset += 8;
343 //printf("type: %08x %.4s sz: %Lx %Lx %Lx\n", type, (char*)&type, size, atom.size, total_size); 352 //av_log(NULL, AV_LOG_DEBUG, "type: %08x %.4s sz: %Lx %Lx %Lx\n", type, (char*)&type, size, atom.size, total_size);
344 if (a.size == 1) { /* 64 bit extended size */ 353 if (a.size == 1) { /* 64 bit extended size */
345 a.size = get_be64(pb) - 8; 354 a.size = get_be64(pb) - 8;
346 a.offset += 8; 355 a.offset += 8;
347 total_size += 8; 356 total_size += 8;
348 } 357 }
354 for (i = 0; c->parse_table[i].type != 0L 363 for (i = 0; c->parse_table[i].type != 0L
355 && c->parse_table[i].type != a.type; i++) 364 && c->parse_table[i].type != a.type; i++)
356 /* empty */; 365 /* empty */;
357 366
358 a.size -= 8; 367 a.size -= 8;
359 // printf(" i=%ld\n", i); 368 // av_log(NULL, AV_LOG_DEBUG, " i=%ld\n", i);
360 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */ 369 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
361 // url_seek(pb, atom.offset+atom.size, SEEK_SET); 370 // url_seek(pb, atom.offset+atom.size, SEEK_SET);
362 #ifdef DEBUG 371 #ifdef DEBUG
363 print_atom("unknown", a); 372 print_atom("unknown", a);
364 #endif 373 #endif
374 a.offset += a.size; 383 a.offset += a.size;
375 total_size += a.size; 384 total_size += a.size;
376 } 385 }
377 386
378 if (!err && total_size < atom.size && atom.size < 0x7ffff) { 387 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
379 //printf("RESET %Ld %Ld err:%d\n", atom.size, total_size, err); 388 //av_log(NULL, AV_LOG_DEBUG, "RESET %Ld %Ld err:%d\n", atom.size, total_size, err);
380 url_fskip(pb, atom.size - total_size); 389 url_fskip(pb, atom.size - total_size);
381 } 390 }
382 391
383 #ifdef DEBUG 392 #ifdef DEBUG
384 debug_indent--; 393 debug_indent--;
421 /* component type */ 430 /* component type */
422 ctype = get_le32(pb); 431 ctype = get_le32(pb);
423 type = get_le32(pb); /* component subtype */ 432 type = get_le32(pb); /* component subtype */
424 433
425 #ifdef DEBUG 434 #ifdef DEBUG
426 printf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype); 435 av_log(NULL, AV_LOG_DEBUG, "ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
427 printf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]); 436 av_log(NULL, AV_LOG_DEBUG, "stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
428 #endif 437 #endif
429 #ifdef DEBUG 438 #ifdef DEBUG
430 /* XXX: yeah this is ugly... */ 439 /* XXX: yeah this is ugly... */
431 if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */ 440 if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */
432 if(type == MKTAG('v', 'i', 'd', 'e')) 441 if(type == MKTAG('v', 'i', 'd', 'e'))
481 #ifdef DEBUG 490 #ifdef DEBUG
482 buf = (uint8_t*) av_malloc(len+1); 491 buf = (uint8_t*) av_malloc(len+1);
483 if (buf) { 492 if (buf) {
484 get_buffer(pb, buf, len); 493 get_buffer(pb, buf, len);
485 buf[len] = '\0'; 494 buf[len] = '\0';
486 printf("**buf='%s'\n", buf); 495 av_log(NULL, AV_LOG_DEBUG, "**buf='%s'\n", buf);
487 av_free(buf); 496 av_free(buf);
488 } else 497 } else
489 #endif 498 #endif
490 url_fskip(pb, len); 499 url_fskip(pb, len);
491 } 500 }
511 { 520 {
512 int len; 521 int len;
513 *tag = get_byte(pb); 522 *tag = get_byte(pb);
514 len = mov_mp4_read_descr_len(pb); 523 len = mov_mp4_read_descr_len(pb);
515 #ifdef DEBUG 524 #ifdef DEBUG
516 printf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len); 525 av_log(NULL, AV_LOG_DEBUG, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
517 #endif 526 #endif
518 return len; 527 return len;
519 } 528 }
520 529
521 static inline unsigned int get_be24(ByteIOContext *s) 530 static inline unsigned int get_be24(ByteIOContext *s)
552 sc->esds.buffer_size_db = get_be24(pb); 561 sc->esds.buffer_size_db = get_be24(pb);
553 sc->esds.max_bitrate = get_be32(pb); 562 sc->esds.max_bitrate = get_be32(pb);
554 sc->esds.avg_bitrate = get_be32(pb); 563 sc->esds.avg_bitrate = get_be32(pb);
555 564
556 len = mov_mp4_read_descr(pb, &tag); 565 len = mov_mp4_read_descr(pb, &tag);
557 //printf("LEN %d TAG %d m:%d a:%d\n", len, tag, sc->esds.max_bitrate, sc->esds.avg_bitrate); 566 //av_log(NULL, AV_LOG_DEBUG, "LEN %d TAG %d m:%d a:%d\n", len, tag, sc->esds.max_bitrate, sc->esds.avg_bitrate);
558 if (tag == MP4DecSpecificDescrTag) { 567 if (tag == MP4DecSpecificDescrTag) {
559 #ifdef DEBUG 568 #ifdef DEBUG
560 printf("Specific MPEG4 header len=%d\n", len); 569 av_log(NULL, AV_LOG_DEBUG, "Specific MPEG4 header len=%d\n", len);
561 #endif 570 #endif
562 st->codec.extradata = (uint8_t*) av_mallocz(len); 571 st->codec.extradata = (uint8_t*) av_mallocz(len);
563 if (st->codec.extradata) { 572 if (st->codec.extradata) {
564 get_buffer(pb, st->codec.extradata, len); 573 get_buffer(pb, st->codec.extradata, len);
565 st->codec.extradata_size = len; 574 st->codec.extradata_size = len;
614 get_byte(pb); /* flags */ 623 get_byte(pb); /* flags */
615 624
616 get_be32(pb); /* creation time */ 625 get_be32(pb); /* creation time */
617 get_be32(pb); /* modification time */ 626 get_be32(pb); /* modification time */
618 627
619 c->streams[c->total_streams]->time_scale = get_be32(pb); 628 c->streams[c->fc->nb_streams-1]->time_scale = get_be32(pb);
620 629
621 #ifdef DEBUG 630 #ifdef DEBUG
622 printf("track[%i].time_scale = %i\n", c->fc->nb_streams-1, c->streams[c->total_streams]->time_scale); /* time scale */ 631 av_log(NULL, AV_LOG_DEBUG, "track[%i].time_scale = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->time_scale); /* time scale */
623 #endif 632 #endif
624 get_be32(pb); /* duration */ 633 get_be32(pb); /* duration */
625 634
626 get_be16(pb); /* language */ 635 get_be16(pb); /* language */
627 get_be16(pb); /* quality */ 636 get_be16(pb); /* quality */
638 647
639 get_be32(pb); /* creation time */ 648 get_be32(pb); /* creation time */
640 get_be32(pb); /* modification time */ 649 get_be32(pb); /* modification time */
641 c->time_scale = get_be32(pb); /* time scale */ 650 c->time_scale = get_be32(pb); /* time scale */
642 #ifdef DEBUG 651 #ifdef DEBUG
643 printf("time scale = %i\n", c->time_scale); 652 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
644 #endif 653 #endif
645 c->duration = get_be32(pb); /* duration */ 654 c->duration = get_be32(pb); /* duration */
646 get_be32(pb); /* preferred scale */ 655 get_be32(pb); /* preferred scale */
647 656
648 get_be16(pb); /* preferred volume */ 657 get_be16(pb); /* preferred volume */
673 st->codec.extradata = (uint8_t*) av_mallocz(st->codec.extradata_size); 682 st->codec.extradata = (uint8_t*) av_mallocz(st->codec.extradata_size);
674 683
675 if (st->codec.extradata) { 684 if (st->codec.extradata) {
676 strcpy(st->codec.extradata, "SVQ3"); // fake 685 strcpy(st->codec.extradata, "SVQ3"); // fake
677 get_buffer(pb, st->codec.extradata + 0x5a, atom.size); 686 get_buffer(pb, st->codec.extradata + 0x5a, atom.size);
678 //printf("Reading SMI %Ld %s\n", atom.size, (char*)st->codec.extradata + 0x5a); 687 //av_log(NULL, AV_LOG_DEBUG, "Reading SMI %Ld %s\n", atom.size, (char*)st->codec.extradata + 0x5a);
679 } else 688 } else
680 url_fskip(pb, atom.size); 689 url_fskip(pb, atom.size);
681 690
682 return 0; 691 return 0;
683 } 692 }
709 } else 718 } else
710 return -1; 719 return -1;
711 #ifdef DEBUG 720 #ifdef DEBUG
712 /* 721 /*
713 for(i=0; i<entries; i++) { 722 for(i=0; i<entries; i++) {
714 printf("chunk offset=0x%Lx\n", sc->chunk_offsets[i]); 723 av_log(NULL, AV_LOG_DEBUG, "chunk offset=0x%Lx\n", sc->chunk_offsets[i]);
715 } 724 }
716 */ 725 */
717 #endif 726 #endif
718 return 0; 727 return 0;
719 } 728 }
760 codec = avcodec_find_decoder(id); 769 codec = avcodec_find_decoder(id);
761 if (codec) 770 if (codec)
762 st->codec.codec_type = codec->type; 771 st->codec.codec_type = codec->type;
763 } 772 }
764 #ifdef DEBUG 773 #ifdef DEBUG
765 printf("size=%d 4CC= %c%c%c%c codec_type=%d\n", 774 av_log(NULL, AV_LOG_DEBUG, "size=%d 4CC= %c%c%c%c codec_type=%d\n",
766 size, 775 size,
767 (format >> 0) & 0xff, 776 (format >> 0) & 0xff,
768 (format >> 8) & 0xff, 777 (format >> 8) & 0xff,
769 (format >> 16) & 0xff, 778 (format >> 16) & 0xff,
770 (format >> 24) & 0xff, 779 (format >> 24) & 0xff,
792 get_be32(pb); /* horiz resolution */ 801 get_be32(pb); /* horiz resolution */
793 get_be32(pb); /* vert resolution */ 802 get_be32(pb); /* vert resolution */
794 get_be32(pb); /* data size, always 0 */ 803 get_be32(pb); /* data size, always 0 */
795 frames_per_sample = get_be16(pb); /* frames per samples */ 804 frames_per_sample = get_be16(pb); /* frames per samples */
796 #ifdef DEBUG 805 #ifdef DEBUG
797 printf("frames/samples = %d\n", frames_per_sample); 806 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
798 #endif 807 #endif
799 get_buffer(pb, (uint8_t *)st->codec.codec_name, 32); /* codec name */ 808 get_buffer(pb, (uint8_t *)st->codec.codec_name, 32); /* codec name */
800 809
801 st->codec.bits_per_sample = get_be16(pb); /* depth */ 810 st->codec.bits_per_sample = get_be16(pb); /* depth */
802 st->codec.color_table_id = get_be16(pb); /* colortable id */ 811 st->codec.color_table_id = get_be16(pb); /* colortable id */
813 822
814 a.size = get_be32(pb); 823 a.size = get_be32(pb);
815 a.type = get_le32(pb); 824 a.type = get_le32(pb);
816 size -= 8; 825 size -= 8;
817 #ifdef DEBUG 826 #ifdef DEBUG
818 printf("VIDEO: atom_type=%c%c%c%c atom.size=%Ld size_left=%d\n", 827 av_log(NULL, AV_LOG_DEBUG, "VIDEO: atom_type=%c%c%c%c atom.size=%Ld size_left=%d\n",
819 (a.type >> 0) & 0xff, 828 (a.type >> 0) & 0xff,
820 (a.type >> 8) & 0xff, 829 (a.type >> 8) & 0xff,
821 (a.type >> 16) & 0xff, 830 (a.type >> 16) & 0xff,
822 (a.type >> 24) & 0xff, 831 (a.type >> 24) & 0xff,
823 a.size, size); 832 a.size, size);
846 len = mov_mp4_read_descr(pb, &tag); 855 len = mov_mp4_read_descr(pb, &tag);
847 if (tag != 0x05) 856 if (tag != 0x05)
848 goto fail; 857 goto fail;
849 /* MP4DecSpecificDescrTag */ 858 /* MP4DecSpecificDescrTag */
850 #ifdef DEBUG 859 #ifdef DEBUG
851 printf("Specific MPEG4 header len=%d\n", len); 860 av_log(NULL, AV_LOG_DEBUG, "Specific MPEG4 header len=%d\n", len);
852 #endif 861 #endif
853 sc->header_data = av_mallocz(len); 862 sc->header_data = av_mallocz(len);
854 if (sc->header_data) { 863 if (sc->header_data) {
855 get_buffer(pb, sc->header_data, len); 864 get_buffer(pb, sc->header_data, len);
856 sc->header_len = len; 865 sc->header_len = len;
861 break; 870 break;
862 default: 871 default:
863 break; 872 break;
864 } 873 }
865 fail: 874 fail:
866 printf("ATOMENEWSIZE %Ld %d\n", atom.size, url_ftell(pb) - start_pos); 875 av_log(NULL, AV_LOG_DEBUG, "ATOMENEWSIZE %Ld %d\n", atom.size, url_ftell(pb) - start_pos);
867 if (atom.size > 8) { 876 if (atom.size > 8) {
868 url_fskip(pb, (atom.size - 8) - 877 url_fskip(pb, (atom.size - 8) -
869 ((url_ftell(pb) - start_pos))); 878 ((url_ftell(pb) - start_pos)));
870 size -= atom.size - 8; 879 size -= atom.size - 8;
871 } 880 }
952 } else { 961 } else {
953 st->codec.codec_id = codec_get_id(mov_audio_tags, format); 962 st->codec.codec_id = codec_get_id(mov_audio_tags, format);
954 if(st->codec.codec_id==CODEC_ID_AMR_NB || st->codec.codec_id==CODEC_ID_AMR_WB) //from TS26.244 963 if(st->codec.codec_id==CODEC_ID_AMR_NB || st->codec.codec_id==CODEC_ID_AMR_WB) //from TS26.244
955 { 964 {
956 #ifdef DEBUG 965 #ifdef DEBUG
957 printf("AMR-NB or AMR-WB audio identified!!\n"); 966 av_log(NULL, AV_LOG_DEBUG, "AMR-NB or AMR-WB audio identified!!\n");
958 #endif 967 #endif
959 get_be32(pb);get_be32(pb); //Reserved_8 968 get_be32(pb);get_be32(pb); //Reserved_8
960 get_be16(pb);//Reserved_2 969 get_be16(pb);//Reserved_2
961 get_be16(pb);//Reserved_2 970 get_be16(pb);//Reserved_2
962 get_be32(pb);//Reserved_4 971 get_be32(pb);//Reserved_4
1025 } 1034 }
1026 } 1035 }
1027 else if(size>=(16+20)) 1036 else if(size>=(16+20))
1028 {//16 bytes read, reading atleast 20 more 1037 {//16 bytes read, reading atleast 20 more
1029 #ifdef DEBUG 1038 #ifdef DEBUG
1030 printf("audio size=0x%X\n",size); 1039 av_log(NULL, AV_LOG_DEBUG, "audio size=0x%X\n",size);
1031 #endif 1040 #endif
1032 uint16_t version = get_be16(pb); /* version */ 1041 uint16_t version = get_be16(pb); /* version */
1033 get_be16(pb); /* revision level */ 1042 get_be16(pb); /* revision level */
1034 get_be32(pb); /* vendor */ 1043 get_be32(pb); /* vendor */
1035 1044
1039 /* handle specific s8 codec */ 1048 /* handle specific s8 codec */
1040 get_be16(pb); /* compression id = 0*/ 1049 get_be16(pb); /* compression id = 0*/
1041 get_be16(pb); /* packet size = 0 */ 1050 get_be16(pb); /* packet size = 0 */
1042 1051
1043 st->codec.sample_rate = ((get_be32(pb) >> 16)); 1052 st->codec.sample_rate = ((get_be32(pb) >> 16));
1044 //printf("CODECID %d %d %.4s\n", st->codec.codec_id, CODEC_ID_PCM_S16BE, (char*)&format); 1053 //av_log(NULL, AV_LOG_DEBUG, "CODECID %d %d %.4s\n", st->codec.codec_id, CODEC_ID_PCM_S16BE, (char*)&format);
1045 1054
1046 switch (st->codec.codec_id) { 1055 switch (st->codec.codec_id) {
1047 case CODEC_ID_PCM_S16BE: 1056 case CODEC_ID_PCM_S16BE:
1048 if (st->codec.bits_per_sample == 8) 1057 if (st->codec.bits_per_sample == 8)
1049 st->codec.codec_id = CODEC_ID_PCM_S8; 1058 st->codec.codec_id = CODEC_ID_PCM_S8;
1055 ; 1064 ;
1056 } 1065 }
1057 1066
1058 //Read QT version 1 fields. In version 0 theese dont exist 1067 //Read QT version 1 fields. In version 0 theese dont exist
1059 #ifdef DEBUG 1068 #ifdef DEBUG
1060 printf("version =%d mp4=%d\n",version,c->mp4); 1069 av_log(NULL, AV_LOG_DEBUG, "version =%d mp4=%d\n",version,c->mp4);
1061 printf("size-(16+20+16)=%d\n",size-(16+20+16)); 1070 av_log(NULL, AV_LOG_DEBUG, "size-(16+20+16)=%d\n",size-(16+20+16));
1062 #endif 1071 #endif
1063 if((version==1) && size>=(16+20+16)) 1072 if((version==1) && size>=(16+20+16))
1064 { 1073 {
1065 get_be32(pb); /* samples per packet */ 1074 get_be32(pb); /* samples per packet */
1066 get_be32(pb); /* bytes per packet */ 1075 get_be32(pb); /* bytes per packet */
1068 get_be32(pb); /* bytes per sample */ 1077 get_be32(pb); /* bytes per sample */
1069 if(size>(16+20+16)) 1078 if(size>(16+20+16))
1070 { 1079 {
1071 //Optional, additional atom-based fields 1080 //Optional, additional atom-based fields
1072 #ifdef DEBUG 1081 #ifdef DEBUG
1073 printf("offest=0x%X, sizeleft=%d=0x%x,format=%c%c%c%c\n",(int)url_ftell(pb),size - (16 + 20 + 16 ),size - (16 + 20 + 16 ), 1082 av_log(NULL, AV_LOG_DEBUG, "offest=0x%X, sizeleft=%d=0x%x,format=%c%c%c%c\n",(int)url_ftell(pb),size - (16 + 20 + 16 ),size - (16 + 20 + 16 ),
1074 (format >> 0) & 0xff, 1083 (format >> 0) & 0xff,
1075 (format >> 8) & 0xff, 1084 (format >> 8) & 0xff,
1076 (format >> 16) & 0xff, 1085 (format >> 16) & 0xff,
1077 (format >> 24) & 0xff); 1086 (format >> 24) & 0xff);
1078 #endif 1087 #endif
1084 { 1093 {
1085 //We should be down to 0 bytes here, but lets make sure. 1094 //We should be down to 0 bytes here, but lets make sure.
1086 size-=(16+20); 1095 size-=(16+20);
1087 #ifdef DEBUG 1096 #ifdef DEBUG
1088 if(size>0) 1097 if(size>0)
1089 printf("skipping 0x%X bytes\n",size-(16+20)); 1098 av_log(NULL, AV_LOG_DEBUG, "skipping 0x%X bytes\n",size-(16+20));
1090 #endif 1099 #endif
1091 url_fskip(pb, size); 1100 url_fskip(pb, size);
1092 } 1101 }
1093 } 1102 }
1094 else 1103 else
1095 { 1104 {
1096 size-=16; 1105 size-=16;
1097 //Unknown size, but lets do our best and skip the rest. 1106 //Unknown size, but lets do our best and skip the rest.
1098 #ifdef DEBUG 1107 #ifdef DEBUG
1099 printf("Strange size, skipping 0x%X bytes\n",size); 1108 av_log(NULL, AV_LOG_DEBUG, "Strange size, skipping 0x%X bytes\n",size);
1100 #endif 1109 #endif
1101 url_fskip(pb, size); 1110 url_fskip(pb, size);
1102 } 1111 }
1103 } 1112 }
1104 } 1113 }
1117 get_byte(pb); /* version */ 1126 get_byte(pb); /* version */
1118 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ 1127 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1119 1128
1120 entries = get_be32(pb); 1129 entries = get_be32(pb);
1121 #ifdef DEBUG 1130 #ifdef DEBUG
1122 printf("track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); 1131 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1123 #endif 1132 #endif
1124 sc->sample_to_chunk_sz = entries; 1133 sc->sample_to_chunk_sz = entries;
1125 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl)); 1134 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1126 if (!sc->sample_to_chunk) 1135 if (!sc->sample_to_chunk)
1127 return -1; 1136 return -1;
1128 for(i=0; i<entries; i++) { 1137 for(i=0; i<entries; i++) {
1129 sc->sample_to_chunk[i].first = get_be32(pb); 1138 sc->sample_to_chunk[i].first = get_be32(pb);
1130 sc->sample_to_chunk[i].count = get_be32(pb); 1139 sc->sample_to_chunk[i].count = get_be32(pb);
1131 sc->sample_to_chunk[i].id = get_be32(pb); 1140 sc->sample_to_chunk[i].id = get_be32(pb);
1132 #ifdef DEBUG 1141 #ifdef DEBUG
1133 /* printf("sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id); */ 1142 /* av_log(NULL, AV_LOG_DEBUG, "sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id); */
1134 #endif 1143 #endif
1135 } 1144 }
1136 return 0; 1145 return 0;
1137 } 1146 }
1138 1147
1177 1186
1178 sc->sample_size = get_be32(pb); 1187 sc->sample_size = get_be32(pb);
1179 entries = get_be32(pb); 1188 entries = get_be32(pb);
1180 sc->sample_count = entries; 1189 sc->sample_count = entries;
1181 #ifdef DEBUG 1190 #ifdef DEBUG
1182 printf("sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count); 1191 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1183 #endif 1192 #endif
1184 if(sc->sample_size) 1193 if(sc->sample_size)
1185 return 0; /* there isn't any table following */ 1194 return 0; /* there isn't any table following */
1186 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long)); 1195 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1187 if (!sc->sample_sizes) 1196 if (!sc->sample_sizes)
1188 return -1; 1197 return -1;
1189 for(i=0; i<entries; i++) { 1198 for(i=0; i<entries; i++) {
1190 sc->sample_sizes[i] = get_be32(pb); 1199 sc->sample_sizes[i] = get_be32(pb);
1191 #ifdef DEBUG 1200 #ifdef DEBUG
1192 /* printf("sample_sizes[]=%ld\n", sc->sample_sizes[i]); */ 1201 /* av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]); */
1193 #endif 1202 #endif
1194 } 1203 }
1195 return 0; 1204 return 0;
1196 } 1205 }
1197 1206
1207 1216
1208 get_byte(pb); /* version */ 1217 get_byte(pb); /* version */
1209 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ 1218 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1210 entries = get_be32(pb); 1219 entries = get_be32(pb);
1211 1220
1212 1221 c->streams[c->fc->nb_streams-1]->stts_count = entries;
1213 #ifdef DEBUG 1222 c->streams[c->fc->nb_streams-1]->stts_data = (uint64_t*) av_malloc(entries * sizeof(uint64_t));
1214 printf("track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries); 1223
1224 #ifdef DEBUG
1225 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1215 #endif 1226 #endif
1216 for(i=0; i<entries; i++) { 1227 for(i=0; i<entries; i++) {
1217 int sample_duration; 1228 int32_t sample_duration;
1218 int sample_count; 1229 int32_t sample_count;
1219 1230
1220 sample_count=get_be32(pb); 1231 sample_count=get_be32(pb);
1221 sample_duration = get_be32(pb); 1232 sample_duration = get_be32(pb);
1222 #ifdef DEBUG 1233 c->streams[c->fc->nb_streams - 1]->stts_data[i] = (uint64_t)sample_count<<32 | (uint64_t)sample_duration;
1223 printf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration); 1234 #ifdef DEBUG
1235 av_log(NULL, AV_LOG_DEBUG, "sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1224 #endif 1236 #endif
1225 duration+=sample_duration*sample_count; 1237 duration+=sample_duration*sample_count;
1226 total_sample_count+=sample_count; 1238 total_sample_count+=sample_count;
1227 1239
1228 #if 0 //We calculate an average instead, needed by .mp4-files created with nec e606 3g phone 1240 #if 0 //We calculate an average instead, needed by .mp4-files created with nec e606 3g phone
1229 1241
1230 if (!i && st->codec.codec_type==CODEC_TYPE_VIDEO) { 1242 if (!i && st->codec.codec_type==CODEC_TYPE_VIDEO) {
1231 st->codec.frame_rate_base = sample_duration ? sample_duration : 1; 1243 st->codec.frame_rate_base = sample_duration ? sample_duration : 1;
1232 st->codec.frame_rate = c->streams[c->total_streams]->time_scale; 1244 st->codec.frame_rate = c->streams[c->fc->nb_streams-1]->time_scale;
1233 #ifdef DEBUG 1245 #ifdef DEBUG
1234 printf("VIDEO FRAME RATE= %i (sd= %i)\n", st->codec.frame_rate, sample_duration); 1246 av_log(NULL, AV_LOG_DEBUG, "VIDEO FRAME RATE= %i (sd= %i)\n", st->codec.frame_rate, sample_duration);
1235 #endif 1247 #endif
1236 } 1248 }
1237 #endif 1249 #endif
1238 } 1250 }
1239 1251
1241 if(duration>0) 1253 if(duration>0)
1242 { 1254 {
1243 av_reduce( 1255 av_reduce(
1244 &st->codec.frame_rate, 1256 &st->codec.frame_rate,
1245 &st->codec.frame_rate_base, 1257 &st->codec.frame_rate_base,
1246 c->streams[c->total_streams]->time_scale * total_sample_count, 1258 c->streams[c->fc->nb_streams-1]->time_scale * total_sample_count,
1247 duration, 1259 duration,
1248 INT_MAX 1260 INT_MAX
1249 ); 1261 );
1250 1262
1251 #ifdef DEBUG 1263 #ifdef DEBUG
1252 printf("FRAME RATE average (video or audio)= %f (tot sample count= %i ,tot dur= %i timescale=%d)\n", (float)st->codec.frame_rate/st->codec.frame_rate_base,total_sample_count,duration,c->streams[c->total_streams]->time_scale); 1264 av_log(NULL, AV_LOG_DEBUG, "FRAME RATE average (video or audio)= %f (tot sample count= %i ,tot dur= %i timescale=%d)\n", (float)st->codec.frame_rate/st->codec.frame_rate_base,total_sample_count,duration,c->streams[c->fc->nb_streams-1]->time_scale);
1253 #endif 1265 #endif
1254 } 1266 }
1255 else 1267 else
1256 { 1268 {
1257 st->codec.frame_rate_base = 1; 1269 st->codec.frame_rate_base = 1;
1258 st->codec.frame_rate = c->streams[c->total_streams]->time_scale; 1270 st->codec.frame_rate = c->streams[c->fc->nb_streams-1]->time_scale;
1259 } 1271 }
1260 return 0; 1272 return 0;
1261 } 1273 }
1262 1274
1263 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) 1275 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1377 1389
1378 get_be32(pb); /* dcom atom */ 1390 get_be32(pb); /* dcom atom */
1379 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' )) 1391 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1380 return -1; 1392 return -1;
1381 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) { 1393 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1382 dprintf("unknown compression for cmov atom !"); 1394 av_log(NULL, AV_LOG_DEBUG, "unknown compression for cmov atom !");
1383 return -1; 1395 return -1;
1384 } 1396 }
1385 get_be32(pb); /* cmvd atom */ 1397 get_be32(pb); /* cmvd atom */
1386 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' )) 1398 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1387 return -1; 1399 return -1;
1413 av_free(cmov_data); 1425 av_free(cmov_data);
1414 1426
1415 return ret; 1427 return ret;
1416 } 1428 }
1417 #endif 1429 #endif
1430
1431 /* edit list atom */
1432 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1433 {
1434 print_atom("elst", atom);
1435
1436 get_byte(pb); /* version */
1437 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1438 c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1439 #ifdef DEBUG
1440 av_log(NULL, AV_LOG_DEBUG, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1441 #endif
1442 return 0;
1443 }
1418 1444
1419 static const MOVParseTableEntry mov_default_parse_table[] = { 1445 static const MOVParseTableEntry mov_default_parse_table[] = {
1420 /* mp4 atoms */ 1446 /* mp4 atoms */
1421 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco }, 1447 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1422 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default }, 1448 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1424 { MKTAG( 'c', 't', 't', 's' ), mov_read_leaf }, /* composition time to sample */ 1450 { MKTAG( 'c', 't', 't', 's' ), mov_read_leaf }, /* composition time to sample */
1425 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */ 1451 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1426 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf }, 1452 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1427 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf }, 1453 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1428 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default }, 1454 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1429 { MKTAG( 'e', 'l', 's', 't' ), mov_read_leaf }, 1455 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1430 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf }, 1456 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1431 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr }, 1457 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1432 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf }, 1458 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1433 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf }, 1459 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1434 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf }, 1460 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1500 av_free(sc->chunk_offsets); 1526 av_free(sc->chunk_offsets);
1501 av_free(sc->sample_to_chunk); 1527 av_free(sc->sample_to_chunk);
1502 av_free(sc->sample_sizes); 1528 av_free(sc->sample_sizes);
1503 av_free(sc->keyframes); 1529 av_free(sc->keyframes);
1504 av_free(sc->header_data); 1530 av_free(sc->header_data);
1531 av_free(sc->stts_data);
1505 av_free(sc); 1532 av_free(sc);
1506 } 1533 }
1507 } 1534 }
1508 1535
1509 static inline uint32_t mov_to_tag(uint8_t *buf) 1536 static inline uint32_t mov_to_tag(uint8_t *buf)
1569 atom.size = url_filesize(url_fileno(pb)); 1596 atom.size = url_filesize(url_fileno(pb));
1570 else 1597 else
1571 atom.size = 0x7FFFFFFFFFFFFFFFLL; 1598 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1572 1599
1573 #ifdef DEBUG 1600 #ifdef DEBUG
1574 printf("filesz=%Ld\n", atom.size); 1601 av_log(NULL, AV_LOG_DEBUG, "filesz=%Ld\n", atom.size);
1575 #endif 1602 #endif
1576 1603
1577 /* check MOV header */ 1604 /* check MOV header */
1578 err = mov_read_default(mov, pb, atom); 1605 err = mov_read_default(mov, pb, atom);
1579 if (err<0 || (!mov->found_moov && !mov->found_mdat)) { 1606 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1580 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%lld\n", 1607 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%lld\n",
1581 err, mov->found_moov, mov->found_mdat, url_ftell(pb)); 1608 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1582 return -1; 1609 return -1;
1583 } 1610 }
1584 #ifdef DEBUG 1611 #ifdef DEBUG
1585 printf("on_parse_exit_offset=%d\n", (int) url_ftell(pb)); 1612 av_log(NULL, AV_LOG_DEBUG, "on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1586 #endif 1613 #endif
1587 /* some cleanup : make sure we are on the mdat atom */ 1614 /* some cleanup : make sure we are on the mdat atom */
1588 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset)) 1615 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1589 url_fseek(pb, mov->mdat_offset, SEEK_SET); 1616 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1590 1617
1591 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */ 1618 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1592 1619
1593 #ifdef DEBUG 1620 #ifdef DEBUG
1594 printf("mdat_reset_offset=%d\n", (int) url_ftell(pb)); 1621 av_log(NULL, AV_LOG_DEBUG, "mdat_reset_offset=%d\n", (int) url_ftell(pb));
1595 #endif 1622 #endif
1596 1623
1597 #ifdef DEBUG 1624 #ifdef DEBUG
1598 printf("streams= %d\n", s->nb_streams); 1625 av_log(NULL, AV_LOG_DEBUG, "streams= %d\n", s->nb_streams);
1599 #endif 1626 #endif
1600 mov->total_streams = nb = s->nb_streams; 1627 mov->total_streams = nb = s->nb_streams;
1601 1628
1602 #if 1 1629 #if 1
1603 for(i=0; i<s->nb_streams;) { 1630 for(i=0; i<s->nb_streams;) {
1615 sc->ffindex = i; 1642 sc->ffindex = i;
1616 sc->is_ff_stream = 1; 1643 sc->is_ff_stream = 1;
1617 } 1644 }
1618 #endif 1645 #endif
1619 #ifdef DEBUG 1646 #ifdef DEBUG
1620 printf("real streams= %d\n", s->nb_streams); 1647 av_log(NULL, AV_LOG_DEBUG, "real streams= %d\n", s->nb_streams);
1621 #endif 1648 #endif
1622 return 0; 1649 return 0;
1623 } 1650 }
1624 1651
1625 /* Yes, this is ugly... I didn't write the specs of QT :p */ 1652 /* Yes, this is ugly... I didn't write the specs of QT :p */
1658 1685
1659 again: 1686 again:
1660 sc = 0; 1687 sc = 0;
1661 for(i=0; i<mov->total_streams; i++) { 1688 for(i=0; i<mov->total_streams; i++) {
1662 MOVStreamContext *msc = mov->streams[i]; 1689 MOVStreamContext *msc = mov->streams[i];
1663 //printf("MOCHUNK %ld %d %p pos:%Ld\n", mov->streams[i]->next_chunk, mov->total_streams, mov->streams[i], url_ftell(&s->pb)); 1690 //av_log(NULL, AV_LOG_DEBUG, "MOCHUNK %ld %d %p pos:%Ld\n", mov->streams[i]->next_chunk, mov->total_streams, mov->streams[i], url_ftell(&s->pb));
1664 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0 1691 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0
1665 && (msc->chunk_offsets[msc->next_chunk] < offset)) { 1692 && (msc->chunk_offsets[msc->next_chunk] < offset)) {
1666 sc = msc; 1693 sc = msc;
1667 offset = msc->chunk_offsets[msc->next_chunk]; 1694 offset = msc->chunk_offsets[msc->next_chunk];
1668 //printf("SELETED %Ld i:%d\n", offset, i); 1695 //av_log(NULL, AV_LOG_DEBUG, "SELETED %Ld i:%d\n", offset, i);
1669 } 1696 }
1670 } 1697 }
1671 if (!sc || offset==0x0FFFFFFFFFFFFFFFLL) 1698 if (!sc || offset==0x0FFFFFFFFFFFFFFFLL)
1672 return -1; 1699 return -1;
1673 1700
1676 if(mov->next_chunk_offset < offset) { /* some meta data */ 1703 if(mov->next_chunk_offset < offset) { /* some meta data */
1677 url_fskip(&s->pb, (offset - mov->next_chunk_offset)); 1704 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1678 mov->next_chunk_offset = offset; 1705 mov->next_chunk_offset = offset;
1679 } 1706 }
1680 1707
1681 //printf("chunk: [%i] %lli -> %lli\n", st_id, mov->next_chunk_offset, offset); 1708 //av_log(NULL, AV_LOG_DEBUG, "chunk: [%i] %lli -> %lli\n", st_id, mov->next_chunk_offset, offset);
1682 if(!sc->is_ff_stream) { 1709 if(!sc->is_ff_stream) {
1683 url_fskip(&s->pb, (offset - mov->next_chunk_offset)); 1710 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1684 mov->next_chunk_offset = offset; 1711 mov->next_chunk_offset = offset;
1685 offset = 0x0FFFFFFFFFFFFFFFLL; 1712 offset = 0x0FFFFFFFFFFFFFFFLL;
1686 goto again; 1713 goto again;
1712 foundsize=(sc->sample_to_chunk[i].count*cod->channels*cod->bits_per_sample)/8; 1739 foundsize=(sc->sample_to_chunk[i].count*cod->channels*cod->bits_per_sample)/8;
1713 else 1740 else
1714 foundsize=sc->sample_to_chunk[i].count*sc->sample_size; 1741 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1715 } 1742 }
1716 #ifdef DEBUG 1743 #ifdef DEBUG
1717 /*printf("sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id);*/ 1744 /*av_log(NULL, AV_LOG_DEBUG, "sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id);*/
1718 #endif 1745 #endif
1719 } 1746 }
1720 if( (foundsize>0) && (foundsize<size) ) 1747 if( (foundsize>0) && (foundsize<size) )
1721 { 1748 {
1722 #ifdef DEBUG 1749 #ifdef DEBUG
1723 /*printf("this size should actually be %d\n",foundsize);*/ 1750 /*av_log(NULL, AV_LOG_DEBUG, "this size should actually be %d\n",foundsize);*/
1724 #endif 1751 #endif
1725 size=foundsize; 1752 size=foundsize;
1726 } 1753 }
1727 } 1754 }
1728 #endif //MOV_MINOLTA_FIX 1755 #endif //MOV_MINOLTA_FIX
1745 sc->current_sample++; 1772 sc->current_sample++;
1746 } 1773 }
1747 #endif 1774 #endif
1748 1775
1749 readchunk: 1776 readchunk:
1750 //printf("chunk: [%i] %lli -> %lli (%i)\n", st_id, offset, offset + size, size); 1777 //av_log(NULL, AV_LOG_DEBUG, "chunk: [%i] %lli -> %lli (%i)\n", st_id, offset, offset + size, size);
1751 if(size == 0x0FFFFFFF) 1778 if(size == 0x0FFFFFFF)
1752 size = mov->mdat_size + mov->mdat_offset - offset; 1779 size = mov->mdat_size + mov->mdat_offset - offset;
1753 if(size < 0) 1780 if(size < 0)
1754 return -1; 1781 return -1;
1755 if(size == 0) 1782 if(size == 0)
1756 return -1; 1783 return -1;
1757 url_fseek(&s->pb, offset, SEEK_SET); 1784 url_fseek(&s->pb, offset, SEEK_SET);
1758 1785
1759 //printf("READCHUNK hlen: %d %d off: %Ld pos:%Ld\n", size, sc->header_len, offset, url_ftell(&s->pb)); 1786 //av_log(NULL, AV_LOG_DEBUG, "READCHUNK hlen: %d %d off: %Ld pos:%Ld\n", size, sc->header_len, offset, url_ftell(&s->pb));
1760 if (sc->header_len > 0) { 1787 if (sc->header_len > 0) {
1761 av_new_packet(pkt, size + sc->header_len); 1788 av_new_packet(pkt, size + sc->header_len);
1762 memcpy(pkt->data, sc->header_data, sc->header_len); 1789 memcpy(pkt->data, sc->header_data, sc->header_len);
1763 get_buffer(&s->pb, pkt->data + sc->header_len, size); 1790 get_buffer(&s->pb, pkt->data + sc->header_len, size);
1764 /* free header */ 1791 /* free header */
1791 else 1818 else
1792 pkt->flags |= PKT_FLAG_KEY; 1819 pkt->flags |= PKT_FLAG_KEY;
1793 1820
1794 #ifdef DEBUG 1821 #ifdef DEBUG
1795 /* 1822 /*
1796 printf("Packet (%d, %d, %ld) ", pkt->stream_index, st_id, pkt->size); 1823 av_log(NULL, AV_LOG_DEBUG, "Packet (%d, %d, %ld) ", pkt->stream_index, st_id, pkt->size);
1797 for(i=0; i<8; i++) 1824 for(i=0; i<8; i++)
1798 printf("%02x ", pkt->data[i]); 1825 av_log(NULL, AV_LOG_DEBUG, "%02x ", pkt->data[i]);
1799 for(i=0; i<8; i++) 1826 for(i=0; i<8; i++)
1800 printf("%c ", (pkt->data[i]) & 0x7F); 1827 av_log(NULL, AV_LOG_DEBUG, "%c ", (pkt->data[i]) & 0x7F);
1801 puts(""); 1828 puts("");
1802 */ 1829 */
1803 #endif 1830 #endif
1804 1831
1805 mov->next_chunk_offset = offset + size; 1832 mov->next_chunk_offset = offset + size;
1806 1833
1807 return 0; 1834 return 0;
1808 } 1835 }
1836
1837 #if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)
1838 /**
1839 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1840 */
1841 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp)
1842 {
1843 MOVContext* mov = (MOVContext *) s->priv_data;
1844 MOVStreamContext* sc;
1845 int32_t i, a, b, m;
1846 int64_t sample_time;
1847 int64_t start_time;
1848 int32_t seek_sample, sample;
1849 int32_t duration;
1850 int32_t count;
1851 int32_t chunk;
1852 int32_t left_in_chunk;
1853 int64_t chunk_file_offset;
1854 int64_t sample_file_offset;
1855 int32_t first_chunk_sample;
1856 int32_t sample_to_chunk_idx;
1857 int mov_idx;
1858
1859 // Find the corresponding mov stream
1860 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1861 if (mov->streams[mov_idx]->ffindex == stream_index)
1862 break;
1863 if (mov_idx == mov->total_streams) {
1864 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1865 return -1;
1866 }
1867 sc = mov->streams[mov_idx];
1868
1869 // Step 1. Find the edit that contains the requested time (elst)
1870 if (sc->edit_count) {
1871 // FIXME should handle edit list
1872 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
1873 return -1;
1874 }
1875
1876 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
1877 #ifdef DEBUG
1878 av_log(s, AV_LOG_DEBUG, "Searching for time %li in stream #%i (time_scale=%i)\n", (long)timestamp, mov_idx, sc->time_scale);
1879 #endif
1880 // convert timestamp from time_base unit to timescale unit
1881 sample_time = av_rescale( timestamp,
1882 (int64_t)sc->time_scale * s->streams[stream_index]->time_base.num,
1883 (int64_t)s->streams[stream_index]->time_base.den);
1884 start_time = 0; // FIXME use elst atom
1885 sample = 1; // sample are 0 based in table
1886 #ifdef DEBUG
1887 av_log(s, AV_LOG_DEBUG, "Searching for sample_time %li \n", (long)sample_time);
1888 #endif
1889 for (i = 0; i < sc->stts_count; i++) {
1890 count = (uint32_t)(sc->stts_data[i]>>32);
1891 duration = (uint32_t)(sc->stts_data[i]&0xffff);
1892 //av_log(s, AV_LOG_DEBUG, "> sample_time %lli \n", (long)sample_time);
1893 //av_log(s, AV_LOG_DEBUG, "> count=%i duration=%i\n", count, duration);
1894 if ((start_time + count*duration) > sample_time) {
1895 sample += (sample_time - start_time) / duration;
1896 break;
1897 }
1898 sample += count;
1899 start_time += count * duration;
1900 }
1901 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
1902 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
1903
1904 #ifdef DEBUG
1905 av_log(s, AV_LOG_DEBUG, "Found time %li at sample #%u\n", (long)sample_time, sample);
1906 #endif
1907 if (sample > sc->sample_count) {
1908 av_log(s, AV_LOG_ERROR, "mov: sample pos is too high, unable to seek (req. sample=%i, sample count=%ld)\n", sample, sc->sample_count);
1909 return -1;
1910 }
1911
1912 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
1913 if (sc->keyframes) {
1914 a = 0;
1915 b = sc->keyframe_count - 1;
1916 while (a < b) {
1917 m = (a + b + 1) >> 1;
1918 if (sc->keyframes[m] > sample) {
1919 b = m - 1;
1920 } else {
1921 a = m;
1922 }
1923 #ifdef DEBUG
1924 // av_log(s, AV_LOG_DEBUG, "a=%i (%i) b=%i (%i) m=%i (%i) stream #%i\n", a, sc->keyframes[a], b, sc->keyframes[b], m, sc->keyframes[m], mov_idx);
1925 #endif
1926 }
1927 seek_sample = sc->keyframes[a];
1928 }
1929 else
1930 seek_sample = sample; // else all samples are key frames
1931 #ifdef DEBUG
1932 av_log(s, AV_LOG_DEBUG, "Found nearest keyframe at sample #%i \n", seek_sample);
1933 #endif
1934
1935 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
1936 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
1937 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
1938 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
1939 break;
1940 first_chunk_sample += b;
1941 }
1942 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
1943 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
1944 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
1945 sample_to_chunk_idx = i;
1946 #ifdef DEBUG
1947 av_log(s, AV_LOG_DEBUG, "Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
1948 #endif
1949
1950 // Step 5. Find the offset of the chunk using the chunk offset atom
1951 if (!sc->chunk_offsets) {
1952 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
1953 return -1;
1954 }
1955 if (chunk > sc->chunk_count) {
1956 av_log(s, AV_LOG_ERROR, "mov: chunk offset atom too short, unable to seek (req. chunk=%i, chunk count=%li)\n", chunk, sc->chunk_count);
1957 return -1;
1958 }
1959 chunk_file_offset = sc->chunk_offsets[chunk - 1];
1960 #ifdef DEBUG
1961 av_log(s, AV_LOG_DEBUG, "Chunk file offset is #%llu \n", chunk_file_offset);
1962 #endif
1963
1964 // Step 6. Find the byte offset within the chunk using the sample size atom
1965 sample_file_offset = chunk_file_offset;
1966 if (sc->sample_size)
1967 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
1968 else {
1969 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
1970 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
1971 }
1972 }
1973 #ifdef DEBUG
1974 av_log(s, AV_LOG_DEBUG, "Sample file offset is #%llu \n", sample_file_offset);
1975 #endif
1976
1977 // Step 6. Update the parser
1978 mov->partial = sc;
1979 mov->next_chunk_offset = sample_file_offset;
1980 // Update current stream state
1981 sc->current_sample = seek_sample - 1; // zero based
1982 sc->left_in_chunk = left_in_chunk;
1983 sc->next_chunk = chunk; // +1 -1 (zero based)
1984 sc->sample_to_chunk_index = sample_to_chunk_idx;
1985
1986 // Update other streams
1987 for (i = 0; i<mov->total_streams; i++) {
1988 if (i == mov_idx) continue;
1989 // Find the nearest 'next' chunk
1990 MOVStreamContext *msc = mov->streams[i];
1991 a = 0;
1992 b = msc->chunk_count - 1;
1993 while (a < b) {
1994 m = (a + b + 1) >> 1;
1995 if (msc->chunk_offsets[m] > chunk_file_offset) {
1996 b = m - 1;
1997 } else {
1998 a = m;
1999 }
2000 #ifdef DEBUG
2001 /* av_log(s, AV_LOG_DEBUG, "a=%i (%li) b=%i (%li) m=%i (%li) stream #%i\n"
2002 , a, (long)msc->chunk_offsets[a], b, (long)msc->chunk_offsets[b], m, (long)msc->chunk_offsets[m], i); */
2003 #endif
2004 }
2005 msc->next_chunk = a;
2006 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2007 msc->next_chunk ++;
2008 #ifdef DEBUG
2009 av_log(s, AV_LOG_DEBUG, "Nearest next chunk for stream #%i is #%i @%lli\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2010 #endif
2011 // Compute sample count and index in the sample_to_chunk table (what a pity)
2012 msc->sample_to_chunk_index = 0;
2013 msc->current_sample = 0;
2014 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2015 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2016 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2017 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2018 }
2019 msc->current_sample += (msc->next_chunk - (msc->sample_to_chunk[msc->sample_to_chunk_index].first - 1)) * sc->sample_to_chunk[msc->sample_to_chunk_index].count;
2020 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2021 #ifdef DEBUG
2022 av_log(s, AV_LOG_DEBUG, "Next Sample for stream #%i is #%i @%i\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2023 #endif
2024 }
2025 return 0;
2026 }
2027 #endif
1809 2028
1810 static int mov_read_close(AVFormatContext *s) 2029 static int mov_read_close(AVFormatContext *s)
1811 { 2030 {
1812 int i; 2031 int i;
1813 MOVContext *mov = (MOVContext *) s->priv_data; 2032 MOVContext *mov = (MOVContext *) s->priv_data;
1826 sizeof(MOVContext), 2045 sizeof(MOVContext),
1827 mov_probe, 2046 mov_probe,
1828 mov_read_header, 2047 mov_read_header,
1829 mov_read_packet, 2048 mov_read_packet,
1830 mov_read_close, 2049 mov_read_close,
2050 #if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)
2051 mov_read_seek,
2052 #endif
1831 }; 2053 };
1832 2054
1833 int mov_init(void) 2055 int mov_init(void)
1834 { 2056 {
1835 av_register_input_format(&mov_iformat); 2057 av_register_input_format(&mov_iformat);