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 Track::Seek(
|
||||||
long long /* time_ns */ ,
|
long long time_ns,
|
||||||
const BlockEntry*& pResult) const
|
const BlockEntry*& pResult) const
|
||||||
{
|
{
|
||||||
// TODO(matthewjheaney): need to implement this?
|
const long status = GetFirst(pResult);
|
||||||
pResult = NULL;
|
|
||||||
return -1; // generic error
|
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*
|
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
|
double AudioTrack::GetSamplingRate() const
|
||||||
{
|
{
|
||||||
return m_rate;
|
return m_rate;
|
||||||
@@ -6835,7 +6825,7 @@ long Tracks::ParseTrackEntry(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// neither video nor audio - probably metadata
|
// neither video nor audio - probably metadata or subtitles
|
||||||
|
|
||||||
if (a.start >= 0)
|
if (a.start >= 0)
|
||||||
return E_FILE_FORMAT_INVALID;
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|||||||
@@ -333,7 +333,12 @@ public:
|
|||||||
long long element_size,
|
long long element_size,
|
||||||
Track*&);
|
Track*&);
|
||||||
|
|
||||||
enum Type { kVideo = 1, kAudio = 2 };
|
enum Type {
|
||||||
|
kVideo = 1,
|
||||||
|
kAudio = 2,
|
||||||
|
kSubtitle = 0x11,
|
||||||
|
kMetadata = 0x21
|
||||||
|
};
|
||||||
|
|
||||||
Segment* const m_pSegment;
|
Segment* const m_pSegment;
|
||||||
const long long m_element_start;
|
const long long m_element_start;
|
||||||
@@ -472,7 +477,6 @@ public:
|
|||||||
double GetSamplingRate() const;
|
double GetSamplingRate() const;
|
||||||
long long GetChannels() const;
|
long long GetChannels() const;
|
||||||
long long GetBitDepth() const;
|
long long GetBitDepth() const;
|
||||||
long Seek(long long time_ns, const BlockEntry*&) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_rate;
|
double m_rate;
|
||||||
@@ -948,8 +952,8 @@ private:
|
|||||||
class Segment
|
class Segment
|
||||||
{
|
{
|
||||||
friend class Cues;
|
friend class Cues;
|
||||||
|
friend class Track;
|
||||||
friend class VideoTrack;
|
friend class VideoTrack;
|
||||||
friend class AudioTrack;
|
|
||||||
|
|
||||||
Segment(const Segment&);
|
Segment(const Segment&);
|
||||||
Segment& operator=(const Segment&);
|
Segment& operator=(const Segment&);
|
||||||
|
|||||||
Reference in New Issue
Block a user