separate cue-based searches
Change-Id: I5d98be1c9c5bc33b4ef216f48de22220f38c0f36
This commit is contained in:
205
mkvparser.cpp
205
mkvparser.cpp
@@ -2033,46 +2033,103 @@ bool Cues::FindNext(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool Cues::GetNext(
|
const CuePoint* Cues::GetNext(const CuePoint* pCurr) const
|
||||||
const CuePoint* pCurrCP,
|
|
||||||
const Track* pTrack,
|
|
||||||
const CuePoint*& pNextCP,
|
|
||||||
const CuePoint::TrackPosition*& pNextTP) const
|
|
||||||
{
|
{
|
||||||
assert(pCurrCP);
|
if (pCurr == NULL)
|
||||||
assert(pCurrCP->GetTimeCode() >= 0);
|
return NULL;
|
||||||
assert(pTrack);
|
|
||||||
|
assert(pCurr->GetTimeCode() >= 0);
|
||||||
assert(m_cue_points);
|
assert(m_cue_points);
|
||||||
assert(m_count >= 1);
|
assert(m_count >= 1);
|
||||||
|
|
||||||
const size_t count = m_count + m_preload_count;
|
const size_t count = m_count + m_preload_count;
|
||||||
|
|
||||||
size_t index = pCurrCP->m_index;
|
size_t index = pCurr->m_index;
|
||||||
assert(index < count);
|
assert(index < count);
|
||||||
|
|
||||||
CuePoint* const* pp = m_cue_points;
|
CuePoint* const* const pp = m_cue_points;
|
||||||
assert(pp);
|
assert(pp);
|
||||||
assert(pp[index] == pCurrCP);
|
assert(pp[index] == pCurr);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
|
|
||||||
if (index >= count)
|
if (index >= count)
|
||||||
return false;
|
return NULL;
|
||||||
|
|
||||||
CuePoint* const p = pp[index];
|
CuePoint* const pNext = pp[index];
|
||||||
assert(p);
|
assert(pNext);
|
||||||
|
|
||||||
p->Load(m_pSegment->m_pReader);
|
pNext->Load(m_pSegment->m_pReader);
|
||||||
|
|
||||||
pNextCP = p;
|
return pNext;
|
||||||
|
|
||||||
pNextTP = pNextCP->Find(pTrack);
|
|
||||||
assert(pNextTP); //TODO
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BlockEntry* Cues::GetBlock(
|
||||||
|
const CuePoint* pCP,
|
||||||
|
const CuePoint::TrackPosition* pTP) const
|
||||||
|
{
|
||||||
|
if (pCP == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (pTP == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_pSegment->GetBlock(*pCP, *pTP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BlockEntry* Segment::GetBlock(
|
||||||
|
const CuePoint& cp,
|
||||||
|
const CuePoint::TrackPosition& tp)
|
||||||
|
{
|
||||||
|
Cluster** const ii = m_clusters;
|
||||||
|
Cluster** i = ii;
|
||||||
|
|
||||||
|
const long count = m_clusterCount + m_clusterPreloadCount;
|
||||||
|
|
||||||
|
Cluster** const jj = ii + count;
|
||||||
|
Cluster** j = jj;
|
||||||
|
|
||||||
|
while (i < j)
|
||||||
|
{
|
||||||
|
//INVARIANT:
|
||||||
|
//[ii, i) < pTP->m_pos
|
||||||
|
//[i, j) ?
|
||||||
|
//[j, jj) > pTP->m_pos
|
||||||
|
|
||||||
|
Cluster** const k = i + (j - i) / 2;
|
||||||
|
assert(k < jj);
|
||||||
|
|
||||||
|
Cluster* const pCluster = *k;
|
||||||
|
assert(pCluster);
|
||||||
|
|
||||||
|
const long long pos_ = pCluster->m_pos;
|
||||||
|
assert(pos_);
|
||||||
|
|
||||||
|
const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
|
||||||
|
|
||||||
|
if (pos < tp.m_pos)
|
||||||
|
i = k + 1;
|
||||||
|
else if (pos > tp.m_pos)
|
||||||
|
j = k;
|
||||||
|
else
|
||||||
|
return pCluster->GetEntry(cp, tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(i == j);
|
||||||
|
|
||||||
|
Cluster* const pCluster = Cluster::Parse(this, -1, tp.m_pos);
|
||||||
|
const ptrdiff_t idx = i - m_clusters;
|
||||||
|
|
||||||
|
PreloadCluster(pCluster, idx);
|
||||||
|
assert(m_clusters);
|
||||||
|
assert(m_clusterPreloadCount > 0);
|
||||||
|
assert(m_clusters[idx] == pCluster);
|
||||||
|
|
||||||
|
return pCluster->GetEntry(cp, tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CuePoint::CuePoint(size_t idx, long long pos) :
|
CuePoint::CuePoint(size_t idx, long long pos) :
|
||||||
@@ -2246,9 +2303,9 @@ void CuePoint::TrackPosition::Parse(
|
|||||||
assert(pos <= stop);
|
assert(pos <= stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_track > 0);
|
|
||||||
assert(m_pos >= 0);
|
assert(m_pos >= 0);
|
||||||
assert(m_block > 0);
|
//assert(m_track > 0);
|
||||||
|
//assert(m_block > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2494,7 +2551,7 @@ Cluster* Segment::GetNext(const Cluster* pCurr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Cluster* Segment::GetCluster(long long time_ns)
|
Cluster* Segment::FindCluster(long long time_ns)
|
||||||
{
|
{
|
||||||
if ((m_clusters == NULL) || (m_clusterCount <= 0))
|
if ((m_clusters == NULL) || (m_clusterCount <= 0))
|
||||||
return &m_eos;
|
return &m_eos;
|
||||||
@@ -2552,44 +2609,26 @@ Cluster* Segment::GetCluster(long long time_ns)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Segment::GetCluster(
|
const BlockEntry* Segment::Seek(
|
||||||
long long time_ns,
|
long long time_ns,
|
||||||
Track* pTrack,
|
const Track* pTrack)
|
||||||
Cluster*& pCluster,
|
|
||||||
const BlockEntry*& pBlockEntry,
|
|
||||||
const CuePoint*& pCP,
|
|
||||||
const CuePoint::TrackPosition*& pTP)
|
|
||||||
{
|
{
|
||||||
assert(pTrack);
|
assert(pTrack);
|
||||||
|
|
||||||
if (SearchCues(time_ns, pTrack, pCluster, pBlockEntry, pCP, pTP))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pCP = NULL;
|
|
||||||
pTP = NULL;
|
|
||||||
|
|
||||||
if ((m_clusters == NULL) || (m_clusterCount <= 0))
|
if ((m_clusters == NULL) || (m_clusterCount <= 0))
|
||||||
{
|
return pTrack->GetEOS();
|
||||||
pCluster = &m_eos;
|
|
||||||
pBlockEntry = pTrack->GetEOS();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cluster** const i = m_clusters;
|
Cluster** const i = m_clusters;
|
||||||
assert(i);
|
assert(i);
|
||||||
|
|
||||||
{
|
{
|
||||||
pCluster = *i;
|
Cluster* const pCluster = *i;
|
||||||
assert(pCluster);
|
assert(pCluster);
|
||||||
assert(pCluster->m_index == 0); //m_clusterCount > 0
|
assert(pCluster->m_index == 0); //m_clusterCount > 0
|
||||||
assert(pCluster->m_pSegment == this);
|
assert(pCluster->m_pSegment == this);
|
||||||
|
|
||||||
if (time_ns <= pCluster->GetTime())
|
if (time_ns <= pCluster->GetTime())
|
||||||
{
|
return pCluster->GetEntry(pTrack);
|
||||||
pBlockEntry = pCluster->GetEntry(pTrack);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cluster** const j = i + m_clusterCount;
|
Cluster** const j = i + m_clusterCount;
|
||||||
@@ -2633,12 +2672,11 @@ void Segment::GetCluster(
|
|||||||
assert(lo > i);
|
assert(lo > i);
|
||||||
assert(lo <= j);
|
assert(lo <= j);
|
||||||
|
|
||||||
pCluster = *--lo;
|
Cluster* const pCluster = *--lo;
|
||||||
assert(pCluster);
|
assert(pCluster);
|
||||||
assert(pCluster->GetTime() <= time_ns);
|
assert(pCluster->GetTime() <= time_ns);
|
||||||
|
|
||||||
pBlockEntry = pCluster->GetEntry(pTrack);
|
return pCluster->GetEntry(pTrack);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pTrack->GetType() == 1); //video
|
assert(pTrack->GetType() == 1); //video
|
||||||
@@ -2673,12 +2711,12 @@ void Segment::GetCluster(
|
|||||||
assert(lo > i);
|
assert(lo > i);
|
||||||
assert(lo <= j);
|
assert(lo <= j);
|
||||||
|
|
||||||
pCluster = *--lo;
|
Cluster* pCluster = *--lo;
|
||||||
assert(pCluster);
|
assert(pCluster);
|
||||||
assert(pCluster->GetTime() <= time_ns);
|
assert(pCluster->GetTime() <= time_ns);
|
||||||
|
|
||||||
{
|
{
|
||||||
pBlockEntry = pCluster->GetEntry(pTrack);
|
const BlockEntry* const pBlockEntry = pCluster->GetEntry(pTrack);
|
||||||
assert(pBlockEntry);
|
assert(pBlockEntry);
|
||||||
|
|
||||||
if (!pBlockEntry->EOS()) //found a keyframe
|
if (!pBlockEntry->EOS()) //found a keyframe
|
||||||
@@ -2693,11 +2731,11 @@ void Segment::GetCluster(
|
|||||||
//simply return the first keyframe we find.
|
//simply return the first keyframe we find.
|
||||||
|
|
||||||
if (pBlock->GetTime(pCluster) <= time_ns)
|
if (pBlock->GetTime(pCluster) <= time_ns)
|
||||||
return;
|
return pBlockEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoTrack* const pVideo = static_cast<VideoTrack*>(pTrack);
|
const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);
|
||||||
|
|
||||||
while (lo != i)
|
while (lo != i)
|
||||||
{
|
{
|
||||||
@@ -2705,21 +2743,21 @@ void Segment::GetCluster(
|
|||||||
assert(pCluster);
|
assert(pCluster);
|
||||||
assert(pCluster->GetTime() <= time_ns);
|
assert(pCluster->GetTime() <= time_ns);
|
||||||
|
|
||||||
pBlockEntry = pCluster->GetMaxKey(pVideo);
|
const BlockEntry* const pBlockEntry = pCluster->GetMaxKey(pVideo);
|
||||||
assert(pBlockEntry);
|
assert(pBlockEntry);
|
||||||
|
|
||||||
if (!pBlockEntry->EOS())
|
if (!pBlockEntry->EOS())
|
||||||
return;
|
return pBlockEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
//weird: we're on the first cluster, but no keyframe found
|
//weird: we're on the first cluster, but no keyframe found
|
||||||
//should never happen but we must return something anyway
|
//should never happen but we must return something anyway
|
||||||
|
|
||||||
pCluster = &m_eos;
|
return pTrack->GetEOS();
|
||||||
pBlockEntry = pTrack->GetEOS();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool Segment::SearchCues(
|
bool Segment::SearchCues(
|
||||||
long long time_ns,
|
long long time_ns,
|
||||||
Track* pTrack,
|
Track* pTrack,
|
||||||
@@ -2745,56 +2783,9 @@ bool Segment::SearchCues(
|
|||||||
//so we now need to search for the cluster having
|
//so we now need to search for the cluster having
|
||||||
//the indicated position.
|
//the indicated position.
|
||||||
|
|
||||||
Cluster** const ii = m_clusters;
|
return GetCluster(pCP, pTP, pCluster, pBlockEntry);
|
||||||
Cluster** i = ii;
|
|
||||||
|
|
||||||
const long count = m_clusterCount + m_clusterPreloadCount;
|
|
||||||
|
|
||||||
Cluster** const jj = ii + count;
|
|
||||||
Cluster** j = jj;
|
|
||||||
|
|
||||||
while (i < j)
|
|
||||||
{
|
|
||||||
//INVARIANT:
|
|
||||||
//[ii, i) < pTP->m_pos
|
|
||||||
//[i, j) ?
|
|
||||||
//[j, jj) > pTP->m_pos
|
|
||||||
|
|
||||||
Cluster** const k = i + (j - i) / 2;
|
|
||||||
assert(k < jj);
|
|
||||||
|
|
||||||
pCluster = *k;
|
|
||||||
assert(pCluster);
|
|
||||||
|
|
||||||
const long long pos_ = pCluster->m_pos;
|
|
||||||
assert(pos_);
|
|
||||||
|
|
||||||
const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
|
|
||||||
|
|
||||||
if (pos < pTP->m_pos)
|
|
||||||
i = k + 1;
|
|
||||||
else if (pos > pTP->m_pos)
|
|
||||||
j = k;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pBlockEntry = pCluster->GetEntry(*pCP, *pTP);
|
|
||||||
return pBlockEntry ? true : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(i == j);
|
|
||||||
|
|
||||||
pCluster = Cluster::Parse(this, -1, pTP->m_pos);
|
|
||||||
const ptrdiff_t idx = i - m_clusters;
|
|
||||||
|
|
||||||
PreloadCluster(pCluster, idx);
|
|
||||||
assert(m_clusters);
|
|
||||||
assert(m_clusterPreloadCount > 0);
|
|
||||||
assert(m_clusters[idx] == pCluster);
|
|
||||||
|
|
||||||
pBlockEntry = pCluster->GetEntry(*pCP, *pTP);
|
|
||||||
return pBlockEntry ? true : false;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Tracks* Segment::GetTracks() const
|
Tracks* Segment::GetTracks() const
|
||||||
|
|||||||
@@ -403,11 +403,11 @@ public:
|
|||||||
const CuePoint::TrackPosition*&) const;
|
const CuePoint::TrackPosition*&) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool GetNext(
|
const CuePoint* GetNext(const CuePoint*) const;
|
||||||
const CuePoint*,
|
|
||||||
const Track*,
|
const BlockEntry* GetBlock(
|
||||||
const CuePoint*&,
|
const CuePoint*,
|
||||||
const CuePoint::TrackPosition*&) const;
|
const CuePoint::TrackPosition*) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init() const;
|
void Init() const;
|
||||||
@@ -474,6 +474,8 @@ private:
|
|||||||
|
|
||||||
class Segment
|
class Segment
|
||||||
{
|
{
|
||||||
|
friend class Cues;
|
||||||
|
|
||||||
Segment(const Segment&);
|
Segment(const Segment&);
|
||||||
Segment& operator=(const Segment&);
|
Segment& operator=(const Segment&);
|
||||||
|
|
||||||
@@ -505,27 +507,17 @@ public:
|
|||||||
|
|
||||||
Tracks* GetTracks() const;
|
Tracks* GetTracks() const;
|
||||||
const SegmentInfo* GetInfo() const;
|
const SegmentInfo* GetInfo() const;
|
||||||
|
const Cues* GetCues() const;
|
||||||
|
|
||||||
long long GetDuration() const;
|
long long GetDuration() const;
|
||||||
|
|
||||||
//NOTE: this turned out to be too inefficient.
|
unsigned long GetCount() const;
|
||||||
//long long Load(long long time_nanoseconds);
|
|
||||||
|
|
||||||
Cluster* GetFirst();
|
Cluster* GetFirst();
|
||||||
Cluster* GetLast();
|
Cluster* GetLast();
|
||||||
unsigned long GetCount() const;
|
|
||||||
|
|
||||||
Cluster* GetNext(const Cluster*);
|
Cluster* GetNext(const Cluster*);
|
||||||
Cluster* GetCluster(long long time_nanoseconds);
|
|
||||||
|
|
||||||
void GetCluster(
|
Cluster* FindCluster(long long time_nanoseconds);
|
||||||
long long time_nanoseconds,
|
const BlockEntry* Seek(long long time_nanoseconds, const Track*);
|
||||||
Track*,
|
|
||||||
Cluster*&,
|
|
||||||
const BlockEntry*&,
|
|
||||||
const CuePoint*&,
|
|
||||||
const CuePoint::TrackPosition*&);
|
|
||||||
|
|
||||||
const Cues* GetCues() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -545,13 +537,9 @@ private:
|
|||||||
void ParseSeekEntry(long long pos, long long size);
|
void ParseSeekEntry(long long pos, long long size);
|
||||||
void ParseCues(long long);
|
void ParseCues(long long);
|
||||||
|
|
||||||
bool SearchCues(
|
const BlockEntry* GetBlock(
|
||||||
long long time_ns,
|
const CuePoint&,
|
||||||
Track*,
|
const CuePoint::TrackPosition&);
|
||||||
Cluster*&,
|
|
||||||
const BlockEntry*&,
|
|
||||||
const CuePoint*&,
|
|
||||||
const CuePoint::TrackPosition*&);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user