Compare commits
8 Commits
libwebm-1.
...
libwebm-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9203d2dcd1 | ||
|
|
be2f81abca | ||
|
|
cb5414a42a | ||
|
|
2ce6965b2d | ||
|
|
8db600e1c9 | ||
|
|
85353469f8 | ||
|
|
d97f236f81 | ||
|
|
790f639f2f |
333
mkvparser.cpp
333
mkvparser.cpp
@@ -11,24 +11,19 @@
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <climits>
|
||||
//#include <windows.h>
|
||||
//#include "odbgstream.hpp"
|
||||
//using std::endl;
|
||||
|
||||
mkvparser::IMkvReader::~IMkvReader()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)
|
||||
{
|
||||
major = 1;
|
||||
minor = 0;
|
||||
build = 0;
|
||||
revision = 7;
|
||||
revision = 8;
|
||||
}
|
||||
|
||||
|
||||
long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
|
||||
{
|
||||
assert(pReader);
|
||||
@@ -113,7 +108,6 @@ long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
long long mkvparser::GetUIntLength(
|
||||
IMkvReader* pReader,
|
||||
long long pos,
|
||||
@@ -155,7 +149,6 @@ long long mkvparser::GetUIntLength(
|
||||
return 0; //success
|
||||
}
|
||||
|
||||
|
||||
long long mkvparser::SyncReadUInt(
|
||||
IMkvReader* pReader,
|
||||
long long pos,
|
||||
@@ -235,6 +228,7 @@ long long mkvparser::UnserializeUInt(
|
||||
|
||||
if (hr < 0)
|
||||
return hr;
|
||||
|
||||
result <<= 8;
|
||||
result |= b;
|
||||
|
||||
@@ -366,7 +360,6 @@ bool mkvparser::Match(
|
||||
long long& pos,
|
||||
unsigned long id_,
|
||||
long long& val)
|
||||
|
||||
{
|
||||
assert(pReader);
|
||||
assert(pos >= 0);
|
||||
@@ -880,7 +873,7 @@ long long Segment::CreateInstance(
|
||||
|
||||
//TODO: if we liberalize the behavior of ReadUInt, we can
|
||||
//probably eliminate having to use GetUIntLength here.
|
||||
const long long size = ReadUInt(pReader, pos, len);
|
||||
long long size = ReadUInt(pReader, pos, len);
|
||||
|
||||
if (size < 0)
|
||||
return size;
|
||||
@@ -889,17 +882,25 @@ long long Segment::CreateInstance(
|
||||
|
||||
//Pos now points to start of payload
|
||||
|
||||
if ((pos + size) > total)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
if (id == 0x08538067) //Segment ID
|
||||
{
|
||||
//Handle "unknown size" for live streaming of webm files.
|
||||
const long long unknown_size = (1LL << (7 * len)) - 1;
|
||||
|
||||
if (size == unknown_size)
|
||||
size = total - pos;
|
||||
else if ((pos + size) > total)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
pSegment = new Segment(pReader, pos, size);
|
||||
assert(pSegment); //TODO
|
||||
|
||||
return 0; //success
|
||||
}
|
||||
|
||||
if ((pos + size) > total)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
pos += size; //consume payload
|
||||
}
|
||||
|
||||
@@ -1073,8 +1074,13 @@ long Segment::ParseCluster(long long& off, long long& new_pos) const
|
||||
|
||||
if (id == 0x0F43B675) //Cluster ID
|
||||
{
|
||||
off = idpos - m_start; // >= 0 means we found a cluster
|
||||
break;
|
||||
const long long off_ = idpos - m_start;
|
||||
|
||||
if (Cluster::HasBlockEntries(this, off_))
|
||||
{
|
||||
off = off_; // >= 0 means we found a cluster
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1161,7 +1167,6 @@ bool Segment::AddCluster(long long off, long long pos)
|
||||
{
|
||||
Cluster* const pCluster = Cluster::Parse(this, m_clusterCount, off);
|
||||
assert(pCluster);
|
||||
assert(pCluster->m_index == m_clusterCount);
|
||||
|
||||
AppendCluster(pCluster);
|
||||
assert(m_clusters);
|
||||
@@ -1170,7 +1175,6 @@ bool Segment::AddCluster(long long off, long long pos)
|
||||
}
|
||||
|
||||
m_pos = pos; //m_pos >= stop is now we know we have all clusters
|
||||
|
||||
return (pos >= stop);
|
||||
}
|
||||
|
||||
@@ -1270,21 +1274,27 @@ long Segment::LoadCluster()
|
||||
--m_clusterPreloadCount;
|
||||
|
||||
m_pos = pos + size; //consume payload
|
||||
break;
|
||||
assert(m_pos <= stop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Cluster* const pCluster = Cluster::Parse(this, idx, idoff);
|
||||
assert(pCluster);
|
||||
assert(pCluster->m_index == idx);
|
||||
|
||||
AppendCluster(pCluster);
|
||||
assert(m_clusters);
|
||||
assert(idx < m_clusterSize);
|
||||
assert(m_clusters[idx] == pCluster);
|
||||
|
||||
m_pos = pos + size; //consume payload
|
||||
break;
|
||||
assert(m_pos <= stop);
|
||||
|
||||
if (Cluster::HasBlockEntries(this, idoff))
|
||||
{
|
||||
Cluster* const pCluster = Cluster::Parse(this, idx, idoff);
|
||||
assert(pCluster);
|
||||
|
||||
AppendCluster(pCluster);
|
||||
assert(m_clusters);
|
||||
assert(idx < m_clusterSize);
|
||||
assert(m_clusters[idx] == pCluster);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_pos <= stop);
|
||||
@@ -1509,14 +1519,16 @@ long Segment::Load()
|
||||
const long idx = m_clusterCount;
|
||||
const long long off = idpos - m_start;
|
||||
|
||||
Cluster* const pCluster = Cluster::Parse(this, idx, off);
|
||||
assert(pCluster);
|
||||
assert(pCluster->m_index == idx);
|
||||
if (Cluster::HasBlockEntries(this, off))
|
||||
{
|
||||
Cluster* const pCluster = Cluster::Parse(this, idx, off);
|
||||
assert(pCluster);
|
||||
|
||||
AppendCluster(pCluster);
|
||||
assert(m_clusters);
|
||||
assert(m_clusterSize > idx);
|
||||
assert(m_clusters[idx] == pCluster);
|
||||
AppendCluster(pCluster);
|
||||
assert(m_clusters);
|
||||
assert(m_clusterSize > idx);
|
||||
assert(m_clusters[idx] == pCluster);
|
||||
}
|
||||
}
|
||||
else if (id == 0x0C53BB6B) //Cues ID
|
||||
{
|
||||
@@ -2153,8 +2165,11 @@ const BlockEntry* Segment::GetBlock(
|
||||
}
|
||||
|
||||
assert(i == j);
|
||||
assert(Cluster::HasBlockEntries(this, tp.m_pos));
|
||||
|
||||
Cluster* const pCluster = Cluster::Parse(this, -1, tp.m_pos);
|
||||
assert(pCluster);
|
||||
|
||||
const ptrdiff_t idx = i - m_clusters;
|
||||
|
||||
PreloadCluster(pCluster, idx);
|
||||
@@ -2529,8 +2544,13 @@ const Cluster* Segment::GetNext(const Cluster* pCurr)
|
||||
|
||||
if (id == 0x0F43B675) //Cluster ID
|
||||
{
|
||||
off_next = idpos - m_start;
|
||||
break;
|
||||
const long long off_next_ = idpos - m_start;
|
||||
|
||||
if (Cluster::HasBlockEntries(this, off_next_))
|
||||
{
|
||||
off_next = off_next_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos += size; //consume payload
|
||||
@@ -2575,6 +2595,8 @@ const Cluster* Segment::GetNext(const Cluster* pCurr)
|
||||
assert(i == j);
|
||||
|
||||
Cluster* const pNext = Cluster::Parse(this, -1, off_next);
|
||||
assert(pNext);
|
||||
|
||||
const ptrdiff_t idx_next = i - m_clusters; //insertion position
|
||||
|
||||
PreloadCluster(pNext, idx_next);
|
||||
@@ -2761,22 +2783,10 @@ const BlockEntry* Segment::Seek(
|
||||
assert(pCluster->GetTime() <= time_ns);
|
||||
|
||||
{
|
||||
const BlockEntry* const pBlockEntry = pCluster->GetEntry(pTrack);
|
||||
const BlockEntry* const pBE = pCluster->GetEntry(pTrack, time_ns);
|
||||
|
||||
if ((pBlockEntry != 0) && !pBlockEntry->EOS()) //found a keyframe
|
||||
{
|
||||
const Block* const pBlock = pBlockEntry->GetBlock();
|
||||
assert(pBlock);
|
||||
|
||||
//NOTE: this isn't necessarily the keyframe we want,
|
||||
//since there might another keyframe on this same
|
||||
//cluster with a greater timecode, that is still
|
||||
//less than the requested time. For now we
|
||||
//simply return the first keyframe we find.
|
||||
|
||||
if (pBlock->GetTime(pCluster) <= time_ns)
|
||||
return pBlockEntry;
|
||||
}
|
||||
if ((pBE != 0) && !pBE->EOS()) //found a keyframe
|
||||
return pBE;
|
||||
}
|
||||
|
||||
const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);
|
||||
@@ -2984,13 +2994,12 @@ Track::~Track()
|
||||
Track::Info::Info():
|
||||
type(-1),
|
||||
number(-1),
|
||||
uid(-1),
|
||||
uid(ULLONG_MAX),
|
||||
nameAsUTF8(NULL),
|
||||
codecId(NULL),
|
||||
codecPrivate(NULL),
|
||||
codecPrivateSize(0),
|
||||
codecNameAsUTF8(NULL)
|
||||
//lacing(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3027,6 +3036,11 @@ long long Track::GetNumber() const
|
||||
return m_info.number;
|
||||
}
|
||||
|
||||
unsigned long long Track::GetUid() const
|
||||
{
|
||||
return m_info.uid;
|
||||
}
|
||||
|
||||
const char* Track::GetNameAsUTF8() const
|
||||
{
|
||||
return m_info.nameAsUTF8;
|
||||
@@ -3060,11 +3074,7 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const
|
||||
{
|
||||
const Cluster* pCluster = m_pSegment->GetFirst();
|
||||
|
||||
//If Segment::GetFirst returns NULL, then this must be a network
|
||||
//download, and we haven't loaded any clusters yet. In this case,
|
||||
//returning NULL from Track::GetFirst means the same thing.
|
||||
|
||||
for (int i = 0; i < 100; ++i) //arbitrary upper bound
|
||||
for (int i = 0; ; )
|
||||
{
|
||||
if (pCluster == NULL)
|
||||
{
|
||||
@@ -3086,7 +3096,13 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const
|
||||
|
||||
pBlockEntry = pCluster->GetFirst();
|
||||
|
||||
while (pBlockEntry)
|
||||
if (pBlockEntry == 0) //empty cluster
|
||||
{
|
||||
pCluster = m_pSegment->GetNext(pCluster);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const Block* const pBlock = pBlockEntry->GetBlock();
|
||||
assert(pBlock);
|
||||
@@ -3095,8 +3111,16 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const
|
||||
return 0;
|
||||
|
||||
pBlockEntry = pCluster->GetNext(pBlockEntry);
|
||||
|
||||
if (pBlockEntry == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
if (i >= 100)
|
||||
break;
|
||||
|
||||
pCluster = m_pSegment->GetNext(pCluster);
|
||||
}
|
||||
|
||||
@@ -3520,8 +3544,8 @@ void Tracks::ParseTrackEntry(
|
||||
#endif
|
||||
if (Match(pReader, pos, 0x57, i.number))
|
||||
assert(i.number > 0);
|
||||
else if (Match(pReader, pos, 0x33C5, i.uid))
|
||||
;
|
||||
//else if (Match(pReader, pos, 0x33C5, i.uid))
|
||||
// ;
|
||||
else if (Match(pReader, pos, 0x03, i.type))
|
||||
;
|
||||
else if (Match(pReader, pos, 0x136E, i.nameAsUTF8))
|
||||
@@ -3542,6 +3566,9 @@ void Tracks::ParseTrackEntry(
|
||||
{
|
||||
long len;
|
||||
|
||||
const long long idpos = pos;
|
||||
idpos;
|
||||
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
@@ -3568,6 +3595,27 @@ void Tracks::ParseTrackEntry(
|
||||
audioSettings.start = start;
|
||||
audioSettings.size = size;
|
||||
}
|
||||
else if (id == 0x33C5) //Track UID
|
||||
{
|
||||
assert(size <= 8);
|
||||
|
||||
i.uid = 0;
|
||||
long long pos_ = start;
|
||||
const long long pos_end = start + size;
|
||||
|
||||
while (pos_ != pos_end)
|
||||
{
|
||||
unsigned char b;
|
||||
|
||||
const long status = pReader->Read(pos_, 1, &b);
|
||||
assert(status == 0);
|
||||
|
||||
i.uid <<= 8;
|
||||
i.uid |= b;
|
||||
|
||||
++pos_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3749,6 +3797,9 @@ Cluster* Cluster::Parse(
|
||||
assert(off >= 0);
|
||||
assert(off < pSegment->m_size);
|
||||
|
||||
//if (!HasBlockEntries(pSegment, off))
|
||||
// return NULL;
|
||||
|
||||
Cluster* const pCluster = new Cluster(pSegment, idx, -off);
|
||||
assert(pCluster);
|
||||
|
||||
@@ -3763,7 +3814,7 @@ Cluster::Cluster() :
|
||||
m_size(0),
|
||||
m_timecode(0),
|
||||
m_entries(NULL),
|
||||
m_entriesCount(0)
|
||||
m_entries_count(0) //means "no entries"
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3778,15 +3829,18 @@ Cluster::Cluster(
|
||||
m_size(-1),
|
||||
m_timecode(-1),
|
||||
m_entries(NULL),
|
||||
m_entriesCount(0)
|
||||
m_entries_count(-1) //means "has not been parsed yet"
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Cluster::~Cluster()
|
||||
{
|
||||
if (m_entries_count <= 0)
|
||||
return;
|
||||
|
||||
BlockEntry** i = m_entries;
|
||||
BlockEntry** const j = m_entries + m_entriesCount;
|
||||
BlockEntry** const j = m_entries + m_entries_count;
|
||||
|
||||
while (i != j)
|
||||
{
|
||||
@@ -3806,15 +3860,80 @@ bool Cluster::EOS() const
|
||||
}
|
||||
|
||||
|
||||
bool Cluster::HasBlockEntries(
|
||||
const Segment* pSegment,
|
||||
long long off) //relative to start of segment payload
|
||||
{
|
||||
assert(pSegment);
|
||||
assert(off >= 0); //relative to segment
|
||||
|
||||
IMkvReader* const pReader = pSegment->m_pReader;
|
||||
|
||||
long long pos = pSegment->m_start + off; //absolute
|
||||
long long size;
|
||||
|
||||
{
|
||||
long len;
|
||||
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
id;
|
||||
assert(id >= 0);
|
||||
assert(id == 0x0F43B675); //Cluster ID
|
||||
|
||||
pos += len; //consume id
|
||||
|
||||
size = ReadUInt(pReader, pos, len);
|
||||
assert(size > 0);
|
||||
|
||||
pos += len; //consume size
|
||||
|
||||
//pos now points to start of payload
|
||||
}
|
||||
|
||||
const long long stop = pos + size;
|
||||
|
||||
while (pos < stop)
|
||||
{
|
||||
long len;
|
||||
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0); //TODO
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
pos += len; //consume id
|
||||
|
||||
const long long size = ReadUInt(pReader, pos, len);
|
||||
assert(size >= 0); //TODO
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
pos += len; //consume size
|
||||
|
||||
if (id == 0x20) //BlockGroup ID
|
||||
return true;
|
||||
|
||||
if (id == 0x23) //SimpleBlock ID
|
||||
return true;
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Cluster::LoadBlockEntries() const
|
||||
{
|
||||
if (m_entries)
|
||||
return;
|
||||
|
||||
if (m_entries_count == 0) //already parsed, and no entries found
|
||||
return;
|
||||
|
||||
assert(m_pSegment);
|
||||
assert(m_pos);
|
||||
assert(m_size);
|
||||
assert(m_entriesCount == 0);
|
||||
assert(m_entries_count < 0);
|
||||
|
||||
IMkvReader* const pReader = m_pSegment->m_pReader;
|
||||
|
||||
@@ -3852,7 +3971,7 @@ void Cluster::LoadBlockEntries() const
|
||||
//First count the number of entries
|
||||
|
||||
long long idx = pos; //points to start of payload
|
||||
m_entriesCount = 0;
|
||||
m_entries_count = 0;
|
||||
|
||||
while (idx < stop)
|
||||
{
|
||||
@@ -3880,9 +3999,9 @@ void Cluster::LoadBlockEntries() const
|
||||
idx += len; //consume size
|
||||
|
||||
if (id == 0x20) //BlockGroup ID
|
||||
++m_entriesCount;
|
||||
++m_entries_count;
|
||||
else if (id == 0x23) //SimpleBlock ID
|
||||
++m_entriesCount;
|
||||
++m_entries_count;
|
||||
|
||||
idx += size; //consume payload
|
||||
assert(idx <= stop);
|
||||
@@ -3892,11 +4011,11 @@ void Cluster::LoadBlockEntries() const
|
||||
assert(idx == stop);
|
||||
assert(m_timecode >= 0);
|
||||
|
||||
if (m_entriesCount == 0) //TODO: handle empty clusters
|
||||
if (m_entries_count == 0)
|
||||
return;
|
||||
|
||||
m_entries = new BlockEntry*[m_entriesCount];
|
||||
size_t index = 0;
|
||||
m_entries = new BlockEntry*[m_entries_count];
|
||||
long index = 0;
|
||||
|
||||
while (pos < stop)
|
||||
{
|
||||
@@ -3929,7 +4048,7 @@ void Cluster::LoadBlockEntries() const
|
||||
|
||||
assert(pos == stop);
|
||||
assert(timecode >= 0);
|
||||
assert(index == m_entriesCount);
|
||||
assert(index == m_entries_count);
|
||||
}
|
||||
|
||||
|
||||
@@ -3988,9 +4107,9 @@ long long Cluster::GetLastTime() const
|
||||
|
||||
void Cluster::ParseBlockGroup(long long st, long long sz, size_t idx) const
|
||||
{
|
||||
assert(m_entries);
|
||||
assert(m_entriesCount);
|
||||
assert(idx < m_entriesCount);
|
||||
assert(m_entries != NULL);
|
||||
assert(m_entries_count > 0);
|
||||
assert(idx < size_t(m_entries_count));
|
||||
|
||||
Cluster* const this_ = const_cast<Cluster*>(this);
|
||||
|
||||
@@ -4004,9 +4123,9 @@ void Cluster::ParseBlockGroup(long long st, long long sz, size_t idx) const
|
||||
|
||||
void Cluster::ParseSimpleBlock(long long st, long long sz, size_t idx) const
|
||||
{
|
||||
assert(m_entries);
|
||||
assert(m_entriesCount);
|
||||
assert(idx < m_entriesCount);
|
||||
assert(m_entries != NULL);
|
||||
assert(m_entries_count > 0);
|
||||
assert(idx < size_t(m_entries_count));
|
||||
|
||||
Cluster* const this_ = const_cast<Cluster*>(this);
|
||||
|
||||
@@ -4021,7 +4140,7 @@ const BlockEntry* Cluster::GetFirst() const
|
||||
{
|
||||
LoadBlockEntries();
|
||||
|
||||
if ((m_entries == NULL) || (m_entriesCount == 0))
|
||||
if ((m_entries == NULL) || (m_entries_count <= 0))
|
||||
return NULL;
|
||||
|
||||
const BlockEntry* const pFirst = m_entries[0];
|
||||
@@ -4035,10 +4154,10 @@ const BlockEntry* Cluster::GetLast() const
|
||||
{
|
||||
LoadBlockEntries();
|
||||
|
||||
if ((m_entries == NULL) || (m_entriesCount == 0))
|
||||
if ((m_entries == NULL) || (m_entries_count <= 0))
|
||||
return NULL;
|
||||
|
||||
const size_t idx = m_entriesCount - 1;
|
||||
const long idx = m_entries_count - 1;
|
||||
|
||||
const BlockEntry* const pLast = m_entries[idx];
|
||||
assert(pLast);
|
||||
@@ -4050,38 +4169,42 @@ const BlockEntry* Cluster::GetLast() const
|
||||
const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
|
||||
{
|
||||
assert(pEntry);
|
||||
assert(m_entries);
|
||||
assert(m_entriesCount);
|
||||
assert(m_entries != NULL);
|
||||
assert(m_entries_count > 0);
|
||||
|
||||
size_t idx = pEntry->GetIndex();
|
||||
assert(idx < m_entriesCount);
|
||||
assert(idx < size_t(m_entries_count));
|
||||
assert(m_entries[idx] == pEntry);
|
||||
|
||||
++idx;
|
||||
|
||||
if (idx >= m_entriesCount)
|
||||
if (idx >= size_t(m_entries_count))
|
||||
return NULL;
|
||||
|
||||
return m_entries[idx];
|
||||
}
|
||||
|
||||
|
||||
const BlockEntry* Cluster::GetEntry(const Track* pTrack) const
|
||||
const BlockEntry* Cluster::GetEntry(
|
||||
const Track* pTrack,
|
||||
long long time_ns) const
|
||||
{
|
||||
assert(pTrack);
|
||||
|
||||
if (m_pSegment == NULL) //EOS
|
||||
if (m_pSegment == NULL) //this is the special EOS cluster
|
||||
return pTrack->GetEOS();
|
||||
|
||||
LoadBlockEntries();
|
||||
|
||||
if ((m_entries == NULL) || (m_entriesCount == 0))
|
||||
return NULL;
|
||||
if ((m_entries == NULL) || (m_entries_count <= 0))
|
||||
return NULL; //return EOS here?
|
||||
|
||||
const BlockEntry* pResult = pTrack->GetEOS();
|
||||
|
||||
BlockEntry** i = m_entries;
|
||||
assert(i);
|
||||
|
||||
BlockEntry** const j = i + m_entriesCount;
|
||||
BlockEntry** const j = i + m_entries_count;
|
||||
|
||||
while (i != j)
|
||||
{
|
||||
@@ -4096,10 +4219,27 @@ const BlockEntry* Cluster::GetEntry(const Track* pTrack) const
|
||||
continue;
|
||||
|
||||
if (pTrack->VetEntry(pEntry))
|
||||
return pEntry;
|
||||
{
|
||||
if (time_ns < 0) //just want first candidate block
|
||||
return pEntry;
|
||||
|
||||
const long long ns = pBlock->GetTime(this);
|
||||
|
||||
if (ns > time_ns)
|
||||
break;
|
||||
|
||||
pResult = pEntry;
|
||||
}
|
||||
else if (time_ns >= 0)
|
||||
{
|
||||
const long long ns = pBlock->GetTime(this);
|
||||
|
||||
if (ns > time_ns)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pTrack->GetEOS(); //no satisfactory block found
|
||||
return pResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -4115,7 +4255,7 @@ Cluster::GetEntry(
|
||||
if (m_entries == NULL)
|
||||
return NULL;
|
||||
|
||||
const long long count = m_entriesCount;
|
||||
const long long count = m_entries_count;
|
||||
|
||||
if (count <= 0)
|
||||
return NULL;
|
||||
@@ -4205,7 +4345,10 @@ const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
|
||||
|
||||
LoadBlockEntries();
|
||||
|
||||
BlockEntry** i = m_entries + m_entriesCount;
|
||||
if ((m_entries == NULL) || (m_entries_count <= 0))
|
||||
return pTrack->GetEOS();
|
||||
|
||||
BlockEntry** i = m_entries + m_entries_count;
|
||||
BlockEntry** const j = m_entries;
|
||||
|
||||
while (i != j)
|
||||
|
||||
@@ -37,7 +37,7 @@ short Unserialize2SInt(IMkvReader*, long long);
|
||||
signed char Unserialize1SInt(IMkvReader*, long long);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, long long&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, char*&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, double&);
|
||||
bool Match(IMkvReader*, long long&, unsigned long, short&);
|
||||
|
||||
@@ -209,6 +209,7 @@ public:
|
||||
|
||||
long long GetType() const;
|
||||
long long GetNumber() const;
|
||||
unsigned long long GetUid() const;
|
||||
const char* GetNameAsUTF8() const;
|
||||
const char* GetCodecNameAsUTF8() const;
|
||||
const char* GetCodecId() const;
|
||||
@@ -227,7 +228,7 @@ public:
|
||||
{
|
||||
long long type;
|
||||
long long number;
|
||||
long long uid;
|
||||
unsigned long long uid;
|
||||
char* nameAsUTF8;
|
||||
char* codecId;
|
||||
unsigned char* codecPrivate;
|
||||
@@ -472,12 +473,14 @@ public:
|
||||
const BlockEntry* GetFirst() const;
|
||||
const BlockEntry* GetLast() const;
|
||||
const BlockEntry* GetNext(const BlockEntry*) const;
|
||||
const BlockEntry* GetEntry(const Track*) const;
|
||||
const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
|
||||
const BlockEntry* GetEntry(
|
||||
const CuePoint&,
|
||||
const CuePoint::TrackPosition&) const;
|
||||
const BlockEntry* GetMaxKey(const VideoTrack*) const;
|
||||
|
||||
static bool HasBlockEntries(const Segment*, long long);
|
||||
|
||||
protected:
|
||||
Cluster(Segment*, long, long long off);
|
||||
|
||||
@@ -490,7 +493,7 @@ public:
|
||||
private:
|
||||
mutable long long m_timecode;
|
||||
mutable BlockEntry** m_entries;
|
||||
mutable size_t m_entriesCount;
|
||||
mutable long m_entries_count;
|
||||
|
||||
void Load() const;
|
||||
void LoadBlockEntries() const;
|
||||
|
||||
@@ -43,13 +43,13 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="true"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
|
||||
15
sample.cpp
15
sample.cpp
@@ -148,14 +148,14 @@ int main(int argc, char* argv[])
|
||||
if (pTrack == NULL)
|
||||
continue;
|
||||
|
||||
const long long trackType_ = pTrack->GetType();
|
||||
unsigned long trackType = static_cast<unsigned long>(trackType_);
|
||||
|
||||
unsigned long trackNumber = pTrack->GetNumber();
|
||||
const long long trackType = pTrack->GetType();
|
||||
const long long trackNumber = pTrack->GetNumber();
|
||||
const unsigned long long trackUid = pTrack->GetUid();
|
||||
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
|
||||
|
||||
printf("\t\tTrack Type\t\t: %ld\n", trackType);
|
||||
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
|
||||
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
|
||||
|
||||
if (pTrackName == NULL)
|
||||
printf("\t\tTrack Name\t\t: NULL\n");
|
||||
@@ -235,8 +235,9 @@ int main(int argc, char* argv[])
|
||||
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
|
||||
{
|
||||
const Block* const pBlock = pBlockEntry->GetBlock();
|
||||
const unsigned long trackNum = pBlock->GetTrackNumber();
|
||||
const Track* const pTrack = pTracks->GetTrackByNumber(trackNum);
|
||||
const long long trackNum = pBlock->GetTrackNumber();
|
||||
const unsigned long tn = static_cast<unsigned long>(trackNum);
|
||||
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
|
||||
const long long trackType = pTrack->GetType();
|
||||
const int frameCount = pBlock->GetFrameCount();
|
||||
const long long time_ns = pBlock->GetTime(pCluster);
|
||||
@@ -250,7 +251,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
const Block::Frame& theFrame = pBlock->GetFrame(i);
|
||||
const long size = theFrame.len;
|
||||
const long offset = theFrame.pos;
|
||||
const long long offset = theFrame.pos;
|
||||
printf("\t\t\t %15ld,%15lx\n", size, offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,13 @@
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
DebugInformationFormat="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
|
||||
Reference in New Issue
Block a user