/*! \warning Assume that the list has been sorted (Sort()) */ const KaxCuePoint * KaxCues::GetTimecodePoint(uint64 aTimecode) const { uint64 TimecodeToLocate = aTimecode / GlobalTimecodeScale(); const KaxCuePoint * aPointPrev = NULL; uint64 aPrevTime = 0; uint64 aNextTime = EBML_PRETTYLONGINT(0xFFFFFFFFFFFF); EBML_MASTER_CONST_ITERATOR Itr; for (Itr = begin(); Itr != end(); ++Itr) { if (EbmlId(*(*Itr)) == EBML_ID(KaxCuePoint)) { const KaxCuePoint *tmp = static_cast<const KaxCuePoint *>(*Itr); // check the tile const KaxCueTime *aTime = static_cast<const KaxCueTime *>(tmp->FindFirstElt(EBML_INFO(KaxCueTime))); if (aTime != NULL) { uint64 _Time = uint64(*aTime); if (_Time > aPrevTime && _Time < TimecodeToLocate) { aPrevTime = _Time; aPointPrev = tmp; } if (_Time < aNextTime && _Time > TimecodeToLocate) { aNextTime= _Time; } } } } return aPointPrev; }
uint64 KaxCluster::GetBlockGlobalTimecode(int16 GlobalSavedTimecode) { if (!bFirstFrameInside) { KaxClusterTimecode * Timecode = static_cast<KaxClusterTimecode *>(this->FindElt(EBML_INFO(KaxClusterTimecode))); assert (bFirstFrameInside); // use the InitTimecode() hack for now MinTimecode = MaxTimecode = PreviousTimecode = *static_cast<EbmlUInteger *>(Timecode); bFirstFrameInside = true; bPreviousTimecodeIsSet = true; } return int64(GlobalSavedTimecode * GlobalTimecodeScale()) + GlobalTimecode(); }
void KaxCues::PositionSet(const KaxBlockBlob & BlockReference) { // look for the element in the temporary references std::vector<const KaxBlockBlob *>::iterator ListIdx; for (ListIdx = myTempReferences.begin(); ListIdx != myTempReferences.end(); ListIdx++) { if (*ListIdx == &BlockReference) { // found, now add the element to the entry list KaxCuePoint & NewPoint = AddNewChild<KaxCuePoint>(*this); NewPoint.PositionSet(BlockReference, GlobalTimecodeScale()); myTempReferences.erase(ListIdx); break; } } }
void KaxCues::PositionSet(const KaxBlockGroup & BlockRef) { // look for the element in the temporary references std::vector<const KaxBlockBlob *>::iterator ListIdx; for (ListIdx = myTempReferences.begin(); ListIdx != myTempReferences.end(); ListIdx++) { const KaxInternalBlock &refTmp = **ListIdx; if (refTmp.GlobalTimecode() == BlockRef.GlobalTimecode() && refTmp.TrackNum() == BlockRef.TrackNumber()) { // found, now add the element to the entry list KaxCuePoint & NewPoint = AddNewChild<KaxCuePoint>(*this); NewPoint.PositionSet(**ListIdx, GlobalTimecodeScale()); myTempReferences.erase(ListIdx); break; } } }
/*! \brief retrieve the relative \todo !!! We need a way to know the TimecodeScale */ int16 KaxCluster::GetBlockLocalTimecode(uint64 aGlobalTimecode) const { int64 TimecodeDelay = (int64(aGlobalTimecode) - int64(GlobalTimecode())) / int64(GlobalTimecodeScale()); assert(TimecodeDelay >= int16(0x8000) && TimecodeDelay <= int16(0x7FFF)); return int16(TimecodeDelay); }
/*! \todo only put the Blocks written in the cue entries */ filepos_t KaxCluster::Render(IOCallback & output, KaxCues & CueToUpdate, bool bSaveDefault) { filepos_t Result = 0; size_t Index; EBML_MASTER_ITERATOR TrkItr, Itr; // update the Timecode of the Cluster before writing KaxClusterTimecode * Timecode = static_cast<KaxClusterTimecode *>(this->FindElt(EBML_INFO(KaxClusterTimecode))); *static_cast<EbmlUInteger *>(Timecode) = GlobalTimecode() / GlobalTimecodeScale(); if (Blobs.size() == 0) { // old-school direct KaxBlockGroup // SilentTracks handling // check the parent cluster for existing tracks and see if they are contained in this cluster or not if (bSilentTracksUsed) { KaxTracks & MyTracks = *static_cast<KaxTracks *>(ParentSegment->FindElt(EBML_INFO(KaxTracks))); for (TrkItr = MyTracks.begin(); TrkItr != MyTracks.end(); ++TrkItr) { if (EbmlId(*(*TrkItr)) == EBML_ID(KaxTrackEntry)) { KaxTrackEntry & entry = *static_cast<KaxTrackEntry *>(*TrkItr); uint32 tracknum = entry.TrackNumber(); for (Itr = begin(); Itr != end(); ++Itr) { if (EbmlId(*(*Itr)) == EBML_ID(KaxBlockGroup)) { KaxBlockGroup & group = *static_cast<KaxBlockGroup *>(*Itr); if (group.TrackNumber() == tracknum) break; // this track is used } } // the track wasn't found in this cluster if (Itr == end()) { KaxClusterSilentTracks * SilentTracks = static_cast<KaxClusterSilentTracks *>(this->FindFirstElt(EBML_INFO(KaxClusterSilentTracks))); assert(SilentTracks != NULL); // the flag bSilentTracksUsed should be set when creating the Cluster KaxClusterSilentTrackNumber * trackelt = static_cast<KaxClusterSilentTrackNumber *>(SilentTracks->AddNewElt(EBML_INFO(KaxClusterSilentTrackNumber))); *static_cast<EbmlUInteger *>(trackelt) = tracknum; } } } } Result = EbmlMaster::Render(output, bSaveDefault); // For all Blocks add their position on the CueEntry for (Itr = begin(); Itr != end(); ++Itr) { if (EbmlId(*(*Itr)) == EBML_ID(KaxBlockGroup)) { CueToUpdate.PositionSet(*static_cast<const KaxBlockGroup *>(*Itr)); } } } else { // new school, using KaxBlockBlob for (Index = 0; Index<Blobs.size(); Index++) { #if MATROSKA_VERSION >= 2 if (Blobs[Index]->IsSimpleBlock()) PushElement( (KaxSimpleBlock&) *Blobs[Index] ); else #endif PushElement( (KaxBlockGroup&) *Blobs[Index] ); } // SilentTracks handling // check the parent cluster for existing tracks and see if they are contained in this cluster or not if (bSilentTracksUsed) { KaxTracks & MyTracks = *static_cast<KaxTracks *>(ParentSegment->FindElt(EBML_INFO(KaxTracks))); for (TrkItr = MyTracks.begin(); TrkItr != MyTracks.end(); ++TrkItr) { if (EbmlId(*(*TrkItr)) == EBML_ID(KaxTrackEntry)) { KaxTrackEntry & entry = *static_cast<KaxTrackEntry *>(*TrkItr); uint32 tracknum = entry.TrackNumber(); for (Index = 0; Index<Blobs.size(); Index++) { if (((KaxInternalBlock&)*Blobs[Index]).TrackNum() == tracknum) break; // this track is used } // the track wasn't found in this cluster if (Index == ListSize()) { KaxClusterSilentTracks * SilentTracks = static_cast<KaxClusterSilentTracks *>(this->FindFirstElt(EBML_INFO(KaxClusterSilentTracks))); assert(SilentTracks != NULL); // the flag bSilentTracksUsed should be set when creating the Cluster KaxClusterSilentTrackNumber * trackelt = static_cast<KaxClusterSilentTrackNumber *>(SilentTracks->AddNewElt(EBML_INFO(KaxClusterSilentTrackNumber))); *static_cast<EbmlUInteger *>(trackelt) = tracknum; } } } } Result = EbmlMaster::Render(output, bSaveDefault); // For all Blocks add their position on the CueEntry for (Index = 0; Index<Blobs.size(); Index++) { CueToUpdate.PositionSet(*Blobs[Index]); } Blobs.clear(); } return Result; }