Changeset 265
- Timestamp:
- 01/07/07 19:04:42 (2 years ago)
- Files:
-
- trunk/MatroskaImport.cpp (modified) (14 diffs)
- trunk/MatroskaImport.h (modified) (6 diffs)
- trunk/MatroskaImportDispatch.h (modified) (1 diff)
- trunk/MatroskaImportPrivate.cpp (modified) (7 diffs)
- trunk/ff_MovieImport.c (modified) (1 diff)
- trunk/ff_private.c (modified) (3 diffs)
- trunk/ff_private.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/MatroskaImport.cpp
r242 r265 34 34 #include "SubImport.h" 35 35 #include "Codecprintf.h" 36 37 extern "C" 38 ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType); 36 39 37 40 using namespace libmatroska; … … 65 68 66 69 // Component Open Request - Required 67 pascalComponentResult MatroskaImportOpen(MatroskaImport *store, ComponentInstance self)70 ComponentResult MatroskaImportOpen(MatroskaImport *store, ComponentInstance self) 68 71 { 69 72 // Allocate memory for our globals, and inform the component manager that we've done so … … 79 82 80 83 // Component Close Request - Required 81 pascalComponentResult MatroskaImportClose(MatroskaImport *store, ComponentInstance self)84 ComponentResult MatroskaImportClose(MatroskaImport *store, ComponentInstance self) 82 85 { 83 86 // Make sure to dealocate our storage … … 88 91 89 92 // Component Version Request - Required 90 pascalComponentResult MatroskaImportVersion(MatroskaImport *store)93 ComponentResult MatroskaImportVersion(MatroskaImport *store) 91 94 { 92 95 return kMatroskaImportVersion; … … 96 99 97 100 // 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) 101 ComponentResult MatroskaImportFile(MatroskaImport *store, const FSSpec *theFile, Movie theMovie, Track targetTrack, 102 Track *usedTrack, TimeValue atTime, TimeValue *durationAdded, long inFlags, long *outFlags) 102 103 { 103 104 OSErr err = noErr; … … 127 128 128 129 // 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) 130 ComponentResult MatroskaImportDataRef(MatroskaImport *store, Handle dataRef, OSType dataRefType, Movie theMovie, Track targetTrack, 131 Track *usedTrack, TimeValue atTime, TimeValue *durationAdded, long inFlags, long *outFlags) 134 132 { 135 133 return store->ImportDataRef(dataRef, dataRefType, theMovie, targetTrack, … … 138 136 139 137 // MovieImportValidate 140 pascal ComponentResult MatroskaImportValidate(MatroskaImport *store, 141 const FSSpec *theFile, 142 Handle theData, Boolean *valid) 138 ComponentResult MatroskaImportValidate(MatroskaImport *store, const FSSpec *theFile, Handle theData, Boolean *valid) 143 139 { 144 140 OSErr err = noErr; … … 164 160 165 161 // MovieImportGetMIMETypeList 166 pascal ComponentResult MatroskaImportGetMIMETypeList(MatroskaImport *store, 167 QTAtomContainer *retMimeInfo) 162 ComponentResult MatroskaImportGetMIMETypeList(MatroskaImport *store, QTAtomContainer *retMimeInfo) 168 163 { 169 164 // Note that GetComponentResource is only available in QuickTime 3.0 or later. … … 173 168 174 169 // MovieImportValidateDataRef 175 pascal ComponentResult MatroskaImportValidateDataRef(MatroskaImport *store, Handle dataRef, 176 OSType dataRefType, UInt8 *valid) 170 ComponentResult MatroskaImportValidateDataRef(MatroskaImport *store, Handle dataRef, OSType dataRefType, UInt8 *valid) 177 171 { 178 172 return store->ValidateDataRef(dataRef, dataRefType, valid); 179 173 } 180 174 181 pascal ComponentResult MatroskaImportIdle(MatroskaImport *store, long inFlags, long *outFlags) 182 { 183 return noErr; //store->Idle(inFlags, outFlags); 175 ComponentResult MatroskaImportIdle(MatroskaImport *store, long inFlags, long *outFlags) 176 { 177 return store->Idle(inFlags, outFlags); 178 } 179 180 ComponentResult MatroskaImportSetIdleManager(MatroskaImport *store, IdleManager im) 181 { 182 return store->SetIdleManager(im); 183 } 184 185 ComponentResult MatroskaImportGetMaxLoadedTime(MatroskaImport *store, TimeValue *time) 186 { 187 return store->GetMaxLoadedTime(time); 188 } 189 190 ComponentResult MatroskaImportGetLoadState(MatroskaImport *store, long *importerLoadState) 191 { 192 return store->GetLoadState(importerLoadState); 184 193 } 185 194 … … 195 204 timecodeScale = 1000000; 196 205 movieDuration = 0; 206 idleManager = NULL; 207 loadState = kMovieLoadStateLoading; 197 208 ioHandler = NULL; 198 209 aStream = NULL; … … 231 242 return paramErr; 232 243 244 loadState = kMovieLoadStateLoading; 245 233 246 try { 234 247 if (!OpenFile()) … … 238 251 SetupMovie(); 239 252 240 do{241 KaxSegment & segment = *static_cast<KaxSegment *>(el_l0);253 if (inFlags & movieImportWithIdle) { 254 create_placeholder_track(theMovie, &baseTrack, movieDuration, dataRef, dataRefType); 242 255 256 // try to import one cluster so we have at least something 243 257 if (EbmlId(*el_l1) == KaxCluster::ClassInfos.GlobalId) { 244 258 int upperLevel = 0; … … 247 261 el_l1->Read(*aStream, KaxCluster::ClassInfos.Context, upperLevel, dummyElt, true); 248 262 KaxCluster & cluster = *static_cast<KaxCluster *>(el_l1); 249 KaxClusterTimecode & clusterTime = GetChild<KaxClusterTimecode>(cluster);250 263 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; 253 279 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); 266 284 } 267 285 } while (NextLevel1Element()); 268 286 269 287 // 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(); 283 290 284 291 } catch (CRTError &err) { 285 292 return err.getError(); 286 293 } 294 295 loadState = kMovieLoadStateComplete; 287 296 288 297 return noErr; … … 305 314 return noErr; 306 315 } 316 317 ComponentResult 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 339 ComponentResult MatroskaImport::SetIdleManager(IdleManager im) 340 { 341 idleManager = im; 342 return noErr; 343 } 344 345 ComponentResult 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 355 ComponentResult MatroskaImport::GetLoadState(long *importerLoadState) 356 { 357 *importerLoadState = loadState; 358 return noErr; 359 } trunk/MatroskaImport.h
r261 r265 65 65 void AddBlock(KaxBlockGroup &blockGroup); 66 66 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 67 71 UInt16 number; 68 72 UInt8 type; … … 73 77 QTSampleDescriptionID qtSampleDesc; 74 78 SInt64 timecodeScale; 75 bool seenFirstFrame;79 TimeValue64 maxLoadedTime; 76 80 77 81 private: 78 82 // adds an individual frame from a block group into the sample table if it exists, 79 83 // the media otherwise, and into the track if the track is a subtitle track. 80 SInt64AddFrame(MatroskaFrame &frame);84 void AddFrame(MatroskaFrame &frame); 81 85 82 86 // Since the duration in Matroska files is generally rather unreliable, rely only on … … 85 89 // previous ones to be the difference in timestamps. 86 90 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 87 97 }; 88 98 … … 107 117 // MatroskaImportValidateDataRef() 108 118 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); 109 131 110 132 // we need to get our component instance to get our mime type resource … … 145 167 void AddChapterAtom(KaxChapterAtom *atom, Track chapterTrack); 146 168 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); 147 172 148 173 ComponentInstance self; … … 157 182 TimeValue64 movieDuration; // in the timescale of timecodeScale 158 183 184 IdleManager idleManager; 185 long loadState; 186 159 187 DataHandlerCallback *ioHandler; 160 188 EbmlStream *aStream; trunk/MatroskaImportDispatch.h
r119 r265 64 64 ComponentCall (Idle) 65 65 ComponentCall (ValidateDataRef) 66 Component Error(GetLoadState)67 Component Error(GetMaxLoadedTime)66 ComponentCall (GetLoadState) 67 ComponentCall (GetMaxLoadedTime) 68 68 ComponentError (EstimateCompletionTime) 69 69 ComponentError (SetDontBlock) 70 70 ComponentError (GetDontBlock) 71 Component Error(SetIdleManager)71 ComponentCall (SetIdleManager) 72 72 ComponentError (SetNewMovieFlags) 73 73 ComponentError (GetDestinationMediaType) trunk/MatroskaImportPrivate.cpp
r261 r265 549 549 } 550 550 551 void 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 551 582 552 583 MatroskaTrack::MatroskaTrack() … … 560 591 qtSampleDesc = 0; 561 592 timecodeScale = 1000000; 593 maxLoadedTime = 0; 562 594 seenFirstFrame = false; 595 firstSample = -1; 596 amountToAdd = 0; 563 597 } 564 598 … … 582 616 qtSampleDesc = copy.qtSampleDesc; 583 617 timecodeScale = copy.timecodeScale; 584 seenFirstFrame = copy.seenFirstFrame;618 maxLoadedTime = copy.maxLoadedTime; 585 619 586 620 for (int i = 0; i < copy.lastFrames.size(); i++) 587 621 lastFrames.push_back(copy.lastFrames[i]); 622 623 seenFirstFrame = copy.seenFirstFrame; 624 firstSample = copy.firstSample; 625 amountToAdd = copy.amountToAdd; 588 626 } 589 627 … … 654 692 } 655 693 656 SInt64MatroskaTrack::AddFrame(MatroskaFrame &frame)694 void MatroskaTrack::AddFrame(MatroskaFrame &frame) 657 695 { 658 696 ComponentResult err = noErr; … … 665 703 if (err) 666 704 Codecprintf(NULL, "MKV: error adding sample reference to table %d\n", err); 705 706 amountToAdd++; 667 707 } else { 668 708 SampleReference64Record sample; … … 677 717 if (err) 678 718 Codecprintf(NULL, "MKV: error adding sample reference to media %d\n", err); 719 720 amountToAdd += frame.duration; 679 721 } 680 722 … … 694 736 } 695 737 696 return sampleNum; 697 } 738 if (firstSample == -1) 739 firstSample = sampleNum; 740 } 741 742 void 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 487 487 488 488 //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); 490 490 491 491 //give the data handler a hint as to how fast we need the data. trunk/ff_private.c
r264 r265 950 950 } /* import_with_idle() */ 951 951 952 ComponentResult create_placeholder_track( ff_global_ptr storage, TimeValue duration, Handle dataRef, OSType dataRefType) {952 ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType) { 953 953 SampleDescriptionHandle sdH; 954 954 Media placeholderMedia; … … 956 956 ComponentResult result = noErr; 957 957 958 movieTimeScale = GetMovieTimeScale( storage->movie);958 movieTimeScale = GetMovieTimeScale(movie); 959 959 960 960 sdH = (SampleDescriptionHandle)NewHandleClear(sizeof(SampleDescription)); 961 961 (*sdH)->descSize = sizeof(SampleDescription); 962 962 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); 965 965 966 966 result = AddMediaSampleReference(placeholderMedia, 0, 1, duration, sdH, 1, 0, NULL); … … 968 968 goto bail; 969 969 970 result = InsertMediaIntoTrack( storage->placeholderTrack, -1, 0, duration, fixed1);970 result = InsertMediaIntoTrack(*placeholderTrack, -1, 0, duration, fixed1); 971 971 972 972 bail: trunk/ff_private.h
r256 r265 101 101 int import_using_index(ff_global_ptr storage, int *hadIndex, TimeValue *addedDuration); 102 102 ComponentResult 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);103 ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType); 104 104 void send_movie_changed_notification(Movie movie); 105 105
