/**************************************************************************** ** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.** ** Contact license@matroska.org if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ /*! \file \version \$Id: KaxCues.cpp 1265 2007-01-14 17:20:35Z mosu $ \author Steve Lhomme */ #include #include "matroska/KaxCues.h" #include "matroska/KaxCuesData.h" #include "matroska/KaxContexts.h" #include "ebml/EbmlStream.h" #include "matroska/KaxDefines.h" #include "matroska/KaxSemantic.h" // sub elements START_LIBMATROSKA_NAMESPACE KaxCues::~KaxCues() { assert(myTempReferences.empty()); // otherwise that means you have added references and forgot to set the position } /* deprecated and wrong bool KaxCues::AddBlockGroup(const KaxBlockGroup & BlockRef) { // Do not add the element if it's already present. std::vector::iterator ListIdx; KaxBlockBlob *BlockReference = new KaxBlockBlob(BLOCK_BLOB_NO_SIMPLE); BlockReference->SetBlockGroup(*const_cast(&BlockRef)); for (ListIdx = myTempReferences.begin(); ListIdx != myTempReferences.end(); ListIdx++) if (&(KaxBlockGroup&)*ListIdx == &BlockRef) { delete BlockReference; return true; } myTempReferences.push_back(BlockReference); return true; } */ bool KaxCues::AddBlockBlob(const KaxBlockBlob & BlockReference) { // Do not add the element if it's already present. bool present = std::any_of(myTempReferences.begin(), myTempReferences.end(), [&](const KaxBlockBlob *myTempReference) { return myTempReference == &BlockReference; }); if (present) { return true; } myTempReferences.push_back(&BlockReference); return true; } void KaxCues::PositionSet(const KaxBlockBlob & BlockReference) { // look for the element in the temporary references auto it = std::find_if(myTempReferences.begin(), myTempReferences.end(), [&](const KaxBlockBlob *myTempReference){ return myTempReference == &BlockReference; }); if (it != myTempReferences.end()) { // found, now add the element to the entry list auto & NewPoint = AddNewChild(*this); NewPoint.PositionSet(BlockReference, GlobalTimecodeScale()); myTempReferences.erase(it); } } void KaxCues::PositionSet(const KaxBlockGroup & BlockRef) { // look for the element in the temporary references auto it = std::find_if(myTempReferences.begin(), myTempReferences.end(), [&](const KaxBlockBlob *myTempReference) { const KaxInternalBlock &refTmp = *myTempReference; return refTmp.GlobalTimecode() == BlockRef.GlobalTimecode() && refTmp.TrackNum() == BlockRef.TrackNumber(); }); if(it != myTempReferences.end()) { // found, now add the element to the entry list auto & NewPoint = AddNewChild(*this); NewPoint.PositionSet(**it, GlobalTimecodeScale()); myTempReferences.erase(it); } } /*! \warning Assume that the list has been sorted (Sort()) */ const KaxCuePoint * KaxCues::GetTimecodePoint(uint64 aTimecode) const { uint64 TimecodeToLocate = aTimecode / GlobalTimecodeScale(); const KaxCuePoint * aPointPrev = nullptr; 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)) { auto tmp = static_cast(*Itr); // check the tile auto aTime = static_cast(tmp->FindFirstElt(EBML_INFO(KaxCueTime))); if (aTime != nullptr) { auto _Time = uint64(*aTime); if (_Time > aPrevTime && _Time < TimecodeToLocate) { aPrevTime = _Time; aPointPrev = tmp; } if (_Time < aNextTime && _Time > TimecodeToLocate) { aNextTime= _Time; } } } } return aPointPrev; } uint64 KaxCues::GetTimecodePosition(uint64 aTimecode) const { const KaxCuePoint * aPoint = GetTimecodePoint(aTimecode); if (aPoint == nullptr) return 0; const KaxCueTrackPositions * aTrack = aPoint->GetSeekPosition(); if (aTrack == nullptr) return 0; return aTrack->ClusterPosition(); } END_LIBMATROSKA_NAMESPACE