/**************************************************************************** ** libmatroska : parse Matroska files, see http://www.matroska.org/ ** ** ** ** Copyright (C) 2002-2010 Steve Lhomme. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ** ** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.** ** Contact license@matroska.org if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ /*! \file \version \$Id: KaxCuesData.cpp 1265 2007-01-14 17:20:35Z mosu $ \author Steve Lhomme */ #include #include "matroska/KaxCuesData.h" #include "matroska/KaxContexts.h" #include "matroska/KaxBlock.h" #include "matroska/KaxBlockData.h" #include "matroska/KaxCluster.h" #include "matroska/KaxSegment.h" #include "matroska/KaxDefines.h" #include "matroska/KaxSemantic.h" START_LIBMATROSKA_NAMESPACE /*! \todo handle codec state checking \todo remove duplicate references (reference to 2 frames that each reference the same frame) */ void KaxCuePoint::PositionSet(const KaxBlockGroup & BlockReference, uint64 GlobalTimecodeScale) { // fill me KaxCueTime & NewTime = GetChild(*this); *static_cast(&NewTime) = BlockReference.GlobalTimecode() / GlobalTimecodeScale; KaxCueTrackPositions & NewPositions = AddNewChild(*this); KaxCueTrack & TheTrack = GetChild(NewPositions); *static_cast(&TheTrack) = BlockReference.TrackNumber(); KaxCueClusterPosition & TheClustPos = GetChild(NewPositions); *static_cast(&TheClustPos) = BlockReference.ClusterPosition(); #if MATROSKA_VERSION >= 2 // handle reference use if (BlockReference.ReferenceCount() != 0) { unsigned int i; for (i=0; i(NewPositions); NewRefs.AddReference(BlockReference.Reference(i).RefBlock(), GlobalTimecodeScale); } } KaxCodecState *CodecState = static_cast(BlockReference.FindFirstElt(EBML_INFO(KaxCodecState))); if (CodecState != NULL) { KaxCueCodecState &CueCodecState = AddNewChild(NewPositions); *static_cast(&CueCodecState) = BlockReference.GetParentCluster()->GetParentSegment()->GetRelativePosition(CodecState->GetElementPosition()); } #endif // MATROSKA_VERSION SetValueIsSet(); } void KaxCuePoint::PositionSet(const KaxBlockBlob & BlobReference, uint64 GlobalTimecodeScale) { const KaxInternalBlock &BlockReference = BlobReference; // fill me KaxCueTime & NewTime = GetChild(*this); *static_cast(&NewTime) = BlockReference.GlobalTimecode() / GlobalTimecodeScale; KaxCueTrackPositions & NewPositions = AddNewChild(*this); KaxCueTrack & TheTrack = GetChild(NewPositions); *static_cast(&TheTrack) = BlockReference.TrackNum(); KaxCueClusterPosition & TheClustPos = GetChild(NewPositions); *static_cast(&TheClustPos) = BlockReference.ClusterPosition(); #if 0 // MATROSKA_VERSION >= 2 // handle reference use if (BlockReference.ReferenceCount() != 0) { unsigned int i; for (i=0; i(NewPositions); NewRefs.AddReference(BlockReference.Reference(i).RefBlock(), GlobalTimecodeScale); } } #endif // MATROSKA_VERSION #if MATROSKA_VERSION >= 2 if (!BlobReference.IsSimpleBlock()) { const KaxBlockGroup &BlockGroup = BlobReference; const KaxCodecState *CodecState = static_cast(BlockGroup.FindFirstElt(EBML_INFO(KaxCodecState))); if (CodecState != NULL) { KaxCueCodecState &CueCodecState = AddNewChild(NewPositions); *static_cast(&CueCodecState) = BlockGroup.GetParentCluster()->GetParentSegment()->GetRelativePosition(CodecState->GetElementPosition()); } } #endif // MATROSKA_VERSION SetValueIsSet(); } #if MATROSKA_VERSION >= 2 /*! \todo handle codec state checking */ void KaxCueReference::AddReference(const KaxBlockBlob & BlockReference, uint64 GlobalTimecodeScale) { const KaxInternalBlock & theBlock = BlockReference; KaxCueRefTime & NewTime = GetChild(*this); *static_cast(&NewTime) = theBlock.GlobalTimecode() / GlobalTimecodeScale; KaxCueRefCluster & TheClustPos = GetChild(*this); *static_cast(&TheClustPos) = theBlock.ClusterPosition(); #ifdef OLD // handle recursive reference use if (BlockReference.ReferenceCount() != 0) { unsigned int i; for (i=0; i(EltB); // compare timecode const KaxCueTime * TimeCodeA = static_cast(FindElt(EBML_INFO(KaxCueTime))); if (TimeCodeA == NULL) return false; const KaxCueTime * TimeCodeB = static_cast(theEltB.FindElt(EBML_INFO(KaxCueTime))); if (TimeCodeB == NULL) return false; if (TimeCodeA->IsSmallerThan(TimeCodeB)) return true; if (TimeCodeB->IsSmallerThan(TimeCodeA)) return false; // compare tracks (timecodes are equal) const KaxCueTrack * TrackA = static_cast(FindElt(EBML_INFO(KaxCueTrack))); if (TrackA == NULL) return false; const KaxCueTrack * TrackB = static_cast(theEltB.FindElt(EBML_INFO(KaxCueTrack))); if (TrackB == NULL) return false; if (TrackA->IsSmallerThan(TrackB)) return true; if (TrackB->IsSmallerThan(TrackA)) return false; return false; } bool KaxCuePoint::Timecode(uint64 & aTimecode, uint64 GlobalTimecodeScale) const { const KaxCueTime *aTime = static_cast(FindFirstElt(EBML_INFO(KaxCueTime))); if (aTime == NULL) return false; aTimecode = uint64(*aTime) * GlobalTimecodeScale; return true; } /*! \brief return the position of the Cluster to load */ const KaxCueTrackPositions * KaxCuePoint::GetSeekPosition() const { const KaxCueTrackPositions * result = NULL; uint64 aPosition = EBML_PRETTYLONGINT(0xFFFFFFFFFFFFFFF); // find the position of the "earlier" Cluster const KaxCueTrackPositions *aPoss = static_cast(FindFirstElt(EBML_INFO(KaxCueTrackPositions))); while (aPoss != NULL) { const KaxCueClusterPosition *aPos = static_cast(aPoss->FindFirstElt(EBML_INFO(KaxCueClusterPosition))); if (aPos != NULL && uint64(*aPos) < aPosition) { aPosition = uint64(*aPos); result = aPoss; } aPoss = static_cast(FindNextElt(*aPoss)); } return result; } uint64 KaxCueTrackPositions::ClusterPosition() const { const KaxCueClusterPosition *aPos = static_cast(FindFirstElt(EBML_INFO(KaxCueClusterPosition))); if (aPos == NULL) return 0; return uint64(*aPos); } uint16 KaxCueTrackPositions::TrackNumber() const { const KaxCueTrack *aTrack = static_cast(FindFirstElt(EBML_INFO(KaxCueTrack))); if (aTrack == NULL) return 0; return uint16(*aTrack); } END_LIBMATROSKA_NAMESPACE