mkvparser: support seek for generic tracks (subtitles)
To support seek in generic tracks with subtitles the audio track implementation of seek is made generic and inherited by audio track. Change-Id: Ic88d2e859d077a1054b2af7d7680cfddfba8a589
This commit is contained in:
committed by
Johan Redestig
parent
0d5b3fc5ae
commit
3af8d02ca1
170
mkvparser.cpp
170
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;
|
||||
|
||||
@@ -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&);
|
||||
|
||||
Reference in New Issue
Block a user