Changeset 265

Show
Ignore:
Timestamp:
01/07/07 19:04:42 (2 years ago)
Author:
dconrad
Message:

First try at mkv idle importing. Refs #29.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/MatroskaImport.cpp

    r242 r265  
    3434#include "SubImport.h" 
    3535#include "Codecprintf.h" 
     36 
     37extern "C"  
     38ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType); 
    3639 
    3740using namespace libmatroska; 
     
    6568 
    6669// Component Open Request - Required 
    67 pascal ComponentResult MatroskaImportOpen(MatroskaImport *store, ComponentInstance self) 
     70ComponentResult MatroskaImportOpen(MatroskaImport *store, ComponentInstance self) 
    6871{ 
    6972        // Allocate memory for our globals, and inform the component manager that we've done so 
     
    7982 
    8083// Component Close Request - Required 
    81 pascal ComponentResult MatroskaImportClose(MatroskaImport *store, ComponentInstance self) 
     84ComponentResult MatroskaImportClose(MatroskaImport *store, ComponentInstance self) 
    8285{ 
    8386        // Make sure to dealocate our storage 
     
    8891 
    8992// Component Version Request - Required 
    90 pascal ComponentResult MatroskaImportVersion(MatroskaImport *store) 
     93ComponentResult MatroskaImportVersion(MatroskaImport *store) 
    9194{ 
    9295        return kMatroskaImportVersion; 
     
    9699 
    97100// MovieImportFile 
    98 pascal ComponentResult MatroskaImportFile(MatroskaImport *store, const FSSpec *theFile, 
    99                                                                                   Movie theMovie, Track targetTrack, Track *usedTrack, 
    100                                                                                   TimeValue atTime, TimeValue *durationAdded, 
    101                                                                                   long inFlags, long *outFlags) 
     101ComponentResult MatroskaImportFile(MatroskaImport *store, const FSSpec *theFile, Movie theMovie, Track targetTrack,  
     102                                                                   Track *usedTrack, TimeValue atTime, TimeValue *durationAdded, long inFlags, long *outFlags) 
    102103{ 
    103104        OSErr err = noErr; 
     
    127128 
    128129// MovieImportDataRef 
    129 pascal ComponentResult MatroskaImportDataRef(MatroskaImport *store, Handle dataRef, 
    130                                                                                          OSType dataRefType, Movie theMovie, 
    131                                                                                          Track targetTrack, Track *usedTrack, 
    132                                                                                          TimeValue atTime, TimeValue *durationAdded, 
    133                                                                                          long inFlags, long *outFlags) 
     130ComponentResult MatroskaImportDataRef(MatroskaImport *store, Handle dataRef, OSType dataRefType, Movie theMovie, Track targetTrack, 
     131                                                                          Track *usedTrack, TimeValue atTime, TimeValue *durationAdded, long inFlags, long *outFlags) 
    134132{ 
    135133        return store->ImportDataRef(dataRef, dataRefType, theMovie, targetTrack, 
     
    138136 
    139137// MovieImportValidate 
    140 pascal ComponentResult MatroskaImportValidate(MatroskaImport *store,  
    141                                               const FSSpec *theFile,  
    142                                               Handle theData, Boolean *valid) 
     138ComponentResult MatroskaImportValidate(MatroskaImport *store, const FSSpec *theFile, Handle theData, Boolean *valid) 
    143139{ 
    144140        OSErr err = noErr; 
     
    164160 
    165161// MovieImportGetMIMETypeList 
    166 pascal ComponentResult MatroskaImportGetMIMETypeList(MatroskaImport *store,  
    167                                                      QTAtomContainer *retMimeInfo) 
     162ComponentResult MatroskaImportGetMIMETypeList(MatroskaImport *store, QTAtomContainer *retMimeInfo) 
    168163{ 
    169164        // Note that GetComponentResource is only available in QuickTime 3.0 or later. 
     
    173168 
    174169// MovieImportValidateDataRef 
    175 pascal ComponentResult MatroskaImportValidateDataRef(MatroskaImport *store, Handle dataRef,  
    176                                                      OSType dataRefType, UInt8 *valid) 
     170ComponentResult MatroskaImportValidateDataRef(MatroskaImport *store, Handle dataRef, OSType dataRefType, UInt8 *valid) 
    177171{ 
    178172        return store->ValidateDataRef(dataRef, dataRefType, valid); 
    179173} 
    180174 
    181 pascal ComponentResult MatroskaImportIdle(MatroskaImport *store, long inFlags, long *outFlags) 
    182 
    183         return noErr; //store->Idle(inFlags, outFlags); 
     175ComponentResult MatroskaImportIdle(MatroskaImport *store, long inFlags, long *outFlags) 
     176
     177        return store->Idle(inFlags, outFlags); 
     178
     179 
     180ComponentResult MatroskaImportSetIdleManager(MatroskaImport *store, IdleManager im) 
     181
     182        return store->SetIdleManager(im); 
     183
     184 
     185ComponentResult MatroskaImportGetMaxLoadedTime(MatroskaImport *store, TimeValue *time) 
     186
     187        return store->GetMaxLoadedTime(time); 
     188
     189 
     190ComponentResult MatroskaImportGetLoadState(MatroskaImport *store, long *importerLoadState) 
     191
     192        return store->GetLoadState(importerLoadState); 
    184193} 
    185194 
     
    195204        timecodeScale = 1000000; 
    196205        movieDuration = 0; 
     206        idleManager = NULL; 
     207        loadState = kMovieLoadStateLoading; 
    197208        ioHandler = NULL; 
    198209        aStream = NULL; 
     
    231242                return paramErr; 
    232243         
     244        loadState = kMovieLoadStateLoading; 
     245         
    233246        try { 
    234247                if (!OpenFile()) 
     
    238251                SetupMovie(); 
    239252                 
    240                 do
    241                         KaxSegment & segment = *static_cast<KaxSegment *>(el_l0); 
     253                if (inFlags & movieImportWithIdle)
     254                        create_placeholder_track(theMovie, &baseTrack, movieDuration, dataRef, dataRefType); 
    242255                         
     256                        // try to import one cluster so we have at least something 
    243257                        if (EbmlId(*el_l1) == KaxCluster::ClassInfos.GlobalId) { 
    244258                                int upperLevel = 0; 
     
    247261                                el_l1->Read(*aStream, KaxCluster::ClassInfos.Context, upperLevel, dummyElt, true); 
    248262                                KaxCluster & cluster = *static_cast<KaxCluster *>(el_l1); 
    249                                 KaxClusterTimecode & clusterTime = GetChild<KaxClusterTimecode>(cluster); 
    250263                                 
    251                                 cluster.SetParent(segment); 
    252                                 cluster.InitTimecode(uint64(clusterTime), timecodeScale); 
     264                                ImportCluster(cluster, true); 
     265                        } 
     266                         
     267                        if (!NextLevel1Element()) 
     268                                *outFlags |= movieImportResultComplete; 
     269                        else 
     270                                *outFlags |= movieImportResultNeedIdles; 
     271                         
     272                        return noErr; 
     273                } 
     274                 
     275                do { 
     276                        if (EbmlId(*el_l1) == KaxCluster::ClassInfos.GlobalId) { 
     277                                int upperLevel = 0; 
     278                                EbmlElement *dummyElt = NULL; 
    253279                                 
    254                                 KaxBlockGroup *blockGroup = FindChild<KaxBlockGroup>(cluster); 
    255                                 while (blockGroup->GetSize() > 0) { 
    256                                         KaxBlock & block = GetChild<KaxBlock>(*blockGroup); 
    257                                         block.SetParent(cluster); 
    258                                          
    259                                         for (int i = 0; i < tracks.size(); i++) { 
    260                                                 if (tracks[i].number == block.TrackNum()) 
    261                                                         tracks[i].AddBlock(*blockGroup); 
    262                                         } 
    263                                          
    264                                         blockGroup = &GetNextChild<KaxBlockGroup>(cluster, *blockGroup); 
    265                                 } 
     280                                el_l1->Read(*aStream, KaxCluster::ClassInfos.Context, upperLevel, dummyElt, true); 
     281                                KaxCluster & cluster = *static_cast<KaxCluster *>(el_l1); 
     282                                 
     283                                ImportCluster(cluster, false); 
    266284                        } 
    267285                } while (NextLevel1Element()); 
    268286                 
    269287                // insert the a/v tracks' samples 
    270                 for (int i = 0; i < tracks.size(); i++) { 
    271                         if (tracks[i].type != track_subtitle) { 
    272                                 if (tracks[i].sampleTable) { 
    273                                         err = AddSampleTableToMedia(tracks[i].theMedia, tracks[i].sampleTable, 1,  
    274                                                                                                 QTSampleTableGetNumberOfSamples(tracks[i].sampleTable), NULL); 
    275                                         if (err) 
    276                                                 Codecprintf(NULL, "MKV: error adding sample table to media %d\n", err); 
    277                                 } 
    278                                 err = InsertMediaIntoTrack(tracks[i].theTrack, 0, 0, GetMediaDuration(tracks[i].theMedia), fixed1); 
    279                                 if (err) 
    280                                         Codecprintf(NULL, "MKV: error inserting media into track %d\n", err); 
    281                         } 
    282                 } 
     288                for (int i = 0; i < tracks.size(); i++) 
     289                        tracks[i].AddSamplesToTrack(); 
    283290                 
    284291        } catch (CRTError &err) { 
    285292                return err.getError(); 
    286293        } 
     294         
     295        loadState = kMovieLoadStateComplete; 
    287296         
    288297        return noErr; 
     
    305314        return noErr; 
    306315} 
     316 
     317ComponentResult MatroskaImport::Idle(long inFlags, long *outFlags) 
     318{ 
     319        if (EbmlId(*el_l1) == KaxCluster::ClassInfos.GlobalId) { 
     320                int upperLevel = 0; 
     321                EbmlElement *dummyElt = NULL; 
     322                 
     323                el_l1->Read(*aStream, KaxCluster::ClassInfos.Context, upperLevel, dummyElt, true); 
     324                KaxCluster & cluster = *static_cast<KaxCluster *>(el_l1); 
     325                 
     326                ImportCluster(cluster, true); 
     327        } 
     328         
     329        if (!NextLevel1Element()) { 
     330                if (baseTrack) 
     331                        DisposeMovieTrack(baseTrack); 
     332                *outFlags |= movieImportResultComplete; 
     333                loadState = kMovieLoadStateComplete; 
     334        } 
     335         
     336        return noErr; 
     337} 
     338 
     339ComponentResult MatroskaImport::SetIdleManager(IdleManager im) 
     340{ 
     341        idleManager = im; 
     342        return noErr; 
     343} 
     344 
     345ComponentResult MatroskaImport::GetMaxLoadedTime(TimeValue *time) 
     346{ 
     347        *time = 0; 
     348        for (int i = 0; i < tracks.size(); i++) { 
     349                if (tracks[i].maxLoadedTime > *time) 
     350                        *time = tracks[i].maxLoadedTime; 
     351        } 
     352        return noErr; 
     353} 
     354 
     355ComponentResult MatroskaImport::GetLoadState(long *importerLoadState) 
     356{ 
     357        *importerLoadState = loadState; 
     358        return noErr; 
     359} 
  • trunk/MatroskaImport.h

    r261 r265  
    6565        void AddBlock(KaxBlockGroup &blockGroup); 
    6666         
     67        // this adds all the samples added through AddBlock() to the track that aren't already 
     68        // added, e.g. from a previous call to AddSamplesToTrack() 
     69        void AddSamplesToTrack(); 
     70         
    6771        UInt16                                  number; 
    6872        UInt8                                   type; 
     
    7377        QTSampleDescriptionID   qtSampleDesc; 
    7478        SInt64                                  timecodeScale; 
    75         bool                                   seenFirstFrame; 
     79        TimeValue64                            maxLoadedTime; 
    7680         
    7781private: 
    7882        // adds an individual frame from a block group into the sample table if it exists, 
    7983        // the media otherwise, and into the track if the track is a subtitle track. 
    80         SInt64 AddFrame(MatroskaFrame &frame); 
     84        void AddFrame(MatroskaFrame &frame); 
    8185         
    8286        // Since the duration in Matroska files is generally rather unreliable, rely only on 
     
    8589        // previous ones to be the difference in timestamps. 
    8690        vector<MatroskaFrame>   lastFrames; 
     91        bool                                    seenFirstFrame; 
     92         
     93        // this is the first sample number (if sample table) or sample time that we haven't  
     94        // yet added to the media/track. A value of -1 means the value is invalid/unset. 
     95        SInt64                                  firstSample; 
     96        SInt64                                  amountToAdd;    // num samples if sampleTable, duration otherwise 
    8797}; 
    8898 
     
    107117        // MatroskaImportValidateDataRef() 
    108118        ComponentResult ValidateDataRef(Handle dataRef, OSType dataRefType, UInt8 *valid); 
     119         
     120        // MatroskaImportIdle() 
     121        ComponentResult Idle(long inFlags, long *outFlags); 
     122         
     123        // MatroskaImportSetIdleManager() 
     124        ComponentResult SetIdleManager(IdleManager im); 
     125         
     126        // MatroskaImportGetMaxLoadedTime() 
     127        ComponentResult GetMaxLoadedTime(TimeValue *time); 
     128         
     129        // MatroskaImportGetLoadState() 
     130        ComponentResult GetLoadState(long *importerLoadState); 
    109131         
    110132        // we need to get our component instance to get our mime type resource 
     
    145167        void AddChapterAtom(KaxChapterAtom *atom, Track chapterTrack); 
    146168         
     169        // assumes cluster has been read already, and cycles through the contained blocks and 
     170        // adds the frames to the media/sample table, and to the track if addToTrack is true 
     171        void ImportCluster(KaxCluster &cluster, bool addToTrack); 
    147172                 
    148173        ComponentInstance               self; 
     
    157182        TimeValue64                             movieDuration;  // in the timescale of timecodeScale 
    158183         
     184        IdleManager                             idleManager; 
     185        long                                    loadState; 
     186         
    159187        DataHandlerCallback             *ioHandler; 
    160188        EbmlStream                              *aStream; 
  • trunk/MatroskaImportDispatch.h

    r119 r265  
    6464                ComponentCall  (Idle) 
    6565                ComponentCall  (ValidateDataRef) 
    66                 ComponentError (GetLoadState) 
    67                 ComponentError (GetMaxLoadedTime) 
     66                ComponentCall (GetLoadState) 
     67                ComponentCall (GetMaxLoadedTime) 
    6868                ComponentError (EstimateCompletionTime) 
    6969                ComponentError (SetDontBlock) 
    7070                ComponentError (GetDontBlock) 
    71                 ComponentError (SetIdleManager) 
     71                ComponentCall (SetIdleManager) 
    7272                ComponentError (SetNewMovieFlags) 
    7373                ComponentError (GetDestinationMediaType) 
  • trunk/MatroskaImportPrivate.cpp

    r261 r265  
    549549} 
    550550 
     551void MatroskaImport::ImportCluster(KaxCluster &cluster, bool addToTrack) 
     552{ 
     553        KaxSegment & segment = *static_cast<KaxSegment *>(el_l0); 
     554        KaxClusterTimecode & clusterTime = GetChild<KaxClusterTimecode>(cluster); 
     555                                 
     556        cluster.SetParent(segment); 
     557        cluster.InitTimecode(uint64(clusterTime), timecodeScale); 
     558         
     559        KaxBlockGroup *blockGroup = FindChild<KaxBlockGroup>(cluster); 
     560        while (blockGroup->GetSize() > 0) { 
     561                KaxBlock & block = GetChild<KaxBlock>(*blockGroup); 
     562                block.SetParent(cluster); 
     563                 
     564                for (int i = 0; i < tracks.size(); i++) { 
     565                        if (tracks[i].number == block.TrackNum()) { 
     566                                tracks[i].AddBlock(*blockGroup); 
     567                                break; 
     568                        } 
     569                } 
     570                 
     571                blockGroup = &GetNextChild<KaxBlockGroup>(cluster, *blockGroup); 
     572        } 
     573         
     574        if (addToTrack) { 
     575                for (int i = 0; i < tracks.size(); i++) 
     576                        tracks[i].AddSamplesToTrack(); 
     577                 
     578                loadState = kMovieLoadStatePlayable; 
     579        } 
     580} 
     581 
    551582 
    552583MatroskaTrack::MatroskaTrack() 
     
    560591        qtSampleDesc = 0; 
    561592        timecodeScale = 1000000; 
     593        maxLoadedTime = 0; 
    562594        seenFirstFrame = false; 
     595        firstSample = -1; 
     596        amountToAdd = 0; 
    563597} 
    564598 
     
    582616        qtSampleDesc = copy.qtSampleDesc; 
    583617        timecodeScale = copy.timecodeScale; 
    584         seenFirstFrame = copy.seenFirstFrame; 
     618        maxLoadedTime = copy.maxLoadedTime; 
    585619         
    586620        for (int i = 0; i < copy.lastFrames.size(); i++) 
    587621                lastFrames.push_back(copy.lastFrames[i]); 
     622         
     623        seenFirstFrame = copy.seenFirstFrame; 
     624        firstSample = copy.firstSample; 
     625        amountToAdd = copy.amountToAdd; 
    588626} 
    589627 
     
    654692} 
    655693 
    656 SInt64 MatroskaTrack::AddFrame(MatroskaFrame &frame) 
     694void MatroskaTrack::AddFrame(MatroskaFrame &frame) 
    657695{ 
    658696        ComponentResult err = noErr; 
     
    665703                if (err) 
    666704                        Codecprintf(NULL, "MKV: error adding sample reference to table %d\n", err); 
     705                 
     706                amountToAdd++; 
    667707        } else { 
    668708                SampleReference64Record sample; 
     
    677717                if (err) 
    678718                        Codecprintf(NULL, "MKV: error adding sample reference to media %d\n", err); 
     719                 
     720                amountToAdd += frame.duration; 
    679721        } 
    680722         
     
    694736        } 
    695737         
    696         return sampleNum; 
    697 
     738        if (firstSample == -1) 
     739                firstSample = sampleNum; 
     740
     741 
     742void MatroskaTrack::AddSamplesToTrack() 
     743
     744        OSStatus err = noErr; 
     745         
     746        if (type == track_subtitle) 
     747                // subtitle tracks add the media in AddFrame() since there's gaps 
     748                return; 
     749         
     750        if (sampleTable) { 
     751                TimeValue64 sampleTime64; 
     752                TimeValue mediaDuration = GetMediaDuration(theMedia); 
     753                 
     754                err = AddSampleTableToMedia(theMedia, sampleTable, firstSample, amountToAdd, &sampleTime64); 
     755                if (err) 
     756                        Codecprintf(NULL, "MKV: error adding sample table to media %d\n", err); 
     757                 
     758                firstSample = sampleTime64; 
     759                amountToAdd = GetMediaDuration(theMedia) - mediaDuration; 
     760        } 
     761        err = InsertMediaIntoTrack(theTrack, -1, firstSample, amountToAdd, fixed1); 
     762        if (err) 
     763                Codecprintf(NULL, "MKV: error inserting media into track %d\n", err); 
     764         
     765        maxLoadedTime += amountToAdd; 
     766        firstSample = -1; 
     767        amountToAdd = 0; 
     768
  • trunk/ff_MovieImport.c

    r257 r265  
    487487                         
    488488                        //create a placeholder track so that progress displays correctly. 
    489                         create_placeholder_track(storage, *addedDuration, dataRef, dataRefType); 
     489                        create_placeholder_track(storage->movie, &storage->placeholderTrack, *addedDuration, dataRef, dataRefType); 
    490490                         
    491491                        //give the data handler a hint as to how fast we need the data. 
  • trunk/ff_private.c

    r264 r265  
    950950} /* import_with_idle() */ 
    951951 
    952 ComponentResult create_placeholder_track(ff_global_ptr storage, TimeValue duration, Handle dataRef, OSType dataRefType) { 
     952ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType) { 
    953953        SampleDescriptionHandle sdH; 
    954954        Media placeholderMedia; 
     
    956956        ComponentResult result = noErr; 
    957957         
    958         movieTimeScale = GetMovieTimeScale(storage->movie); 
     958        movieTimeScale = GetMovieTimeScale(movie); 
    959959         
    960960        sdH = (SampleDescriptionHandle)NewHandleClear(sizeof(SampleDescription)); 
    961961        (*sdH)->descSize = sizeof(SampleDescription); 
    962962         
    963         storage->placeholderTrack = NewMovieTrack(storage->movie, 0, 0, kNoVolume); 
    964         placeholderMedia = NewTrackMedia(storage->placeholderTrack, BaseMediaType, movieTimeScale, dataRef, dataRefType); 
     963        *placeholderTrack = NewMovieTrack(movie, 0, 0, kNoVolume); 
     964        placeholderMedia = NewTrackMedia(*placeholderTrack, BaseMediaType, movieTimeScale, dataRef, dataRefType); 
    965965         
    966966        result = AddMediaSampleReference(placeholderMedia, 0, 1, duration, sdH, 1, 0, NULL); 
     
    968968                goto bail; 
    969969         
    970         result = InsertMediaIntoTrack(storage->placeholderTrack, -1, 0, duration, fixed1); 
     970        result = InsertMediaIntoTrack(*placeholderTrack, -1, 0, duration, fixed1); 
    971971         
    972972bail: 
  • trunk/ff_private.h

    r256 r265  
    101101int import_using_index(ff_global_ptr storage, int *hadIndex, TimeValue *addedDuration); 
    102102ComponentResult import_with_idle(ff_global_ptr storage, long inFlags, long *outFlags, int minFrames, int maxFrames); 
    103 ComponentResult create_placeholder_track(ff_global_ptr storage, TimeValue duration, Handle dataRef, OSType dataRefType); 
     103ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType); 
    104104void send_movie_changed_notification(Movie movie); 
    105105