Compare commits
1 Commits
libwebm-1.
...
libwebm-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fa7c7611c |
487
mkvparser.cpp
487
mkvparser.cpp
@@ -21,7 +21,7 @@ void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)
|
||||
major = 1;
|
||||
minor = 0;
|
||||
build = 0;
|
||||
revision = 22;
|
||||
revision = 23;
|
||||
}
|
||||
|
||||
long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
|
||||
@@ -5404,7 +5404,10 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const
|
||||
return E_BUFFER_NOT_FULL;
|
||||
}
|
||||
|
||||
pBlockEntry = pCluster->GetFirst();
|
||||
long status = pCluster->GetFirst(pBlockEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (pBlockEntry == 0) //empty cluster
|
||||
{
|
||||
@@ -5422,10 +5425,17 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const
|
||||
if ((tn == m_info.number) && VetEntry(pBlockEntry))
|
||||
return 0;
|
||||
|
||||
pBlockEntry = pCluster->GetNext(pBlockEntry);
|
||||
const BlockEntry* pNextEntry;
|
||||
|
||||
if (pBlockEntry == 0)
|
||||
status = pCluster->GetNext(pBlockEntry, pNextEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (pNextEntry == 0)
|
||||
break;
|
||||
|
||||
pBlockEntry = pNextEntry;
|
||||
}
|
||||
|
||||
++i;
|
||||
@@ -5459,7 +5469,10 @@ long Track::GetNext(
|
||||
assert(pCluster);
|
||||
assert(!pCluster->EOS());
|
||||
|
||||
pNextEntry = pCluster->GetNext(pCurrEntry);
|
||||
long status = pCluster->GetNext(pCurrEntry, pNextEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
for (int i = 0; ; )
|
||||
{
|
||||
@@ -5471,7 +5484,12 @@ long Track::GetNext(
|
||||
if (pNextBlock->GetTrackNumber() == m_info.number)
|
||||
return 0;
|
||||
|
||||
pNextEntry = pCluster->GetNext(pNextEntry);
|
||||
pCurrEntry = pNextEntry;
|
||||
|
||||
status = pCluster->GetNext(pCurrEntry, pNextEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
}
|
||||
|
||||
pCluster = m_pSegment->GetNext(pCluster);
|
||||
@@ -5514,7 +5532,10 @@ long Track::GetNext(
|
||||
return E_BUFFER_NOT_FULL;
|
||||
}
|
||||
|
||||
pNextEntry = pCluster->GetFirst();
|
||||
status = pCluster->GetFirst(pNextEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (pNextEntry == NULL) //empty cluster
|
||||
continue;
|
||||
@@ -5632,7 +5653,6 @@ Track::EOSBlock::EOSBlock() :
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BlockEntry::Kind Track::EOSBlock::GetKind() const
|
||||
{
|
||||
return kBlockEOS;
|
||||
@@ -6767,11 +6787,13 @@ long Cluster::Parse(long long& pos, long& len) const
|
||||
return E_BUFFER_NOT_FULL;
|
||||
}
|
||||
|
||||
Cluster* const this_ = const_cast<Cluster*>(this);
|
||||
|
||||
if (id == 0x20) //BlockGroup
|
||||
return ParseBlockGroup(size, pos, len);
|
||||
return this_->ParseBlockGroup(size, pos, len);
|
||||
|
||||
if (id == 0x23) //SimpleBlock
|
||||
return ParseSimpleBlock(size, pos, len);
|
||||
return this_->ParseSimpleBlock(size, pos, len);
|
||||
|
||||
pos += size; //consume payload
|
||||
assert((cluster_stop < 0) || (pos <= cluster_stop));
|
||||
@@ -6813,7 +6835,7 @@ long Cluster::Parse(long long& pos, long& len) const
|
||||
long Cluster::ParseSimpleBlock(
|
||||
long long block_size,
|
||||
long long& pos,
|
||||
long& len) const
|
||||
long& len)
|
||||
{
|
||||
const long long block_start = pos;
|
||||
const long long block_stop = pos + block_size;
|
||||
@@ -6915,7 +6937,11 @@ long Cluster::ParseSimpleBlock(
|
||||
return E_BUFFER_NOT_FULL;
|
||||
}
|
||||
|
||||
CreateBlock(0x23, block_start, block_size); //simple block id
|
||||
status = CreateBlock(0x23, block_start, block_size); //simple block id
|
||||
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
m_pos = block_stop;
|
||||
|
||||
return 0; //success
|
||||
@@ -6925,7 +6951,7 @@ long Cluster::ParseSimpleBlock(
|
||||
long Cluster::ParseBlockGroup(
|
||||
long long payload_size,
|
||||
long long& pos,
|
||||
long& len) const
|
||||
long& len)
|
||||
{
|
||||
const long long payload_start = pos;
|
||||
const long long payload_stop = pos + payload_size;
|
||||
@@ -7133,7 +7159,11 @@ long Cluster::ParseBlockGroup(
|
||||
|
||||
assert(pos == payload_stop);
|
||||
|
||||
CreateBlock(0x20, payload_start, payload_size); //BlockGroup ID
|
||||
status = CreateBlock(0x20, payload_start, payload_size); //BlockGroup ID
|
||||
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
m_pos = payload_stop;
|
||||
|
||||
return 0; //success
|
||||
@@ -7595,7 +7625,12 @@ long long Cluster::GetTime() const
|
||||
|
||||
long long Cluster::GetFirstTime() const
|
||||
{
|
||||
const BlockEntry* const pEntry = GetFirst();
|
||||
const BlockEntry* pEntry;
|
||||
|
||||
const long status = GetFirst(pEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (pEntry == NULL) //empty cluster
|
||||
return GetTime();
|
||||
@@ -7609,7 +7644,12 @@ long long Cluster::GetFirstTime() const
|
||||
|
||||
long long Cluster::GetLastTime() const
|
||||
{
|
||||
const BlockEntry* const pEntry = GetLast();
|
||||
const BlockEntry* pEntry;
|
||||
|
||||
const long status = GetLast(pEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (pEntry == NULL) //empty cluster
|
||||
return GetTime();
|
||||
@@ -7621,12 +7661,12 @@ long long Cluster::GetLastTime() const
|
||||
}
|
||||
|
||||
|
||||
void Cluster::CreateBlock(
|
||||
long Cluster::CreateBlock(
|
||||
long long id,
|
||||
long long pos, //absolute pos of payload
|
||||
long long size) const
|
||||
long long size)
|
||||
{
|
||||
BlockEntry** ppEntry;
|
||||
assert((id == 0x20) || (id == 0x23)); //BlockGroup or SimpleBlock
|
||||
|
||||
if (m_entries_count < 0) //haven't parsed anything yet
|
||||
{
|
||||
@@ -7636,14 +7676,12 @@ void Cluster::CreateBlock(
|
||||
m_entries_size = 1024;
|
||||
m_entries = new BlockEntry*[m_entries_size];
|
||||
|
||||
ppEntry = m_entries;
|
||||
m_entries_count = 1;
|
||||
m_entries_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_entries);
|
||||
assert(m_entries_size > 0);
|
||||
assert(m_entries_count > 0);
|
||||
assert(m_entries_count <= m_entries_size);
|
||||
|
||||
if (m_entries_count >= m_entries_size)
|
||||
@@ -7666,36 +7704,23 @@ void Cluster::CreateBlock(
|
||||
m_entries = entries;
|
||||
m_entries_size = entries_size;
|
||||
}
|
||||
|
||||
ppEntry = m_entries + m_entries_count;
|
||||
++m_entries_count;
|
||||
}
|
||||
|
||||
if (id == 0x20) //BlockGroup ID
|
||||
CreateBlockGroup(pos, size, ppEntry);
|
||||
else
|
||||
{
|
||||
assert(id == 0x23); //SimpleBlock ID
|
||||
CreateSimpleBlock(pos, size, ppEntry);
|
||||
}
|
||||
return CreateBlockGroup(pos, size);
|
||||
else //SimpleBlock ID
|
||||
return CreateSimpleBlock(pos, size);
|
||||
}
|
||||
|
||||
|
||||
void Cluster::CreateBlockGroup(
|
||||
long Cluster::CreateBlockGroup(
|
||||
long long st,
|
||||
long long sz,
|
||||
BlockEntry**& ppEntry) const
|
||||
long long sz)
|
||||
{
|
||||
assert(m_entries);
|
||||
assert(m_entries_size > 0);
|
||||
assert(ppEntry);
|
||||
assert(ppEntry >= m_entries);
|
||||
|
||||
const ptrdiff_t idx = ppEntry - m_entries;
|
||||
assert(idx >= 0);
|
||||
assert(idx < m_entries_size);
|
||||
|
||||
Cluster* const this_ = const_cast<Cluster*>(this);
|
||||
assert(m_entries_count >= 0);
|
||||
assert(m_entries_count < m_entries_size);
|
||||
|
||||
IMkvReader* const pReader = m_pSegment->m_pReader;
|
||||
|
||||
@@ -7769,133 +7794,185 @@ void Cluster::CreateBlockGroup(
|
||||
assert(bpos >= 0);
|
||||
assert(bsize >= 0);
|
||||
|
||||
*ppEntry++ = new BlockGroup(this_, idx, bpos, bsize, prev, next, duration);
|
||||
const long idx = m_entries_count;
|
||||
|
||||
BlockEntry** const ppEntry = m_entries + idx;
|
||||
BlockEntry*& pEntry = *ppEntry;
|
||||
|
||||
pEntry = new (std::nothrow) BlockGroup(
|
||||
this,
|
||||
idx,
|
||||
bpos,
|
||||
bsize,
|
||||
prev,
|
||||
next,
|
||||
duration);
|
||||
|
||||
if (pEntry == NULL)
|
||||
return -1; //generic error
|
||||
|
||||
BlockGroup* const p = static_cast<BlockGroup*>(pEntry);
|
||||
|
||||
const long status = p->Parse();
|
||||
|
||||
if (status == 0) //success
|
||||
{
|
||||
++m_entries_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete pEntry;
|
||||
pEntry = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Cluster::CreateSimpleBlock(
|
||||
long Cluster::CreateSimpleBlock(
|
||||
long long st,
|
||||
long long sz,
|
||||
BlockEntry**& ppEntry) const
|
||||
long long sz)
|
||||
{
|
||||
assert(m_entries);
|
||||
assert(m_entries_size > 0);
|
||||
assert(ppEntry);
|
||||
assert(ppEntry >= m_entries);
|
||||
assert(m_entries_count >= 0);
|
||||
assert(m_entries_count < m_entries_size);
|
||||
|
||||
const ptrdiff_t idx = ppEntry - m_entries;
|
||||
assert(idx >= 0);
|
||||
assert(idx < m_entries_size);
|
||||
const long idx = m_entries_count;
|
||||
|
||||
Cluster* const this_ = const_cast<Cluster*>(this);
|
||||
*ppEntry++ = new SimpleBlock(this_, idx, st, sz);
|
||||
BlockEntry** const ppEntry = m_entries + idx;
|
||||
BlockEntry*& pEntry = *ppEntry;
|
||||
|
||||
pEntry = new (std::nothrow) SimpleBlock(this, idx, st, sz);
|
||||
|
||||
if (pEntry == NULL)
|
||||
return -1; //generic error
|
||||
|
||||
SimpleBlock* const p = static_cast<SimpleBlock*>(pEntry);
|
||||
|
||||
const long status = p->Parse();
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
++m_entries_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete pEntry;
|
||||
pEntry = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
const BlockEntry* Cluster::GetFirst() const
|
||||
long Cluster::GetFirst(const BlockEntry*& pFirst) const
|
||||
{
|
||||
#if 0
|
||||
LoadBlockEntries();
|
||||
|
||||
if ((m_entries == NULL) || (m_entries_count <= 0))
|
||||
return NULL;
|
||||
#else
|
||||
if (m_entries_count <= 0)
|
||||
{
|
||||
long long pos;
|
||||
long len;
|
||||
|
||||
const long status = Parse(pos, len);
|
||||
assert(status >= 0);
|
||||
|
||||
if (m_entries_count <= 0)
|
||||
return NULL; //empty cluster
|
||||
if (status < 0) //error
|
||||
{
|
||||
pFirst = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
assert(m_entries);
|
||||
assert(m_entries_count > 0);
|
||||
if (m_entries_count <= 0) //empty cluster
|
||||
{
|
||||
pFirst = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const BlockEntry* const pFirst = m_entries[0];
|
||||
assert(m_entries);
|
||||
|
||||
pFirst = m_entries[0];
|
||||
assert(pFirst);
|
||||
|
||||
return pFirst;
|
||||
return 0; //success
|
||||
}
|
||||
|
||||
|
||||
const BlockEntry* Cluster::GetLast() const
|
||||
long Cluster::GetLast(const BlockEntry*& pLast) const
|
||||
{
|
||||
#if 0
|
||||
LoadBlockEntries();
|
||||
|
||||
if ((m_entries == NULL) || (m_entries_count <= 0))
|
||||
return NULL;
|
||||
#else
|
||||
for (;;)
|
||||
{
|
||||
long long pos;
|
||||
long len;
|
||||
|
||||
const long status = Parse(pos, len);
|
||||
assert(status >= 0);
|
||||
|
||||
if (status != 0) //no new block
|
||||
if (status < 0) //error
|
||||
{
|
||||
pLast = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status > 0) //no new block
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_entries_count <= 0)
|
||||
return NULL;
|
||||
{
|
||||
pLast = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(m_entries);
|
||||
#endif
|
||||
|
||||
const long idx = m_entries_count - 1;
|
||||
|
||||
const BlockEntry* const pLast = m_entries[idx];
|
||||
pLast = m_entries[idx];
|
||||
assert(pLast);
|
||||
|
||||
return pLast;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
|
||||
long Cluster::GetNext(
|
||||
const BlockEntry* pCurr,
|
||||
const BlockEntry*& pNext) const
|
||||
{
|
||||
assert(pEntry);
|
||||
assert(m_entries != NULL);
|
||||
assert(pCurr);
|
||||
assert(m_entries);
|
||||
assert(m_entries_count > 0);
|
||||
|
||||
size_t idx = pEntry->GetIndex();
|
||||
size_t idx = pCurr->GetIndex();
|
||||
assert(idx < size_t(m_entries_count));
|
||||
assert(m_entries[idx] == pEntry);
|
||||
assert(m_entries[idx] == pCurr);
|
||||
|
||||
++idx;
|
||||
|
||||
#if 0
|
||||
if (idx >= size_t(m_entries_count))
|
||||
return NULL;
|
||||
#else
|
||||
if (idx >= size_t(m_entries_count))
|
||||
{
|
||||
long long pos;
|
||||
long len;
|
||||
|
||||
const long status = Parse(pos, len);
|
||||
assert(status >= 0);
|
||||
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
if (status < 0) //error
|
||||
{
|
||||
pNext = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status > 0)
|
||||
return NULL;
|
||||
{
|
||||
pNext = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(m_entries);
|
||||
assert(m_entries_count > 0);
|
||||
assert(idx < size_t(m_entries_count));
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_entries[idx];
|
||||
pNext = m_entries[idx];
|
||||
assert(pNext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8313,11 +8390,17 @@ SimpleBlock::SimpleBlock(
|
||||
long long start,
|
||||
long long size) :
|
||||
BlockEntry(pCluster, idx),
|
||||
m_block(start, size, pCluster->m_pSegment->m_pReader)
|
||||
m_block(start, size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
long SimpleBlock::Parse()
|
||||
{
|
||||
return m_block.Parse(m_pCluster->m_pSegment->m_pReader);
|
||||
}
|
||||
|
||||
|
||||
BlockEntry::Kind SimpleBlock::GetKind() const
|
||||
{
|
||||
return kBlockSimple;
|
||||
@@ -8339,12 +8422,24 @@ BlockGroup::BlockGroup(
|
||||
long long next,
|
||||
long long duration) :
|
||||
BlockEntry(pCluster, idx),
|
||||
m_block(block_start, block_size, pCluster->m_pSegment->m_pReader),
|
||||
m_block(block_start, block_size),
|
||||
m_prev(prev),
|
||||
m_next(next),
|
||||
m_duration(duration)
|
||||
{
|
||||
m_block.SetKey((prev > 0) && (next <= 0));
|
||||
}
|
||||
|
||||
|
||||
long BlockGroup::Parse()
|
||||
{
|
||||
const long status = m_block.Parse(m_pCluster->m_pSegment->m_pReader);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
m_block.SetKey((m_prev > 0) && (m_next <= 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8389,56 +8484,86 @@ long long BlockGroup::GetNextTimeCode() const
|
||||
}
|
||||
|
||||
|
||||
Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
Block::Block(long long start, long long size_) :
|
||||
m_start(start),
|
||||
m_size(size_)
|
||||
m_size(size_),
|
||||
m_track(0),
|
||||
m_timecode(-1),
|
||||
m_flags(0),
|
||||
m_frames(NULL),
|
||||
m_frame_count(-1)
|
||||
{
|
||||
long long pos = start;
|
||||
const long long stop = start + size_;
|
||||
}
|
||||
|
||||
|
||||
Block::~Block()
|
||||
{
|
||||
delete[] m_frames;
|
||||
}
|
||||
|
||||
|
||||
long Block::Parse(IMkvReader* pReader)
|
||||
{
|
||||
assert(pReader);
|
||||
assert(m_start >= 0);
|
||||
assert(m_size >= 0);
|
||||
assert(m_track <= 0);
|
||||
assert(m_frames == NULL);
|
||||
assert(m_frame_count <= 0);
|
||||
|
||||
long long pos = m_start;
|
||||
const long long stop = m_start + m_size;
|
||||
|
||||
long len;
|
||||
|
||||
m_track = ReadUInt(pReader, pos, len);
|
||||
assert(m_track > 0);
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
if (m_track <= 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if ((pos + len) > stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
pos += len; //consume track number
|
||||
assert((stop - pos) >= 2);
|
||||
|
||||
if ((stop - pos) < 2)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
long status;
|
||||
|
||||
#if 0
|
||||
m_timecode = Unserialize2SInt(pReader, pos);
|
||||
#else
|
||||
long long value;
|
||||
|
||||
status = UnserializeInt(pReader, pos, 2, value);
|
||||
assert(status == 0);
|
||||
assert(value >= SHRT_MIN);
|
||||
assert(value <= SHRT_MAX);
|
||||
|
||||
if (status)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if (value < SHRT_MIN)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if (value > SHRT_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
m_timecode = static_cast<short>(value);
|
||||
#endif
|
||||
|
||||
pos += 2;
|
||||
assert((stop - pos) >= 1);
|
||||
|
||||
if ((stop - pos) <= 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
status = pReader->Read(pos, 1, &m_flags);
|
||||
assert(status == 0);
|
||||
|
||||
#if 0
|
||||
const int invisible = int(m_flags & 0x08) >> 3;
|
||||
invisible;
|
||||
assert(!invisible); //TODO
|
||||
#endif
|
||||
if (status)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
const int lacing = int(m_flags & 0x06) >> 1;
|
||||
|
||||
++pos; //consume flags byte
|
||||
assert(pos <= stop);
|
||||
|
||||
if (lacing == 0) //no lacing
|
||||
{
|
||||
if (pos > stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
m_frame_count = 1;
|
||||
m_frames = new Frame[m_frame_count];
|
||||
|
||||
@@ -8446,19 +8571,24 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
f.pos = pos;
|
||||
|
||||
const long long frame_size = stop - pos;
|
||||
assert(frame_size <= LONG_MAX);
|
||||
|
||||
if (frame_size > LONG_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
f.len = static_cast<long>(frame_size);
|
||||
|
||||
return;
|
||||
return 0; //success
|
||||
}
|
||||
|
||||
assert(pos < stop);
|
||||
if (pos >= stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
unsigned char biased_count;
|
||||
|
||||
status = pReader->Read(pos, 1, &biased_count);
|
||||
assert(status == 0);
|
||||
|
||||
if (status)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
++pos; //consume frame count
|
||||
assert(pos <= stop);
|
||||
@@ -8484,8 +8614,13 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
if (pos >= stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
status = pReader->Read(pos, 1, &val);
|
||||
assert(status == 0);
|
||||
|
||||
if (status)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
++pos; //consume xiph size byte
|
||||
|
||||
@@ -8498,6 +8633,8 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
Frame& f = *pf++;
|
||||
assert(pf < pf_end);
|
||||
|
||||
f.pos = 0; //patch later
|
||||
|
||||
f.len = frame_size;
|
||||
size += frame_size; //contribution of this frame
|
||||
|
||||
@@ -8505,17 +8642,25 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
}
|
||||
|
||||
assert(pf < pf_end);
|
||||
assert(pos < stop);
|
||||
assert(pos <= stop);
|
||||
|
||||
{
|
||||
Frame& f = *pf++;
|
||||
assert(pf == pf_end);
|
||||
|
||||
if (pf != pf_end)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
f.pos = 0; //patch later
|
||||
|
||||
const long long total_size = stop - pos;
|
||||
assert(total_size > size);
|
||||
|
||||
if (total_size < size)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
const long long frame_size = total_size - size;
|
||||
assert(frame_size <= LONG_MAX);
|
||||
|
||||
if (frame_size > LONG_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
f.len = static_cast<long>(frame_size);
|
||||
}
|
||||
@@ -8535,10 +8680,14 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
else if (lacing == 2) //fixed-size lacing
|
||||
{
|
||||
const long long total_size = stop - pos;
|
||||
assert((total_size % m_frame_count) == 0);
|
||||
|
||||
if ((total_size % m_frame_count) != 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
const long long frame_size = total_size / m_frame_count;
|
||||
assert(frame_size <= LONG_MAX);
|
||||
|
||||
if (frame_size > LONG_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
Frame* pf = m_frames;
|
||||
Frame* const pf_end = pf + m_frame_count;
|
||||
@@ -8560,18 +8709,28 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
else
|
||||
{
|
||||
assert(lacing == 3); //EBML lacing
|
||||
assert(pos < stop);
|
||||
|
||||
if (pos >= stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
long size = 0;
|
||||
int frame_count = m_frame_count;
|
||||
|
||||
long long frame_size = ReadUInt(pReader, pos, len);
|
||||
assert(frame_size > 0);
|
||||
assert(frame_size <= LONG_MAX);
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
if (frame_size < 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if (frame_size > LONG_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if ((pos + len) > stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
pos += len; //consume length of size of first frame
|
||||
assert((pos + frame_size) <= stop);
|
||||
|
||||
if ((pos + frame_size) > stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
Frame* pf = m_frames;
|
||||
Frame* const pf_end = pf + m_frame_count;
|
||||
@@ -8579,6 +8738,8 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
{
|
||||
Frame& curr = *pf;
|
||||
|
||||
curr.pos = 0; //patch later
|
||||
|
||||
curr.len = static_cast<long>(frame_size);
|
||||
size += curr.len; //contribution of this frame
|
||||
}
|
||||
@@ -8587,18 +8748,27 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
|
||||
while (frame_count > 1)
|
||||
{
|
||||
assert(pos < stop);
|
||||
if (pos >= stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
assert(pf < pf_end);
|
||||
|
||||
const Frame& prev = *pf++;
|
||||
assert(pf < pf_end);
|
||||
assert(prev.len == frame_size);
|
||||
|
||||
assert(pf < pf_end);
|
||||
|
||||
Frame& curr = *pf;
|
||||
|
||||
curr.pos = 0; //patch later
|
||||
|
||||
const long long delta_size_ = ReadUInt(pReader, pos, len);
|
||||
assert(delta_size_ >= 0);
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
if (delta_size_ < 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if ((pos + len) > stop)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
pos += len; //consume length of (delta) size
|
||||
assert(pos <= stop);
|
||||
@@ -8608,8 +8778,12 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
const long long delta_size = delta_size_ - bias;
|
||||
|
||||
frame_size += delta_size;
|
||||
assert(frame_size > 0);
|
||||
assert(frame_size <= LONG_MAX);
|
||||
|
||||
if (frame_size < 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if (frame_size > LONG_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
curr.len = static_cast<long>(frame_size);
|
||||
size += curr.len; //contribution of this frame
|
||||
@@ -8618,23 +8792,28 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
}
|
||||
|
||||
{
|
||||
assert(pos < stop);
|
||||
assert(pos <= stop);
|
||||
assert(pf < pf_end);
|
||||
|
||||
const Frame& prev = *pf++;
|
||||
assert(pf < pf_end);
|
||||
assert(prev.len == frame_size);
|
||||
|
||||
assert(pf < pf_end);
|
||||
|
||||
Frame& curr = *pf++;
|
||||
assert(pf == pf_end);
|
||||
|
||||
curr.pos = 0; //patch later
|
||||
|
||||
const long long total_size = stop - pos;
|
||||
assert(total_size > 0);
|
||||
assert(total_size > size);
|
||||
|
||||
if (total_size < size)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
frame_size = total_size - size;
|
||||
assert(frame_size > 0);
|
||||
assert(frame_size <= LONG_MAX);
|
||||
|
||||
if (frame_size > LONG_MAX)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
curr.len = static_cast<long>(frame_size);
|
||||
}
|
||||
@@ -8651,12 +8830,8 @@ Block::Block(long long start, long long size_, IMkvReader* pReader) :
|
||||
|
||||
assert(pos == stop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Block::~Block()
|
||||
{
|
||||
delete[] m_frames;
|
||||
return 0; //success
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -80,9 +80,11 @@ public:
|
||||
const long long m_start;
|
||||
const long long m_size;
|
||||
|
||||
Block(long long start, long long size, IMkvReader*);
|
||||
Block(long long start, long long size);
|
||||
~Block();
|
||||
|
||||
long Parse(IMkvReader*);
|
||||
|
||||
long long GetTrackNumber() const;
|
||||
long long GetTimeCode(const Cluster*) const; //absolute, but not scaled
|
||||
long long GetTime(const Cluster*) const; //absolute, and scaled (ns)
|
||||
@@ -126,6 +128,7 @@ protected:
|
||||
|
||||
public:
|
||||
virtual ~BlockEntry();
|
||||
|
||||
bool EOS() const;
|
||||
const Cluster* GetCluster() const;
|
||||
long GetIndex() const;
|
||||
@@ -148,6 +151,7 @@ class SimpleBlock : public BlockEntry
|
||||
|
||||
public:
|
||||
SimpleBlock(Cluster*, long index, long long start, long long size);
|
||||
long Parse();
|
||||
|
||||
Kind GetKind() const;
|
||||
const Block* GetBlock() const;
|
||||
@@ -173,6 +177,8 @@ public:
|
||||
long long next,
|
||||
long long duration);
|
||||
|
||||
long Parse();
|
||||
|
||||
Kind GetKind() const;
|
||||
const Block* GetBlock() const;
|
||||
|
||||
@@ -345,9 +351,6 @@ protected:
|
||||
public:
|
||||
EOSBlock();
|
||||
|
||||
//bool EOS() const;
|
||||
//const Cluster* GetCluster() const;
|
||||
//long GetIndex() const;
|
||||
Kind GetKind() const;
|
||||
const Block* GetBlock() const;
|
||||
};
|
||||
@@ -680,9 +683,10 @@ public:
|
||||
long long GetFirstTime() const; //time (ns) of first (earliest) block
|
||||
long long GetLastTime() const; //time (ns) of last (latest) block
|
||||
|
||||
const BlockEntry* GetFirst() const;
|
||||
const BlockEntry* GetLast() const;
|
||||
const BlockEntry* GetNext(const BlockEntry*) const;
|
||||
long GetFirst(const BlockEntry*&) const;
|
||||
long GetLast(const BlockEntry*&) const;
|
||||
long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
|
||||
|
||||
const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
|
||||
const BlockEntry* GetEntry(
|
||||
const CuePoint&,
|
||||
@@ -731,12 +735,12 @@ private:
|
||||
mutable long m_entries_size;
|
||||
mutable long m_entries_count;
|
||||
|
||||
long ParseSimpleBlock(long long, long long&, long&) const;
|
||||
long ParseBlockGroup(long long, long long&, long&) const;
|
||||
long ParseSimpleBlock(long long, long long&, long&);
|
||||
long ParseBlockGroup(long long, long long&, long&);
|
||||
|
||||
void CreateBlock(long long id, long long pos, long long size) const;
|
||||
void CreateBlockGroup(long long, long long, BlockEntry**&) const;
|
||||
void CreateSimpleBlock(long long, long long, BlockEntry**&) const;
|
||||
long CreateBlock(long long id, long long pos, long long size);
|
||||
long CreateBlockGroup(long long, long long);
|
||||
long CreateSimpleBlock(long long, long long);
|
||||
|
||||
};
|
||||
|
||||
|
||||
21
sample.cpp
21
sample.cpp
@@ -256,7 +256,16 @@ int main(int argc, char* argv[])
|
||||
const long long time_ns = pCluster->GetTime();
|
||||
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
|
||||
|
||||
const BlockEntry* pBlockEntry = pCluster->GetFirst();
|
||||
const BlockEntry* pBlockEntry;
|
||||
|
||||
long status = pCluster->GetFirst(pBlockEntry);
|
||||
|
||||
if (status < 0) //error
|
||||
{
|
||||
printf("\t\tError parsing first block of cluster\n");
|
||||
fflush(stdout);
|
||||
goto done;
|
||||
}
|
||||
|
||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
|
||||
{
|
||||
@@ -281,12 +290,20 @@ int main(int argc, char* argv[])
|
||||
printf("\t\t\t %15ld,%15llx\n", size, offset);
|
||||
}
|
||||
|
||||
pBlockEntry = pCluster->GetNext(pBlockEntry);
|
||||
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("\t\t\tError parsing next block of cluster\n");
|
||||
fflush(stdout);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
pCluster = pSegment->GetNext(pCluster);
|
||||
}
|
||||
|
||||
done:
|
||||
delete pSegment;
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -317,7 +317,15 @@ int main(int argc, char* argv[]) {
|
||||
const mkvparser::Cluster* cluster = parser_segment->GetFirst();
|
||||
|
||||
while ((cluster != NULL) && !cluster->EOS()) {
|
||||
const mkvparser::BlockEntry* block_entry = cluster->GetFirst();
|
||||
const mkvparser::BlockEntry* block_entry;
|
||||
|
||||
long status = cluster->GetFirst(block_entry);
|
||||
|
||||
if (status)
|
||||
{
|
||||
printf("\n Could not get first block of cluster.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((block_entry != NULL) && !block_entry->EOS()) {
|
||||
const mkvparser::Block* const block = block_entry->GetBlock();
|
||||
@@ -362,7 +370,13 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
block_entry = cluster->GetNext(block_entry);
|
||||
status = cluster->GetNext(block_entry, block_entry);
|
||||
|
||||
if (status)
|
||||
{
|
||||
printf("\n Could not get next block of cluster.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
cluster = parser_segment->GetNext(cluster);
|
||||
|
||||
Reference in New Issue
Block a user