parse SeekHead to find Cues

Change-Id: I08334e48c587e08392c29dfa4118eb92eca7c25d
This commit is contained in:
matthewjheaney 2010-10-05 14:12:15 -04:00
parent f56533b30e
commit 6efbd56948
2 changed files with 286 additions and 221 deletions

View File

@ -783,6 +783,7 @@ Segment::Segment(
m_pCues(NULL), m_pCues(NULL),
m_clusters(NULL), m_clusters(NULL),
m_clusterCount(0), m_clusterCount(0),
m_clusterPreloadCount(0),
m_clusterSize(0) m_clusterSize(0)
{ {
} }
@ -790,8 +791,10 @@ Segment::Segment(
Segment::~Segment() Segment::~Segment()
{ {
const long count = m_clusterCount + m_clusterPreloadCount;
Cluster** i = m_clusters; Cluster** i = m_clusters;
Cluster** j = m_clusters + m_clusterCount; Cluster** j = m_clusters + count;
while (i != j) while (i != j)
{ {
@ -996,12 +999,17 @@ long long Segment::ParseHeaders()
m_pCues = new Cues(this, pos, size); m_pCues = new Cues(this, pos, size);
assert(m_pCues); //TODO assert(m_pCues); //TODO
} }
else if (id == 0x014D9B74) //SeekHead ID
{
ParseSeekHead(pos, size);
}
else if (id == 0x0F43B675) //Cluster ID else if (id == 0x0F43B675) //Cluster ID
{ {
bQuit = true; bQuit = true;
} }
m_pos = pos + size; //consume payload if (!bQuit)
m_pos = pos + size; //consume payload
} }
assert(m_pos <= stop); assert(m_pos <= stop);
@ -1232,14 +1240,43 @@ long Segment::LoadCluster()
const long idx = m_clusterCount; const long idx = m_clusterCount;
const long long off = idpos - m_start; const long long off = idpos - m_start;
Cluster* const pCluster = Cluster::Parse(this, idx, off); bool bParse = true;
assert(pCluster);
assert(pCluster->m_index == idx);
AppendCluster(pCluster); if (m_clusterPreloadCount > 0)
assert(m_clusters); {
assert(m_clusterSize > idx); assert(idx < m_clusterSize);
assert(m_clusters[idx] == pCluster);
Cluster* const pCluster = m_clusters[idx];
assert(pCluster);
assert(pCluster->m_index < 0);
const long long pos_ = pCluster->m_pos;
assert(pos_);
const long long pos = pos_ * ((pos_ >= 0) ? 1 : -1);
assert(off <= pos);
if (off == pos) //match
{
pCluster->m_index = idx;
++m_clusterCount;
--m_clusterPreloadCount;
bParse = false;
}
}
if (bParse)
{
Cluster* const pCluster = Cluster::Parse(this, idx, off);
assert(pCluster);
assert(pCluster->m_index == idx);
AppendCluster(pCluster);
assert(m_clusters);
assert(idx < m_clusterSize);
assert(m_clusters[idx] == pCluster);
}
} }
#if 0 //TODO #if 0 //TODO
else if (id == 0x0C53BB6B) //Cues ID else if (id == 0x0C53BB6B) //Cues ID
@ -1266,6 +1303,7 @@ long Segment::LoadCluster()
void Segment::AppendCluster(Cluster* pCluster) void Segment::AppendCluster(Cluster* pCluster)
{ {
assert(pCluster); assert(pCluster);
assert(pCluster->m_index >= 0);
long& size = m_clusterSize; long& size = m_clusterSize;
assert(size >= m_clusterCount); assert(size >= m_clusterCount);
@ -1273,46 +1311,67 @@ void Segment::AppendCluster(Cluster* pCluster)
const long idx = pCluster->m_index; const long idx = pCluster->m_index;
assert(idx == m_clusterCount); assert(idx == m_clusterCount);
if (idx < size) const long count = m_clusterCount + m_clusterPreloadCount;
if (count >= size)
{ {
m_clusters[idx] = pCluster; long n;
++m_clusterCount;
return; if (size > 0)
} n = 2 * size;
else if (m_pInfo == 0)
long n;
if (size > 0)
n = 2 * size;
else if (m_pInfo == 0)
n = 2048;
else
{
const long long ns = m_pInfo->GetDuration();
if (ns <= 0)
n = 2048; n = 2048;
else else
{ {
const long long sec = (ns + 999999999LL) / 1000000000LL; const long long ns = m_pInfo->GetDuration();
n = static_cast<long>(sec);
if (ns <= 0)
n = 2048;
else
{
const long long sec = (ns + 999999999LL) / 1000000000LL;
n = static_cast<long>(sec);
}
} }
Cluster** const qq = new Cluster*[n];
Cluster** q = qq;
Cluster** p = m_clusters;
Cluster** const pp = p + count;
while (p != pp)
*q++ = *p++;
delete[] m_clusters;
m_clusters = qq;
size = n;
} }
Cluster** const qq = new Cluster*[n]; if (m_clusterPreloadCount > 0)
Cluster** q = qq; {
assert(m_clusters);
Cluster** p = m_clusters; Cluster** const p = m_clusters + m_clusterCount;
Cluster** const pp = p + m_clusterCount; assert(*p);
assert((*p)->m_index < 0);
while (p != pp) Cluster** q = p + m_clusterPreloadCount;
*q++ = *p++; assert(q < (m_clusters + size));
delete[] m_clusters; for (;;)
{
Cluster** const qq = q - 1;
assert((*qq)->m_index < 0);
m_clusters = qq; *q = *qq;
size = n; q = qq;
if (q == p)
break;
}
}
m_clusters[idx] = pCluster; m_clusters[idx] = pCluster;
++m_clusterCount; ++m_clusterCount;
@ -1441,160 +1500,166 @@ long Segment::Load()
} }
//#if 0 void Segment::ParseSeekHead(long long start, long long size_)
//void Segment::ParseSeekHead(long long start, long long size_, size_t* pIndex) {
//{ long long pos = start;
// long long pos = start; const long long stop = start + size_;
// const long long stop = start + size_;
// while (pos < stop)
// while (pos < stop) {
// { long len;
// long len;
// const long long id = ReadUInt(m_pReader, pos, len);
// const long long id = ReadUInt(m_pReader, pos, len); assert(id >= 0); //TODO
// assert(id >= 0); //TODO assert((pos + len) <= stop);
// assert((pos + len) <= stop);
// pos += len; //consume ID
// pos += len; //consume ID
// const long long size = ReadUInt(m_pReader, pos, len);
// const long long size = ReadUInt(m_pReader, pos, len); assert(size >= 0);
// assert(size >= 0); assert((pos + len) <= stop);
// assert((pos + len) <= stop);
// pos += len; //consume Size field
// pos += len; //consume Size field assert((pos + size) <= stop);
// assert((pos + size) <= stop);
// if (id == 0x0DBB) //SeekEntry ID
// if (id == 0x0DBB) //SeekEntry ID ParseSeekEntry(pos, size);
// ParseSeekEntry(pos, size, pIndex);
// pos += size; //consume payload
// pos += size; //consume payload assert(pos <= stop);
// assert(pos <= stop); }
// }
// assert(pos == stop);
// assert(pos == stop); }
//}
//
// void Segment::ParseCues(long long off)
//void Segment::ParseSecondarySeekHead(long long off, size_t* pIndex) {
//{ assert(off >= 0);
// assert(off >= 0); assert(off < m_size);
// assert(off < m_size);
// long long pos = m_start + off;
// long long pos = m_start + off; const long long stop = m_start + m_size;
// const long long stop = m_start + m_size;
// long len;
// long len;
// long long result = GetUIntLength(m_pReader, pos, len);
// long long result = GetUIntLength(m_pReader, pos, len); assert(result == 0);
// assert(result == 0); assert((pos + len) <= stop);
// assert((pos + len) <= stop);
// const long long idpos = pos;
// const long long idpos = pos;
// const long long id = ReadUInt(m_pReader, idpos, len);
// const long long id = ReadUInt(m_pReader, idpos, len); assert(id == 0x0C53BB6B); //Cues ID
// assert(id == 0x014D9B74); //SeekHead ID
// pos += len; //consume ID
// pos += len; //consume ID assert(pos < stop);
// assert(pos < stop);
// //Read Size
// //Read Size
// result = GetUIntLength(m_pReader, pos, len);
// result = GetUIntLength(m_pReader, pos, len); assert(result == 0);
// assert(result == 0); assert((pos + len) <= stop);
// assert((pos + len) <= stop);
// const long long size = ReadUInt(m_pReader, pos, len);
// const long long size = ReadUInt(m_pReader, pos, len); assert(size >= 0);
// assert(size >= 0);
// pos += len; //consume length of size of element
// pos += len; //consume length of size of element assert((pos + size) <= stop);
// assert((pos + size) <= stop);
// //Pos now points to start of payload
// //Pos now points to start of payload
// assert(m_pCues == NULL); //TODO: make this check sooner
// ParseSeekHead(pos, size, pIndex);
//} m_pCues = new Cues(this, pos, size);
// assert(m_pCues); //TODO
//void Segment::ParseSeekEntry( }
// long long start,
// long long size_,
// size_t* pIndex) void Segment::ParseSeekEntry(
//{ long long start,
// long long pos = start; long long size_)
// {
// const long long stop = start + size_; long long pos = start;
//
// long len; const long long stop = start + size_;
//
// const long long seekIdId = ReadUInt(m_pReader, pos, len); long len;
// //seekIdId;
// assert(seekIdId == 0x13AB); //SeekID ID const long long seekIdId = ReadUInt(m_pReader, pos, len);
// assert((pos + len) <= stop); //seekIdId;
// assert(seekIdId == 0x13AB); //SeekID ID
// pos += len; //consume id assert((pos + len) <= stop);
//
// const long long seekIdSize = ReadUInt(m_pReader, pos, len); pos += len; //consume id
// assert(seekIdSize >= 0);
// assert((pos + len) <= stop); const long long seekIdSize = ReadUInt(m_pReader, pos, len);
// assert(seekIdSize >= 0);
// pos += len; //consume size assert((pos + len) <= stop);
//
// const long long seekId = ReadUInt(m_pReader, pos, len); //payload pos += len; //consume size
// assert(seekId >= 0);
// assert(len == seekIdSize); const long long seekId = ReadUInt(m_pReader, pos, len); //payload
// assert((pos + len) <= stop); assert(seekId >= 0);
// assert(len == seekIdSize);
// pos += seekIdSize; //consume payload assert((pos + len) <= stop);
//
// const long long seekPosId = ReadUInt(m_pReader, pos, len); pos += seekIdSize; //consume payload
// //seekPosId;
// assert(seekPosId == 0x13AC); //SeekPos ID const long long seekPosId = ReadUInt(m_pReader, pos, len);
// assert((pos + len) <= stop); //seekPosId;
// assert(seekPosId == 0x13AC); //SeekPos ID
// pos += len; //consume id assert((pos + len) <= stop);
//
// const long long seekPosSize = ReadUInt(m_pReader, pos, len); pos += len; //consume id
// assert(seekPosSize >= 0);
// assert((pos + len) <= stop); const long long seekPosSize = ReadUInt(m_pReader, pos, len);
// assert(seekPosSize >= 0);
// pos += len; //consume size assert((pos + len) <= stop);
// assert((pos + seekPosSize) <= stop);
// pos += len; //consume size
// const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize); assert((pos + seekPosSize) <= stop);
// assert(seekOff >= 0);
// assert(seekOff < m_size); const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
// assert(seekOff >= 0);
// pos += seekPosSize; //consume payload assert(seekOff < m_size);
// assert(pos == stop);
// pos += seekPosSize; //consume payload
// const long long seekPos = m_start + seekOff; assert(pos == stop);
// assert(seekPos < (m_start + m_size));
// const long long seekPos = m_start + seekOff;
// if (seekId == 0x0F43B675) //cluster id assert(seekPos < (m_start + m_size));
// {
// if (pIndex == NULL) #if 0
// ++m_clusterCount; if (seekId == 0x0F43B675) //cluster id
// else {
// { if (pIndex == NULL)
// assert(m_clusters); ++m_clusterCount;
// assert(m_clusterCount > 0); else
// {
// size_t& index = *pIndex; assert(m_clusters);
// assert(index < m_clusterCount); assert(m_clusterCount > 0);
//
// Cluster*& pCluster = m_clusters[index]; size_t& index = *pIndex;
// assert(index < m_clusterCount);
// pCluster = Cluster::Parse(this, index, seekOff);
// assert(pCluster); //TODO Cluster*& pCluster = m_clusters[index];
//
// ++index; pCluster = Cluster::Parse(this, index, seekOff);
// } assert(pCluster); //TODO
// }
// else if (seekId == 0x014D9B74) //SeekHead ID ++index;
// { }
// ParseSecondarySeekHead(seekOff, pIndex); }
// } else if (seekId == 0x014D9B74) //SeekHead ID
//} {
//#endif ParseSecondarySeekHead(seekOff, pIndex);
}
#endif
if (seekId == 0x0C53BB6B) //Cues ID
ParseCues(seekOff);
}
Cues::Cues(Segment* pSegment, long long start_, long long size_) : Cues::Cues(Segment* pSegment, long long start_, long long size_) :
@ -3260,7 +3325,7 @@ Cluster::Cluster() :
m_pos(0), m_pos(0),
m_size(0), m_size(0),
m_timecode(0), m_timecode(0),
m_pEntries(NULL), m_entries(NULL),
m_entriesCount(0) m_entriesCount(0)
{ {
} }
@ -3275,7 +3340,7 @@ Cluster::Cluster(
m_pos(off), m_pos(off),
m_size(-1), m_size(-1),
m_timecode(-1), m_timecode(-1),
m_pEntries(NULL), m_entries(NULL),
m_entriesCount(0) m_entriesCount(0)
{ {
} }
@ -3283,8 +3348,8 @@ Cluster::Cluster(
Cluster::~Cluster() Cluster::~Cluster()
{ {
BlockEntry** i = m_pEntries; BlockEntry** i = m_entries;
BlockEntry** const j = m_pEntries + m_entriesCount; BlockEntry** const j = m_entries + m_entriesCount;
while (i != j) while (i != j)
{ {
@ -3294,7 +3359,7 @@ Cluster::~Cluster()
delete p; delete p;
} }
delete[] m_pEntries; delete[] m_entries;
} }
@ -3306,7 +3371,7 @@ bool Cluster::EOS() const
void Cluster::LoadBlockEntries() void Cluster::LoadBlockEntries()
{ {
if (m_pEntries) if (m_entries)
return; return;
assert(m_pSegment); assert(m_pSegment);
@ -3393,7 +3458,7 @@ void Cluster::LoadBlockEntries()
if (m_entriesCount == 0) //TODO: handle empty clusters if (m_entriesCount == 0) //TODO: handle empty clusters
return; return;
m_pEntries = new BlockEntry*[m_entriesCount]; m_entries = new BlockEntry*[m_entriesCount];
size_t index = 0; size_t index = 0;
while (pos < stop) while (pos < stop)
@ -3473,7 +3538,7 @@ long long Cluster::GetFirstTime()
void Cluster::ParseBlockGroup(long long start, long long size, size_t index) void Cluster::ParseBlockGroup(long long start, long long size, size_t index)
{ {
assert(m_pEntries); assert(m_entries);
assert(m_entriesCount); assert(m_entriesCount);
assert(index < m_entriesCount); assert(index < m_entriesCount);
@ -3481,14 +3546,14 @@ void Cluster::ParseBlockGroup(long long start, long long size, size_t index)
new (std::nothrow) BlockGroup(this, index, start, size); new (std::nothrow) BlockGroup(this, index, start, size);
assert(pGroup); //TODO assert(pGroup); //TODO
m_pEntries[index] = pGroup; m_entries[index] = pGroup;
} }
void Cluster::ParseSimpleBlock(long long start, long long size, size_t index) void Cluster::ParseSimpleBlock(long long start, long long size, size_t index)
{ {
assert(m_pEntries); assert(m_entries);
assert(m_entriesCount); assert(m_entriesCount);
assert(index < m_entriesCount); assert(index < m_entriesCount);
@ -3496,7 +3561,7 @@ void Cluster::ParseSimpleBlock(long long start, long long size, size_t index)
new (std::nothrow) SimpleBlock(this, index, start, size); new (std::nothrow) SimpleBlock(this, index, start, size);
assert(pSimpleBlock); //TODO assert(pSimpleBlock); //TODO
m_pEntries[index] = pSimpleBlock; m_entries[index] = pSimpleBlock;
} }
@ -3505,10 +3570,10 @@ const BlockEntry* Cluster::GetFirst()
//TODO: handle empty cluster //TODO: handle empty cluster
LoadBlockEntries(); LoadBlockEntries();
assert(m_pEntries); assert(m_entries);
assert(m_entriesCount >= 1); assert(m_entriesCount >= 1);
const BlockEntry* const pFirst = m_pEntries[0]; const BlockEntry* const pFirst = m_entries[0];
assert(pFirst); assert(pFirst);
return pFirst; return pFirst;
@ -3520,12 +3585,12 @@ const BlockEntry* Cluster::GetLast()
//TODO: handle empty cluster //TODO: handle empty cluster
LoadBlockEntries(); LoadBlockEntries();
assert(m_pEntries); assert(m_entries);
assert(m_entriesCount >= 1); assert(m_entriesCount >= 1);
const size_t idx = m_entriesCount - 1; const size_t idx = m_entriesCount - 1;
const BlockEntry* const pLast = m_pEntries[idx]; const BlockEntry* const pLast = m_entries[idx];
assert(pLast); assert(pLast);
return pLast; return pLast;
@ -3535,19 +3600,19 @@ const BlockEntry* Cluster::GetLast()
const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
{ {
assert(pEntry); assert(pEntry);
assert(m_pEntries); assert(m_entries);
assert(m_entriesCount); assert(m_entriesCount);
size_t idx = pEntry->GetIndex(); size_t idx = pEntry->GetIndex();
assert(idx < m_entriesCount); assert(idx < m_entriesCount);
assert(m_pEntries[idx] == pEntry); assert(m_entries[idx] == pEntry);
++idx; ++idx;
if (idx >= m_entriesCount) if (idx >= m_entriesCount)
return NULL; return NULL;
return m_pEntries[idx]; return m_entries[idx];
} }
@ -3560,7 +3625,7 @@ const BlockEntry* Cluster::GetEntry(const Track* pTrack)
LoadBlockEntries(); LoadBlockEntries();
BlockEntry** i = m_pEntries; BlockEntry** i = m_entries;
assert(i); assert(i);
BlockEntry** const j = i + m_entriesCount; BlockEntry** const j = i + m_entriesCount;
@ -3594,14 +3659,14 @@ Cluster::GetEntry(
assert(tp.m_block > 0); assert(tp.m_block > 0);
LoadBlockEntries(); LoadBlockEntries();
assert(m_pEntries); //TODO: handle empty cluster assert(m_entries); //TODO: handle empty cluster
assert(m_entriesCount > 0); assert(m_entriesCount > 0);
assert(tp.m_block <= (long long)m_entriesCount); //blocks are 1-based assert(tp.m_block <= (long long)m_entriesCount); //blocks are 1-based
const size_t block = static_cast<size_t>(tp.m_block); const size_t block = static_cast<size_t>(tp.m_block);
const size_t index = block - 1; const size_t index = block - 1;
const BlockEntry* const pEntry = m_pEntries[index]; const BlockEntry* const pEntry = m_entries[index];
assert(pEntry); assert(pEntry);
assert(!pEntry->EOS()); assert(!pEntry->EOS());
assert(pEntry->GetBlock()->GetTrackNumber() == tp.m_track); assert(pEntry->GetBlock()->GetTrackNumber() == tp.m_track);
@ -3619,10 +3684,10 @@ const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack)
return pTrack->GetEOS(); return pTrack->GetEOS();
LoadBlockEntries(); LoadBlockEntries();
assert(m_pEntries); assert(m_entries);
BlockEntry** i = m_pEntries + m_entriesCount; BlockEntry** i = m_entries + m_entriesCount;
BlockEntry** const j = m_pEntries; BlockEntry** const j = m_entries;
while (i != j) while (i != j)
{ {

View File

@ -439,7 +439,7 @@ public:
private: private:
long long m_timecode; long long m_timecode;
BlockEntry** m_pEntries; BlockEntry** m_entries;
size_t m_entriesCount; size_t m_entriesCount;
void Load(); void Load();
@ -507,14 +507,14 @@ private:
Tracks* m_pTracks; Tracks* m_pTracks;
Cues* m_pCues; Cues* m_pCues;
Cluster** m_clusters; Cluster** m_clusters;
long m_clusterCount; //number of entries long m_clusterCount; //number of entries for which m_index >= 0
long m_clusterSize; //array size long m_clusterPreloadCount; //number of entries for which m_index < 0
long m_clusterSize; //array size
void AppendCluster(Cluster*); void AppendCluster(Cluster*);
//void ParseSeekHead(long long pos, long long size, size_t*); void ParseSeekHead(long long pos, long long size);
//void ParseSeekEntry(long long pos, long long size, size_t*); void ParseSeekEntry(long long pos, long long size);
//void ParseSecondarySeekHead(long long off, size_t*);
void ParseCues(long long off); void ParseCues(long long off);
bool SearchCues( bool SearchCues(