Changeset 242

Show
Ignore:
Timestamp:
01/06/07 00:44:26 (2 years ago)
Author:
dconrad
Message:

Rewrite/cleanup of the Matroska importer
- No longer reads the entire file into memory before processing it
- Imports subtitle tracks that are numerically before video tracks correctly
- Fixes some memory leaks
- Fixes EOF in DataHandlerCallback?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/CommonUtils.c

    r210 r242  
    157157}; 
    158158 
    159 short TwoCharLangCodeToQTLangCode(char *lang) 
     159short ISO639_1ToQTLangCode(const char *lang) 
    160160{ 
    161161        int i; 
     
    170170} 
    171171 
    172 short ThreeCharLangCodeToQTLangCode(char *lang) 
     172short ISO639_2ToQTLangCode(const char *lang) 
    173173{ 
    174174        int i; 
  • trunk/CommonUtils.h

    r210 r242  
    1717 
    1818// ISO 639-1 to language ID expected by SetMediaLanguage 
    19 short TwoCharLangCodeToQTLangCode(char *lang); 
     19short ISO639_1ToQTLangCode(const char *lang); 
    2020 
    2121// ISO 639-2 to language ID expected by SetMediaLanguage 
    22 short ThreeCharLangCodeToQTLangCode(char *lang); 
     22short ISO639_2ToQTLangCode(const char *lang); 
    2323 
    2424/* write the int32_t data to target & then return a pointer which points after that data */ 
  • trunk/DataHandlerCallback.cpp

    r203 r242  
    2222 * 
    2323 */ 
    24  
    25 #include <sstream> 
    2624 
    2725#include "DataHandlerCallback.h" 
     
    5149        this->dataHandler = NULL; 
    5250        mCurrentPosition = 0; 
     51        filesize = 0; 
    5352        this->aMode = aMode; 
    5453         
     
    7877        dataHComponent = NULL; 
    7978        mCurrentPosition = 0; 
     79        filesize = 0; 
    8080        this->aMode = aMode; 
    8181         
     
    8989        err = OpenAComponent(dataHComponent, &dataHandler); 
    9090        if (err) { 
    91                 stringstream Msg; 
    92                 Msg << "Error opening data handler component " << err; 
    93                 throw CRTError(Msg.str()); 
     91                throw CRTError("Error opening data handler component", err); 
    9492        } 
    9593         
    9694        err = DataHSetDataRef(dataHandler, dataRef); 
    9795        if (err) { 
    98                 stringstream Msg; 
    99                 Msg << "Error setting data handler ref " << err; 
    100                 throw CRTError(Msg.str()); 
     96                throw CRTError("Error setting data handler ref", err); 
    10197        } 
    10298         
     
    104100                err = DataHOpenForRead(dataHandler); 
    105101        if (err) { 
    106             stringstream Msg; 
    107             Msg << "Error opening data handler for read " << err; 
    108             throw CRTError(Msg.str()); 
     102            throw CRTError("Error opening data handler for read", err); 
    109103        } 
    110104        } else if (aMode == MODE_WRITE) { 
    111105                err = DataHOpenForWrite(dataHandler); 
    112106        if (err) { 
    113             stringstream Msg; 
    114             Msg << "Error opening data handler for write " << err; 
    115             throw CRTError(Msg.str()); 
     107            throw CRTError("Error opening data handler for write", err); 
    116108        } 
    117109        } else { 
     
    133125uint32 DataHandlerCallback::read(void *Buffer, size_t Size) 
    134126{ 
    135         assert(dataHandler != 0); 
    136          
    137127        ComponentResult err = noErr; 
    138128         
     
    146136         
    147137        if (err) { 
    148                 stringstream Msg; 
    149                 Msg << "Error reading data " << err; 
    150                 throw CRTError(Msg.str(), err); 
     138                throw CRTError("Error reading data", err); 
    151139        } 
    152140        mCurrentPosition += Size; 
     141         
     142        if (mCurrentPosition > filesize) { 
     143                Size -= mCurrentPosition - filesize; 
     144                mCurrentPosition = filesize; 
     145        } 
    153146         
    154147        // does QuickTime tell us how much it's read? 
     
    158151void DataHandlerCallback::setFilePointer(int64 Offset, LIBEBML_NAMESPACE::seek_mode Mode) 
    159152{ 
    160         assert(Offset <= LONG_MAX); 
    161         assert(Offset >= LONG_MIN); 
    162  
    163         assert(Mode==SEEK_CUR||Mode==SEEK_END||Mode==SEEK_SET); 
    164          
    165153        switch ( Mode ) 
    166154        { 
     
    180168size_t DataHandlerCallback::write(const void *Buffer, size_t Size) 
    181169{ 
    182         assert(dataHandler != NULL); 
    183          
    184170        ComponentResult err = noErr; 
    185171         
     
    193179         
    194180        if (err) { 
    195                 stringstream Msg; 
    196                 Msg << "Error writing data " << err; 
    197                 throw CRTError(Msg.str(), err); 
     181                throw CRTError("Error writing data", err); 
    198182        } 
    199183        mCurrentPosition += Size; 
     
    205189uint64 DataHandlerCallback::getFilePointer() 
    206190{ 
    207         assert(dataHandler != NULL); 
    208  
    209191        return mCurrentPosition; 
    210192} 
     
    224206{ 
    225207        ComponentResult err = noErr; 
    226         SInt64 filesize; 
    227208        wide wideFilesize; 
     209         
     210        if (filesize > 0)  
     211                return filesize; 
    228212         
    229213        err = DataHGetFileSize64(dataHandler, &wideFilesize); 
  • trunk/DataHandlerCallback.h

    r203 r242  
    5858        bool supportsWideOffsets; 
    5959        open_mode aMode; 
     60        SInt64 filesize; 
    6061     
    6162public: 
  • trunk/MatroskaCodecIDs.cpp

    r218 r242  
    3030#include "MatroskaCodecIDs.h" 
    3131#include "CommonUtils.h" 
     32#include "Codecprintf.h" 
    3233#include <string> 
    3334 
     
    441442ComponentResult MkvFinishSampleDescription(KaxTrackEntry *tr_entry, SampleDescriptionHandle desc, DescExtDirection dir) 
    442443{ 
    443         switch ((*desc)->dataFormat) { 
    444                 case kH264CodecType: 
    445                         return DescExt_H264(tr_entry, desc, dir); 
    446                          
    447                 case kAudioFormatXiphVorbis: 
    448                         return DescExt_XiphVorbis(tr_entry, desc, dir); 
    449                          
    450                 case kAudioFormatXiphFLAC: 
    451                         return DescExt_XiphFLAC(tr_entry, desc, dir); 
    452                          
    453                 case kSubFormatVobSub: 
    454                         return DescExt_VobSub(tr_entry, desc, dir); 
    455                          
    456                 case kVideoFormatReal5: 
    457                 case kVideoFormatRealG2: 
    458                 case kVideoFormatReal8: 
    459                 case kVideoFormatReal9: 
    460                         return DescExt_Real(tr_entry, desc, dir); 
    461                          
    462                 case kMPEG4VisualCodecType: 
    463                         return DescExt_mp4v(tr_entry, desc, dir); 
    464         } 
    465         return noErr; 
     444        KaxCodecID & tr_codec = GetChild<KaxCodecID>(*tr_entry); 
     445         
     446        string codecString(tr_codec); 
     447         
     448        if (codecString == MKV_V_MS) { 
     449                // BITMAPINFOHEADER is stored in the private data, and some codecs (WMV) 
     450                // need it to decode 
     451                KaxCodecPrivate & codecPrivate = GetChild<KaxCodecPrivate>(*tr_entry); 
     452                 
     453                Handle imgDescExt = NewHandle(codecPrivate.GetSize()); 
     454                memcpy(*imgDescExt, codecPrivate.GetBuffer(), codecPrivate.GetSize()); 
     455                 
     456                AddImageDescriptionExtension((ImageDescriptionHandle) desc, imgDescExt, 'strf'); 
     457                 
     458        } else if (codecString == MKV_V_QT) { 
     459                // This seems to work fine, but there's something it's missing to get the  
     460                // image description to match perfectly (last 2 bytes are different) 
     461                // Figure it out later... 
     462                KaxCodecPrivate & codecPrivate = GetChild<KaxCodecPrivate>(*tr_entry); 
     463                if (codecPrivate.GetSize() < sizeof(ImageDescription)) { 
     464                        Codecprintf(NULL, "MatroskaQT: QuickTime track %hu doesn't have needed stsd data\n",  
     465                                                uint16(tr_entry->TrackNumber())); 
     466                        return -1; 
     467                } 
     468                 
     469                ImageDescriptionHandle imgDesc = (ImageDescriptionHandle) desc; 
     470                SetHandleSize((Handle) imgDesc, codecPrivate.GetSize()); 
     471                memcpy(&(*imgDesc)->cType, codecPrivate.GetBuffer(), codecPrivate.GetSize()); 
     472                // it's stored in big endian, so flip endian to native 
     473                // I think we have to do this, need to check on Intel without them 
     474                (*imgDesc)->idSize = codecPrivate.GetSize(); 
     475                (*imgDesc)->cType = EndianU32_BtoN((*imgDesc)->cType); 
     476                (*imgDesc)->resvd1 = EndianS32_BtoN((*imgDesc)->resvd1); 
     477                (*imgDesc)->resvd2 = EndianS16_BtoN((*imgDesc)->resvd2); 
     478                (*imgDesc)->dataRefIndex = EndianS16_BtoN((*imgDesc)->dataRefIndex); 
     479                (*imgDesc)->version = EndianS16_BtoN((*imgDesc)->version); 
     480                (*imgDesc)->revisionLevel = EndianS16_BtoN((*imgDesc)->revisionLevel); 
     481                (*imgDesc)->vendor = EndianS32_BtoN((*imgDesc)->vendor); 
     482                (*imgDesc)->temporalQuality = EndianU32_BtoN((*imgDesc)->temporalQuality); 
     483                (*imgDesc)->spatialQuality = EndianU32_BtoN((*imgDesc)->spatialQuality); 
     484                (*imgDesc)->width = EndianS16_BtoN((*imgDesc)->width); 
     485                (*imgDesc)->height = EndianS16_BtoN((*imgDesc)->height); 
     486                (*imgDesc)->vRes = EndianS32_BtoN((*imgDesc)->vRes); 
     487                (*imgDesc)->hRes = EndianS32_BtoN((*imgDesc)->hRes); 
     488                (*imgDesc)->dataSize = EndianS32_BtoN((*imgDesc)->dataSize); 
     489                (*imgDesc)->frameCount = EndianS16_BtoN((*imgDesc)->frameCount); 
     490                (*imgDesc)->depth = EndianS16_BtoN((*imgDesc)->depth); 
     491                (*imgDesc)->clutID = EndianS16_BtoN((*imgDesc)->clutID); 
     492#if 0 
     493        } else if (codecString == MKV_V_THEORA) { 
     494                // we need 3 setup packets for the image description extension, but 
     495                // the sample files I muxed have only 2 packets in the Codec Private element. 
     496                // Despite the Matroska specs agreeing with me about the 3 packets. 
     497                // Will figure out later. 
     498        } else if (codecString.compare(0, strlen(MKV_A_AAC), string(MKV_A_AAC)) == 0) { 
     499                // esds extension gives us the channel mapping for AAC 
     500                SoundDescriptionHandle sndDesc = (SoundDescriptionHandle) desc; 
     501                 
     502                KaxCodecPrivate *codecPrivate = FindChild<KaxCodecPrivate>(*tr_entry); 
     503                if (codecPrivate == NULL) 
     504                        return; 
     505                 
     506                Handle sndDescExt = NewHandle(codecPrivate->GetSize()); 
     507                memcpy(*sndDescExt, codecPrivate->GetBuffer(), codecPrivate->GetSize()); 
     508                 
     509                AddSoundDescriptionExtension(sndDesc, sndDescExt, 'esds'); 
     510                 
     511                DisposeHandle((Handle) sndDescExt); 
     512#endif 
     513        } else { 
     514                switch ((*desc)->dataFormat) { 
     515                        case kH264CodecType: 
     516                                return DescExt_H264(tr_entry, desc, dir); 
     517                                 
     518                        case kAudioFormatXiphVorbis: 
     519                                return DescExt_XiphVorbis(tr_entry, desc, dir); 
     520                                 
     521                        case kAudioFormatXiphFLAC: 
     522                                return DescExt_XiphFLAC(tr_entry, desc, dir); 
     523                                 
     524                        case kSubFormatVobSub: 
     525                                return DescExt_VobSub(tr_entry, desc, dir); 
     526                                 
     527                        case kVideoFormatReal5: 
     528                        case kVideoFormatRealG2: 
     529                        case kVideoFormatReal8: 
     530                        case kVideoFormatReal9: 
     531                                return DescExt_Real(tr_entry, desc, dir); 
     532                                 
     533                        case kMPEG4VisualCodecType: 
     534                                return DescExt_mp4v(tr_entry, desc, dir); 
     535                } 
     536        } 
     537        return noErr; 
     538
     539 
     540// some default channel layouts for up to 8 channels 
     541// vorbis and aac should be correct unless extradata specifices something else for aac 
     542static const AudioChannelLayout vorbisChannelLayouts[9] = { 
     543        { 0 }, 
     544        { kAudioChannelLayoutTag_Mono }, 
     545        { kAudioChannelLayoutTag_Stereo }, 
     546        { kAudioChannelLayoutTag_UseChannelBitmap, kAudioChannelBit_Left | kAudioChannelBit_Right | kAudioChannelBit_CenterSurround }, 
     547        { kAudioChannelLayoutTag_Quadraphonic }, 
     548        { kAudioChannelLayoutTag_MPEG_5_0_C }, 
     549        { kAudioChannelLayoutTag_MPEG_5_1_C } 
     550}; 
     551 
     552// these should be the default for the number of channels; esds can specify other mappings 
     553static const AudioChannelLayout aacChannelLayouts[9] = { 
     554        { 0 }, 
     555        { kAudioChannelLayoutTag_Mono }, 
     556        { kAudioChannelLayoutTag_Stereo }, 
     557        { kAudioChannelLayoutTag_MPEG_3_0_B },          // C L R according to wiki.multimedia.cx 
     558        { kAudioChannelLayoutTag_AAC_4_0 }, 
     559        { kAudioChannelLayoutTag_AAC_5_0 }, 
     560        { kAudioChannelLayoutTag_AAC_5_1 }, 
     561        { kAudioChannelLayoutTag_AAC_6_1 }, 
     562        { kAudioChannelLayoutTag_AAC_7_1 } 
     563}; 
     564 
     565static const AudioChannelLayout ac3ChannelLayouts[9] = { 
     566        { 0 }, 
     567        { kAudioChannelLayoutTag_ITU_1_0 }, 
     568        { kAudioChannelLayoutTag_ITU_2_0 }, 
     569        { kAudioChannelLayoutTag_ITU_3_0 }, 
     570        { kAudioChannelLayoutTag_ITU_3_1 }, 
     571        { kAudioChannelLayoutTag_ITU_3_2 }, 
     572        { kAudioChannelLayoutTag_ITU_3_2_1 } 
     573}; 
     574 
     575 
     576AudioChannelLayout GetDefaultChannelLayout(AudioStreamBasicDescription *asbd) 
     577
     578        AudioChannelLayout acl = {0}; 
     579         
     580        if (asbd->mChannelsPerFrame <= 8) { 
     581                switch (asbd->mFormatID) { 
     582                        case kAudioFormatXiphVorbis: 
     583                        case kAudioFormatXiphFLAC:              // FLAC doesn't have official mappings, but the author said Vorbis's were likely to be used 
     584                                acl = vorbisChannelLayouts[asbd->mChannelsPerFrame]; 
     585                                break; 
     586                                 
     587                        case kAudioFormatMPEG4AAC: 
     588                                // TODO: use extradata to make ACL 
     589                                acl = aacChannelLayouts[asbd->mChannelsPerFrame]; 
     590                                break; 
     591                                 
     592                        case kAudioFormatAC3: 
     593                                // TODO: implement channel layout choosing based on an AC3 frame 
     594                                acl = ac3ChannelLayouts[asbd->mChannelsPerFrame]; 
     595                                break; 
     596                } 
     597        } 
     598         
     599        return acl; 
    466600} 
    467601 
     
    480614        return noErr; 
    481615} 
    482  
    483  
    484 short GetTrackLanguage(KaxTrackEntry *tr_entry) { 
    485         KaxTrackLanguage *trLang = FindChild<KaxTrackLanguage>(*tr_entry); 
    486         if (trLang != NULL) { 
    487                 char lang[4]; 
    488                 string langStr(*trLang); 
    489                 strncpy(lang, langStr.c_str(), 3); 
    490                 lang[3] = '\0'; 
    491                  
    492                 return ThreeCharLangCodeToQTLangCode(lang); 
    493         } 
    494         return langUnspecified; 
    495 } 
    496  
    497616 
    498617 
  • trunk/MatroskaCodecIDs.h

    r218 r242  
    5252ComponentResult MkvFinishSampleDescription(KaxTrackEntry *tr_entry, SampleDescriptionHandle desc, DescExtDirection dir); 
    5353ComponentResult MkvFinishASBD(KaxTrackEntry *tr_entry, AudioStreamBasicDescription *asbd); 
    54 short GetTrackLanguage(KaxTrackEntry *tr_entry); 
    5554FourCharCode GetFourCC(KaxTrackEntry *tr_entry); 
     55AudioChannelLayout GetDefaultChannelLayout(AudioStreamBasicDescription *asbd); 
    5656 
    5757#endif 
  • trunk/MatroskaImport.h

    r119 r242  
    2626#define __MATROSKAIMPORT_H__ 
    2727 
     28#include <vector> 
    2829#include <QuickTime/QuickTime.h> 
     30#include "DataHandlerCallback.h" 
    2931 
    30 struct MkvBlock; 
    31 struct KaxPrivate; 
     32#include <ebml/EbmlStream.h> 
     33#include <matroska/KaxSeekHead.h> 
     34#include <matroska/KaxInfo.h> 
     35#include <matroska/KaxTracks.h> 
     36#include <matroska/KaxChapters.h> 
     37#include <matroska/KaxBlock.h> 
    3238 
    33 typedef struct { 
    34         UInt16                                                  trackNumber; 
    35         Track                                                   theTrack; 
    36         Media                                                   theMedia; 
    37         SampleDescriptionHandle                 sampleHdl; 
    38         AudioStreamBasicDescription             asbd; 
    39         UInt64                                                  defaultDuration; 
    40         // this is so the last block of a track that has no DefaultDuration can be imported 
    41         // with the same duration as the preceding block 
    42         // any better solutions? 
    43         UInt64                                                  lastDuration; 
    44         UInt64                                                  uid; 
    45         SInt64                                                  timecodeScale; 
     39using namespace libmatroska; 
     40using namespace std; 
     41 
     42 
     43struct MatroskaFrame { 
     44        TimeValue64             timecode; 
     45//      TimeValue64             duration; 
     46        UInt32                  duration;               // hack so that H.264 tracks kinda work 
     47        SInt64                  offset; 
     48        SInt64                  size; 
     49        short                   flags; 
     50}; 
     51 
     52class MatroskaTrack { 
     53public: 
     54        MatroskaTrack(); 
    4655         
    47         QTMutableSampleTableRef                 sampleTable; 
    48         QTSampleDescriptionID                   qtSampleDesc; 
     56        // retains the sampleTable if it exists, allocates a new SampleDescriptionHandle 
     57        // and copies it if necessary 
     58        MatroskaTrack(const MatroskaTrack &copy); 
     59         
     60        // releases the sampleTable and sample description 
     61        ~MatroskaTrack(); 
     62         
     63        // adds the all the frames in the block group to the sample table if it exists,  
     64        // the media otherwise. If this track type is subtitle, also inserts it into the track. 
     65        void AddBlock(KaxBlockGroup &blockGroup); 
     66         
     67        UInt16                                  number; 
     68        UInt8                                   type; 
     69        Track                                   theTrack; 
     70        Media                                   theMedia; 
     71        SampleDescriptionHandle desc; 
     72        QTMutableSampleTableRef sampleTable; 
     73        QTSampleDescriptionID   qtSampleDesc; 
     74        SInt64                                  timecodeScale; 
     75         
     76private: 
     77        // adds an individual frame from a block group into the sample table if it exists, 
     78        // the media otherwise, and into the track if the track is a subtitle track. 
     79        SInt64 AddFrame(MatroskaFrame &frame); 
     80         
     81        // Since the duration in Matroska files is generally rather unreliable, rely only on 
     82        // the difference in timestamps between two frames. Thus, AddBlock() buffers frames 
     83        // from one block group until the next block group is found to set the duration of the 
     84        // previous ones to be the difference in timestamps. 
     85        vector<MatroskaFrame>   lastFrames; 
     86}; 
     87 
     88 
     89class MatroskaImport { 
     90public: 
     91        // public interface functions, simply called from the C equivalents defined  
     92        // by ComponentDispatchHelper.c and implemented in MatroskaImport.cpp 
     93         
     94        // MatroskaImportOpen() 
     95        MatroskaImport(ComponentInstance self); 
     96         
     97        // MatrosakImportClose() 
     98        ~MatroskaImport(); 
     99         
     100        // MatroskaImportDataRef() 
     101        ComponentResult ImportDataRef(Handle dataRef, OSType dataRefType, Movie theMovie, 
     102                                                                  Track targetTrack, Track *usedTrack, 
     103                                                                  TimeValue atTime, TimeValue *durationAdded, 
     104                                                                  long inFlags, long *outFlags); 
     105         
     106        // MatroskaImportValidateDataRef() 
     107        ComponentResult ValidateDataRef(Handle dataRef, OSType dataRefType, UInt8 *valid); 
     108         
     109        // we need to get our component instance to get our mime type resource 
     110        ComponentInstance Component() { return self; } 
     111         
     112private: 
     113        // open the ioHandler and EBML stream, and read the EBML head to verify it's a matroska file 
     114        // returns true if it's a valid file and false otherwise 
     115        bool OpenFile(); 
     116         
     117        // create all the tracks and their sample descriptions as described by the file header 
     118        // also create chapters if any. Leaves el_l1 pointing to the first cluster, unread. 
     119        void SetupMovie(); 
     120         
     121        // This finds the next level 1 element and both replaces the el_l1 variable with it and 
     122        // returns it. Does not read the data. 
     123        EbmlElement *NextLevel1Element(); 
     124         
     125        // sets up timescale & file name metadata 
     126        void ReadSegmentInfo(KaxInfo &segmentInfo); 
     127         
     128        // sets up all the movie tracks and media 
     129        void ReadTracks(KaxTracks &trackEntries); 
     130         
     131        // Creates a chapter track, but doesn't actually add the chapter reference to the other 
     132        // enabled tracks in case some weird file has this element before the Tracks element 
     133        void ReadChapters(KaxChapters &chapterEntries); 
     134         
     135        // These three are called from ReadTracks to set up a track of the specific type,  
     136        // modifying the MatroskaTrack structure to reflect the newly create track.  
     137        // They return an error if the track couldn't be created or noErr on success. 
     138        ComponentResult AddVideoTrack(KaxTrackEntry &kaxTrack, MatroskaTrack &mkvTrack); 
     139        ComponentResult AddAudioTrack(KaxTrackEntry &kaxTrack, MatroskaTrack &mkvTrack); 
     140        ComponentResult AddSubtitleTrack(KaxTrackEntry &kaxTrack, MatroskaTrack &mkvTrack); 
     141         
     142        // this is called recursively to add only the leaves on the chapter tree to  
     143        // chapter track, since QT doesn't support chapter nesting. 
     144        void AddChapterAtom(KaxChapterAtom *atom, Track chapterTrack); 
     145         
    49146                 
    50         UInt8                                                   trackType; 
    51          
    52         struct MkvBlock                                 *lastBlock; 
    53 } MkvTrackRecord, *MkvTrackPtr, **MkvTrackHandle; 
    54  
    55 // Component globals 
    56 typedef struct { 
    57147        ComponentInstance               self; 
    58148        Handle                                  dataRef; 
     
    60150         
    61151        Movie                                   theMovie; 
    62         Track                                   baseTrack;                      // so that the duration of the movie remains  
    63                                                                                                 // constant while idle importing 
    64         SInt64                                  segmentTimecodeScale; 
    65         TimeValue64                             movieDuration;          // in the timescale of segmentTimecodeScale 
    66  
    67         CFStringRef                             filename; 
    68         bool                                    useIdle; 
    69         TimeValue                               maxLoadedTime; 
    70         TimeValue                               lastIdleTime; 
    71         struct KaxPrivate               *kaxPrivate; 
    72 } MatroskaImportGlobalsRecord, *MatroskaImportGlobals; 
     152        Track                                   chapterTrack; 
     153        Track                                   baseTrack;              // fake track created to set the duration  
     154                                                                                        // of a movie while idle importing 
     155        SInt64                                  timecodeScale; 
     156        TimeValue64                             movieDuration;  // in the timescale of timecodeScale 
     157         
     158        DataHandlerCallback             *ioHandler; 
     159        EbmlStream                              *aStream; 
     160         
     161        EbmlElement                             *el_l0; 
     162        EbmlElement                             *el_l1; 
     163         
     164        vector<MatroskaTrack>   tracks; 
     165}; 
    73166 
    74167#endif 
  • trunk/Perian.xcodeproj/project.pbxproj

    r240 r242  
    164164                61CB11F30ACE0F6D007994BD /* libebml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 61CB10FF0ACDF350007994BD /* libebml.a */; }; 
    165165                61CB11F40ACE0F73007994BD /* libmatroska.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 61CB11770ACDF4D8007994BD /* libmatroska.a */; }; 
    166                 61CB12090ACE0F85007994BD /* MatroskaImport.c in Sources */ = {isa = PBXBuildFile; fileRef = 61D691570AC8E382000EFC7D /* MatroskaImport.c */; }; 
    167                 61CB120A0ACE0F86007994BD /* MkvImportPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61D6915E0AC8E382000EFC7D /* MkvImportPrivate.cpp */; }; 
    168                 61CB120B0ACE0F87007994BD /* MkvMovieSetup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61D691600AC8E382000EFC7D /* MkvMovieSetup.cpp */; }; 
     166                61CB12090ACE0F85007994BD /* MatroskaImport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61D691570AC8E382000EFC7D /* MatroskaImport.cpp */; }; 
    169167                61CB120C0ACE0F8A007994BD /* DataHandlerCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61D6914E0AC8E382000EFC7D /* DataHandlerCallback.cpp */; }; 
    170168                61CB120D0ACE0F8D007994BD /* MatroskaCodecIDs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61D691500AC8E382000EFC7D /* MatroskaCodecIDs.cpp */; }; 
     
    172170                61D514DE0ADF3DBA00A671E1 /* SubImport.c in Sources */ = {isa = PBXBuildFile; fileRef = 61D514DD0ADF3DBA00A671E1 /* SubImport.c */; }; 
    173171                61D517730AE0402E00A671E1 /* CommonUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 61D517720AE0402E00A671E1 /* CommonUtils.c */; }; 
     172                61FD41330B4F6F0800BEEFEA /* MatroskaImportPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61FD41320B4F6F0800BEEFEA /* MatroskaImportPrivate.cpp */; }; 
    174173                83D1D6CF0B4C7AC400E09EC9 /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83D1D6CE0B4C7AC400E09EC9 /* PreferencePanes.framework */; }; 
    175174                83D1D6DE0B4C7F8300E09EC9 /* PerianPrefPane.nib in Resources */ = {isa = PBXBuildFile; fileRef = 83D1D6DD0B4C7F8300E09EC9 /* PerianPrefPane.nib */; }; 
     
    395394                61D691550AC8E382000EFC7D /* MatroskaExportDispatch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MatroskaExportDispatch.h; sourceTree = "<group>"; }; 
    396395                61D691560AC8E382000EFC7D /* MatroskaExportVersion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MatroskaExportVersion.h; sourceTree = "<group>"; }; 
    397                 61D691570AC8E382000EFC7D /* MatroskaImport.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = MatroskaImport.c; sourceTree = "<group>"; }; 
     396                61D691570AC8E382000EFC7D /* MatroskaImport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MatroskaImport.cpp; sourceTree = "<group>"; }; 
    398397                61D691580AC8E382000EFC7D /* MatroskaImport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MatroskaImport.h; sourceTree = "<group>"; }; 
    399398                61D691590AC8E382000EFC7D /* MatroskaImport.r */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.rez; path = MatroskaImport.r; sourceTree = "<group>"; }; 
     
    402401                61D6915C0AC8E382000EFC7D /* MkvExportPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MkvExportPrivate.cpp; sourceTree = "<group>"; }; 
    403402                61D6915D0AC8E382000EFC7D /* MkvExportPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MkvExportPrivate.h; sourceTree = "<group>"; }; 
    404                 61D6915E0AC8E382000EFC7D /* MkvImportPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MkvImportPrivate.cpp; sourceTree = "<group>"; }; 
    405                 61D6915F0AC8E382000EFC7D /* MkvImportPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MkvImportPrivate.h; sourceTree = "<group>"; }; 
    406                 61D691600AC8E382000EFC7D /* MkvMovieSetup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MkvMovieSetup.cpp; sourceTree = "<group>"; }; 
    407                 61D691610AC8E382000EFC7D /* MkvMovieSetup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MkvMovieSetup.h; sourceTree = "<group>"; }; 
     403                61FD41320B4F6F0800BEEFEA /* MatroskaImportPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MatroskaImportPrivate.cpp; sourceTree = "<group>"; }; 
    408404                83D1D6C80B4C794700E09EC9 /* PerianPane.prefPane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PerianPane.prefPane; sourceTree = BUILT_PRODUCTS_DIR; }; 
    409405                83D1D6C90B4C794800E09EC9 /* PerianPane-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "PerianPane-Info.plist"; sourceTree = "<group>"; }; 
     
    739735                        isa = PBXGroup; 
    740736                        children = ( 
    741                                 61D691570AC8E382000EFC7D /* MatroskaImport.c */, 
     737                                61D691570AC8E382000EFC7D /* MatroskaImport.cpp */, 
    742738                                61D691580AC8E382000EFC7D /* MatroskaImport.h */, 
     739                                61FD41320B4F6F0800BEEFEA /* MatroskaImportPrivate.cpp */, 
    743740                                61D6915A0AC8E382000EFC7D /* MatroskaImportDispatch.h */, 
    744741                                61D6915B0AC8E382000EFC7D /* MatroskaImportVersion.h */, 
    745                                 61D6915E0AC8E382000EFC7D /* MkvImportPrivate.cpp */, 
    746                                 61D6915F0AC8E382000EFC7D /* MkvImportPrivate.h */, 
    747                                 61D691600AC8E382000EFC7D /* MkvMovieSetup.cpp */, 
    748                                 61D691610AC8E382000EFC7D /* MkvMovieSetup.h */, 
    749742                        ); 
    750743                        name = Import; 
     
    10801073                                112E0C820A6436BA00DB4C29 /* FFusionCodec.c in Sources */, 
    10811074                                113F589A0A6B091600509987 /* Codecprintf.c in Sources */, 
    1082                                 61CB12090ACE0F85007994BD /* MatroskaImport.c in Sources */, 
    1083                                 61CB120A0ACE0F86007994BD /* MkvImportPrivate.cpp in Sources */, 
    1084                                 61CB120B0ACE0F87007994BD /* MkvMovieSetup.cpp in Sources */, 
     1075                                61CB12090ACE0F85007994BD /* MatroskaImport.cpp in Sources */, 
    10851076                                61CB120C0ACE0F8A007994BD /* DataHandlerCallback.cpp in Sources */, 
    10861077                                61CB120D0ACE0F8D007994BD /* MatroskaCodecIDs.cpp in Sources */, 
     
    10981089                                6116E6200B44A5B30020F1CE /* CADebugMacros.cpp in Sources */, 
    10991090                                6116E6220B44A5BC0020F1CE /* CABundleLocker.cpp in Sources */, 
     1091                                61FD41330B4F6F0800BEEFEA /* MatroskaImportPrivate.cpp in Sources */, 
    11001092                        ); 
    11011093                        runOnlyForDeploymentPostprocessing = 0; 
  • trunk/SubImport.c

    r217 r242  
    3838                langStr = CFStringCreateWithSubstring(NULL, baseName, findResult); 
    3939                CFStringGetCString(langStr, langCStr, 4, kCFStringEncodingASCII); 
    40                 lang = ThreeCharLangCodeToQTLangCode(langCStr); 
     40                lang = ISO639_2ToQTLangCode(langCStr); 
    4141 
    4242                CFRelease(langStr); 
     
    4848                langStr = CFStringCreateWithSubstring(NULL, baseName, findResult); 
    4949                CFStringGetCString(langStr, langCStr, 3, kCFStringEncodingASCII); 
    50                 lang = TwoCharLangCodeToQTLangCode(langCStr); 
     50                lang = ISO639_1ToQTLangCode(langCStr); 
    5151 
    5252                CFRelease(langStr);