diff --git a/mkvparser.cpp b/mkvparser.cpp index 7cde951..66348bf 100644 --- a/mkvparser.cpp +++ b/mkvparser.cpp @@ -5878,12 +5878,87 @@ bool Track::VetEntry(const BlockEntry* pBlockEntry) const } long Track::Seek( - long long /* time_ns */ , + long long time_ns, const BlockEntry*& pResult) const { - // TODO(matthewjheaney): need to implement this? - pResult = NULL; - return -1; // generic error + const long status = GetFirst(pResult); + + if (status < 0) //buffer underflow, etc + return status; + + assert(pResult); + + if (pResult->EOS()) + return 0; + + const Cluster* pCluster = pResult->GetCluster(); + assert(pCluster); + assert(pCluster->GetIndex() >= 0); + + if (time_ns <= pResult->GetBlock()->GetTime(pCluster)) + return 0; + + Cluster** const clusters = m_pSegment->m_clusters; + assert(clusters); + + const long count = m_pSegment->GetCount(); //loaded only, not preloaded + assert(count > 0); + + Cluster** const i = clusters + pCluster->GetIndex(); + assert(i); + assert(*i == pCluster); + assert(pCluster->GetTime() <= time_ns); + + Cluster** const j = clusters + count; + + Cluster** lo = i; + Cluster** hi = j; + + while (lo < hi) + { + //INVARIANT: + //[i, lo) <= time_ns + //[lo, hi) ? + //[hi, j) > time_ns + + Cluster** const mid = lo + (hi - lo) / 2; + assert(mid < hi); + + pCluster = *mid; + assert(pCluster); + assert(pCluster->GetIndex() >= 0); + assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters)); + + const long long t = pCluster->GetTime(); + + if (t <= time_ns) + lo = mid + 1; + else + hi = mid; + + assert(lo <= hi); + } + + assert(lo == hi); + assert(lo > i); + assert(lo <= j); + + while (lo > i) + { + pCluster = *--lo; + assert(pCluster); + assert(pCluster->GetTime() <= time_ns); + + pResult = pCluster->GetEntry(this); + + if ((pResult != 0) && !pResult->EOS()) + return 0; + + //landed on empty cluster (no entries) + } + + pResult = GetEOS(); //weird + return 0; } const ContentEncoding* @@ -6341,91 +6416,6 @@ long AudioTrack::Parse( } -long AudioTrack::Seek( - long long time_ns, - const BlockEntry*& pResult) const -{ - const long status = GetFirst(pResult); - - if (status < 0) //buffer underflow, etc - return status; - - assert(pResult); - - if (pResult->EOS()) - return 0; - - const Cluster* pCluster = pResult->GetCluster(); - assert(pCluster); - assert(pCluster->GetIndex() >= 0); - - if (time_ns <= pResult->GetBlock()->GetTime(pCluster)) - return 0; - - Cluster** const clusters = m_pSegment->m_clusters; - assert(clusters); - - const long count = m_pSegment->GetCount(); //loaded only, not preloaded - assert(count > 0); - - Cluster** const i = clusters + pCluster->GetIndex(); - assert(i); - assert(*i == pCluster); - assert(pCluster->GetTime() <= time_ns); - - Cluster** const j = clusters + count; - - Cluster** lo = i; - Cluster** hi = j; - - while (lo < hi) - { - //INVARIANT: - //[i, lo) <= time_ns - //[lo, hi) ? - //[hi, j) > time_ns - - Cluster** const mid = lo + (hi - lo) / 2; - assert(mid < hi); - - pCluster = *mid; - assert(pCluster); - assert(pCluster->GetIndex() >= 0); - assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters)); - - const long long t = pCluster->GetTime(); - - if (t <= time_ns) - lo = mid + 1; - else - hi = mid; - - assert(lo <= hi); - } - - assert(lo == hi); - assert(lo > i); - assert(lo <= j); - - while (lo > i) - { - pCluster = *--lo; - assert(pCluster); - assert(pCluster->GetTime() <= time_ns); - - pResult = pCluster->GetEntry(this); - - if ((pResult != 0) && !pResult->EOS()) - return 0; - - //landed on empty cluster (no entries) - } - - pResult = GetEOS(); //weird - return 0; -} - - double AudioTrack::GetSamplingRate() const { return m_rate; @@ -6835,7 +6825,7 @@ long Tracks::ParseTrackEntry( } else { - // neither video nor audio - probably metadata + // neither video nor audio - probably metadata or subtitles if (a.start >= 0) return E_FILE_FORMAT_INVALID; diff --git a/mkvparser.hpp b/mkvparser.hpp index 8da2b38..d1852b0 100644 --- a/mkvparser.hpp +++ b/mkvparser.hpp @@ -333,7 +333,12 @@ public: long long element_size, Track*&); - enum Type { kVideo = 1, kAudio = 2 }; + enum Type { + kVideo = 1, + kAudio = 2, + kSubtitle = 0x11, + kMetadata = 0x21 + }; Segment* const m_pSegment; const long long m_element_start; @@ -472,7 +477,6 @@ public: double GetSamplingRate() const; long long GetChannels() const; long long GetBitDepth() const; - long Seek(long long time_ns, const BlockEntry*&) const; private: double m_rate; @@ -948,8 +952,8 @@ private: class Segment { friend class Cues; + friend class Track; friend class VideoTrack; - friend class AudioTrack; Segment(const Segment&); Segment& operator=(const Segment&);