diff --git a/mkvparser.cpp b/mkvparser.cpp index d2f8155..d54654e 100644 --- a/mkvparser.cpp +++ b/mkvparser.cpp @@ -1830,7 +1830,7 @@ void Cues::PreloadCuePoint( cue_points_size = n; } - CuePoint* const pCP = new CuePoint(pos); + CuePoint* const pCP = new CuePoint(m_preload_count, pos); m_cue_points[m_preload_count++] = pCP; } @@ -1880,8 +1880,9 @@ bool Cues::LoadCuePoint() const CuePoint* const pCP = m_cue_points[m_count]; assert(pCP); + assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos)); - pCP->Load(pReader, idpos); + pCP->Load(pReader); ++m_count; --m_preload_count; @@ -1939,7 +1940,7 @@ bool Cues::Find( CuePoint* const pCP = *k; assert(pCP); - pCP->Load(pReader, 0); + pCP->Load(pReader); const long long t = pCP->GetTime(m_pSegment); @@ -2032,7 +2033,50 @@ bool Cues::FindNext( #endif -CuePoint::CuePoint(long long pos) : +bool Cues::GetNext( + const CuePoint* pCurrCP, + const Track* pTrack, + const CuePoint*& pNextCP, + const CuePoint::TrackPosition*& pNextTP) const +{ + assert(pCurrCP); + assert(pCurrCP->GetTimeCode() >= 0); + assert(pTrack); + assert(m_cue_points); + assert(m_count >= 1); + + const size_t count = m_count + m_preload_count; + + size_t index = pCurrCP->m_index; + assert(index < count); + + CuePoint* const* pp = m_cue_points; + assert(pp); + assert(pp[index] == pCurrCP); + + ++index; + + if (index >= count) + return false; + + CuePoint* const p = pp[index]; + assert(p); + + p->Load(m_pSegment->m_pReader); + + pNextCP = p; + + pNextTP = pNextCP->Find(pTrack); + assert(pNextTP); //TODO + + return true; +} + + + + +CuePoint::CuePoint(size_t idx, long long pos) : + m_index(idx), m_timecode(-1 * pos), m_track_positions(NULL), m_track_positions_count(0) @@ -2047,7 +2091,7 @@ CuePoint::~CuePoint() } -void CuePoint::Load(IMkvReader* pReader, long long idpos) +void CuePoint::Load(IMkvReader* pReader) { //odbgstream os; //os << "CuePoint::Load(begin): timecode=" << m_timecode << endl; @@ -2058,8 +2102,7 @@ void CuePoint::Load(IMkvReader* pReader, long long idpos) assert(m_track_positions == NULL); assert(m_track_positions_count == 0); - long long pos_ = -1 * m_timecode; - assert((idpos <= 0) || (idpos == pos_)); + long long pos_ = -m_timecode; long long stop; @@ -2534,7 +2577,7 @@ void Segment::GetCluster( { pCluster = *i; assert(pCluster); - assert(pCluster->m_index == 0); + assert(pCluster->m_index == 0); //m_clusterCount > 0 assert(pCluster->m_pSegment == this); if (time_ns <= pCluster->GetTime()) @@ -2731,9 +2774,7 @@ bool Segment::SearchCues( else { pBlockEntry = pCluster->GetEntry(*pCP, *pTP); - assert(pBlockEntry); - - return true; + return pBlockEntry ? true : false; } } @@ -2748,9 +2789,7 @@ bool Segment::SearchCues( assert(m_clusters[idx] == pCluster); pBlockEntry = pCluster->GetEntry(*pCP, *pTP); - assert(pBlockEntry); - - return true; + return pBlockEntry ? true : false; } @@ -2766,7 +2805,7 @@ const SegmentInfo* Segment::GetInfo() const } -Cues* Segment::GetCues() const +const Cues* Segment::GetCues() const { return m_pCues; } @@ -3986,23 +4025,85 @@ Cluster::GetEntry( const CuePoint::TrackPosition& tp) { assert(m_pSegment); - assert(tp.m_block > 0); LoadBlockEntries(); - assert(m_entries); //TODO: handle empty cluster - assert(m_entriesCount > 0); - assert(tp.m_block <= (long long)m_entriesCount); //blocks are 1-based - const size_t block = static_cast(tp.m_block); - const size_t index = block - 1; + if (m_entries == NULL) + return NULL; - const BlockEntry* const pEntry = m_entries[index]; - assert(pEntry); - assert(!pEntry->EOS()); - assert(pEntry->GetBlock()->GetTrackNumber() == tp.m_track); - assert(pEntry->GetBlock()->GetTimeCode(this) == cp.GetTimeCode()); + const long long count = m_entriesCount; - return pEntry; + if (count <= 0) + return NULL; + + const long long tc = cp.GetTimeCode(); + + if ((tp.m_block > 0) && (tp.m_block <= count)) + { + const size_t block = static_cast(tp.m_block); + const size_t index = block - 1; + + const BlockEntry* const pEntry = m_entries[index]; + assert(pEntry); + assert(!pEntry->EOS()); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + if ((pBlock->GetTrackNumber() == tp.m_track) && + (pBlock->GetTimeCode(this) == tc)) + { + return pEntry; + } + } + + const BlockEntry* const* i = m_entries; + const BlockEntry* const* const j = i + count; + + while (i != j) + { + const BlockEntry* const pEntry = *i++; + assert(pEntry); + assert(!pEntry->EOS()); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + if (pBlock->GetTrackNumber() != tp.m_track) + continue; + + const long long tc_ = pBlock->GetTimeCode(this); + + if (tc_ < tc) + continue; + + if (tc_ > tc) + return NULL; + + const Tracks* const pTracks = m_pSegment->GetTracks(); + assert(pTracks); + + const long tn = static_cast(tp.m_track); + const Track* const pTrack = pTracks->GetTrackByNumber(tn); + + if (pTrack == NULL) + return NULL; + + const long long type = pTrack->GetType(); + + if (type == 2) //audio + return pEntry; + + if (type != 1) //not video + return NULL; + + if (!pBlock->IsKey()) + return NULL; + + return pEntry; + } + + return NULL; } diff --git a/mkvparser.hpp b/mkvparser.hpp index c174727..908c12c 100644 --- a/mkvparser.hpp +++ b/mkvparser.hpp @@ -334,18 +334,19 @@ private: char* m_pTitleAsUTF8; }; - +class Cues; class CuePoint { + friend class Cues; + + CuePoint(size_t, long long); + ~CuePoint(); + CuePoint(const CuePoint&); CuePoint& operator=(const CuePoint&); public: - explicit CuePoint(long long); - ~CuePoint(); - - //void Parse(IMkvReader*, long long start, long long size); - void Load(IMkvReader*, long long); + void Load(IMkvReader*); long long GetTimeCode() const; //absolute but unscaled long long GetTime(Segment*) const; //absolute and scaled (ns units) @@ -365,7 +366,7 @@ public: const TrackPosition* Find(const Track*) const; private: - //long long m_pos; + const size_t m_index; long long m_timecode; TrackPosition* m_track_positions; size_t m_track_positions_count; @@ -375,6 +376,11 @@ private: class Cues { + friend class Segment; + + Cues(Segment*, long long start, long long size); + ~Cues(); + Cues(const Cues&); Cues& operator=(const Cues&); @@ -383,9 +389,6 @@ public: const long long m_start; const long long m_size; - Cues(Segment*, long long start, long long size); - ~Cues(); - bool Find( //lower bound of time_ns long long time_ns, const Track*, @@ -400,6 +403,12 @@ public: const CuePoint::TrackPosition*&) const; #endif + bool GetNext( + const CuePoint*, + const Track*, + const CuePoint*&, + const CuePoint::TrackPosition*&) const; + private: void Init() const; bool LoadCuePoint() const; @@ -514,7 +523,7 @@ public: Cluster*&, const BlockEntry*&); - Cues* GetCues() const; + const Cues* GetCues() const; private: