std::map<id_timecode_t, uint64_t> cues_c::calculate_block_positions(KaxCluster &cluster) const { std::map<id_timecode_t, uint64_t> positions; for (auto child : cluster) { auto simple_block = dynamic_cast<KaxSimpleBlock *>(child); if (simple_block) { simple_block->SetParent(cluster); positions[ id_timecode_t{ simple_block->TrackNum(), simple_block->GlobalTimecode() } ] = simple_block->GetElementPosition(); continue; } auto block_group = dynamic_cast<KaxBlockGroup *>(child); if (!block_group) continue; auto block = FindChild<KaxBlock>(block_group); if (!block) continue; block->SetParent(cluster); positions[ id_timecode_t{ block->TrackNum(), block->GlobalTimecode() } ] = block->GetElementPosition(); } return positions; }
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(); }
/*! \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; }