/external/libvpx/mkvparser/mkvparser.cpp

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk · C++ · 2062 lines · 1365 code · 581 blank · 116 comment · 388 complexity · 60d2d32c0653bab330da450f1efaa4e7 MD5 · raw file

  1. // Copyright (c) 2010 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. #include "mkvparser.hpp"
  9. #include <cassert>
  10. #include <cstring>
  11. #include <new>
  12. #include <climits>
  13. mkvparser::IMkvReader::~IMkvReader()
  14. {
  15. }
  16. void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)
  17. {
  18. major = 1;
  19. minor = 0;
  20. build = 0;
  21. revision = 24;
  22. }
  23. long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
  24. {
  25. assert(pReader);
  26. assert(pos >= 0);
  27. int status;
  28. //#ifdef _DEBUG
  29. // long long total, available;
  30. // status = pReader->Length(&total, &available);
  31. // assert(status >= 0);
  32. // assert((total < 0) || (available <= total));
  33. // assert(pos < available);
  34. // assert((available - pos) >= 1); //assume here max u-int len is 8
  35. //#endif
  36. len = 1;
  37. unsigned char b;
  38. status = pReader->Read(pos, 1, &b);
  39. if (status < 0) //error or underflow
  40. return status;
  41. if (status > 0) //interpreted as "underflow"
  42. return E_BUFFER_NOT_FULL;
  43. if (b == 0) //we can't handle u-int values larger than 8 bytes
  44. return E_FILE_FORMAT_INVALID;
  45. unsigned char m = 0x80;
  46. while (!(b & m))
  47. {
  48. m >>= 1;
  49. ++len;
  50. }
  51. //#ifdef _DEBUG
  52. // assert((available - pos) >= len);
  53. //#endif
  54. long long result = b & (~m);
  55. ++pos;
  56. for (int i = 1; i < len; ++i)
  57. {
  58. status = pReader->Read(pos, 1, &b);
  59. if (status < 0)
  60. {
  61. len = 1;
  62. return status;
  63. }
  64. if (status > 0)
  65. {
  66. len = 1;
  67. return E_BUFFER_NOT_FULL;
  68. }
  69. result <<= 8;
  70. result |= b;
  71. ++pos;
  72. }
  73. return result;
  74. }
  75. long long mkvparser::GetUIntLength(
  76. IMkvReader* pReader,
  77. long long pos,
  78. long& len)
  79. {
  80. assert(pReader);
  81. assert(pos >= 0);
  82. long long total, available;
  83. int status = pReader->Length(&total, &available);
  84. assert(status >= 0);
  85. assert((total < 0) || (available <= total));
  86. len = 1;
  87. if (pos >= available)
  88. return pos; //too few bytes available
  89. unsigned char b;
  90. status = pReader->Read(pos, 1, &b);
  91. if (status < 0)
  92. return status;
  93. assert(status == 0);
  94. if (b == 0) //we can't handle u-int values larger than 8 bytes
  95. return E_FILE_FORMAT_INVALID;
  96. unsigned char m = 0x80;
  97. while (!(b & m))
  98. {
  99. m >>= 1;
  100. ++len;
  101. }
  102. return 0; //success
  103. }
  104. long long mkvparser::UnserializeUInt(
  105. IMkvReader* pReader,
  106. long long pos,
  107. long long size)
  108. {
  109. assert(pReader);
  110. assert(pos >= 0);
  111. if ((size <= 0) || (size > 8))
  112. return E_FILE_FORMAT_INVALID;
  113. long long result = 0;
  114. for (long long i = 0; i < size; ++i)
  115. {
  116. unsigned char b;
  117. const long status = pReader->Read(pos, 1, &b);
  118. if (status < 0)
  119. return status;
  120. result <<= 8;
  121. result |= b;
  122. ++pos;
  123. }
  124. return result;
  125. }
  126. long mkvparser::UnserializeFloat(
  127. IMkvReader* pReader,
  128. long long pos,
  129. long long size_,
  130. double& result)
  131. {
  132. assert(pReader);
  133. assert(pos >= 0);
  134. if ((size_ != 4) && (size_ != 8))
  135. return E_FILE_FORMAT_INVALID;
  136. const long size = static_cast<long>(size_);
  137. unsigned char buf[8];
  138. const int status = pReader->Read(pos, size, buf);
  139. if (status < 0) //error
  140. return status;
  141. if (size == 4)
  142. {
  143. union
  144. {
  145. float f;
  146. unsigned long ff;
  147. };
  148. ff = 0;
  149. for (int i = 0;;)
  150. {
  151. ff |= buf[i];
  152. if (++i >= 4)
  153. break;
  154. ff <<= 8;
  155. }
  156. result = f;
  157. }
  158. else
  159. {
  160. assert(size == 8);
  161. union
  162. {
  163. double d;
  164. unsigned long long dd;
  165. };
  166. dd = 0;
  167. for (int i = 0;;)
  168. {
  169. dd |= buf[i];
  170. if (++i >= 8)
  171. break;
  172. dd <<= 8;
  173. }
  174. result = d;
  175. }
  176. return 0;
  177. }
  178. long mkvparser::UnserializeInt(
  179. IMkvReader* pReader,
  180. long long pos,
  181. long size,
  182. long long& result)
  183. {
  184. assert(pReader);
  185. assert(pos >= 0);
  186. assert(size > 0);
  187. assert(size <= 8);
  188. {
  189. signed char b;
  190. const long status = pReader->Read(pos, 1, (unsigned char*)&b);
  191. if (status < 0)
  192. return status;
  193. result = b;
  194. ++pos;
  195. }
  196. for (long i = 1; i < size; ++i)
  197. {
  198. unsigned char b;
  199. const long status = pReader->Read(pos, 1, &b);
  200. if (status < 0)
  201. return status;
  202. result <<= 8;
  203. result |= b;
  204. ++pos;
  205. }
  206. return 0; //success
  207. }
  208. long mkvparser::UnserializeString(
  209. IMkvReader* pReader,
  210. long long pos,
  211. long long size_,
  212. char*& str)
  213. {
  214. delete[] str;
  215. str = NULL;
  216. if (size_ >= LONG_MAX) //we need (size+1) chars
  217. return E_FILE_FORMAT_INVALID;
  218. const long size = static_cast<long>(size_);
  219. str = new (std::nothrow) char[size+1];
  220. if (str == NULL)
  221. return -1;
  222. unsigned char* const buf = reinterpret_cast<unsigned char*>(str);
  223. const long status = pReader->Read(pos, size, buf);
  224. if (status)
  225. {
  226. delete[] str;
  227. str = NULL;
  228. return status;
  229. }
  230. str[size] = '\0';
  231. return 0; //success
  232. }
  233. long mkvparser::ParseElementHeader(
  234. IMkvReader* pReader,
  235. long long& pos,
  236. long long stop,
  237. long long& id,
  238. long long& size)
  239. {
  240. if ((stop >= 0) && (pos >= stop))
  241. return E_FILE_FORMAT_INVALID;
  242. long len;
  243. id = ReadUInt(pReader, pos, len);
  244. if (id <= 0)
  245. return E_FILE_FORMAT_INVALID;
  246. pos += len; //consume id
  247. if ((stop >= 0) && (pos >= stop))
  248. return E_FILE_FORMAT_INVALID;
  249. size = ReadUInt(pReader, pos, len);
  250. if (size < 0)
  251. return E_FILE_FORMAT_INVALID;
  252. pos += len; //consume length of size
  253. //pos now designates payload
  254. if ((stop >= 0) && ((pos + size) > stop))
  255. return E_FILE_FORMAT_INVALID;
  256. return 0; //success
  257. }
  258. bool mkvparser::Match(
  259. IMkvReader* pReader,
  260. long long& pos,
  261. unsigned long id_,
  262. long long& val)
  263. {
  264. assert(pReader);
  265. assert(pos >= 0);
  266. long long total, available;
  267. const long status = pReader->Length(&total, &available);
  268. assert(status >= 0);
  269. assert((total < 0) || (available <= total));
  270. long len;
  271. const long long id = ReadUInt(pReader, pos, len);
  272. assert(id >= 0);
  273. assert(len > 0);
  274. assert(len <= 8);
  275. assert((pos + len) <= available);
  276. if ((unsigned long)id != id_)
  277. return false;
  278. pos += len; //consume id
  279. const long long size = ReadUInt(pReader, pos, len);
  280. assert(size >= 0);
  281. assert(size <= 8);
  282. assert(len > 0);
  283. assert(len <= 8);
  284. assert((pos + len) <= available);
  285. pos += len; //consume length of size of payload
  286. val = UnserializeUInt(pReader, pos, size);
  287. assert(val >= 0);
  288. pos += size; //consume size of payload
  289. return true;
  290. }
  291. bool mkvparser::Match(
  292. IMkvReader* pReader,
  293. long long& pos,
  294. unsigned long id_,
  295. unsigned char*& buf,
  296. size_t& buflen)
  297. {
  298. assert(pReader);
  299. assert(pos >= 0);
  300. long long total, available;
  301. long status = pReader->Length(&total, &available);
  302. assert(status >= 0);
  303. assert((total < 0) || (available <= total));
  304. long len;
  305. const long long id = ReadUInt(pReader, pos, len);
  306. assert(id >= 0);
  307. assert(len > 0);
  308. assert(len <= 8);
  309. assert((pos + len) <= available);
  310. if ((unsigned long)id != id_)
  311. return false;
  312. pos += len; //consume id
  313. const long long size_ = ReadUInt(pReader, pos, len);
  314. assert(size_ >= 0);
  315. assert(len > 0);
  316. assert(len <= 8);
  317. assert((pos + len) <= available);
  318. pos += len; //consume length of size of payload
  319. assert((pos + size_) <= available);
  320. const long buflen_ = static_cast<long>(size_);
  321. buf = new (std::nothrow) unsigned char[buflen_];
  322. assert(buf); //TODO
  323. status = pReader->Read(pos, buflen_, buf);
  324. assert(status == 0); //TODO
  325. buflen = buflen_;
  326. pos += size_; //consume size of payload
  327. return true;
  328. }
  329. namespace mkvparser
  330. {
  331. EBMLHeader::EBMLHeader() :
  332. m_docType(NULL)
  333. {
  334. Init();
  335. }
  336. EBMLHeader::~EBMLHeader()
  337. {
  338. delete[] m_docType;
  339. }
  340. void EBMLHeader::Init()
  341. {
  342. m_version = 1;
  343. m_readVersion = 1;
  344. m_maxIdLength = 4;
  345. m_maxSizeLength = 8;
  346. if (m_docType)
  347. {
  348. delete[] m_docType;
  349. m_docType = NULL;
  350. }
  351. m_docTypeVersion = 1;
  352. m_docTypeReadVersion = 1;
  353. }
  354. long long EBMLHeader::Parse(
  355. IMkvReader* pReader,
  356. long long& pos)
  357. {
  358. assert(pReader);
  359. long long total, available;
  360. long status = pReader->Length(&total, &available);
  361. if (status < 0) //error
  362. return status;
  363. pos = 0;
  364. long long end = (available >= 1024) ? 1024 : available;
  365. for (;;)
  366. {
  367. unsigned char b = 0;
  368. while (pos < end)
  369. {
  370. status = pReader->Read(pos, 1, &b);
  371. if (status < 0) //error
  372. return status;
  373. if (b == 0x1A)
  374. break;
  375. ++pos;
  376. }
  377. if (b != 0x1A)
  378. {
  379. if (pos >= 1024)
  380. return E_FILE_FORMAT_INVALID; //don't bother looking anymore
  381. if ((total >= 0) && ((total - available) < 5))
  382. return E_FILE_FORMAT_INVALID;
  383. return available + 5; //5 = 4-byte ID + 1st byte of size
  384. }
  385. if ((total >= 0) && ((total - pos) < 5))
  386. return E_FILE_FORMAT_INVALID;
  387. if ((available - pos) < 5)
  388. return pos + 5; //try again later
  389. long len;
  390. const long long result = ReadUInt(pReader, pos, len);
  391. if (result < 0) //error
  392. return result;
  393. if (result == 0x0A45DFA3) //EBML Header ID
  394. {
  395. pos += len; //consume ID
  396. break;
  397. }
  398. ++pos; //throw away just the 0x1A byte, and try again
  399. }
  400. //pos designates start of size field
  401. //get length of size field
  402. long len;
  403. long long result = GetUIntLength(pReader, pos, len);
  404. if (result < 0) //error
  405. return result;
  406. if (result > 0) //need more data
  407. return result;
  408. assert(len > 0);
  409. assert(len <= 8);
  410. if ((total >= 0) && ((total - pos) < len))
  411. return E_FILE_FORMAT_INVALID;
  412. if ((available - pos) < len)
  413. return pos + len; //try again later
  414. //get the EBML header size
  415. result = ReadUInt(pReader, pos, len);
  416. if (result < 0) //error
  417. return result;
  418. pos += len; //consume size field
  419. //pos now designates start of payload
  420. if ((total >= 0) && ((total - pos) < result))
  421. return E_FILE_FORMAT_INVALID;
  422. if ((available - pos) < result)
  423. return pos + result;
  424. end = pos + result;
  425. Init();
  426. while (pos < end)
  427. {
  428. long long id, size;
  429. status = ParseElementHeader(
  430. pReader,
  431. pos,
  432. end,
  433. id,
  434. size);
  435. if (status < 0) //error
  436. return status;
  437. if (size == 0) //weird
  438. return E_FILE_FORMAT_INVALID;
  439. if (id == 0x0286) //version
  440. {
  441. m_version = UnserializeUInt(pReader, pos, size);
  442. if (m_version <= 0)
  443. return E_FILE_FORMAT_INVALID;
  444. }
  445. else if (id == 0x02F7) //read version
  446. {
  447. m_readVersion = UnserializeUInt(pReader, pos, size);
  448. if (m_readVersion <= 0)
  449. return E_FILE_FORMAT_INVALID;
  450. }
  451. else if (id == 0x02F2) //max id length
  452. {
  453. m_maxIdLength = UnserializeUInt(pReader, pos, size);
  454. if (m_maxIdLength <= 0)
  455. return E_FILE_FORMAT_INVALID;
  456. }
  457. else if (id == 0x02F3) //max size length
  458. {
  459. m_maxSizeLength = UnserializeUInt(pReader, pos, size);
  460. if (m_maxSizeLength <= 0)
  461. return E_FILE_FORMAT_INVALID;
  462. }
  463. else if (id == 0x0282) //doctype
  464. {
  465. if (m_docType)
  466. return E_FILE_FORMAT_INVALID;
  467. status = UnserializeString(pReader, pos, size, m_docType);
  468. if (status) //error
  469. return status;
  470. }
  471. else if (id == 0x0287) //doctype version
  472. {
  473. m_docTypeVersion = UnserializeUInt(pReader, pos, size);
  474. if (m_docTypeVersion <= 0)
  475. return E_FILE_FORMAT_INVALID;
  476. }
  477. else if (id == 0x0285) //doctype read version
  478. {
  479. m_docTypeReadVersion = UnserializeUInt(pReader, pos, size);
  480. if (m_docTypeReadVersion <= 0)
  481. return E_FILE_FORMAT_INVALID;
  482. }
  483. pos += size;
  484. }
  485. assert(pos == end);
  486. return 0;
  487. }
  488. Segment::Segment(
  489. IMkvReader* pReader,
  490. long long elem_start,
  491. //long long elem_size,
  492. long long start,
  493. long long size) :
  494. m_pReader(pReader),
  495. m_element_start(elem_start),
  496. //m_element_size(elem_size),
  497. m_start(start),
  498. m_size(size),
  499. m_pos(start),
  500. m_pUnknownSize(0),
  501. m_pSeekHead(NULL),
  502. m_pInfo(NULL),
  503. m_pTracks(NULL),
  504. m_pCues(NULL),
  505. m_clusters(NULL),
  506. m_clusterCount(0),
  507. m_clusterPreloadCount(0),
  508. m_clusterSize(0)
  509. {
  510. }
  511. Segment::~Segment()
  512. {
  513. const long count = m_clusterCount + m_clusterPreloadCount;
  514. Cluster** i = m_clusters;
  515. Cluster** j = m_clusters + count;
  516. while (i != j)
  517. {
  518. Cluster* const p = *i++;
  519. assert(p);
  520. delete p;
  521. }
  522. delete[] m_clusters;
  523. delete m_pTracks;
  524. delete m_pInfo;
  525. delete m_pCues;
  526. delete m_pSeekHead;
  527. }
  528. long long Segment::CreateInstance(
  529. IMkvReader* pReader,
  530. long long pos,
  531. Segment*& pSegment)
  532. {
  533. assert(pReader);
  534. assert(pos >= 0);
  535. pSegment = NULL;
  536. long long total, available;
  537. const long status = pReader->Length(&total, &available);
  538. if (status < 0) //error
  539. return status;
  540. if (available < 0)
  541. return -1;
  542. if ((total >= 0) && (available > total))
  543. return -1;
  544. const long long end = (total >= 0) ? total : available;
  545. //TODO: this might need to be liberalized
  546. //I would assume that in practice this loop would execute
  547. //exactly once, but we allow for other elements (e.g. Void)
  548. //to immediately follow the EBML header. This is fine for
  549. //the source filter case (since the entire file is available),
  550. //but in the splitter case over a network we should probably
  551. //just give up early. We could for example decide only to
  552. //execute this loop a maximum of, say, 10 times.
  553. //TODO:
  554. //There is an implied "give up early" by only parsing up
  555. //to the available limit. We do do that, but only if the
  556. //total file size is unknown. We could decide to always
  557. //use what's available as our limit (irrespective of whether
  558. //we happen to know the total file length). This would have
  559. //as its sense "parse this much of the file before giving up",
  560. //which a slightly different sense from "try to parse up to
  561. //10 EMBL elements before giving up".
  562. while (pos < end)
  563. {
  564. //Read ID
  565. long len;
  566. long long result = GetUIntLength(pReader, pos, len);
  567. if (result) //error, or too few available bytes
  568. return result;
  569. if ((pos + len) > end)
  570. return E_FILE_FORMAT_INVALID;
  571. if ((pos + len) > available)
  572. return pos + len;
  573. const long long idpos = pos;
  574. const long long id = ReadUInt(pReader, pos, len);
  575. if (id < 0) //error
  576. return id;
  577. pos += len; //consume ID
  578. //Read Size
  579. result = GetUIntLength(pReader, pos, len);
  580. if (result) //error, or too few available bytes
  581. return result;
  582. if ((pos + len) > end)
  583. return E_FILE_FORMAT_INVALID;
  584. if ((pos + len) > available)
  585. return pos + len;
  586. long long size = ReadUInt(pReader, pos, len);
  587. if (size < 0) //error
  588. return size;
  589. pos += len; //consume length of size of element
  590. //Pos now points to start of payload
  591. //Handle "unknown size" for live streaming of webm files.
  592. const long long unknown_size = (1LL << (7 * len)) - 1;
  593. if (id == 0x08538067) //Segment ID
  594. {
  595. if (size == unknown_size)
  596. size = -1;
  597. else if (total < 0)
  598. size = -1;
  599. else if ((pos + size) > total)
  600. size = -1;
  601. pSegment = new (std::nothrow) Segment(
  602. pReader,
  603. idpos,
  604. //elem_size
  605. pos,
  606. size);
  607. if (pSegment == 0)
  608. return -1; //generic error
  609. return 0; //success
  610. }
  611. if (size == unknown_size)
  612. return E_FILE_FORMAT_INVALID;
  613. if ((pos + size) > end)
  614. return E_FILE_FORMAT_INVALID;
  615. pos += size; //consume payload
  616. }
  617. return E_FILE_FORMAT_INVALID; //there is no segment
  618. //TODO: this might need to be liberalized. See comments above.
  619. }
  620. long long Segment::ParseHeaders()
  621. {
  622. //Outermost (level 0) segment object has been constructed,
  623. //and pos designates start of payload. We need to find the
  624. //inner (level 1) elements.
  625. long long total, available;
  626. const int status = m_pReader->Length(&total, &available);
  627. if (status < 0) //error
  628. return status;
  629. assert((total < 0) || (available <= total));
  630. const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
  631. assert((segment_stop < 0) || (total < 0) || (segment_stop <= total));
  632. assert((segment_stop < 0) || (m_pos <= segment_stop));
  633. for (;;)
  634. {
  635. if ((total >= 0) && (m_pos >= total))
  636. break;
  637. if ((segment_stop >= 0) && (m_pos >= segment_stop))
  638. break;
  639. long long pos = m_pos;
  640. const long long element_start = pos;
  641. if ((pos + 1) > available)
  642. return (pos + 1);
  643. long len;
  644. long long result = GetUIntLength(m_pReader, pos, len);
  645. if (result < 0) //error
  646. return result;
  647. if (result > 0) //underflow (weird)
  648. return (pos + 1);
  649. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  650. return E_FILE_FORMAT_INVALID;
  651. if ((pos + len) > available)
  652. return pos + len;
  653. const long long idpos = pos;
  654. const long long id = ReadUInt(m_pReader, idpos, len);
  655. if (id < 0) //error
  656. return id;
  657. if (id == 0x0F43B675) //Cluster ID
  658. break;
  659. pos += len; //consume ID
  660. if ((pos + 1) > available)
  661. return (pos + 1);
  662. //Read Size
  663. result = GetUIntLength(m_pReader, pos, len);
  664. if (result < 0) //error
  665. return result;
  666. if (result > 0) //underflow (weird)
  667. return (pos + 1);
  668. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  669. return E_FILE_FORMAT_INVALID;
  670. if ((pos + len) > available)
  671. return pos + len;
  672. const long long size = ReadUInt(m_pReader, pos, len);
  673. if (size < 0) //error
  674. return size;
  675. pos += len; //consume length of size of element
  676. const long long element_size = size + pos - element_start;
  677. //Pos now points to start of payload
  678. if ((segment_stop >= 0) && ((pos + size) > segment_stop))
  679. return E_FILE_FORMAT_INVALID;
  680. //We read EBML elements either in total or nothing at all.
  681. if ((pos + size) > available)
  682. return pos + size;
  683. if (id == 0x0549A966) //Segment Info ID
  684. {
  685. if (m_pInfo)
  686. return E_FILE_FORMAT_INVALID;
  687. m_pInfo = new (std::nothrow) SegmentInfo(
  688. this,
  689. pos,
  690. size,
  691. element_start,
  692. element_size);
  693. if (m_pInfo == NULL)
  694. return -1;
  695. const long status = m_pInfo->Parse();
  696. if (status)
  697. return status;
  698. }
  699. else if (id == 0x0654AE6B) //Tracks ID
  700. {
  701. if (m_pTracks)
  702. return E_FILE_FORMAT_INVALID;
  703. m_pTracks = new (std::nothrow) Tracks(this,
  704. pos,
  705. size,
  706. element_start,
  707. element_size);
  708. if (m_pTracks == NULL)
  709. return -1;
  710. const long status = m_pTracks->Parse();
  711. if (status)
  712. return status;
  713. }
  714. else if (id == 0x0C53BB6B) //Cues ID
  715. {
  716. if (m_pCues == NULL)
  717. {
  718. m_pCues = new (std::nothrow) Cues(
  719. this,
  720. pos,
  721. size,
  722. element_start,
  723. element_size);
  724. if (m_pCues == NULL)
  725. return -1;
  726. }
  727. }
  728. else if (id == 0x014D9B74) //SeekHead ID
  729. {
  730. if (m_pSeekHead == NULL)
  731. {
  732. m_pSeekHead = new (std::nothrow) SeekHead(
  733. this,
  734. pos,
  735. size,
  736. element_start,
  737. element_size);
  738. if (m_pSeekHead == NULL)
  739. return -1;
  740. const long status = m_pSeekHead->Parse();
  741. if (status)
  742. return status;
  743. }
  744. }
  745. m_pos = pos + size; //consume payload
  746. }
  747. assert((segment_stop < 0) || (m_pos <= segment_stop));
  748. if (m_pInfo == NULL) //TODO: liberalize this behavior
  749. return E_FILE_FORMAT_INVALID;
  750. if (m_pTracks == NULL)
  751. return E_FILE_FORMAT_INVALID;
  752. return 0; //success
  753. }
  754. long Segment::LoadCluster(
  755. long long& pos,
  756. long& len)
  757. {
  758. for (;;)
  759. {
  760. const long result = DoLoadCluster(pos, len);
  761. if (result <= 1)
  762. return result;
  763. }
  764. }
  765. long Segment::DoLoadCluster(
  766. long long& pos,
  767. long& len)
  768. {
  769. if (m_pos < 0)
  770. return DoLoadClusterUnknownSize(pos, len);
  771. long long total, avail;
  772. long status = m_pReader->Length(&total, &avail);
  773. if (status < 0) //error
  774. return status;
  775. assert((total < 0) || (avail <= total));
  776. const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
  777. long long cluster_off = -1; //offset relative to start of segment
  778. long long cluster_size = -1; //size of cluster payload
  779. for (;;)
  780. {
  781. if ((total >= 0) && (m_pos >= total))
  782. return 1; //no more clusters
  783. if ((segment_stop >= 0) && (m_pos >= segment_stop))
  784. return 1; //no more clusters
  785. pos = m_pos;
  786. //Read ID
  787. if ((pos + 1) > avail)
  788. {
  789. len = 1;
  790. return E_BUFFER_NOT_FULL;
  791. }
  792. long long result = GetUIntLength(m_pReader, pos, len);
  793. if (result < 0) //error
  794. return static_cast<long>(result);
  795. if (result > 0) //weird
  796. return E_BUFFER_NOT_FULL;
  797. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  798. return E_FILE_FORMAT_INVALID;
  799. if ((pos + len) > avail)
  800. return E_BUFFER_NOT_FULL;
  801. const long long idpos = pos;
  802. const long long id = ReadUInt(m_pReader, idpos, len);
  803. if (id < 0) //error (or underflow)
  804. return static_cast<long>(id);
  805. pos += len; //consume ID
  806. //Read Size
  807. if ((pos + 1) > avail)
  808. {
  809. len = 1;
  810. return E_BUFFER_NOT_FULL;
  811. }
  812. result = GetUIntLength(m_pReader, pos, len);
  813. if (result < 0) //error
  814. return static_cast<long>(result);
  815. if (result > 0) //weird
  816. return E_BUFFER_NOT_FULL;
  817. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  818. return E_FILE_FORMAT_INVALID;
  819. if ((pos + len) > avail)
  820. return E_BUFFER_NOT_FULL;
  821. const long long size = ReadUInt(m_pReader, pos, len);
  822. if (size < 0) //error
  823. return static_cast<long>(size);
  824. pos += len; //consume length of size of element
  825. //pos now points to start of payload
  826. if (size == 0) //weird
  827. {
  828. m_pos = pos;
  829. continue;
  830. }
  831. const long long unknown_size = (1LL << (7 * len)) - 1;
  832. #if 0 //we must handle this to support live webm
  833. if (size == unknown_size)
  834. return E_FILE_FORMAT_INVALID; //TODO: allow this
  835. #endif
  836. if ((segment_stop >= 0) &&
  837. (size != unknown_size) &&
  838. ((pos + size) > segment_stop))
  839. {
  840. return E_FILE_FORMAT_INVALID;
  841. }
  842. #if 0 //commented-out, to support incremental cluster parsing
  843. len = static_cast<long>(size);
  844. if ((pos + size) > avail)
  845. return E_BUFFER_NOT_FULL;
  846. #endif
  847. if (id == 0x0C53BB6B) //Cues ID
  848. {
  849. if (size == unknown_size)
  850. return E_FILE_FORMAT_INVALID; //TODO: liberalize
  851. if (m_pCues == NULL)
  852. {
  853. const long long element_size = (pos - idpos) + size;
  854. m_pCues = new Cues(this,
  855. pos,
  856. size,
  857. idpos,
  858. element_size);
  859. assert(m_pCues); //TODO
  860. }
  861. m_pos = pos + size; //consume payload
  862. continue;
  863. }
  864. if (id != 0x0F43B675) //Cluster ID
  865. {
  866. if (size == unknown_size)
  867. return E_FILE_FORMAT_INVALID; //TODO: liberalize
  868. m_pos = pos + size; //consume payload
  869. continue;
  870. }
  871. //We have a cluster.
  872. cluster_off = idpos - m_start; //relative pos
  873. if (size != unknown_size)
  874. cluster_size = size;
  875. break;
  876. }
  877. assert(cluster_off >= 0); //have cluster
  878. long long pos_;
  879. long len_;
  880. status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_);
  881. if (status < 0) //error, or underflow
  882. {
  883. pos = pos_;
  884. len = len_;
  885. return status;
  886. }
  887. //status == 0 means "no block entries found"
  888. //status > 0 means "found at least one block entry"
  889. //TODO:
  890. //The issue here is that the segment increments its own
  891. //pos ptr past the most recent cluster parsed, and then
  892. //starts from there to parse the next cluster. If we
  893. //don't know the size of the current cluster, then we
  894. //must either parse its payload (as we do below), looking
  895. //for the cluster (or cues) ID to terminate the parse.
  896. //This isn't really what we want: rather, we really need
  897. //a way to create the curr cluster object immediately.
  898. //The pity is that cluster::parse can determine its own
  899. //boundary, and we largely duplicate that same logic here.
  900. //
  901. //Maybe we need to get rid of our look-ahead preloading
  902. //in source::parse???
  903. //
  904. //As we're parsing the blocks in the curr cluster
  905. //(in cluster::parse), we should have some way to signal
  906. //to the segment that we have determined the boundary,
  907. //so it can adjust its own segment::m_pos member.
  908. //
  909. //The problem is that we're asserting in asyncreadinit,
  910. //because we adjust the pos down to the curr seek pos,
  911. //and the resulting adjusted len is > 2GB. I'm suspicious
  912. //that this is even correct, but even if it is, we can't
  913. //be loading that much data in the cache anyway.
  914. const long idx = m_clusterCount;
  915. if (m_clusterPreloadCount > 0)
  916. {
  917. assert(idx < m_clusterSize);
  918. Cluster* const pCluster = m_clusters[idx];
  919. assert(pCluster);
  920. assert(pCluster->m_index < 0);
  921. const long long off = pCluster->GetPosition();
  922. assert(off >= 0);
  923. if (off == cluster_off) //preloaded already
  924. {
  925. if (status == 0) //no entries found
  926. return E_FILE_FORMAT_INVALID;
  927. if (cluster_size >= 0)
  928. pos += cluster_size;
  929. else
  930. {
  931. const long long element_size = pCluster->GetElementSize();
  932. if (element_size <= 0)
  933. return E_FILE_FORMAT_INVALID; //TODO: handle this case
  934. pos = pCluster->m_element_start + element_size;
  935. }
  936. pCluster->m_index = idx; //move from preloaded to loaded
  937. ++m_clusterCount;
  938. --m_clusterPreloadCount;
  939. m_pos = pos; //consume payload
  940. assert((segment_stop < 0) || (m_pos <= segment_stop));
  941. return 0; //success
  942. }
  943. }
  944. if (status == 0) //no entries found
  945. {
  946. if (cluster_size < 0)
  947. return E_FILE_FORMAT_INVALID; //TODO: handle this
  948. pos += cluster_size;
  949. if ((total >= 0) && (pos >= total))
  950. {
  951. m_pos = total;
  952. return 1; //no more clusters
  953. }
  954. if ((segment_stop >= 0) && (pos >= segment_stop))
  955. {
  956. m_pos = segment_stop;
  957. return 1; //no more clusters
  958. }
  959. m_pos = pos;
  960. return 2; //try again
  961. }
  962. //status > 0 means we have an entry
  963. Cluster* const pCluster = Cluster::Create(this,
  964. idx,
  965. cluster_off);
  966. //element_size);
  967. assert(pCluster);
  968. AppendCluster(pCluster);
  969. assert(m_clusters);
  970. assert(idx < m_clusterSize);
  971. assert(m_clusters[idx] == pCluster);
  972. if (cluster_size >= 0)
  973. {
  974. pos += cluster_size;
  975. m_pos = pos;
  976. assert((segment_stop < 0) || (m_pos <= segment_stop));
  977. return 0;
  978. }
  979. m_pUnknownSize = pCluster;
  980. m_pos = -pos;
  981. return 0; //partial success, since we have a new cluster
  982. //status == 0 means "no block entries found"
  983. //pos designates start of payload
  984. //m_pos has NOT been adjusted yet (in case we need to come back here)
  985. #if 0
  986. if (cluster_size < 0) //unknown size
  987. {
  988. const long long payload_pos = pos; //absolute pos of cluster payload
  989. for (;;) //determine cluster size
  990. {
  991. if ((total >= 0) && (pos >= total))
  992. break;
  993. if ((segment_stop >= 0) && (pos >= segment_stop))
  994. break; //no more clusters
  995. //Read ID
  996. if ((pos + 1) > avail)
  997. {
  998. len = 1;
  999. return E_BUFFER_NOT_FULL;
  1000. }
  1001. long long result = GetUIntLength(m_pReader, pos, len);
  1002. if (result < 0) //error
  1003. return static_cast<long>(result);
  1004. if (result > 0) //weird
  1005. return E_BUFFER_NOT_FULL;
  1006. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  1007. return E_FILE_FORMAT_INVALID;
  1008. if ((pos + len) > avail)
  1009. return E_BUFFER_NOT_FULL;
  1010. const long long idpos = pos;
  1011. const long long id = ReadUInt(m_pReader, idpos, len);
  1012. if (id < 0) //error (or underflow)
  1013. return static_cast<long>(id);
  1014. //This is the distinguished set of ID's we use to determine
  1015. //that we have exhausted the sub-element's inside the cluster
  1016. //whose ID we parsed earlier.
  1017. if (id == 0x0F43B675) //Cluster ID
  1018. break;
  1019. if (id == 0x0C53BB6B) //Cues ID
  1020. break;
  1021. switch (id)
  1022. {
  1023. case 0x20: //BlockGroup
  1024. case 0x23: //Simple Block
  1025. case 0x67: //TimeCode
  1026. case 0x2B: //PrevSize
  1027. break;
  1028. default:
  1029. assert(false);
  1030. break;
  1031. }
  1032. pos += len; //consume ID (of sub-element)
  1033. //Read Size
  1034. if ((pos + 1) > avail)
  1035. {
  1036. len = 1;
  1037. return E_BUFFER_NOT_FULL;
  1038. }
  1039. result = GetUIntLength(m_pReader, pos, len);
  1040. if (result < 0) //error
  1041. return static_cast<long>(result);
  1042. if (result > 0) //weird
  1043. return E_BUFFER_NOT_FULL;
  1044. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  1045. return E_FILE_FORMAT_INVALID;
  1046. if ((pos + len) > avail)
  1047. return E_BUFFER_NOT_FULL;
  1048. const long long size = ReadUInt(m_pReader, pos, len);
  1049. if (size < 0) //error
  1050. return static_cast<long>(size);
  1051. pos += len; //consume size field of element
  1052. //pos now points to start of sub-element's payload
  1053. if (size == 0) //weird
  1054. continue;
  1055. const long long unknown_size = (1LL << (7 * len)) - 1;
  1056. if (size == unknown_size)
  1057. return E_FILE_FORMAT_INVALID; //not allowed for sub-elements
  1058. if ((segment_stop >= 0) && ((pos + size) > segment_stop)) //weird
  1059. return E_FILE_FORMAT_INVALID;
  1060. pos += size; //consume payload of sub-element
  1061. assert((segment_stop < 0) || (pos <= segment_stop));
  1062. } //determine cluster size
  1063. cluster_size = pos - payload_pos;
  1064. assert(cluster_size >= 0);
  1065. pos = payload_pos; //reset and re-parse original cluster
  1066. }
  1067. if (m_clusterPreloadCount > 0)
  1068. {
  1069. assert(idx < m_clusterSize);
  1070. Cluster* const pCluster = m_clusters[idx];
  1071. assert(pCluster);
  1072. assert(pCluster->m_index < 0);
  1073. const long long off = pCluster->GetPosition();
  1074. assert(off >= 0);
  1075. if (off == cluster_off) //preloaded already
  1076. return E_FILE_FORMAT_INVALID; //subtle
  1077. }
  1078. m_pos = pos + cluster_size; //consume payload
  1079. assert((segment_stop < 0) || (m_pos <= segment_stop));
  1080. return 2; //try to find another cluster
  1081. #endif
  1082. }
  1083. long Segment::DoLoadClusterUnknownSize(
  1084. long long& pos,
  1085. long& len)
  1086. {
  1087. assert(m_pos < 0);
  1088. assert(m_pUnknownSize);
  1089. #if 0
  1090. assert(m_pUnknownSize->GetElementSize() < 0); //TODO: verify this
  1091. const long long element_start = m_pUnknownSize->m_element_start;
  1092. pos = -m_pos;
  1093. assert(pos > element_start);
  1094. //We have already consumed the (cluster) ID and size fields.
  1095. //We just need to consume the blocks and other sub-elements
  1096. //of this cluster, until we discover the boundary.
  1097. long long total, avail;
  1098. long status = m_pReader->Length(&total, &avail);
  1099. if (status < 0) //error
  1100. return status;
  1101. assert((total < 0) || (avail <= total));
  1102. const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
  1103. long long element_size = -1;
  1104. for (;;) //determine cluster size
  1105. {
  1106. if ((total >= 0) && (pos >= total))
  1107. {
  1108. element_size = total - element_start;
  1109. assert(element_size > 0);
  1110. break;
  1111. }
  1112. if ((segment_stop >= 0) && (pos >= segment_stop))
  1113. {
  1114. element_size = segment_stop - element_start;
  1115. assert(element_size > 0);
  1116. break;
  1117. }
  1118. //Read ID
  1119. if ((pos + 1) > avail)
  1120. {
  1121. len = 1;
  1122. return E_BUFFER_NOT_FULL;
  1123. }
  1124. long long result = GetUIntLength(m_pReader, pos, len);
  1125. if (result < 0) //error
  1126. return static_cast<long>(result);
  1127. if (result > 0) //weird
  1128. return E_BUFFER_NOT_FULL;
  1129. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  1130. return E_FILE_FORMAT_INVALID;
  1131. if ((pos + len) > avail)
  1132. return E_BUFFER_NOT_FULL;
  1133. const long long idpos = pos;
  1134. const long long id = ReadUInt(m_pReader, idpos, len);
  1135. if (id < 0) //error (or underflow)
  1136. return static_cast<long>(id);
  1137. //This is the distinguished set of ID's we use to determine
  1138. //that we have exhausted the sub-element's inside the cluster
  1139. //whose ID we parsed earlier.
  1140. if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) //Cluster ID or Cues ID
  1141. {
  1142. element_size = pos - element_start;
  1143. assert(element_size > 0);
  1144. break;
  1145. }
  1146. #ifdef _DEBUG
  1147. switch (id)
  1148. {
  1149. case 0x20: //BlockGroup
  1150. case 0x23: //Simple Block
  1151. case 0x67: //TimeCode
  1152. case 0x2B: //PrevSize
  1153. break;
  1154. default:
  1155. assert(false);
  1156. break;
  1157. }
  1158. #endif
  1159. pos += len; //consume ID (of sub-element)
  1160. //Read Size
  1161. if ((pos + 1) > avail)
  1162. {
  1163. len = 1;
  1164. return E_BUFFER_NOT_FULL;
  1165. }
  1166. result = GetUIntLength(m_pReader, pos, len);
  1167. if (result < 0) //error
  1168. return static_cast<long>(result);
  1169. if (result > 0) //weird
  1170. return E_BUFFER_NOT_FULL;
  1171. if ((segment_stop >= 0) && ((pos + len) > segment_stop))
  1172. return E_FILE_FORMAT_INVALID;
  1173. if ((pos + len) > avail)
  1174. return E_BUFFER_NOT_FULL;
  1175. const long long size = ReadUInt(m_pReader, pos, len);
  1176. if (size < 0) //error
  1177. return static_cast<long>(size);
  1178. pos += len; //consume size field of element
  1179. //pos now points to start of sub-element's payload
  1180. if (size == 0) //weird
  1181. continue;
  1182. const long long unknown_size = (1LL << (7 * len)) - 1;
  1183. if (size == unknown_size)
  1184. return E_FILE_FORMAT_INVALID; //not allowed for sub-elements
  1185. if ((segment_stop >= 0) && ((pos + size) > segment_stop)) //weird
  1186. return E_FILE_FORMAT_INVALID;
  1187. pos += size; //consume payload of sub-element
  1188. assert((segment_stop < 0) || (pos <= segment_stop));
  1189. } //determine cluster size
  1190. assert(element_size >= 0);
  1191. m_pos = element_start + element_size;
  1192. m_pUnknownSize = 0;
  1193. return 2; //continue parsing
  1194. #else
  1195. const long status = m_pUnknownSize->Parse(pos, len);
  1196. if (status < 0) //error or underflow
  1197. return status;
  1198. if (status == 0) //parsed a block
  1199. return 2; //continue parsing
  1200. assert(status > 0); //nothing left to parse of this cluster
  1201. const long long start = m_pUnknownSize->m_element_start;
  1202. const long long size = m_pUnknownSize->GetElementSize();
  1203. assert(size >= 0);
  1204. pos = start + size;
  1205. m_pos = pos;
  1206. m_pUnknownSize = 0;
  1207. return 2; //continue parsing
  1208. #endif
  1209. }
  1210. void Segment::AppendCluster(Cluster* pCluster)
  1211. {
  1212. assert(pCluster);
  1213. assert(pCluster->m_index >= 0);
  1214. const long count = m_clusterCount + m_clusterPreloadCount;
  1215. long& size = m_clusterSize;
  1216. assert(size >= count);
  1217. const long idx = pCluster->m_index;
  1218. assert(idx == m_clusterCount);
  1219. if (count >= size)
  1220. {
  1221. const long n = (size <= 0) ? 2048 : 2*size;
  1222. Cluster** const qq = new Cluster*[n];
  1223. Cluster** q = qq;
  1224. Cluster** p = m_clusters;
  1225. Cluster** const pp = p + count;
  1226. while (p != pp)
  1227. *q++ = *p++;
  1228. delete[] m_clusters;
  1229. m_clusters = qq;
  1230. size = n;
  1231. }
  1232. if (m_clusterPreloadCount > 0)
  1233. {
  1234. assert(m_clusters);
  1235. Cluster** const p = m_clusters + m_clusterCount;
  1236. assert(*p);
  1237. assert((*p)->m_index < 0);
  1238. Cluster** q = p + m_clusterPreloadCount;
  1239. assert(q < (m_clusters + size));
  1240. for (;;)
  1241. {
  1242. Cluster** const qq = q - 1;
  1243. assert((*qq)->m_index < 0);
  1244. *q = *qq;
  1245. q = qq;
  1246. if (q == p)
  1247. break;
  1248. }
  1249. }
  1250. m_clusters[idx] = pCluster;
  1251. ++m_clusterCount;
  1252. }
  1253. void Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx)
  1254. {
  1255. assert(pCluster);
  1256. assert(pCluster->m_index < 0);
  1257. assert(idx >= m_clusterCount);
  1258. const long count = m_clusterCount + m_clusterPreloadCount;
  1259. long& size = m_clusterSize;
  1260. assert(size >= count);
  1261. if (count >= size)
  1262. {
  1263. const long n = (size <= 0) ? 2048 : 2*size;
  1264. Cluster** const qq = new Cluster*[n];
  1265. Cluster** q = qq;
  1266. Cluster** p = m_clusters;
  1267. Cluster** const pp = p + count;
  1268. while (p != pp)
  1269. *q++ = *p++;
  1270. delete[] m_clusters;
  1271. m_clusters = qq;
  1272. size = n;
  1273. }
  1274. assert(m_clusters);
  1275. Cluster** const p = m_clusters + idx;
  1276. Cluster** q = m_clusters + count;
  1277. assert(q >= p);
  1278. assert(q < (m_clusters + size));
  1279. while (q > p)
  1280. {
  1281. Cluster** const qq = q - 1;
  1282. assert((*qq)->m_index < 0);
  1283. *q = *qq;
  1284. q = qq;
  1285. }
  1286. m_clusters[idx] = pCluster;
  1287. ++m_clusterPreloadCount;
  1288. }
  1289. long Segment::Load()
  1290. {
  1291. assert(m_clusters == NULL);
  1292. assert(m_clusterSize == 0);
  1293. assert(m_clusterCount == 0);
  1294. //assert(m_size >= 0);
  1295. //Outermost (level 0) segment object has been constructed,
  1296. //and pos designates start of payload. We need to find the
  1297. //inner (level 1) elements.
  1298. const long long header_status = ParseHeaders();
  1299. if (header_status < 0) //error
  1300. return static_cast<long>(header_status);
  1301. if (header_status > 0) //underflow
  1302. return E_BUFFER_NOT_FULL;
  1303. assert(m_pInfo);
  1304. assert(m_pTracks);
  1305. for (;;)
  1306. {
  1307. const int status = LoadCluster();
  1308. if (status < 0) //error
  1309. return status;
  1310. if (status >= 1) //no more clusters
  1311. return 0;
  1312. }
  1313. }
  1314. SeekHead::SeekHead(
  1315. Segment* pSegment,
  1316. long long start,
  1317. long long size_,
  1318. long long element_start,
  1319. long long element_size) :
  1320. m_pSegment(pSegment),
  1321. m_start(start),
  1322. m_size(size_),
  1323. m_element_start(element_start),
  1324. m_element_size(element_size),
  1325. m_entries(0),
  1326. m_entry_count(0),
  1327. m_void_elements(0),
  1328. m_void_element_count(0)
  1329. {
  1330. }
  1331. SeekHead::~SeekHead()
  1332. {
  1333. delete[] m_entries;
  1334. delete[] m_void_elements;
  1335. }
  1336. long SeekHead::Parse()
  1337. {
  1338. IMkvReader* const pReader = m_pSegment->m_pReader;
  1339. long long pos = m_start;
  1340. const long long stop = m_start + m_size;
  1341. //first count the seek head entries
  1342. int entry_count = 0;
  1343. int void_element_count = 0;
  1344. while (pos < stop)
  1345. {
  1346. long long id, size;
  1347. const long status = ParseElementHeader(
  1348. pReader,
  1349. pos,
  1350. stop,
  1351. id,
  1352. size);
  1353. if (status < 0) //error
  1354. return status;
  1355. if (id == 0x0DBB) //SeekEntry ID
  1356. ++entry_count;
  1357. else if (id == 0x6C) //Void ID
  1358. ++void_element_count;
  1359. pos += size; //consume payload
  1360. assert(pos <= stop);
  1361. }
  1362. assert(pos == stop);
  1363. m_entries = new (std::nothrow) Entry[entry_count];
  1364. if (m_entries == NULL)
  1365. return -1;
  1366. m_void_elements = new (std::nothrow) VoidElement[void_element_count];
  1367. if (m_void_elements == NULL)
  1368. return -1;
  1369. //now parse the entries and void elements
  1370. Entry* pEntry = m_entries;
  1371. VoidElement* pVoidElement = m_void_elements;
  1372. pos = m_start;
  1373. while (pos < stop)
  1374. {
  1375. const long long idpos = pos;
  1376. long long id, size;
  1377. const long status = ParseElementHeader(
  1378. pReader,
  1379. pos,
  1380. stop,
  1381. id,
  1382. size);
  1383. if (status < 0) //error
  1384. return status;
  1385. if (id == 0x0DBB) //SeekEntry ID
  1386. {
  1387. if (ParseEntry(pReader, pos, size, pEntry))
  1388. {
  1389. Entry& e = *pEntry++;
  1390. e.element_start = idpos;
  1391. e.element_size = (pos + size) - idpos;
  1392. }
  1393. }
  1394. else if (id == 0x6C) //Void ID
  1395. {
  1396. VoidElement& e = *pVoidElement++;
  1397. e.element_start = idpos;
  1398. e.element_size = (pos + size) - idpos;
  1399. }
  1400. pos += size; //consume payload
  1401. assert(pos <= stop);
  1402. }
  1403. assert(pos == stop);
  1404. ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries);
  1405. assert(count_ >= 0);
  1406. assert(count_ <= entry_count);
  1407. m_entry_count = static_cast<int>(count_);
  1408. count_ = ptrdiff_t(pVoidElement - m_void_elements);
  1409. assert(count_ >= 0);
  1410. assert(count_ <= void_element_count);
  1411. m_void_element_count = static_cast<int>(count_);
  1412. return 0;
  1413. }
  1414. int SeekHead::GetCount() const
  1415. {
  1416. return m_entry_count;
  1417. }
  1418. const SeekHead::Entry* SeekHead::GetEntry(int idx) const
  1419. {
  1420. if (idx < 0)
  1421. return 0;
  1422. if (idx >= m_entry_count)
  1423. return 0;
  1424. return m_entries + idx;
  1425. }
  1426. int SeekHead::GetVoidElementCount() const
  1427. {
  1428. return m_void_element_count;
  1429. }
  1430. const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const
  1431. {
  1432. if (idx < 0)
  1433. return 0;
  1434. if (idx >= m_void_element_count)
  1435. return 0;
  1436. return m_void_elements + idx;
  1437. }
  1438. #if 0
  1439. void Segment::ParseCues(long long off)
  1440. {
  1441. if (m_pCues)
  1442. return;
  1443. //odbgstream os;
  1444. //os << "Segment::ParseCues (begin)" << endl;
  1445. long long pos = m_start + off;
  1446. const long long element_start = pos;
  1447. const long long stop = m_start + m_size;
  1448. long len;
  1449. long long result = GetUIntLength(m_pReader, pos, len);
  1450. assert(result == 0);
  1451. assert((pos + len) <= stop);
  1452. const long long idpos = pos;
  1453. const long long id = ReadUInt(m_pReader, idpos, len);
  1454. assert(id == 0x0C53BB6B); //Cues ID
  1455. pos += len; //consume ID
  1456. assert(pos < stop);
  1457. //Read Size
  1458. result = GetUIntLength(m_pReader, pos, len);
  1459. assert(result == 0);
  1460. assert((pos + len) <= stop);
  1461. const long long size = ReadUInt(m_pReader, pos, len);
  1462. assert(size >= 0);
  1463. pos += len; //consume length of size of element
  1464. assert((pos + size) <= stop);
  1465. const long long element_size = size + pos - element_start;
  1466. //Pos now points to start of payload
  1467. m_pCues = new Cues(this, pos, size, element_start, element_size);
  1468. assert(m_pCues); //TODO
  1469. //os << "Segment::ParseCues (end)" << endl;
  1470. }
  1471. #else
  1472. long Segment::ParseCues(
  1473. long long off,
  1474. long long& pos,
  1475. long& len)
  1476. {
  1477. if (m_pCues)
  1478. return 0; //success
  1479. if (off < 0)
  1480. return -1;
  1481. long long tota