Home | History | Annotate | Download | only in libwebm
      1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the LICENSE file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS.  All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 
      9 #include "mkvparser.hpp"
     10 
     11 #if defined(_MSC_VER) && _MSC_VER < 1800
     12 #include <float.h>  // _isnan() / _finite()
     13 #define MSC_COMPAT
     14 #endif
     15 
     16 #include <cassert>
     17 #include <climits>
     18 #include <cmath>
     19 #include <cstring>
     20 #include <new>
     21 
     22 #include "webmids.hpp"
     23 
     24 #ifdef _MSC_VER
     25 // Disable MSVC warnings that suggest making code non-portable.
     26 #pragma warning(disable : 4996)
     27 #endif
     28 
     29 namespace mkvparser {
     30 
     31 #ifdef MSC_COMPAT
     32 inline bool isnan(double val) { return !!_isnan(val); }
     33 inline bool isinf(double val) { return !_finite(val); }
     34 #else
     35 inline bool isnan(double val) { return std::isnan(val); }
     36 inline bool isinf(double val) { return std::isinf(val); }
     37 #endif  // MSC_COMPAT
     38 
     39 IMkvReader::~IMkvReader() {}
     40 
     41 template<typename Type> Type* SafeArrayAlloc(unsigned long long num_elements,
     42                                              unsigned long long element_size) {
     43   if (num_elements == 0 || element_size == 0)
     44     return NULL;
     45 
     46   const size_t kMaxAllocSize = 0x80000000;  // 2GiB
     47   const unsigned long long num_bytes = num_elements * element_size;
     48   if (element_size > (kMaxAllocSize / num_elements))
     49     return NULL;
     50   if (num_bytes != static_cast<size_t>(num_bytes))
     51     return NULL;
     52 
     53   return new (std::nothrow) Type[static_cast<size_t>(num_bytes)];
     54 }
     55 
     56 void GetVersion(int& major, int& minor, int& build, int& revision) {
     57   major = 1;
     58   minor = 0;
     59   build = 0;
     60   revision = 30;
     61 }
     62 
     63 long long ReadUInt(IMkvReader* pReader, long long pos, long& len) {
     64   if (!pReader || pos < 0)
     65     return E_FILE_FORMAT_INVALID;
     66 
     67   len = 1;
     68   unsigned char b;
     69   int status = pReader->Read(pos, 1, &b);
     70 
     71   if (status < 0)  // error or underflow
     72     return status;
     73 
     74   if (status > 0)  // interpreted as "underflow"
     75     return E_BUFFER_NOT_FULL;
     76 
     77   if (b == 0)  // we can't handle u-int values larger than 8 bytes
     78     return E_FILE_FORMAT_INVALID;
     79 
     80   unsigned char m = 0x80;
     81 
     82   while (!(b & m)) {
     83     m >>= 1;
     84     ++len;
     85   }
     86 
     87   long long result = b & (~m);
     88   ++pos;
     89 
     90   for (int i = 1; i < len; ++i) {
     91     status = pReader->Read(pos, 1, &b);
     92 
     93     if (status < 0) {
     94       len = 1;
     95       return status;
     96     }
     97 
     98     if (status > 0) {
     99       len = 1;
    100       return E_BUFFER_NOT_FULL;
    101     }
    102 
    103     result <<= 8;
    104     result |= b;
    105 
    106     ++pos;
    107   }
    108 
    109   return result;
    110 }
    111 
    112 // Reads an EBML ID and returns it.
    113 // An ID must at least 1 byte long, cannot exceed 4, and its value must be
    114 // greater than 0.
    115 // See known EBML values and EBMLMaxIDLength:
    116 // http://www.matroska.org/technical/specs/index.html
    117 // Returns the ID, or a value less than 0 to report an error while reading the
    118 // ID.
    119 long long ReadID(IMkvReader* pReader, long long pos, long& len) {
    120   if (pReader == NULL || pos < 0)
    121     return E_FILE_FORMAT_INVALID;
    122 
    123   // Read the first byte. The length in bytes of the ID is determined by
    124   // finding the first set bit in the first byte of the ID.
    125   unsigned char temp_byte = 0;
    126   int read_status = pReader->Read(pos, 1, &temp_byte);
    127 
    128   if (read_status < 0)
    129     return E_FILE_FORMAT_INVALID;
    130   else if (read_status > 0)  // No data to read.
    131     return E_BUFFER_NOT_FULL;
    132 
    133   if (temp_byte == 0)  // ID length > 8 bytes; invalid file.
    134     return E_FILE_FORMAT_INVALID;
    135 
    136   int bit_pos = 0;
    137   const int kMaxIdLengthInBytes = 4;
    138   const int kCheckByte = 0x80;
    139 
    140   // Find the first bit that's set.
    141   bool found_bit = false;
    142   for (; bit_pos < kMaxIdLengthInBytes; ++bit_pos) {
    143     if ((kCheckByte >> bit_pos) & temp_byte) {
    144       found_bit = true;
    145       break;
    146     }
    147   }
    148 
    149   if (!found_bit) {
    150     // The value is too large to be a valid ID.
    151     return E_FILE_FORMAT_INVALID;
    152   }
    153 
    154   // Read the remaining bytes of the ID (if any).
    155   const int id_length = bit_pos + 1;
    156   long long ebml_id = temp_byte;
    157   for (int i = 1; i < id_length; ++i) {
    158     ebml_id <<= 8;
    159     read_status = pReader->Read(pos + i, 1, &temp_byte);
    160 
    161     if (read_status < 0)
    162       return E_FILE_FORMAT_INVALID;
    163     else if (read_status > 0)
    164       return E_BUFFER_NOT_FULL;
    165 
    166     ebml_id |= temp_byte;
    167   }
    168 
    169   len = id_length;
    170   return ebml_id;
    171 }
    172 
    173 long long GetUIntLength(IMkvReader* pReader, long long pos, long& len) {
    174   if (!pReader || pos < 0)
    175     return E_FILE_FORMAT_INVALID;
    176 
    177   long long total, available;
    178 
    179   int status = pReader->Length(&total, &available);
    180   if (status < 0 || (total >= 0 && available > total))
    181     return E_FILE_FORMAT_INVALID;
    182 
    183   len = 1;
    184 
    185   if (pos >= available)
    186     return pos;  // too few bytes available
    187 
    188   unsigned char b;
    189 
    190   status = pReader->Read(pos, 1, &b);
    191 
    192   if (status != 0)
    193     return status;
    194 
    195   if (b == 0)  // we can't handle u-int values larger than 8 bytes
    196     return E_FILE_FORMAT_INVALID;
    197 
    198   unsigned char m = 0x80;
    199 
    200   while (!(b & m)) {
    201     m >>= 1;
    202     ++len;
    203   }
    204 
    205   return 0;  // success
    206 }
    207 
    208 // TODO(vigneshv): This function assumes that unsigned values never have their
    209 // high bit set.
    210 long long UnserializeUInt(IMkvReader* pReader, long long pos, long long size) {
    211   if (!pReader || pos < 0 || (size <= 0) || (size > 8))
    212     return E_FILE_FORMAT_INVALID;
    213 
    214   long long result = 0;
    215 
    216   for (long long i = 0; i < size; ++i) {
    217     unsigned char b;
    218 
    219     const long status = pReader->Read(pos, 1, &b);
    220 
    221     if (status < 0)
    222       return status;
    223 
    224     result <<= 8;
    225     result |= b;
    226 
    227     ++pos;
    228   }
    229 
    230   return result;
    231 }
    232 
    233 long UnserializeFloat(IMkvReader* pReader, long long pos, long long size_,
    234                       double& result) {
    235   if (!pReader || pos < 0 || ((size_ != 4) && (size_ != 8)))
    236     return E_FILE_FORMAT_INVALID;
    237 
    238   const long size = static_cast<long>(size_);
    239 
    240   unsigned char buf[8];
    241 
    242   const int status = pReader->Read(pos, size, buf);
    243 
    244   if (status < 0)  // error
    245     return status;
    246 
    247   if (size == 4) {
    248     union {
    249       float f;
    250       unsigned long ff;
    251     };
    252 
    253     ff = 0;
    254 
    255     for (int i = 0;;) {
    256       ff |= buf[i];
    257 
    258       if (++i >= 4)
    259         break;
    260 
    261       ff <<= 8;
    262     }
    263 
    264     result = f;
    265   } else {
    266     union {
    267       double d;
    268       unsigned long long dd;
    269     };
    270 
    271     dd = 0;
    272 
    273     for (int i = 0;;) {
    274       dd |= buf[i];
    275 
    276       if (++i >= 8)
    277         break;
    278 
    279       dd <<= 8;
    280     }
    281 
    282     result = d;
    283   }
    284 
    285   if (mkvparser::isinf(result) || mkvparser::isnan(result))
    286     return E_FILE_FORMAT_INVALID;
    287 
    288   return 0;
    289 }
    290 
    291 long UnserializeInt(IMkvReader* pReader, long long pos, long long size,
    292                     long long& result_ref) {
    293   if (!pReader || pos < 0 || size < 1 || size > 8)
    294     return E_FILE_FORMAT_INVALID;
    295 
    296   signed char first_byte = 0;
    297   const long status = pReader->Read(pos, 1, (unsigned char*)&first_byte);
    298 
    299   if (status < 0)
    300     return status;
    301 
    302   unsigned long long result = first_byte;
    303   ++pos;
    304 
    305   for (long i = 1; i < size; ++i) {
    306     unsigned char b;
    307 
    308     const long status = pReader->Read(pos, 1, &b);
    309 
    310     if (status < 0)
    311       return status;
    312 
    313     result <<= 8;
    314     result |= b;
    315 
    316     ++pos;
    317   }
    318 
    319   result_ref = static_cast<long long>(result);
    320   return 0;
    321 }
    322 
    323 long UnserializeString(IMkvReader* pReader, long long pos, long long size,
    324                        char*& str) {
    325   delete[] str;
    326   str = NULL;
    327 
    328   if (size >= LONG_MAX || size < 0)
    329     return E_FILE_FORMAT_INVALID;
    330 
    331   // +1 for '\0' terminator
    332   const long required_size = static_cast<long>(size) + 1;
    333 
    334   str = SafeArrayAlloc<char>(1, required_size);
    335   if (str == NULL)
    336     return E_FILE_FORMAT_INVALID;
    337 
    338   unsigned char* const buf = reinterpret_cast<unsigned char*>(str);
    339 
    340   const long status = pReader->Read(pos, static_cast<long>(size), buf);
    341 
    342   if (status) {
    343     delete[] str;
    344     str = NULL;
    345 
    346     return status;
    347   }
    348 
    349   str[required_size - 1] = '\0';
    350   return 0;
    351 }
    352 
    353 long ParseElementHeader(IMkvReader* pReader, long long& pos,
    354                         long long stop, long long& id,
    355                         long long& size) {
    356   if (stop >= 0 && pos >= stop)
    357     return E_FILE_FORMAT_INVALID;
    358 
    359   long len;
    360 
    361   id = ReadID(pReader, pos, len);
    362 
    363   if (id < 0)
    364     return E_FILE_FORMAT_INVALID;
    365 
    366   pos += len;  // consume id
    367 
    368   if (stop >= 0 && pos >= stop)
    369     return E_FILE_FORMAT_INVALID;
    370 
    371   size = ReadUInt(pReader, pos, len);
    372 
    373   if (size < 0 || len < 1 || len > 8) {
    374     // Invalid: Negative payload size, negative or 0 length integer, or integer
    375     // larger than 64 bits (libwebm cannot handle them).
    376     return E_FILE_FORMAT_INVALID;
    377   }
    378 
    379   // Avoid rolling over pos when very close to LLONG_MAX.
    380   const unsigned long long rollover_check =
    381       static_cast<unsigned long long>(pos) + len;
    382   if (rollover_check > LLONG_MAX)
    383     return E_FILE_FORMAT_INVALID;
    384 
    385   pos += len;  // consume length of size
    386 
    387   // pos now designates payload
    388 
    389   if (stop >= 0 && pos >= stop)
    390     return E_FILE_FORMAT_INVALID;
    391 
    392   return 0;  // success
    393 }
    394 
    395 bool Match(IMkvReader* pReader, long long& pos, unsigned long expected_id,
    396            long long& val) {
    397   if (!pReader || pos < 0)
    398     return false;
    399 
    400   long long total = 0;
    401   long long available = 0;
    402 
    403   const long status = pReader->Length(&total, &available);
    404   if (status < 0 || (total >= 0 && available > total))
    405     return false;
    406 
    407   long len = 0;
    408 
    409   const long long id = ReadID(pReader, pos, len);
    410   if (id < 0 || (available - pos) > len)
    411     return false;
    412 
    413   if (static_cast<unsigned long>(id) != expected_id)
    414     return false;
    415 
    416   pos += len;  // consume id
    417 
    418   const long long size = ReadUInt(pReader, pos, len);
    419   if (size < 0 || size > 8 || len < 1 || len > 8 || (available - pos) > len)
    420     return false;
    421 
    422   pos += len;  // consume length of size of payload
    423 
    424   val = UnserializeUInt(pReader, pos, size);
    425   if (val < 0)
    426     return false;
    427 
    428   pos += size;  // consume size of payload
    429 
    430   return true;
    431 }
    432 
    433 bool Match(IMkvReader* pReader, long long& pos, unsigned long expected_id,
    434            unsigned char*& buf, size_t& buflen) {
    435   if (!pReader || pos < 0)
    436     return false;
    437 
    438   long long total = 0;
    439   long long available = 0;
    440 
    441   long status = pReader->Length(&total, &available);
    442   if (status < 0 || (total >= 0 && available > total))
    443     return false;
    444 
    445   long len = 0;
    446   const long long id = ReadID(pReader, pos, len);
    447   if (id < 0 || (available - pos) > len)
    448     return false;
    449 
    450   if (static_cast<unsigned long>(id) != expected_id)
    451     return false;
    452 
    453   pos += len;  // consume id
    454 
    455   const long long size = ReadUInt(pReader, pos, len);
    456   if (size < 0 || len <= 0 || len > 8 || (available - pos) > len)
    457     return false;
    458 
    459   unsigned long long rollover_check =
    460       static_cast<unsigned long long>(pos) + len;
    461   if (rollover_check > LLONG_MAX)
    462     return false;
    463 
    464   pos += len;  // consume length of size of payload
    465 
    466   rollover_check = static_cast<unsigned long long>(pos) + size;
    467   if (rollover_check > LLONG_MAX)
    468     return false;
    469 
    470   if ((pos + size) > available)
    471     return false;
    472 
    473   if (size >= LONG_MAX)
    474     return false;
    475 
    476   const long buflen_ = static_cast<long>(size);
    477 
    478   buf = SafeArrayAlloc<unsigned char>(1, buflen_);
    479   if (!buf)
    480     return false;
    481 
    482   status = pReader->Read(pos, buflen_, buf);
    483   if (status != 0)
    484     return false;
    485 
    486   buflen = buflen_;
    487 
    488   pos += size;  // consume size of payload
    489   return true;
    490 }
    491 
    492 EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); }
    493 
    494 EBMLHeader::~EBMLHeader() { delete[] m_docType; }
    495 
    496 void EBMLHeader::Init() {
    497   m_version = 1;
    498   m_readVersion = 1;
    499   m_maxIdLength = 4;
    500   m_maxSizeLength = 8;
    501 
    502   if (m_docType) {
    503     delete[] m_docType;
    504     m_docType = NULL;
    505   }
    506 
    507   m_docTypeVersion = 1;
    508   m_docTypeReadVersion = 1;
    509 }
    510 
    511 long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) {
    512   if (!pReader)
    513     return E_FILE_FORMAT_INVALID;
    514 
    515   long long total, available;
    516 
    517   long status = pReader->Length(&total, &available);
    518 
    519   if (status < 0)  // error
    520     return status;
    521 
    522   pos = 0;
    523   long long end = (available >= 1024) ? 1024 : available;
    524 
    525   // Scan until we find what looks like the first byte of the EBML header.
    526   const long long kMaxScanBytes = (available >= 1024) ? 1024 : available;
    527   const unsigned char kEbmlByte0 = 0x1A;
    528   unsigned char scan_byte = 0;
    529 
    530   while (pos < kMaxScanBytes) {
    531     status = pReader->Read(pos, 1, &scan_byte);
    532 
    533     if (status < 0)  // error
    534       return status;
    535     else if (status > 0)
    536       return E_BUFFER_NOT_FULL;
    537 
    538     if (scan_byte == kEbmlByte0)
    539       break;
    540 
    541     ++pos;
    542   }
    543 
    544   long len = 0;
    545   const long long ebml_id = ReadID(pReader, pos, len);
    546 
    547   // TODO(tomfinegan): Move Matroska ID constants into a common namespace.
    548   if (len != 4 || ebml_id != mkvmuxer::kMkvEBML)
    549     return E_FILE_FORMAT_INVALID;
    550 
    551   // Move read pos forward to the EBML header size field.
    552   pos += 4;
    553 
    554   // Read length of size field.
    555   long long result = GetUIntLength(pReader, pos, len);
    556 
    557   if (result < 0)  // error
    558     return E_FILE_FORMAT_INVALID;
    559   else if (result > 0)  // need more data
    560     return E_BUFFER_NOT_FULL;
    561 
    562   if (len < 1 || len > 8)
    563     return E_FILE_FORMAT_INVALID;
    564 
    565   if ((total >= 0) && ((total - pos) < len))
    566     return E_FILE_FORMAT_INVALID;
    567 
    568   if ((available - pos) < len)
    569     return pos + len;  // try again later
    570 
    571   // Read the EBML header size.
    572   result = ReadUInt(pReader, pos, len);
    573 
    574   if (result < 0)  // error
    575     return result;
    576 
    577   pos += len;  // consume size field
    578 
    579   // pos now designates start of payload
    580 
    581   if ((total >= 0) && ((total - pos) < result))
    582     return E_FILE_FORMAT_INVALID;
    583 
    584   if ((available - pos) < result)
    585     return pos + result;
    586 
    587   end = pos + result;
    588 
    589   Init();
    590 
    591   while (pos < end) {
    592     long long id, size;
    593 
    594     status = ParseElementHeader(pReader, pos, end, id, size);
    595 
    596     if (status < 0)  // error
    597       return status;
    598 
    599     if (size == 0)
    600       return E_FILE_FORMAT_INVALID;
    601 
    602     if (id == mkvmuxer::kMkvEBMLVersion) {
    603       m_version = UnserializeUInt(pReader, pos, size);
    604 
    605       if (m_version <= 0)
    606         return E_FILE_FORMAT_INVALID;
    607     } else if (id == mkvmuxer::kMkvEBMLReadVersion) {
    608       m_readVersion = UnserializeUInt(pReader, pos, size);
    609 
    610       if (m_readVersion <= 0)
    611         return E_FILE_FORMAT_INVALID;
    612     } else if (id == mkvmuxer::kMkvEBMLMaxIDLength) {
    613       m_maxIdLength = UnserializeUInt(pReader, pos, size);
    614 
    615       if (m_maxIdLength <= 0)
    616         return E_FILE_FORMAT_INVALID;
    617     } else if (id == mkvmuxer::kMkvEBMLMaxSizeLength) {
    618       m_maxSizeLength = UnserializeUInt(pReader, pos, size);
    619 
    620       if (m_maxSizeLength <= 0)
    621         return E_FILE_FORMAT_INVALID;
    622     } else if (id == mkvmuxer::kMkvDocType) {
    623       if (m_docType)
    624         return E_FILE_FORMAT_INVALID;
    625 
    626       status = UnserializeString(pReader, pos, size, m_docType);
    627 
    628       if (status)  // error
    629         return status;
    630     } else if (id == mkvmuxer::kMkvDocTypeVersion) {
    631       m_docTypeVersion = UnserializeUInt(pReader, pos, size);
    632 
    633       if (m_docTypeVersion <= 0)
    634         return E_FILE_FORMAT_INVALID;
    635     } else if (id == mkvmuxer::kMkvDocTypeReadVersion) {
    636       m_docTypeReadVersion = UnserializeUInt(pReader, pos, size);
    637 
    638       if (m_docTypeReadVersion <= 0)
    639         return E_FILE_FORMAT_INVALID;
    640     }
    641 
    642     pos += size;
    643   }
    644 
    645   if (pos != end)
    646     return E_FILE_FORMAT_INVALID;
    647 
    648   // Make sure DocType, DocTypeReadVersion, and DocTypeVersion are valid.
    649   if (m_docType == NULL || m_docTypeReadVersion <= 0 || m_docTypeVersion <= 0)
    650     return E_FILE_FORMAT_INVALID;
    651 
    652   // Make sure EBMLMaxIDLength and EBMLMaxSizeLength are valid.
    653   if (m_maxIdLength <= 0 || m_maxIdLength > 4 ||
    654       m_maxSizeLength <= 0 || m_maxSizeLength > 8)
    655     return E_FILE_FORMAT_INVALID;
    656 
    657   return 0;
    658 }
    659 
    660 Segment::Segment(IMkvReader* pReader, long long elem_start,
    661                  // long long elem_size,
    662                  long long start, long long size)
    663     : m_pReader(pReader),
    664       m_element_start(elem_start),
    665       // m_element_size(elem_size),
    666       m_start(start),
    667       m_size(size),
    668       m_pos(start),
    669       m_pUnknownSize(0),
    670       m_pSeekHead(NULL),
    671       m_pInfo(NULL),
    672       m_pTracks(NULL),
    673       m_pCues(NULL),
    674       m_pChapters(NULL),
    675       m_pTags(NULL),
    676       m_clusters(NULL),
    677       m_clusterCount(0),
    678       m_clusterPreloadCount(0),
    679       m_clusterSize(0) {}
    680 
    681 Segment::~Segment() {
    682   const long count = m_clusterCount + m_clusterPreloadCount;
    683 
    684   Cluster** i = m_clusters;
    685   Cluster** j = m_clusters + count;
    686 
    687   while (i != j) {
    688     Cluster* const p = *i++;
    689     delete p;
    690   }
    691 
    692   delete[] m_clusters;
    693 
    694   delete m_pTracks;
    695   delete m_pInfo;
    696   delete m_pCues;
    697   delete m_pChapters;
    698   delete m_pTags;
    699   delete m_pSeekHead;
    700 }
    701 
    702 long long Segment::CreateInstance(IMkvReader* pReader, long long pos,
    703                                   Segment*& pSegment) {
    704   if (pReader == NULL || pos < 0)
    705     return E_PARSE_FAILED;
    706 
    707   pSegment = NULL;
    708 
    709   long long total, available;
    710 
    711   const long status = pReader->Length(&total, &available);
    712 
    713   if (status < 0)  // error
    714     return status;
    715 
    716   if (available < 0)
    717     return -1;
    718 
    719   if ((total >= 0) && (available > total))
    720     return -1;
    721 
    722   // I would assume that in practice this loop would execute
    723   // exactly once, but we allow for other elements (e.g. Void)
    724   // to immediately follow the EBML header.  This is fine for
    725   // the source filter case (since the entire file is available),
    726   // but in the splitter case over a network we should probably
    727   // just give up early.  We could for example decide only to
    728   // execute this loop a maximum of, say, 10 times.
    729   // TODO:
    730   // There is an implied "give up early" by only parsing up
    731   // to the available limit.  We do do that, but only if the
    732   // total file size is unknown.  We could decide to always
    733   // use what's available as our limit (irrespective of whether
    734   // we happen to know the total file length).  This would have
    735   // as its sense "parse this much of the file before giving up",
    736   // which a slightly different sense from "try to parse up to
    737   // 10 EMBL elements before giving up".
    738 
    739   for (;;) {
    740     if ((total >= 0) && (pos >= total))
    741       return E_FILE_FORMAT_INVALID;
    742 
    743     // Read ID
    744     long len;
    745     long long result = GetUIntLength(pReader, pos, len);
    746 
    747     if (result)  // error, or too few available bytes
    748       return result;
    749 
    750     if ((total >= 0) && ((pos + len) > total))
    751       return E_FILE_FORMAT_INVALID;
    752 
    753     if ((pos + len) > available)
    754       return pos + len;
    755 
    756     const long long idpos = pos;
    757     const long long id = ReadID(pReader, pos, len);
    758 
    759     if (id < 0)
    760       return E_FILE_FORMAT_INVALID;
    761 
    762     pos += len;  // consume ID
    763 
    764     // Read Size
    765 
    766     result = GetUIntLength(pReader, pos, len);
    767 
    768     if (result)  // error, or too few available bytes
    769       return result;
    770 
    771     if ((total >= 0) && ((pos + len) > total))
    772       return E_FILE_FORMAT_INVALID;
    773 
    774     if ((pos + len) > available)
    775       return pos + len;
    776 
    777     long long size = ReadUInt(pReader, pos, len);
    778 
    779     if (size < 0)  // error
    780       return size;
    781 
    782     pos += len;  // consume length of size of element
    783 
    784     // Pos now points to start of payload
    785 
    786     // Handle "unknown size" for live streaming of webm files.
    787     const long long unknown_size = (1LL << (7 * len)) - 1;
    788 
    789     if (id == mkvmuxer::kMkvSegment) {
    790       if (size == unknown_size)
    791         size = -1;
    792 
    793       else if (total < 0)
    794         size = -1;
    795 
    796       else if ((pos + size) > total)
    797         size = -1;
    798 
    799       pSegment = new (std::nothrow) Segment(pReader, idpos, pos, size);
    800       if (pSegment == NULL)
    801         return E_PARSE_FAILED;
    802 
    803       return 0;  // success
    804     }
    805 
    806     if (size == unknown_size)
    807       return E_FILE_FORMAT_INVALID;
    808 
    809     if ((total >= 0) && ((pos + size) > total))
    810       return E_FILE_FORMAT_INVALID;
    811 
    812     if ((pos + size) > available)
    813       return pos + size;
    814 
    815     pos += size;  // consume payload
    816   }
    817 }
    818 
    819 long long Segment::ParseHeaders() {
    820   // Outermost (level 0) segment object has been constructed,
    821   // and pos designates start of payload.  We need to find the
    822   // inner (level 1) elements.
    823   long long total, available;
    824 
    825   const int status = m_pReader->Length(&total, &available);
    826 
    827   if (status < 0)  // error
    828     return status;
    829 
    830   if (total > 0 && available > total)
    831     return E_FILE_FORMAT_INVALID;
    832 
    833   const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
    834 
    835   if ((segment_stop >= 0 && total >= 0 && segment_stop > total) ||
    836       (segment_stop >= 0 && m_pos > segment_stop)) {
    837     return E_FILE_FORMAT_INVALID;
    838   }
    839 
    840   for (;;) {
    841     if ((total >= 0) && (m_pos >= total))
    842       break;
    843 
    844     if ((segment_stop >= 0) && (m_pos >= segment_stop))
    845       break;
    846 
    847     long long pos = m_pos;
    848     const long long element_start = pos;
    849 
    850     // Avoid rolling over pos when very close to LLONG_MAX.
    851     unsigned long long rollover_check = pos + 1ULL;
    852     if (rollover_check > LLONG_MAX)
    853       return E_FILE_FORMAT_INVALID;
    854 
    855     if ((pos + 1) > available)
    856       return (pos + 1);
    857 
    858     long len;
    859     long long result = GetUIntLength(m_pReader, pos, len);
    860 
    861     if (result < 0)  // error
    862       return result;
    863 
    864     if (result > 0) {
    865       // MkvReader doesn't have enough data to satisfy this read attempt.
    866       return (pos + 1);
    867     }
    868 
    869     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
    870       return E_FILE_FORMAT_INVALID;
    871 
    872     if ((pos + len) > available)
    873       return pos + len;
    874 
    875     const long long idpos = pos;
    876     const long long id = ReadID(m_pReader, idpos, len);
    877 
    878     if (id < 0)
    879       return E_FILE_FORMAT_INVALID;
    880 
    881     if (id == mkvmuxer::kMkvCluster)
    882       break;
    883 
    884     pos += len;  // consume ID
    885 
    886     if ((pos + 1) > available)
    887       return (pos + 1);
    888 
    889     // Read Size
    890     result = GetUIntLength(m_pReader, pos, len);
    891 
    892     if (result < 0)  // error
    893       return result;
    894 
    895     if (result > 0) {
    896       // MkvReader doesn't have enough data to satisfy this read attempt.
    897       return (pos + 1);
    898     }
    899 
    900     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
    901       return E_FILE_FORMAT_INVALID;
    902 
    903     if ((pos + len) > available)
    904       return pos + len;
    905 
    906     const long long size = ReadUInt(m_pReader, pos, len);
    907 
    908     if (size < 0 || len < 1 || len > 8) {
    909       // TODO(tomfinegan): ReadUInt should return an error when len is < 1 or
    910       // len > 8 is true instead of checking this _everywhere_.
    911       return size;
    912     }
    913 
    914     pos += len;  // consume length of size of element
    915 
    916     // Avoid rolling over pos when very close to LLONG_MAX.
    917     rollover_check = static_cast<unsigned long long>(pos) + size;
    918     if (rollover_check > LLONG_MAX)
    919       return E_FILE_FORMAT_INVALID;
    920 
    921     const long long element_size = size + pos - element_start;
    922 
    923     // Pos now points to start of payload
    924 
    925     if ((segment_stop >= 0) && ((pos + size) > segment_stop))
    926       return E_FILE_FORMAT_INVALID;
    927 
    928     // We read EBML elements either in total or nothing at all.
    929 
    930     if ((pos + size) > available)
    931       return pos + size;
    932 
    933     if (id == mkvmuxer::kMkvInfo) {
    934       if (m_pInfo)
    935         return E_FILE_FORMAT_INVALID;
    936 
    937       m_pInfo = new (std::nothrow)
    938           SegmentInfo(this, pos, size, element_start, element_size);
    939 
    940       if (m_pInfo == NULL)
    941         return -1;
    942 
    943       const long status = m_pInfo->Parse();
    944 
    945       if (status)
    946         return status;
    947     } else if (id == mkvmuxer::kMkvTracks) {
    948       if (m_pTracks)
    949         return E_FILE_FORMAT_INVALID;
    950 
    951       m_pTracks = new (std::nothrow)
    952           Tracks(this, pos, size, element_start, element_size);
    953 
    954       if (m_pTracks == NULL)
    955         return -1;
    956 
    957       const long status = m_pTracks->Parse();
    958 
    959       if (status)
    960         return status;
    961     } else if (id == mkvmuxer::kMkvCues) {
    962       if (m_pCues == NULL) {
    963         m_pCues = new (std::nothrow)
    964             Cues(this, pos, size, element_start, element_size);
    965 
    966         if (m_pCues == NULL)
    967           return -1;
    968       }
    969     } else if (id == mkvmuxer::kMkvSeekHead) {
    970       if (m_pSeekHead == NULL) {
    971         m_pSeekHead = new (std::nothrow)
    972             SeekHead(this, pos, size, element_start, element_size);
    973 
    974         if (m_pSeekHead == NULL)
    975           return -1;
    976 
    977         const long status = m_pSeekHead->Parse();
    978 
    979         if (status)
    980           return status;
    981       }
    982     } else if (id == mkvmuxer::kMkvChapters) {
    983       if (m_pChapters == NULL) {
    984         m_pChapters = new (std::nothrow)
    985             Chapters(this, pos, size, element_start, element_size);
    986 
    987         if (m_pChapters == NULL)
    988           return -1;
    989 
    990         const long status = m_pChapters->Parse();
    991 
    992         if (status)
    993           return status;
    994       }
    995     } else if (id == mkvmuxer::kMkvTags) {
    996       if (m_pTags == NULL) {
    997         m_pTags = new (std::nothrow)
    998             Tags(this, pos, size, element_start, element_size);
    999 
   1000         if (m_pTags == NULL)
   1001           return -1;
   1002 
   1003         const long status = m_pTags->Parse();
   1004 
   1005         if (status)
   1006           return status;
   1007       }
   1008     }
   1009 
   1010     m_pos = pos + size;  // consume payload
   1011   }
   1012 
   1013   if (segment_stop >= 0 && m_pos > segment_stop)
   1014     return E_FILE_FORMAT_INVALID;
   1015 
   1016   if (m_pInfo == NULL)  // TODO: liberalize this behavior
   1017     return E_FILE_FORMAT_INVALID;
   1018 
   1019   if (m_pTracks == NULL)
   1020     return E_FILE_FORMAT_INVALID;
   1021 
   1022   return 0;  // success
   1023 }
   1024 
   1025 long Segment::LoadCluster(long long& pos, long& len) {
   1026   for (;;) {
   1027     const long result = DoLoadCluster(pos, len);
   1028 
   1029     if (result <= 1)
   1030       return result;
   1031   }
   1032 }
   1033 
   1034 long Segment::DoLoadCluster(long long& pos, long& len) {
   1035   if (m_pos < 0)
   1036     return DoLoadClusterUnknownSize(pos, len);
   1037 
   1038   long long total, avail;
   1039 
   1040   long status = m_pReader->Length(&total, &avail);
   1041 
   1042   if (status < 0)  // error
   1043     return status;
   1044 
   1045   if (total >= 0 && avail > total)
   1046     return E_FILE_FORMAT_INVALID;
   1047 
   1048   const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
   1049 
   1050   long long cluster_off = -1;  // offset relative to start of segment
   1051   long long cluster_size = -1;  // size of cluster payload
   1052 
   1053   for (;;) {
   1054     if ((total >= 0) && (m_pos >= total))
   1055       return 1;  // no more clusters
   1056 
   1057     if ((segment_stop >= 0) && (m_pos >= segment_stop))
   1058       return 1;  // no more clusters
   1059 
   1060     pos = m_pos;
   1061 
   1062     // Read ID
   1063 
   1064     if ((pos + 1) > avail) {
   1065       len = 1;
   1066       return E_BUFFER_NOT_FULL;
   1067     }
   1068 
   1069     long long result = GetUIntLength(m_pReader, pos, len);
   1070 
   1071     if (result < 0)  // error
   1072       return static_cast<long>(result);
   1073 
   1074     if (result > 0)
   1075       return E_BUFFER_NOT_FULL;
   1076 
   1077     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   1078       return E_FILE_FORMAT_INVALID;
   1079 
   1080     if ((pos + len) > avail)
   1081       return E_BUFFER_NOT_FULL;
   1082 
   1083     const long long idpos = pos;
   1084     const long long id = ReadID(m_pReader, idpos, len);
   1085 
   1086     if (id < 0)
   1087       return E_FILE_FORMAT_INVALID;
   1088 
   1089     pos += len;  // consume ID
   1090 
   1091     // Read Size
   1092 
   1093     if ((pos + 1) > avail) {
   1094       len = 1;
   1095       return E_BUFFER_NOT_FULL;
   1096     }
   1097 
   1098     result = GetUIntLength(m_pReader, pos, len);
   1099 
   1100     if (result < 0)  // error
   1101       return static_cast<long>(result);
   1102 
   1103     if (result > 0)
   1104       return E_BUFFER_NOT_FULL;
   1105 
   1106     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   1107       return E_FILE_FORMAT_INVALID;
   1108 
   1109     if ((pos + len) > avail)
   1110       return E_BUFFER_NOT_FULL;
   1111 
   1112     const long long size = ReadUInt(m_pReader, pos, len);
   1113 
   1114     if (size < 0)  // error
   1115       return static_cast<long>(size);
   1116 
   1117     pos += len;  // consume length of size of element
   1118 
   1119     // pos now points to start of payload
   1120 
   1121     if (size == 0) {
   1122       // Missing element payload: move on.
   1123       m_pos = pos;
   1124       continue;
   1125     }
   1126 
   1127     const long long unknown_size = (1LL << (7 * len)) - 1;
   1128 
   1129     if ((segment_stop >= 0) && (size != unknown_size) &&
   1130         ((pos + size) > segment_stop)) {
   1131       return E_FILE_FORMAT_INVALID;
   1132     }
   1133 
   1134     if (id == mkvmuxer::kMkvCues) {
   1135       if (size == unknown_size) {
   1136         // Cues element of unknown size: Not supported.
   1137         return E_FILE_FORMAT_INVALID;
   1138       }
   1139 
   1140       if (m_pCues == NULL) {
   1141         const long long element_size = (pos - idpos) + size;
   1142 
   1143         m_pCues = new (std::nothrow) Cues(this, pos, size, idpos, element_size);
   1144         if (m_pCues == NULL)
   1145           return -1;
   1146       }
   1147 
   1148       m_pos = pos + size;  // consume payload
   1149       continue;
   1150     }
   1151 
   1152     if (id != mkvmuxer::kMkvCluster) {
   1153       // Besides the Segment, Libwebm allows only cluster elements of unknown
   1154       // size. Fail the parse upon encountering a non-cluster element reporting
   1155       // unknown size.
   1156       if (size == unknown_size)
   1157         return E_FILE_FORMAT_INVALID;
   1158 
   1159       m_pos = pos + size;  // consume payload
   1160       continue;
   1161     }
   1162 
   1163     // We have a cluster.
   1164 
   1165     cluster_off = idpos - m_start;  // relative pos
   1166 
   1167     if (size != unknown_size)
   1168       cluster_size = size;
   1169 
   1170     break;
   1171   }
   1172 
   1173   if (cluster_off < 0) {
   1174     // No cluster, die.
   1175     return E_FILE_FORMAT_INVALID;
   1176   }
   1177 
   1178   long long pos_;
   1179   long len_;
   1180 
   1181   status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_);
   1182 
   1183   if (status < 0) {  // error, or underflow
   1184     pos = pos_;
   1185     len = len_;
   1186 
   1187     return status;
   1188   }
   1189 
   1190   // status == 0 means "no block entries found"
   1191   // status > 0 means "found at least one block entry"
   1192 
   1193   // TODO:
   1194   // The issue here is that the segment increments its own
   1195   // pos ptr past the most recent cluster parsed, and then
   1196   // starts from there to parse the next cluster.  If we
   1197   // don't know the size of the current cluster, then we
   1198   // must either parse its payload (as we do below), looking
   1199   // for the cluster (or cues) ID to terminate the parse.
   1200   // This isn't really what we want: rather, we really need
   1201   // a way to create the curr cluster object immediately.
   1202   // The pity is that cluster::parse can determine its own
   1203   // boundary, and we largely duplicate that same logic here.
   1204   //
   1205   // Maybe we need to get rid of our look-ahead preloading
   1206   // in source::parse???
   1207   //
   1208   // As we're parsing the blocks in the curr cluster
   1209   //(in cluster::parse), we should have some way to signal
   1210   // to the segment that we have determined the boundary,
   1211   // so it can adjust its own segment::m_pos member.
   1212   //
   1213   // The problem is that we're asserting in asyncreadinit,
   1214   // because we adjust the pos down to the curr seek pos,
   1215   // and the resulting adjusted len is > 2GB.  I'm suspicious
   1216   // that this is even correct, but even if it is, we can't
   1217   // be loading that much data in the cache anyway.
   1218 
   1219   const long idx = m_clusterCount;
   1220 
   1221   if (m_clusterPreloadCount > 0) {
   1222     if (idx >= m_clusterSize)
   1223       return E_FILE_FORMAT_INVALID;
   1224 
   1225     Cluster* const pCluster = m_clusters[idx];
   1226     if (pCluster == NULL || pCluster->m_index >= 0)
   1227       return E_FILE_FORMAT_INVALID;
   1228 
   1229     const long long off = pCluster->GetPosition();
   1230     if (off < 0)
   1231       return E_FILE_FORMAT_INVALID;
   1232 
   1233     if (off == cluster_off) {  // preloaded already
   1234       if (status == 0)  // no entries found
   1235         return E_FILE_FORMAT_INVALID;
   1236 
   1237       if (cluster_size >= 0)
   1238         pos += cluster_size;
   1239       else {
   1240         const long long element_size = pCluster->GetElementSize();
   1241 
   1242         if (element_size <= 0)
   1243           return E_FILE_FORMAT_INVALID;  // TODO: handle this case
   1244 
   1245         pos = pCluster->m_element_start + element_size;
   1246       }
   1247 
   1248       pCluster->m_index = idx;  // move from preloaded to loaded
   1249       ++m_clusterCount;
   1250       --m_clusterPreloadCount;
   1251 
   1252       m_pos = pos;  // consume payload
   1253       if (segment_stop >= 0 && m_pos > segment_stop)
   1254         return E_FILE_FORMAT_INVALID;
   1255 
   1256       return 0;  // success
   1257     }
   1258   }
   1259 
   1260   if (status == 0) {  // no entries found
   1261     if (cluster_size >= 0)
   1262       pos += cluster_size;
   1263 
   1264     if ((total >= 0) && (pos >= total)) {
   1265       m_pos = total;
   1266       return 1;  // no more clusters
   1267     }
   1268 
   1269     if ((segment_stop >= 0) && (pos >= segment_stop)) {
   1270       m_pos = segment_stop;
   1271       return 1;  // no more clusters
   1272     }
   1273 
   1274     m_pos = pos;
   1275     return 2;  // try again
   1276   }
   1277 
   1278   // status > 0 means we have an entry
   1279 
   1280   Cluster* const pCluster = Cluster::Create(this, idx, cluster_off);
   1281   if (pCluster == NULL)
   1282     return -1;
   1283 
   1284   if (!AppendCluster(pCluster)) {
   1285     delete pCluster;
   1286     return -1;
   1287   }
   1288 
   1289   if (cluster_size >= 0) {
   1290     pos += cluster_size;
   1291 
   1292     m_pos = pos;
   1293 
   1294     if (segment_stop > 0 && m_pos > segment_stop)
   1295       return E_FILE_FORMAT_INVALID;
   1296 
   1297     return 0;
   1298   }
   1299 
   1300   m_pUnknownSize = pCluster;
   1301   m_pos = -pos;
   1302 
   1303   return 0;  // partial success, since we have a new cluster
   1304 
   1305   // status == 0 means "no block entries found"
   1306   // pos designates start of payload
   1307   // m_pos has NOT been adjusted yet (in case we need to come back here)
   1308 }
   1309 
   1310 long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) {
   1311   if (m_pos >= 0 || m_pUnknownSize == NULL)
   1312     return E_PARSE_FAILED;
   1313 
   1314   const long status = m_pUnknownSize->Parse(pos, len);
   1315 
   1316   if (status < 0)  // error or underflow
   1317     return status;
   1318 
   1319   if (status == 0)  // parsed a block
   1320     return 2;  // continue parsing
   1321 
   1322   const long long start = m_pUnknownSize->m_element_start;
   1323   const long long size = m_pUnknownSize->GetElementSize();
   1324 
   1325   if (size < 0)
   1326     return E_FILE_FORMAT_INVALID;
   1327 
   1328   pos = start + size;
   1329   m_pos = pos;
   1330 
   1331   m_pUnknownSize = 0;
   1332 
   1333   return 2;  // continue parsing
   1334 }
   1335 
   1336 bool Segment::AppendCluster(Cluster* pCluster) {
   1337   if (pCluster == NULL || pCluster->m_index < 0)
   1338     return false;
   1339 
   1340   const long count = m_clusterCount + m_clusterPreloadCount;
   1341 
   1342   long& size = m_clusterSize;
   1343   const long idx = pCluster->m_index;
   1344 
   1345   if (size < count || idx != m_clusterCount)
   1346     return false;
   1347 
   1348   if (count >= size) {
   1349     const long n = (size <= 0) ? 2048 : 2 * size;
   1350 
   1351     Cluster** const qq = new (std::nothrow) Cluster*[n];
   1352     if (qq == NULL)
   1353       return false;
   1354 
   1355     Cluster** q = qq;
   1356     Cluster** p = m_clusters;
   1357     Cluster** const pp = p + count;
   1358 
   1359     while (p != pp)
   1360       *q++ = *p++;
   1361 
   1362     delete[] m_clusters;
   1363 
   1364     m_clusters = qq;
   1365     size = n;
   1366   }
   1367 
   1368   if (m_clusterPreloadCount > 0) {
   1369     Cluster** const p = m_clusters + m_clusterCount;
   1370     if (*p == NULL || (*p)->m_index >= 0)
   1371       return false;
   1372 
   1373     Cluster** q = p + m_clusterPreloadCount;
   1374     if (q >= (m_clusters + size))
   1375       return false;
   1376 
   1377     for (;;) {
   1378       Cluster** const qq = q - 1;
   1379       if ((*qq)->m_index >= 0)
   1380         return false;
   1381 
   1382       *q = *qq;
   1383       q = qq;
   1384 
   1385       if (q == p)
   1386         break;
   1387     }
   1388   }
   1389 
   1390   m_clusters[idx] = pCluster;
   1391   ++m_clusterCount;
   1392   return true;
   1393 }
   1394 
   1395 bool Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) {
   1396   if (pCluster == NULL || pCluster->m_index >= 0 || idx < m_clusterCount)
   1397     return false;
   1398 
   1399   const long count = m_clusterCount + m_clusterPreloadCount;
   1400 
   1401   long& size = m_clusterSize;
   1402   if (size < count)
   1403     return false;
   1404 
   1405   if (count >= size) {
   1406     const long n = (size <= 0) ? 2048 : 2 * size;
   1407 
   1408     Cluster** const qq = new (std::nothrow) Cluster*[n];
   1409     if (qq == NULL)
   1410       return false;
   1411     Cluster** q = qq;
   1412 
   1413     Cluster** p = m_clusters;
   1414     Cluster** const pp = p + count;
   1415 
   1416     while (p != pp)
   1417       *q++ = *p++;
   1418 
   1419     delete[] m_clusters;
   1420 
   1421     m_clusters = qq;
   1422     size = n;
   1423   }
   1424 
   1425   if (m_clusters == NULL)
   1426     return false;
   1427 
   1428   Cluster** const p = m_clusters + idx;
   1429 
   1430   Cluster** q = m_clusters + count;
   1431   if (q < p || q >= (m_clusters + size))
   1432     return false;
   1433 
   1434   while (q > p) {
   1435     Cluster** const qq = q - 1;
   1436 
   1437     if ((*qq)->m_index >= 0)
   1438       return false;
   1439 
   1440     *q = *qq;
   1441     q = qq;
   1442   }
   1443 
   1444   m_clusters[idx] = pCluster;
   1445   ++m_clusterPreloadCount;
   1446   return true;
   1447 }
   1448 
   1449 long Segment::Load() {
   1450   if (m_clusters != NULL || m_clusterSize != 0 || m_clusterCount != 0)
   1451     return E_PARSE_FAILED;
   1452 
   1453   // Outermost (level 0) segment object has been constructed,
   1454   // and pos designates start of payload.  We need to find the
   1455   // inner (level 1) elements.
   1456 
   1457   const long long header_status = ParseHeaders();
   1458 
   1459   if (header_status < 0)  // error
   1460     return static_cast<long>(header_status);
   1461 
   1462   if (header_status > 0)  // underflow
   1463     return E_BUFFER_NOT_FULL;
   1464 
   1465   if (m_pInfo == NULL || m_pTracks == NULL)
   1466     return E_FILE_FORMAT_INVALID;
   1467 
   1468   for (;;) {
   1469     const int status = LoadCluster();
   1470 
   1471     if (status < 0)  // error
   1472       return status;
   1473 
   1474     if (status >= 1)  // no more clusters
   1475       return 0;
   1476   }
   1477 }
   1478 
   1479 SeekHead::SeekHead(Segment* pSegment, long long start, long long size_,
   1480                    long long element_start, long long element_size)
   1481     : m_pSegment(pSegment),
   1482       m_start(start),
   1483       m_size(size_),
   1484       m_element_start(element_start),
   1485       m_element_size(element_size),
   1486       m_entries(0),
   1487       m_entry_count(0),
   1488       m_void_elements(0),
   1489       m_void_element_count(0) {}
   1490 
   1491 SeekHead::~SeekHead() {
   1492   delete[] m_entries;
   1493   delete[] m_void_elements;
   1494 }
   1495 
   1496 long SeekHead::Parse() {
   1497   IMkvReader* const pReader = m_pSegment->m_pReader;
   1498 
   1499   long long pos = m_start;
   1500   const long long stop = m_start + m_size;
   1501 
   1502   // first count the seek head entries
   1503 
   1504   int entry_count = 0;
   1505   int void_element_count = 0;
   1506 
   1507   while (pos < stop) {
   1508     long long id, size;
   1509 
   1510     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   1511 
   1512     if (status < 0)  // error
   1513       return status;
   1514 
   1515     if (id == mkvmuxer::kMkvSeek)
   1516       ++entry_count;
   1517     else if (id == mkvmuxer::kMkvVoid)
   1518       ++void_element_count;
   1519 
   1520     pos += size;  // consume payload
   1521 
   1522     if (pos > stop)
   1523       return E_FILE_FORMAT_INVALID;
   1524   }
   1525 
   1526   if (pos != stop)
   1527     return E_FILE_FORMAT_INVALID;
   1528 
   1529   m_entries = new (std::nothrow) Entry[entry_count];
   1530 
   1531   if (m_entries == NULL)
   1532     return -1;
   1533 
   1534   m_void_elements = new (std::nothrow) VoidElement[void_element_count];
   1535 
   1536   if (m_void_elements == NULL)
   1537     return -1;
   1538 
   1539   // now parse the entries and void elements
   1540 
   1541   Entry* pEntry = m_entries;
   1542   VoidElement* pVoidElement = m_void_elements;
   1543 
   1544   pos = m_start;
   1545 
   1546   while (pos < stop) {
   1547     const long long idpos = pos;
   1548 
   1549     long long id, size;
   1550 
   1551     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   1552 
   1553     if (status < 0)  // error
   1554       return status;
   1555 
   1556     if (id == mkvmuxer::kMkvSeek) {
   1557       if (ParseEntry(pReader, pos, size, pEntry)) {
   1558         Entry& e = *pEntry++;
   1559 
   1560         e.element_start = idpos;
   1561         e.element_size = (pos + size) - idpos;
   1562       }
   1563     } else if (id == mkvmuxer::kMkvVoid) {
   1564       VoidElement& e = *pVoidElement++;
   1565 
   1566       e.element_start = idpos;
   1567       e.element_size = (pos + size) - idpos;
   1568     }
   1569 
   1570     pos += size;  // consume payload
   1571     if (pos > stop)
   1572       return E_FILE_FORMAT_INVALID;
   1573   }
   1574 
   1575   if (pos != stop)
   1576     return E_FILE_FORMAT_INVALID;
   1577 
   1578   ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries);
   1579   assert(count_ >= 0);
   1580   assert(count_ <= entry_count);
   1581 
   1582   m_entry_count = static_cast<int>(count_);
   1583 
   1584   count_ = ptrdiff_t(pVoidElement - m_void_elements);
   1585   assert(count_ >= 0);
   1586   assert(count_ <= void_element_count);
   1587 
   1588   m_void_element_count = static_cast<int>(count_);
   1589 
   1590   return 0;
   1591 }
   1592 
   1593 int SeekHead::GetCount() const { return m_entry_count; }
   1594 
   1595 const SeekHead::Entry* SeekHead::GetEntry(int idx) const {
   1596   if (idx < 0)
   1597     return 0;
   1598 
   1599   if (idx >= m_entry_count)
   1600     return 0;
   1601 
   1602   return m_entries + idx;
   1603 }
   1604 
   1605 int SeekHead::GetVoidElementCount() const { return m_void_element_count; }
   1606 
   1607 const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const {
   1608   if (idx < 0)
   1609     return 0;
   1610 
   1611   if (idx >= m_void_element_count)
   1612     return 0;
   1613 
   1614   return m_void_elements + idx;
   1615 }
   1616 
   1617 long Segment::ParseCues(long long off, long long& pos, long& len) {
   1618   if (m_pCues)
   1619     return 0;  // success
   1620 
   1621   if (off < 0)
   1622     return -1;
   1623 
   1624   long long total, avail;
   1625 
   1626   const int status = m_pReader->Length(&total, &avail);
   1627 
   1628   if (status < 0)  // error
   1629     return status;
   1630 
   1631   assert((total < 0) || (avail <= total));
   1632 
   1633   pos = m_start + off;
   1634 
   1635   if ((total < 0) || (pos >= total))
   1636     return 1;  // don't bother parsing cues
   1637 
   1638   const long long element_start = pos;
   1639   const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
   1640 
   1641   if ((pos + 1) > avail) {
   1642     len = 1;
   1643     return E_BUFFER_NOT_FULL;
   1644   }
   1645 
   1646   long long result = GetUIntLength(m_pReader, pos, len);
   1647 
   1648   if (result < 0)  // error
   1649     return static_cast<long>(result);
   1650 
   1651   if (result > 0)  // underflow (weird)
   1652   {
   1653     len = 1;
   1654     return E_BUFFER_NOT_FULL;
   1655   }
   1656 
   1657   if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   1658     return E_FILE_FORMAT_INVALID;
   1659 
   1660   if ((pos + len) > avail)
   1661     return E_BUFFER_NOT_FULL;
   1662 
   1663   const long long idpos = pos;
   1664 
   1665   const long long id = ReadID(m_pReader, idpos, len);
   1666 
   1667   if (id != mkvmuxer::kMkvCues)
   1668     return E_FILE_FORMAT_INVALID;
   1669 
   1670   pos += len;  // consume ID
   1671   assert((segment_stop < 0) || (pos <= segment_stop));
   1672 
   1673   // Read Size
   1674 
   1675   if ((pos + 1) > avail) {
   1676     len = 1;
   1677     return E_BUFFER_NOT_FULL;
   1678   }
   1679 
   1680   result = GetUIntLength(m_pReader, pos, len);
   1681 
   1682   if (result < 0)  // error
   1683     return static_cast<long>(result);
   1684 
   1685   if (result > 0)  // underflow (weird)
   1686   {
   1687     len = 1;
   1688     return E_BUFFER_NOT_FULL;
   1689   }
   1690 
   1691   if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   1692     return E_FILE_FORMAT_INVALID;
   1693 
   1694   if ((pos + len) > avail)
   1695     return E_BUFFER_NOT_FULL;
   1696 
   1697   const long long size = ReadUInt(m_pReader, pos, len);
   1698 
   1699   if (size < 0)  // error
   1700     return static_cast<long>(size);
   1701 
   1702   if (size == 0)  // weird, although technically not illegal
   1703     return 1;  // done
   1704 
   1705   pos += len;  // consume length of size of element
   1706   assert((segment_stop < 0) || (pos <= segment_stop));
   1707 
   1708   // Pos now points to start of payload
   1709 
   1710   const long long element_stop = pos + size;
   1711 
   1712   if ((segment_stop >= 0) && (element_stop > segment_stop))
   1713     return E_FILE_FORMAT_INVALID;
   1714 
   1715   if ((total >= 0) && (element_stop > total))
   1716     return 1;  // don't bother parsing anymore
   1717 
   1718   len = static_cast<long>(size);
   1719 
   1720   if (element_stop > avail)
   1721     return E_BUFFER_NOT_FULL;
   1722 
   1723   const long long element_size = element_stop - element_start;
   1724 
   1725   m_pCues =
   1726       new (std::nothrow) Cues(this, pos, size, element_start, element_size);
   1727   if (m_pCues == NULL)
   1728     return -1;
   1729 
   1730   return 0;  // success
   1731 }
   1732 
   1733 bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
   1734                           Entry* pEntry) {
   1735   if (size_ <= 0)
   1736     return false;
   1737 
   1738   long long pos = start;
   1739   const long long stop = start + size_;
   1740 
   1741   long len;
   1742 
   1743   // parse the container for the level-1 element ID
   1744 
   1745   const long long seekIdId = ReadID(pReader, pos, len);
   1746   if (seekIdId < 0)
   1747     return false;
   1748 
   1749   if (seekIdId != mkvmuxer::kMkvSeekID)
   1750     return false;
   1751 
   1752   if ((pos + len) > stop)
   1753     return false;
   1754 
   1755   pos += len;  // consume SeekID id
   1756 
   1757   const long long seekIdSize = ReadUInt(pReader, pos, len);
   1758 
   1759   if (seekIdSize <= 0)
   1760     return false;
   1761 
   1762   if ((pos + len) > stop)
   1763     return false;
   1764 
   1765   pos += len;  // consume size of field
   1766 
   1767   if ((pos + seekIdSize) > stop)
   1768     return false;
   1769 
   1770   // Note that the SeekId payload really is serialized
   1771   // as a "Matroska integer", not as a plain binary value.
   1772   // In fact, Matroska requires that ID values in the
   1773   // stream exactly match the binary representation as listed
   1774   // in the Matroska specification.
   1775   //
   1776   // This parser is more liberal, and permits IDs to have
   1777   // any width.  (This could make the representation in the stream
   1778   // different from what's in the spec, but it doesn't matter here,
   1779   // since we always normalize "Matroska integer" values.)
   1780 
   1781   pEntry->id = ReadUInt(pReader, pos, len);  // payload
   1782 
   1783   if (pEntry->id <= 0)
   1784     return false;
   1785 
   1786   if (len != seekIdSize)
   1787     return false;
   1788 
   1789   pos += seekIdSize;  // consume SeekID payload
   1790 
   1791   const long long seekPosId = ReadID(pReader, pos, len);
   1792 
   1793   if (seekPosId != mkvmuxer::kMkvSeekPosition)
   1794     return false;
   1795 
   1796   if ((pos + len) > stop)
   1797     return false;
   1798 
   1799   pos += len;  // consume id
   1800 
   1801   const long long seekPosSize = ReadUInt(pReader, pos, len);
   1802 
   1803   if (seekPosSize <= 0)
   1804     return false;
   1805 
   1806   if ((pos + len) > stop)
   1807     return false;
   1808 
   1809   pos += len;  // consume size
   1810 
   1811   if ((pos + seekPosSize) > stop)
   1812     return false;
   1813 
   1814   pEntry->pos = UnserializeUInt(pReader, pos, seekPosSize);
   1815 
   1816   if (pEntry->pos < 0)
   1817     return false;
   1818 
   1819   pos += seekPosSize;  // consume payload
   1820 
   1821   if (pos != stop)
   1822     return false;
   1823 
   1824   return true;
   1825 }
   1826 
   1827 Cues::Cues(Segment* pSegment, long long start_, long long size_,
   1828            long long element_start, long long element_size)
   1829     : m_pSegment(pSegment),
   1830       m_start(start_),
   1831       m_size(size_),
   1832       m_element_start(element_start),
   1833       m_element_size(element_size),
   1834       m_cue_points(NULL),
   1835       m_count(0),
   1836       m_preload_count(0),
   1837       m_pos(start_) {}
   1838 
   1839 Cues::~Cues() {
   1840   const long n = m_count + m_preload_count;
   1841 
   1842   CuePoint** p = m_cue_points;
   1843   CuePoint** const q = p + n;
   1844 
   1845   while (p != q) {
   1846     CuePoint* const pCP = *p++;
   1847     assert(pCP);
   1848 
   1849     delete pCP;
   1850   }
   1851 
   1852   delete[] m_cue_points;
   1853 }
   1854 
   1855 long Cues::GetCount() const {
   1856   if (m_cue_points == NULL)
   1857     return -1;
   1858 
   1859   return m_count;  // TODO: really ignore preload count?
   1860 }
   1861 
   1862 bool Cues::DoneParsing() const {
   1863   const long long stop = m_start + m_size;
   1864   return (m_pos >= stop);
   1865 }
   1866 
   1867 bool Cues::Init() const {
   1868   if (m_cue_points)
   1869     return true;
   1870 
   1871   if (m_count != 0 || m_preload_count != 0)
   1872     return false;
   1873 
   1874   IMkvReader* const pReader = m_pSegment->m_pReader;
   1875 
   1876   const long long stop = m_start + m_size;
   1877   long long pos = m_start;
   1878 
   1879   long cue_points_size = 0;
   1880 
   1881   while (pos < stop) {
   1882     const long long idpos = pos;
   1883 
   1884     long len;
   1885 
   1886     const long long id = ReadID(pReader, pos, len);
   1887     if (id < 0 || (pos + len) > stop) {
   1888       return false;
   1889     }
   1890 
   1891     pos += len;  // consume ID
   1892 
   1893     const long long size = ReadUInt(pReader, pos, len);
   1894     if (size < 0 || (pos + len > stop)) {
   1895       return false;
   1896     }
   1897 
   1898     pos += len;  // consume Size field
   1899     if (pos + size > stop) {
   1900       return false;
   1901     }
   1902 
   1903     if (id == mkvmuxer::kMkvCuePoint) {
   1904       if (!PreloadCuePoint(cue_points_size, idpos))
   1905         return false;
   1906     }
   1907 
   1908     pos += size;  // skip payload
   1909   }
   1910   return true;
   1911 }
   1912 
   1913 bool Cues::PreloadCuePoint(long& cue_points_size, long long pos) const {
   1914   if (m_count != 0)
   1915     return false;
   1916 
   1917   if (m_preload_count >= cue_points_size) {
   1918     const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size;
   1919 
   1920     CuePoint** const qq = new (std::nothrow) CuePoint*[n];
   1921     if (qq == NULL)
   1922       return false;
   1923 
   1924     CuePoint** q = qq;  // beginning of target
   1925 
   1926     CuePoint** p = m_cue_points;  // beginning of source
   1927     CuePoint** const pp = p + m_preload_count;  // end of source
   1928 
   1929     while (p != pp)
   1930       *q++ = *p++;
   1931 
   1932     delete[] m_cue_points;
   1933 
   1934     m_cue_points = qq;
   1935     cue_points_size = n;
   1936   }
   1937 
   1938   CuePoint* const pCP = new (std::nothrow) CuePoint(m_preload_count, pos);
   1939   if (pCP == NULL)
   1940     return false;
   1941 
   1942   m_cue_points[m_preload_count++] = pCP;
   1943   return true;
   1944 }
   1945 
   1946 bool Cues::LoadCuePoint() const {
   1947   const long long stop = m_start + m_size;
   1948 
   1949   if (m_pos >= stop)
   1950     return false;  // nothing else to do
   1951 
   1952   if (!Init()) {
   1953     m_pos = stop;
   1954     return false;
   1955   }
   1956 
   1957   IMkvReader* const pReader = m_pSegment->m_pReader;
   1958 
   1959   while (m_pos < stop) {
   1960     const long long idpos = m_pos;
   1961 
   1962     long len;
   1963 
   1964     const long long id = ReadID(pReader, m_pos, len);
   1965     if (id < 0 || (m_pos + len) > stop)
   1966       return false;
   1967 
   1968     m_pos += len;  // consume ID
   1969 
   1970     const long long size = ReadUInt(pReader, m_pos, len);
   1971     if (size < 0 || (m_pos + len) > stop)
   1972       return false;
   1973 
   1974     m_pos += len;  // consume Size field
   1975     if ((m_pos + size) > stop)
   1976       return false;
   1977 
   1978     if (id != mkvmuxer::kMkvCuePoint) {
   1979       m_pos += size;  // consume payload
   1980       if (m_pos > stop)
   1981         return false;
   1982 
   1983       continue;
   1984     }
   1985 
   1986     if (m_preload_count < 1)
   1987       return false;
   1988 
   1989     CuePoint* const pCP = m_cue_points[m_count];
   1990     if (!pCP || (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos)))
   1991       return false;
   1992 
   1993     if (!pCP->Load(pReader)) {
   1994       m_pos = stop;
   1995       return false;
   1996     }
   1997     ++m_count;
   1998     --m_preload_count;
   1999 
   2000     m_pos += size;  // consume payload
   2001     if (m_pos > stop)
   2002       return false;
   2003 
   2004     return true;  // yes, we loaded a cue point
   2005   }
   2006 
   2007   return false;  // no, we did not load a cue point
   2008 }
   2009 
   2010 bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
   2011                 const CuePoint::TrackPosition*& pTP) const {
   2012   if (time_ns < 0 || pTrack == NULL || m_cue_points == NULL || m_count == 0)
   2013     return false;
   2014 
   2015   CuePoint** const ii = m_cue_points;
   2016   CuePoint** i = ii;
   2017 
   2018   CuePoint** const jj = ii + m_count;
   2019   CuePoint** j = jj;
   2020 
   2021   pCP = *i;
   2022   if (pCP == NULL)
   2023     return false;
   2024 
   2025   if (time_ns <= pCP->GetTime(m_pSegment)) {
   2026     pTP = pCP->Find(pTrack);
   2027     return (pTP != NULL);
   2028   }
   2029 
   2030   while (i < j) {
   2031     // INVARIANT:
   2032     //[ii, i) <= time_ns
   2033     //[i, j)  ?
   2034     //[j, jj) > time_ns
   2035 
   2036     CuePoint** const k = i + (j - i) / 2;
   2037     if (k >= jj)
   2038       return false;
   2039 
   2040     CuePoint* const pCP = *k;
   2041     if (pCP == NULL)
   2042       return false;
   2043 
   2044     const long long t = pCP->GetTime(m_pSegment);
   2045 
   2046     if (t <= time_ns)
   2047       i = k + 1;
   2048     else
   2049       j = k;
   2050 
   2051     if (i > j)
   2052       return false;
   2053   }
   2054 
   2055   if (i != j || i > jj || i <= ii)
   2056     return false;
   2057 
   2058   pCP = *--i;
   2059 
   2060   if (pCP == NULL || pCP->GetTime(m_pSegment) > time_ns)
   2061     return false;
   2062 
   2063   // TODO: here and elsewhere, it's probably not correct to search
   2064   // for the cue point with this time, and then search for a matching
   2065   // track.  In principle, the matching track could be on some earlier
   2066   // cue point, and with our current algorithm, we'd miss it.  To make
   2067   // this bullet-proof, we'd need to create a secondary structure,
   2068   // with a list of cue points that apply to a track, and then search
   2069   // that track-based structure for a matching cue point.
   2070 
   2071   pTP = pCP->Find(pTrack);
   2072   return (pTP != NULL);
   2073 }
   2074 
   2075 const CuePoint* Cues::GetFirst() const {
   2076   if (m_cue_points == NULL || m_count == 0)
   2077     return NULL;
   2078 
   2079   CuePoint* const* const pp = m_cue_points;
   2080   if (pp == NULL)
   2081     return NULL;
   2082 
   2083   CuePoint* const pCP = pp[0];
   2084   if (pCP == NULL || pCP->GetTimeCode() < 0)
   2085     return NULL;
   2086 
   2087   return pCP;
   2088 }
   2089 
   2090 const CuePoint* Cues::GetLast() const {
   2091   if (m_cue_points == NULL || m_count <= 0)
   2092     return NULL;
   2093 
   2094   const long index = m_count - 1;
   2095 
   2096   CuePoint* const* const pp = m_cue_points;
   2097   if (pp == NULL)
   2098     return NULL;
   2099 
   2100   CuePoint* const pCP = pp[index];
   2101   if (pCP == NULL || pCP->GetTimeCode() < 0)
   2102     return NULL;
   2103 
   2104   return pCP;
   2105 }
   2106 
   2107 const CuePoint* Cues::GetNext(const CuePoint* pCurr) const {
   2108   if (pCurr == NULL || pCurr->GetTimeCode() < 0 ||
   2109       m_cue_points == NULL || m_count < 1) {
   2110     return NULL;
   2111   }
   2112 
   2113   long index = pCurr->m_index;
   2114   if (index >= m_count)
   2115     return NULL;
   2116 
   2117   CuePoint* const* const pp = m_cue_points;
   2118   if (pp == NULL || pp[index] != pCurr)
   2119     return NULL;
   2120 
   2121   ++index;
   2122 
   2123   if (index >= m_count)
   2124     return NULL;
   2125 
   2126   CuePoint* const pNext = pp[index];
   2127 
   2128   if (pNext == NULL || pNext->GetTimeCode() < 0)
   2129     return NULL;
   2130 
   2131   return pNext;
   2132 }
   2133 
   2134 const BlockEntry* Cues::GetBlock(const CuePoint* pCP,
   2135                                  const CuePoint::TrackPosition* pTP) const {
   2136   if (pCP == NULL || pTP == NULL)
   2137     return NULL;
   2138 
   2139   return m_pSegment->GetBlock(*pCP, *pTP);
   2140 }
   2141 
   2142 const BlockEntry* Segment::GetBlock(const CuePoint& cp,
   2143                                     const CuePoint::TrackPosition& tp) {
   2144   Cluster** const ii = m_clusters;
   2145   Cluster** i = ii;
   2146 
   2147   const long count = m_clusterCount + m_clusterPreloadCount;
   2148 
   2149   Cluster** const jj = ii + count;
   2150   Cluster** j = jj;
   2151 
   2152   while (i < j) {
   2153     // INVARIANT:
   2154     //[ii, i) < pTP->m_pos
   2155     //[i, j) ?
   2156     //[j, jj)  > pTP->m_pos
   2157 
   2158     Cluster** const k = i + (j - i) / 2;
   2159     assert(k < jj);
   2160 
   2161     Cluster* const pCluster = *k;
   2162     assert(pCluster);
   2163 
   2164     // const long long pos_ = pCluster->m_pos;
   2165     // assert(pos_);
   2166     // const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
   2167 
   2168     const long long pos = pCluster->GetPosition();
   2169     assert(pos >= 0);
   2170 
   2171     if (pos < tp.m_pos)
   2172       i = k + 1;
   2173     else if (pos > tp.m_pos)
   2174       j = k;
   2175     else
   2176       return pCluster->GetEntry(cp, tp);
   2177   }
   2178 
   2179   assert(i == j);
   2180   // assert(Cluster::HasBlockEntries(this, tp.m_pos));
   2181 
   2182   Cluster* const pCluster = Cluster::Create(this, -1, tp.m_pos);  //, -1);
   2183   if (pCluster == NULL)
   2184     return NULL;
   2185 
   2186   const ptrdiff_t idx = i - m_clusters;
   2187 
   2188   if (!PreloadCluster(pCluster, idx)) {
   2189     delete pCluster;
   2190     return NULL;
   2191   }
   2192   assert(m_clusters);
   2193   assert(m_clusterPreloadCount > 0);
   2194   assert(m_clusters[idx] == pCluster);
   2195 
   2196   return pCluster->GetEntry(cp, tp);
   2197 }
   2198 
   2199 const Cluster* Segment::FindOrPreloadCluster(long long requested_pos) {
   2200   if (requested_pos < 0)
   2201     return 0;
   2202 
   2203   Cluster** const ii = m_clusters;
   2204   Cluster** i = ii;
   2205 
   2206   const long count = m_clusterCount + m_clusterPreloadCount;
   2207 
   2208   Cluster** const jj = ii + count;
   2209   Cluster** j = jj;
   2210 
   2211   while (i < j) {
   2212     // INVARIANT:
   2213     //[ii, i) < pTP->m_pos
   2214     //[i, j) ?
   2215     //[j, jj)  > pTP->m_pos
   2216 
   2217     Cluster** const k = i + (j - i) / 2;
   2218     assert(k < jj);
   2219 
   2220     Cluster* const pCluster = *k;
   2221     assert(pCluster);
   2222 
   2223     // const long long pos_ = pCluster->m_pos;
   2224     // assert(pos_);
   2225     // const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
   2226 
   2227     const long long pos = pCluster->GetPosition();
   2228     assert(pos >= 0);
   2229 
   2230     if (pos < requested_pos)
   2231       i = k + 1;
   2232     else if (pos > requested_pos)
   2233       j = k;
   2234     else
   2235       return pCluster;
   2236   }
   2237 
   2238   assert(i == j);
   2239   // assert(Cluster::HasBlockEntries(this, tp.m_pos));
   2240 
   2241   Cluster* const pCluster = Cluster::Create(this, -1, requested_pos);
   2242   if (pCluster == NULL)
   2243     return NULL;
   2244 
   2245   const ptrdiff_t idx = i - m_clusters;
   2246 
   2247   if (!PreloadCluster(pCluster, idx)) {
   2248     delete pCluster;
   2249     return NULL;
   2250   }
   2251   assert(m_clusters);
   2252   assert(m_clusterPreloadCount > 0);
   2253   assert(m_clusters[idx] == pCluster);
   2254 
   2255   return pCluster;
   2256 }
   2257 
   2258 CuePoint::CuePoint(long idx, long long pos)
   2259     : m_element_start(0),
   2260       m_element_size(0),
   2261       m_index(idx),
   2262       m_timecode(-1 * pos),
   2263       m_track_positions(NULL),
   2264       m_track_positions_count(0) {
   2265   assert(pos > 0);
   2266 }
   2267 
   2268 CuePoint::~CuePoint() { delete[] m_track_positions; }
   2269 
   2270 bool CuePoint::Load(IMkvReader* pReader) {
   2271   // odbgstream os;
   2272   // os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;
   2273 
   2274   if (m_timecode >= 0)  // already loaded
   2275     return true;
   2276 
   2277   assert(m_track_positions == NULL);
   2278   assert(m_track_positions_count == 0);
   2279 
   2280   long long pos_ = -m_timecode;
   2281   const long long element_start = pos_;
   2282 
   2283   long long stop;
   2284 
   2285   {
   2286     long len;
   2287 
   2288     const long long id = ReadID(pReader, pos_, len);
   2289     if (id != mkvmuxer::kMkvCuePoint)
   2290       return false;
   2291 
   2292     pos_ += len;  // consume ID
   2293 
   2294     const long long size = ReadUInt(pReader, pos_, len);
   2295     assert(size >= 0);
   2296 
   2297     pos_ += len;  // consume Size field
   2298     // pos_ now points to start of payload
   2299 
   2300     stop = pos_ + size;
   2301   }
   2302 
   2303   const long long element_size = stop - element_start;
   2304 
   2305   long long pos = pos_;
   2306 
   2307   // First count number of track positions
   2308 
   2309   while (pos < stop) {
   2310     long len;
   2311 
   2312     const long long id = ReadID(pReader, pos, len);
   2313     if ((id < 0) || (pos + len > stop)) {
   2314       return false;
   2315     }
   2316 
   2317     pos += len;  // consume ID
   2318 
   2319     const long long size = ReadUInt(pReader, pos, len);
   2320     if ((size < 0) || (pos + len > stop)) {
   2321       return false;
   2322     }
   2323 
   2324     pos += len;  // consume Size field
   2325     if ((pos + size) > stop) {
   2326       return false;
   2327     }
   2328 
   2329     if (id == mkvmuxer::kMkvCueTime)
   2330       m_timecode = UnserializeUInt(pReader, pos, size);
   2331 
   2332     else if (id == mkvmuxer::kMkvCueTrackPositions)
   2333       ++m_track_positions_count;
   2334 
   2335     pos += size;  // consume payload
   2336   }
   2337 
   2338   if (m_timecode < 0 || m_track_positions_count <= 0) {
   2339     return false;
   2340   }
   2341 
   2342   // os << "CuePoint::Load(cont'd): idpos=" << idpos
   2343   //   << " timecode=" << m_timecode
   2344   //   << endl;
   2345 
   2346   m_track_positions = new (std::nothrow) TrackPosition[m_track_positions_count];
   2347   if (m_track_positions == NULL)
   2348     return false;
   2349 
   2350   // Now parse track positions
   2351 
   2352   TrackPosition* p = m_track_positions;
   2353   pos = pos_;
   2354 
   2355   while (pos < stop) {
   2356     long len;
   2357 
   2358     const long long id = ReadID(pReader, pos, len);
   2359     if (id < 0 || (pos + len) > stop)
   2360       return false;
   2361 
   2362     pos += len;  // consume ID
   2363 
   2364     const long long size = ReadUInt(pReader, pos, len);
   2365     assert(size >= 0);
   2366     assert((pos + len) <= stop);
   2367 
   2368     pos += len;  // consume Size field
   2369     assert((pos + size) <= stop);
   2370 
   2371     if (id == mkvmuxer::kMkvCueTrackPositions) {
   2372       TrackPosition& tp = *p++;
   2373       if (!tp.Parse(pReader, pos, size)) {
   2374         return false;
   2375       }
   2376     }
   2377 
   2378     pos += size;  // consume payload
   2379     if (pos > stop)
   2380       return false;
   2381   }
   2382 
   2383   assert(size_t(p - m_track_positions) == m_track_positions_count);
   2384 
   2385   m_element_start = element_start;
   2386   m_element_size = element_size;
   2387 
   2388   return true;
   2389 }
   2390 
   2391 bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
   2392                                     long long size_) {
   2393   const long long stop = start_ + size_;
   2394   long long pos = start_;
   2395 
   2396   m_track = -1;
   2397   m_pos = -1;
   2398   m_block = 1;  // default
   2399 
   2400   while (pos < stop) {
   2401     long len;
   2402 
   2403     const long long id = ReadID(pReader, pos, len);
   2404     if ((id < 0) || ((pos + len) > stop)) {
   2405       return false;
   2406     }
   2407 
   2408     pos += len;  // consume ID
   2409 
   2410     const long long size = ReadUInt(pReader, pos, len);
   2411     if ((size < 0) || ((pos + len) > stop)) {
   2412       return false;
   2413     }
   2414 
   2415     pos += len;  // consume Size field
   2416     if ((pos + size) > stop) {
   2417       return false;
   2418     }
   2419 
   2420     if (id == mkvmuxer::kMkvCueTrack)
   2421       m_track = UnserializeUInt(pReader, pos, size);
   2422     else if (id == mkvmuxer::kMkvCueClusterPosition)
   2423       m_pos = UnserializeUInt(pReader, pos, size);
   2424     else if (id == mkvmuxer::kMkvCueBlockNumber)
   2425       m_block = UnserializeUInt(pReader, pos, size);
   2426 
   2427     pos += size;  // consume payload
   2428   }
   2429 
   2430   if ((m_pos < 0) || (m_track <= 0)) {
   2431     return false;
   2432   }
   2433 
   2434   return true;
   2435 }
   2436 
   2437 const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const {
   2438   assert(pTrack);
   2439 
   2440   const long long n = pTrack->GetNumber();
   2441 
   2442   const TrackPosition* i = m_track_positions;
   2443   const TrackPosition* const j = i + m_track_positions_count;
   2444 
   2445   while (i != j) {
   2446     const TrackPosition& p = *i++;
   2447 
   2448     if (p.m_track == n)
   2449       return &p;
   2450   }
   2451 
   2452   return NULL;  // no matching track number found
   2453 }
   2454 
   2455 long long CuePoint::GetTimeCode() const { return m_timecode; }
   2456 
   2457 long long CuePoint::GetTime(const Segment* pSegment) const {
   2458   assert(pSegment);
   2459   assert(m_timecode >= 0);
   2460 
   2461   const SegmentInfo* const pInfo = pSegment->GetInfo();
   2462   assert(pInfo);
   2463 
   2464   const long long scale = pInfo->GetTimeCodeScale();
   2465   assert(scale >= 1);
   2466 
   2467   const long long time = scale * m_timecode;
   2468 
   2469   return time;
   2470 }
   2471 
   2472 bool Segment::DoneParsing() const {
   2473   if (m_size < 0) {
   2474     long long total, avail;
   2475 
   2476     const int status = m_pReader->Length(&total, &avail);
   2477 
   2478     if (status < 0)  // error
   2479       return true;  // must assume done
   2480 
   2481     if (total < 0)
   2482       return false;  // assume live stream
   2483 
   2484     return (m_pos >= total);
   2485   }
   2486 
   2487   const long long stop = m_start + m_size;
   2488 
   2489   return (m_pos >= stop);
   2490 }
   2491 
   2492 const Cluster* Segment::GetFirst() const {
   2493   if ((m_clusters == NULL) || (m_clusterCount <= 0))
   2494     return &m_eos;
   2495 
   2496   Cluster* const pCluster = m_clusters[0];
   2497   assert(pCluster);
   2498 
   2499   return pCluster;
   2500 }
   2501 
   2502 const Cluster* Segment::GetLast() const {
   2503   if ((m_clusters == NULL) || (m_clusterCount <= 0))
   2504     return &m_eos;
   2505 
   2506   const long idx = m_clusterCount - 1;
   2507 
   2508   Cluster* const pCluster = m_clusters[idx];
   2509   assert(pCluster);
   2510 
   2511   return pCluster;
   2512 }
   2513 
   2514 unsigned long Segment::GetCount() const { return m_clusterCount; }
   2515 
   2516 const Cluster* Segment::GetNext(const Cluster* pCurr) {
   2517   assert(pCurr);
   2518   assert(pCurr != &m_eos);
   2519   assert(m_clusters);
   2520 
   2521   long idx = pCurr->m_index;
   2522 
   2523   if (idx >= 0) {
   2524     assert(m_clusterCount > 0);
   2525     assert(idx < m_clusterCount);
   2526     assert(pCurr == m_clusters[idx]);
   2527 
   2528     ++idx;
   2529 
   2530     if (idx >= m_clusterCount)
   2531       return &m_eos;  // caller will LoadCluster as desired
   2532 
   2533     Cluster* const pNext = m_clusters[idx];
   2534     assert(pNext);
   2535     assert(pNext->m_index >= 0);
   2536     assert(pNext->m_index == idx);
   2537 
   2538     return pNext;
   2539   }
   2540 
   2541   assert(m_clusterPreloadCount > 0);
   2542 
   2543   long long pos = pCurr->m_element_start;
   2544 
   2545   assert(m_size >= 0);  // TODO
   2546   const long long stop = m_start + m_size;  // end of segment
   2547 
   2548   {
   2549     long len;
   2550 
   2551     long long result = GetUIntLength(m_pReader, pos, len);
   2552     assert(result == 0);
   2553     assert((pos + len) <= stop);  // TODO
   2554     if (result != 0)
   2555       return NULL;
   2556 
   2557     const long long id = ReadID(m_pReader, pos, len);
   2558     if (id != mkvmuxer::kMkvCluster)
   2559       return NULL;
   2560 
   2561     pos += len;  // consume ID
   2562 
   2563     // Read Size
   2564     result = GetUIntLength(m_pReader, pos, len);
   2565     assert(result == 0);  // TODO
   2566     assert((pos + len) <= stop);  // TODO
   2567 
   2568     const long long size = ReadUInt(m_pReader, pos, len);
   2569     assert(size > 0);  // TODO
   2570     // assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
   2571 
   2572     pos += len;  // consume length of size of element
   2573     assert((pos + size) <= stop);  // TODO
   2574 
   2575     // Pos now points to start of payload
   2576 
   2577     pos += size;  // consume payload
   2578   }
   2579 
   2580   long long off_next = 0;
   2581 
   2582   while (pos < stop) {
   2583     long len;
   2584 
   2585     long long result = GetUIntLength(m_pReader, pos, len);
   2586     assert(result == 0);
   2587     assert((pos + len) <= stop);  // TODO
   2588     if (result != 0)
   2589       return NULL;
   2590 
   2591     const long long idpos = pos;  // pos of next (potential) cluster
   2592 
   2593     const long long id = ReadID(m_pReader, idpos, len);
   2594     if (id < 0)
   2595       return NULL;
   2596 
   2597     pos += len;  // consume ID
   2598 
   2599     // Read Size
   2600     result = GetUIntLength(m_pReader, pos, len);
   2601     assert(result == 0);  // TODO
   2602     assert((pos + len) <= stop);  // TODO
   2603 
   2604     const long long size = ReadUInt(m_pReader, pos, len);
   2605     assert(size >= 0);  // TODO
   2606 
   2607     pos += len;  // consume length of size of element
   2608     assert((pos + size) <= stop);  // TODO
   2609 
   2610     // Pos now points to start of payload
   2611 
   2612     if (size == 0)  // weird
   2613       continue;
   2614 
   2615     if (id == mkvmuxer::kMkvCluster) {
   2616       const long long off_next_ = idpos - m_start;
   2617 
   2618       long long pos_;
   2619       long len_;
   2620 
   2621       const long status = Cluster::HasBlockEntries(this, off_next_, pos_, len_);
   2622 
   2623       assert(status >= 0);
   2624 
   2625       if (status > 0) {
   2626         off_next = off_next_;
   2627         break;
   2628       }
   2629     }
   2630 
   2631     pos += size;  // consume payload
   2632   }
   2633 
   2634   if (off_next <= 0)
   2635     return 0;
   2636 
   2637   Cluster** const ii = m_clusters + m_clusterCount;
   2638   Cluster** i = ii;
   2639 
   2640   Cluster** const jj = ii + m_clusterPreloadCount;
   2641   Cluster** j = jj;
   2642 
   2643   while (i < j) {
   2644     // INVARIANT:
   2645     //[0, i) < pos_next
   2646     //[i, j) ?
   2647     //[j, jj)  > pos_next
   2648 
   2649     Cluster** const k = i + (j - i) / 2;
   2650     assert(k < jj);
   2651 
   2652     Cluster* const pNext = *k;
   2653     assert(pNext);
   2654     assert(pNext->m_index < 0);
   2655 
   2656     // const long long pos_ = pNext->m_pos;
   2657     // assert(pos_);
   2658     // pos = pos_ * ((pos_ < 0) ? -1 : 1);
   2659 
   2660     pos = pNext->GetPosition();
   2661 
   2662     if (pos < off_next)
   2663       i = k + 1;
   2664     else if (pos > off_next)
   2665       j = k;
   2666     else
   2667       return pNext;
   2668   }
   2669 
   2670   assert(i == j);
   2671 
   2672   Cluster* const pNext = Cluster::Create(this, -1, off_next);
   2673   if (pNext == NULL)
   2674     return NULL;
   2675 
   2676   const ptrdiff_t idx_next = i - m_clusters;  // insertion position
   2677 
   2678   if (!PreloadCluster(pNext, idx_next)) {
   2679     delete pNext;
   2680     return NULL;
   2681   }
   2682   assert(m_clusters);
   2683   assert(idx_next < m_clusterSize);
   2684   assert(m_clusters[idx_next] == pNext);
   2685 
   2686   return pNext;
   2687 }
   2688 
   2689 long Segment::ParseNext(const Cluster* pCurr, const Cluster*& pResult,
   2690                         long long& pos, long& len) {
   2691   assert(pCurr);
   2692   assert(!pCurr->EOS());
   2693   assert(m_clusters);
   2694 
   2695   pResult = 0;
   2696 
   2697   if (pCurr->m_index >= 0) {  // loaded (not merely preloaded)
   2698     assert(m_clusters[pCurr->m_index] == pCurr);
   2699 
   2700     const long next_idx = pCurr->m_index + 1;
   2701 
   2702     if (next_idx < m_clusterCount) {
   2703       pResult = m_clusters[next_idx];
   2704       return 0;  // success
   2705     }
   2706 
   2707     // curr cluster is last among loaded
   2708 
   2709     const long result = LoadCluster(pos, len);
   2710 
   2711     if (result < 0)  // error or underflow
   2712       return result;
   2713 
   2714     if (result > 0)  // no more clusters
   2715     {
   2716       // pResult = &m_eos;
   2717       return 1;
   2718     }
   2719 
   2720     pResult = GetLast();
   2721     return 0;  // success
   2722   }
   2723 
   2724   assert(m_pos > 0);
   2725 
   2726   long long total, avail;
   2727 
   2728   long status = m_pReader->Length(&total, &avail);
   2729 
   2730   if (status < 0)  // error
   2731     return status;
   2732 
   2733   assert((total < 0) || (avail <= total));
   2734 
   2735   const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
   2736 
   2737   // interrogate curr cluster
   2738 
   2739   pos = pCurr->m_element_start;
   2740 
   2741   if (pCurr->m_element_size >= 0)
   2742     pos += pCurr->m_element_size;
   2743   else {
   2744     if ((pos + 1) > avail) {
   2745       len = 1;
   2746       return E_BUFFER_NOT_FULL;
   2747     }
   2748 
   2749     long long result = GetUIntLength(m_pReader, pos, len);
   2750 
   2751     if (result < 0)  // error
   2752       return static_cast<long>(result);
   2753 
   2754     if (result > 0)  // weird
   2755       return E_BUFFER_NOT_FULL;
   2756 
   2757     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   2758       return E_FILE_FORMAT_INVALID;
   2759 
   2760     if ((pos + len) > avail)
   2761       return E_BUFFER_NOT_FULL;
   2762 
   2763     const long long id = ReadUInt(m_pReader, pos, len);
   2764 
   2765     if (id != mkvmuxer::kMkvCluster)
   2766       return -1;
   2767 
   2768     pos += len;  // consume ID
   2769 
   2770     // Read Size
   2771 
   2772     if ((pos + 1) > avail) {
   2773       len = 1;
   2774       return E_BUFFER_NOT_FULL;
   2775     }
   2776 
   2777     result = GetUIntLength(m_pReader, pos, len);
   2778 
   2779     if (result < 0)  // error
   2780       return static_cast<long>(result);
   2781 
   2782     if (result > 0)  // weird
   2783       return E_BUFFER_NOT_FULL;
   2784 
   2785     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   2786       return E_FILE_FORMAT_INVALID;
   2787 
   2788     if ((pos + len) > avail)
   2789       return E_BUFFER_NOT_FULL;
   2790 
   2791     const long long size = ReadUInt(m_pReader, pos, len);
   2792 
   2793     if (size < 0)  // error
   2794       return static_cast<long>(size);
   2795 
   2796     pos += len;  // consume size field
   2797 
   2798     const long long unknown_size = (1LL << (7 * len)) - 1;
   2799 
   2800     if (size == unknown_size)  // TODO: should never happen
   2801       return E_FILE_FORMAT_INVALID;  // TODO: resolve this
   2802 
   2803     // assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
   2804 
   2805     if ((segment_stop >= 0) && ((pos + size) > segment_stop))
   2806       return E_FILE_FORMAT_INVALID;
   2807 
   2808     // Pos now points to start of payload
   2809 
   2810     pos += size;  // consume payload (that is, the current cluster)
   2811     if (segment_stop >= 0 && pos > segment_stop)
   2812       return E_FILE_FORMAT_INVALID;
   2813 
   2814     // By consuming the payload, we are assuming that the curr
   2815     // cluster isn't interesting.  That is, we don't bother checking
   2816     // whether the payload of the curr cluster is less than what
   2817     // happens to be available (obtained via IMkvReader::Length).
   2818     // Presumably the caller has already dispensed with the current
   2819     // cluster, and really does want the next cluster.
   2820   }
   2821 
   2822   // pos now points to just beyond the last fully-loaded cluster
   2823 
   2824   for (;;) {
   2825     const long status = DoParseNext(pResult, pos, len);
   2826 
   2827     if (status <= 1)
   2828       return status;
   2829   }
   2830 }
   2831 
   2832 long Segment::DoParseNext(const Cluster*& pResult, long long& pos, long& len) {
   2833   long long total, avail;
   2834 
   2835   long status = m_pReader->Length(&total, &avail);
   2836 
   2837   if (status < 0)  // error
   2838     return status;
   2839 
   2840   assert((total < 0) || (avail <= total));
   2841 
   2842   const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
   2843 
   2844   // Parse next cluster.  This is strictly a parsing activity.
   2845   // Creation of a new cluster object happens later, after the
   2846   // parsing is done.
   2847 
   2848   long long off_next = 0;
   2849   long long cluster_size = -1;
   2850 
   2851   for (;;) {
   2852     if ((total >= 0) && (pos >= total))
   2853       return 1;  // EOF
   2854 
   2855     if ((segment_stop >= 0) && (pos >= segment_stop))
   2856       return 1;  // EOF
   2857 
   2858     if ((pos + 1) > avail) {
   2859       len = 1;
   2860       return E_BUFFER_NOT_FULL;
   2861     }
   2862 
   2863     long long result = GetUIntLength(m_pReader, pos, len);
   2864 
   2865     if (result < 0)  // error
   2866       return static_cast<long>(result);
   2867 
   2868     if (result > 0)  // weird
   2869       return E_BUFFER_NOT_FULL;
   2870 
   2871     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   2872       return E_FILE_FORMAT_INVALID;
   2873 
   2874     if ((pos + len) > avail)
   2875       return E_BUFFER_NOT_FULL;
   2876 
   2877     const long long idpos = pos;  // absolute
   2878     const long long idoff = pos - m_start;  // relative
   2879 
   2880     const long long id = ReadID(m_pReader, idpos, len);  // absolute
   2881 
   2882     if (id < 0)  // error
   2883       return static_cast<long>(id);
   2884 
   2885     if (id == 0)  // weird
   2886       return -1;  // generic error
   2887 
   2888     pos += len;  // consume ID
   2889 
   2890     // Read Size
   2891 
   2892     if ((pos + 1) > avail) {
   2893       len = 1;
   2894       return E_BUFFER_NOT_FULL;
   2895     }
   2896 
   2897     result = GetUIntLength(m_pReader, pos, len);
   2898 
   2899     if (result < 0)  // error
   2900       return static_cast<long>(result);
   2901 
   2902     if (result > 0)  // weird
   2903       return E_BUFFER_NOT_FULL;
   2904 
   2905     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   2906       return E_FILE_FORMAT_INVALID;
   2907 
   2908     if ((pos + len) > avail)
   2909       return E_BUFFER_NOT_FULL;
   2910 
   2911     const long long size = ReadUInt(m_pReader, pos, len);
   2912 
   2913     if (size < 0)  // error
   2914       return static_cast<long>(size);
   2915 
   2916     pos += len;  // consume length of size of element
   2917 
   2918     // Pos now points to start of payload
   2919 
   2920     if (size == 0)  // weird
   2921       continue;
   2922 
   2923     const long long unknown_size = (1LL << (7 * len)) - 1;
   2924 
   2925     if ((segment_stop >= 0) && (size != unknown_size) &&
   2926         ((pos + size) > segment_stop)) {
   2927       return E_FILE_FORMAT_INVALID;
   2928     }
   2929 
   2930     if (id == mkvmuxer::kMkvCues) {
   2931       if (size == unknown_size)
   2932         return E_FILE_FORMAT_INVALID;
   2933 
   2934       const long long element_stop = pos + size;
   2935 
   2936       if ((segment_stop >= 0) && (element_stop > segment_stop))
   2937         return E_FILE_FORMAT_INVALID;
   2938 
   2939       const long long element_start = idpos;
   2940       const long long element_size = element_stop - element_start;
   2941 
   2942       if (m_pCues == NULL) {
   2943         m_pCues = new (std::nothrow)
   2944             Cues(this, pos, size, element_start, element_size);
   2945         if (m_pCues == NULL)
   2946           return false;
   2947       }
   2948 
   2949       pos += size;  // consume payload
   2950       if (segment_stop >= 0 && pos > segment_stop)
   2951         return E_FILE_FORMAT_INVALID;
   2952 
   2953       continue;
   2954     }
   2955 
   2956     if (id != mkvmuxer::kMkvCluster) {  // not a Cluster ID
   2957       if (size == unknown_size)
   2958         return E_FILE_FORMAT_INVALID;
   2959 
   2960       pos += size;  // consume payload
   2961       if (segment_stop >= 0 && pos > segment_stop)
   2962         return E_FILE_FORMAT_INVALID;
   2963 
   2964       continue;
   2965     }
   2966 
   2967     // We have a cluster.
   2968     off_next = idoff;
   2969 
   2970     if (size != unknown_size)
   2971       cluster_size = size;
   2972 
   2973     break;
   2974   }
   2975 
   2976   assert(off_next > 0);  // have cluster
   2977 
   2978   // We have parsed the next cluster.
   2979   // We have not created a cluster object yet.  What we need
   2980   // to do now is determine whether it has already be preloaded
   2981   //(in which case, an object for this cluster has already been
   2982   // created), and if not, create a new cluster object.
   2983 
   2984   Cluster** const ii = m_clusters + m_clusterCount;
   2985   Cluster** i = ii;
   2986 
   2987   Cluster** const jj = ii + m_clusterPreloadCount;
   2988   Cluster** j = jj;
   2989 
   2990   while (i < j) {
   2991     // INVARIANT:
   2992     //[0, i) < pos_next
   2993     //[i, j) ?
   2994     //[j, jj)  > pos_next
   2995 
   2996     Cluster** const k = i + (j - i) / 2;
   2997     assert(k < jj);
   2998 
   2999     const Cluster* const pNext = *k;
   3000     assert(pNext);
   3001     assert(pNext->m_index < 0);
   3002 
   3003     pos = pNext->GetPosition();
   3004     assert(pos >= 0);
   3005 
   3006     if (pos < off_next)
   3007       i = k + 1;
   3008     else if (pos > off_next)
   3009       j = k;
   3010     else {
   3011       pResult = pNext;
   3012       return 0;  // success
   3013     }
   3014   }
   3015 
   3016   assert(i == j);
   3017 
   3018   long long pos_;
   3019   long len_;
   3020 
   3021   status = Cluster::HasBlockEntries(this, off_next, pos_, len_);
   3022 
   3023   if (status < 0) {  // error or underflow
   3024     pos = pos_;
   3025     len = len_;
   3026 
   3027     return status;
   3028   }
   3029 
   3030   if (status > 0) {  // means "found at least one block entry"
   3031     Cluster* const pNext = Cluster::Create(this,
   3032                                            -1,  // preloaded
   3033                                            off_next);
   3034     if (pNext == NULL)
   3035       return -1;
   3036 
   3037     const ptrdiff_t idx_next = i - m_clusters;  // insertion position
   3038 
   3039     if (!PreloadCluster(pNext, idx_next)) {
   3040       delete pNext;
   3041       return -1;
   3042     }
   3043     assert(m_clusters);
   3044     assert(idx_next < m_clusterSize);
   3045     assert(m_clusters[idx_next] == pNext);
   3046 
   3047     pResult = pNext;
   3048     return 0;  // success
   3049   }
   3050 
   3051   // status == 0 means "no block entries found"
   3052 
   3053   if (cluster_size < 0) {  // unknown size
   3054     const long long payload_pos = pos;  // absolute pos of cluster payload
   3055 
   3056     for (;;) {  // determine cluster size
   3057       if ((total >= 0) && (pos >= total))
   3058         break;
   3059 
   3060       if ((segment_stop >= 0) && (pos >= segment_stop))
   3061         break;  // no more clusters
   3062 
   3063       // Read ID
   3064 
   3065       if ((pos + 1) > avail) {
   3066         len = 1;
   3067         return E_BUFFER_NOT_FULL;
   3068       }
   3069 
   3070       long long result = GetUIntLength(m_pReader, pos, len);
   3071 
   3072       if (result < 0)  // error
   3073         return static_cast<long>(result);
   3074 
   3075       if (result > 0)  // weird
   3076         return E_BUFFER_NOT_FULL;
   3077 
   3078       if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   3079         return E_FILE_FORMAT_INVALID;
   3080 
   3081       if ((pos + len) > avail)
   3082         return E_BUFFER_NOT_FULL;
   3083 
   3084       const long long idpos = pos;
   3085       const long long id = ReadID(m_pReader, idpos, len);
   3086 
   3087       if (id < 0)  // error (or underflow)
   3088         return static_cast<long>(id);
   3089 
   3090       // This is the distinguished set of ID's we use to determine
   3091       // that we have exhausted the sub-element's inside the cluster
   3092       // whose ID we parsed earlier.
   3093 
   3094       if (id == mkvmuxer::kMkvCluster || id == mkvmuxer::kMkvCues)
   3095         break;
   3096 
   3097       pos += len;  // consume ID (of sub-element)
   3098 
   3099       // Read Size
   3100 
   3101       if ((pos + 1) > avail) {
   3102         len = 1;
   3103         return E_BUFFER_NOT_FULL;
   3104       }
   3105 
   3106       result = GetUIntLength(m_pReader, pos, len);
   3107 
   3108       if (result < 0)  // error
   3109         return static_cast<long>(result);
   3110 
   3111       if (result > 0)  // weird
   3112         return E_BUFFER_NOT_FULL;
   3113 
   3114       if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   3115         return E_FILE_FORMAT_INVALID;
   3116 
   3117       if ((pos + len) > avail)
   3118         return E_BUFFER_NOT_FULL;
   3119 
   3120       const long long size = ReadUInt(m_pReader, pos, len);
   3121 
   3122       if (size < 0)  // error
   3123         return static_cast<long>(size);
   3124 
   3125       pos += len;  // consume size field of element
   3126 
   3127       // pos now points to start of sub-element's payload
   3128 
   3129       if (size == 0)  // weird
   3130         continue;
   3131 
   3132       const long long unknown_size = (1LL << (7 * len)) - 1;
   3133 
   3134       if (size == unknown_size)
   3135         return E_FILE_FORMAT_INVALID;  // not allowed for sub-elements
   3136 
   3137       if ((segment_stop >= 0) && ((pos + size) > segment_stop))  // weird
   3138         return E_FILE_FORMAT_INVALID;
   3139 
   3140       pos += size;  // consume payload of sub-element
   3141       if (segment_stop >= 0 && pos > segment_stop)
   3142         return E_FILE_FORMAT_INVALID;
   3143     }  // determine cluster size
   3144 
   3145     cluster_size = pos - payload_pos;
   3146     assert(cluster_size >= 0);  // TODO: handle cluster_size = 0
   3147 
   3148     pos = payload_pos;  // reset and re-parse original cluster
   3149   }
   3150 
   3151   pos += cluster_size;  // consume payload
   3152   if (segment_stop >= 0 && pos > segment_stop)
   3153     return E_FILE_FORMAT_INVALID;
   3154 
   3155   return 2;  // try to find a cluster that follows next
   3156 }
   3157 
   3158 const Cluster* Segment::FindCluster(long long time_ns) const {
   3159   if ((m_clusters == NULL) || (m_clusterCount <= 0))
   3160     return &m_eos;
   3161 
   3162   {
   3163     Cluster* const pCluster = m_clusters[0];
   3164     assert(pCluster);
   3165     assert(pCluster->m_index == 0);
   3166 
   3167     if (time_ns <= pCluster->GetTime())
   3168       return pCluster;
   3169   }
   3170 
   3171   // Binary search of cluster array
   3172 
   3173   long i = 0;
   3174   long j = m_clusterCount;
   3175 
   3176   while (i < j) {
   3177     // INVARIANT:
   3178     //[0, i) <= time_ns
   3179     //[i, j) ?
   3180     //[j, m_clusterCount)  > time_ns
   3181 
   3182     const long k = i + (j - i) / 2;
   3183     assert(k < m_clusterCount);
   3184 
   3185     Cluster* const pCluster = m_clusters[k];
   3186     assert(pCluster);
   3187     assert(pCluster->m_index == k);
   3188 
   3189     const long long t = pCluster->GetTime();
   3190 
   3191     if (t <= time_ns)
   3192       i = k + 1;
   3193     else
   3194       j = k;
   3195 
   3196     assert(i <= j);
   3197   }
   3198 
   3199   assert(i == j);
   3200   assert(i > 0);
   3201   assert(i <= m_clusterCount);
   3202 
   3203   const long k = i - 1;
   3204 
   3205   Cluster* const pCluster = m_clusters[k];
   3206   assert(pCluster);
   3207   assert(pCluster->m_index == k);
   3208   assert(pCluster->GetTime() <= time_ns);
   3209 
   3210   return pCluster;
   3211 }
   3212 
   3213 const Tracks* Segment::GetTracks() const { return m_pTracks; }
   3214 const SegmentInfo* Segment::GetInfo() const { return m_pInfo; }
   3215 const Cues* Segment::GetCues() const { return m_pCues; }
   3216 const Chapters* Segment::GetChapters() const { return m_pChapters; }
   3217 const Tags* Segment::GetTags() const { return m_pTags; }
   3218 const SeekHead* Segment::GetSeekHead() const { return m_pSeekHead; }
   3219 
   3220 long long Segment::GetDuration() const {
   3221   assert(m_pInfo);
   3222   return m_pInfo->GetDuration();
   3223 }
   3224 
   3225 Chapters::Chapters(Segment* pSegment, long long payload_start,
   3226                    long long payload_size, long long element_start,
   3227                    long long element_size)
   3228     : m_pSegment(pSegment),
   3229       m_start(payload_start),
   3230       m_size(payload_size),
   3231       m_element_start(element_start),
   3232       m_element_size(element_size),
   3233       m_editions(NULL),
   3234       m_editions_size(0),
   3235       m_editions_count(0) {}
   3236 
   3237 Chapters::~Chapters() {
   3238   while (m_editions_count > 0) {
   3239     Edition& e = m_editions[--m_editions_count];
   3240     e.Clear();
   3241   }
   3242   delete[] m_editions;
   3243 }
   3244 
   3245 long Chapters::Parse() {
   3246   IMkvReader* const pReader = m_pSegment->m_pReader;
   3247 
   3248   long long pos = m_start;  // payload start
   3249   const long long stop = pos + m_size;  // payload stop
   3250 
   3251   while (pos < stop) {
   3252     long long id, size;
   3253 
   3254     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3255 
   3256     if (status < 0)  // error
   3257       return status;
   3258 
   3259     if (size == 0)  // weird
   3260       continue;
   3261 
   3262     if (id == mkvmuxer::kMkvEditionEntry) {
   3263       status = ParseEdition(pos, size);
   3264 
   3265       if (status < 0)  // error
   3266         return status;
   3267     }
   3268 
   3269     pos += size;
   3270     if (pos > stop)
   3271       return E_FILE_FORMAT_INVALID;
   3272   }
   3273 
   3274   if (pos != stop)
   3275     return E_FILE_FORMAT_INVALID;
   3276   return 0;
   3277 }
   3278 
   3279 int Chapters::GetEditionCount() const { return m_editions_count; }
   3280 
   3281 const Chapters::Edition* Chapters::GetEdition(int idx) const {
   3282   if (idx < 0)
   3283     return NULL;
   3284 
   3285   if (idx >= m_editions_count)
   3286     return NULL;
   3287 
   3288   return m_editions + idx;
   3289 }
   3290 
   3291 bool Chapters::ExpandEditionsArray() {
   3292   if (m_editions_size > m_editions_count)
   3293     return true;  // nothing else to do
   3294 
   3295   const int size = (m_editions_size == 0) ? 1 : 2 * m_editions_size;
   3296 
   3297   Edition* const editions = new (std::nothrow) Edition[size];
   3298 
   3299   if (editions == NULL)
   3300     return false;
   3301 
   3302   for (int idx = 0; idx < m_editions_count; ++idx) {
   3303     m_editions[idx].ShallowCopy(editions[idx]);
   3304   }
   3305 
   3306   delete[] m_editions;
   3307   m_editions = editions;
   3308 
   3309   m_editions_size = size;
   3310   return true;
   3311 }
   3312 
   3313 long Chapters::ParseEdition(long long pos, long long size) {
   3314   if (!ExpandEditionsArray())
   3315     return -1;
   3316 
   3317   Edition& e = m_editions[m_editions_count++];
   3318   e.Init();
   3319 
   3320   return e.Parse(m_pSegment->m_pReader, pos, size);
   3321 }
   3322 
   3323 Chapters::Edition::Edition() {}
   3324 
   3325 Chapters::Edition::~Edition() {}
   3326 
   3327 int Chapters::Edition::GetAtomCount() const { return m_atoms_count; }
   3328 
   3329 const Chapters::Atom* Chapters::Edition::GetAtom(int index) const {
   3330   if (index < 0)
   3331     return NULL;
   3332 
   3333   if (index >= m_atoms_count)
   3334     return NULL;
   3335 
   3336   return m_atoms + index;
   3337 }
   3338 
   3339 void Chapters::Edition::Init() {
   3340   m_atoms = NULL;
   3341   m_atoms_size = 0;
   3342   m_atoms_count = 0;
   3343 }
   3344 
   3345 void Chapters::Edition::ShallowCopy(Edition& rhs) const {
   3346   rhs.m_atoms = m_atoms;
   3347   rhs.m_atoms_size = m_atoms_size;
   3348   rhs.m_atoms_count = m_atoms_count;
   3349 }
   3350 
   3351 void Chapters::Edition::Clear() {
   3352   while (m_atoms_count > 0) {
   3353     Atom& a = m_atoms[--m_atoms_count];
   3354     a.Clear();
   3355   }
   3356 
   3357   delete[] m_atoms;
   3358   m_atoms = NULL;
   3359 
   3360   m_atoms_size = 0;
   3361 }
   3362 
   3363 long Chapters::Edition::Parse(IMkvReader* pReader, long long pos,
   3364                               long long size) {
   3365   const long long stop = pos + size;
   3366 
   3367   while (pos < stop) {
   3368     long long id, size;
   3369 
   3370     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3371 
   3372     if (status < 0)  // error
   3373       return status;
   3374 
   3375     if (size == 0)
   3376       continue;
   3377 
   3378     if (id == mkvmuxer::kMkvChapterAtom) {
   3379       status = ParseAtom(pReader, pos, size);
   3380 
   3381       if (status < 0)  // error
   3382         return status;
   3383     }
   3384 
   3385     pos += size;
   3386     if (pos > stop)
   3387       return E_FILE_FORMAT_INVALID;
   3388   }
   3389 
   3390   if (pos != stop)
   3391     return E_FILE_FORMAT_INVALID;
   3392   return 0;
   3393 }
   3394 
   3395 long Chapters::Edition::ParseAtom(IMkvReader* pReader, long long pos,
   3396                                   long long size) {
   3397   if (!ExpandAtomsArray())
   3398     return -1;
   3399 
   3400   Atom& a = m_atoms[m_atoms_count++];
   3401   a.Init();
   3402 
   3403   return a.Parse(pReader, pos, size);
   3404 }
   3405 
   3406 bool Chapters::Edition::ExpandAtomsArray() {
   3407   if (m_atoms_size > m_atoms_count)
   3408     return true;  // nothing else to do
   3409 
   3410   const int size = (m_atoms_size == 0) ? 1 : 2 * m_atoms_size;
   3411 
   3412   Atom* const atoms = new (std::nothrow) Atom[size];
   3413 
   3414   if (atoms == NULL)
   3415     return false;
   3416 
   3417   for (int idx = 0; idx < m_atoms_count; ++idx) {
   3418     m_atoms[idx].ShallowCopy(atoms[idx]);
   3419   }
   3420 
   3421   delete[] m_atoms;
   3422   m_atoms = atoms;
   3423 
   3424   m_atoms_size = size;
   3425   return true;
   3426 }
   3427 
   3428 Chapters::Atom::Atom() {}
   3429 
   3430 Chapters::Atom::~Atom() {}
   3431 
   3432 unsigned long long Chapters::Atom::GetUID() const { return m_uid; }
   3433 
   3434 const char* Chapters::Atom::GetStringUID() const { return m_string_uid; }
   3435 
   3436 long long Chapters::Atom::GetStartTimecode() const { return m_start_timecode; }
   3437 
   3438 long long Chapters::Atom::GetStopTimecode() const { return m_stop_timecode; }
   3439 
   3440 long long Chapters::Atom::GetStartTime(const Chapters* pChapters) const {
   3441   return GetTime(pChapters, m_start_timecode);
   3442 }
   3443 
   3444 long long Chapters::Atom::GetStopTime(const Chapters* pChapters) const {
   3445   return GetTime(pChapters, m_stop_timecode);
   3446 }
   3447 
   3448 int Chapters::Atom::GetDisplayCount() const { return m_displays_count; }
   3449 
   3450 const Chapters::Display* Chapters::Atom::GetDisplay(int index) const {
   3451   if (index < 0)
   3452     return NULL;
   3453 
   3454   if (index >= m_displays_count)
   3455     return NULL;
   3456 
   3457   return m_displays + index;
   3458 }
   3459 
   3460 void Chapters::Atom::Init() {
   3461   m_string_uid = NULL;
   3462   m_uid = 0;
   3463   m_start_timecode = -1;
   3464   m_stop_timecode = -1;
   3465 
   3466   m_displays = NULL;
   3467   m_displays_size = 0;
   3468   m_displays_count = 0;
   3469 }
   3470 
   3471 void Chapters::Atom::ShallowCopy(Atom& rhs) const {
   3472   rhs.m_string_uid = m_string_uid;
   3473   rhs.m_uid = m_uid;
   3474   rhs.m_start_timecode = m_start_timecode;
   3475   rhs.m_stop_timecode = m_stop_timecode;
   3476 
   3477   rhs.m_displays = m_displays;
   3478   rhs.m_displays_size = m_displays_size;
   3479   rhs.m_displays_count = m_displays_count;
   3480 }
   3481 
   3482 void Chapters::Atom::Clear() {
   3483   delete[] m_string_uid;
   3484   m_string_uid = NULL;
   3485 
   3486   while (m_displays_count > 0) {
   3487     Display& d = m_displays[--m_displays_count];
   3488     d.Clear();
   3489   }
   3490 
   3491   delete[] m_displays;
   3492   m_displays = NULL;
   3493 
   3494   m_displays_size = 0;
   3495 }
   3496 
   3497 long Chapters::Atom::Parse(IMkvReader* pReader, long long pos, long long size) {
   3498   const long long stop = pos + size;
   3499 
   3500   while (pos < stop) {
   3501     long long id, size;
   3502 
   3503     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3504 
   3505     if (status < 0)  // error
   3506       return status;
   3507 
   3508     if (size == 0)  // 0 length payload, skip.
   3509       continue;
   3510 
   3511     if (id == mkvmuxer::kMkvChapterDisplay) {
   3512       status = ParseDisplay(pReader, pos, size);
   3513 
   3514       if (status < 0)  // error
   3515         return status;
   3516     } else if (id == mkvmuxer::kMkvChapterStringUID) {
   3517       status = UnserializeString(pReader, pos, size, m_string_uid);
   3518 
   3519       if (status < 0)  // error
   3520         return status;
   3521     } else if (id == mkvmuxer::kMkvChapterUID) {
   3522       long long val;
   3523       status = UnserializeInt(pReader, pos, size, val);
   3524 
   3525       if (status < 0)  // error
   3526         return status;
   3527 
   3528       m_uid = static_cast<unsigned long long>(val);
   3529     } else if (id == mkvmuxer::kMkvChapterTimeStart) {
   3530       const long long val = UnserializeUInt(pReader, pos, size);
   3531 
   3532       if (val < 0)  // error
   3533         return static_cast<long>(val);
   3534 
   3535       m_start_timecode = val;
   3536     } else if (id == mkvmuxer::kMkvChapterTimeEnd) {
   3537       const long long val = UnserializeUInt(pReader, pos, size);
   3538 
   3539       if (val < 0)  // error
   3540         return static_cast<long>(val);
   3541 
   3542       m_stop_timecode = val;
   3543     }
   3544 
   3545     pos += size;
   3546     if (pos > stop)
   3547       return E_FILE_FORMAT_INVALID;
   3548   }
   3549 
   3550   if (pos != stop)
   3551     return E_FILE_FORMAT_INVALID;
   3552   return 0;
   3553 }
   3554 
   3555 long long Chapters::Atom::GetTime(const Chapters* pChapters,
   3556                                   long long timecode) {
   3557   if (pChapters == NULL)
   3558     return -1;
   3559 
   3560   Segment* const pSegment = pChapters->m_pSegment;
   3561 
   3562   if (pSegment == NULL)  // weird
   3563     return -1;
   3564 
   3565   const SegmentInfo* const pInfo = pSegment->GetInfo();
   3566 
   3567   if (pInfo == NULL)
   3568     return -1;
   3569 
   3570   const long long timecode_scale = pInfo->GetTimeCodeScale();
   3571 
   3572   if (timecode_scale < 1)  // weird
   3573     return -1;
   3574 
   3575   if (timecode < 0)
   3576     return -1;
   3577 
   3578   const long long result = timecode_scale * timecode;
   3579 
   3580   return result;
   3581 }
   3582 
   3583 long Chapters::Atom::ParseDisplay(IMkvReader* pReader, long long pos,
   3584                                   long long size) {
   3585   if (!ExpandDisplaysArray())
   3586     return -1;
   3587 
   3588   Display& d = m_displays[m_displays_count++];
   3589   d.Init();
   3590 
   3591   return d.Parse(pReader, pos, size);
   3592 }
   3593 
   3594 bool Chapters::Atom::ExpandDisplaysArray() {
   3595   if (m_displays_size > m_displays_count)
   3596     return true;  // nothing else to do
   3597 
   3598   const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size;
   3599 
   3600   Display* const displays = new (std::nothrow) Display[size];
   3601 
   3602   if (displays == NULL)
   3603     return false;
   3604 
   3605   for (int idx = 0; idx < m_displays_count; ++idx) {
   3606     m_displays[idx].ShallowCopy(displays[idx]);
   3607   }
   3608 
   3609   delete[] m_displays;
   3610   m_displays = displays;
   3611 
   3612   m_displays_size = size;
   3613   return true;
   3614 }
   3615 
   3616 Chapters::Display::Display() {}
   3617 
   3618 Chapters::Display::~Display() {}
   3619 
   3620 const char* Chapters::Display::GetString() const { return m_string; }
   3621 
   3622 const char* Chapters::Display::GetLanguage() const { return m_language; }
   3623 
   3624 const char* Chapters::Display::GetCountry() const { return m_country; }
   3625 
   3626 void Chapters::Display::Init() {
   3627   m_string = NULL;
   3628   m_language = NULL;
   3629   m_country = NULL;
   3630 }
   3631 
   3632 void Chapters::Display::ShallowCopy(Display& rhs) const {
   3633   rhs.m_string = m_string;
   3634   rhs.m_language = m_language;
   3635   rhs.m_country = m_country;
   3636 }
   3637 
   3638 void Chapters::Display::Clear() {
   3639   delete[] m_string;
   3640   m_string = NULL;
   3641 
   3642   delete[] m_language;
   3643   m_language = NULL;
   3644 
   3645   delete[] m_country;
   3646   m_country = NULL;
   3647 }
   3648 
   3649 long Chapters::Display::Parse(IMkvReader* pReader, long long pos,
   3650                               long long size) {
   3651   const long long stop = pos + size;
   3652 
   3653   while (pos < stop) {
   3654     long long id, size;
   3655 
   3656     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3657 
   3658     if (status < 0)  // error
   3659       return status;
   3660 
   3661     if (size == 0)  // No payload.
   3662       continue;
   3663 
   3664     if (id == mkvmuxer::kMkvChapString) {
   3665       status = UnserializeString(pReader, pos, size, m_string);
   3666 
   3667       if (status)
   3668         return status;
   3669     } else if (id == mkvmuxer::kMkvChapLanguage) {
   3670       status = UnserializeString(pReader, pos, size, m_language);
   3671 
   3672       if (status)
   3673         return status;
   3674     } else if (id == mkvmuxer::kMkvChapCountry) {
   3675       status = UnserializeString(pReader, pos, size, m_country);
   3676 
   3677       if (status)
   3678         return status;
   3679     }
   3680 
   3681     pos += size;
   3682     if (pos > stop)
   3683       return E_FILE_FORMAT_INVALID;
   3684   }
   3685 
   3686   if (pos != stop)
   3687     return E_FILE_FORMAT_INVALID;
   3688   return 0;
   3689 }
   3690 
   3691 Tags::Tags(Segment* pSegment, long long payload_start, long long payload_size,
   3692            long long element_start, long long element_size)
   3693     : m_pSegment(pSegment),
   3694       m_start(payload_start),
   3695       m_size(payload_size),
   3696       m_element_start(element_start),
   3697       m_element_size(element_size),
   3698       m_tags(NULL),
   3699       m_tags_size(0),
   3700       m_tags_count(0) {}
   3701 
   3702 Tags::~Tags() {
   3703   while (m_tags_count > 0) {
   3704     Tag& t = m_tags[--m_tags_count];
   3705     t.Clear();
   3706   }
   3707   delete[] m_tags;
   3708 }
   3709 
   3710 long Tags::Parse() {
   3711   IMkvReader* const pReader = m_pSegment->m_pReader;
   3712 
   3713   long long pos = m_start;  // payload start
   3714   const long long stop = pos + m_size;  // payload stop
   3715 
   3716   while (pos < stop) {
   3717     long long id, size;
   3718 
   3719     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3720 
   3721     if (status < 0)
   3722       return status;
   3723 
   3724     if (size == 0)  // 0 length tag, read another
   3725       continue;
   3726 
   3727     if (id == mkvmuxer::kMkvTag) {
   3728       status = ParseTag(pos, size);
   3729 
   3730       if (status < 0)
   3731         return status;
   3732     }
   3733 
   3734     pos += size;
   3735     if (pos > stop)
   3736       return E_FILE_FORMAT_INVALID;
   3737   }
   3738 
   3739   if (pos != stop)
   3740     return E_FILE_FORMAT_INVALID;
   3741 
   3742   return 0;
   3743 }
   3744 
   3745 int Tags::GetTagCount() const { return m_tags_count; }
   3746 
   3747 const Tags::Tag* Tags::GetTag(int idx) const {
   3748   if (idx < 0)
   3749     return NULL;
   3750 
   3751   if (idx >= m_tags_count)
   3752     return NULL;
   3753 
   3754   return m_tags + idx;
   3755 }
   3756 
   3757 bool Tags::ExpandTagsArray() {
   3758   if (m_tags_size > m_tags_count)
   3759     return true;  // nothing else to do
   3760 
   3761   const int size = (m_tags_size == 0) ? 1 : 2 * m_tags_size;
   3762 
   3763   Tag* const tags = new (std::nothrow) Tag[size];
   3764 
   3765   if (tags == NULL)
   3766     return false;
   3767 
   3768   for (int idx = 0; idx < m_tags_count; ++idx) {
   3769     m_tags[idx].ShallowCopy(tags[idx]);
   3770   }
   3771 
   3772   delete[] m_tags;
   3773   m_tags = tags;
   3774 
   3775   m_tags_size = size;
   3776   return true;
   3777 }
   3778 
   3779 long Tags::ParseTag(long long pos, long long size) {
   3780   if (!ExpandTagsArray())
   3781     return -1;
   3782 
   3783   Tag& t = m_tags[m_tags_count++];
   3784   t.Init();
   3785 
   3786   return t.Parse(m_pSegment->m_pReader, pos, size);
   3787 }
   3788 
   3789 Tags::Tag::Tag() {}
   3790 
   3791 Tags::Tag::~Tag() {}
   3792 
   3793 int Tags::Tag::GetSimpleTagCount() const { return m_simple_tags_count; }
   3794 
   3795 const Tags::SimpleTag* Tags::Tag::GetSimpleTag(int index) const {
   3796   if (index < 0)
   3797     return NULL;
   3798 
   3799   if (index >= m_simple_tags_count)
   3800     return NULL;
   3801 
   3802   return m_simple_tags + index;
   3803 }
   3804 
   3805 void Tags::Tag::Init() {
   3806   m_simple_tags = NULL;
   3807   m_simple_tags_size = 0;
   3808   m_simple_tags_count = 0;
   3809 }
   3810 
   3811 void Tags::Tag::ShallowCopy(Tag& rhs) const {
   3812   rhs.m_simple_tags = m_simple_tags;
   3813   rhs.m_simple_tags_size = m_simple_tags_size;
   3814   rhs.m_simple_tags_count = m_simple_tags_count;
   3815 }
   3816 
   3817 void Tags::Tag::Clear() {
   3818   while (m_simple_tags_count > 0) {
   3819     SimpleTag& d = m_simple_tags[--m_simple_tags_count];
   3820     d.Clear();
   3821   }
   3822 
   3823   delete[] m_simple_tags;
   3824   m_simple_tags = NULL;
   3825 
   3826   m_simple_tags_size = 0;
   3827 }
   3828 
   3829 long Tags::Tag::Parse(IMkvReader* pReader, long long pos, long long size) {
   3830   const long long stop = pos + size;
   3831 
   3832   while (pos < stop) {
   3833     long long id, size;
   3834 
   3835     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3836 
   3837     if (status < 0)
   3838       return status;
   3839 
   3840     if (size == 0)  // 0 length tag, read another
   3841       continue;
   3842 
   3843     if (id == mkvmuxer::kMkvSimpleTag) {
   3844       status = ParseSimpleTag(pReader, pos, size);
   3845 
   3846       if (status < 0)
   3847         return status;
   3848     }
   3849 
   3850     pos += size;
   3851     if (pos > stop)
   3852       return E_FILE_FORMAT_INVALID;
   3853   }
   3854 
   3855   if (pos != stop)
   3856     return E_FILE_FORMAT_INVALID;
   3857   return 0;
   3858 }
   3859 
   3860 long Tags::Tag::ParseSimpleTag(IMkvReader* pReader, long long pos,
   3861                                long long size) {
   3862   if (!ExpandSimpleTagsArray())
   3863     return -1;
   3864 
   3865   SimpleTag& st = m_simple_tags[m_simple_tags_count++];
   3866   st.Init();
   3867 
   3868   return st.Parse(pReader, pos, size);
   3869 }
   3870 
   3871 bool Tags::Tag::ExpandSimpleTagsArray() {
   3872   if (m_simple_tags_size > m_simple_tags_count)
   3873     return true;  // nothing else to do
   3874 
   3875   const int size = (m_simple_tags_size == 0) ? 1 : 2 * m_simple_tags_size;
   3876 
   3877   SimpleTag* const displays = new (std::nothrow) SimpleTag[size];
   3878 
   3879   if (displays == NULL)
   3880     return false;
   3881 
   3882   for (int idx = 0; idx < m_simple_tags_count; ++idx) {
   3883     m_simple_tags[idx].ShallowCopy(displays[idx]);
   3884   }
   3885 
   3886   delete[] m_simple_tags;
   3887   m_simple_tags = displays;
   3888 
   3889   m_simple_tags_size = size;
   3890   return true;
   3891 }
   3892 
   3893 Tags::SimpleTag::SimpleTag() {}
   3894 
   3895 Tags::SimpleTag::~SimpleTag() {}
   3896 
   3897 const char* Tags::SimpleTag::GetTagName() const { return m_tag_name; }
   3898 
   3899 const char* Tags::SimpleTag::GetTagString() const { return m_tag_string; }
   3900 
   3901 void Tags::SimpleTag::Init() {
   3902   m_tag_name = NULL;
   3903   m_tag_string = NULL;
   3904 }
   3905 
   3906 void Tags::SimpleTag::ShallowCopy(SimpleTag& rhs) const {
   3907   rhs.m_tag_name = m_tag_name;
   3908   rhs.m_tag_string = m_tag_string;
   3909 }
   3910 
   3911 void Tags::SimpleTag::Clear() {
   3912   delete[] m_tag_name;
   3913   m_tag_name = NULL;
   3914 
   3915   delete[] m_tag_string;
   3916   m_tag_string = NULL;
   3917 }
   3918 
   3919 long Tags::SimpleTag::Parse(IMkvReader* pReader, long long pos,
   3920                             long long size) {
   3921   const long long stop = pos + size;
   3922 
   3923   while (pos < stop) {
   3924     long long id, size;
   3925 
   3926     long status = ParseElementHeader(pReader, pos, stop, id, size);
   3927 
   3928     if (status < 0)  // error
   3929       return status;
   3930 
   3931     if (size == 0)  // weird
   3932       continue;
   3933 
   3934     if (id == mkvmuxer::kMkvTagName) {
   3935       status = UnserializeString(pReader, pos, size, m_tag_name);
   3936 
   3937       if (status)
   3938         return status;
   3939     } else if (id == mkvmuxer::kMkvTagString) {
   3940       status = UnserializeString(pReader, pos, size, m_tag_string);
   3941 
   3942       if (status)
   3943         return status;
   3944     }
   3945 
   3946     pos += size;
   3947     if (pos > stop)
   3948       return E_FILE_FORMAT_INVALID;
   3949   }
   3950 
   3951   if (pos != stop)
   3952     return E_FILE_FORMAT_INVALID;
   3953   return 0;
   3954 }
   3955 
   3956 SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_,
   3957                          long long element_start, long long element_size)
   3958     : m_pSegment(pSegment),
   3959       m_start(start),
   3960       m_size(size_),
   3961       m_element_start(element_start),
   3962       m_element_size(element_size),
   3963       m_pMuxingAppAsUTF8(NULL),
   3964       m_pWritingAppAsUTF8(NULL),
   3965       m_pTitleAsUTF8(NULL) {}
   3966 
   3967 SegmentInfo::~SegmentInfo() {
   3968   delete[] m_pMuxingAppAsUTF8;
   3969   m_pMuxingAppAsUTF8 = NULL;
   3970 
   3971   delete[] m_pWritingAppAsUTF8;
   3972   m_pWritingAppAsUTF8 = NULL;
   3973 
   3974   delete[] m_pTitleAsUTF8;
   3975   m_pTitleAsUTF8 = NULL;
   3976 }
   3977 
   3978 long SegmentInfo::Parse() {
   3979   assert(m_pMuxingAppAsUTF8 == NULL);
   3980   assert(m_pWritingAppAsUTF8 == NULL);
   3981   assert(m_pTitleAsUTF8 == NULL);
   3982 
   3983   IMkvReader* const pReader = m_pSegment->m_pReader;
   3984 
   3985   long long pos = m_start;
   3986   const long long stop = m_start + m_size;
   3987 
   3988   m_timecodeScale = 1000000;
   3989   m_duration = -1;
   3990 
   3991   while (pos < stop) {
   3992     long long id, size;
   3993 
   3994     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   3995 
   3996     if (status < 0)  // error
   3997       return status;
   3998 
   3999     if (id == mkvmuxer::kMkvTimecodeScale) {
   4000       m_timecodeScale = UnserializeUInt(pReader, pos, size);
   4001 
   4002       if (m_timecodeScale <= 0)
   4003         return E_FILE_FORMAT_INVALID;
   4004     } else if (id == mkvmuxer::kMkvDuration) {
   4005       const long status = UnserializeFloat(pReader, pos, size, m_duration);
   4006 
   4007       if (status < 0)
   4008         return status;
   4009 
   4010       if (m_duration < 0)
   4011         return E_FILE_FORMAT_INVALID;
   4012     } else if (id == mkvmuxer::kMkvMuxingApp) {
   4013       const long status =
   4014           UnserializeString(pReader, pos, size, m_pMuxingAppAsUTF8);
   4015 
   4016       if (status)
   4017         return status;
   4018     } else if (id == mkvmuxer::kMkvWritingApp) {
   4019       const long status =
   4020           UnserializeString(pReader, pos, size, m_pWritingAppAsUTF8);
   4021 
   4022       if (status)
   4023         return status;
   4024     } else if (id == mkvmuxer::kMkvTitle) {
   4025       const long status = UnserializeString(pReader, pos, size, m_pTitleAsUTF8);
   4026 
   4027       if (status)
   4028         return status;
   4029     }
   4030 
   4031     pos += size;
   4032 
   4033     if (pos > stop)
   4034       return E_FILE_FORMAT_INVALID;
   4035   }
   4036 
   4037   const double rollover_check = m_duration * m_timecodeScale;
   4038   if (rollover_check > LLONG_MAX)
   4039     return E_FILE_FORMAT_INVALID;
   4040 
   4041   if (pos != stop)
   4042     return E_FILE_FORMAT_INVALID;
   4043 
   4044   return 0;
   4045 }
   4046 
   4047 long long SegmentInfo::GetTimeCodeScale() const { return m_timecodeScale; }
   4048 
   4049 long long SegmentInfo::GetDuration() const {
   4050   if (m_duration < 0)
   4051     return -1;
   4052 
   4053   assert(m_timecodeScale >= 1);
   4054 
   4055   const double dd = double(m_duration) * double(m_timecodeScale);
   4056   const long long d = static_cast<long long>(dd);
   4057 
   4058   return d;
   4059 }
   4060 
   4061 const char* SegmentInfo::GetMuxingAppAsUTF8() const {
   4062   return m_pMuxingAppAsUTF8;
   4063 }
   4064 
   4065 const char* SegmentInfo::GetWritingAppAsUTF8() const {
   4066   return m_pWritingAppAsUTF8;
   4067 }
   4068 
   4069 const char* SegmentInfo::GetTitleAsUTF8() const { return m_pTitleAsUTF8; }
   4070 
   4071 ///////////////////////////////////////////////////////////////
   4072 // ContentEncoding element
   4073 ContentEncoding::ContentCompression::ContentCompression()
   4074     : algo(0), settings(NULL), settings_len(0) {}
   4075 
   4076 ContentEncoding::ContentCompression::~ContentCompression() {
   4077   delete[] settings;
   4078 }
   4079 
   4080 ContentEncoding::ContentEncryption::ContentEncryption()
   4081     : algo(0),
   4082       key_id(NULL),
   4083       key_id_len(0),
   4084       signature(NULL),
   4085       signature_len(0),
   4086       sig_key_id(NULL),
   4087       sig_key_id_len(0),
   4088       sig_algo(0),
   4089       sig_hash_algo(0) {}
   4090 
   4091 ContentEncoding::ContentEncryption::~ContentEncryption() {
   4092   delete[] key_id;
   4093   delete[] signature;
   4094   delete[] sig_key_id;
   4095 }
   4096 
   4097 ContentEncoding::ContentEncoding()
   4098     : compression_entries_(NULL),
   4099       compression_entries_end_(NULL),
   4100       encryption_entries_(NULL),
   4101       encryption_entries_end_(NULL),
   4102       encoding_order_(0),
   4103       encoding_scope_(1),
   4104       encoding_type_(0) {}
   4105 
   4106 ContentEncoding::~ContentEncoding() {
   4107   ContentCompression** comp_i = compression_entries_;
   4108   ContentCompression** const comp_j = compression_entries_end_;
   4109 
   4110   while (comp_i != comp_j) {
   4111     ContentCompression* const comp = *comp_i++;
   4112     delete comp;
   4113   }
   4114 
   4115   delete[] compression_entries_;
   4116 
   4117   ContentEncryption** enc_i = encryption_entries_;
   4118   ContentEncryption** const enc_j = encryption_entries_end_;
   4119 
   4120   while (enc_i != enc_j) {
   4121     ContentEncryption* const enc = *enc_i++;
   4122     delete enc;
   4123   }
   4124 
   4125   delete[] encryption_entries_;
   4126 }
   4127 
   4128 const ContentEncoding::ContentCompression*
   4129     ContentEncoding::GetCompressionByIndex(unsigned long idx) const {
   4130   const ptrdiff_t count = compression_entries_end_ - compression_entries_;
   4131   assert(count >= 0);
   4132 
   4133   if (idx >= static_cast<unsigned long>(count))
   4134     return NULL;
   4135 
   4136   return compression_entries_[idx];
   4137 }
   4138 
   4139 unsigned long ContentEncoding::GetCompressionCount() const {
   4140   const ptrdiff_t count = compression_entries_end_ - compression_entries_;
   4141   assert(count >= 0);
   4142 
   4143   return static_cast<unsigned long>(count);
   4144 }
   4145 
   4146 const ContentEncoding::ContentEncryption* ContentEncoding::GetEncryptionByIndex(
   4147     unsigned long idx) const {
   4148   const ptrdiff_t count = encryption_entries_end_ - encryption_entries_;
   4149   assert(count >= 0);
   4150 
   4151   if (idx >= static_cast<unsigned long>(count))
   4152     return NULL;
   4153 
   4154   return encryption_entries_[idx];
   4155 }
   4156 
   4157 unsigned long ContentEncoding::GetEncryptionCount() const {
   4158   const ptrdiff_t count = encryption_entries_end_ - encryption_entries_;
   4159   assert(count >= 0);
   4160 
   4161   return static_cast<unsigned long>(count);
   4162 }
   4163 
   4164 long ContentEncoding::ParseContentEncAESSettingsEntry(
   4165     long long start, long long size, IMkvReader* pReader,
   4166     ContentEncAESSettings* aes) {
   4167   assert(pReader);
   4168   assert(aes);
   4169 
   4170   long long pos = start;
   4171   const long long stop = start + size;
   4172 
   4173   while (pos < stop) {
   4174     long long id, size;
   4175     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   4176     if (status < 0)  // error
   4177       return status;
   4178 
   4179     if (id == mkvmuxer::kMkvAESSettingsCipherMode) {
   4180       aes->cipher_mode = UnserializeUInt(pReader, pos, size);
   4181       if (aes->cipher_mode != 1)
   4182         return E_FILE_FORMAT_INVALID;
   4183     }
   4184 
   4185     pos += size;  // consume payload
   4186     if (pos > stop)
   4187       return E_FILE_FORMAT_INVALID;
   4188   }
   4189 
   4190   return 0;
   4191 }
   4192 
   4193 long ContentEncoding::ParseContentEncodingEntry(long long start, long long size,
   4194                                                 IMkvReader* pReader) {
   4195   assert(pReader);
   4196 
   4197   long long pos = start;
   4198   const long long stop = start + size;
   4199 
   4200   // Count ContentCompression and ContentEncryption elements.
   4201   int compression_count = 0;
   4202   int encryption_count = 0;
   4203 
   4204   while (pos < stop) {
   4205     long long id, size;
   4206     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   4207     if (status < 0)  // error
   4208       return status;
   4209 
   4210     if (id == mkvmuxer::kMkvContentCompression)
   4211       ++compression_count;
   4212 
   4213     if (id == mkvmuxer::kMkvContentEncryption)
   4214       ++encryption_count;
   4215 
   4216     pos += size;  // consume payload
   4217     if (pos > stop)
   4218       return E_FILE_FORMAT_INVALID;
   4219   }
   4220 
   4221   if (compression_count <= 0 && encryption_count <= 0)
   4222     return -1;
   4223 
   4224   if (compression_count > 0) {
   4225     compression_entries_ =
   4226         new (std::nothrow) ContentCompression*[compression_count];
   4227     if (!compression_entries_)
   4228       return -1;
   4229     compression_entries_end_ = compression_entries_;
   4230   }
   4231 
   4232   if (encryption_count > 0) {
   4233     encryption_entries_ =
   4234         new (std::nothrow) ContentEncryption*[encryption_count];
   4235     if (!encryption_entries_) {
   4236       delete[] compression_entries_;
   4237       return -1;
   4238     }
   4239     encryption_entries_end_ = encryption_entries_;
   4240   }
   4241 
   4242   pos = start;
   4243   while (pos < stop) {
   4244     long long id, size;
   4245     long status = ParseElementHeader(pReader, pos, stop, id, size);
   4246     if (status < 0)  // error
   4247       return status;
   4248 
   4249     if (id == mkvmuxer::kMkvContentEncodingOrder) {
   4250       encoding_order_ = UnserializeUInt(pReader, pos, size);
   4251     } else if (id == mkvmuxer::kMkvContentEncodingScope) {
   4252       encoding_scope_ = UnserializeUInt(pReader, pos, size);
   4253       if (encoding_scope_ < 1)
   4254         return -1;
   4255     } else if (id == mkvmuxer::kMkvContentEncodingType) {
   4256       encoding_type_ = UnserializeUInt(pReader, pos, size);
   4257     } else if (id == mkvmuxer::kMkvContentCompression) {
   4258       ContentCompression* const compression =
   4259           new (std::nothrow) ContentCompression();
   4260       if (!compression)
   4261         return -1;
   4262 
   4263       status = ParseCompressionEntry(pos, size, pReader, compression);
   4264       if (status) {
   4265         delete compression;
   4266         return status;
   4267       }
   4268       *compression_entries_end_++ = compression;
   4269     } else if (id == mkvmuxer::kMkvContentEncryption) {
   4270       ContentEncryption* const encryption =
   4271           new (std::nothrow) ContentEncryption();
   4272       if (!encryption)
   4273         return -1;
   4274 
   4275       status = ParseEncryptionEntry(pos, size, pReader, encryption);
   4276       if (status) {
   4277         delete encryption;
   4278         return status;
   4279       }
   4280       *encryption_entries_end_++ = encryption;
   4281     }
   4282 
   4283     pos += size;  // consume payload
   4284     if (pos > stop)
   4285       return E_FILE_FORMAT_INVALID;
   4286   }
   4287 
   4288   if (pos != stop)
   4289     return E_FILE_FORMAT_INVALID;
   4290   return 0;
   4291 }
   4292 
   4293 long ContentEncoding::ParseCompressionEntry(long long start, long long size,
   4294                                             IMkvReader* pReader,
   4295                                             ContentCompression* compression) {
   4296   assert(pReader);
   4297   assert(compression);
   4298 
   4299   long long pos = start;
   4300   const long long stop = start + size;
   4301 
   4302   bool valid = false;
   4303 
   4304   while (pos < stop) {
   4305     long long id, size;
   4306     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   4307     if (status < 0)  // error
   4308       return status;
   4309 
   4310     if (id == mkvmuxer::kMkvContentCompAlgo) {
   4311       long long algo = UnserializeUInt(pReader, pos, size);
   4312       if (algo < 0)
   4313         return E_FILE_FORMAT_INVALID;
   4314       compression->algo = algo;
   4315       valid = true;
   4316     } else if (id == mkvmuxer::kMkvContentCompSettings) {
   4317       if (size <= 0)
   4318         return E_FILE_FORMAT_INVALID;
   4319 
   4320       const size_t buflen = static_cast<size_t>(size);
   4321       unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
   4322       if (buf == NULL)
   4323         return -1;
   4324 
   4325       const int read_status =
   4326           pReader->Read(pos, static_cast<long>(buflen), buf);
   4327       if (read_status) {
   4328         delete[] buf;
   4329         return status;
   4330       }
   4331 
   4332       compression->settings = buf;
   4333       compression->settings_len = buflen;
   4334     }
   4335 
   4336     pos += size;  // consume payload
   4337     if (pos > stop)
   4338       return E_FILE_FORMAT_INVALID;
   4339   }
   4340 
   4341   // ContentCompAlgo is mandatory
   4342   if (!valid)
   4343     return E_FILE_FORMAT_INVALID;
   4344 
   4345   return 0;
   4346 }
   4347 
   4348 long ContentEncoding::ParseEncryptionEntry(long long start, long long size,
   4349                                            IMkvReader* pReader,
   4350                                            ContentEncryption* encryption) {
   4351   assert(pReader);
   4352   assert(encryption);
   4353 
   4354   long long pos = start;
   4355   const long long stop = start + size;
   4356 
   4357   while (pos < stop) {
   4358     long long id, size;
   4359     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   4360     if (status < 0)  // error
   4361       return status;
   4362 
   4363     if (id == mkvmuxer::kMkvContentEncAlgo) {
   4364       encryption->algo = UnserializeUInt(pReader, pos, size);
   4365       if (encryption->algo != 5)
   4366         return E_FILE_FORMAT_INVALID;
   4367     } else if (id == mkvmuxer::kMkvContentEncKeyID) {
   4368       delete[] encryption->key_id;
   4369       encryption->key_id = NULL;
   4370       encryption->key_id_len = 0;
   4371 
   4372       if (size <= 0)
   4373         return E_FILE_FORMAT_INVALID;
   4374 
   4375       const size_t buflen = static_cast<size_t>(size);
   4376       unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
   4377       if (buf == NULL)
   4378         return -1;
   4379 
   4380       const int read_status =
   4381           pReader->Read(pos, static_cast<long>(buflen), buf);
   4382       if (read_status) {
   4383         delete[] buf;
   4384         return status;
   4385       }
   4386 
   4387       encryption->key_id = buf;
   4388       encryption->key_id_len = buflen;
   4389     } else if (id == mkvmuxer::kMkvContentSignature) {
   4390       delete[] encryption->signature;
   4391       encryption->signature = NULL;
   4392       encryption->signature_len = 0;
   4393 
   4394       if (size <= 0)
   4395         return E_FILE_FORMAT_INVALID;
   4396 
   4397       const size_t buflen = static_cast<size_t>(size);
   4398       unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
   4399       if (buf == NULL)
   4400         return -1;
   4401 
   4402       const int read_status =
   4403           pReader->Read(pos, static_cast<long>(buflen), buf);
   4404       if (read_status) {
   4405         delete[] buf;
   4406         return status;
   4407       }
   4408 
   4409       encryption->signature = buf;
   4410       encryption->signature_len = buflen;
   4411     } else if (id == mkvmuxer::kMkvContentSigKeyID) {
   4412       delete[] encryption->sig_key_id;
   4413       encryption->sig_key_id = NULL;
   4414       encryption->sig_key_id_len = 0;
   4415 
   4416       if (size <= 0)
   4417         return E_FILE_FORMAT_INVALID;
   4418 
   4419       const size_t buflen = static_cast<size_t>(size);
   4420       unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
   4421       if (buf == NULL)
   4422         return -1;
   4423 
   4424       const int read_status =
   4425           pReader->Read(pos, static_cast<long>(buflen), buf);
   4426       if (read_status) {
   4427         delete[] buf;
   4428         return status;
   4429       }
   4430 
   4431       encryption->sig_key_id = buf;
   4432       encryption->sig_key_id_len = buflen;
   4433     } else if (id == mkvmuxer::kMkvContentSigAlgo) {
   4434       encryption->sig_algo = UnserializeUInt(pReader, pos, size);
   4435     } else if (id == mkvmuxer::kMkvContentSigHashAlgo) {
   4436       encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size);
   4437     } else if (id == mkvmuxer::kMkvContentEncAESSettings) {
   4438       const long status = ParseContentEncAESSettingsEntry(
   4439           pos, size, pReader, &encryption->aes_settings);
   4440       if (status)
   4441         return status;
   4442     }
   4443 
   4444     pos += size;  // consume payload
   4445     if (pos > stop)
   4446       return E_FILE_FORMAT_INVALID;
   4447   }
   4448 
   4449   return 0;
   4450 }
   4451 
   4452 Track::Track(Segment* pSegment, long long element_start, long long element_size)
   4453     : m_pSegment(pSegment),
   4454       m_element_start(element_start),
   4455       m_element_size(element_size),
   4456       content_encoding_entries_(NULL),
   4457       content_encoding_entries_end_(NULL) {}
   4458 
   4459 Track::~Track() {
   4460   Info& info = const_cast<Info&>(m_info);
   4461   info.Clear();
   4462 
   4463   ContentEncoding** i = content_encoding_entries_;
   4464   ContentEncoding** const j = content_encoding_entries_end_;
   4465 
   4466   while (i != j) {
   4467     ContentEncoding* const encoding = *i++;
   4468     delete encoding;
   4469   }
   4470 
   4471   delete[] content_encoding_entries_;
   4472 }
   4473 
   4474 long Track::Create(Segment* pSegment, const Info& info, long long element_start,
   4475                    long long element_size, Track*& pResult) {
   4476   if (pResult)
   4477     return -1;
   4478 
   4479   Track* const pTrack =
   4480       new (std::nothrow) Track(pSegment, element_start, element_size);
   4481 
   4482   if (pTrack == NULL)
   4483     return -1;  // generic error
   4484 
   4485   const int status = info.Copy(pTrack->m_info);
   4486 
   4487   if (status) {  // error
   4488     delete pTrack;
   4489     return status;
   4490   }
   4491 
   4492   pResult = pTrack;
   4493   return 0;  // success
   4494 }
   4495 
   4496 Track::Info::Info()
   4497     : uid(0),
   4498       defaultDuration(0),
   4499       codecDelay(0),
   4500       seekPreRoll(0),
   4501       nameAsUTF8(NULL),
   4502       language(NULL),
   4503       codecId(NULL),
   4504       codecNameAsUTF8(NULL),
   4505       codecPrivate(NULL),
   4506       codecPrivateSize(0),
   4507       lacing(false) {}
   4508 
   4509 Track::Info::~Info() { Clear(); }
   4510 
   4511 void Track::Info::Clear() {
   4512   delete[] nameAsUTF8;
   4513   nameAsUTF8 = NULL;
   4514 
   4515   delete[] language;
   4516   language = NULL;
   4517 
   4518   delete[] codecId;
   4519   codecId = NULL;
   4520 
   4521   delete[] codecPrivate;
   4522   codecPrivate = NULL;
   4523   codecPrivateSize = 0;
   4524 
   4525   delete[] codecNameAsUTF8;
   4526   codecNameAsUTF8 = NULL;
   4527 }
   4528 
   4529 int Track::Info::CopyStr(char* Info::*str, Info& dst_) const {
   4530   if (str == static_cast<char * Info::*>(NULL))
   4531     return -1;
   4532 
   4533   char*& dst = dst_.*str;
   4534 
   4535   if (dst)  // should be NULL already
   4536     return -1;
   4537 
   4538   const char* const src = this->*str;
   4539 
   4540   if (src == NULL)
   4541     return 0;
   4542 
   4543   const size_t len = strlen(src);
   4544 
   4545   dst = SafeArrayAlloc<char>(1, len + 1);
   4546 
   4547   if (dst == NULL)
   4548     return -1;
   4549 
   4550   strcpy(dst, src);
   4551 
   4552   return 0;
   4553 }
   4554 
   4555 int Track::Info::Copy(Info& dst) const {
   4556   if (&dst == this)
   4557     return 0;
   4558 
   4559   dst.type = type;
   4560   dst.number = number;
   4561   dst.defaultDuration = defaultDuration;
   4562   dst.codecDelay = codecDelay;
   4563   dst.seekPreRoll = seekPreRoll;
   4564   dst.uid = uid;
   4565   dst.lacing = lacing;
   4566   dst.settings = settings;
   4567 
   4568   // We now copy the string member variables from src to dst.
   4569   // This involves memory allocation so in principle the operation
   4570   // can fail (indeed, that's why we have Info::Copy), so we must
   4571   // report this to the caller.  An error return from this function
   4572   // therefore implies that the copy was only partially successful.
   4573 
   4574   if (int status = CopyStr(&Info::nameAsUTF8, dst))
   4575     return status;
   4576 
   4577   if (int status = CopyStr(&Info::language, dst))
   4578     return status;
   4579 
   4580   if (int status = CopyStr(&Info::codecId, dst))
   4581     return status;
   4582 
   4583   if (int status = CopyStr(&Info::codecNameAsUTF8, dst))
   4584     return status;
   4585 
   4586   if (codecPrivateSize > 0) {
   4587     if (codecPrivate == NULL)
   4588       return -1;
   4589 
   4590     if (dst.codecPrivate)
   4591       return -1;
   4592 
   4593     if (dst.codecPrivateSize != 0)
   4594       return -1;
   4595 
   4596     dst.codecPrivate = SafeArrayAlloc<unsigned char>(1, codecPrivateSize);
   4597 
   4598     if (dst.codecPrivate == NULL)
   4599       return -1;
   4600 
   4601     memcpy(dst.codecPrivate, codecPrivate, codecPrivateSize);
   4602     dst.codecPrivateSize = codecPrivateSize;
   4603   }
   4604 
   4605   return 0;
   4606 }
   4607 
   4608 const BlockEntry* Track::GetEOS() const { return &m_eos; }
   4609 
   4610 long Track::GetType() const { return m_info.type; }
   4611 
   4612 long Track::GetNumber() const { return m_info.number; }
   4613 
   4614 unsigned long long Track::GetUid() const { return m_info.uid; }
   4615 
   4616 const char* Track::GetNameAsUTF8() const { return m_info.nameAsUTF8; }
   4617 
   4618 const char* Track::GetLanguage() const { return m_info.language; }
   4619 
   4620 const char* Track::GetCodecNameAsUTF8() const { return m_info.codecNameAsUTF8; }
   4621 
   4622 const char* Track::GetCodecId() const { return m_info.codecId; }
   4623 
   4624 const unsigned char* Track::GetCodecPrivate(size_t& size) const {
   4625   size = m_info.codecPrivateSize;
   4626   return m_info.codecPrivate;
   4627 }
   4628 
   4629 bool Track::GetLacing() const { return m_info.lacing; }
   4630 
   4631 unsigned long long Track::GetDefaultDuration() const {
   4632   return m_info.defaultDuration;
   4633 }
   4634 
   4635 unsigned long long Track::GetCodecDelay() const { return m_info.codecDelay; }
   4636 
   4637 unsigned long long Track::GetSeekPreRoll() const { return m_info.seekPreRoll; }
   4638 
   4639 long Track::GetFirst(const BlockEntry*& pBlockEntry) const {
   4640   const Cluster* pCluster = m_pSegment->GetFirst();
   4641 
   4642   for (int i = 0;;) {
   4643     if (pCluster == NULL) {
   4644       pBlockEntry = GetEOS();
   4645       return 1;
   4646     }
   4647 
   4648     if (pCluster->EOS()) {
   4649       if (m_pSegment->DoneParsing()) {
   4650         pBlockEntry = GetEOS();
   4651         return 1;
   4652       }
   4653 
   4654       pBlockEntry = 0;
   4655       return E_BUFFER_NOT_FULL;
   4656     }
   4657 
   4658     long status = pCluster->GetFirst(pBlockEntry);
   4659 
   4660     if (status < 0)  // error
   4661       return status;
   4662 
   4663     if (pBlockEntry == 0) {  // empty cluster
   4664       pCluster = m_pSegment->GetNext(pCluster);
   4665       continue;
   4666     }
   4667 
   4668     for (;;) {
   4669       const Block* const pBlock = pBlockEntry->GetBlock();
   4670       assert(pBlock);
   4671 
   4672       const long long tn = pBlock->GetTrackNumber();
   4673 
   4674       if ((tn == m_info.number) && VetEntry(pBlockEntry))
   4675         return 0;
   4676 
   4677       const BlockEntry* pNextEntry;
   4678 
   4679       status = pCluster->GetNext(pBlockEntry, pNextEntry);
   4680 
   4681       if (status < 0)  // error
   4682         return status;
   4683 
   4684       if (pNextEntry == 0)
   4685         break;
   4686 
   4687       pBlockEntry = pNextEntry;
   4688     }
   4689 
   4690     ++i;
   4691 
   4692     if (i >= 100)
   4693       break;
   4694 
   4695     pCluster = m_pSegment->GetNext(pCluster);
   4696   }
   4697 
   4698   // NOTE: if we get here, it means that we didn't find a block with
   4699   // a matching track number.  We interpret that as an error (which
   4700   // might be too conservative).
   4701 
   4702   pBlockEntry = GetEOS();  // so we can return a non-NULL value
   4703   return 1;
   4704 }
   4705 
   4706 long Track::GetNext(const BlockEntry* pCurrEntry,
   4707                     const BlockEntry*& pNextEntry) const {
   4708   assert(pCurrEntry);
   4709   assert(!pCurrEntry->EOS());  //?
   4710 
   4711   const Block* const pCurrBlock = pCurrEntry->GetBlock();
   4712   assert(pCurrBlock && pCurrBlock->GetTrackNumber() == m_info.number);
   4713   if (!pCurrBlock || pCurrBlock->GetTrackNumber() != m_info.number)
   4714     return -1;
   4715 
   4716   const Cluster* pCluster = pCurrEntry->GetCluster();
   4717   assert(pCluster);
   4718   assert(!pCluster->EOS());
   4719 
   4720   long status = pCluster->GetNext(pCurrEntry, pNextEntry);
   4721 
   4722   if (status < 0)  // error
   4723     return status;
   4724 
   4725   for (int i = 0;;) {
   4726     while (pNextEntry) {
   4727       const Block* const pNextBlock = pNextEntry->GetBlock();
   4728       assert(pNextBlock);
   4729 
   4730       if (pNextBlock->GetTrackNumber() == m_info.number)
   4731         return 0;
   4732 
   4733       pCurrEntry = pNextEntry;
   4734 
   4735       status = pCluster->GetNext(pCurrEntry, pNextEntry);
   4736 
   4737       if (status < 0)  // error
   4738         return status;
   4739     }
   4740 
   4741     pCluster = m_pSegment->GetNext(pCluster);
   4742 
   4743     if (pCluster == NULL) {
   4744       pNextEntry = GetEOS();
   4745       return 1;
   4746     }
   4747 
   4748     if (pCluster->EOS()) {
   4749       if (m_pSegment->DoneParsing()) {
   4750         pNextEntry = GetEOS();
   4751         return 1;
   4752       }
   4753 
   4754       // TODO: there is a potential O(n^2) problem here: we tell the
   4755       // caller to (pre)load another cluster, which he does, but then he
   4756       // calls GetNext again, which repeats the same search.  This is
   4757       // a pathological case, since the only way it can happen is if
   4758       // there exists a long sequence of clusters none of which contain a
   4759       // block from this track.  One way around this problem is for the
   4760       // caller to be smarter when he loads another cluster: don't call
   4761       // us back until you have a cluster that contains a block from this
   4762       // track. (Of course, that's not cheap either, since our caller
   4763       // would have to scan the each cluster as it's loaded, so that
   4764       // would just push back the problem.)
   4765 
   4766       pNextEntry = NULL;
   4767       return E_BUFFER_NOT_FULL;
   4768     }
   4769 
   4770     status = pCluster->GetFirst(pNextEntry);
   4771 
   4772     if (status < 0)  // error
   4773       return status;
   4774 
   4775     if (pNextEntry == NULL)  // empty cluster
   4776       continue;
   4777 
   4778     ++i;
   4779 
   4780     if (i >= 100)
   4781       break;
   4782   }
   4783 
   4784   // NOTE: if we get here, it means that we didn't find a block with
   4785   // a matching track number after lots of searching, so we give
   4786   // up trying.
   4787 
   4788   pNextEntry = GetEOS();  // so we can return a non-NULL value
   4789   return 1;
   4790 }
   4791 
   4792 bool Track::VetEntry(const BlockEntry* pBlockEntry) const {
   4793   assert(pBlockEntry);
   4794   const Block* const pBlock = pBlockEntry->GetBlock();
   4795   assert(pBlock);
   4796   assert(pBlock->GetTrackNumber() == m_info.number);
   4797   if (!pBlock || pBlock->GetTrackNumber() != m_info.number)
   4798     return false;
   4799 
   4800   // This function is used during a seek to determine whether the
   4801   // frame is a valid seek target.  This default function simply
   4802   // returns true, which means all frames are valid seek targets.
   4803   // It gets overridden by the VideoTrack class, because only video
   4804   // keyframes can be used as seek target.
   4805 
   4806   return true;
   4807 }
   4808 
   4809 long Track::Seek(long long time_ns, const BlockEntry*& pResult) const {
   4810   const long status = GetFirst(pResult);
   4811 
   4812   if (status < 0)  // buffer underflow, etc
   4813     return status;
   4814 
   4815   assert(pResult);
   4816 
   4817   if (pResult->EOS())
   4818     return 0;
   4819 
   4820   const Cluster* pCluster = pResult->GetCluster();
   4821   assert(pCluster);
   4822   assert(pCluster->GetIndex() >= 0);
   4823 
   4824   if (time_ns <= pResult->GetBlock()->GetTime(pCluster))
   4825     return 0;
   4826 
   4827   Cluster** const clusters = m_pSegment->m_clusters;
   4828   assert(clusters);
   4829 
   4830   const long count = m_pSegment->GetCount();  // loaded only, not preloaded
   4831   assert(count > 0);
   4832 
   4833   Cluster** const i = clusters + pCluster->GetIndex();
   4834   assert(i);
   4835   assert(*i == pCluster);
   4836   assert(pCluster->GetTime() <= time_ns);
   4837 
   4838   Cluster** const j = clusters + count;
   4839 
   4840   Cluster** lo = i;
   4841   Cluster** hi = j;
   4842 
   4843   while (lo < hi) {
   4844     // INVARIANT:
   4845     //[i, lo) <= time_ns
   4846     //[lo, hi) ?
   4847     //[hi, j)  > time_ns
   4848 
   4849     Cluster** const mid = lo + (hi - lo) / 2;
   4850     assert(mid < hi);
   4851 
   4852     pCluster = *mid;
   4853     assert(pCluster);
   4854     assert(pCluster->GetIndex() >= 0);
   4855     assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters));
   4856 
   4857     const long long t = pCluster->GetTime();
   4858 
   4859     if (t <= time_ns)
   4860       lo = mid + 1;
   4861     else
   4862       hi = mid;
   4863 
   4864     assert(lo <= hi);
   4865   }
   4866 
   4867   assert(lo == hi);
   4868   assert(lo > i);
   4869   assert(lo <= j);
   4870 
   4871   while (lo > i) {
   4872     pCluster = *--lo;
   4873     assert(pCluster);
   4874     assert(pCluster->GetTime() <= time_ns);
   4875 
   4876     pResult = pCluster->GetEntry(this);
   4877 
   4878     if ((pResult != 0) && !pResult->EOS())
   4879       return 0;
   4880 
   4881     // landed on empty cluster (no entries)
   4882   }
   4883 
   4884   pResult = GetEOS();  // weird
   4885   return 0;
   4886 }
   4887 
   4888 const ContentEncoding* Track::GetContentEncodingByIndex(
   4889     unsigned long idx) const {
   4890   const ptrdiff_t count =
   4891       content_encoding_entries_end_ - content_encoding_entries_;
   4892   assert(count >= 0);
   4893 
   4894   if (idx >= static_cast<unsigned long>(count))
   4895     return NULL;
   4896 
   4897   return content_encoding_entries_[idx];
   4898 }
   4899 
   4900 unsigned long Track::GetContentEncodingCount() const {
   4901   const ptrdiff_t count =
   4902       content_encoding_entries_end_ - content_encoding_entries_;
   4903   assert(count >= 0);
   4904 
   4905   return static_cast<unsigned long>(count);
   4906 }
   4907 
   4908 long Track::ParseContentEncodingsEntry(long long start, long long size) {
   4909   IMkvReader* const pReader = m_pSegment->m_pReader;
   4910   assert(pReader);
   4911 
   4912   long long pos = start;
   4913   const long long stop = start + size;
   4914 
   4915   // Count ContentEncoding elements.
   4916   int count = 0;
   4917   while (pos < stop) {
   4918     long long id, size;
   4919     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   4920     if (status < 0)  // error
   4921       return status;
   4922 
   4923     // pos now designates start of element
   4924     if (id == mkvmuxer::kMkvContentEncoding)
   4925       ++count;
   4926 
   4927     pos += size;  // consume payload
   4928     if (pos > stop)
   4929       return E_FILE_FORMAT_INVALID;
   4930   }
   4931 
   4932   if (count <= 0)
   4933     return -1;
   4934 
   4935   content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
   4936   if (!content_encoding_entries_)
   4937     return -1;
   4938 
   4939   content_encoding_entries_end_ = content_encoding_entries_;
   4940 
   4941   pos = start;
   4942   while (pos < stop) {
   4943     long long id, size;
   4944     long status = ParseElementHeader(pReader, pos, stop, id, size);
   4945     if (status < 0)  // error
   4946       return status;
   4947 
   4948     // pos now designates start of element
   4949     if (id == mkvmuxer::kMkvContentEncoding) {
   4950       ContentEncoding* const content_encoding =
   4951           new (std::nothrow) ContentEncoding();
   4952       if (!content_encoding)
   4953         return -1;
   4954 
   4955       status = content_encoding->ParseContentEncodingEntry(pos, size, pReader);
   4956       if (status) {
   4957         delete content_encoding;
   4958         return status;
   4959       }
   4960 
   4961       *content_encoding_entries_end_++ = content_encoding;
   4962     }
   4963 
   4964     pos += size;  // consume payload
   4965     if (pos > stop)
   4966       return E_FILE_FORMAT_INVALID;
   4967   }
   4968 
   4969   if (pos != stop)
   4970     return E_FILE_FORMAT_INVALID;
   4971 
   4972   return 0;
   4973 }
   4974 
   4975 Track::EOSBlock::EOSBlock() : BlockEntry(NULL, LONG_MIN) {}
   4976 
   4977 BlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; }
   4978 
   4979 const Block* Track::EOSBlock::GetBlock() const { return NULL; }
   4980 
   4981 VideoTrack::VideoTrack(Segment* pSegment, long long element_start,
   4982                        long long element_size)
   4983     : Track(pSegment, element_start, element_size) {}
   4984 
   4985 long VideoTrack::Parse(Segment* pSegment, const Info& info,
   4986                        long long element_start, long long element_size,
   4987                        VideoTrack*& pResult) {
   4988   if (pResult)
   4989     return -1;
   4990 
   4991   if (info.type != Track::kVideo)
   4992     return -1;
   4993 
   4994   long long width = 0;
   4995   long long height = 0;
   4996   long long display_width = 0;
   4997   long long display_height = 0;
   4998   long long display_unit = 0;
   4999   long long stereo_mode = 0;
   5000 
   5001   double rate = 0.0;
   5002 
   5003   IMkvReader* const pReader = pSegment->m_pReader;
   5004 
   5005   const Settings& s = info.settings;
   5006   assert(s.start >= 0);
   5007   assert(s.size >= 0);
   5008 
   5009   long long pos = s.start;
   5010   assert(pos >= 0);
   5011 
   5012   const long long stop = pos + s.size;
   5013 
   5014   while (pos < stop) {
   5015     long long id, size;
   5016 
   5017     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   5018 
   5019     if (status < 0)  // error
   5020       return status;
   5021 
   5022     if (id == mkvmuxer::kMkvPixelWidth) {
   5023       width = UnserializeUInt(pReader, pos, size);
   5024 
   5025       if (width <= 0)
   5026         return E_FILE_FORMAT_INVALID;
   5027     } else if (id == mkvmuxer::kMkvPixelHeight) {
   5028       height = UnserializeUInt(pReader, pos, size);
   5029 
   5030       if (height <= 0)
   5031         return E_FILE_FORMAT_INVALID;
   5032     } else if (id == mkvmuxer::kMkvDisplayWidth) {
   5033       display_width = UnserializeUInt(pReader, pos, size);
   5034 
   5035       if (display_width <= 0)
   5036         return E_FILE_FORMAT_INVALID;
   5037     } else if (id == mkvmuxer::kMkvDisplayHeight) {
   5038       display_height = UnserializeUInt(pReader, pos, size);
   5039 
   5040       if (display_height <= 0)
   5041         return E_FILE_FORMAT_INVALID;
   5042     } else if (id == mkvmuxer::kMkvDisplayUnit) {
   5043       display_unit = UnserializeUInt(pReader, pos, size);
   5044 
   5045       if (display_unit < 0)
   5046         return E_FILE_FORMAT_INVALID;
   5047     } else if (id == mkvmuxer::kMkvStereoMode) {
   5048       stereo_mode = UnserializeUInt(pReader, pos, size);
   5049 
   5050       if (stereo_mode < 0)
   5051         return E_FILE_FORMAT_INVALID;
   5052     } else if (id == mkvmuxer::kMkvFrameRate) {
   5053       const long status = UnserializeFloat(pReader, pos, size, rate);
   5054 
   5055       if (status < 0)
   5056         return status;
   5057 
   5058       if (rate <= 0)
   5059         return E_FILE_FORMAT_INVALID;
   5060     }
   5061 
   5062     pos += size;  // consume payload
   5063     if (pos > stop)
   5064       return E_FILE_FORMAT_INVALID;
   5065   }
   5066 
   5067   if (pos != stop)
   5068     return E_FILE_FORMAT_INVALID;
   5069 
   5070   VideoTrack* const pTrack =
   5071       new (std::nothrow) VideoTrack(pSegment, element_start, element_size);
   5072 
   5073   if (pTrack == NULL)
   5074     return -1;  // generic error
   5075 
   5076   const int status = info.Copy(pTrack->m_info);
   5077 
   5078   if (status) {  // error
   5079     delete pTrack;
   5080     return status;
   5081   }
   5082 
   5083   pTrack->m_width = width;
   5084   pTrack->m_height = height;
   5085   pTrack->m_display_width = display_width;
   5086   pTrack->m_display_height = display_height;
   5087   pTrack->m_display_unit = display_unit;
   5088   pTrack->m_stereo_mode = stereo_mode;
   5089   pTrack->m_rate = rate;
   5090 
   5091   pResult = pTrack;
   5092   return 0;  // success
   5093 }
   5094 
   5095 bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const {
   5096   return Track::VetEntry(pBlockEntry) && pBlockEntry->GetBlock()->IsKey();
   5097 }
   5098 
   5099 long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {
   5100   const long status = GetFirst(pResult);
   5101 
   5102   if (status < 0)  // buffer underflow, etc
   5103     return status;
   5104 
   5105   assert(pResult);
   5106 
   5107   if (pResult->EOS())
   5108     return 0;
   5109 
   5110   const Cluster* pCluster = pResult->GetCluster();
   5111   assert(pCluster);
   5112   assert(pCluster->GetIndex() >= 0);
   5113 
   5114   if (time_ns <= pResult->GetBlock()->GetTime(pCluster))
   5115     return 0;
   5116 
   5117   Cluster** const clusters = m_pSegment->m_clusters;
   5118   assert(clusters);
   5119 
   5120   const long count = m_pSegment->GetCount();  // loaded only, not pre-loaded
   5121   assert(count > 0);
   5122 
   5123   Cluster** const i = clusters + pCluster->GetIndex();
   5124   assert(i);
   5125   assert(*i == pCluster);
   5126   assert(pCluster->GetTime() <= time_ns);
   5127 
   5128   Cluster** const j = clusters + count;
   5129 
   5130   Cluster** lo = i;
   5131   Cluster** hi = j;
   5132 
   5133   while (lo < hi) {
   5134     // INVARIANT:
   5135     //[i, lo) <= time_ns
   5136     //[lo, hi) ?
   5137     //[hi, j)  > time_ns
   5138 
   5139     Cluster** const mid = lo + (hi - lo) / 2;
   5140     assert(mid < hi);
   5141 
   5142     pCluster = *mid;
   5143     assert(pCluster);
   5144     assert(pCluster->GetIndex() >= 0);
   5145     assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters));
   5146 
   5147     const long long t = pCluster->GetTime();
   5148 
   5149     if (t <= time_ns)
   5150       lo = mid + 1;
   5151     else
   5152       hi = mid;
   5153 
   5154     assert(lo <= hi);
   5155   }
   5156 
   5157   assert(lo == hi);
   5158   assert(lo > i);
   5159   assert(lo <= j);
   5160 
   5161   pCluster = *--lo;
   5162   assert(pCluster);
   5163   assert(pCluster->GetTime() <= time_ns);
   5164 
   5165   pResult = pCluster->GetEntry(this, time_ns);
   5166 
   5167   if ((pResult != 0) && !pResult->EOS())  // found a keyframe
   5168     return 0;
   5169 
   5170   while (lo != i) {
   5171     pCluster = *--lo;
   5172     assert(pCluster);
   5173     assert(pCluster->GetTime() <= time_ns);
   5174 
   5175     pResult = pCluster->GetEntry(this, time_ns);
   5176 
   5177     if ((pResult != 0) && !pResult->EOS())
   5178       return 0;
   5179   }
   5180 
   5181   // weird: we're on the first cluster, but no keyframe found
   5182   // should never happen but we must return something anyway
   5183 
   5184   pResult = GetEOS();
   5185   return 0;
   5186 }
   5187 
   5188 long long VideoTrack::GetWidth() const { return m_width; }
   5189 
   5190 long long VideoTrack::GetHeight() const { return m_height; }
   5191 
   5192 long long VideoTrack::GetDisplayWidth() const {
   5193   return m_display_width > 0 ? m_display_width : GetWidth();
   5194 }
   5195 
   5196 long long VideoTrack::GetDisplayHeight() const {
   5197   return m_display_height > 0 ? m_display_height : GetHeight();
   5198 }
   5199 
   5200 long long VideoTrack::GetDisplayUnit() const { return m_display_unit; }
   5201 
   5202 long long VideoTrack::GetStereoMode() const { return m_stereo_mode; }
   5203 
   5204 double VideoTrack::GetFrameRate() const { return m_rate; }
   5205 
   5206 AudioTrack::AudioTrack(Segment* pSegment, long long element_start,
   5207                        long long element_size)
   5208     : Track(pSegment, element_start, element_size) {}
   5209 
   5210 long AudioTrack::Parse(Segment* pSegment, const Info& info,
   5211                        long long element_start, long long element_size,
   5212                        AudioTrack*& pResult) {
   5213   if (pResult)
   5214     return -1;
   5215 
   5216   if (info.type != Track::kAudio)
   5217     return -1;
   5218 
   5219   IMkvReader* const pReader = pSegment->m_pReader;
   5220 
   5221   const Settings& s = info.settings;
   5222   assert(s.start >= 0);
   5223   assert(s.size >= 0);
   5224 
   5225   long long pos = s.start;
   5226   assert(pos >= 0);
   5227 
   5228   const long long stop = pos + s.size;
   5229 
   5230   double rate = 8000.0;  // MKV default
   5231   long long channels = 1;
   5232   long long bit_depth = 0;
   5233 
   5234   while (pos < stop) {
   5235     long long id, size;
   5236 
   5237     long status = ParseElementHeader(pReader, pos, stop, id, size);
   5238 
   5239     if (status < 0)  // error
   5240       return status;
   5241 
   5242     if (id == mkvmuxer::kMkvSamplingFrequency) {
   5243       status = UnserializeFloat(pReader, pos, size, rate);
   5244 
   5245       if (status < 0)
   5246         return status;
   5247 
   5248       if (rate <= 0)
   5249         return E_FILE_FORMAT_INVALID;
   5250     } else if (id == mkvmuxer::kMkvChannels) {
   5251       channels = UnserializeUInt(pReader, pos, size);
   5252 
   5253       if (channels <= 0)
   5254         return E_FILE_FORMAT_INVALID;
   5255     } else if (id == mkvmuxer::kMkvBitDepth) {
   5256       bit_depth = UnserializeUInt(pReader, pos, size);
   5257 
   5258       if (bit_depth <= 0)
   5259         return E_FILE_FORMAT_INVALID;
   5260     }
   5261 
   5262     pos += size;  // consume payload
   5263     if (pos > stop)
   5264       return E_FILE_FORMAT_INVALID;
   5265   }
   5266 
   5267   if (pos != stop)
   5268     return E_FILE_FORMAT_INVALID;
   5269 
   5270   AudioTrack* const pTrack =
   5271       new (std::nothrow) AudioTrack(pSegment, element_start, element_size);
   5272 
   5273   if (pTrack == NULL)
   5274     return -1;  // generic error
   5275 
   5276   const int status = info.Copy(pTrack->m_info);
   5277 
   5278   if (status) {
   5279     delete pTrack;
   5280     return status;
   5281   }
   5282 
   5283   pTrack->m_rate = rate;
   5284   pTrack->m_channels = channels;
   5285   pTrack->m_bitDepth = bit_depth;
   5286 
   5287   pResult = pTrack;
   5288   return 0;  // success
   5289 }
   5290 
   5291 double AudioTrack::GetSamplingRate() const { return m_rate; }
   5292 
   5293 long long AudioTrack::GetChannels() const { return m_channels; }
   5294 
   5295 long long AudioTrack::GetBitDepth() const { return m_bitDepth; }
   5296 
   5297 Tracks::Tracks(Segment* pSegment, long long start, long long size_,
   5298                long long element_start, long long element_size)
   5299     : m_pSegment(pSegment),
   5300       m_start(start),
   5301       m_size(size_),
   5302       m_element_start(element_start),
   5303       m_element_size(element_size),
   5304       m_trackEntries(NULL),
   5305       m_trackEntriesEnd(NULL) {}
   5306 
   5307 long Tracks::Parse() {
   5308   assert(m_trackEntries == NULL);
   5309   assert(m_trackEntriesEnd == NULL);
   5310 
   5311   const long long stop = m_start + m_size;
   5312   IMkvReader* const pReader = m_pSegment->m_pReader;
   5313 
   5314   int count = 0;
   5315   long long pos = m_start;
   5316 
   5317   while (pos < stop) {
   5318     long long id, size;
   5319 
   5320     const long status = ParseElementHeader(pReader, pos, stop, id, size);
   5321 
   5322     if (status < 0)  // error
   5323       return status;
   5324 
   5325     if (size == 0)  // weird
   5326       continue;
   5327 
   5328     if (id == mkvmuxer::kMkvTrackEntry)
   5329       ++count;
   5330 
   5331     pos += size;  // consume payload
   5332     if (pos > stop)
   5333       return E_FILE_FORMAT_INVALID;
   5334   }
   5335 
   5336   if (pos != stop)
   5337     return E_FILE_FORMAT_INVALID;
   5338 
   5339   if (count <= 0)
   5340     return 0;  // success
   5341 
   5342   m_trackEntries = new (std::nothrow) Track*[count];
   5343 
   5344   if (m_trackEntries == NULL)
   5345     return -1;
   5346 
   5347   m_trackEntriesEnd = m_trackEntries;
   5348 
   5349   pos = m_start;
   5350 
   5351   while (pos < stop) {
   5352     const long long element_start = pos;
   5353 
   5354     long long id, payload_size;
   5355 
   5356     const long status =
   5357         ParseElementHeader(pReader, pos, stop, id, payload_size);
   5358 
   5359     if (status < 0)  // error
   5360       return status;
   5361 
   5362     if (payload_size == 0)  // weird
   5363       continue;
   5364 
   5365     const long long payload_stop = pos + payload_size;
   5366     assert(payload_stop <= stop);  // checked in ParseElement
   5367 
   5368     const long long element_size = payload_stop - element_start;
   5369 
   5370     if (id == mkvmuxer::kMkvTrackEntry) {
   5371       Track*& pTrack = *m_trackEntriesEnd;
   5372       pTrack = NULL;
   5373 
   5374       const long status = ParseTrackEntry(pos, payload_size, element_start,
   5375                                           element_size, pTrack);
   5376       if (status)
   5377         return status;
   5378 
   5379       if (pTrack)
   5380         ++m_trackEntriesEnd;
   5381     }
   5382 
   5383     pos = payload_stop;
   5384     if (pos > stop)
   5385       return E_FILE_FORMAT_INVALID;
   5386   }
   5387 
   5388   if (pos != stop)
   5389     return E_FILE_FORMAT_INVALID;
   5390 
   5391   return 0;  // success
   5392 }
   5393 
   5394 unsigned long Tracks::GetTracksCount() const {
   5395   const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
   5396   assert(result >= 0);
   5397 
   5398   return static_cast<unsigned long>(result);
   5399 }
   5400 
   5401 long Tracks::ParseTrackEntry(long long track_start, long long track_size,
   5402                              long long element_start, long long element_size,
   5403                              Track*& pResult) const {
   5404   if (pResult)
   5405     return -1;
   5406 
   5407   IMkvReader* const pReader = m_pSegment->m_pReader;
   5408 
   5409   long long pos = track_start;
   5410   const long long track_stop = track_start + track_size;
   5411 
   5412   Track::Info info;
   5413 
   5414   info.type = 0;
   5415   info.number = 0;
   5416   info.uid = 0;
   5417   info.defaultDuration = 0;
   5418 
   5419   Track::Settings v;
   5420   v.start = -1;
   5421   v.size = -1;
   5422 
   5423   Track::Settings a;
   5424   a.start = -1;
   5425   a.size = -1;
   5426 
   5427   Track::Settings e;  // content_encodings_settings;
   5428   e.start = -1;
   5429   e.size = -1;
   5430 
   5431   long long lacing = 1;  // default is true
   5432 
   5433   while (pos < track_stop) {
   5434     long long id, size;
   5435 
   5436     const long status = ParseElementHeader(pReader, pos, track_stop, id, size);
   5437 
   5438     if (status < 0)  // error
   5439       return status;
   5440 
   5441     if (size < 0)
   5442       return E_FILE_FORMAT_INVALID;
   5443 
   5444     const long long start = pos;
   5445 
   5446     if (id == mkvmuxer::kMkvVideo) {
   5447       v.start = start;
   5448       v.size = size;
   5449     } else if (id == mkvmuxer::kMkvAudio) {
   5450       a.start = start;
   5451       a.size = size;
   5452     } else if (id == mkvmuxer::kMkvContentEncodings) {
   5453       e.start = start;
   5454       e.size = size;
   5455     } else if (id == mkvmuxer::kMkvTrackUID) {
   5456       if (size > 8)
   5457         return E_FILE_FORMAT_INVALID;
   5458 
   5459       info.uid = 0;
   5460 
   5461       long long pos_ = start;
   5462       const long long pos_end = start + size;
   5463 
   5464       while (pos_ != pos_end) {
   5465         unsigned char b;
   5466 
   5467         const int status = pReader->Read(pos_, 1, &b);
   5468 
   5469         if (status)
   5470           return status;
   5471 
   5472         info.uid <<= 8;
   5473         info.uid |= b;
   5474 
   5475         ++pos_;
   5476       }
   5477     } else if (id == mkvmuxer::kMkvTrackNumber) {
   5478       const long long num = UnserializeUInt(pReader, pos, size);
   5479 
   5480       if ((num <= 0) || (num > 127))
   5481         return E_FILE_FORMAT_INVALID;
   5482 
   5483       info.number = static_cast<long>(num);
   5484     } else if (id == mkvmuxer::kMkvTrackType) {
   5485       const long long type = UnserializeUInt(pReader, pos, size);
   5486 
   5487       if ((type <= 0) || (type > 254))
   5488         return E_FILE_FORMAT_INVALID;
   5489 
   5490       info.type = static_cast<long>(type);
   5491     } else if (id == mkvmuxer::kMkvName) {
   5492       const long status =
   5493           UnserializeString(pReader, pos, size, info.nameAsUTF8);
   5494 
   5495       if (status)
   5496         return status;
   5497     } else if (id == mkvmuxer::kMkvLanguage) {
   5498       const long status = UnserializeString(pReader, pos, size, info.language);
   5499 
   5500       if (status)
   5501         return status;
   5502     } else if (id == mkvmuxer::kMkvDefaultDuration) {
   5503       const long long duration = UnserializeUInt(pReader, pos, size);
   5504 
   5505       if (duration < 0)
   5506         return E_FILE_FORMAT_INVALID;
   5507 
   5508       info.defaultDuration = static_cast<unsigned long long>(duration);
   5509     } else if (id == mkvmuxer::kMkvCodecID) {
   5510       const long status = UnserializeString(pReader, pos, size, info.codecId);
   5511 
   5512       if (status)
   5513         return status;
   5514     } else if (id == mkvmuxer::kMkvFlagLacing) {
   5515       lacing = UnserializeUInt(pReader, pos, size);
   5516 
   5517       if ((lacing < 0) || (lacing > 1))
   5518         return E_FILE_FORMAT_INVALID;
   5519     } else if (id == mkvmuxer::kMkvCodecPrivate) {
   5520       delete[] info.codecPrivate;
   5521       info.codecPrivate = NULL;
   5522       info.codecPrivateSize = 0;
   5523 
   5524       const size_t buflen = static_cast<size_t>(size);
   5525 
   5526       if (buflen) {
   5527         unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
   5528 
   5529         if (buf == NULL)
   5530           return -1;
   5531 
   5532         const int status = pReader->Read(pos, static_cast<long>(buflen), buf);
   5533 
   5534         if (status) {
   5535           delete[] buf;
   5536           return status;
   5537         }
   5538 
   5539         info.codecPrivate = buf;
   5540         info.codecPrivateSize = buflen;
   5541       }
   5542     } else if (id == mkvmuxer::kMkvCodecName) {
   5543       const long status =
   5544           UnserializeString(pReader, pos, size, info.codecNameAsUTF8);
   5545 
   5546       if (status)
   5547         return status;
   5548     } else if (id == mkvmuxer::kMkvCodecDelay) {
   5549       info.codecDelay = UnserializeUInt(pReader, pos, size);
   5550     } else if (id == mkvmuxer::kMkvSeekPreRoll) {
   5551       info.seekPreRoll = UnserializeUInt(pReader, pos, size);
   5552     }
   5553 
   5554     pos += size;  // consume payload
   5555     if (pos > track_stop)
   5556       return E_FILE_FORMAT_INVALID;
   5557   }
   5558 
   5559   if (pos != track_stop)
   5560     return E_FILE_FORMAT_INVALID;
   5561 
   5562   if (info.number <= 0)  // not specified
   5563     return E_FILE_FORMAT_INVALID;
   5564 
   5565   if (GetTrackByNumber(info.number))
   5566     return E_FILE_FORMAT_INVALID;
   5567 
   5568   if (info.type <= 0)  // not specified
   5569     return E_FILE_FORMAT_INVALID;
   5570 
   5571   info.lacing = (lacing > 0) ? true : false;
   5572 
   5573   if (info.type == Track::kVideo) {
   5574     if (v.start < 0)
   5575       return E_FILE_FORMAT_INVALID;
   5576 
   5577     if (a.start >= 0)
   5578       return E_FILE_FORMAT_INVALID;
   5579 
   5580     info.settings = v;
   5581 
   5582     VideoTrack* pTrack = NULL;
   5583 
   5584     const long status = VideoTrack::Parse(m_pSegment, info, element_start,
   5585                                           element_size, pTrack);
   5586 
   5587     if (status)
   5588       return status;
   5589 
   5590     pResult = pTrack;
   5591     assert(pResult);
   5592 
   5593     if (e.start >= 0)
   5594       pResult->ParseContentEncodingsEntry(e.start, e.size);
   5595   } else if (info.type == Track::kAudio) {
   5596     if (a.start < 0)
   5597       return E_FILE_FORMAT_INVALID;
   5598 
   5599     if (v.start >= 0)
   5600       return E_FILE_FORMAT_INVALID;
   5601 
   5602     info.settings = a;
   5603 
   5604     AudioTrack* pTrack = NULL;
   5605 
   5606     const long status = AudioTrack::Parse(m_pSegment, info, element_start,
   5607                                           element_size, pTrack);
   5608 
   5609     if (status)
   5610       return status;
   5611 
   5612     pResult = pTrack;
   5613     assert(pResult);
   5614 
   5615     if (e.start >= 0)
   5616       pResult->ParseContentEncodingsEntry(e.start, e.size);
   5617   } else {
   5618     // neither video nor audio - probably metadata or subtitles
   5619 
   5620     if (a.start >= 0)
   5621       return E_FILE_FORMAT_INVALID;
   5622 
   5623     if (v.start >= 0)
   5624       return E_FILE_FORMAT_INVALID;
   5625 
   5626     if (info.type == Track::kMetadata && e.start >= 0)
   5627       return E_FILE_FORMAT_INVALID;
   5628 
   5629     info.settings.start = -1;
   5630     info.settings.size = 0;
   5631 
   5632     Track* pTrack = NULL;
   5633 
   5634     const long status =
   5635         Track::Create(m_pSegment, info, element_start, element_size, pTrack);
   5636 
   5637     if (status)
   5638       return status;
   5639 
   5640     pResult = pTrack;
   5641     assert(pResult);
   5642   }
   5643 
   5644   return 0;  // success
   5645 }
   5646 
   5647 Tracks::~Tracks() {
   5648   Track** i = m_trackEntries;
   5649   Track** const j = m_trackEntriesEnd;
   5650 
   5651   while (i != j) {
   5652     Track* const pTrack = *i++;
   5653     delete pTrack;
   5654   }
   5655 
   5656   delete[] m_trackEntries;
   5657 }
   5658 
   5659 const Track* Tracks::GetTrackByNumber(long tn) const {
   5660   if (tn < 0)
   5661     return NULL;
   5662 
   5663   Track** i = m_trackEntries;
   5664   Track** const j = m_trackEntriesEnd;
   5665 
   5666   while (i != j) {
   5667     Track* const pTrack = *i++;
   5668 
   5669     if (pTrack == NULL)
   5670       continue;
   5671 
   5672     if (tn == pTrack->GetNumber())
   5673       return pTrack;
   5674   }
   5675 
   5676   return NULL;  // not found
   5677 }
   5678 
   5679 const Track* Tracks::GetTrackByIndex(unsigned long idx) const {
   5680   const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
   5681 
   5682   if (idx >= static_cast<unsigned long>(count))
   5683     return NULL;
   5684 
   5685   return m_trackEntries[idx];
   5686 }
   5687 
   5688 long Cluster::Load(long long& pos, long& len) const {
   5689   if (m_pSegment == NULL)
   5690     return E_PARSE_FAILED;
   5691 
   5692   if (m_timecode >= 0)  // at least partially loaded
   5693     return 0;
   5694 
   5695   if (m_pos != m_element_start || m_element_size >= 0)
   5696     return E_PARSE_FAILED;
   5697 
   5698   IMkvReader* const pReader = m_pSegment->m_pReader;
   5699   long long total, avail;
   5700   const int status = pReader->Length(&total, &avail);
   5701 
   5702   if (status < 0)  // error
   5703     return status;
   5704 
   5705   if (total >= 0 && (avail > total || m_pos > total))
   5706     return E_FILE_FORMAT_INVALID;
   5707 
   5708   pos = m_pos;
   5709 
   5710   long long cluster_size = -1;
   5711 
   5712   if ((pos + 1) > avail) {
   5713     len = 1;
   5714     return E_BUFFER_NOT_FULL;
   5715   }
   5716 
   5717   long long result = GetUIntLength(pReader, pos, len);
   5718 
   5719   if (result < 0)  // error or underflow
   5720     return static_cast<long>(result);
   5721 
   5722   if (result > 0)
   5723     return E_BUFFER_NOT_FULL;
   5724 
   5725   if ((pos + len) > avail)
   5726     return E_BUFFER_NOT_FULL;
   5727 
   5728   const long long id_ = ReadID(pReader, pos, len);
   5729 
   5730   if (id_ < 0)  // error
   5731     return static_cast<long>(id_);
   5732 
   5733   if (id_ != mkvmuxer::kMkvCluster)
   5734     return E_FILE_FORMAT_INVALID;
   5735 
   5736   pos += len;  // consume id
   5737 
   5738   // read cluster size
   5739 
   5740   if ((pos + 1) > avail) {
   5741     len = 1;
   5742     return E_BUFFER_NOT_FULL;
   5743   }
   5744 
   5745   result = GetUIntLength(pReader, pos, len);
   5746 
   5747   if (result < 0)  // error
   5748     return static_cast<long>(result);
   5749 
   5750   if (result > 0)
   5751     return E_BUFFER_NOT_FULL;
   5752 
   5753   if ((pos + len) > avail)
   5754     return E_BUFFER_NOT_FULL;
   5755 
   5756   const long long size = ReadUInt(pReader, pos, len);
   5757 
   5758   if (size < 0)  // error
   5759     return static_cast<long>(cluster_size);
   5760 
   5761   if (size == 0)
   5762     return E_FILE_FORMAT_INVALID;
   5763 
   5764   pos += len;  // consume length of size of element
   5765 
   5766   const long long unknown_size = (1LL << (7 * len)) - 1;
   5767 
   5768   if (size != unknown_size)
   5769     cluster_size = size;
   5770 
   5771   // pos points to start of payload
   5772   long long timecode = -1;
   5773   long long new_pos = -1;
   5774   bool bBlock = false;
   5775 
   5776   long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size;
   5777 
   5778   for (;;) {
   5779     if ((cluster_stop >= 0) && (pos >= cluster_stop))
   5780       break;
   5781 
   5782     // Parse ID
   5783 
   5784     if ((pos + 1) > avail) {
   5785       len = 1;
   5786       return E_BUFFER_NOT_FULL;
   5787     }
   5788 
   5789     long long result = GetUIntLength(pReader, pos, len);
   5790 
   5791     if (result < 0)  // error
   5792       return static_cast<long>(result);
   5793 
   5794     if (result > 0)
   5795       return E_BUFFER_NOT_FULL;
   5796 
   5797     if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
   5798       return E_FILE_FORMAT_INVALID;
   5799 
   5800     if ((pos + len) > avail)
   5801       return E_BUFFER_NOT_FULL;
   5802 
   5803     const long long id = ReadID(pReader, pos, len);
   5804 
   5805     if (id < 0)  // error
   5806       return static_cast<long>(id);
   5807 
   5808     if (id == 0)
   5809       return E_FILE_FORMAT_INVALID;
   5810 
   5811     // This is the distinguished set of ID's we use to determine
   5812     // that we have exhausted the sub-element's inside the cluster
   5813     // whose ID we parsed earlier.
   5814 
   5815     if (id == mkvmuxer::kMkvCluster)
   5816       break;
   5817 
   5818     if (id == mkvmuxer::kMkvCues)
   5819       break;
   5820 
   5821     pos += len;  // consume ID field
   5822 
   5823     // Parse Size
   5824 
   5825     if ((pos + 1) > avail) {
   5826       len = 1;
   5827       return E_BUFFER_NOT_FULL;
   5828     }
   5829 
   5830     result = GetUIntLength(pReader, pos, len);
   5831 
   5832     if (result < 0)  // error
   5833       return static_cast<long>(result);
   5834 
   5835     if (result > 0)
   5836       return E_BUFFER_NOT_FULL;
   5837 
   5838     if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
   5839       return E_FILE_FORMAT_INVALID;
   5840 
   5841     if ((pos + len) > avail)
   5842       return E_BUFFER_NOT_FULL;
   5843 
   5844     const long long size = ReadUInt(pReader, pos, len);
   5845 
   5846     if (size < 0)  // error
   5847       return static_cast<long>(size);
   5848 
   5849     const long long unknown_size = (1LL << (7 * len)) - 1;
   5850 
   5851     if (size == unknown_size)
   5852       return E_FILE_FORMAT_INVALID;
   5853 
   5854     pos += len;  // consume size field
   5855 
   5856     if ((cluster_stop >= 0) && (pos > cluster_stop))
   5857       return E_FILE_FORMAT_INVALID;
   5858 
   5859     // pos now points to start of payload
   5860 
   5861     if (size == 0)
   5862       continue;
   5863 
   5864     if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
   5865       return E_FILE_FORMAT_INVALID;
   5866 
   5867     if (id == mkvmuxer::kMkvTimecode) {
   5868       len = static_cast<long>(size);
   5869 
   5870       if ((pos + size) > avail)
   5871         return E_BUFFER_NOT_FULL;
   5872 
   5873       timecode = UnserializeUInt(pReader, pos, size);
   5874 
   5875       if (timecode < 0)  // error (or underflow)
   5876         return static_cast<long>(timecode);
   5877 
   5878       new_pos = pos + size;
   5879 
   5880       if (bBlock)
   5881         break;
   5882     } else if (id == mkvmuxer::kMkvBlockGroup) {
   5883       bBlock = true;
   5884       break;
   5885     } else if (id == mkvmuxer::kMkvSimpleBlock) {
   5886       bBlock = true;
   5887       break;
   5888     }
   5889 
   5890     pos += size;  // consume payload
   5891     if (cluster_stop >= 0 && pos > cluster_stop)
   5892       return E_FILE_FORMAT_INVALID;
   5893   }
   5894 
   5895   if (cluster_stop >= 0 && pos > cluster_stop)
   5896     return E_FILE_FORMAT_INVALID;
   5897 
   5898   if (timecode < 0)  // no timecode found
   5899     return E_FILE_FORMAT_INVALID;
   5900 
   5901   if (!bBlock)
   5902     return E_FILE_FORMAT_INVALID;
   5903 
   5904   m_pos = new_pos;  // designates position just beyond timecode payload
   5905   m_timecode = timecode;  // m_timecode >= 0 means we're partially loaded
   5906 
   5907   if (cluster_size >= 0)
   5908     m_element_size = cluster_stop - m_element_start;
   5909 
   5910   return 0;
   5911 }
   5912 
   5913 long Cluster::Parse(long long& pos, long& len) const {
   5914   long status = Load(pos, len);
   5915 
   5916   if (status < 0)
   5917     return status;
   5918 
   5919   if (m_pos < m_element_start || m_timecode < 0)
   5920     return E_PARSE_FAILED;
   5921 
   5922   const long long cluster_stop =
   5923       (m_element_size < 0) ? -1 : m_element_start + m_element_size;
   5924 
   5925   if ((cluster_stop >= 0) && (m_pos >= cluster_stop))
   5926     return 1;  // nothing else to do
   5927 
   5928   IMkvReader* const pReader = m_pSegment->m_pReader;
   5929 
   5930   long long total, avail;
   5931 
   5932   status = pReader->Length(&total, &avail);
   5933 
   5934   if (status < 0)  // error
   5935     return status;
   5936 
   5937   if (total >= 0 && avail > total)
   5938     return E_FILE_FORMAT_INVALID;
   5939 
   5940   pos = m_pos;
   5941 
   5942   for (;;) {
   5943     if ((cluster_stop >= 0) && (pos >= cluster_stop))
   5944       break;
   5945 
   5946     if ((total >= 0) && (pos >= total)) {
   5947       if (m_element_size < 0)
   5948         m_element_size = pos - m_element_start;
   5949 
   5950       break;
   5951     }
   5952 
   5953     // Parse ID
   5954 
   5955     if ((pos + 1) > avail) {
   5956       len = 1;
   5957       return E_BUFFER_NOT_FULL;
   5958     }
   5959 
   5960     long long result = GetUIntLength(pReader, pos, len);
   5961 
   5962     if (result < 0)  // error
   5963       return static_cast<long>(result);
   5964 
   5965     if (result > 0)
   5966       return E_BUFFER_NOT_FULL;
   5967 
   5968     if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
   5969       return E_FILE_FORMAT_INVALID;
   5970 
   5971     if ((pos + len) > avail)
   5972       return E_BUFFER_NOT_FULL;
   5973 
   5974     const long long id = ReadID(pReader, pos, len);
   5975 
   5976     if (id < 0)
   5977       return E_FILE_FORMAT_INVALID;
   5978 
   5979     // This is the distinguished set of ID's we use to determine
   5980     // that we have exhausted the sub-element's inside the cluster
   5981     // whose ID we parsed earlier.
   5982 
   5983     if ((id == mkvmuxer::kMkvCluster) || (id == mkvmuxer::kMkvCues)) {
   5984       if (m_element_size < 0)
   5985         m_element_size = pos - m_element_start;
   5986 
   5987       break;
   5988     }
   5989 
   5990     pos += len;  // consume ID field
   5991 
   5992     // Parse Size
   5993 
   5994     if ((pos + 1) > avail) {
   5995       len = 1;
   5996       return E_BUFFER_NOT_FULL;
   5997     }
   5998 
   5999     result = GetUIntLength(pReader, pos, len);
   6000 
   6001     if (result < 0)  // error
   6002       return static_cast<long>(result);
   6003 
   6004     if (result > 0)
   6005       return E_BUFFER_NOT_FULL;
   6006 
   6007     if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
   6008       return E_FILE_FORMAT_INVALID;
   6009 
   6010     if ((pos + len) > avail)
   6011       return E_BUFFER_NOT_FULL;
   6012 
   6013     const long long size = ReadUInt(pReader, pos, len);
   6014 
   6015     if (size < 0)  // error
   6016       return static_cast<long>(size);
   6017 
   6018     const long long unknown_size = (1LL << (7 * len)) - 1;
   6019 
   6020     if (size == unknown_size)
   6021       return E_FILE_FORMAT_INVALID;
   6022 
   6023     pos += len;  // consume size field
   6024 
   6025     if ((cluster_stop >= 0) && (pos > cluster_stop))
   6026       return E_FILE_FORMAT_INVALID;
   6027 
   6028     // pos now points to start of payload
   6029 
   6030     if (size == 0)
   6031       continue;
   6032 
   6033     // const long long block_start = pos;
   6034     const long long block_stop = pos + size;
   6035 
   6036     if (cluster_stop >= 0) {
   6037       if (block_stop > cluster_stop) {
   6038         if (id == mkvmuxer::kMkvBlockGroup ||
   6039             id == mkvmuxer::kMkvSimpleBlock) {
   6040           return E_FILE_FORMAT_INVALID;
   6041         }
   6042 
   6043         pos = cluster_stop;
   6044         break;
   6045       }
   6046     } else if ((total >= 0) && (block_stop > total)) {
   6047       m_element_size = total - m_element_start;
   6048       pos = total;
   6049       break;
   6050     } else if (block_stop > avail) {
   6051       len = static_cast<long>(size);
   6052       return E_BUFFER_NOT_FULL;
   6053     }
   6054 
   6055     Cluster* const this_ = const_cast<Cluster*>(this);
   6056 
   6057     if (id == mkvmuxer::kMkvBlockGroup)
   6058       return this_->ParseBlockGroup(size, pos, len);
   6059 
   6060     if (id == mkvmuxer::kMkvSimpleBlock)
   6061       return this_->ParseSimpleBlock(size, pos, len);
   6062 
   6063     pos += size;  // consume payload
   6064     if (cluster_stop >= 0 && pos > cluster_stop)
   6065       return E_FILE_FORMAT_INVALID;
   6066   }
   6067 
   6068   if (m_element_size < 1)
   6069     return E_FILE_FORMAT_INVALID;
   6070 
   6071   m_pos = pos;
   6072   if (cluster_stop >= 0 && m_pos > cluster_stop)
   6073     return E_FILE_FORMAT_INVALID;
   6074 
   6075   if (m_entries_count > 0) {
   6076     const long idx = m_entries_count - 1;
   6077 
   6078     const BlockEntry* const pLast = m_entries[idx];
   6079     if (pLast == NULL)
   6080       return E_PARSE_FAILED;
   6081 
   6082     const Block* const pBlock = pLast->GetBlock();
   6083     if (pBlock == NULL)
   6084       return E_PARSE_FAILED;
   6085 
   6086     const long long start = pBlock->m_start;
   6087 
   6088     if ((total >= 0) && (start > total))
   6089       return E_PARSE_FAILED;  // defend against trucated stream
   6090 
   6091     const long long size = pBlock->m_size;
   6092 
   6093     const long long stop = start + size;
   6094     if (cluster_stop >= 0 && stop > cluster_stop)
   6095       return E_FILE_FORMAT_INVALID;
   6096 
   6097     if ((total >= 0) && (stop > total))
   6098       return E_PARSE_FAILED;  // defend against trucated stream
   6099   }
   6100 
   6101   return 1;  // no more entries
   6102 }
   6103 
   6104 long Cluster::ParseSimpleBlock(long long block_size, long long& pos,
   6105                                long& len) {
   6106   const long long block_start = pos;
   6107   const long long block_stop = pos + block_size;
   6108 
   6109   IMkvReader* const pReader = m_pSegment->m_pReader;
   6110 
   6111   long long total, avail;
   6112 
   6113   long status = pReader->Length(&total, &avail);
   6114 
   6115   if (status < 0)  // error
   6116     return status;
   6117 
   6118   assert((total < 0) || (avail <= total));
   6119 
   6120   // parse track number
   6121 
   6122   if ((pos + 1) > avail) {
   6123     len = 1;
   6124     return E_BUFFER_NOT_FULL;
   6125   }
   6126 
   6127   long long result = GetUIntLength(pReader, pos, len);
   6128 
   6129   if (result < 0)  // error
   6130     return static_cast<long>(result);
   6131 
   6132   if (result > 0)  // weird
   6133     return E_BUFFER_NOT_FULL;
   6134 
   6135   if ((pos + len) > block_stop)
   6136     return E_FILE_FORMAT_INVALID;
   6137 
   6138   if ((pos + len) > avail)
   6139     return E_BUFFER_NOT_FULL;
   6140 
   6141   const long long track = ReadUInt(pReader, pos, len);
   6142 
   6143   if (track < 0)  // error
   6144     return static_cast<long>(track);
   6145 
   6146   if (track == 0)
   6147     return E_FILE_FORMAT_INVALID;
   6148 
   6149   pos += len;  // consume track number
   6150 
   6151   if ((pos + 2) > block_stop)
   6152     return E_FILE_FORMAT_INVALID;
   6153 
   6154   if ((pos + 2) > avail) {
   6155     len = 2;
   6156     return E_BUFFER_NOT_FULL;
   6157   }
   6158 
   6159   pos += 2;  // consume timecode
   6160 
   6161   if ((pos + 1) > block_stop)
   6162     return E_FILE_FORMAT_INVALID;
   6163 
   6164   if ((pos + 1) > avail) {
   6165     len = 1;
   6166     return E_BUFFER_NOT_FULL;
   6167   }
   6168 
   6169   unsigned char flags;
   6170 
   6171   status = pReader->Read(pos, 1, &flags);
   6172 
   6173   if (status < 0) {  // error or underflow
   6174     len = 1;
   6175     return status;
   6176   }
   6177 
   6178   ++pos;  // consume flags byte
   6179   assert(pos <= avail);
   6180 
   6181   if (pos >= block_stop)
   6182     return E_FILE_FORMAT_INVALID;
   6183 
   6184   const int lacing = int(flags & 0x06) >> 1;
   6185 
   6186   if ((lacing != 0) && (block_stop > avail)) {
   6187     len = static_cast<long>(block_stop - pos);
   6188     return E_BUFFER_NOT_FULL;
   6189   }
   6190 
   6191   status = CreateBlock(mkvmuxer::kMkvSimpleBlock,
   6192                        block_start, block_size,
   6193                        0);  // DiscardPadding
   6194 
   6195   if (status != 0)
   6196     return status;
   6197 
   6198   m_pos = block_stop;
   6199 
   6200   return 0;  // success
   6201 }
   6202 
   6203 long Cluster::ParseBlockGroup(long long payload_size, long long& pos,
   6204                               long& len) {
   6205   const long long payload_start = pos;
   6206   const long long payload_stop = pos + payload_size;
   6207 
   6208   IMkvReader* const pReader = m_pSegment->m_pReader;
   6209 
   6210   long long total, avail;
   6211 
   6212   long status = pReader->Length(&total, &avail);
   6213 
   6214   if (status < 0)  // error
   6215     return status;
   6216 
   6217   assert((total < 0) || (avail <= total));
   6218 
   6219   if ((total >= 0) && (payload_stop > total))
   6220     return E_FILE_FORMAT_INVALID;
   6221 
   6222   if (payload_stop > avail) {
   6223     len = static_cast<long>(payload_size);
   6224     return E_BUFFER_NOT_FULL;
   6225   }
   6226 
   6227   long long discard_padding = 0;
   6228 
   6229   while (pos < payload_stop) {
   6230     // parse sub-block element ID
   6231 
   6232     if ((pos + 1) > avail) {
   6233       len = 1;
   6234       return E_BUFFER_NOT_FULL;
   6235     }
   6236 
   6237     long long result = GetUIntLength(pReader, pos, len);
   6238 
   6239     if (result < 0)  // error
   6240       return static_cast<long>(result);
   6241 
   6242     if (result > 0)  // weird
   6243       return E_BUFFER_NOT_FULL;
   6244 
   6245     if ((pos + len) > payload_stop)
   6246       return E_FILE_FORMAT_INVALID;
   6247 
   6248     if ((pos + len) > avail)
   6249       return E_BUFFER_NOT_FULL;
   6250 
   6251     const long long id = ReadID(pReader, pos, len);
   6252 
   6253     if (id < 0)  // error
   6254       return static_cast<long>(id);
   6255 
   6256     if (id == 0)  // not a valid ID
   6257       return E_FILE_FORMAT_INVALID;
   6258 
   6259     pos += len;  // consume ID field
   6260 
   6261     // Parse Size
   6262 
   6263     if ((pos + 1) > avail) {
   6264       len = 1;
   6265       return E_BUFFER_NOT_FULL;
   6266     }
   6267 
   6268     result = GetUIntLength(pReader, pos, len);
   6269 
   6270     if (result < 0)  // error
   6271       return static_cast<long>(result);
   6272 
   6273     if (result > 0)  // weird
   6274       return E_BUFFER_NOT_FULL;
   6275 
   6276     if ((pos + len) > payload_stop)
   6277       return E_FILE_FORMAT_INVALID;
   6278 
   6279     if ((pos + len) > avail)
   6280       return E_BUFFER_NOT_FULL;
   6281 
   6282     const long long size = ReadUInt(pReader, pos, len);
   6283 
   6284     if (size < 0)  // error
   6285       return static_cast<long>(size);
   6286 
   6287     pos += len;  // consume size field
   6288 
   6289     // pos now points to start of sub-block group payload
   6290 
   6291     if (pos > payload_stop)
   6292       return E_FILE_FORMAT_INVALID;
   6293 
   6294     if (size == 0)  // weird
   6295       continue;
   6296 
   6297     const long long unknown_size = (1LL << (7 * len)) - 1;
   6298 
   6299     if (size == unknown_size)
   6300       return E_FILE_FORMAT_INVALID;
   6301 
   6302     if (id == mkvmuxer::kMkvDiscardPadding) {
   6303       status = UnserializeInt(pReader, pos, size, discard_padding);
   6304 
   6305       if (status < 0)  // error
   6306         return status;
   6307     }
   6308 
   6309     if (id != mkvmuxer::kMkvBlock) {
   6310       pos += size;  // consume sub-part of block group
   6311 
   6312       if (pos > payload_stop)
   6313         return E_FILE_FORMAT_INVALID;
   6314 
   6315       continue;
   6316     }
   6317 
   6318     const long long block_stop = pos + size;
   6319 
   6320     if (block_stop > payload_stop)
   6321       return E_FILE_FORMAT_INVALID;
   6322 
   6323     // parse track number
   6324 
   6325     if ((pos + 1) > avail) {
   6326       len = 1;
   6327       return E_BUFFER_NOT_FULL;
   6328     }
   6329 
   6330     result = GetUIntLength(pReader, pos, len);
   6331 
   6332     if (result < 0)  // error
   6333       return static_cast<long>(result);
   6334 
   6335     if (result > 0)  // weird
   6336       return E_BUFFER_NOT_FULL;
   6337 
   6338     if ((pos + len) > block_stop)
   6339       return E_FILE_FORMAT_INVALID;
   6340 
   6341     if ((pos + len) > avail)
   6342       return E_BUFFER_NOT_FULL;
   6343 
   6344     const long long track = ReadUInt(pReader, pos, len);
   6345 
   6346     if (track < 0)  // error
   6347       return static_cast<long>(track);
   6348 
   6349     if (track == 0)
   6350       return E_FILE_FORMAT_INVALID;
   6351 
   6352     pos += len;  // consume track number
   6353 
   6354     if ((pos + 2) > block_stop)
   6355       return E_FILE_FORMAT_INVALID;
   6356 
   6357     if ((pos + 2) > avail) {
   6358       len = 2;
   6359       return E_BUFFER_NOT_FULL;
   6360     }
   6361 
   6362     pos += 2;  // consume timecode
   6363 
   6364     if ((pos + 1) > block_stop)
   6365       return E_FILE_FORMAT_INVALID;
   6366 
   6367     if ((pos + 1) > avail) {
   6368       len = 1;
   6369       return E_BUFFER_NOT_FULL;
   6370     }
   6371 
   6372     unsigned char flags;
   6373 
   6374     status = pReader->Read(pos, 1, &flags);
   6375 
   6376     if (status < 0) {  // error or underflow
   6377       len = 1;
   6378       return status;
   6379     }
   6380 
   6381     ++pos;  // consume flags byte
   6382     assert(pos <= avail);
   6383 
   6384     if (pos >= block_stop)
   6385       return E_FILE_FORMAT_INVALID;
   6386 
   6387     const int lacing = int(flags & 0x06) >> 1;
   6388 
   6389     if ((lacing != 0) && (block_stop > avail)) {
   6390       len = static_cast<long>(block_stop - pos);
   6391       return E_BUFFER_NOT_FULL;
   6392     }
   6393 
   6394     pos = block_stop;  // consume block-part of block group
   6395     if (pos > payload_stop)
   6396       return E_FILE_FORMAT_INVALID;
   6397   }
   6398 
   6399   if (pos != payload_stop)
   6400     return E_FILE_FORMAT_INVALID;
   6401 
   6402   status = CreateBlock(mkvmuxer::kMkvBlockGroup,
   6403                        payload_start, payload_size, discard_padding);
   6404   if (status != 0)
   6405     return status;
   6406 
   6407   m_pos = payload_stop;
   6408 
   6409   return 0;  // success
   6410 }
   6411 
   6412 long Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const {
   6413   assert(m_pos >= m_element_start);
   6414 
   6415   pEntry = NULL;
   6416 
   6417   if (index < 0)
   6418     return -1;  // generic error
   6419 
   6420   if (m_entries_count < 0)
   6421     return E_BUFFER_NOT_FULL;
   6422 
   6423   assert(m_entries);
   6424   assert(m_entries_size > 0);
   6425   assert(m_entries_count <= m_entries_size);
   6426 
   6427   if (index < m_entries_count) {
   6428     pEntry = m_entries[index];
   6429     assert(pEntry);
   6430 
   6431     return 1;  // found entry
   6432   }
   6433 
   6434   if (m_element_size < 0)  // we don't know cluster end yet
   6435     return E_BUFFER_NOT_FULL;  // underflow
   6436 
   6437   const long long element_stop = m_element_start + m_element_size;
   6438 
   6439   if (m_pos >= element_stop)
   6440     return 0;  // nothing left to parse
   6441 
   6442   return E_BUFFER_NOT_FULL;  // underflow, since more remains to be parsed
   6443 }
   6444 
   6445 Cluster* Cluster::Create(Segment* pSegment, long idx, long long off) {
   6446   if (!pSegment || off < 0)
   6447     return NULL;
   6448 
   6449   const long long element_start = pSegment->m_start + off;
   6450 
   6451   Cluster* const pCluster =
   6452       new (std::nothrow) Cluster(pSegment, idx, element_start);
   6453 
   6454   return pCluster;
   6455 }
   6456 
   6457 Cluster::Cluster()
   6458     : m_pSegment(NULL),
   6459       m_element_start(0),
   6460       m_index(0),
   6461       m_pos(0),
   6462       m_element_size(0),
   6463       m_timecode(0),
   6464       m_entries(NULL),
   6465       m_entries_size(0),
   6466       m_entries_count(0)  // means "no entries"
   6467 {}
   6468 
   6469 Cluster::Cluster(Segment* pSegment, long idx, long long element_start
   6470                  /* long long element_size */)
   6471     : m_pSegment(pSegment),
   6472       m_element_start(element_start),
   6473       m_index(idx),
   6474       m_pos(element_start),
   6475       m_element_size(-1 /* element_size */),
   6476       m_timecode(-1),
   6477       m_entries(NULL),
   6478       m_entries_size(0),
   6479       m_entries_count(-1)  // means "has not been parsed yet"
   6480 {}
   6481 
   6482 Cluster::~Cluster() {
   6483   if (m_entries_count <= 0)
   6484     return;
   6485 
   6486   BlockEntry** i = m_entries;
   6487   BlockEntry** const j = m_entries + m_entries_count;
   6488 
   6489   while (i != j) {
   6490     BlockEntry* p = *i++;
   6491     assert(p);
   6492 
   6493     delete p;
   6494   }
   6495 
   6496   delete[] m_entries;
   6497 }
   6498 
   6499 bool Cluster::EOS() const { return (m_pSegment == NULL); }
   6500 
   6501 long Cluster::GetIndex() const { return m_index; }
   6502 
   6503 long long Cluster::GetPosition() const {
   6504   const long long pos = m_element_start - m_pSegment->m_start;
   6505   assert(pos >= 0);
   6506 
   6507   return pos;
   6508 }
   6509 
   6510 long long Cluster::GetElementSize() const { return m_element_size; }
   6511 
   6512 long Cluster::HasBlockEntries(
   6513     const Segment* pSegment,
   6514     long long off,  // relative to start of segment payload
   6515     long long& pos, long& len) {
   6516   assert(pSegment);
   6517   assert(off >= 0);  // relative to segment
   6518 
   6519   IMkvReader* const pReader = pSegment->m_pReader;
   6520 
   6521   long long total, avail;
   6522 
   6523   long status = pReader->Length(&total, &avail);
   6524 
   6525   if (status < 0)  // error
   6526     return status;
   6527 
   6528   assert((total < 0) || (avail <= total));
   6529 
   6530   pos = pSegment->m_start + off;  // absolute
   6531 
   6532   if ((total >= 0) && (pos >= total))
   6533     return 0;  // we don't even have a complete cluster
   6534 
   6535   const long long segment_stop =
   6536       (pSegment->m_size < 0) ? -1 : pSegment->m_start + pSegment->m_size;
   6537 
   6538   long long cluster_stop = -1;  // interpreted later to mean "unknown size"
   6539 
   6540   {
   6541     if ((pos + 1) > avail) {
   6542       len = 1;
   6543       return E_BUFFER_NOT_FULL;
   6544     }
   6545 
   6546     long long result = GetUIntLength(pReader, pos, len);
   6547 
   6548     if (result < 0)  // error
   6549       return static_cast<long>(result);
   6550 
   6551     if (result > 0)  // need more data
   6552       return E_BUFFER_NOT_FULL;
   6553 
   6554     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   6555       return E_FILE_FORMAT_INVALID;
   6556 
   6557     if ((total >= 0) && ((pos + len) > total))
   6558       return 0;
   6559 
   6560     if ((pos + len) > avail)
   6561       return E_BUFFER_NOT_FULL;
   6562 
   6563     const long long id = ReadID(pReader, pos, len);
   6564 
   6565     if (id < 0)  // error
   6566       return static_cast<long>(id);
   6567 
   6568     if (id != mkvmuxer::kMkvCluster)
   6569       return E_PARSE_FAILED;
   6570 
   6571     pos += len;  // consume Cluster ID field
   6572 
   6573     // read size field
   6574 
   6575     if ((pos + 1) > avail) {
   6576       len = 1;
   6577       return E_BUFFER_NOT_FULL;
   6578     }
   6579 
   6580     result = GetUIntLength(pReader, pos, len);
   6581 
   6582     if (result < 0)  // error
   6583       return static_cast<long>(result);
   6584 
   6585     if (result > 0)  // weird
   6586       return E_BUFFER_NOT_FULL;
   6587 
   6588     if ((segment_stop >= 0) && ((pos + len) > segment_stop))
   6589       return E_FILE_FORMAT_INVALID;
   6590 
   6591     if ((total >= 0) && ((pos + len) > total))
   6592       return 0;
   6593 
   6594     if ((pos + len) > avail)
   6595       return E_BUFFER_NOT_FULL;
   6596 
   6597     const long long size = ReadUInt(pReader, pos, len);
   6598 
   6599     if (size < 0)  // error
   6600       return static_cast<long>(size);
   6601 
   6602     if (size == 0)
   6603       return 0;  // cluster does not have entries
   6604 
   6605     pos += len;  // consume size field
   6606 
   6607     // pos now points to start of payload
   6608 
   6609     const long long unknown_size = (1LL << (7 * len)) - 1;
   6610 
   6611     if (size != unknown_size) {
   6612       cluster_stop = pos + size;
   6613       assert(cluster_stop >= 0);
   6614 
   6615       if ((segment_stop >= 0) && (cluster_stop > segment_stop))
   6616         return E_FILE_FORMAT_INVALID;
   6617 
   6618       if ((total >= 0) && (cluster_stop > total))
   6619         // return E_FILE_FORMAT_INVALID;  //too conservative
   6620         return 0;  // cluster does not have any entries
   6621     }
   6622   }
   6623 
   6624   for (;;) {
   6625     if ((cluster_stop >= 0) && (pos >= cluster_stop))
   6626       return 0;  // no entries detected
   6627 
   6628     if ((pos + 1) > avail) {
   6629       len = 1;
   6630       return E_BUFFER_NOT_FULL;
   6631     }
   6632 
   6633     long long result = GetUIntLength(pReader, pos, len);
   6634 
   6635     if (result < 0)  // error
   6636       return static_cast<long>(result);
   6637 
   6638     if (result > 0)  // need more data
   6639       return E_BUFFER_NOT_FULL;
   6640 
   6641     if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
   6642       return E_FILE_FORMAT_INVALID;
   6643 
   6644     if ((pos + len) > avail)
   6645       return E_BUFFER_NOT_FULL;
   6646 
   6647     const long long id = ReadID(pReader, pos, len);
   6648 
   6649     if (id < 0)  // error
   6650       return static_cast<long>(id);
   6651 
   6652     // This is the distinguished set of ID's we use to determine
   6653     // that we have exhausted the sub-element's inside the cluster
   6654     // whose ID we parsed earlier.
   6655 
   6656     if (id == mkvmuxer::kMkvCluster)
   6657       return 0;  // no entries found
   6658 
   6659     if (id == mkvmuxer::kMkvCues)
   6660       return 0;  // no entries found
   6661 
   6662     pos += len;  // consume id field
   6663 
   6664     if ((cluster_stop >= 0) && (pos >= cluster_stop))
   6665       return E_FILE_FORMAT_INVALID;
   6666 
   6667     // read size field
   6668 
   6669     if ((pos + 1) > avail) {
   6670       len = 1;
   6671       return E_BUFFER_NOT_FULL;
   6672     }
   6673 
   6674     result = GetUIntLength(pReader, pos, len);
   6675 
   6676     if (result < 0)  // error
   6677       return static_cast<long>(result);
   6678 
   6679     if (result > 0)  // underflow
   6680       return E_BUFFER_NOT_FULL;
   6681 
   6682     if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
   6683       return E_FILE_FORMAT_INVALID;
   6684 
   6685     if ((pos + len) > avail)
   6686       return E_BUFFER_NOT_FULL;
   6687 
   6688     const long long size = ReadUInt(pReader, pos, len);
   6689 
   6690     if (size < 0)  // error
   6691       return static_cast<long>(size);
   6692 
   6693     pos += len;  // consume size field
   6694 
   6695     // pos now points to start of payload
   6696 
   6697     if ((cluster_stop >= 0) && (pos > cluster_stop))
   6698       return E_FILE_FORMAT_INVALID;
   6699 
   6700     if (size == 0)  // weird
   6701       continue;
   6702 
   6703     const long long unknown_size = (1LL << (7 * len)) - 1;
   6704 
   6705     if (size == unknown_size)
   6706       return E_FILE_FORMAT_INVALID;  // not supported inside cluster
   6707 
   6708     if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
   6709       return E_FILE_FORMAT_INVALID;
   6710 
   6711     if (id == mkvmuxer::kMkvBlockGroup)
   6712       return 1;  // have at least one entry
   6713 
   6714     if (id == mkvmuxer::kMkvSimpleBlock)
   6715       return 1;  // have at least one entry
   6716 
   6717     pos += size;  // consume payload
   6718     if (cluster_stop >= 0 && pos > cluster_stop)
   6719       return E_FILE_FORMAT_INVALID;
   6720   }
   6721 }
   6722 
   6723 long long Cluster::GetTimeCode() const {
   6724   long long pos;
   6725   long len;
   6726 
   6727   const long status = Load(pos, len);
   6728 
   6729   if (status < 0)  // error
   6730     return status;
   6731 
   6732   return m_timecode;
   6733 }
   6734 
   6735 long long Cluster::GetTime() const {
   6736   const long long tc = GetTimeCode();
   6737 
   6738   if (tc < 0)
   6739     return tc;
   6740 
   6741   const SegmentInfo* const pInfo = m_pSegment->GetInfo();
   6742   assert(pInfo);
   6743 
   6744   const long long scale = pInfo->GetTimeCodeScale();
   6745   assert(scale >= 1);
   6746 
   6747   const long long t = m_timecode * scale;
   6748 
   6749   return t;
   6750 }
   6751 
   6752 long long Cluster::GetFirstTime() const {
   6753   const BlockEntry* pEntry;
   6754 
   6755   const long status = GetFirst(pEntry);
   6756 
   6757   if (status < 0)  // error
   6758     return status;
   6759 
   6760   if (pEntry == NULL)  // empty cluster
   6761     return GetTime();
   6762 
   6763   const Block* const pBlock = pEntry->GetBlock();
   6764   assert(pBlock);
   6765 
   6766   return pBlock->GetTime(this);
   6767 }
   6768 
   6769 long long Cluster::GetLastTime() const {
   6770   const BlockEntry* pEntry;
   6771 
   6772   const long status = GetLast(pEntry);
   6773 
   6774   if (status < 0)  // error
   6775     return status;
   6776 
   6777   if (pEntry == NULL)  // empty cluster
   6778     return GetTime();
   6779 
   6780   const Block* const pBlock = pEntry->GetBlock();
   6781   assert(pBlock);
   6782 
   6783   return pBlock->GetTime(this);
   6784 }
   6785 
   6786 long Cluster::CreateBlock(long long id,
   6787                           long long pos,  // absolute pos of payload
   6788                           long long size, long long discard_padding) {
   6789   if (id != mkvmuxer::kMkvBlockGroup && id != mkvmuxer::kMkvSimpleBlock)
   6790     return E_PARSE_FAILED;
   6791 
   6792   if (m_entries_count < 0) {  // haven't parsed anything yet
   6793     assert(m_entries == NULL);
   6794     assert(m_entries_size == 0);
   6795 
   6796     m_entries_size = 1024;
   6797     m_entries = new (std::nothrow) BlockEntry*[m_entries_size];
   6798     if (m_entries == NULL)
   6799       return -1;
   6800 
   6801     m_entries_count = 0;
   6802   } else {
   6803     assert(m_entries);
   6804     assert(m_entries_size > 0);
   6805     assert(m_entries_count <= m_entries_size);
   6806 
   6807     if (m_entries_count >= m_entries_size) {
   6808       const long entries_size = 2 * m_entries_size;
   6809 
   6810       BlockEntry** const entries = new (std::nothrow) BlockEntry*[entries_size];
   6811       if (entries == NULL)
   6812         return -1;
   6813 
   6814       BlockEntry** src = m_entries;
   6815       BlockEntry** const src_end = src + m_entries_count;
   6816 
   6817       BlockEntry** dst = entries;
   6818 
   6819       while (src != src_end)
   6820         *dst++ = *src++;
   6821 
   6822       delete[] m_entries;
   6823 
   6824       m_entries = entries;
   6825       m_entries_size = entries_size;
   6826     }
   6827   }
   6828 
   6829   if (id == mkvmuxer::kMkvBlockGroup)
   6830     return CreateBlockGroup(pos, size, discard_padding);
   6831   else
   6832     return CreateSimpleBlock(pos, size);
   6833 }
   6834 
   6835 long Cluster::CreateBlockGroup(long long start_offset, long long size,
   6836                                long long discard_padding) {
   6837   assert(m_entries);
   6838   assert(m_entries_size > 0);
   6839   assert(m_entries_count >= 0);
   6840   assert(m_entries_count < m_entries_size);
   6841 
   6842   IMkvReader* const pReader = m_pSegment->m_pReader;
   6843 
   6844   long long pos = start_offset;
   6845   const long long stop = start_offset + size;
   6846 
   6847   // For WebM files, there is a bias towards previous reference times
   6848   //(in order to support alt-ref frames, which refer back to the previous
   6849   // keyframe).  Normally a 0 value is not possible, but here we tenatively
   6850   // allow 0 as the value of a reference frame, with the interpretation
   6851   // that this is a "previous" reference time.
   6852 
   6853   long long prev = 1;  // nonce
   6854   long long next = 0;  // nonce
   6855   long long duration = -1;  // really, this is unsigned
   6856 
   6857   long long bpos = -1;
   6858   long long bsize = -1;
   6859 
   6860   while (pos < stop) {
   6861     long len;
   6862     const long long id = ReadID(pReader, pos, len);
   6863     if (id < 0 || (pos + len) > stop)
   6864       return E_FILE_FORMAT_INVALID;
   6865 
   6866     pos += len;  // consume ID
   6867 
   6868     const long long size = ReadUInt(pReader, pos, len);
   6869     assert(size >= 0);  // TODO
   6870     assert((pos + len) <= stop);
   6871 
   6872     pos += len;  // consume size
   6873 
   6874     if (id == mkvmuxer::kMkvBlock) {
   6875       if (bpos < 0) {  // Block ID
   6876         bpos = pos;
   6877         bsize = size;
   6878       }
   6879     } else if (id == mkvmuxer::kMkvBlockDuration) {
   6880       if (size > 8)
   6881         return E_FILE_FORMAT_INVALID;
   6882 
   6883       duration = UnserializeUInt(pReader, pos, size);
   6884 
   6885       if (duration < 0)
   6886         return E_FILE_FORMAT_INVALID;
   6887     } else if (id == mkvmuxer::kMkvReferenceBlock) {
   6888       if (size > 8 || size <= 0)
   6889         return E_FILE_FORMAT_INVALID;
   6890       const long size_ = static_cast<long>(size);
   6891 
   6892       long long time;
   6893 
   6894       long status = UnserializeInt(pReader, pos, size_, time);
   6895       assert(status == 0);
   6896       if (status != 0)
   6897         return -1;
   6898 
   6899       if (time <= 0)  // see note above
   6900         prev = time;
   6901       else
   6902         next = time;
   6903     }
   6904 
   6905     pos += size;  // consume payload
   6906     if (pos > stop)
   6907       return E_FILE_FORMAT_INVALID;
   6908   }
   6909   if (bpos < 0)
   6910     return E_FILE_FORMAT_INVALID;
   6911 
   6912   if (pos != stop)
   6913     return E_FILE_FORMAT_INVALID;
   6914   assert(bsize >= 0);
   6915 
   6916   const long idx = m_entries_count;
   6917 
   6918   BlockEntry** const ppEntry = m_entries + idx;
   6919   BlockEntry*& pEntry = *ppEntry;
   6920 
   6921   pEntry = new (std::nothrow)
   6922       BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding);
   6923 
   6924   if (pEntry == NULL)
   6925     return -1;  // generic error
   6926 
   6927   BlockGroup* const p = static_cast<BlockGroup*>(pEntry);
   6928 
   6929   const long status = p->Parse();
   6930 
   6931   if (status == 0) {  // success
   6932     ++m_entries_count;
   6933     return 0;
   6934   }
   6935 
   6936   delete pEntry;
   6937   pEntry = 0;
   6938 
   6939   return status;
   6940 }
   6941 
   6942 long Cluster::CreateSimpleBlock(long long st, long long sz) {
   6943   assert(m_entries);
   6944   assert(m_entries_size > 0);
   6945   assert(m_entries_count >= 0);
   6946   assert(m_entries_count < m_entries_size);
   6947 
   6948   const long idx = m_entries_count;
   6949 
   6950   BlockEntry** const ppEntry = m_entries + idx;
   6951   BlockEntry*& pEntry = *ppEntry;
   6952 
   6953   pEntry = new (std::nothrow) SimpleBlock(this, idx, st, sz);
   6954 
   6955   if (pEntry == NULL)
   6956     return -1;  // generic error
   6957 
   6958   SimpleBlock* const p = static_cast<SimpleBlock*>(pEntry);
   6959 
   6960   const long status = p->Parse();
   6961 
   6962   if (status == 0) {
   6963     ++m_entries_count;
   6964     return 0;
   6965   }
   6966 
   6967   delete pEntry;
   6968   pEntry = 0;
   6969 
   6970   return status;
   6971 }
   6972 
   6973 long Cluster::GetFirst(const BlockEntry*& pFirst) const {
   6974   if (m_entries_count <= 0) {
   6975     long long pos;
   6976     long len;
   6977 
   6978     const long status = Parse(pos, len);
   6979 
   6980     if (status < 0) {  // error
   6981       pFirst = NULL;
   6982       return status;
   6983     }
   6984 
   6985     if (m_entries_count <= 0) {  // empty cluster
   6986       pFirst = NULL;
   6987       return 0;
   6988     }
   6989   }
   6990 
   6991   assert(m_entries);
   6992 
   6993   pFirst = m_entries[0];
   6994   assert(pFirst);
   6995 
   6996   return 0;  // success
   6997 }
   6998 
   6999 long Cluster::GetLast(const BlockEntry*& pLast) const {
   7000   for (;;) {
   7001     long long pos;
   7002     long len;
   7003 
   7004     const long status = Parse(pos, len);
   7005 
   7006     if (status < 0) {  // error
   7007       pLast = NULL;
   7008       return status;
   7009     }
   7010 
   7011     if (status > 0)  // no new block
   7012       break;
   7013   }
   7014 
   7015   if (m_entries_count <= 0) {
   7016     pLast = NULL;
   7017     return 0;
   7018   }
   7019 
   7020   assert(m_entries);
   7021 
   7022   const long idx = m_entries_count - 1;
   7023 
   7024   pLast = m_entries[idx];
   7025   assert(pLast);
   7026 
   7027   return 0;
   7028 }
   7029 
   7030 long Cluster::GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const {
   7031   assert(pCurr);
   7032   assert(m_entries);
   7033   assert(m_entries_count > 0);
   7034 
   7035   size_t idx = pCurr->GetIndex();
   7036   assert(idx < size_t(m_entries_count));
   7037   assert(m_entries[idx] == pCurr);
   7038 
   7039   ++idx;
   7040 
   7041   if (idx >= size_t(m_entries_count)) {
   7042     long long pos;
   7043     long len;
   7044 
   7045     const long status = Parse(pos, len);
   7046 
   7047     if (status < 0) {  // error
   7048       pNext = NULL;
   7049       return status;
   7050     }
   7051 
   7052     if (status > 0) {
   7053       pNext = NULL;
   7054       return 0;
   7055     }
   7056 
   7057     assert(m_entries);
   7058     assert(m_entries_count > 0);
   7059     assert(idx < size_t(m_entries_count));
   7060   }
   7061 
   7062   pNext = m_entries[idx];
   7063   assert(pNext);
   7064 
   7065   return 0;
   7066 }
   7067 
   7068 long Cluster::GetEntryCount() const { return m_entries_count; }
   7069 
   7070 const BlockEntry* Cluster::GetEntry(const Track* pTrack,
   7071                                     long long time_ns) const {
   7072   assert(pTrack);
   7073 
   7074   if (m_pSegment == NULL)  // this is the special EOS cluster
   7075     return pTrack->GetEOS();
   7076 
   7077   const BlockEntry* pResult = pTrack->GetEOS();
   7078 
   7079   long index = 0;
   7080 
   7081   for (;;) {
   7082     if (index >= m_entries_count) {
   7083       long long pos;
   7084       long len;
   7085 
   7086       const long status = Parse(pos, len);
   7087       assert(status >= 0);
   7088 
   7089       if (status > 0)  // completely parsed, and no more entries
   7090         return pResult;
   7091 
   7092       if (status < 0)  // should never happen
   7093         return 0;
   7094 
   7095       assert(m_entries);
   7096       assert(index < m_entries_count);
   7097     }
   7098 
   7099     const BlockEntry* const pEntry = m_entries[index];
   7100     assert(pEntry);
   7101     assert(!pEntry->EOS());
   7102 
   7103     const Block* const pBlock = pEntry->GetBlock();
   7104     assert(pBlock);
   7105 
   7106     if (pBlock->GetTrackNumber() != pTrack->GetNumber()) {
   7107       ++index;
   7108       continue;
   7109     }
   7110 
   7111     if (pTrack->VetEntry(pEntry)) {
   7112       if (time_ns < 0)  // just want first candidate block
   7113         return pEntry;
   7114 
   7115       const long long ns = pBlock->GetTime(this);
   7116 
   7117       if (ns > time_ns)
   7118         return pResult;
   7119 
   7120       pResult = pEntry;  // have a candidate
   7121     } else if (time_ns >= 0) {
   7122       const long long ns = pBlock->GetTime(this);
   7123 
   7124       if (ns > time_ns)
   7125         return pResult;
   7126     }
   7127 
   7128     ++index;
   7129   }
   7130 }
   7131 
   7132 const BlockEntry* Cluster::GetEntry(const CuePoint& cp,
   7133                                     const CuePoint::TrackPosition& tp) const {
   7134   assert(m_pSegment);
   7135   const long long tc = cp.GetTimeCode();
   7136 
   7137   if (tp.m_block > 0) {
   7138     const long block = static_cast<long>(tp.m_block);
   7139     const long index = block - 1;
   7140 
   7141     while (index >= m_entries_count) {
   7142       long long pos;
   7143       long len;
   7144 
   7145       const long status = Parse(pos, len);
   7146 
   7147       if (status < 0)  // TODO: can this happen?
   7148         return NULL;
   7149 
   7150       if (status > 0)  // nothing remains to be parsed
   7151         return NULL;
   7152     }
   7153 
   7154     const BlockEntry* const pEntry = m_entries[index];
   7155     assert(pEntry);
   7156     assert(!pEntry->EOS());
   7157 
   7158     const Block* const pBlock = pEntry->GetBlock();
   7159     assert(pBlock);
   7160 
   7161     if ((pBlock->GetTrackNumber() == tp.m_track) &&
   7162         (pBlock->GetTimeCode(this) == tc)) {
   7163       return pEntry;
   7164     }
   7165   }
   7166 
   7167   long index = 0;
   7168 
   7169   for (;;) {
   7170     if (index >= m_entries_count) {
   7171       long long pos;
   7172       long len;
   7173 
   7174       const long status = Parse(pos, len);
   7175 
   7176       if (status < 0)  // TODO: can this happen?
   7177         return NULL;
   7178 
   7179       if (status > 0)  // nothing remains to be parsed
   7180         return NULL;
   7181 
   7182       assert(m_entries);
   7183       assert(index < m_entries_count);
   7184     }
   7185 
   7186     const BlockEntry* const pEntry = m_entries[index];
   7187     assert(pEntry);
   7188     assert(!pEntry->EOS());
   7189 
   7190     const Block* const pBlock = pEntry->GetBlock();
   7191     assert(pBlock);
   7192 
   7193     if (pBlock->GetTrackNumber() != tp.m_track) {
   7194       ++index;
   7195       continue;
   7196     }
   7197 
   7198     const long long tc_ = pBlock->GetTimeCode(this);
   7199 
   7200     if (tc_ < tc) {
   7201       ++index;
   7202       continue;
   7203     }
   7204 
   7205     if (tc_ > tc)
   7206       return NULL;
   7207 
   7208     const Tracks* const pTracks = m_pSegment->GetTracks();
   7209     assert(pTracks);
   7210 
   7211     const long tn = static_cast<long>(tp.m_track);
   7212     const Track* const pTrack = pTracks->GetTrackByNumber(tn);
   7213 
   7214     if (pTrack == NULL)
   7215       return NULL;
   7216 
   7217     const long long type = pTrack->GetType();
   7218 
   7219     if (type == 2)  // audio
   7220       return pEntry;
   7221 
   7222     if (type != 1)  // not video
   7223       return NULL;
   7224 
   7225     if (!pBlock->IsKey())
   7226       return NULL;
   7227 
   7228     return pEntry;
   7229   }
   7230 }
   7231 
   7232 BlockEntry::BlockEntry(Cluster* p, long idx) : m_pCluster(p), m_index(idx) {}
   7233 BlockEntry::~BlockEntry() {}
   7234 bool BlockEntry::EOS() const { return (GetKind() == kBlockEOS); }
   7235 const Cluster* BlockEntry::GetCluster() const { return m_pCluster; }
   7236 long BlockEntry::GetIndex() const { return m_index; }
   7237 
   7238 SimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start,
   7239                          long long size)
   7240     : BlockEntry(pCluster, idx), m_block(start, size, 0) {}
   7241 
   7242 long SimpleBlock::Parse() { return m_block.Parse(m_pCluster); }
   7243 BlockEntry::Kind SimpleBlock::GetKind() const { return kBlockSimple; }
   7244 const Block* SimpleBlock::GetBlock() const { return &m_block; }
   7245 
   7246 BlockGroup::BlockGroup(Cluster* pCluster, long idx, long long block_start,
   7247                        long long block_size, long long prev, long long next,
   7248                        long long duration, long long discard_padding)
   7249     : BlockEntry(pCluster, idx),
   7250       m_block(block_start, block_size, discard_padding),
   7251       m_prev(prev),
   7252       m_next(next),
   7253       m_duration(duration) {}
   7254 
   7255 long BlockGroup::Parse() {
   7256   const long status = m_block.Parse(m_pCluster);
   7257 
   7258   if (status)
   7259     return status;
   7260 
   7261   m_block.SetKey((m_prev > 0) && (m_next <= 0));
   7262 
   7263   return 0;
   7264 }
   7265 
   7266 BlockEntry::Kind BlockGroup::GetKind() const { return kBlockGroup; }
   7267 const Block* BlockGroup::GetBlock() const { return &m_block; }
   7268 long long BlockGroup::GetPrevTimeCode() const { return m_prev; }
   7269 long long BlockGroup::GetNextTimeCode() const { return m_next; }
   7270 long long BlockGroup::GetDurationTimeCode() const { return m_duration; }
   7271 
   7272 Block::Block(long long start, long long size_, long long discard_padding)
   7273     : m_start(start),
   7274       m_size(size_),
   7275       m_track(0),
   7276       m_timecode(-1),
   7277       m_flags(0),
   7278       m_frames(NULL),
   7279       m_frame_count(-1),
   7280       m_discard_padding(discard_padding) {}
   7281 
   7282 Block::~Block() { delete[] m_frames; }
   7283 
   7284 long Block::Parse(const Cluster* pCluster) {
   7285   if (pCluster == NULL)
   7286     return -1;
   7287 
   7288   if (pCluster->m_pSegment == NULL)
   7289     return -1;
   7290 
   7291   assert(m_start >= 0);
   7292   assert(m_size >= 0);
   7293   assert(m_track <= 0);
   7294   assert(m_frames == NULL);
   7295   assert(m_frame_count <= 0);
   7296 
   7297   long long pos = m_start;
   7298   const long long stop = m_start + m_size;
   7299 
   7300   long len;
   7301 
   7302   IMkvReader* const pReader = pCluster->m_pSegment->m_pReader;
   7303 
   7304   m_track = ReadUInt(pReader, pos, len);
   7305 
   7306   if (m_track <= 0)
   7307     return E_FILE_FORMAT_INVALID;
   7308 
   7309   if ((pos + len) > stop)
   7310     return E_FILE_FORMAT_INVALID;
   7311 
   7312   pos += len;  // consume track number
   7313 
   7314   if ((stop - pos) < 2)
   7315     return E_FILE_FORMAT_INVALID;
   7316 
   7317   long status;
   7318   long long value;
   7319 
   7320   status = UnserializeInt(pReader, pos, 2, value);
   7321 
   7322   if (status)
   7323     return E_FILE_FORMAT_INVALID;
   7324 
   7325   if (value < SHRT_MIN)
   7326     return E_FILE_FORMAT_INVALID;
   7327 
   7328   if (value > SHRT_MAX)
   7329     return E_FILE_FORMAT_INVALID;
   7330 
   7331   m_timecode = static_cast<short>(value);
   7332 
   7333   pos += 2;
   7334 
   7335   if ((stop - pos) <= 0)
   7336     return E_FILE_FORMAT_INVALID;
   7337 
   7338   status = pReader->Read(pos, 1, &m_flags);
   7339 
   7340   if (status)
   7341     return E_FILE_FORMAT_INVALID;
   7342 
   7343   const int lacing = int(m_flags & 0x06) >> 1;
   7344 
   7345   ++pos;  // consume flags byte
   7346 
   7347   if (lacing == 0) {  // no lacing
   7348     if (pos > stop)
   7349       return E_FILE_FORMAT_INVALID;
   7350 
   7351     m_frame_count = 1;
   7352     m_frames = new (std::nothrow) Frame[m_frame_count];
   7353     if (m_frames == NULL)
   7354       return -1;
   7355 
   7356     Frame& f = m_frames[0];
   7357     f.pos = pos;
   7358 
   7359     const long long frame_size = stop - pos;
   7360 
   7361     if (frame_size > LONG_MAX || frame_size <= 0)
   7362       return E_FILE_FORMAT_INVALID;
   7363 
   7364     f.len = static_cast<long>(frame_size);
   7365 
   7366     return 0;  // success
   7367   }
   7368 
   7369   if (pos >= stop)
   7370     return E_FILE_FORMAT_INVALID;
   7371 
   7372   unsigned char biased_count;
   7373 
   7374   status = pReader->Read(pos, 1, &biased_count);
   7375 
   7376   if (status)
   7377     return E_FILE_FORMAT_INVALID;
   7378 
   7379   ++pos;  // consume frame count
   7380   if (pos > stop)
   7381     return E_FILE_FORMAT_INVALID;
   7382 
   7383   m_frame_count = int(biased_count) + 1;
   7384 
   7385   m_frames = new (std::nothrow) Frame[m_frame_count];
   7386   if (m_frames == NULL)
   7387     return -1;
   7388 
   7389   if (!m_frames)
   7390     return E_FILE_FORMAT_INVALID;
   7391 
   7392   if (lacing == 1) {  // Xiph
   7393     Frame* pf = m_frames;
   7394     Frame* const pf_end = pf + m_frame_count;
   7395 
   7396     long long size = 0;
   7397     int frame_count = m_frame_count;
   7398 
   7399     while (frame_count > 1) {
   7400       long frame_size = 0;
   7401 
   7402       for (;;) {
   7403         unsigned char val;
   7404 
   7405         if (pos >= stop)
   7406           return E_FILE_FORMAT_INVALID;
   7407 
   7408         status = pReader->Read(pos, 1, &val);
   7409 
   7410         if (status)
   7411           return E_FILE_FORMAT_INVALID;
   7412 
   7413         ++pos;  // consume xiph size byte
   7414 
   7415         frame_size += val;
   7416 
   7417         if (val < 255)
   7418           break;
   7419       }
   7420 
   7421       Frame& f = *pf++;
   7422       assert(pf < pf_end);
   7423       if (pf >= pf_end)
   7424         return E_FILE_FORMAT_INVALID;
   7425 
   7426       f.pos = 0;  // patch later
   7427 
   7428       if (frame_size <= 0)
   7429         return E_FILE_FORMAT_INVALID;
   7430 
   7431       f.len = frame_size;
   7432       size += frame_size;  // contribution of this frame
   7433 
   7434       --frame_count;
   7435     }
   7436 
   7437     if (pf >= pf_end || pos > stop)
   7438       return E_FILE_FORMAT_INVALID;
   7439 
   7440     {
   7441       Frame& f = *pf++;
   7442 
   7443       if (pf != pf_end)
   7444         return E_FILE_FORMAT_INVALID;
   7445 
   7446       f.pos = 0;  // patch later
   7447 
   7448       const long long total_size = stop - pos;
   7449 
   7450       if (total_size < size)
   7451         return E_FILE_FORMAT_INVALID;
   7452 
   7453       const long long frame_size = total_size - size;
   7454 
   7455       if (frame_size > LONG_MAX || frame_size <= 0)
   7456         return E_FILE_FORMAT_INVALID;
   7457 
   7458       f.len = static_cast<long>(frame_size);
   7459     }
   7460 
   7461     pf = m_frames;
   7462     while (pf != pf_end) {
   7463       Frame& f = *pf++;
   7464       assert((pos + f.len) <= stop);
   7465 
   7466       if ((pos + f.len) > stop)
   7467         return E_FILE_FORMAT_INVALID;
   7468 
   7469       f.pos = pos;
   7470       pos += f.len;
   7471     }
   7472 
   7473     assert(pos == stop);
   7474     if (pos != stop)
   7475       return E_FILE_FORMAT_INVALID;
   7476 
   7477   } else if (lacing == 2) {  // fixed-size lacing
   7478     if (pos >= stop)
   7479       return E_FILE_FORMAT_INVALID;
   7480 
   7481     const long long total_size = stop - pos;
   7482 
   7483     if ((total_size % m_frame_count) != 0)
   7484       return E_FILE_FORMAT_INVALID;
   7485 
   7486     const long long frame_size = total_size / m_frame_count;
   7487 
   7488     if (frame_size > LONG_MAX || frame_size <= 0)
   7489       return E_FILE_FORMAT_INVALID;
   7490 
   7491     Frame* pf = m_frames;
   7492     Frame* const pf_end = pf + m_frame_count;
   7493 
   7494     while (pf != pf_end) {
   7495       assert((pos + frame_size) <= stop);
   7496       if ((pos + frame_size) > stop)
   7497         return E_FILE_FORMAT_INVALID;
   7498 
   7499       Frame& f = *pf++;
   7500 
   7501       f.pos = pos;
   7502       f.len = static_cast<long>(frame_size);
   7503 
   7504       pos += frame_size;
   7505     }
   7506 
   7507     assert(pos == stop);
   7508     if (pos != stop)
   7509       return E_FILE_FORMAT_INVALID;
   7510 
   7511   } else {
   7512     assert(lacing == 3);  // EBML lacing
   7513 
   7514     if (pos >= stop)
   7515       return E_FILE_FORMAT_INVALID;
   7516 
   7517     long long size = 0;
   7518     int frame_count = m_frame_count;
   7519 
   7520     long long frame_size = ReadUInt(pReader, pos, len);
   7521 
   7522     if (frame_size <= 0)
   7523       return E_FILE_FORMAT_INVALID;
   7524 
   7525     if (frame_size > LONG_MAX)
   7526       return E_FILE_FORMAT_INVALID;
   7527 
   7528     if ((pos + len) > stop)
   7529       return E_FILE_FORMAT_INVALID;
   7530 
   7531     pos += len;  // consume length of size of first frame
   7532 
   7533     if ((pos + frame_size) > stop)
   7534       return E_FILE_FORMAT_INVALID;
   7535 
   7536     Frame* pf = m_frames;
   7537     Frame* const pf_end = pf + m_frame_count;
   7538 
   7539     {
   7540       Frame& curr = *pf;
   7541 
   7542       curr.pos = 0;  // patch later
   7543 
   7544       curr.len = static_cast<long>(frame_size);
   7545       size += curr.len;  // contribution of this frame
   7546     }
   7547 
   7548     --frame_count;
   7549 
   7550     while (frame_count > 1) {
   7551       if (pos >= stop)
   7552         return E_FILE_FORMAT_INVALID;
   7553 
   7554       assert(pf < pf_end);
   7555       if (pf >= pf_end)
   7556         return E_FILE_FORMAT_INVALID;
   7557 
   7558 
   7559       const Frame& prev = *pf++;
   7560       assert(prev.len == frame_size);
   7561       if (prev.len != frame_size)
   7562         return E_FILE_FORMAT_INVALID;
   7563 
   7564       assert(pf < pf_end);
   7565       if (pf >= pf_end)
   7566         return E_FILE_FORMAT_INVALID;
   7567 
   7568       Frame& curr = *pf;
   7569 
   7570       curr.pos = 0;  // patch later
   7571 
   7572       const long long delta_size_ = ReadUInt(pReader, pos, len);
   7573 
   7574       if (delta_size_ < 0)
   7575         return E_FILE_FORMAT_INVALID;
   7576 
   7577       if ((pos + len) > stop)
   7578         return E_FILE_FORMAT_INVALID;
   7579 
   7580       pos += len;  // consume length of (delta) size
   7581       if (pos > stop)
   7582         return E_FILE_FORMAT_INVALID;
   7583 
   7584       const int exp = 7 * len - 1;
   7585       const long long bias = (1LL << exp) - 1LL;
   7586       const long long delta_size = delta_size_ - bias;
   7587 
   7588       frame_size += delta_size;
   7589 
   7590       if (frame_size <= 0)
   7591         return E_FILE_FORMAT_INVALID;
   7592 
   7593       if (frame_size > LONG_MAX)
   7594         return E_FILE_FORMAT_INVALID;
   7595 
   7596       curr.len = static_cast<long>(frame_size);
   7597       size += curr.len;  // contribution of this frame
   7598 
   7599       --frame_count;
   7600     }
   7601 
   7602     // parse last frame
   7603     if (frame_count > 0) {
   7604       if (pos > stop || pf >= pf_end)
   7605         return E_FILE_FORMAT_INVALID;
   7606 
   7607       const Frame& prev = *pf++;
   7608       assert(prev.len == frame_size);
   7609       if (prev.len != frame_size)
   7610         return E_FILE_FORMAT_INVALID;
   7611 
   7612       if (pf >= pf_end)
   7613         return E_FILE_FORMAT_INVALID;
   7614 
   7615       Frame& curr = *pf++;
   7616       if (pf != pf_end)
   7617         return E_FILE_FORMAT_INVALID;
   7618 
   7619       curr.pos = 0;  // patch later
   7620 
   7621       const long long total_size = stop - pos;
   7622 
   7623       if (total_size < size)
   7624         return E_FILE_FORMAT_INVALID;
   7625 
   7626       frame_size = total_size - size;
   7627 
   7628       if (frame_size > LONG_MAX || frame_size <= 0)
   7629         return E_FILE_FORMAT_INVALID;
   7630 
   7631       curr.len = static_cast<long>(frame_size);
   7632     }
   7633 
   7634     pf = m_frames;
   7635     while (pf != pf_end) {
   7636       Frame& f = *pf++;
   7637       assert((pos + f.len) <= stop);
   7638       if ((pos + f.len) > stop)
   7639         return E_FILE_FORMAT_INVALID;
   7640 
   7641       f.pos = pos;
   7642       pos += f.len;
   7643     }
   7644 
   7645     if (pos != stop)
   7646       return E_FILE_FORMAT_INVALID;
   7647   }
   7648 
   7649   return 0;  // success
   7650 }
   7651 
   7652 long long Block::GetTimeCode(const Cluster* pCluster) const {
   7653   if (pCluster == 0)
   7654     return m_timecode;
   7655 
   7656   const long long tc0 = pCluster->GetTimeCode();
   7657   assert(tc0 >= 0);
   7658 
   7659   const long long tc = tc0 + m_timecode;
   7660 
   7661   return tc;  // unscaled timecode units
   7662 }
   7663 
   7664 long long Block::GetTime(const Cluster* pCluster) const {
   7665   assert(pCluster);
   7666 
   7667   const long long tc = GetTimeCode(pCluster);
   7668 
   7669   const Segment* const pSegment = pCluster->m_pSegment;
   7670   const SegmentInfo* const pInfo = pSegment->GetInfo();
   7671   assert(pInfo);
   7672 
   7673   const long long scale = pInfo->GetTimeCodeScale();
   7674   assert(scale >= 1);
   7675 
   7676   const long long ns = tc * scale;
   7677 
   7678   return ns;
   7679 }
   7680 
   7681 long long Block::GetTrackNumber() const { return m_track; }
   7682 
   7683 bool Block::IsKey() const {
   7684   return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
   7685 }
   7686 
   7687 void Block::SetKey(bool bKey) {
   7688   if (bKey)
   7689     m_flags |= static_cast<unsigned char>(1 << 7);
   7690   else
   7691     m_flags &= 0x7F;
   7692 }
   7693 
   7694 bool Block::IsInvisible() const { return bool(int(m_flags & 0x08) != 0); }
   7695 
   7696 Block::Lacing Block::GetLacing() const {
   7697   const int value = int(m_flags & 0x06) >> 1;
   7698   return static_cast<Lacing>(value);
   7699 }
   7700 
   7701 int Block::GetFrameCount() const { return m_frame_count; }
   7702 
   7703 const Block::Frame& Block::GetFrame(int idx) const {
   7704   assert(idx >= 0);
   7705   assert(idx < m_frame_count);
   7706 
   7707   const Frame& f = m_frames[idx];
   7708   assert(f.pos > 0);
   7709   assert(f.len > 0);
   7710 
   7711   return f;
   7712 }
   7713 
   7714 long Block::Frame::Read(IMkvReader* pReader, unsigned char* buf) const {
   7715   assert(pReader);
   7716   assert(buf);
   7717 
   7718   const long status = pReader->Read(pos, len, buf);
   7719   return status;
   7720 }
   7721 
   7722 long long Block::GetDiscardPadding() const { return m_discard_padding; }
   7723 
   7724 }  // end namespace mkvparser
   7725