Compare commits
12 Commits
libwebm-1.
...
libwebm-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a977a2b536 | ||
|
|
5e72a2dfc2 | ||
|
|
056b0d96a8 | ||
|
|
dbc58d0510 | ||
|
|
a131a01446 | ||
|
|
b8cb358204 | ||
|
|
5b06b22b31 | ||
|
|
598de03ef3 | ||
|
|
94f2d589fc | ||
|
|
786357a59d | ||
|
|
6e723319e8 | ||
|
|
9911f61616 |
747
mkvparser.cpp
747
mkvparser.cpp
@@ -21,7 +21,7 @@ void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)
|
|||||||
major = 1;
|
major = 1;
|
||||||
minor = 0;
|
minor = 0;
|
||||||
build = 0;
|
build = 0;
|
||||||
revision = 11;
|
revision = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
|
long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
|
||||||
@@ -228,13 +228,16 @@ float mkvparser::Unserialize4Float(
|
|||||||
assert(pReader);
|
assert(pReader);
|
||||||
assert(pos >= 0);
|
assert(pos >= 0);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
long long total, available;
|
long long total, available;
|
||||||
|
|
||||||
long hr = pReader->Length(&total, &available);
|
long hr = pReader->Length(&total, &available);
|
||||||
assert(hr >= 0);
|
assert(hr >= 0);
|
||||||
assert(available <= total);
|
assert(available <= total);
|
||||||
assert((pos + 4) <= available);
|
assert((pos + 4) <= available);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
unsigned char* const p = (unsigned char*)&result;
|
unsigned char* const p = (unsigned char*)&result;
|
||||||
@@ -250,6 +253,32 @@ float mkvparser::Unserialize4Float(
|
|||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
union
|
||||||
|
{
|
||||||
|
float result;
|
||||||
|
unsigned long buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
buf = 0;
|
||||||
|
|
||||||
|
for (int i = 0;;)
|
||||||
|
{
|
||||||
|
unsigned char b;
|
||||||
|
|
||||||
|
const int status = pReader->Read(pos++, 1, &b);
|
||||||
|
|
||||||
|
if (status < 0) //error
|
||||||
|
return static_cast<float>(status);
|
||||||
|
|
||||||
|
buf |= b;
|
||||||
|
|
||||||
|
if (++i >= 4)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buf <<= 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -262,6 +291,7 @@ double mkvparser::Unserialize8Double(
|
|||||||
assert(pReader);
|
assert(pReader);
|
||||||
assert(pos >= 0);
|
assert(pos >= 0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
unsigned char* const p = (unsigned char*)&result;
|
unsigned char* const p = (unsigned char*)&result;
|
||||||
@@ -277,6 +307,32 @@ double mkvparser::Unserialize8Double(
|
|||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
long long buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
buf = 0;
|
||||||
|
|
||||||
|
for (int i = 0;;)
|
||||||
|
{
|
||||||
|
unsigned char b;
|
||||||
|
|
||||||
|
const int status = pReader->Read(pos++, 1, &b);
|
||||||
|
|
||||||
|
if (status < 0) //error
|
||||||
|
return static_cast<double>(status);
|
||||||
|
|
||||||
|
buf |= b;
|
||||||
|
|
||||||
|
if (++i >= 8)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buf <<= 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -288,17 +344,20 @@ signed char mkvparser::Unserialize1SInt(
|
|||||||
assert(pReader);
|
assert(pReader);
|
||||||
assert(pos >= 0);
|
assert(pos >= 0);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
long long total, available;
|
long long total, available;
|
||||||
|
|
||||||
long hr = pReader->Length(&total, &available);
|
long hr = pReader->Length(&total, &available);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
assert(available <= total);
|
assert(available <= total);
|
||||||
assert(pos < available);
|
assert(pos < available);
|
||||||
|
#endif
|
||||||
|
|
||||||
signed char result;
|
signed char result;
|
||||||
|
unsigned char& b = reinterpret_cast<unsigned char&>(result);
|
||||||
|
|
||||||
hr = pReader->Read(pos, 1, (unsigned char*)&result);
|
const int status = pReader->Read(pos, 1, &b);
|
||||||
assert(hr == 0);
|
assert(status == 0); //TODO: must be handled somehow
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -310,13 +369,16 @@ short mkvparser::Unserialize2SInt(
|
|||||||
assert(pReader);
|
assert(pReader);
|
||||||
assert(pos >= 0);
|
assert(pos >= 0);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
long long total, available;
|
long long total, available;
|
||||||
|
|
||||||
long hr = pReader->Length(&total, &available);
|
long hr = pReader->Length(&total, &available);
|
||||||
assert(hr >= 0);
|
assert(hr >= 0);
|
||||||
assert(available <= total);
|
assert(available <= total);
|
||||||
assert((pos + 2) <= available);
|
assert((pos + 2) <= available);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
short result;
|
short result;
|
||||||
|
|
||||||
unsigned char* const p = (unsigned char*)&result;
|
unsigned char* const p = (unsigned char*)&result;
|
||||||
@@ -332,6 +394,24 @@ short mkvparser::Unserialize2SInt(
|
|||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
short result = 0;
|
||||||
|
|
||||||
|
for (int i = 0;;)
|
||||||
|
{
|
||||||
|
unsigned char b;
|
||||||
|
|
||||||
|
const int status = pReader->Read(pos++, 1, &b);
|
||||||
|
assert(status == 0); //TODO: must be handled somehow
|
||||||
|
|
||||||
|
result |= b;
|
||||||
|
|
||||||
|
if (++i >= 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
result <<= 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -770,6 +850,7 @@ Segment::Segment(
|
|||||||
m_start(start),
|
m_start(start),
|
||||||
m_size(size),
|
m_size(size),
|
||||||
m_pos(start),
|
m_pos(start),
|
||||||
|
m_pSeekHead(NULL),
|
||||||
m_pInfo(NULL),
|
m_pInfo(NULL),
|
||||||
m_pTracks(NULL),
|
m_pTracks(NULL),
|
||||||
m_pCues(NULL),
|
m_pCues(NULL),
|
||||||
@@ -801,6 +882,7 @@ Segment::~Segment()
|
|||||||
delete m_pTracks;
|
delete m_pTracks;
|
||||||
delete m_pInfo;
|
delete m_pInfo;
|
||||||
delete m_pCues;
|
delete m_pCues;
|
||||||
|
delete m_pSeekHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1028,8 +1110,21 @@ long long Segment::ParseHeaders()
|
|||||||
}
|
}
|
||||||
else if (id == 0x014D9B74) //SeekHead ID
|
else if (id == 0x014D9B74) //SeekHead ID
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (available >= total)
|
if (available >= total)
|
||||||
ParseSeekHead(pos, size);
|
ParseSeekHead(pos, size);
|
||||||
|
#else
|
||||||
|
if (m_pSeekHead == NULL)
|
||||||
|
{
|
||||||
|
m_pSeekHead = new SeekHead(this,
|
||||||
|
pos,
|
||||||
|
size,
|
||||||
|
element_start,
|
||||||
|
element_size);
|
||||||
|
|
||||||
|
assert(m_pSeekHead); //TODO
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pos = pos + size; //consume payload
|
m_pos = pos + size; //consume payload
|
||||||
@@ -1293,7 +1388,7 @@ long Segment::LoadCluster(
|
|||||||
{
|
{
|
||||||
long long total, avail;
|
long long total, avail;
|
||||||
|
|
||||||
const int status = m_pReader->Length(&total, &avail);
|
long status = m_pReader->Length(&total, &avail);
|
||||||
|
|
||||||
if (status < 0) //error
|
if (status < 0) //error
|
||||||
return status;
|
return status;
|
||||||
@@ -1435,11 +1530,12 @@ long Segment::LoadCluster(
|
|||||||
++m_clusterCount;
|
++m_clusterCount;
|
||||||
--m_clusterPreloadCount;
|
--m_clusterPreloadCount;
|
||||||
|
|
||||||
pCluster->Load(); //establish invariant
|
|
||||||
|
|
||||||
m_pos = pos + size; //consume payload
|
m_pos = pos + size; //consume payload
|
||||||
assert(m_pos <= stop);
|
assert(m_pos <= stop);
|
||||||
|
|
||||||
|
status = pCluster->LoadBlockEntries(pos, len);
|
||||||
|
assert(status == 0); //TODO
|
||||||
|
|
||||||
return 0; //we have a new cluster
|
return 0; //we have a new cluster
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1461,7 +1557,8 @@ long Segment::LoadCluster(
|
|||||||
assert(idx < m_clusterSize);
|
assert(idx < m_clusterSize);
|
||||||
assert(m_clusters[idx] == pCluster);
|
assert(m_clusters[idx] == pCluster);
|
||||||
|
|
||||||
pCluster->Load(); //establish invariant
|
status = pCluster->LoadBlockEntries(pos, len);
|
||||||
|
assert(status == 0); //TODO
|
||||||
|
|
||||||
return 0; //we have a new cluster
|
return 0; //we have a new cluster
|
||||||
}
|
}
|
||||||
@@ -1751,14 +1848,11 @@ long Segment::Load()
|
|||||||
if (m_clusters == NULL) //TODO: ignore this case?
|
if (m_clusters == NULL) //TODO: ignore this case?
|
||||||
return E_FILE_FORMAT_INVALID;
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
//TODO: decide whether we require Cues element
|
|
||||||
//if (m_pCues == NULL)
|
|
||||||
// return E_FILE_FORMAT_INVALID;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
void Segment::ParseSeekHead(long long start, long long size_)
|
void Segment::ParseSeekHead(long long start, long long size_)
|
||||||
{
|
{
|
||||||
long long pos = start;
|
long long pos = start;
|
||||||
@@ -1790,8 +1884,124 @@ void Segment::ParseSeekHead(long long start, long long size_)
|
|||||||
|
|
||||||
assert(pos == stop);
|
assert(pos == stop);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
SeekHead::SeekHead(
|
||||||
|
Segment* pSegment,
|
||||||
|
long long start,
|
||||||
|
long long size_,
|
||||||
|
long long element_start,
|
||||||
|
long long element_size) :
|
||||||
|
m_pSegment(pSegment),
|
||||||
|
m_start(start),
|
||||||
|
m_size(size_),
|
||||||
|
m_element_start(element_start),
|
||||||
|
m_element_size(element_size),
|
||||||
|
m_entries(0),
|
||||||
|
m_count(0)
|
||||||
|
{
|
||||||
|
long long pos = start;
|
||||||
|
const long long stop = start + size_;
|
||||||
|
|
||||||
|
IMkvReader* const pReader = m_pSegment->m_pReader;
|
||||||
|
|
||||||
|
//first count the seek head entries
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
assert((pos + len) <= stop);
|
||||||
|
|
||||||
|
pos += len; //consume Size field
|
||||||
|
assert((pos + size) <= stop);
|
||||||
|
|
||||||
|
if (id == 0x0DBB) //SeekEntry ID
|
||||||
|
++count;
|
||||||
|
|
||||||
|
pos += size; //consume payload
|
||||||
|
assert(pos <= stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pos == stop);
|
||||||
|
|
||||||
|
if (count <= 0)
|
||||||
|
return; //nothing else for us to do
|
||||||
|
|
||||||
|
m_entries = new (std::nothrow) Entry[count];
|
||||||
|
assert(m_entries); //TODO
|
||||||
|
|
||||||
|
//now parse the entries
|
||||||
|
|
||||||
|
Entry* pEntry = m_entries;
|
||||||
|
pos = start;
|
||||||
|
|
||||||
|
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);
|
||||||
|
assert((pos + len) <= stop);
|
||||||
|
|
||||||
|
pos += len; //consume Size field
|
||||||
|
assert((pos + size) <= stop);
|
||||||
|
|
||||||
|
if (id == 0x0DBB) //SeekEntry ID
|
||||||
|
ParseEntry(pReader, pos, size, pEntry);
|
||||||
|
|
||||||
|
pos += size; //consume payload
|
||||||
|
assert(pos <= stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pos == stop);
|
||||||
|
|
||||||
|
const ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries);
|
||||||
|
assert(count_ >= 0);
|
||||||
|
assert(count_ <= count);
|
||||||
|
|
||||||
|
m_count = static_cast<int>(count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SeekHead::~SeekHead()
|
||||||
|
{
|
||||||
|
delete[] m_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SeekHead::GetCount() const
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SeekHead::Entry* SeekHead::GetEntry(int idx) const
|
||||||
|
{
|
||||||
|
if (idx < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (idx >= m_count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_entries + idx;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
void Segment::ParseCues(long long off)
|
void Segment::ParseCues(long long off)
|
||||||
{
|
{
|
||||||
if (m_pCues)
|
if (m_pCues)
|
||||||
@@ -1839,8 +2049,137 @@ void Segment::ParseCues(long long off)
|
|||||||
|
|
||||||
//os << "Segment::ParseCues (end)" << endl;
|
//os << "Segment::ParseCues (end)" << endl;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
long Segment::ParseCues(
|
||||||
|
long long off,
|
||||||
|
long long& pos,
|
||||||
|
long& len)
|
||||||
|
{
|
||||||
|
if (m_pCues)
|
||||||
|
return 0; //success
|
||||||
|
|
||||||
|
if (off < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
long long total, avail;
|
||||||
|
|
||||||
|
const int status = m_pReader->Length(&total, &avail);
|
||||||
|
|
||||||
|
if (status < 0) //error
|
||||||
|
return status;
|
||||||
|
|
||||||
|
assert(total >= 0);
|
||||||
|
assert(avail <= total);
|
||||||
|
|
||||||
|
pos = m_start + off;
|
||||||
|
|
||||||
|
const long long element_start = pos;
|
||||||
|
const long long stop = m_start + m_size; //end of segment
|
||||||
|
|
||||||
|
if ((pos + 1) > avail)
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long result = GetUIntLength(m_pReader, pos, len);
|
||||||
|
|
||||||
|
if (result < 0) //error
|
||||||
|
return static_cast<long>(result);
|
||||||
|
|
||||||
|
if (result > 0) //underflow (weird)
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos + len) > stop) //not a very useful test
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if ((pos + len) > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
const long long idpos = pos;
|
||||||
|
|
||||||
|
const long long id = ReadUInt(m_pReader, idpos, len);
|
||||||
|
|
||||||
|
if (id != 0x0C53BB6B) //Cues ID
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
pos += len; //consume ID
|
||||||
|
assert(pos < stop);
|
||||||
|
|
||||||
|
//Read Size
|
||||||
|
|
||||||
|
if ((pos + 1) > avail)
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = GetUIntLength(m_pReader, pos, len);
|
||||||
|
|
||||||
|
if (result < 0) //error
|
||||||
|
return static_cast<long>(result);
|
||||||
|
|
||||||
|
if (result > 0) //underflow (weird)
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos + len) > stop) //not a very useful test
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if ((pos + len) > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
const long long size = ReadUInt(m_pReader, pos, len);
|
||||||
|
|
||||||
|
if (size < 0) //error
|
||||||
|
return static_cast<long>(size);
|
||||||
|
|
||||||
|
if (size == 0) //weird, although technically not illegal
|
||||||
|
return 1; //done
|
||||||
|
|
||||||
|
pos += len; //consume length of size of element
|
||||||
|
|
||||||
|
//Pos now points to start of payload
|
||||||
|
|
||||||
|
const long long element_stop = pos + size;
|
||||||
|
|
||||||
|
if (element_stop > stop)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
len = static_cast<long>(size);
|
||||||
|
|
||||||
|
if (element_stop > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
const long long element_size = element_stop - element_start;
|
||||||
|
|
||||||
|
m_pCues = new (std::nothrow) Cues(
|
||||||
|
this,
|
||||||
|
pos,
|
||||||
|
size,
|
||||||
|
element_start,
|
||||||
|
element_size);
|
||||||
|
assert(m_pCues); //TODO
|
||||||
|
|
||||||
|
#if 0 //TODO
|
||||||
|
//we should do this incrementally as well
|
||||||
|
|
||||||
|
while (m_pCues->LoadCuePoint())
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0; //success
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
void Segment::ParseSeekEntry(
|
void Segment::ParseSeekEntry(
|
||||||
long long start,
|
long long start,
|
||||||
long long size_)
|
long long size_)
|
||||||
@@ -1898,6 +2237,95 @@ void Segment::ParseSeekEntry(
|
|||||||
if (seekId == 0x0C53BB6B) //Cues ID
|
if (seekId == 0x0C53BB6B) //Cues ID
|
||||||
ParseCues(seekOff);
|
ParseCues(seekOff);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void SeekHead::ParseEntry(
|
||||||
|
IMkvReader* pReader,
|
||||||
|
long long start,
|
||||||
|
long long size_,
|
||||||
|
Entry*& pEntry)
|
||||||
|
{
|
||||||
|
long long pos = start;
|
||||||
|
const long long stop = start + size_;
|
||||||
|
|
||||||
|
long len;
|
||||||
|
|
||||||
|
//parse the container for the level-1 element ID
|
||||||
|
|
||||||
|
const long long seekIdId = ReadUInt(pReader, pos, len);
|
||||||
|
//seekIdId;
|
||||||
|
|
||||||
|
if (seekIdId != 0x13AB) //SeekID ID
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((pos + len) > stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos += len; //consume SeekID id
|
||||||
|
|
||||||
|
const long long seekIdSize = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (seekIdSize <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((pos + len) > stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos += len; //consume size of field
|
||||||
|
|
||||||
|
if ((pos + seekIdSize) > stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//TODO: it's not clear whether this is correct
|
||||||
|
//It seems as if the payload here is "binary" which
|
||||||
|
//means the value of the ID should be unserialized,
|
||||||
|
//not parsed as an uint.
|
||||||
|
//
|
||||||
|
pEntry->id = ReadUInt(pReader, pos, len); //payload
|
||||||
|
|
||||||
|
if (pEntry->id <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (len != seekIdSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos += seekIdSize; //consume SeekID payload
|
||||||
|
|
||||||
|
const long long seekPosId = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (seekPosId != 0x13AC) //SeekPos ID
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((pos + len) > stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos += len; //consume id
|
||||||
|
|
||||||
|
const long long seekPosSize = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (seekPosSize <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((pos + len) > stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos += len; //consume size
|
||||||
|
|
||||||
|
if ((pos + seekPosSize) > stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pEntry->pos = UnserializeUInt(pReader, pos, seekPosSize);
|
||||||
|
|
||||||
|
if (pEntry->pos < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos += seekPosSize; //consume payload
|
||||||
|
|
||||||
|
if (pos != stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++pEntry; //success
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Cues::Cues(
|
Cues::Cues(
|
||||||
@@ -2102,7 +2530,7 @@ bool Cues::Find(
|
|||||||
assert(time_ns >= 0);
|
assert(time_ns >= 0);
|
||||||
assert(pTrack);
|
assert(pTrack);
|
||||||
|
|
||||||
LoadCuePoint();
|
LoadCuePoint(); //establish invariant
|
||||||
|
|
||||||
assert(m_cue_points);
|
assert(m_cue_points);
|
||||||
assert(m_count > 0);
|
assert(m_count > 0);
|
||||||
@@ -2375,6 +2803,61 @@ const BlockEntry* Segment::GetBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Cluster* Segment::FindOrPreloadCluster(long long requested_pos)
|
||||||
|
{
|
||||||
|
if (requested_pos < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Cluster** const ii = m_clusters;
|
||||||
|
Cluster** i = ii;
|
||||||
|
|
||||||
|
const long count = m_clusterCount + m_clusterPreloadCount;
|
||||||
|
|
||||||
|
Cluster** const jj = ii + count;
|
||||||
|
Cluster** j = jj;
|
||||||
|
|
||||||
|
while (i < j)
|
||||||
|
{
|
||||||
|
//INVARIANT:
|
||||||
|
//[ii, i) < pTP->m_pos
|
||||||
|
//[i, j) ?
|
||||||
|
//[j, jj) > pTP->m_pos
|
||||||
|
|
||||||
|
Cluster** const k = i + (j - i) / 2;
|
||||||
|
assert(k < jj);
|
||||||
|
|
||||||
|
Cluster* const pCluster = *k;
|
||||||
|
assert(pCluster);
|
||||||
|
|
||||||
|
const long long pos_ = pCluster->m_pos;
|
||||||
|
assert(pos_);
|
||||||
|
|
||||||
|
const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
|
||||||
|
|
||||||
|
if (pos < requested_pos)
|
||||||
|
i = k + 1;
|
||||||
|
else if (pos > requested_pos)
|
||||||
|
j = k;
|
||||||
|
else
|
||||||
|
return pCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(i == j);
|
||||||
|
//assert(Cluster::HasBlockEntries(this, tp.m_pos));
|
||||||
|
|
||||||
|
Cluster* const pCluster = Cluster::Parse(this, -1, requested_pos, 0, 0);
|
||||||
|
assert(pCluster);
|
||||||
|
|
||||||
|
const ptrdiff_t idx = i - m_clusters;
|
||||||
|
|
||||||
|
PreloadCluster(pCluster, idx);
|
||||||
|
assert(m_clusters);
|
||||||
|
assert(m_clusterPreloadCount > 0);
|
||||||
|
assert(m_clusters[idx] == pCluster);
|
||||||
|
|
||||||
|
return pCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CuePoint::CuePoint(size_t idx, long long pos) :
|
CuePoint::CuePoint(size_t idx, long long pos) :
|
||||||
m_element_start(0),
|
m_element_start(0),
|
||||||
@@ -2587,7 +3070,7 @@ long long CuePoint::GetTimeCode() const
|
|||||||
return m_timecode;
|
return m_timecode;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long CuePoint::GetTime(Segment* pSegment) const
|
long long CuePoint::GetTime(const Segment* pSegment) const
|
||||||
{
|
{
|
||||||
assert(pSegment);
|
assert(pSegment);
|
||||||
assert(m_timecode >= 0);
|
assert(m_timecode >= 0);
|
||||||
@@ -2860,7 +3343,7 @@ long Segment::ParseNext(
|
|||||||
|
|
||||||
long long total, avail;
|
long long total, avail;
|
||||||
|
|
||||||
const int status = m_pReader->Length(&total, &avail);
|
long status = m_pReader->Length(&total, &avail);
|
||||||
|
|
||||||
if (status < 0) //error
|
if (status < 0) //error
|
||||||
return status;
|
return status;
|
||||||
@@ -3072,10 +3555,8 @@ long Segment::ParseNext(
|
|||||||
|
|
||||||
len = static_cast<long>(size);
|
len = static_cast<long>(size);
|
||||||
|
|
||||||
#if 1 //TODO: get rid of this
|
|
||||||
if (element_stop > avail)
|
if (element_stop > avail)
|
||||||
return E_BUFFER_NOT_FULL;
|
return E_BUFFER_NOT_FULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (Cluster::HasBlockEntries(this, idoff)) //relative
|
if (Cluster::HasBlockEntries(this, idoff)) //relative
|
||||||
{
|
{
|
||||||
@@ -3126,6 +3607,9 @@ long Segment::ParseNext(
|
|||||||
j = k;
|
j = k;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
status = pNext->LoadBlockEntries(pos, len);
|
||||||
|
assert(status == 0);
|
||||||
|
|
||||||
pResult = pNext;
|
pResult = pNext;
|
||||||
return 0; //success
|
return 0; //success
|
||||||
}
|
}
|
||||||
@@ -3147,7 +3631,8 @@ long Segment::ParseNext(
|
|||||||
assert(idx_next < m_clusterSize);
|
assert(idx_next < m_clusterSize);
|
||||||
assert(m_clusters[idx_next] == pNext);
|
assert(m_clusters[idx_next] == pNext);
|
||||||
|
|
||||||
pNext->Load(); //because we need this now
|
status = pNext->LoadBlockEntries(pos, len);
|
||||||
|
assert(status == 0); //TODO
|
||||||
|
|
||||||
pResult = pNext;
|
pResult = pNext;
|
||||||
return 0; //success
|
return 0; //success
|
||||||
@@ -3389,7 +3874,7 @@ bool Segment::SearchCues(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Tracks* Segment::GetTracks() const
|
const Tracks* Segment::GetTracks() const
|
||||||
{
|
{
|
||||||
return m_pTracks;
|
return m_pTracks;
|
||||||
}
|
}
|
||||||
@@ -3407,6 +3892,12 @@ const Cues* Segment::GetCues() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const SeekHead* Segment::GetSeekHead() const
|
||||||
|
{
|
||||||
|
return m_pSeekHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
long long Segment::GetDuration() const
|
long long Segment::GetDuration() const
|
||||||
{
|
{
|
||||||
assert(m_pInfo);
|
assert(m_pInfo);
|
||||||
@@ -4559,6 +5050,220 @@ void Cluster::Load() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long Cluster::LoadBlockEntries(long long& pos, long& len) const
|
||||||
|
{
|
||||||
|
assert(m_pSegment);
|
||||||
|
assert(m_pos);
|
||||||
|
assert(m_size);
|
||||||
|
|
||||||
|
//if (m_pos > 0) //loaded
|
||||||
|
//{
|
||||||
|
// assert(m_size > 0);
|
||||||
|
// assert(m_timecode >= 0);
|
||||||
|
// assert(m_entries_count >= 0);
|
||||||
|
//
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//assert(m_pos < 0); //not loaded yet
|
||||||
|
//assert(m_size < 0);
|
||||||
|
//assert(m_timecode < 0);
|
||||||
|
|
||||||
|
IMkvReader* const pReader = m_pSegment->m_pReader;
|
||||||
|
|
||||||
|
long long total, avail;
|
||||||
|
|
||||||
|
const int status = pReader->Length(&total, &avail);
|
||||||
|
|
||||||
|
if (status < 0) //error
|
||||||
|
return status;
|
||||||
|
|
||||||
|
assert(total >= 0);
|
||||||
|
assert(avail <= total);
|
||||||
|
|
||||||
|
const long long segment_stop = m_pSegment->m_start + m_pSegment->m_size;
|
||||||
|
|
||||||
|
if (m_pos > 0) //at least partially loaded
|
||||||
|
{
|
||||||
|
assert(m_size > 0);
|
||||||
|
|
||||||
|
if (m_entries_count >= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pos = m_pSegment->m_start + m_pos; //absolute pos of payload
|
||||||
|
|
||||||
|
const long long cluster_stop = pos + m_size;
|
||||||
|
|
||||||
|
len = static_cast<long>(m_size);
|
||||||
|
|
||||||
|
if (cluster_stop > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
LoadBlockEntries(); //TODO
|
||||||
|
assert(m_entries_count >= 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_pos *= -1; //relative to segment
|
||||||
|
pos = m_pSegment->m_start - m_pos; //absolute
|
||||||
|
|
||||||
|
if ((pos + 1) > avail)
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long result = GetUIntLength(pReader, pos, len);
|
||||||
|
|
||||||
|
if (result < 0) //error
|
||||||
|
return static_cast<long>(result);
|
||||||
|
|
||||||
|
if (result > 0) //weird
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos + len) > segment_stop)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if ((pos + len) > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
const long long id_ = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (id_ < 0) //error
|
||||||
|
return static_cast<long>(id_);
|
||||||
|
|
||||||
|
if (id_ != 0x0F43B675) //Cluster ID
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
pos += len; //consume id
|
||||||
|
|
||||||
|
//read cluster size
|
||||||
|
|
||||||
|
if ((pos + 1) > avail)
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = GetUIntLength(pReader, pos, len);
|
||||||
|
|
||||||
|
if (result < 0) //error
|
||||||
|
return static_cast<long>(result);
|
||||||
|
|
||||||
|
if (result > 0) //weird
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos + len) > segment_stop)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if ((pos + len) > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
const long long size_ = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (size_ < 0) //error
|
||||||
|
return static_cast<long>(size_);
|
||||||
|
|
||||||
|
if (size_ == 0)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
pos += len; //consume length of size of element
|
||||||
|
|
||||||
|
//pos now points to start of payload
|
||||||
|
|
||||||
|
//m_size = size_;
|
||||||
|
const long long cluster_stop = pos + size_;
|
||||||
|
|
||||||
|
len = static_cast<long>(size_);
|
||||||
|
|
||||||
|
if (cluster_stop > avail)
|
||||||
|
return E_BUFFER_NOT_FULL;
|
||||||
|
|
||||||
|
long long timecode = -1;
|
||||||
|
bool bBlock = false;
|
||||||
|
|
||||||
|
while (pos < cluster_stop)
|
||||||
|
{
|
||||||
|
if (Match(pReader, pos, 0x67, timecode))
|
||||||
|
{
|
||||||
|
if (bBlock)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const long long id = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (id < 0) //error
|
||||||
|
return static_cast<long>(id);
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if ((pos + len) > cluster_stop)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
pos += len; //consume id
|
||||||
|
|
||||||
|
const long long size = ReadUInt(pReader, pos, len);
|
||||||
|
|
||||||
|
if (size < 0) //error
|
||||||
|
return static_cast<long>(size);
|
||||||
|
|
||||||
|
if ((pos + len) > cluster_stop)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
pos += len; //consume size field
|
||||||
|
|
||||||
|
//pos now points to start of payload
|
||||||
|
|
||||||
|
if (size == 0) //weird
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((pos + size) > cluster_stop)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if (id == 0x20) //BlockGroup ID
|
||||||
|
{
|
||||||
|
bBlock = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == 0x23) //SimpleBlock ID
|
||||||
|
{
|
||||||
|
bBlock = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += size; //consume payload
|
||||||
|
assert(pos <= cluster_stop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pos <= cluster_stop);
|
||||||
|
|
||||||
|
if (timecode < 0)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
if (!bBlock)
|
||||||
|
return E_FILE_FORMAT_INVALID;
|
||||||
|
|
||||||
|
m_pos *= -1; // m_pos > 0 means we're partially loaded
|
||||||
|
m_size = size_; // m_size > 0 means we're partially loaded
|
||||||
|
m_timecode = timecode; // m_timecode >= 0 means we're partially loaded
|
||||||
|
|
||||||
|
LoadBlockEntries(); //TODO
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Cluster* Cluster::Parse(
|
Cluster* Cluster::Parse(
|
||||||
Segment* pSegment,
|
Segment* pSegment,
|
||||||
long idx,
|
long idx,
|
||||||
@@ -4968,6 +5673,12 @@ const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long Cluster::GetEntryCount() const
|
||||||
|
{
|
||||||
|
return m_entries_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const BlockEntry* Cluster::GetEntry(
|
const BlockEntry* Cluster::GetEntry(
|
||||||
const Track* pTrack,
|
const Track* pTrack,
|
||||||
long long time_ns) const
|
long long time_ns) const
|
||||||
|
|||||||
@@ -371,7 +371,9 @@ public:
|
|||||||
long long size,
|
long long size,
|
||||||
long long element_start,
|
long long element_start,
|
||||||
long long element_size);
|
long long element_size);
|
||||||
|
|
||||||
~SegmentInfo();
|
~SegmentInfo();
|
||||||
|
|
||||||
long long GetTimeCodeScale() const;
|
long long GetTimeCodeScale() const;
|
||||||
long long GetDuration() const; //scaled
|
long long GetDuration() const; //scaled
|
||||||
const char* GetMuxingAppAsUTF8() const;
|
const char* GetMuxingAppAsUTF8() const;
|
||||||
@@ -386,6 +388,49 @@ private:
|
|||||||
char* m_pTitleAsUTF8;
|
char* m_pTitleAsUTF8;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SeekHead
|
||||||
|
{
|
||||||
|
SeekHead(const SeekHead&);
|
||||||
|
SeekHead& operator=(const SeekHead&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Segment* const m_pSegment;
|
||||||
|
const long long m_start;
|
||||||
|
const long long m_size;
|
||||||
|
const long long m_element_start;
|
||||||
|
const long long m_element_size;
|
||||||
|
|
||||||
|
SeekHead(
|
||||||
|
Segment*,
|
||||||
|
long long start,
|
||||||
|
long long size,
|
||||||
|
long long element_start,
|
||||||
|
long long element_size);
|
||||||
|
|
||||||
|
~SeekHead();
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
long long id;
|
||||||
|
long long pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
int GetCount() const;
|
||||||
|
const Entry* GetEntry(int idx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Entry* m_entries;
|
||||||
|
int m_count;
|
||||||
|
|
||||||
|
static void ParseEntry(
|
||||||
|
IMkvReader*,
|
||||||
|
long long pos,
|
||||||
|
long long size,
|
||||||
|
Entry*&);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Cues;
|
class Cues;
|
||||||
class CuePoint
|
class CuePoint
|
||||||
{
|
{
|
||||||
@@ -404,7 +449,7 @@ public:
|
|||||||
void Load(IMkvReader*);
|
void Load(IMkvReader*);
|
||||||
|
|
||||||
long long GetTimeCode() const; //absolute but unscaled
|
long long GetTimeCode() const; //absolute but unscaled
|
||||||
long long GetTime(Segment*) const; //absolute and scaled (ns units)
|
long long GetTime(const Segment*) const; //absolute and scaled (ns units)
|
||||||
|
|
||||||
struct TrackPosition
|
struct TrackPosition
|
||||||
{
|
{
|
||||||
@@ -473,9 +518,10 @@ public:
|
|||||||
const CuePoint*,
|
const CuePoint*,
|
||||||
const CuePoint::TrackPosition*) const;
|
const CuePoint::TrackPosition*) const;
|
||||||
|
|
||||||
|
bool LoadCuePoint() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init() const;
|
void Init() const;
|
||||||
bool LoadCuePoint() const;
|
|
||||||
void PreloadCuePoint(size_t&, long long) const;
|
void PreloadCuePoint(size_t&, long long) const;
|
||||||
|
|
||||||
mutable CuePoint** m_cue_points;
|
mutable CuePoint** m_cue_points;
|
||||||
@@ -522,7 +568,11 @@ public:
|
|||||||
const BlockEntry* GetMaxKey(const VideoTrack*) const;
|
const BlockEntry* GetMaxKey(const VideoTrack*) const;
|
||||||
|
|
||||||
static bool HasBlockEntries(const Segment*, long long);
|
static bool HasBlockEntries(const Segment*, long long);
|
||||||
|
long GetEntryCount() const;
|
||||||
|
|
||||||
void Load() const;
|
void Load() const;
|
||||||
|
void LoadBlockEntries() const;
|
||||||
|
long LoadBlockEntries(long long& pos, long& size) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Cluster(
|
Cluster(
|
||||||
@@ -545,7 +595,6 @@ private:
|
|||||||
mutable BlockEntry** m_entries;
|
mutable BlockEntry** m_entries;
|
||||||
mutable long m_entries_count;
|
mutable long m_entries_count;
|
||||||
|
|
||||||
void LoadBlockEntries() const;
|
|
||||||
void ParseBlockGroup(long long, long long, size_t) const;
|
void ParseBlockGroup(long long, long long, size_t) const;
|
||||||
void ParseSimpleBlock(long long, long long, size_t) const;
|
void ParseSimpleBlock(long long, long long, size_t) const;
|
||||||
|
|
||||||
@@ -593,7 +642,8 @@ public:
|
|||||||
long ParseCluster(long long& cluster_pos, long long& new_pos) const;
|
long ParseCluster(long long& cluster_pos, long long& new_pos) const;
|
||||||
bool AddCluster(long long cluster_pos, long long new_pos);
|
bool AddCluster(long long cluster_pos, long long new_pos);
|
||||||
|
|
||||||
Tracks* GetTracks() const;
|
const SeekHead* GetSeekHead() const;
|
||||||
|
const Tracks* GetTracks() const;
|
||||||
const SegmentInfo* GetInfo() const;
|
const SegmentInfo* GetInfo() const;
|
||||||
const Cues* GetCues() const;
|
const Cues* GetCues() const;
|
||||||
|
|
||||||
@@ -607,9 +657,18 @@ public:
|
|||||||
const Cluster* FindCluster(long long time_nanoseconds) const;
|
const Cluster* FindCluster(long long time_nanoseconds) const;
|
||||||
//const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
|
//const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
|
||||||
|
|
||||||
|
const Cluster* FindOrPreloadCluster(long long pos);
|
||||||
|
|
||||||
|
long ParseCues(
|
||||||
|
long long cues_off, //offset relative to start of segment
|
||||||
|
long long& parse_pos,
|
||||||
|
long& parse_len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
long long m_pos; //absolute file posn; what has been consumed so far
|
long long m_pos; //absolute file posn; what has been consumed so far
|
||||||
|
|
||||||
|
SeekHead* m_pSeekHead;
|
||||||
SegmentInfo* m_pInfo;
|
SegmentInfo* m_pInfo;
|
||||||
Tracks* m_pTracks;
|
Tracks* m_pTracks;
|
||||||
Cues* m_pCues;
|
Cues* m_pCues;
|
||||||
@@ -621,9 +680,9 @@ private:
|
|||||||
void AppendCluster(Cluster*);
|
void AppendCluster(Cluster*);
|
||||||
void PreloadCluster(Cluster*, ptrdiff_t);
|
void PreloadCluster(Cluster*, ptrdiff_t);
|
||||||
|
|
||||||
void ParseSeekHead(long long pos, long long size);
|
//void ParseSeekHead(long long pos, long long size);
|
||||||
void ParseSeekEntry(long long pos, long long size);
|
//void ParseSeekEntry(long long pos, long long size);
|
||||||
void ParseCues(long long);
|
//void ParseCues(long long);
|
||||||
|
|
||||||
const BlockEntry* GetBlock(
|
const BlockEntry* GetBlock(
|
||||||
const CuePoint&,
|
const CuePoint&,
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ int main(int argc, char* argv[])
|
|||||||
// size of segment payload
|
// size of segment payload
|
||||||
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
|
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
|
||||||
|
|
||||||
mkvparser::Tracks* const pTracks = pSegment->GetTracks();
|
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
|
||||||
|
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
const unsigned long j = pTracks->GetTracksCount();
|
const unsigned long j = pTracks->GetTracksCount();
|
||||||
|
|||||||
Reference in New Issue
Block a user