Changeset 181 for trunk/libmpdemux/demux_mov.c
- Timestamp:
- Aug 14, 2006, 10:01:29 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/libmpdemux/demux_mov.c ¶
r172 r181 551 551 } 552 552 553 unsigned int store_ughvlc(unsigned char *s, unsigned int v){ 554 unsigned int n = 0; 555 556 while(v >= 0xff) { 557 *s++ = 0xff; 558 v -= 0xff; 559 n++; 560 } 561 *s = v; 562 n++; 563 564 return n; 565 } 566 553 567 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, 554 568 off_t pos, off_t len, mov_track_t* trak); … … 556 570 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ 557 571 mov_priv_t* priv=demuxer->priv; 558 // printf("lschunks (level=%d,endpos=%x)\n", level, endpos);572 // printf("lschunks (level=%d,endpos=%x)\n", level, endpos); 559 573 while(1){ 560 561 562 563 564 574 off_t pos; 575 off_t len; 576 unsigned int id; 577 // 578 pos=stream_tell(demuxer->stream); 565 579 dprintf("MOV: stream_tell==%lli\n",pos); 566 if(pos>=endpos) return; // END 567 len=stream_read_dword(demuxer->stream); 568 // printf("len==%d\n",len); 569 if(len<8) return; // error 570 len-=8; 571 id=stream_read_dword(demuxer->stream); 572 // 573 dprintf("lschunks %.4s %d\n",(char *)&id,(int)len); 574 // 575 if(trak){ 576 if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0) 577 return; 578 } else { /* not in track */ 579 switch(id) { 580 case MOV_FOURCC('m','v','h','d'): { 581 stream_skip(demuxer->stream,12); 582 priv->timescale=stream_read_dword(demuxer->stream); 583 priv->duration=stream_read_dword(demuxer->stream); 584 dprintf("MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len, 585 (int)priv->timescale,(int)priv->duration); 586 break; 587 } 588 case MOV_FOURCC('t','r','a','k'): { 589 // if(trak) printf("MOV: Warning! trak in trak?\n"); 590 if(priv->track_db>=MOV_MAX_TRACKS){ 591 dprintf("MOV: too may tracks\n"); 592 return; 593 } 594 if(!priv->track_db) dprintf( "--------------\n"); 595 trak=malloc(sizeof(mov_track_t)); 596 memset(trak,0,sizeof(mov_track_t)); 597 dprintf("MOV: Track #%d:\n",priv->track_db); 598 trak->id=priv->track_db; 599 priv->tracks[priv->track_db]=trak; 600 lschunks(demuxer,level+1,pos+len,trak); 601 mov_build_index(trak,priv->timescale); 602 switch(trak->type){ 603 case MOV_TRAK_AUDIO: { 604 #if 0 605 struct { 606 int16_t version; // 0 or 1 (version 1 is qt3.0+) 607 int16_t revision; // 0 608 int32_t vendor_id; // 0 609 int16_t channels; // 1 or 2 (Mono/Stereo) 610 int16_t samplesize; // 8 or 16 (8Bit/16Bit) 611 int16_t compression_id; // if version 0 then 0 612 // if version 1 and vbr then -2 else 0 613 int16_t packet_size; // 0 614 uint16_t sample_rate; // samplerate (Hz) 615 // qt3.0+ (version == 1) 616 uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet 617 // if 0 below three values are also 0 618 uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel 619 uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels 620 // (channels * bytes_per_packet) 621 uint32_t bytes_per_sample; // 0 or size of uncompressed sample 622 // if samples_per_packet and bytes_per_packet are constant (CBR) 623 // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR) 624 // --- 625 // optional additional atom-based fields 626 // ([int32_t size,int32_t type,some data ],repeat) 627 } my_stdata; 628 #endif 629 int version, adjust; 630 sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); 631 sh->format=trak->fourcc; 632 633 switch( sh->format ) { 634 case 0x726D6173: /* samr */ 635 /* amr narrowband */ 636 trak->samplebytes=sh->samplesize=1; 637 trak->nchannels=sh->channels=1; 638 sh->samplerate=8000; 639 break; 640 641 case 0x62776173: /* sawb */ 642 /* amr wideband */ 643 trak->samplebytes=sh->samplesize=1; 644 trak->nchannels=sh->channels=1; 645 sh->samplerate=16000; 646 break; 647 648 default: 649 650 // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit 651 // XXX: 32bit fixed point numbers (intfp) are only 2 Byte! 652 // short values are usually one byte leftpadded by zero 653 // int values are usually two byte leftpadded by zero 654 // stdata[]: 655 // 8 short version 656 // 10 short revision 657 // 12 int vendor_id 658 // 16 short channels 659 // 18 short samplesize 660 // 20 short compression_id 661 // 22 short packet_size (==0) 662 // 24 intfp sample_rate 663 // (26 short) unknown (==0) 664 // ---- qt3.0+ (version>=1) 665 // 28 int samples_per_packet 666 // 32 int bytes_per_packet 667 // 36 int bytes_per_frame 668 // 40 int bytes_per_sample 669 // there may be additional atoms following at 28 (version 0) 670 // or 44 (version 1), eg. esds atom of .MP4 files 671 // esds atom: 672 // 28 int atom size (bytes of int size, int type and data) 673 // 32 char[4] atom type (fourc charater code -> esds) 674 // 36 char[] atom data (len=size-8) 675 676 // TODO: fix parsing for files using version 2. 677 version=char2short(trak->stdata,8); 678 if (version > 1) 679 dprintf( "MOV: version %d sound atom may not parse correctly!\n", version); 680 trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; 681 682 /* I can't find documentation, but so far this is the case. -Corey */ 683 switch (char2short(trak->stdata,16)) { 684 case 1: 685 trak->nchannels = 1; break; 686 case 2: 687 trak->nchannels = 2; break; 688 case 3: 689 trak->nchannels = 6; break; 690 default: 691 dprintf( 692 "MOV: unable to determine audio channels, assuming 2 (got %d)\n", 693 char2short(trak->stdata,16)); 694 trak->nchannels = 2; 695 } 696 sh->channels = trak->nchannels; 697 698 /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n", 699 trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur, 700 trak->durmap[0].num, trak->timescale/trak->durmap[0].dur, 701 char2short(trak->stdata,24)/trak->durmap[0].dur);*/ 702 sh->samplerate=char2short(trak->stdata,24); 703 if((sh->samplerate < 7000) && trak->durmap) { 704 switch(char2short(trak->stdata,24)/trak->durmap[0].dur) { 705 // TODO: add more cases. 706 case 31: 707 sh->samplerate = 32000; break; 708 case 43: 709 sh->samplerate = 44100; break; 710 case 47: 711 sh->samplerate = 48000; break; 712 default: 713 dprintf( 714 "MOV: unable to determine audio samplerate, " 715 "assuming 44.1kHz (got %d)\n", 716 char2short(trak->stdata,24)/trak->durmap[0].dur); 717 sh->samplerate = 44100; 718 } 719 } 720 } 721 dprintf( "Audio bits: %d chans: %d rate: %d\n", 722 sh->samplesize*8,sh->channels,sh->samplerate); 723 724 if(trak->stdata_len >= 44 && trak->stdata[9]>=1){ 725 dprintf("Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n", 726 char2int(trak->stdata,28), 727 char2int(trak->stdata,32), 728 char2int(trak->stdata,36), 729 char2int(trak->stdata,40)); 730 if(trak->stdata_len>=44+8){ 731 int len=char2int(trak->stdata,44); 732 int fcc=char2int(trak->stdata,48); 733 // we have extra audio headers!!! 734 dprintf("Audio extra header: len=%d fcc=0x%X\n",len,fcc); 735 if((len >= 4) && 736 (char2int(trak->stdata,52) >= 12) && 737 (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) { 738 switch(char2int(trak->stdata,52+8)) { 739 case MOV_FOURCC('a','l','a','c'): 740 if (len >= 36 + char2int(trak->stdata,52)) { 741 sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); 742 dprintf( "MOV: Found alac atom (%d)!\n", sh->codecdata_len); 743 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 744 memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); 745 } 746 break; 747 case MOV_FOURCC('i','n','2','4'): 748 case MOV_FOURCC('i','n','3','2'): 749 case MOV_FOURCC('f','l','3','2'): 750 case MOV_FOURCC('f','l','6','4'): 751 if ((len >= 22) && 752 (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) && 753 (char2short(trak->stdata,52+20))) { 754 sh->format=char2int(trak->stdata,52+8); 755 dprintf( "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format); 756 } 757 break; 758 default: 759 if (len > 8 && len + 44 <= trak->stdata_len) { 760 sh->codecdata_len = len-8; 761 sh->codecdata = trak->stdata+44+8; 762 } 763 } 764 } else { 765 if (len > 8 && len + 44 <= trak->stdata_len) { 766 sh->codecdata_len = len-8; 767 sh->codecdata = trak->stdata+44+8; 768 } 769 } 770 } 771 } 772 773 switch (version) { 774 case 0: 775 adjust = 0; break; 776 case 1: 777 adjust = 48; break; 778 case 2: 779 adjust = 68; break; 780 default: 781 dprintf( "MOV: unknown sound atom version (%d); may not work!\n", version); 782 adjust = 68; 783 } 784 if (trak->stdata_len >= 36 + adjust) { 785 int atom_len = char2int(trak->stdata,28+adjust); 786 switch(char2int(trak->stdata,32+adjust)) { // atom type 787 case MOV_FOURCC('e','s','d','s'): { 788 dprintf( "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); 789 if(atom_len > 8) { 790 esds_t esds; 791 if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { 792 793 sh->i_bps = esds.avgBitrate/8; 794 795 // printf("######## audio format = %d ########\n",esds.objectTypeId); 796 if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) 797 sh->format=0x55; // .mp3 798 799 // dump away the codec specific configuration for the AAC decoder 800 if(esds.decoderConfigLen){ 801 if( (esds.decoderConfig[0]>>3) == 29 ) 802 sh->format = 0x1d61346d; // request multi-channel mp3 decoder 803 sh->codecdata_len = esds.decoderConfigLen; 804 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 805 memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); 806 } 807 } 808 mp4_free_esds(&esds); // freeup esds mem 809 #if 0 810 { FILE* f=fopen("esds.dat","wb"); 811 fwrite(&trak->stdata[36],atom_len-8,1,f); 812 fclose(f); } 813 #endif 814 } 815 } break; 816 case MOV_FOURCC('a','l','a','c'): { 817 dprintf( "MOV: Found alac atom (%d)!\n", atom_len); 818 if(atom_len > 8) { 819 // copy all the atom (not only payload) for lavc alac decoder 820 sh->codecdata_len = atom_len; 821 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 822 memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); 823 } 824 } break; 825 case MOV_FOURCC('d','a','m','r'): 826 dprintf( "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); 827 if (atom_len>14) { 828 dprintf( "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]); 829 dprintf( "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]); 830 dprintf( "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]); 831 } 832 break; 833 default: 834 dprintf( "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", 835 trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], 836 atom_len); 837 } 838 } 839 dprintf( "Fourcc: %.4s\n",(char *)&trak->fourcc); 840 #if 0 841 { FILE* f=fopen("stdata.dat","wb"); 842 fwrite(trak->stdata,trak->stdata_len,1,f); 843 fclose(f); } 844 { FILE* f=fopen("tkdata.dat","wb"); 845 fwrite(trak->tkdata,trak->tkdata_len,1,f); 846 fclose(f); } 847 #endif 848 // Emulate WAVEFORMATEX struct: 849 sh->wf=malloc(sizeof(WAVEFORMATEX)); 850 memset(sh->wf,0,sizeof(WAVEFORMATEX)); 851 sh->wf->nChannels=sh->channels; 852 sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; 853 // sh->wf->nSamplesPerSec=trak->timescale; 854 sh->wf->nSamplesPerSec=sh->samplerate; 855 if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ 856 //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 857 sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* 858 char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) 859 /char2int(trak->stdata,28); 860 sh->wf->nBlockAlign=char2int(trak->stdata,36); 861 } else { 862 sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; 863 // workaround for ms11 ima4 864 if (sh->format == 0x1100736d && trak->stdata_len >= 36) 865 sh->wf->nBlockAlign=char2int(trak->stdata,36); 866 } 867 // Selection: 868 // if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ 869 // // (auto)selected audio track: 870 // demuxer->audio->id=priv->track_db; 871 // demuxer->audio->sh=sh; sh->ds=demuxer->audio; 872 // } 873 break; 874 } 875 case MOV_TRAK_VIDEO: { 876 int i, entry; 877 int flag, start, count_flag, end, palette_count, gray; 878 int hdr_ptr = 76; // the byte just after depth 879 unsigned char *palette_map; 880 sh_video_t* sh=new_sh_video(demuxer,priv->track_db); 881 int depth; 882 sh->format=trak->fourcc; 883 884 if (trak->stdata_len < 78) { 885 dprintf("MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", 886 trak->stdata_len); 887 break; 888 } 889 depth = trak->stdata[75] | (trak->stdata[74] << 8); 890 // stdata[]: 891 // 8 short version 892 // 10 short revision 893 // 12 int vendor_id 894 // 16 int temporal_quality 895 // 20 int spatial_quality 896 // 24 short width 897 // 26 short height 898 // 28 int h_dpi 899 // 32 int v_dpi 900 // 36 int 0 901 // 40 short frames_per_sample 902 // 42 char[4] compressor_name 903 // 74 short depth 904 // 76 short color_table_id 905 // additional atoms may follow, 906 // eg esds atom from .MP4 files 907 // 78 int atom size 908 // 82 char[4] atom type 909 // 86 ... atom data 910 911 { ImageDescription* id=malloc(8+trak->stdata_len); // safe 912 trak->desc=id; 913 id->idSize=8+trak->stdata_len; 914 // id->cType=bswap_32(trak->fourcc); 915 id->cType=le2me_32(trak->fourcc); 916 id->version=char2short(trak->stdata,8); 917 id->revisionLevel=char2short(trak->stdata,10); 918 id->vendor=char2int(trak->stdata,12); 919 id->temporalQuality=char2int(trak->stdata,16); 920 id->spatialQuality=char2int(trak->stdata,20); 921 id->width=char2short(trak->stdata,24); 922 id->height=char2short(trak->stdata,26); 923 id->hRes=char2int(trak->stdata,28); 924 id->vRes=char2int(trak->stdata,32); 925 id->dataSize=char2int(trak->stdata,36); 926 id->frameCount=char2short(trak->stdata,40); 927 memcpy(&id->name,trak->stdata+42,32); 928 id->depth=char2short(trak->stdata,74); 929 id->clutID=char2short(trak->stdata,76); 930 if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); 931 sh->ImageDesc=id; 932 #if 0 933 { FILE *f=fopen("ImageDescription","wb"); 934 fwrite(id,id->idSize,1,f); 935 fclose(f); 936 } 937 #endif 938 } 939 940 if(trak->stdata_len >= 86) { // extra atoms found 941 int pos=78; 942 int atom_len; 943 while(pos+8<=trak->stdata_len && 944 (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ 945 switch(char2int(trak->stdata,pos+4)) { // switch atom type 946 case MOV_FOURCC('g','a','m','a'): 947 // intfp with gamma value at which movie was captured 948 // can be used to gamma correct movie display 949 dprintf( "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", 950 atom_len); 951 break; 952 case MOV_FOURCC('f','i','e','l'): 953 // 2 char-values (8bit int) that specify field handling 954 // see the Apple's QuickTime Fileformat PDF for more info 955 dprintf( "MOV: Found unsupported Field-Handling movie atom (%d)!\n", 956 atom_len); 957 break; 958 case MOV_FOURCC('m','j','q','t'): 959 // Motion-JPEG default quantization table 960 dprintf( "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n", 961 atom_len); 962 break; 963 case MOV_FOURCC('m','j','h','t'): 964 // Motion-JPEG default huffman table 965 dprintf( "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n", 966 atom_len); 967 break; 968 case MOV_FOURCC('e','s','d','s'): 969 // MPEG4 Elementary Stream Descriptor header 970 dprintf( "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len); 971 // add code here to save esds header of length atom_len-8 972 // beginning at stdata[86] to some variable to pass it 973 // on to the decoder ::atmos 974 if(atom_len > 8) { 975 esds_t esds; 976 if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) { 977 978 if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain || 979 esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial || 980 esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422) 981 sh->format=mmioFOURCC('m', 'p', 'g', '2'); 982 else if(esds.objectTypeId==MP4OTI_MPEG1Visual) 983 sh->format=mmioFOURCC('m', 'p', 'g', '1'); 984 985 // dump away the codec specific configuration for the AAC decoder 986 trak->stream_header_len = esds.decoderConfigLen; 987 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 988 memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len); 989 } 990 mp4_free_esds(&esds); // freeup esds mem 991 } 992 break; 993 case MOV_FOURCC('a','v','c','C'): 994 // AVC decoder configuration record 995 dprintf( "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); 996 if(atom_len > 8) { 997 int i, poffs, cnt; 998 // Parse some parts of avcC, just for fun :) 999 // real parsing is done by avc1 decoder 1000 dprintf( "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); 1001 if (*(trak->stdata+pos+8) != 1) 1002 dprintf( "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); 1003 dprintf( "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); 1004 dprintf( "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); 1005 dprintf( "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); 1006 dprintf( "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1); 1007 dprintf( "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); 1008 poffs = pos + 14; 1009 for (i = 0; i < cnt; i++) { 1010 dprintf( "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1011 poffs += BE_16(trak->stdata+poffs) + 2; 1012 } 1013 dprintf( "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); 1014 poffs++; 1015 for (i = 0; i < cnt; i++) { 1016 dprintf( "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1017 poffs += BE_16(trak->stdata+poffs) + 2; 1018 } 1019 // Copy avcC for the AVC decoder 1020 // This data will be put in extradata below, where BITMAPINFOHEADER is created 1021 trak->stream_header_len = atom_len-8; 1022 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1023 memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); 1024 } 1025 break; 1026 case MOV_FOURCC('d','2','6','3'): 1027 dprintf( "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len); 1028 if (atom_len>10) 1029 dprintf( "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]); 1030 break; 1031 case 0: 1032 break; 1033 default: 1034 dprintf( "MOV: Found unknown movie atom %c%c%c%c (%d)!\n", 1035 trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7], 1036 atom_len); 1037 } 1038 if(atom_len<8) break; 1039 pos+=atom_len; 1040 // printf("pos=%d max=%d\n",pos,trak->stdata_len); 1041 } 1042 } 1043 sh->fps=trak->timescale/ 1044 ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1); 1045 sh->frametime=1.0f/sh->fps; 1046 1047 sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8); 1048 sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8); 1049 // if image size is zero, fallback to display size 1050 if(!sh->disp_w && !sh->disp_h) { 1051 sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); 1052 sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); 1053 } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){ 1054 // codec and display width differ... use display one for aspect 1055 sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8); 1056 sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8); 1057 } 1058 1059 if(depth>32+8) printf("*** depth = 0x%X\n",depth); 1060 1061 // palettized? 1062 gray = 0; 1063 if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale 1064 if ((depth == 2) || (depth == 4) || (depth == 8)) 1065 palette_count = (1 << depth); 1066 else 1067 palette_count = 0; 1068 1069 // emulate BITMAPINFOHEADER: 1070 if (palette_count) 1071 { 1072 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1073 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1074 sh->bih->biSize=40 + palette_count * 4; 1075 // fetch the relevant fields 1076 flag = BE_16(&trak->stdata[hdr_ptr]); 1077 hdr_ptr += 2; 1078 start = BE_32(&trak->stdata[hdr_ptr]); 1079 hdr_ptr += 4; 1080 count_flag = BE_16(&trak->stdata[hdr_ptr]); 1081 hdr_ptr += 2; 1082 end = BE_16(&trak->stdata[hdr_ptr]); 1083 hdr_ptr += 2; 1084 palette_map = (unsigned char *)sh->bih + 40; 1085 dprintf( "Allocated %d entries for palette\n", 1086 palette_count); 1087 dprintf( "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n", 1088 start, end, count_flag, flag); 1089 1090 /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/ 1091 1092 // load default palette 1093 if (flag & 0x08) 1094 { 1095 if (gray) 1096 { 1097 dprintf( "Using default QT grayscale palette\n"); 1098 if (palette_count == 16) 1099 memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4); 1100 else if (palette_count == 256) { 1101 memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4); 1102 if (trak->fourcc == mmioFOURCC('c','v','i','d')) { 1103 int i; 1104 // Hack for grayscale CVID, negative palette 1105 // If you have samples where this is not required contact me (rxt) 1106 dprintf( "MOV: greyscale cvid with default palette," 1107 " enabling negative palette hack.\n"); 1108 for (i = 0; i < 256 * 4; i++) 1109 palette_map[i] = palette_map[i] ^ 0xff; 1110 } 1111 } 1112 } 1113 else 1114 { 1115 dprintf( "Using default QT colour palette\n"); 1116 if (palette_count == 4) 1117 memcpy(palette_map, qt_default_palette_4, 4 * 4); 1118 else if (palette_count == 16) 1119 memcpy(palette_map, qt_default_palette_16, 16 * 4); 1120 else if (palette_count == 256) 1121 memcpy(palette_map, qt_default_palette_256, 256 * 4); 1122 } 1123 } 1124 // load palette from file 1125 else 1126 { 1127 dprintf( "Loading palette from file\n"); 1128 for (i = start; i <= end; i++) 1129 { 1130 entry = BE_16(&trak->stdata[hdr_ptr]); 1131 hdr_ptr += 2; 1132 // apparently, if count_flag is set, entry is same as i 1133 if (count_flag & 0x8000) 1134 entry = i; 1135 // only care about top 8 bits of 16-bit R, G, or B value 1136 if (entry <= palette_count && entry >= 0) 1137 { 1138 palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0]; 1139 palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2]; 1140 palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4]; 1141 dprintf("QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n", 1142 entry, palette_count, 1143 palette_map[entry * 4 + 2], 1144 palette_map[entry * 4 + 1], 1145 palette_map[entry * 4 + 0]); 1146 } 1147 else 1148 dprintf( "QT palette: skipped entry (out of count): %d of %d\n", 1149 entry, palette_count); 1150 hdr_ptr += 6; 1151 } 1152 } 1153 } 1154 else 1155 { 1156 if (trak->fourcc == mmioFOURCC('a','v','c','1')) { 1157 if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADERw)) { 1158 dprintf("Invalid extradata size %d, skipping\n"); 1159 trak->stream_header_len = 0; 1160 } 1161 1162 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1163 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1164 sh->bih->biSize=40 + trak->stream_header_len; 1165 memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len); 1166 free (trak->stream_header); 1167 trak->stream_header_len = 0; 1168 trak->stream_header = NULL; 1169 } else { 1170 sh->bih=malloc(sizeof(BITMAPINFOHEADERw)); 1171 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw)); 1172 sh->bih->biSize=40; 1173 } 1174 } 1175 sh->bih->biWidth=sh->disp_w; 1176 sh->bih->biHeight=sh->disp_h; 1177 sh->bih->biPlanes=0; 1178 sh->bih->biBitCount=depth; 1179 sh->bih->biCompression=trak->fourcc; 1180 sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; 1181 1182 dprintf( "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount); 1183 if(trak->tkdata_len>81) 1184 dprintf( "Display size: %d x %d\n", 1185 trak->tkdata[77]|(trak->tkdata[76]<<8), 1186 trak->tkdata[81]|(trak->tkdata[80]<<8)); 1187 dprintf( "Fourcc: %.4s Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43); 1188 1189 // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ 1190 // // (auto)selected video track: 1191 // demuxer->video->id=priv->track_db; 1192 // demuxer->video->sh=sh; sh->ds=demuxer->video; 1193 // } 1194 break; 1195 } 1196 case MOV_TRAK_GENERIC: 1197 dprintf( "Generic track - not completely understood! (id: %d)\n", 1198 trak->id); 1199 /* XXX: Also this contains the FLASH data */ 1200 1201 #if 0 1202 { 1203 int pos = stream_tell(demuxer->stream); 1204 int i; 1205 int fd; 1206 char name[20]; 1207 1208 for (i=0; i<trak->samples_size; i++) 1209 { 1210 char buf[trak->samples[i].size]; 1211 stream_seek(demuxer->stream, trak->samples[i].pos); 1212 snprintf((char *)&name[0], 20, "samp%d", i); 1213 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1214 stream_read(demuxer->stream, &buf[0], trak->samples[i].size); 1215 write(fd, &buf[0], trak->samples[i].size); 1216 close(fd); 1217 } 1218 for (i=0; i<trak->chunks_size; i++) 1219 { 1220 char buf[trak->length]; 1221 stream_seek(demuxer->stream, trak->chunks[i].pos); 1222 snprintf((char *)&name[0], 20, "chunk%d", i); 1223 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1224 stream_read(demuxer->stream, &buf[0], trak->length); 1225 write(fd, &buf[0], trak->length); 1226 close(fd); 1227 } 1228 if (trak->samplesize > 0) 1229 { 1230 char *buf; 1231 1232 buf = malloc(trak->samplesize); 1233 stream_seek(demuxer->stream, trak->chunks[0].pos); 1234 snprintf((char *)&name[0], 20, "trak%d", trak->id); 1235 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1236 stream_read(demuxer->stream, buf, trak->samplesize); 1237 write(fd, buf, trak->samplesize); 1238 close(fd); 1239 } 1240 stream_seek(demuxer->stream, pos); 1241 } 1242 #endif 1243 break; 1244 default: 1245 dprintf( "Unknown track type found (type: %d)\n", trak->type); 1246 break; 1247 } 1248 dprintf( "--------------\n"); 1249 priv->track_db++; 1250 trak=NULL; 1251 break; 1252 } 1253 #ifndef HAVE_ZLIB 1254 case MOV_FOURCC('c','m','o','v'): { 1255 dprintf("MOV: got compressed header but have no zlib\n"); 1256 return; 1257 } 1258 #else 1259 case MOV_FOURCC('m','o','o','v'): 1260 case MOV_FOURCC('c','m','o','v'): { 1261 // dprintf(MSGTR_MOVcomprhdr); 1262 lschunks(demuxer,level+1,pos+len,NULL); 1263 break; 1264 } 1265 case MOV_FOURCC('d','c','o','m'): { 1266 // int temp=stream_read_dword(demuxer->stream); 1267 unsigned int algo=be2me_32(stream_read_dword(demuxer->stream)); 1268 dprintf( "Compressed header uses %.4s algo!\n",(char *)&algo); 1269 break; 1270 } 1271 case MOV_FOURCC('c','m','v','d'): { 1272 // int temp=stream_read_dword(demuxer->stream); 1273 unsigned int moov_sz=stream_read_dword(demuxer->stream); 1274 unsigned int cmov_sz=len-4; 1275 unsigned char* cmov_buf; 1276 unsigned char* moov_buf; 1277 int zret; 1278 z_stream zstrm; 1279 stream_t* backup; 1280 1281 if (moov_sz > 0xffffffff - 16) { 1282 dprintf("Invalid cmvd atom size %d\n", moov_sz); 580 if(pos>=endpos) return; // END 581 len=stream_read_dword(demuxer->stream); 582 // printf("len==%d\n",len); 583 if(len<8) return; // error 584 len-=8; 585 id=stream_read_dword(demuxer->stream); 586 // 587 dprintf("lschunks %.4s %d\n",(char *)&id,(int)len); 588 // 589 if(trak){ 590 if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0) 591 return; 592 } else { /* not in track */ 593 switch(id) { 594 case MOV_FOURCC('m','v','h','d'): { 595 int version = stream_read_char(demuxer->stream); 596 stream_skip(demuxer->stream, (version == 1) ? 19 : 11); 597 priv->timescale=stream_read_dword(demuxer->stream); 598 if (version == 1) 599 priv->duration=stream_read_qword(demuxer->stream); 600 else 601 priv->duration=stream_read_dword(demuxer->stream); 602 dprintf("MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len, 603 (int)priv->timescale,(int)priv->duration); 1283 604 break; 1284 605 } 1285 cmov_buf=malloc(cmov_sz); 1286 moov_buf=malloc(moov_sz+16); 1287 dprintf( "Compressed header size: %d / %d\n",cmov_sz,moov_sz); 1288 1289 stream_read(demuxer->stream,cmov_buf,cmov_sz); 1290 1291 zstrm.zalloc = (alloc_func)0; 1292 zstrm.zfree = (free_func)0; 1293 zstrm.opaque = (voidpf)0; 1294 zstrm.next_in = cmov_buf; 1295 zstrm.avail_in = cmov_sz; 1296 zstrm.next_out = moov_buf; 1297 zstrm.avail_out = moov_sz; 1298 1299 zret = inflateInit(&zstrm); 1300 if (zret != Z_OK) 1301 { dprintf( "QT cmov: inflateInit err %d\n",zret); 1302 return; 1303 } 1304 zret = inflate(&zstrm, Z_NO_FLUSH); 1305 if ((zret != Z_OK) && (zret != Z_STREAM_END)) 1306 { dprintf( "QT cmov inflate: ERR %d\n",zret); 1307 return; 1308 } 606 case MOV_FOURCC('t','r','a','k'): { 607 // if(trak) printf("MOV: Warning! trak in trak?\n"); 608 if(priv->track_db>=MOV_MAX_TRACKS){ 609 dprintf("MOV: too may tracks\n"); 610 return; 611 } 612 if(!priv->track_db) dprintf( "--------------\n"); 613 trak=malloc(sizeof(mov_track_t)); 614 memset(trak,0,sizeof(mov_track_t)); 615 dprintf("MOV: Track #%d:\n",priv->track_db); 616 trak->id=priv->track_db; 617 priv->tracks[priv->track_db]=trak; 618 lschunks(demuxer,level+1,pos+len,trak); 619 mov_build_index(trak,priv->timescale); 620 switch(trak->type){ 621 case MOV_TRAK_AUDIO: { 1309 622 #if 0 1310 else { 1311 FILE *DecOut; 1312 DecOut = fopen("Out.bin", "w"); 1313 fwrite(moov_buf, 1, moov_sz, DecOut); 1314 fclose(DecOut); 1315 } 623 struct { 624 int16_t version; // 0 or 1 (version 1 is qt3.0+) 625 int16_t revision; // 0 626 int32_t vendor_id; // 0 627 int16_t channels; // 1 or 2 (Mono/Stereo) 628 int16_t samplesize; // 8 or 16 (8Bit/16Bit) 629 int16_t compression_id; // if version 0 then 0 630 // if version 1 and vbr then -2 else 0 631 int16_t packet_size; // 0 632 uint16_t sample_rate; // samplerate (Hz) 633 // qt3.0+ (version == 1) 634 uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet 635 // if 0 below three values are also 0 636 uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel 637 uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels 638 // (channels * bytes_per_packet) 639 uint32_t bytes_per_sample; // 0 or size of uncompressed sample 640 // if samples_per_packet and bytes_per_packet are constant (CBR) 641 // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR) 642 // --- 643 // optional additional atom-based fields 644 // ([int32_t size,int32_t type,some data ],repeat) 645 } my_stdata; 1316 646 #endif 1317 if(moov_sz != zstrm.total_out) 1318 dprintf( "Warning! moov size differs cmov: %d zlib: %ld\n",moov_sz,zstrm.total_out); 1319 zret = inflateEnd(&zstrm); 1320 1321 backup=demuxer->stream; 1322 demuxer->stream=new_memory_stream(moov_buf,moov_sz); 1323 stream_skip(demuxer->stream,8); 1324 lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' 1325 //free_stream(demuxer->stream); 1326 demuxer->stream=backup; 1327 free(cmov_buf); 1328 free(moov_buf); 1329 break; 1330 } 647 int version, adjust; 648 int is_vorbis = 0; 649 sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); 650 sh->format=trak->fourcc; 651 652 // crude audio delay from editlist0 hack ::atm 653 if(trak->editlist_size>=1) { 654 if(trak->editlist[0].pos == -1) { 655 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 656 dprintf("MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay); 657 } 658 } 659 660 switch( sh->format ) { 661 case 0x726D6173: /* samr */ 662 /* amr narrowband */ 663 trak->samplebytes=sh->samplesize=1; 664 trak->nchannels=sh->channels=1; 665 sh->samplerate=8000; 666 break; 667 668 case 0x62776173: /* sawb */ 669 /* amr wideband */ 670 trak->samplebytes=sh->samplesize=1; 671 trak->nchannels=sh->channels=1; 672 sh->samplerate=16000; 673 break; 674 675 default: 676 677 // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit 678 // XXX: 32bit fixed point numbers (intfp) are only 2 Byte! 679 // short values are usually one byte leftpadded by zero 680 // int values are usually two byte leftpadded by zero 681 // stdata[]: 682 // 8 short version 683 // 10 short revision 684 // 12 int vendor_id 685 // 16 short channels 686 // 18 short samplesize 687 // 20 short compression_id 688 // 22 short packet_size (==0) 689 // 24 intfp sample_rate 690 // (26 short) unknown (==0) 691 // ---- qt3.0+ (version>=1) 692 // 28 int samples_per_packet 693 // 32 int bytes_per_packet 694 // 36 int bytes_per_frame 695 // 40 int bytes_per_sample 696 // there may be additional atoms following at 28 (version 0) 697 // or 44 (version 1), eg. esds atom of .MP4 files 698 // esds atom: 699 // 28 int atom size (bytes of int size, int type and data) 700 // 32 char[4] atom type (fourc charater code -> esds) 701 // 36 char[] atom data (len=size-8) 702 703 // TODO: fix parsing for files using version 2. 704 version=char2short(trak->stdata,8); 705 if (version > 1) 706 dprintf( "MOV: version %d sound atom may not parse correctly!\n", version); 707 trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; 708 709 /* I can't find documentation, but so far this is the case. -Corey */ 710 switch (char2short(trak->stdata,16)) { 711 case 1: 712 trak->nchannels = 1; break; 713 case 2: 714 trak->nchannels = 2; break; 715 case 3: 716 trak->nchannels = 6; break; 717 default: 718 dprintf( 719 "MOV: unable to determine audio channels, assuming 2 (got %d)\n", 720 char2short(trak->stdata,16)); 721 trak->nchannels = 2; 722 } 723 sh->channels = trak->nchannels; 724 725 /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n", 726 trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur, 727 trak->durmap[0].num, trak->timescale/trak->durmap[0].dur, 728 char2short(trak->stdata,24)/trak->durmap[0].dur);*/ 729 sh->samplerate=char2short(trak->stdata,24); 730 if((sh->samplerate < 7000) && trak->durmap) { 731 switch(char2short(trak->stdata,24)/trak->durmap[0].dur) { 732 // TODO: add more cases. 733 case 31: 734 sh->samplerate = 32000; break; 735 case 43: 736 sh->samplerate = 44100; break; 737 case 47: 738 sh->samplerate = 48000; break; 739 default: 740 dprintf( 741 "MOV: unable to determine audio samplerate, " 742 "assuming 44.1kHz (got %d)\n", 743 char2short(trak->stdata,24)/trak->durmap[0].dur); 744 sh->samplerate = 44100; 745 } 746 } 747 } 748 dprintf( "Audio bits: %d chans: %d rate: %d\n", 749 sh->samplesize*8,sh->channels,sh->samplerate); 750 751 if(trak->stdata_len >= 44 && trak->stdata[9]>=1){ 752 dprintf("Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n", 753 char2int(trak->stdata,28), 754 char2int(trak->stdata,32), 755 char2int(trak->stdata,36), 756 char2int(trak->stdata,40)); 757 if(trak->stdata_len>=44+8){ 758 int len=char2int(trak->stdata,44); 759 int fcc=char2int(trak->stdata,48); 760 // we have extra audio headers!!! 761 dprintf("Audio extra header: len=%d fcc=0x%X\n",len,fcc); 762 if((len >= 4) && 763 (char2int(trak->stdata,52) >= 12) && 764 (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) { 765 switch(char2int(trak->stdata,52+8)) { 766 case MOV_FOURCC('a','l','a','c'): 767 if (len >= 36 + char2int(trak->stdata,52)) { 768 sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); 769 dprintf( "MOV: Found alac atom (%d)!\n", sh->codecdata_len); 770 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 771 memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); 772 } 773 break; 774 case MOV_FOURCC('i','n','2','4'): 775 case MOV_FOURCC('i','n','3','2'): 776 case MOV_FOURCC('f','l','3','2'): 777 case MOV_FOURCC('f','l','6','4'): 778 if ((len >= 22) && 779 (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) && 780 (char2short(trak->stdata,52+20))) { 781 sh->format=char2int(trak->stdata,52+8); 782 dprintf( "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format); 783 } 784 break; 785 default: 786 if (len > 8 && len + 44 <= trak->stdata_len) { 787 sh->codecdata_len = len-8; 788 sh->codecdata = trak->stdata+44+8; 789 } 790 } 791 } else { 792 if (len > 8 && len + 44 <= trak->stdata_len) { 793 sh->codecdata_len = len-8; 794 sh->codecdata = trak->stdata+44+8; 795 } 796 } 797 } 798 } 799 800 switch (version) { 801 case 0: 802 adjust = 0; break; 803 case 1: 804 adjust = 48; break; 805 case 2: 806 adjust = 68; break; 807 default: 808 dprintf( "MOV: unknown sound atom version (%d); may not work!\n", version); 809 adjust = 68; 810 } 811 if (trak->stdata_len >= 36 + adjust) { 812 int atom_len = char2int(trak->stdata,28+adjust); 813 switch(char2int(trak->stdata,32+adjust)) { // atom type 814 case MOV_FOURCC('e','s','d','s'): { 815 dprintf( "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); 816 if(atom_len > 8) { 817 esds_t esds; 818 if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { 819 /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html), 820 so perform some extra checks to be sure that this is really vorbis audio */ 821 if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8) 822 { 823 //vorbis audio 824 unsigned char *buf[3]; 825 unsigned short sizes[3]; 826 int offset, len, k; 827 unsigned char *ptr = esds.decoderConfig; 828 829 if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout 830 831 offset = len = 0; 832 for(k = 0; k < 3; k++) 833 { 834 sizes[k] = (ptr[offset]<<8) | ptr[offset+1]; 835 len += sizes[k]; 836 offset += 2; 837 if(offset + sizes[k] > esds.decoderConfigLen) 838 { 839 dprintf("MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen); 840 goto quit_vorbis_block; 841 } 842 buf[k] = malloc(sizes[k]); 843 if(!buf[k]) goto quit_vorbis_block; 844 memcpy(buf[k], &ptr[offset], sizes[k]); 845 offset += sizes[k]; 846 } 847 848 sh->codecdata_len = len + len/255 + 64; 849 sh->codecdata = malloc(sh->codecdata_len); 850 ptr = sh->codecdata; 851 852 ptr[0] = 2; 853 offset = 1; 854 offset += store_ughvlc(&ptr[offset], sizes[0]); 855 offset += store_ughvlc(&ptr[offset], sizes[1]); 856 for(k = 0; k < 3; k++) 857 { 858 memcpy(&ptr[offset], buf[k], sizes[k]); 859 offset += sizes[k]; 860 } 861 862 sh->codecdata_len = offset; 863 sh->codecdata = realloc(sh->codecdata, offset); 864 dprintf("demux_mov, vorbis extradata size: %d\n", offset); 865 is_vorbis = 1; 866 quit_vorbis_block: 867 sh->format = mmioFOURCC('v', 'r', 'b', 's'); 868 } 869 sh->i_bps = esds.avgBitrate/8; 870 871 // printf("######## audio format = %d ########\n",esds.objectTypeId); 872 if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) 873 sh->format=0x55; // .mp3 874 if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2 875 sh->format=mmioFOURCC('Q', 'c', 'l', 'p'); 876 trak->nchannels=sh->channels=1; 877 trak->samplebytes=sh->samplesize=1; 878 } 879 880 // dump away the codec specific configuration for the AAC decoder 881 if(esds.decoderConfigLen){ 882 if( (esds.decoderConfig[0]>>3) == 29 ) 883 sh->format = 0x1d61346d; // request multi-channel mp3 decoder 884 if(!is_vorbis) 885 { 886 sh->codecdata_len = esds.decoderConfigLen; 887 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 888 memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); 889 } 890 } 891 } 892 mp4_free_esds(&esds); // freeup esds mem 893 #if 0 894 { FILE* f=fopen("esds.dat","wb"); 895 fwrite(&trak->stdata[36],atom_len-8,1,f); 896 fclose(f); } 1331 897 #endif 1332 case MOV_FOURCC('u','d','t','a'): 1333 { 1334 unsigned int udta_id; 1335 off_t udta_len; 1336 off_t udta_size = len; 1337 1338 dprintf( "mov: user data record found\n"); 1339 dprintf( "Quicktime Clip Info:\n"); 1340 1341 while((len > 8) && (udta_size > 8)) 1342 { 1343 udta_len = stream_read_dword(demuxer->stream); 1344 udta_id = stream_read_dword(demuxer->stream); 1345 udta_size -= 8; 1346 dprintf( "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len); 1347 switch (udta_id) 1348 { 1349 case MOV_FOURCC(0xa9,'c','p','y'): 1350 case MOV_FOURCC(0xa9,'d','a','y'): 1351 case MOV_FOURCC(0xa9,'d','i','r'): 1352 /* 0xa9,'e','d','1' - '9' : edit timestamps */ 1353 case MOV_FOURCC(0xa9,'f','m','t'): 1354 case MOV_FOURCC(0xa9,'i','n','f'): 1355 case MOV_FOURCC(0xa9,'p','r','d'): 1356 case MOV_FOURCC(0xa9,'p','r','f'): 1357 case MOV_FOURCC(0xa9,'r','e','q'): 1358 case MOV_FOURCC(0xa9,'s','r','c'): 1359 case MOV_FOURCC('n','a','m','e'): 1360 case MOV_FOURCC(0xa9,'n','a','m'): 1361 case MOV_FOURCC(0xa9,'A','R','T'): 1362 case MOV_FOURCC(0xa9,'c','m','t'): 1363 case MOV_FOURCC(0xa9,'a','u','t'): 1364 case MOV_FOURCC(0xa9,'s','w','r'): 1365 { 1366 off_t text_len = stream_read_word(demuxer->stream); 1367 char text[text_len+2+1]; 1368 stream_read(demuxer->stream, (char *)&text, text_len+2); 1369 text[text_len+2] = 0x0; 1370 switch(udta_id) 1371 { 1372 case MOV_FOURCC(0xa9,'a','u','t'): 1373 demux_info_add(demuxer, "author", &text[2]); 1374 dprintf( " Author: %s\n", &text[2]); 1375 break; 1376 case MOV_FOURCC(0xa9,'c','p','y'): 1377 demux_info_add(demuxer, "copyright", &text[2]); 1378 dprintf( " Copyright: %s\n", &text[2]); 1379 break; 1380 case MOV_FOURCC(0xa9,'i','n','f'): 1381 dprintf( " Info: %s\n", &text[2]); 1382 break; 1383 case MOV_FOURCC('n','a','m','e'): 1384 case MOV_FOURCC(0xa9,'n','a','m'): 1385 demux_info_add(demuxer, "name", &text[2]); 1386 dprintf( " Name: %s\n", &text[2]); 1387 break; 1388 case MOV_FOURCC(0xa9,'A','R','T'): 1389 dprintf( " Artist: %s\n", &text[2]); 1390 break; 1391 case MOV_FOURCC(0xa9,'d','i','r'): 1392 dprintf( " Director: %s\n", &text[2]); 1393 break; 1394 case MOV_FOURCC(0xa9,'c','m','t'): 1395 demux_info_add(demuxer, "comments", &text[2]); 1396 dprintf( " Comment: %s\n", &text[2]); 1397 break; 1398 case MOV_FOURCC(0xa9,'r','e','q'): 1399 dprintf( " Requirements: %s\n", &text[2]); 1400 break; 1401 case MOV_FOURCC(0xa9,'s','w','r'): 1402 demux_info_add(demuxer, "encoder", &text[2]); 1403 dprintf( " Software: %s\n", &text[2]); 1404 break; 1405 case MOV_FOURCC(0xa9,'d','a','y'): 1406 dprintf( " Creation timestamp: %s\n", &text[2]); 1407 break; 1408 case MOV_FOURCC(0xa9,'f','m','t'): 1409 dprintf( " Format: %s\n", &text[2]); 1410 break; 1411 case MOV_FOURCC(0xa9,'p','r','d'): 1412 dprintf( " Producer: %s\n", &text[2]); 1413 break; 1414 case MOV_FOURCC(0xa9,'p','r','f'): 1415 dprintf( " Performer(s): %s\n", &text[2]); 1416 break; 1417 case MOV_FOURCC(0xa9,'s','r','c'): 1418 dprintf( " Source providers: %s\n", &text[2]); 1419 break; 1420 } 1421 udta_size -= 4+text_len; 1422 break; 1423 } 1424 /* some other shits: WLOC - window location, 1425 LOOP - looping style, 1426 SelO - play only selected frames 1427 AllF - play all frames 1428 */ 1429 case MOV_FOURCC('W','L','O','C'): 1430 case MOV_FOURCC('L','O','O','P'): 1431 case MOV_FOURCC('S','e','l','O'): 1432 case MOV_FOURCC('A','l','l','F'): 1433 default: 1434 { 1435 if( udta_len>udta_size) 1436 udta_len=udta_size; 1437 { 1438 char dump[udta_len-4]; 1439 stream_read(demuxer->stream, (char *)&dump, udta_len-4-4); 1440 udta_size -= udta_len; 1441 } 1442 } 1443 } 1444 } 1445 break; 1446 } /* eof udta */ 1447 default: 1448 id = be2me_32(id); 1449 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 1450 } /* endof switch */ 1451 } /* endof else */ 1452 1453 pos+=len+8; 1454 if(pos>=endpos) break; 1455 if(!stream_seek(demuxer->stream,pos)) break; 898 } 899 } break; 900 case MOV_FOURCC('a','l','a','c'): { 901 dprintf( "MOV: Found alac atom (%d)!\n", atom_len); 902 if(atom_len > 8) { 903 // copy all the atom (not only payload) for lavc alac decoder 904 sh->codecdata_len = atom_len; 905 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 906 memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); 907 } 908 } break; 909 case MOV_FOURCC('d','a','m','r'): 910 dprintf( "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); 911 if (atom_len>14) { 912 dprintf( "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]); 913 dprintf( "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]); 914 dprintf( "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]); 915 } 916 break; 917 default: 918 dprintf( "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", 919 trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], 920 atom_len); 921 } 922 } 923 dprintf( "Fourcc: %.4s\n",(char *)&trak->fourcc); 924 #if 0 925 { FILE* f=fopen("stdata.dat","wb"); 926 fwrite(trak->stdata,trak->stdata_len,1,f); 927 fclose(f); } 928 { FILE* f=fopen("tkdata.dat","wb"); 929 fwrite(trak->tkdata,trak->tkdata_len,1,f); 930 fclose(f); } 931 #endif 932 // Emulate WAVEFORMATEX struct: 933 sh->wf=malloc(sizeof(WAVEFORMATEX) + (is_vorbis ? sh->codecdata_len : 0)); 934 memset(sh->wf,0,sizeof(WAVEFORMATEX)); 935 sh->wf->nChannels=sh->channels; 936 sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; 937 // sh->wf->nSamplesPerSec=trak->timescale; 938 sh->wf->nSamplesPerSec=sh->samplerate; 939 if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ 940 //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 941 sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* 942 char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) 943 /char2int(trak->stdata,28); 944 sh->wf->nBlockAlign=char2int(trak->stdata,36); 945 } else { 946 sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; 947 // workaround for ms11 ima4 948 if (sh->format == 0x1100736d && trak->stdata_len >= 36) 949 sh->wf->nBlockAlign=char2int(trak->stdata,36); 950 } 951 if(is_vorbis && sh->codecdata_len) 952 { 953 memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len); 954 sh->wf->cbSize = sh->codecdata_len; 955 } 956 // Selection: 957 // if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ 958 // // (auto)selected audio track: 959 // demuxer->audio->id=priv->track_db; 960 // demuxer->audio->sh=sh; sh->ds=demuxer->audio; 961 // } 962 break; 963 } 964 case MOV_TRAK_VIDEO: { 965 int i, entry; 966 int flag, start, count_flag, end, palette_count, gray; 967 int hdr_ptr = 76; // the byte just after depth 968 unsigned char *palette_map; 969 sh_video_t* sh=new_sh_video(demuxer,priv->track_db); 970 int depth; 971 sh->format=trak->fourcc; 972 973 // crude video delay from editlist0 hack ::atm 974 if(trak->editlist_size>=1) { 975 if(trak->editlist[0].pos == -1) { 976 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 977 dprintf("MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay); 978 } 979 } 980 981 if (trak->stdata_len < 78) { 982 dprintf("MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", 983 trak->stdata_len); 984 break; 985 } 986 depth = trak->stdata[75] | (trak->stdata[74] << 8); 987 // stdata[]: 988 // 8 short version 989 // 10 short revision 990 // 12 int vendor_id 991 // 16 int temporal_quality 992 // 20 int spatial_quality 993 // 24 short width 994 // 26 short height 995 // 28 int h_dpi 996 // 32 int v_dpi 997 // 36 int 0 998 // 40 short frames_per_sample 999 // 42 char[4] compressor_name 1000 // 74 short depth 1001 // 76 short color_table_id 1002 // additional atoms may follow, 1003 // eg esds atom from .MP4 files 1004 // 78 int atom size 1005 // 82 char[4] atom type 1006 // 86 ... atom data 1007 1008 { ImageDescription* id=malloc(8+trak->stdata_len); // safe 1009 trak->desc=id; 1010 id->idSize=8+trak->stdata_len; 1011 // id->cType=bswap_32(trak->fourcc); 1012 id->cType=le2me_32(trak->fourcc); 1013 id->version=char2short(trak->stdata,8); 1014 id->revisionLevel=char2short(trak->stdata,10); 1015 id->vendor=char2int(trak->stdata,12); 1016 id->temporalQuality=char2int(trak->stdata,16); 1017 id->spatialQuality=char2int(trak->stdata,20); 1018 id->width=char2short(trak->stdata,24); 1019 id->height=char2short(trak->stdata,26); 1020 id->hRes=char2int(trak->stdata,28); 1021 id->vRes=char2int(trak->stdata,32); 1022 id->dataSize=char2int(trak->stdata,36); 1023 id->frameCount=char2short(trak->stdata,40); 1024 memcpy(&id->name,trak->stdata+42,32); 1025 id->depth=char2short(trak->stdata,74); 1026 id->clutID=char2short(trak->stdata,76); 1027 if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); 1028 sh->ImageDesc=id; 1029 #if 0 1030 { FILE *f=fopen("ImageDescription","wb"); 1031 fwrite(id,id->idSize,1,f); 1032 fclose(f); 1033 } 1034 #endif 1035 } 1036 1037 if(trak->stdata_len >= 86) { // extra atoms found 1038 int pos=78; 1039 int atom_len; 1040 while(pos+8<=trak->stdata_len && 1041 (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ 1042 switch(char2int(trak->stdata,pos+4)) { // switch atom type 1043 case MOV_FOURCC('g','a','m','a'): 1044 // intfp with gamma value at which movie was captured 1045 // can be used to gamma correct movie display 1046 dprintf( "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", 1047 atom_len); 1048 break; 1049 case MOV_FOURCC('f','i','e','l'): 1050 // 2 char-values (8bit int) that specify field handling 1051 // see the Apple's QuickTime Fileformat PDF for more info 1052 dprintf( "MOV: Found unsupported Field-Handling movie atom (%d)!\n", 1053 atom_len); 1054 break; 1055 case MOV_FOURCC('m','j','q','t'): 1056 // Motion-JPEG default quantization table 1057 dprintf( "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n", 1058 atom_len); 1059 break; 1060 case MOV_FOURCC('m','j','h','t'): 1061 // Motion-JPEG default huffman table 1062 dprintf( "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n", 1063 atom_len); 1064 break; 1065 case MOV_FOURCC('e','s','d','s'): 1066 // MPEG4 Elementary Stream Descriptor header 1067 dprintf( "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len); 1068 // add code here to save esds header of length atom_len-8 1069 // beginning at stdata[86] to some variable to pass it 1070 // on to the decoder ::atmos 1071 if(atom_len > 8) { 1072 esds_t esds; 1073 if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) { 1074 1075 if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain || 1076 esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial || 1077 esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422) 1078 sh->format=mmioFOURCC('m', 'p', 'g', '2'); 1079 else if(esds.objectTypeId==MP4OTI_MPEG1Visual) 1080 sh->format=mmioFOURCC('m', 'p', 'g', '1'); 1081 1082 // dump away the codec specific configuration for the AAC decoder 1083 trak->stream_header_len = esds.decoderConfigLen; 1084 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1085 memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len); 1086 } 1087 mp4_free_esds(&esds); // freeup esds mem 1088 } 1089 break; 1090 case MOV_FOURCC('a','v','c','C'): 1091 // AVC decoder configuration record 1092 dprintf( "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); 1093 if(atom_len > 8) { 1094 int i, poffs, cnt; 1095 // Parse some parts of avcC, just for fun :) 1096 // real parsing is done by avc1 decoder 1097 dprintf( "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); 1098 if (*(trak->stdata+pos+8) != 1) 1099 dprintf( "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); 1100 dprintf( "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); 1101 dprintf( "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); 1102 dprintf( "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); 1103 dprintf( "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1); 1104 dprintf( "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); 1105 poffs = pos + 14; 1106 for (i = 0; i < cnt; i++) { 1107 dprintf( "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1108 poffs += BE_16(trak->stdata+poffs) + 2; 1109 } 1110 dprintf( "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); 1111 poffs++; 1112 for (i = 0; i < cnt; i++) { 1113 dprintf( "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1114 poffs += BE_16(trak->stdata+poffs) + 2; 1115 } 1116 // Copy avcC for the AVC decoder 1117 // This data will be put in extradata below, where BITMAPINFOHEADER is created 1118 trak->stream_header_len = atom_len-8; 1119 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1120 memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); 1121 } 1122 break; 1123 case MOV_FOURCC('d','2','6','3'): 1124 dprintf( "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len); 1125 if (atom_len>10) 1126 dprintf( "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]); 1127 break; 1128 case 0: 1129 break; 1130 default: 1131 dprintf( "MOV: Found unknown movie atom %c%c%c%c (%d)!\n", 1132 trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7], 1133 atom_len); 1134 } 1135 if(atom_len<8) break; 1136 pos+=atom_len; 1137 // printf("pos=%d max=%d\n",pos,trak->stdata_len); 1138 } 1139 } 1140 sh->fps=trak->timescale/ 1141 ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1); 1142 sh->frametime=1.0f/sh->fps; 1143 1144 sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8); 1145 sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8); 1146 // if image size is zero, fallback to display size 1147 if(!sh->disp_w && !sh->disp_h) { 1148 sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); 1149 sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); 1150 } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){ 1151 // codec and display width differ... use display one for aspect 1152 sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8); 1153 sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8); 1154 } 1155 1156 if(depth>32+8) printf("*** depth = 0x%X\n",depth); 1157 1158 // palettized? 1159 gray = 0; 1160 if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale 1161 if ((depth == 2) || (depth == 4) || (depth == 8)) 1162 palette_count = (1 << depth); 1163 else 1164 palette_count = 0; 1165 1166 // emulate BITMAPINFOHEADER: 1167 if (palette_count) 1168 { 1169 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1170 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1171 sh->bih->biSize=40 + palette_count * 4; 1172 // fetch the relevant fields 1173 flag = BE_16(&trak->stdata[hdr_ptr]); 1174 hdr_ptr += 2; 1175 start = BE_32(&trak->stdata[hdr_ptr]); 1176 hdr_ptr += 4; 1177 count_flag = BE_16(&trak->stdata[hdr_ptr]); 1178 hdr_ptr += 2; 1179 end = BE_16(&trak->stdata[hdr_ptr]); 1180 hdr_ptr += 2; 1181 palette_map = (unsigned char *)sh->bih + 40; 1182 dprintf( "Allocated %d entries for palette\n", 1183 palette_count); 1184 dprintf( "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n", 1185 start, end, count_flag, flag); 1186 1187 /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/ 1188 1189 // load default palette 1190 if (flag & 0x08) 1191 { 1192 if (gray) 1193 { 1194 dprintf( "Using default QT grayscale palette\n"); 1195 if (palette_count == 16) 1196 memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4); 1197 else if (palette_count == 256) { 1198 memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4); 1199 if (trak->fourcc == mmioFOURCC('c','v','i','d')) { 1200 int i; 1201 // Hack for grayscale CVID, negative palette 1202 // If you have samples where this is not required contact me (rxt) 1203 dprintf( "MOV: greyscale cvid with default palette," 1204 " enabling negative palette hack.\n"); 1205 for (i = 0; i < 256 * 4; i++) 1206 palette_map[i] = palette_map[i] ^ 0xff; 1207 } 1208 } 1209 } 1210 else 1211 { 1212 dprintf( "Using default QT colour palette\n"); 1213 if (palette_count == 4) 1214 memcpy(palette_map, qt_default_palette_4, 4 * 4); 1215 else if (palette_count == 16) 1216 memcpy(palette_map, qt_default_palette_16, 16 * 4); 1217 else if (palette_count == 256) 1218 memcpy(palette_map, qt_default_palette_256, 256 * 4); 1219 } 1220 } 1221 // load palette from file 1222 else 1223 { 1224 dprintf( "Loading palette from file\n"); 1225 for (i = start; i <= end; i++) 1226 { 1227 entry = BE_16(&trak->stdata[hdr_ptr]); 1228 hdr_ptr += 2; 1229 // apparently, if count_flag is set, entry is same as i 1230 if (count_flag & 0x8000) 1231 entry = i; 1232 // only care about top 8 bits of 16-bit R, G, or B value 1233 if (entry <= palette_count && entry >= 0) 1234 { 1235 palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0]; 1236 palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2]; 1237 palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4]; 1238 dprintf("QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n", 1239 entry, palette_count, 1240 palette_map[entry * 4 + 2], 1241 palette_map[entry * 4 + 1], 1242 palette_map[entry * 4 + 0]); 1243 } 1244 else 1245 dprintf( "QT palette: skipped entry (out of count): %d of %d\n", 1246 entry, palette_count); 1247 hdr_ptr += 6; 1248 } 1249 } 1250 } 1251 else 1252 { 1253 if (trak->fourcc == mmioFOURCC('a','v','c','1')) { 1254 if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADERw)) { 1255 dprintf("Invalid extradata size %d, skipping\n"); 1256 trak->stream_header_len = 0; 1257 } 1258 1259 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1260 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1261 sh->bih->biSize=40 + trak->stream_header_len; 1262 memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len); 1263 free (trak->stream_header); 1264 trak->stream_header_len = 0; 1265 trak->stream_header = NULL; 1266 } else { 1267 sh->bih=malloc(sizeof(BITMAPINFOHEADERw)); 1268 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw)); 1269 sh->bih->biSize=40; 1270 } 1271 } 1272 sh->bih->biWidth=sh->disp_w; 1273 sh->bih->biHeight=sh->disp_h; 1274 sh->bih->biPlanes=0; 1275 sh->bih->biBitCount=depth; 1276 sh->bih->biCompression=trak->fourcc; 1277 sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; 1278 1279 dprintf( "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount); 1280 if(trak->tkdata_len>81) 1281 dprintf( "Display size: %d x %d\n", 1282 trak->tkdata[77]|(trak->tkdata[76]<<8), 1283 trak->tkdata[81]|(trak->tkdata[80]<<8)); 1284 dprintf( "Fourcc: %.4s Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43); 1285 1286 // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ 1287 // // (auto)selected video track: 1288 // demuxer->video->id=priv->track_db; 1289 // demuxer->video->sh=sh; sh->ds=demuxer->video; 1290 // } 1291 break; 1292 } 1293 case MOV_TRAK_GENERIC: 1294 dprintf( "Generic track - not completely understood! (id: %d)\n", 1295 trak->id); 1296 /* XXX: Also this contains the FLASH data */ 1297 1298 #if 0 1299 { 1300 int pos = stream_tell(demuxer->stream); 1301 int i; 1302 int fd; 1303 char name[20]; 1304 1305 for (i=0; i<trak->samples_size; i++) 1306 { 1307 char buf[trak->samples[i].size]; 1308 stream_seek(demuxer->stream, trak->samples[i].pos); 1309 snprintf((char *)&name[0], 20, "samp%d", i); 1310 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1311 stream_read(demuxer->stream, &buf[0], trak->samples[i].size); 1312 write(fd, &buf[0], trak->samples[i].size); 1313 close(fd); 1314 } 1315 for (i=0; i<trak->chunks_size; i++) 1316 { 1317 char buf[trak->length]; 1318 stream_seek(demuxer->stream, trak->chunks[i].pos); 1319 snprintf((char *)&name[0], 20, "chunk%d", i); 1320 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1321 stream_read(demuxer->stream, &buf[0], trak->length); 1322 write(fd, &buf[0], trak->length); 1323 close(fd); 1324 } 1325 if (trak->samplesize > 0) 1326 { 1327 char *buf; 1328 1329 buf = malloc(trak->samplesize); 1330 stream_seek(demuxer->stream, trak->chunks[0].pos); 1331 snprintf((char *)&name[0], 20, "trak%d", trak->id); 1332 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1333 stream_read(demuxer->stream, buf, trak->samplesize); 1334 write(fd, buf, trak->samplesize); 1335 close(fd); 1336 } 1337 stream_seek(demuxer->stream, pos); 1338 } 1339 #endif 1340 break; 1341 default: 1342 dprintf( "Unknown track type found (type: %d)\n", trak->type); 1343 break; 1344 } 1345 dprintf( "--------------\n"); 1346 priv->track_db++; 1347 trak=NULL; 1348 break; 1349 } 1350 #ifndef HAVE_ZLIB 1351 case MOV_FOURCC('c','m','o','v'): { 1352 dprintf("MOV: got compressed header but have no zlib\n"); 1353 return; 1354 } 1355 #else 1356 case MOV_FOURCC('m','o','o','v'): 1357 case MOV_FOURCC('c','m','o','v'): { 1358 // dprintf(MSGTR_MOVcomprhdr); 1359 lschunks(demuxer,level+1,pos+len,NULL); 1360 break; 1361 } 1362 case MOV_FOURCC('d','c','o','m'): { 1363 // int temp=stream_read_dword(demuxer->stream); 1364 unsigned int algo=be2me_32(stream_read_dword(demuxer->stream)); 1365 dprintf( "Compressed header uses %.4s algo!\n",(char *)&algo); 1366 break; 1367 } 1368 case MOV_FOURCC('c','m','v','d'): { 1369 // int temp=stream_read_dword(demuxer->stream); 1370 unsigned int moov_sz=stream_read_dword(demuxer->stream); 1371 unsigned int cmov_sz=len-4; 1372 unsigned char* cmov_buf; 1373 unsigned char* moov_buf; 1374 int zret; 1375 z_stream zstrm; 1376 stream_t* backup; 1377 1378 if (moov_sz > 0xffffffff - 16) { 1379 dprintf("Invalid cmvd atom size %d\n", moov_sz); 1380 break; 1381 } 1382 cmov_buf=malloc(cmov_sz); 1383 moov_buf=malloc(moov_sz+16); 1384 dprintf( "Compressed header size: %d / %d\n",cmov_sz,moov_sz); 1385 1386 stream_read(demuxer->stream,cmov_buf,cmov_sz); 1387 1388 zstrm.zalloc = (alloc_func)0; 1389 zstrm.zfree = (free_func)0; 1390 zstrm.opaque = (voidpf)0; 1391 zstrm.next_in = cmov_buf; 1392 zstrm.avail_in = cmov_sz; 1393 zstrm.next_out = moov_buf; 1394 zstrm.avail_out = moov_sz; 1395 1396 zret = inflateInit(&zstrm); 1397 if (zret != Z_OK) 1398 { dprintf( "QT cmov: inflateInit err %d\n",zret); 1399 return; 1400 } 1401 zret = inflate(&zstrm, Z_NO_FLUSH); 1402 if ((zret != Z_OK) && (zret != Z_STREAM_END)) 1403 { dprintf( "QT cmov inflate: ERR %d\n",zret); 1404 return; 1405 } 1406 #if 0 1407 else { 1408 FILE *DecOut; 1409 DecOut = fopen("Out.bin", "w"); 1410 fwrite(moov_buf, 1, moov_sz, DecOut); 1411 fclose(DecOut); 1412 } 1413 #endif 1414 if(moov_sz != zstrm.total_out) 1415 dprintf( "Warning! moov size differs cmov: %d zlib: %ld\n",moov_sz,zstrm.total_out); 1416 zret = inflateEnd(&zstrm); 1417 1418 backup=demuxer->stream; 1419 demuxer->stream=new_memory_stream(moov_buf,moov_sz); 1420 stream_skip(demuxer->stream,8); 1421 lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' 1422 //free_stream(demuxer->stream); 1423 demuxer->stream=backup; 1424 free(cmov_buf); 1425 free(moov_buf); 1426 break; 1427 } 1428 #endif 1429 case MOV_FOURCC('u','d','t','a'): 1430 { 1431 unsigned int udta_id; 1432 off_t udta_len; 1433 off_t udta_size = len; 1434 1435 dprintf( "mov: user data record found\n"); 1436 dprintf( "Quicktime Clip Info:\n"); 1437 1438 while((len > 8) && (udta_size > 8)) 1439 { 1440 udta_len = stream_read_dword(demuxer->stream); 1441 udta_id = stream_read_dword(demuxer->stream); 1442 udta_size -= 8; 1443 dprintf( "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len); 1444 switch (udta_id) 1445 { 1446 case MOV_FOURCC(0xa9,'c','p','y'): 1447 case MOV_FOURCC(0xa9,'d','a','y'): 1448 case MOV_FOURCC(0xa9,'d','i','r'): 1449 /* 0xa9,'e','d','1' - '9' : edit timestamps */ 1450 case MOV_FOURCC(0xa9,'f','m','t'): 1451 case MOV_FOURCC(0xa9,'i','n','f'): 1452 case MOV_FOURCC(0xa9,'p','r','d'): 1453 case MOV_FOURCC(0xa9,'p','r','f'): 1454 case MOV_FOURCC(0xa9,'r','e','q'): 1455 case MOV_FOURCC(0xa9,'s','r','c'): 1456 case MOV_FOURCC('n','a','m','e'): 1457 case MOV_FOURCC(0xa9,'n','a','m'): 1458 case MOV_FOURCC(0xa9,'A','R','T'): 1459 case MOV_FOURCC(0xa9,'c','m','t'): 1460 case MOV_FOURCC(0xa9,'a','u','t'): 1461 case MOV_FOURCC(0xa9,'s','w','r'): 1462 { 1463 off_t text_len = stream_read_word(demuxer->stream); 1464 char text[text_len+2+1]; 1465 stream_read(demuxer->stream, (char *)&text, text_len+2); 1466 text[text_len+2] = 0x0; 1467 switch(udta_id) 1468 { 1469 case MOV_FOURCC(0xa9,'a','u','t'): 1470 demux_info_add(demuxer, "author", &text[2]); 1471 dprintf( " Author: %s\n", &text[2]); 1472 break; 1473 case MOV_FOURCC(0xa9,'c','p','y'): 1474 demux_info_add(demuxer, "copyright", &text[2]); 1475 dprintf( " Copyright: %s\n", &text[2]); 1476 break; 1477 case MOV_FOURCC(0xa9,'i','n','f'): 1478 dprintf( " Info: %s\n", &text[2]); 1479 break; 1480 case MOV_FOURCC('n','a','m','e'): 1481 case MOV_FOURCC(0xa9,'n','a','m'): 1482 demux_info_add(demuxer, "name", &text[2]); 1483 dprintf( " Name: %s\n", &text[2]); 1484 break; 1485 case MOV_FOURCC(0xa9,'A','R','T'): 1486 dprintf( " Artist: %s\n", &text[2]); 1487 break; 1488 case MOV_FOURCC(0xa9,'d','i','r'): 1489 dprintf( " Director: %s\n", &text[2]); 1490 break; 1491 case MOV_FOURCC(0xa9,'c','m','t'): 1492 demux_info_add(demuxer, "comments", &text[2]); 1493 dprintf( " Comment: %s\n", &text[2]); 1494 break; 1495 case MOV_FOURCC(0xa9,'r','e','q'): 1496 dprintf( " Requirements: %s\n", &text[2]); 1497 break; 1498 case MOV_FOURCC(0xa9,'s','w','r'): 1499 demux_info_add(demuxer, "encoder", &text[2]); 1500 dprintf( " Software: %s\n", &text[2]); 1501 break; 1502 case MOV_FOURCC(0xa9,'d','a','y'): 1503 dprintf( " Creation timestamp: %s\n", &text[2]); 1504 break; 1505 case MOV_FOURCC(0xa9,'f','m','t'): 1506 dprintf( " Format: %s\n", &text[2]); 1507 break; 1508 case MOV_FOURCC(0xa9,'p','r','d'): 1509 dprintf( " Producer: %s\n", &text[2]); 1510 break; 1511 case MOV_FOURCC(0xa9,'p','r','f'): 1512 dprintf( " Performer(s): %s\n", &text[2]); 1513 break; 1514 case MOV_FOURCC(0xa9,'s','r','c'): 1515 dprintf( " Source providers: %s\n", &text[2]); 1516 break; 1517 } 1518 udta_size -= 4+text_len; 1519 break; 1520 } 1521 /* some other shits: WLOC - window location, 1522 LOOP - looping style, 1523 SelO - play only selected frames 1524 AllF - play all frames 1525 */ 1526 case MOV_FOURCC('W','L','O','C'): 1527 case MOV_FOURCC('L','O','O','P'): 1528 case MOV_FOURCC('S','e','l','O'): 1529 case MOV_FOURCC('A','l','l','F'): 1530 default: 1531 { 1532 if( udta_len>udta_size) 1533 udta_len=udta_size; 1534 { 1535 char dump[udta_len-4]; 1536 stream_read(demuxer->stream, (char *)&dump, udta_len-4-4); 1537 udta_size -= udta_len; 1538 } 1539 } 1540 } 1541 } 1542 break; 1543 } /* eof udta */ 1544 default: 1545 id = be2me_32(id); 1546 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 1547 } /* endof switch */ 1548 } /* endof else */ 1549 1550 pos+=len+8; 1551 if(pos>=endpos) break; 1552 if(!stream_seek(demuxer->stream,pos)) break; 1456 1553 } 1457 1554 } … … 1502 1599 } 1503 1600 case MOV_FOURCC('m','d','h','d'): { 1504 dprintf( "MOV: %*sMedia header!\n", level, ""); 1505 stream_skip(demuxer->stream, 12); 1506 // read timescale 1507 trak->timescale = stream_read_dword(demuxer->stream); 1508 // read length 1509 trak->length = stream_read_dword(demuxer->stream); 1601 dprintf( "MOV: %*sMedia header!\n", level, ""); 1602 int version = stream_read_char(demuxer->stream); 1603 stream_skip(demuxer->stream, (version == 1) ? 19 : 11); 1604 // read timescale 1605 trak->timescale = stream_read_dword(demuxer->stream); 1606 // read length 1607 if (version == 1) 1608 trak->length = stream_read_qword(demuxer->stream); 1609 else 1610 trak->length = stream_read_dword(demuxer->stream); 1510 1611 break; 1511 1612 } … … 1823 1924 demuxer->video->id=-2; 1824 1925 } 1926 } 1927 1928 if(demuxer->video->id<0 && demuxer->audio->id<0) { 1929 /* No AV streams found. Try to find an MPEG stream. */ 1930 for(t_no=0;t_no<priv->track_db;t_no++){ 1931 mov_track_t* trak=priv->tracks[t_no]; 1932 if(trak->media_handler == MOV_FOURCC('M','P','E','G')) { 1933 stream_t *s; 1934 demuxer_t *od; 1935 1936 demuxer->video->id = t_no; 1937 s = new_ds_stream(demuxer->video); 1938 od = demux_open(s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL); 1939 if(od) return new_demuxers_demuxer(od, od, od); 1940 demuxer->video->id = -2; //new linked demuxer couldn't be allocated 1941 break; 1942 } 1943 } 1825 1944 } 1826 1945
Note:
See TracChangeset
for help on using the changeset viewer.