From 8ccdd10ad8408a687c9110369b2e9745f646d737 Mon Sep 17 00:00:00 2001 From: Hwasoo Lee Date: Fri, 11 Jun 2010 16:30:13 -0400 Subject: [PATCH] initialized AudioTrack and fixed indentation in Linux Change-Id: I7ca148256f695b053318e962b06e34034b6c7cd4 --- mkvparser.cpp | 1094 ++++++++++++++++++++++++------------------------- 1 file changed, 543 insertions(+), 551 deletions(-) diff --git a/mkvparser.cpp b/mkvparser.cpp index 1a4018b..0f21176 100644 --- a/mkvparser.cpp +++ b/mkvparser.cpp @@ -18,27 +18,27 @@ long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(pos < available); assert((available - pos) >= 1); //assume here max u-int len is 8 - + unsigned char b; hr = pReader->Read(pos, 1, &b); if (hr < 0) return hr; - + assert(hr == 0L); - + if (b & 0x80) //1000 0000 { len = 1; b &= 0x7F; //0111 1111 - } + } else if (b & 0x40) //0100 0000 { len = 2; @@ -69,81 +69,81 @@ long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) len = 7; b &= 0x01; //0000 0001 } - else + else { assert(b & 0x01); //0000 0001 len = 8; b = 0; //0000 0000 } - + assert((available - pos) >= len); - + long long result = b; ++pos; for (long i = 1; i < len; ++i) { hr = pReader->Read(pos, 1, &b); - + if (hr < 0) return hr; - + assert(hr == 0L); - + result <<= 8; result |= b; - + ++pos; } - + return result; } - - + + long long mkvparser::GetUIntLength( IMkvReader* pReader, - long long pos, + long long pos, long& len) { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + if (pos >= available) return pos; //too few bytes available - + unsigned char b; - + hr = pReader->Read(pos, 1, &b); - + if (hr < 0) return hr; assert(hr == 0L); - + if (b == 0) //we can't handle u-int values larger than 8 bytes return E_FILE_FORMAT_INVALID; - + unsigned char m = 0x80; len = 1; - + while (!(b & m)) { m >>= 1; ++len; } - + return 0; //success } long long mkvparser::SyncReadUInt( IMkvReader* pReader, - long long pos, + long long pos, long long stop, long& len) { @@ -151,57 +151,57 @@ long long mkvparser::SyncReadUInt( if (pos >= stop) return E_FILE_FORMAT_INVALID; - + unsigned char b; - + long hr = pReader->Read(pos, 1, &b); - + if (hr < 0) return hr; - + if (hr != 0L) return E_BUFFER_NOT_FULL; if (b == 0) //we can't handle u-int values larger than 8 bytes return E_FILE_FORMAT_INVALID; - + unsigned char m = 0x80; len = 1; - + while (!(b & m)) { m >>= 1; ++len; } - + if ((pos + len) > stop) return E_FILE_FORMAT_INVALID; - + long long result = b & (~m); ++pos; - + for (int i = 1; i < len; ++i) { hr = pReader->Read(pos, 1, &b); - + if (hr < 0) return hr; - + if (hr != 0L) return E_BUFFER_NOT_FULL; - + result <<= 8; result |= b; - + ++pos; } - + return result; } long long mkvparser::UnserializeUInt( - IMkvReader* pReader, + IMkvReader* pReader, long long pos, long long size) { @@ -209,84 +209,84 @@ long long mkvparser::UnserializeUInt( assert(pos >= 0); assert(size > 0); assert(size <= 8); - + long long result = 0; - + for (long long i = 0; i < size; ++i) { unsigned char b; - + const long hr = pReader->Read(pos, 1, &b); - - if (hr < 0) + + if (hr < 0) return hr; result <<= 8; result |= b; - + ++pos; } - + return result; } float mkvparser::Unserialize4Float( - IMkvReader* pReader, + IMkvReader* pReader, long long pos) { assert(pReader); assert(pos >= 0); - + long long total, available; - + long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); assert((pos + 4) <= available); - + float result; - + unsigned char* const p = (unsigned char*)&result; unsigned char* q = p + 4; - + for (;;) { hr = pReader->Read(pos, 1, --q); assert(hr == 0L); - + if (q == p) break; - + ++pos; } - + return result; } double mkvparser::Unserialize8Double( - IMkvReader* pReader, + IMkvReader* pReader, long long pos) { assert(pReader); assert(pos >= 0); - + double result; - + unsigned char* const p = (unsigned char*)&result; unsigned char* q = p + 8; - + for (;;) { const long hr = pReader->Read(pos, 1, --q); assert(hr == 0L); - + if (q == p) break; - + ++pos; } - + return result; } @@ -296,11 +296,11 @@ signed char mkvparser::Unserialize1SInt( { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); - assert(hr == 0); + assert(hr == 0); assert(available <= total); assert(pos < available); @@ -313,35 +313,35 @@ signed char mkvparser::Unserialize1SInt( } short mkvparser::Unserialize2SInt( - IMkvReader* pReader, + IMkvReader* pReader, long long pos) { assert(pReader); assert(pos >= 0); - + long long total, available; - + long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); assert((pos + 2) <= available); - + short result; - + unsigned char* const p = (unsigned char*)&result; unsigned char* q = p + 2; - + for (;;) { hr = pReader->Read(pos, 1, --q); assert(hr == 0L); - + if (q == p) break; - + ++pos; } - + return result; } @@ -355,13 +355,13 @@ bool mkvparser::Match( { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + long len; const long long id = ReadUInt(pReader, pos, len); @@ -369,26 +369,26 @@ bool mkvparser::Match( assert(len > 0); assert(len <= 8); assert((pos + len) <= available); - + if ((unsigned long)id != id_) return false; - + pos += len; //consume id - + const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); assert(size <= 8); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); - + pos += len; //consume length of size of payload - + val = UnserializeUInt(pReader, pos, size); assert(val >= 0); - + pos += size; //consume size of payload - + return true; } @@ -400,13 +400,13 @@ bool mkvparser::Match( { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + long len; const long long id = ReadUInt(pReader, pos, len); @@ -414,22 +414,22 @@ bool mkvparser::Match( assert(len > 0); assert(len <= 8); assert((pos + len) <= available); - + if ((unsigned long)id != id_) return false; - + pos += len; //consume id - + const long long size_ = ReadUInt(pReader, pos, len); assert(size_ >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); - + pos += len; //consume length of size of payload assert((pos + size_) <= available); - const size_t size = static_cast(size_); + const size_t size = static_cast(size_); val = new char[size+1]; for (size_t i = 0; i < size; ++i) @@ -438,17 +438,17 @@ bool mkvparser::Match( hr = pReader->Read(pos + i, 1, (unsigned char*)&c); assert(hr == 0L); - + val[i] = c; - + if (c == '\0') - break; - + break; + } val[size] = '\0'; pos += size_; //consume size of payload - + return true; } @@ -460,23 +460,23 @@ bool mkvparser::Match( wchar_t*& val) { char* str; - + if (!Match(pReader, pos, id, str)) return false; const size_t size = mbstowcs(NULL, str, 0); - - if (size == 0) + + if (size == 0) val = NULL; - else - { + else + { val = new wchar_t[size+1]; mbstowcs(val, str, size); val[size] = L'\0'; } delete[] str; - return true; + return true; } #endif @@ -490,31 +490,31 @@ bool mkvparser::Match( { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); - + if ((unsigned long)id != id_) return false; - + pos += len; //consume id - + const long long size_ = ReadUInt(pReader, pos, len); assert(size_ >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); - + pos += len; //consume length of size of payload assert((pos + size_) <= available); @@ -522,13 +522,13 @@ bool mkvparser::Match( buf = new (std::nothrow) unsigned char[buflen_]; assert(buf); //TODO - + hr = pReader->Read(pos, buflen_, buf); assert(hr == 0L); - + buflen = buflen_; - pos += size_; //consume size of payload + pos += size_; //consume size of payload return true; } @@ -541,7 +541,7 @@ bool mkvparser::Match( { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); @@ -550,7 +550,7 @@ bool mkvparser::Match( long idlen; const long long id = ReadUInt(pReader, pos, idlen); assert(id >= 0); //TODO - + if ((unsigned long)id != id_) return false; @@ -558,7 +558,7 @@ bool mkvparser::Match( const long long size = ReadUInt(pReader, pos + idlen, sizelen); switch (size) - { + { case 4: case 8: break; @@ -576,9 +576,9 @@ bool mkvparser::Match( assert(size == 8); val = Unserialize8Double(pReader, pos); } - + pos += size; //consume size of payload - + return true; } @@ -591,27 +591,27 @@ bool mkvparser::Match( { assert(pReader); assert(pos >= 0); - + long long total, available; long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert((pos + len) <= available); - + if ((unsigned long)id != id_) return false; - + pos += len; //consume id - + const long long size = ReadUInt(pReader, pos, len); assert(size <= 2); assert((pos + len) <= available); - + pos += len; //consume length of size of payload assert((pos + size) <= available); @@ -619,11 +619,11 @@ bool mkvparser::Match( // Generalize this to work for any size signed int if (size == 1) val = Unserialize1SInt(pReader, pos); - else + else val = Unserialize2SInt(pReader, pos); - + pos += size; //consume size of payload - + return true; } @@ -646,57 +646,57 @@ long long EBMLHeader::Parse( long long& pos) { assert(pReader); - + long long total, available; - + long hr = pReader->Length(&total, &available); - - if (hr < 0) + + if (hr < 0) return hr; - - pos = 0; - long long end = (1024 < available)? 1024: available; + + pos = 0; + long long end = (1024 < available)? 1024: available; for (;;) - { + { unsigned char b = 0; - + while (pos < end) { hr = pReader->Read(pos, 1, &b); - + if (hr < 0) return hr; - + if (b == 0x1A) break; - + ++pos; } - + if (b != 0x1A) { if ((pos >= 1024) || - (available >= total) || + (available >= total) || ((total - available) < 5)) return -1; - + return available + 5; //5 = 4-byte ID + 1st byte of size } - + if ((total - pos) < 5) return E_FILE_FORMAT_INVALID; - + if ((available - pos) < 5) return pos + 5; //try again later - long len; + long len; const long long result = ReadUInt(pReader, pos, len); - + if (result < 0) //error return result; - + if (result == 0x0A45DFA3) //ReadId masks-off length indicator bits { assert(len == 4); @@ -706,39 +706,39 @@ long long EBMLHeader::Parse( ++pos; //throw away just the 0x1A byte, and try again } - + long len; long long result = GetUIntLength(pReader, pos, len); - + if (result < 0) //error return result; - + if (result > 0) //need more data return result; - + assert(len > 0); assert(len <= 8); - + if ((total - pos) < len) return E_FILE_FORMAT_INVALID; if ((available - pos) < len) return pos + len; //try again later - + result = ReadUInt(pReader, pos, len); - + if (result < 0) //error return result; - + pos += len; //consume u-int - + if ((total - pos) < result) return E_FILE_FORMAT_INVALID; if ((available - pos) < result) return pos + result; - + end = pos + result; - + m_version = 1; m_readVersion = 1; m_maxIdLength = 4; @@ -748,19 +748,19 @@ long long EBMLHeader::Parse( while (pos < end) { - if (Match(pReader, pos, 0x0286, m_version)) + if (Match(pReader, pos, 0x0286, m_version)) ; - else if (Match(pReader, pos, 0x02F7, m_readVersion)) + else if (Match(pReader, pos, 0x02F7, m_readVersion)) ; - else if (Match(pReader, pos, 0x02F2, m_maxIdLength)) + else if (Match(pReader, pos, 0x02F2, m_maxIdLength)) ; - else if (Match(pReader, pos, 0x02F3, m_maxSizeLength)) + else if (Match(pReader, pos, 0x02F3, m_maxSizeLength)) ; - else if (Match(pReader, pos, 0x0282, m_docType)) - ; - else if (Match(pReader, pos, 0x0287, m_docTypeVersion)) + else if (Match(pReader, pos, 0x0282, m_docType)) ; - else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion)) + else if (Match(pReader, pos, 0x0287, m_docTypeVersion)) + ; + else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion)) ; else { @@ -768,23 +768,23 @@ long long EBMLHeader::Parse( assert(result > 0); assert(len > 0); assert(len <= 8); - + pos += len; assert(pos < end); - + result = ReadUInt(pReader, pos, len); assert(result >= 0); assert(len > 0); assert(len <= 8); - + pos += len + result; assert(pos <= end); } } - + assert(pos == end); - - return 0; + + return 0; } @@ -799,7 +799,6 @@ Segment::Segment( m_pInfo(NULL), m_pTracks(NULL), m_clusterCount(0) - //m_clusterNumber(0) { } @@ -812,12 +811,12 @@ Segment::~Segment() while (i != j) { Cluster* p = *i++; - assert(p); + assert(p); delete p; - } - + } + delete[] m_clusters; - + delete m_pTracks; delete m_pInfo; } @@ -830,15 +829,15 @@ long long Segment::CreateInstance( { assert(pReader); assert(pos >= 0); - + pSegment = NULL; - + long long total, available; - + long hr = pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + //I would assume that in practice this loop would execute //exactly once, but we allow for other elements (e.g. Void) //to immediately follow the EBML header. This is fine for @@ -846,74 +845,74 @@ long long Segment::CreateInstance( //but in the splitter case over a network we should probably //just give up early. We could for example decide only to //execute this loop a maximum of, say, 10 times. - + while (pos < total) - { + { //Read ID - + long len; long long result = GetUIntLength(pReader, pos, len); - + if (result) //error, or too few available bytes return result; - + if ((pos + len) > total) return E_FILE_FORMAT_INVALID; - + if ((pos + len) > available) return pos + len; //TODO: if we liberalize the behavior of ReadUInt, we can //probably eliminate having to use GetUIntLength here. const long long id = ReadUInt(pReader, pos, len); - + if (id < 0) //error return id; - + pos += len; //consume ID - + //Read Size - + result = GetUIntLength(pReader, pos, len); - + if (result) //error, or too few available bytes return result; - + if ((pos + len) > total) return E_FILE_FORMAT_INVALID; - + if ((pos + len) > available) return pos + len; //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); - + if (size < 0) return size; - + pos += len; //consume length of size of element - + //Pos now points to start of payload - + if ((pos + size) > total) return E_FILE_FORMAT_INVALID; - + if (id == 0x08538067) //Segment ID { - pSegment = new Segment(pReader, pos, size); - assert(pSegment); //TODO + pSegment = new Segment(pReader, pos, size); + assert(pSegment); //TODO return 0; //success } - + pos += size; //consume payload } - + assert(pos == total); - - pSegment = new Segment(pReader, pos, 0); - assert(pSegment); //TODO + + pSegment = new Segment(pReader, pos, 0); + assert(pSegment); //TODO return 0; //success (sort of) } @@ -921,79 +920,79 @@ long long Segment::CreateInstance( long long Segment::ParseHeaders() { - //Outermost (level 0) segment object has been constructed, + //Outermost (level 0) segment object has been constructed, //and pos designates start of payload. We need to find the //inner (level 1) elements. long long total, available; - + long hr = m_pReader->Length(&total, &available); assert(hr >= 0); assert(available <= total); - + const long long stop = m_start + m_size; assert(stop <= total); assert(m_pos <= stop); - + bool bQuit = false; while ((m_pos < stop) && !bQuit) { long long pos = m_pos; - + long len; long long result = GetUIntLength(m_pReader, pos, len); - + if (result) //error, or too few available bytes return result; - + if ((pos + len) > stop) return E_FILE_FORMAT_INVALID; - + if ((pos + len) > available) return pos + len; - + const long long idpos = pos; const long long id = ReadUInt(m_pReader, idpos, len); - + if (id < 0) //error return id; - + pos += len; //consume ID - + //Read Size result = GetUIntLength(m_pReader, pos, len); - + if (result) //error, or too few available bytes return result; - + if ((pos + len) > stop) return E_FILE_FORMAT_INVALID; - + if ((pos + len) > available) return pos + len; const long long size = ReadUInt(m_pReader, pos, len); - + if (size < 0) return size; - + pos += len; //consume length of size of element - + //Pos now points to start of payload - + if ((pos + size) > stop) return E_FILE_FORMAT_INVALID; - + //We read EBML elements either in total or nothing at all. - + if ((pos + size) > available) return pos + size; - + if (id == 0x0549A966) //Segment Info ID { assert(m_pInfo == NULL); m_pInfo = new SegmentInfo(this, pos, size); assert(m_pInfo); //TODO - + if (m_pTracks) bQuit = true; } @@ -1002,7 +1001,7 @@ long long Segment::ParseHeaders() assert(m_pTracks == NULL); m_pTracks = new Tracks(this, pos, size); assert(m_pTracks); //TODO - + if (m_pInfo) bQuit = true; } @@ -1010,21 +1009,21 @@ long long Segment::ParseHeaders() { #if 0 if (m_pInfo == NULL) //TODO: liberalize - ; + ; else if (m_pTracks == NULL) ; else - //ParseCluster(idpos, pos, size); + //ParseCluster(idpos, pos, size); Cluster::Parse(this, m_clusters, pos, size); #endif bQuit = true; } - + m_pos = pos + size; //consume payload } - + assert(m_pos <= stop); - + return 0; //success } @@ -1033,43 +1032,43 @@ long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const { pCluster = NULL; pos_ = -1; - + const long long stop = m_start + m_size; assert(m_pos <= stop); - + long long pos = m_pos; long long off = -1; - - + + while (pos < stop) { long len; const long long idpos = pos; - + const long long id = SyncReadUInt(m_pReader, pos, stop, len); - + if (id < 0) //error return static_cast(id); - + if (id == 0) return E_FILE_FORMAT_INVALID; - - pos += len; //consume id + + pos += len; //consume id assert(pos < stop); const long long size = SyncReadUInt(m_pReader, pos, stop, len); - + if (size < 0) //error return static_cast(size); - + pos += len; //consume size assert(pos <= stop); - + if (size == 0) //weird continue; - + //pos now points to start of payload - + pos += size; //consume payload assert(pos <= stop); @@ -1082,15 +1081,15 @@ long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const if (id == 0x0F43B675) //Cluster ID off = idpos - m_start; } - + Segment* const this_ = const_cast(this); const size_t idx = m_clusterCount; - + if (pos >= stop) { pos_ = stop; - -#if 0 + +#if 0 if (off < 0) { pCluster = Cluster::CreateEndOfStream(this_, idx); @@ -1100,21 +1099,21 @@ long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const if (off < 0) return 1L; #endif - - //Reading 0 bytes at pos might work too -- it would depend + + //Reading 0 bytes at pos might work too -- it would depend //on how the reader is implemented. - + unsigned char b; const long hr = m_pReader->Read(pos - 1, 1, &b); - + if (hr < 0) return hr; - + if (hr != 0L) return E_BUFFER_NOT_FULL; } - + assert(off >= 0); assert(pos_ >= m_start); assert(pos_ <= stop); @@ -1127,29 +1126,29 @@ long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const bool Segment::AddCluster(Cluster* pCluster, long long pos) { assert(pos >= m_start); - + const long long stop = m_start + m_size; assert(pos <= stop); - if (pCluster) + if (pCluster) m_clusters[pos] = pCluster; - + m_pos = pos; //m_pos >= stop is now we know we have all clusters - + return (pos >= stop); } long Segment::Load() { - //Outermost (level 0) segment object has been constructed, + //Outermost (level 0) segment object has been constructed, //and pos designates start of payload. We need to find the //inner (level 1) elements. const long long stop = m_start + m_size; #ifdef _DEBUG { long long total, available; - + long hr = m_pReader->Length(&total, &available); assert(hr >= 0); assert(available >= total); @@ -1157,74 +1156,74 @@ long Segment::Load() } #endif long long index = m_pos; - + m_clusterCount = 0; - long long* fileposition_of_clusters = NULL; - long long size_of_cluster_pos = 0; + long long* fileposition_of_clusters = NULL; + long long size_of_cluster_pos = 0; while (index < stop) { long len = 0; long long result = GetUIntLength(m_pReader, index, len); - + if (result < 0) //error return static_cast(result); - + if ((index + len) > stop) return E_FILE_FORMAT_INVALID; - + const long long idpos = index; const long long id = ReadUInt(m_pReader, idpos, len); - + if (id < 0) //error return static_cast(id); - + index += len; //consume ID - + //Read Size result = GetUIntLength(m_pReader, index, len); - + if (result < 0) //error return static_cast(result); - + if ((index + len) > stop) return E_FILE_FORMAT_INVALID; - + const long long size = ReadUInt(m_pReader, index, len); - + if (size < 0) //error return static_cast(size); - + index += len; //consume length of size of element - - if (id == 0x0F43B675) // Cluster ID - { - assert(fileposition_of_clusters); - if (m_clusterCount > size_of_cluster_pos) - { - size_of_cluster_pos *= 2; - long long* const temp = new long long[size_of_cluster_pos]; - memset(temp, 0, size_of_cluster_pos); - memcpy(temp, fileposition_of_clusters, size_of_cluster_pos); - delete [] fileposition_of_clusters; - fileposition_of_clusters = temp; - } - fileposition_of_clusters[m_clusterCount] = idpos; - ++m_clusterCount; - } - else if (id == 0x0549A966) //Segment Info ID + + if (id == 0x0F43B675) // Cluster ID + { + assert(fileposition_of_clusters); + if (m_clusterCount > size_of_cluster_pos) + { + size_of_cluster_pos *= 2; + long long* const temp = new long long[size_of_cluster_pos]; + memset(temp, 0, size_of_cluster_pos); + memcpy(temp, fileposition_of_clusters, size_of_cluster_pos); + delete [] fileposition_of_clusters; + fileposition_of_clusters = temp; + } + fileposition_of_clusters[m_clusterCount] = idpos; + ++m_clusterCount; + } + else if (id == 0x0549A966) //Segment Info ID { assert(m_pInfo == NULL); - m_pInfo = new SegmentInfo(this, index, size); - assert(m_pInfo); - assert(m_clusterCount == 0); + m_pInfo = new SegmentInfo(this, index, size); + assert(m_pInfo); + assert(m_clusterCount == 0); - const long long duration = m_pInfo->GetDuration(); - size_of_cluster_pos = duration / 1000000000 + 1; - fileposition_of_clusters = new long long[size_of_cluster_pos]; - memset(fileposition_of_clusters, 0, size_of_cluster_pos); + const long long duration = m_pInfo->GetDuration(); + size_of_cluster_pos = duration / 1000000000 + 1; + fileposition_of_clusters = new long long[size_of_cluster_pos]; + memset(fileposition_of_clusters, 0, size_of_cluster_pos); } index += size; } @@ -1232,58 +1231,56 @@ long Segment::Load() if (m_clusterCount == 0) return -1L; - m_clusters = new Cluster*[m_clusterCount]; + m_clusters = new Cluster*[m_clusterCount]; - for (int i = 0; i < m_clusterCount; ++i) - { - m_clusters[i] = Cluster::Parse(this, i, fileposition_of_clusters[i]); - } - - delete [] fileposition_of_clusters; + for (int i = 0; i < m_clusterCount; ++i) + m_clusters[i] = Cluster::Parse(this, i, fileposition_of_clusters[i]); + + delete [] fileposition_of_clusters; while (m_pos < stop) { long long pos = m_pos; - + long len; long long result = GetUIntLength(m_pReader, pos, len); - + if (result < 0) //error return static_cast(result); - + if ((pos + len) > stop) return E_FILE_FORMAT_INVALID; - + const long long idpos = pos; const long long id = ReadUInt(m_pReader, idpos, len); - + if (id < 0) //error return static_cast(id); - + pos += len; //consume ID - + //Read Size result = GetUIntLength(m_pReader, pos, len); - + if (result < 0) //error return static_cast(result); - + if ((pos + len) > stop) - return E_FILE_FORMAT_INVALID; - + return E_FILE_FORMAT_INVALID; + const long long size = ReadUInt(m_pReader, pos, len); - + if (size < 0) //error return static_cast(size); - + pos += len; //consume length of size of element - + //Pos now points to start of payload - + if ((pos + size) > stop) return E_FILE_FORMAT_INVALID; - + if (id == 0x0F43B675) //Cluster ID break; @@ -1296,9 +1293,9 @@ long Segment::Load() m_pos = pos + size; //consume payload } - + assert(m_clusters); - + //TODO: see notes above. This check is here (temporarily) to ensure //that the first seekhead has entries for the clusters (because that's //when they're loaded). In case we are given a file that lists the @@ -1307,10 +1304,10 @@ long Segment::Load() //asserting somewhere). But that's only a work-around. What we need //to do is be able to handle having multiple seekheads, and having //clusters listed somewhere besides the first seekhead. - // + // //if (m_clusters == NULL) // return E_FILE_FORMAT_INVALID; - + //NOTE: we stop parsing when we reach the first cluster, under the //assumption all clusters are named in some SeekHead. Clusters //will have been (pre)loaded, so we indicate that we have all clusters @@ -1328,27 +1325,27 @@ void Segment::ParseSeekHead(long long start, long long size_, size_t* pIndex) while (pos < stop) { long len; - + const long long id = ReadUInt(m_pReader, pos, len); assert(id >= 0); //TODO assert((pos + len) <= stop); - + pos += len; //consume ID - + const long long size = ReadUInt(m_pReader, pos, len); assert(size >= 0); assert((pos + len) <= stop); - + pos += len; //consume Size field assert((pos + size) <= stop); if (id == 0x0DBB) //SeekEntry ID ParseSeekEntry(pos, size, pIndex); - + pos += size; //consume payload assert(pos <= stop); } - + assert(pos == stop); } @@ -1360,35 +1357,35 @@ void Segment::ParseSecondarySeekHead(long long off, size_t* pIndex) long long pos = m_start + off; const long long stop = m_start + m_size; - + long len; long long result = GetUIntLength(m_pReader, pos, len); assert(result == 0); assert((pos + len) <= stop); - + const long long idpos = pos; const long long id = ReadUInt(m_pReader, idpos, len); assert(id == 0x014D9B74); //SeekHead ID - + pos += len; //consume ID assert(pos < stop); - + //Read Size - + result = GetUIntLength(m_pReader, pos, len); assert(result == 0); assert((pos + len) <= stop); - + const long long size = ReadUInt(m_pReader, pos, len); assert(size >= 0); - + pos += len; //consume length of size of element assert((pos + size) <= stop); - + //Pos now points to start of payload - + ParseSeekHead(pos, size, pIndex); } @@ -1397,70 +1394,70 @@ void Segment::ParseSeekEntry(long long start, long long size_, size_t* pIndex) long long pos = start; const long long stop = start + size_; - + long len; - + const long long seekIdId = ReadUInt(m_pReader, pos, len); //seekIdId; assert(seekIdId == 0x13AB); //SeekID ID assert((pos + len) <= stop); - + pos += len; //consume id const long long seekIdSize = ReadUInt(m_pReader, pos, len); assert(seekIdSize >= 0); assert((pos + len) <= stop); - + pos += len; //consume size - + const long long seekId = ReadUInt(m_pReader, pos, len); //payload assert(seekId >= 0); assert(len == seekIdSize); assert((pos + len) <= stop); - + pos += seekIdSize; //consume payload - + const long long seekPosId = ReadUInt(m_pReader, pos, len); //seekPosId; assert(seekPosId == 0x13AC); //SeekPos ID assert((pos + len) <= stop); - + pos += len; //consume id - + const long long seekPosSize = ReadUInt(m_pReader, pos, len); assert(seekPosSize >= 0); assert((pos + len) <= stop); pos += len; //consume size assert((pos + seekPosSize) <= stop); - + const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize); assert(seekOff >= 0); assert(seekOff < m_size); - + pos += seekPosSize; //consume payload assert(pos == stop); - + const long long seekPos = m_start + seekOff; assert(seekPos < (m_start + m_size)); - + if (seekId == 0x0F43B675) //cluster id - { + { if (pIndex == NULL) - ++m_clusterCount; + ++m_clusterCount; else { assert(m_clusters); assert(m_clusterCount > 0); - + size_t& index = *pIndex; assert(index < m_clusterCount); - + Cluster*& pCluster = m_clusters[index]; - + pCluster = Cluster::Parse(this, index, seekOff); assert(pCluster); //TODO - + ++index; } } @@ -1477,7 +1474,7 @@ long long Segment::Unparsed() const const long long result = stop - m_pos; assert(result >= 0); - + return result; } @@ -1487,30 +1484,30 @@ long long Segment::Load(long long time_ns) { if (Unparsed() <= 0) return 0; - + while (m_clusters.empty()) { const long long result = Parse(); - + if (result) //error, or not enough bytes available return result; - + if (Unparsed() <= 0) return 0; } - + while (m_clusters.back()->GetTime() < time_ns) { const long long result = Parse(); - + if (result) //error, or not enough bytes available return result; - + if (Unparsed() <= 0) return 0; - } + } - return 0; + return 0; } #endif @@ -1522,7 +1519,7 @@ Cluster* Segment::GetFirst() Cluster* const pCluster = m_clusters[0]; assert(pCluster); - + return pCluster; } @@ -1532,10 +1529,10 @@ Cluster* Segment::GetLast() if ((m_clusters == NULL) || (m_clusterCount <= 0)) return &m_eos; - const size_t idx = m_clusterCount - 1; + const size_t idx = m_clusterCount - 1; Cluster* const pCluster = m_clusters[idx]; assert(pCluster); - + return pCluster; } @@ -1557,15 +1554,15 @@ Cluster* Segment::GetNext(const Cluster* pCurr) size_t idx = pCurr->m_index; assert(idx < m_clusterCount); assert(pCurr == m_clusters[idx]); - + idx++; - - if (idx >= m_clusterCount) + + if (idx >= m_clusterCount) return &m_eos; - + Cluster* const pNext = m_clusters[idx]; assert(pNext); - + return pNext; } @@ -1574,56 +1571,56 @@ Cluster* Segment::GetCluster(long long time_ns) { if ((m_clusters == NULL) || (m_clusterCount <= 0)) return &m_eos; - + { Cluster* const pCluster = m_clusters[0]; assert(pCluster); assert(pCluster->m_index == 0); - + if (time_ns <= pCluster->GetTime()) return pCluster; } - + //Binary search of cluster array - + size_t i = 0; size_t j = m_clusterCount; - + while (i < j) { //INVARIANT: //[0, i) <= time_ns //[i, j) ? //[j, m_clusterCount) > time_ns - + const size_t k = i + (j - i) / 2; assert(k < m_clusterCount); Cluster* const pCluster = m_clusters[k]; assert(pCluster); assert(pCluster->m_index == k); - + const long long t = pCluster->GetTime(); - + if (t <= time_ns) i = k + 1; else j = k; - + assert(i <= j); } - + assert(i == j); assert(i > 0); assert(i <= m_clusterCount); - + const size_t k = i - 1; - + Cluster* const pCluster = m_clusters[k]; assert(pCluster); assert(pCluster->m_index == k); assert(pCluster->GetTime() <= time_ns); - + return pCluster; } @@ -1656,14 +1653,14 @@ SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) : m_pTitleAsUTF8(NULL) { IMkvReader* const pReader = m_pSegment->m_pReader; - + long long pos = start; const long long stop = start + size_; - + m_timecodeScale = 1000000; m_duration = 0; - - + + while (pos < stop) { if (Match(pReader, pos, 0x0AD7B1, m_timecodeScale)) @@ -1672,36 +1669,35 @@ SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) : else if (Match(pReader, pos, 0x0489, m_duration)) assert(m_duration >= 0); - else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8)) //[4D][80] + else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8)) //[4D][80] assert(m_pMuxingAppAsUTF8); else if (Match(pReader, pos, 0x1741, m_pWritingAppAsUTF8)) //[57][41] assert(m_pWritingAppAsUTF8); - + else if (Match(pReader, pos, 0x3BA9, m_pTitleAsUTF8)) //[7B][A9] assert(m_pTitleAsUTF8); - else { long len; - + const long long id = ReadUInt(pReader, pos, len); //id; assert(id >= 0); assert((pos + len) <= stop); - + pos += len; //consume id assert((stop - pos) > 0); - + const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); assert((pos + len) <= stop); - + pos += len + size; //consume size and payload assert(pos <= stop); } } - + assert(pos == stop); } @@ -1718,7 +1714,7 @@ SegmentInfo::~SegmentInfo() delete[] m_pWritingAppAsUTF8; m_pWritingAppAsUTF8 = NULL; } - + if (m_pTitleAsUTF8) { delete[] m_pTitleAsUTF8; @@ -1734,12 +1730,12 @@ long long SegmentInfo::GetTimeCodeScale() const long long SegmentInfo::GetDuration() const { - assert(m_duration >= 0); + assert(m_duration >= 0); assert(m_timecodeScale >= 1); - + const double dd = double(m_duration) * double(m_timecodeScale); const long long d = static_cast(dd); - + return d; } @@ -1782,7 +1778,7 @@ Track::Info::Info(): { } -void Track::Info::Clear() +void Track::Info::Clear() { delete[] nameAsUTF8; nameAsUTF8 = NULL; @@ -1792,7 +1788,7 @@ void Track::Info::Clear() delete[] codecPrivate; codecPrivate = NULL; - + codecPrivateSize = 0; delete[] codecNameAsUTF8; @@ -1823,7 +1819,7 @@ const char* Track::GetNameAsUTF8() const } const char* Track::GetCodecNameAsUTF8() const -{ +{ return m_info.codecNameAsUTF8; } @@ -1844,8 +1840,8 @@ const unsigned char* Track::GetCodecPrivate(size_t& size) const long Track::GetFirst(const BlockEntry*& pBlockEntry) const { Cluster* const pCluster = m_pSegment->GetFirst(); - - //If Segment::GetFirst returns NULL, then this must be a network + + //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. @@ -1854,20 +1850,20 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const pBlockEntry = NULL; return E_BUFFER_NOT_FULL; //return 1L instead? } - + pBlockEntry = pCluster->GetFirst(); - + while (pBlockEntry) { const Block* const pBlock = pBlockEntry->GetBlock(); assert(pBlock); - + if (pBlock->GetTrackNumber() == (unsigned long)m_info.number) return 0L; - + pBlockEntry = pCluster->GetNext(pBlockEntry); } - + //NOTE: if we get here, it means that we didn't find a block with //a matching track number. We interpret that as an error (which //might be too conservative). @@ -1881,28 +1877,28 @@ long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) { assert(pCurrEntry); assert(!pCurrEntry->EOS()); //? - assert(pCurrEntry->GetBlock()->GetTrackNumber() == (unsigned long)m_info.number); - + assert(pCurrEntry->GetBlock()->GetTrackNumber() == (unsigned long)m_info.number); + const Cluster* const pCurrCluster = pCurrEntry->GetCluster(); assert(pCurrCluster); assert(!pCurrCluster->EOS()); - + pNextEntry = pCurrCluster->GetNext(pCurrEntry); - + while (pNextEntry) - { + { const Block* const pNextBlock = pNextEntry->GetBlock(); assert(pNextBlock); - + if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number) return 0L; - + pNextEntry = pCurrCluster->GetNext(pNextEntry); } - Segment* pSegment = pCurrCluster->m_pSegment; + Segment* pSegment = pCurrCluster->m_pSegment; Cluster* const pNextCluster = pSegment->GetNext(pCurrCluster); - + if ((pNextCluster == NULL) || pNextCluster->EOS()) { if (pSegment->Unparsed() <= 0) //all clusters have been loaded @@ -1910,27 +1906,27 @@ long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) pNextEntry = GetEOS(); return 1L; } - + pNextEntry = NULL; return E_BUFFER_NOT_FULL; } - + pNextEntry = pNextCluster->GetFirst(); - + while (pNextEntry) { const Block* const pNextBlock = pNextEntry->GetBlock(); assert(pNextBlock); - + if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number) return 0L; - + pNextEntry = pNextCluster->GetNext(pNextEntry); } - + //TODO: what has happened here is that we did not find a block //with a matching track number on the next cluster. It might - //be the case that some cluster beyond the next cluster + //be the case that some cluster beyond the next cluster //contains a block having a matching track number, but for //now we terminate the search immediately. We do this so that //we don't end up searching the entire file looking for the @@ -1940,7 +1936,7 @@ long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) //there is a large gap in time, or large gap in file position. It //might very well be the case that the approach we use here is //unnecessarily conservative. - + //TODO: again, here's a case where we need to return the special //EOS block. Or something. It's OK if pNext is NULL, because //we only need it to set the stop time of the media sample. @@ -2027,18 +2023,18 @@ VideoTrack::VideoTrack(Segment* pSegment, const Info& i) : { assert(i.type == 1); assert(i.number > 0); - + IMkvReader* const pReader = pSegment->m_pReader; - + const Settings& s = i.settings; assert(s.start >= 0); assert(s.size >= 0); - + long long pos = s.start; assert(pos >= 0); - + const long long stop = pos + s.size; - + while (pos < stop) { #ifdef _DEBUG @@ -2047,11 +2043,11 @@ VideoTrack::VideoTrack(Segment* pSegment, const Info& i) : assert(id >= 0); //TODO: handle error case assert((pos + len) <= stop); #endif - if (Match(pReader, pos, 0x30, m_width)) + if (Match(pReader, pos, 0x30, m_width)) ; - else if (Match(pReader, pos, 0x3A, m_height)) + else if (Match(pReader, pos, 0x3A, m_height)) ; - else if (Match(pReader, pos, 0x0383E3, m_rate)) + else if (Match(pReader, pos, 0x0383E3, m_rate)) ; else { @@ -2059,23 +2055,23 @@ VideoTrack::VideoTrack(Segment* pSegment, const Info& i) : const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); //TODO: handle error case assert((pos + len) <= stop); - + pos += len; //consume id - + const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); //TODO: handle error case assert((pos + len) <= stop); - + pos += len; //consume length of size assert((pos + size) <= stop); - + //pos now designates start of payload - + pos += size; //consume payload assert(pos <= stop); } } - + return; } @@ -2083,16 +2079,15 @@ VideoTrack::VideoTrack(Segment* pSegment, const Info& i) : bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const { assert(pBlockEntry); - + const Block* const pBlock = pBlockEntry->GetBlock(); - assert(pBlock); + assert(pBlock); assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number); - + return pBlock->IsKey(); } - long long VideoTrack::GetWidth() const { return m_width; @@ -2112,22 +2107,25 @@ double VideoTrack::GetFrameRate() const AudioTrack::AudioTrack(Segment* pSegment, const Info& i) : - Track(pSegment, i) + Track(pSegment, i), + m_rate(0.0), + m_channels(0), + m_bitDepth(-1) { assert(i.type == 2); assert(i.number > 0); IMkvReader* const pReader = pSegment->m_pReader; - + const Settings& s = i.settings; assert(s.start >= 0); assert(s.size >= 0); - + long long pos = s.start; assert(pos >= 0); - + const long long stop = pos + s.size; - + while (pos < stop) { #ifdef _DEBUG @@ -2136,30 +2134,30 @@ AudioTrack::AudioTrack(Segment* pSegment, const Info& i) : assert(id >= 0); //TODO: handle error case assert((pos + len) <= stop); #endif - if (Match(pReader, pos, 0x35, m_rate)) + if (Match(pReader, pos, 0x35, m_rate)) ; - else if (Match(pReader, pos, 0x1F, m_channels)) + else if (Match(pReader, pos, 0x1F, m_channels)) + ; + else if (Match(pReader, pos, 0x2264, m_bitDepth)) ; - else if (Match(pReader, pos, 0x2264, m_bitDepth)) - ; else { long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); //TODO: handle error case assert((pos + len) <= stop); - + pos += len; //consume id - + const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); //TODO: handle error case assert((pos + len) <= stop); - + pos += len; //consume length of size assert((pos + size) <= stop); - + //pos now designates start of payload - + pos += size; //consume payload assert(pos <= stop); } @@ -2171,7 +2169,7 @@ AudioTrack::AudioTrack(Segment* pSegment, const Info& i) : bool AudioTrack::VetEntry(const BlockEntry* pBlockEntry) const { assert(pBlockEntry); - + const Block* const pBlock = pBlockEntry->GetBlock(); assert(pBlock); assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number); @@ -2205,32 +2203,32 @@ Tracks::Tracks(Segment* pSegment, long long start, long long size_) : { long long stop = m_start + m_size; IMkvReader* const pReader = m_pSegment->m_pReader; - + long long pos1 = m_start; int count = 0; - + while (pos1 < stop) { long len; const long long id = ReadUInt(pReader, pos1, len); assert(id >= 0); assert((pos1 + len) <= stop); - + pos1 += len; //consume id - + const long long size = ReadUInt(pReader, pos1, len); assert(size >= 0); assert((pos1 + len) <= stop); - + pos1 += len; //consume length of size - + //pos now desinates start of element if (id == 0x2E) //TrackEntry ID ++count; - + pos1 += size; //consume payload assert(pos1 <= stop); - } + } if (count <= 0) return; @@ -2246,30 +2244,31 @@ Tracks::Tracks(Segment* pSegment, long long start, long long size_) : const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert((pos + len) <= stop); - + pos += len; //consume id - + const long long size1 = ReadUInt(pReader, pos, len); assert(size1 >= 0); assert((pos + len) <= stop); - + pos += len; //consume length of size - + //pos now desinates start of element - + if (id == 0x2E) //TrackEntry ID ParseTrackEntry(pos, size1, *m_trackEntriesEnd++); - + pos += size1; //consume payload assert(pos <= stop); - } + } } + unsigned long Tracks::GetTracksCount() const { const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries; assert(result >= 0); - + return static_cast(result); } @@ -2280,18 +2279,18 @@ void Tracks::ParseTrackEntry( Track*& pTrack) { IMkvReader* const pReader = m_pSegment->m_pReader; - + long long pos = start; const long long stop = start + size; Track::Info i; - + Track::Settings videoSettings; videoSettings.start = -1; - + Track::Settings audioSettings; audioSettings.start = -1; - + while (pos < stop) { #ifdef _DEBUG @@ -2302,45 +2301,38 @@ 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, 0x03, i.type)) - ; - - else if (Match(pReader, pos, 0x136E, i.nameAsUTF8)) - assert(i.nameAsUTF8); - - else if (Match(pReader, pos, 0x06, i.codecId)) - ; - - else if (Match(pReader, pos, 0x23A2, i.codecPrivate, i.codecPrivateSize)) - ; - - else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8)) - assert(i.codecNameAsUTF8); - + else if (Match(pReader, pos, 0x33C5, i.uid)) + ; + else if (Match(pReader, pos, 0x03, i.type)) + ; + else if (Match(pReader, pos, 0x136E, i.nameAsUTF8)) + assert(i.nameAsUTF8); + else if (Match(pReader, pos, 0x06, i.codecId)) + ; + else if (Match(pReader, pos, 0x23A2, i.codecPrivate, i.codecPrivateSize)) + ; + else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8)) + assert(i.codecNameAsUTF8); else { long len; - + const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); //TODO: handle error case assert((pos + len) <= stop); - + pos += len; //consume id - + const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); //TODO: handle error case assert((pos + len) <= stop); - + pos += len; //consume length of size const long long start = pos; - + pos += size; //consume payload assert(pos <= stop); - + if (id == 0x60) { videoSettings.start = start; @@ -2353,7 +2345,7 @@ void Tracks::ParseTrackEntry( } } } - + assert(pos == stop); //TODO: propertly vet info.number, to ensure both its existence, //and that it is unique among all tracks. @@ -2361,38 +2353,38 @@ void Tracks::ParseTrackEntry( //TODO: vet settings, to ensure that video settings (0x60) //were specified when type = 1, and that audio settings (0x61) - //were specified when type = 2. + //were specified when type = 2. if (i.type == 1) //video { assert(audioSettings.start < 0); assert(videoSettings.start >= 0); - + i.settings = videoSettings; - + VideoTrack* const t = new VideoTrack(m_pSegment, i); assert(t); //TODO - pTrack = t; + pTrack = t; } else if (i.type == 2) //audio { assert(videoSettings.start < 0); assert(audioSettings.start >= 0); - + i.settings = audioSettings; - + AudioTrack* const t = new AudioTrack(m_pSegment, i); assert(t); //TODO - pTrack = t; + pTrack = t; } else { // for now we do not support other track types yet. // TODO: support other track types i.Clear(); - + pTrack = NULL; } - + return; } @@ -2401,12 +2393,12 @@ Tracks::~Tracks() { Track** i = m_trackEntries; Track** const j = m_trackEntriesEnd; - + while (i != j) { Track* pTrack = *i++; delete pTrack; - pTrack = NULL; + pTrack = NULL; } delete[] m_trackEntries; @@ -2421,7 +2413,7 @@ Track* Tracks::GetTrackByNumber(unsigned long tn) const while (i != j) { Track* const pTrack = *i++; - + if (pTrack == NULL) continue; @@ -2436,7 +2428,7 @@ Track* Tracks::GetTrackByNumber(unsigned long tn) const Track* Tracks::GetTrackByIndex(unsigned long idx) const { const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries; - + if (idx >= static_cast(count)) return NULL; @@ -2447,62 +2439,62 @@ Track* Tracks::GetTrackByIndex(unsigned long idx) const void Cluster::Load() { assert(m_pSegment); - + if (m_start > 0) { assert(m_size > 0); assert(m_timecode >= 0); return; } - + assert(m_size == 0); assert(m_timecode < 0); - + IMkvReader* const pReader = m_pSegment->m_pReader; long long pos = -m_start; - - long len; + + long len; const long long id_ = ReadUInt(pReader, pos, len); assert(id_ >= 0); assert(id_ == 0x0F43B675); //Cluster ID - + pos += len; //consume id - + const long long size_ = ReadUInt(pReader, pos, len); assert(size_ >= 0); - + pos += len; //consume size - + m_start = pos; m_size = size_; - + const long long stop = m_start + size_; - + long long timecode = -1; - + while (pos < stop) { if (Match(pReader, pos, 0x67, timecode)) - break; + break; else { 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 break; - + if (id == 0x23) //SimpleBlock ID break; @@ -2510,10 +2502,10 @@ void Cluster::Load() assert(pos <= stop); } } - + assert(pos <= stop); assert(timecode >= 0); - + m_timecode = timecode; } @@ -2528,7 +2520,7 @@ Cluster* Cluster::Parse( assert(off < pSegment->m_size); Cluster* const pCluster = new Cluster(pSegment, idx, -off); assert(pCluster); - + return pCluster; } @@ -2566,7 +2558,7 @@ Cluster::~Cluster() { BlockEntry* pBlockEntry = m_pEntries.front(); assert(pBlockEntry); - + m_pEntries.pop_front(); delete pBlockEntry; } @@ -2576,11 +2568,11 @@ Cluster::~Cluster() while (i != j) { BlockEntry* p = *i++; - + assert(p); delete p; } - + delete[] m_pEntries; #endif