spacepaste

  1.  
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mp4_demuxer/MoofParser.h"
  6. #include "mp4_demuxer/Box.h"
  7. #include "mp4_demuxer/SinfParser.h"
  8. #include <limits>
  9. #include "Intervals.h"
  10. #include "prlog.h"
  11. #ifdef PR_LOGGING
  12. extern PRLogModuleInfo* GetDemuxerLog();
  13. /* Polyfill __func__ on MSVC to pass to the log. */
  14. #ifdef _MSC_VER
  15. #define __func__ __FUNCTION__
  16. #endif
  17. #define STRINGIFY(x) #x
  18. #define TOSTRING(x) STRINGIFY(x)
  19. #define LOG(name, arg, ...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (TOSTRING(name) "(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
  20. #else
  21. #define LOG(...)
  22. #endif
  23. namespace mp4_demuxer
  24. {
  25. using namespace stagefright;
  26. using namespace mozilla;
  27. bool
  28. MoofParser::RebuildFragmentedIndex(
  29. const nsTArray<mozilla::MediaByteRange>& aByteRanges)
  30. {
  31. BoxContext context(mSource, aByteRanges);
  32. return RebuildFragmentedIndex(context);
  33. }
  34. bool
  35. MoofParser::RebuildFragmentedIndex(BoxContext& aContext)
  36. {
  37. bool foundValidMoof = false;
  38. bool foundMdat = false;
  39. for (Box box(&aContext, mOffset); box.IsAvailable(); box = box.Next()) {
  40. if (box.IsType("moov") && mInitRange.IsNull()) {
  41. mInitRange = MediaByteRange(0, box.Range().mEnd);
  42. ParseMoov(box);
  43. } else if (box.IsType("moof")) {
  44. Moof moof(box, mTrex, mMvhd, mMdhd, mEdts, mSinf, mIsAudio);
  45. if (!moof.IsValid() && !box.Next().IsAvailable()) {
  46. // Moof isn't valid abort search for now.
  47. break;
  48. }
  49. if (!mMoofs.IsEmpty()) {
  50. // Stitch time ranges together in the case of a (hopefully small) time
  51. // range gap between moofs.
  52. mMoofs.LastElement().FixRounding(moof);
  53. }
  54. mMoofs.AppendElement(moof);
  55. mMediaRanges.AppendElement(moof.mRange);
  56. foundValidMoof = true;
  57. } else if (box.IsType("mdat") && !Moofs().IsEmpty()) {
  58. // Check if we have all our data from last moof.
  59. Moof& moof = Moofs().LastElement();
  60. media::Interval<int64_t> datarange(moof.mMdatRange.mStart, moof.mMdatRange.mEnd, 0);
  61. media::Interval<int64_t> mdat(box.Range().mStart, box.Range().mEnd, 0);
  62. if (datarange.Intersects(mdat)) {
  63. mMediaRanges.LastElement() =
  64. mMediaRanges.LastElement().Extents(box.Range());
  65. }
  66. }
  67. mOffset = box.NextOffset();
  68. }
  69. return foundValidMoof;
  70. }
  71. MediaByteRange
  72. MoofParser::FirstCompleteMediaHeader()
  73. {
  74. if (Moofs().IsEmpty()) {
  75. return MediaByteRange();
  76. }
  77. return Moofs()[0].mRange;
  78. }
  79. MediaByteRange
  80. MoofParser::FirstCompleteMediaSegment()
  81. {
  82. for (uint32_t i = 0 ; i < mMediaRanges.Length(); i++) {
  83. if (mMediaRanges[i].Contains(Moofs()[i].mMdatRange)) {
  84. return mMediaRanges[i];
  85. }
  86. }
  87. return MediaByteRange();
  88. }
  89. class BlockingStream : public Stream {
  90. public:
  91. explicit BlockingStream(Stream* aStream) : mStream(aStream)
  92. {
  93. }
  94. bool ReadAt(int64_t offset, void* data, size_t size, size_t* bytes_read)
  95. override
  96. {
  97. return mStream->ReadAt(offset, data, size, bytes_read);
  98. }
  99. bool CachedReadAt(int64_t offset, void* data, size_t size, size_t* bytes_read)
  100. override
  101. {
  102. return mStream->ReadAt(offset, data, size, bytes_read);
  103. }
  104. virtual bool Length(int64_t* size) override
  105. {
  106. return mStream->Length(size);
  107. }
  108. private:
  109. nsRefPtr<Stream> mStream;
  110. };
  111. bool
  112. MoofParser::BlockingReadNextMoof()
  113. {
  114. int64_t length = std::numeric_limits<int64_t>::max();
  115. mSource->Length(&length);
  116. nsTArray<MediaByteRange> byteRanges;
  117. byteRanges.AppendElement(MediaByteRange(0, length));
  118. nsRefPtr<mp4_demuxer::BlockingStream> stream = new BlockingStream(mSource);
  119. BoxContext context(stream, byteRanges);
  120. for (Box box(&context, mOffset); box.IsAvailable(); box = box.Next()) {
  121. if (box.IsType("moof")) {
  122. byteRanges.Clear();
  123. byteRanges.AppendElement(MediaByteRange(mOffset, box.Range().mEnd));
  124. return RebuildFragmentedIndex(context);
  125. }
  126. }
  127. return false;
  128. }
  129. void
  130. MoofParser::ScanForMetadata(mozilla::MediaByteRange& aFtyp,
  131. mozilla::MediaByteRange& aMoov)
  132. {
  133. int64_t length = std::numeric_limits<int64_t>::max();
  134. mSource->Length(&length);
  135. nsTArray<MediaByteRange> byteRanges;
  136. byteRanges.AppendElement(MediaByteRange(0, length));
  137. nsRefPtr<mp4_demuxer::BlockingStream> stream = new BlockingStream(mSource);
  138. BoxContext context(stream, byteRanges);
  139. for (Box box(&context, mOffset); box.IsAvailable(); box = box.Next()) {
  140. if (box.IsType("ftyp")) {
  141. aFtyp = box.Range();
  142. continue;
  143. }
  144. if (box.IsType("moov")) {
  145. aMoov = box.Range();
  146. break;
  147. }
  148. }
  149. mInitRange = aFtyp.Extents(aMoov);
  150. }
  151. bool
  152. MoofParser::HasMetadata()
  153. {
  154. MediaByteRange ftyp;
  155. MediaByteRange moov;
  156. ScanForMetadata(ftyp, moov);
  157. return !!ftyp.Length() && !!moov.Length();
  158. }
  159. already_AddRefed<mozilla::MediaLargeByteBuffer>
  160. MoofParser::Metadata()
  161. {
  162. MediaByteRange ftyp;
  163. MediaByteRange moov;
  164. ScanForMetadata(ftyp, moov);
  165. if (!ftyp.Length() || !moov.Length()) {
  166. return nullptr;
  167. }
  168. nsRefPtr<MediaLargeByteBuffer> metadata = new MediaLargeByteBuffer();
  169. if (!metadata->SetLength(ftyp.Length() + moov.Length())) {
  170. // OOM
  171. return nullptr;
  172. }
  173. nsRefPtr<mp4_demuxer::BlockingStream> stream = new BlockingStream(mSource);
  174. size_t read;
  175. bool rv =
  176. stream->ReadAt(ftyp.mStart, metadata->Elements(), ftyp.Length(), &read);
  177. if (!rv || read != ftyp.Length()) {
  178. return nullptr;
  179. }
  180. rv =
  181. stream->ReadAt(moov.mStart, metadata->Elements() + ftyp.Length(), moov.Length(), &read);
  182. if (!rv || read != moov.Length()) {
  183. return nullptr;
  184. }
  185. return metadata.forget();
  186. }
  187. Interval<Microseconds>
  188. MoofParser::GetCompositionRange(const nsTArray<MediaByteRange>& aByteRanges)
  189. {
  190. Interval<Microseconds> compositionRange;
  191. BoxContext context(mSource, aByteRanges);
  192. for (size_t i = 0; i < mMoofs.Length(); i++) {
  193. Moof& moof = mMoofs[i];
  194. Box box(&context, moof.mRange.mStart);
  195. if (box.IsAvailable()) {
  196. compositionRange = compositionRange.Extents(moof.mTimeRange);
  197. }
  198. }
  199. return compositionRange;
  200. }
  201. bool
  202. MoofParser::ReachedEnd()
  203. {
  204. int64_t length;
  205. return mSource->Length(&length) && mOffset == length;
  206. }
  207. void
  208. MoofParser::ParseMoov(Box& aBox)
  209. {
  210. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  211. if (box.IsType("mvhd")) {
  212. mMvhd = Mvhd(box);
  213. } else if (box.IsType("trak")) {
  214. ParseTrak(box);
  215. } else if (box.IsType("mvex")) {
  216. ParseMvex(box);
  217. }
  218. }
  219. }
  220. void
  221. MoofParser::ParseTrak(Box& aBox)
  222. {
  223. Tkhd tkhd;
  224. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  225. if (box.IsType("tkhd")) {
  226. tkhd = Tkhd(box);
  227. } else if (box.IsType("mdia")) {
  228. if (!mTrex.mTrackId || tkhd.mTrackId == mTrex.mTrackId) {
  229. ParseMdia(box, tkhd);
  230. }
  231. } else if (box.IsType("edts") &&
  232. (!mTrex.mTrackId || tkhd.mTrackId == mTrex.mTrackId)) {
  233. mEdts = Edts(box);
  234. }
  235. }
  236. }
  237. void
  238. MoofParser::ParseMdia(Box& aBox, Tkhd& aTkhd)
  239. {
  240. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  241. if (box.IsType("mdhd")) {
  242. mMdhd = Mdhd(box);
  243. } else if (box.IsType("minf")) {
  244. ParseMinf(box);
  245. }
  246. }
  247. }
  248. void
  249. MoofParser::ParseMvex(Box& aBox)
  250. {
  251. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  252. if (box.IsType("trex")) {
  253. Trex trex = Trex(box);
  254. if (!mTrex.mTrackId || trex.mTrackId == mTrex.mTrackId) {
  255. auto trackId = mTrex.mTrackId;
  256. mTrex = trex;
  257. // Keep the original trackId, as should it be 0 we want to continue
  258. // parsing all tracks.
  259. mTrex.mTrackId = trackId;
  260. }
  261. }
  262. }
  263. }
  264. void
  265. MoofParser::ParseMinf(Box& aBox)
  266. {
  267. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  268. if (box.IsType("stbl")) {
  269. ParseStbl(box);
  270. }
  271. }
  272. }
  273. void
  274. MoofParser::ParseStbl(Box& aBox)
  275. {
  276. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  277. if (box.IsType("stsd")) {
  278. ParseStsd(box);
  279. }
  280. }
  281. }
  282. void
  283. MoofParser::ParseStsd(Box& aBox)
  284. {
  285. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  286. if (box.IsType("encv") || box.IsType("enca")) {
  287. ParseEncrypted(box);
  288. }
  289. }
  290. }
  291. void
  292. MoofParser::ParseEncrypted(Box& aBox)
  293. {
  294. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  295. // Some MP4 files have been found to have multiple sinf boxes in the same
  296. // enc* box. This does not match spec anyway, so just choose the first
  297. // one that parses properly.
  298. if (box.IsType("sinf")) {
  299. mSinf = Sinf(box);
  300. if (mSinf.IsValid()) {
  301. break;
  302. }
  303. }
  304. }
  305. }
  306. Moof::Moof(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, bool aIsAudio)
  307. : mRange(aBox.Range())
  308. , mMaxRoundingError(35000)
  309. {
  310. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  311. if (box.IsType("traf")) {
  312. ParseTraf(box, aTrex, aMvhd, aMdhd, aEdts, aSinf, aIsAudio);
  313. }
  314. }
  315. if (IsValid()) {
  316. ProcessCenc();
  317. }
  318. }
  319. bool
  320. Moof::GetAuxInfo(AtomType aType, nsTArray<MediaByteRange>* aByteRanges)
  321. {
  322. aByteRanges->Clear();
  323. Saiz* saiz = nullptr;
  324. for (int i = 0; ; i++) {
  325. if (i == mSaizs.Length()) {
  326. return false;
  327. }
  328. if (mSaizs[i].mAuxInfoType == aType) {
  329. saiz = &mSaizs[i];
  330. break;
  331. }
  332. }
  333. Saio* saio = nullptr;
  334. for (int i = 0; ; i++) {
  335. if (i == mSaios.Length()) {
  336. return false;
  337. }
  338. if (mSaios[i].mAuxInfoType == aType) {
  339. saio = &mSaios[i];
  340. break;
  341. }
  342. }
  343. if (saio->mOffsets.Length() == 1) {
  344. aByteRanges->SetCapacity(saiz->mSampleInfoSize.Length());
  345. uint64_t offset = mRange.mStart + saio->mOffsets[0];
  346. for (size_t i = 0; i < saiz->mSampleInfoSize.Length(); i++) {
  347. aByteRanges->AppendElement(
  348. MediaByteRange(offset, offset + saiz->mSampleInfoSize[i]));
  349. offset += saiz->mSampleInfoSize[i];
  350. }
  351. return true;
  352. }
  353. if (saio->mOffsets.Length() == saiz->mSampleInfoSize.Length()) {
  354. aByteRanges->SetCapacity(saiz->mSampleInfoSize.Length());
  355. for (size_t i = 0; i < saio->mOffsets.Length(); i++) {
  356. uint64_t offset = mRange.mStart + saio->mOffsets[i];
  357. aByteRanges->AppendElement(
  358. MediaByteRange(offset, offset + saiz->mSampleInfoSize[i]));
  359. }
  360. return true;
  361. }
  362. return false;
  363. }
  364. bool
  365. Moof::ProcessCenc()
  366. {
  367. nsTArray<MediaByteRange> cencRanges;
  368. if (!GetAuxInfo(AtomType("cenc"), &cencRanges) ||
  369. cencRanges.Length() != mIndex.Length()) {
  370. return false;
  371. }
  372. for (int i = 0; i < cencRanges.Length(); i++) {
  373. mIndex[i].mCencRange = cencRanges[i];
  374. }
  375. return true;
  376. }
  377. void
  378. Moof::ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, bool aIsAudio)
  379. {
  380. Tfhd tfhd(aTrex);
  381. Tfdt tfdt;
  382. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  383. if (box.IsType("tfhd")) {
  384. tfhd = Tfhd(box, aTrex);
  385. } else if (!aTrex.mTrackId || tfhd.mTrackId == aTrex.mTrackId) {
  386. if (box.IsType("tfdt")) {
  387. tfdt = Tfdt(box);
  388. } else if (box.IsType("saiz")) {
  389. mSaizs.AppendElement(Saiz(box, aSinf.mDefaultEncryptionType));
  390. } else if (box.IsType("saio")) {
  391. mSaios.AppendElement(Saio(box, aSinf.mDefaultEncryptionType));
  392. }
  393. }
  394. }
  395. if (aTrex.mTrackId && tfhd.mTrackId != aTrex.mTrackId) {
  396. return;
  397. }
  398. if (!tfdt.IsValid()) {
  399. return;
  400. }
  401. // Now search for TRUN boxes.
  402. uint64_t decodeTime = tfdt.mBaseMediaDecodeTime;
  403. for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
  404. if (box.IsType("trun")) {
  405. if (ParseTrun(box, tfhd, aMvhd, aMdhd, aEdts, &decodeTime, aIsAudio)) {
  406. mValid = true;
  407. } else {
  408. mValid = false;
  409. break;
  410. }
  411. }
  412. }
  413. }
  414. void
  415. Moof::FixRounding(const Moof& aMoof) {
  416. Microseconds gap = aMoof.mTimeRange.start - mTimeRange.end;
  417. if (gap > 0 && gap <= mMaxRoundingError) {
  418. mTimeRange.end = aMoof.mTimeRange.start;
  419. }
  420. }
  421. class CtsComparator
  422. {
  423. public:
  424. bool Equals(Sample* const aA, Sample* const aB) const
  425. {
  426. return aA->mCompositionRange.start == aB->mCompositionRange.start;
  427. }
  428. bool
  429. LessThan(Sample* const aA, Sample* const aB) const
  430. {
  431. return aA->mCompositionRange.start < aB->mCompositionRange.start;
  432. }
  433. };
  434. bool
  435. Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, uint64_t* aDecodeTime, bool aIsAudio)
  436. {
  437. if (!aTfhd.IsValid() || !aMvhd.IsValid() || !aMdhd.IsValid() ||
  438. !aEdts.IsValid()) {
  439. return false;
  440. }
  441. BoxReader reader(aBox);
  442. if (!reader->CanReadType<uint32_t>()) {
  443. return false;
  444. }
  445. uint32_t flags = reader->ReadU32();
  446. uint8_t version = flags >> 24;
  447. if (!reader->CanReadType<uint32_t>()) {
  448. return false;
  449. }
  450. uint32_t sampleCount = reader->ReadU32();
  451. if (sampleCount == 0) {
  452. return true;
  453. }
  454. size_t need =
  455. ((flags & 1) ? sizeof(uint32_t) : 0) +
  456. ((flags & 4) ? sizeof(uint32_t) : 0);
  457. uint16_t flag[] = { 0x100, 0x200, 0x400, 0x800, 0 };
  458. for (size_t i = 0; flag[i]; i++) {
  459. if (flags & flag[i]) {
  460. need += sizeof(uint32_t) * sampleCount;
  461. }
  462. }
  463. if (reader->Remaining() < need) {
  464. return false;
  465. }
  466. uint64_t offset = aTfhd.mBaseDataOffset + (flags & 1 ? reader->ReadU32() : 0);
  467. uint32_t firstSampleFlags =
  468. flags & 4 ? reader->ReadU32() : aTfhd.mDefaultSampleFlags;
  469. uint64_t decodeTime = *aDecodeTime;
  470. nsTArray<Interval<Microseconds>> timeRanges;
  471. if (!mIndex.SetCapacity(sampleCount)) {
  472. return false;
  473. }
  474. for (size_t i = 0; i < sampleCount; i++) {
  475. uint32_t sampleDuration =
  476. flags & 0x100 ? reader->ReadU32() : aTfhd.mDefaultSampleDuration;
  477. uint32_t sampleSize =
  478. flags & 0x200 ? reader->ReadU32() : aTfhd.mDefaultSampleSize;
  479. uint32_t sampleFlags =
  480. flags & 0x400 ? reader->ReadU32()
  481. : i ? aTfhd.mDefaultSampleFlags : firstSampleFlags;
  482. int32_t ctsOffset = 0;
  483. if (flags & 0x800) {
  484. ctsOffset = reader->Read32();
  485. }
  486. Sample sample;
  487. sample.mByteRange = MediaByteRange(offset, offset + sampleSize);
  488. offset += sampleSize;
  489. sample.mDecodeTime =
  490. aMdhd.ToMicroseconds((int64_t)decodeTime - aEdts.mMediaStart) + aMvhd.ToMicroseconds(aEdts.mEmptyOffset);
  491. sample.mCompositionRange = Interval<Microseconds>(
  492. aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset - aEdts.mMediaStart) + aMvhd.ToMicroseconds(aEdts.mEmptyOffset),
  493. aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset + sampleDuration - aEdts.mMediaStart) + aMvhd.ToMicroseconds(aEdts.mEmptyOffset));
  494. decodeTime += sampleDuration;
  495. // Sometimes audio streams don't properly mark their samples as keyframes,
  496. // because every audio sample is a keyframe.
  497. sample.mSync = !(sampleFlags & 0x1010000) || aIsAudio;
  498. MOZ_ALWAYS_TRUE(mIndex.AppendElement(sample));
  499. mMdatRange = mMdatRange.Extents(sample.mByteRange);
  500. }
  501. mMaxRoundingError += aMdhd.ToMicroseconds(sampleCount);
  502. nsTArray<Sample*> ctsOrder;
  503. for (int i = 0; i < mIndex.Length(); i++) {
  504. ctsOrder.AppendElement(&mIndex[i]);
  505. }
  506. ctsOrder.Sort(CtsComparator());
  507. for (size_t i = 0; i < ctsOrder.Length(); i++) {
  508. if (i + 1 < ctsOrder.Length()) {
  509. ctsOrder[i]->mCompositionRange.end = ctsOrder[i + 1]->mCompositionRange.start;
  510. }
  511. }
  512. mTimeRange = Interval<Microseconds>(ctsOrder[0]->mCompositionRange.start,
  513. ctsOrder.LastElement()->mCompositionRange.end);
  514. *aDecodeTime = decodeTime;
  515. return true;
  516. }
  517. Tkhd::Tkhd(Box& aBox)
  518. {
  519. BoxReader reader(aBox);
  520. if (!reader->CanReadType<uint32_t>()) {
  521. return;
  522. }
  523. uint32_t flags = reader->ReadU32();
  524. uint8_t version = flags >> 24;
  525. size_t need =
  526. 3*(version ? sizeof(int64_t) : sizeof(int32_t)) + 2*sizeof(int32_t);
  527. if (reader->Remaining() < need) {
  528. return;
  529. }
  530. if (version == 0) {
  531. mCreationTime = reader->ReadU32();
  532. mModificationTime = reader->ReadU32();
  533. mTrackId = reader->ReadU32();
  534. uint32_t reserved = reader->ReadU32();
  535. NS_ASSERTION(!reserved, "reserved should be 0");
  536. mDuration = reader->ReadU32();
  537. } else if (version == 1) {
  538. mCreationTime = reader->ReadU64();
  539. mModificationTime = reader->ReadU64();
  540. mTrackId = reader->ReadU32();
  541. uint32_t reserved = reader->ReadU32();
  542. NS_ASSERTION(!reserved, "reserved should be 0");
  543. mDuration = reader->ReadU64();
  544. }
  545. // More stuff that we don't care about
  546. reader->DiscardRemaining();
  547. mValid = true;
  548. }
  549. Mvhd::Mvhd(Box& aBox)
  550. {
  551. BoxReader reader(aBox);
  552. if (!reader->CanReadType<uint32_t>()) {
  553. return;
  554. }
  555. uint32_t flags = reader->ReadU32();
  556. uint8_t version = flags >> 24;
  557. size_t need =
  558. 3*(version ? sizeof(int64_t) : sizeof(int32_t)) + sizeof(uint32_t);
  559. if (reader->Remaining() < need) {
  560. return;
  561. }
  562. if (version == 0) {
  563. mCreationTime = reader->ReadU32();
  564. mModificationTime = reader->ReadU32();
  565. mTimescale = reader->ReadU32();
  566. mDuration = reader->ReadU32();
  567. } else if (version == 1) {
  568. mCreationTime = reader->ReadU64();
  569. mModificationTime = reader->ReadU64();
  570. mTimescale = reader->ReadU32();
  571. mDuration = reader->ReadU64();
  572. } else {
  573. reader->DiscardRemaining();
  574. return;
  575. }
  576. // More stuff that we don't care about
  577. reader->DiscardRemaining();
  578. mValid = true;
  579. }
  580. Mdhd::Mdhd(Box& aBox)
  581. : Mvhd(aBox)
  582. {
  583. }
  584. Trex::Trex(Box& aBox)
  585. {
  586. BoxReader reader(aBox);
  587. if (reader->Remaining() < 6*sizeof(uint32_t)) {
  588. return;
  589. }
  590. mFlags = reader->ReadU32();
  591. mTrackId = reader->ReadU32();
  592. mDefaultSampleDescriptionIndex = reader->ReadU32();
  593. mDefaultSampleDuration = reader->ReadU32();
  594. mDefaultSampleSize = reader->ReadU32();
  595. mDefaultSampleFlags = reader->ReadU32();
  596. mValid = true;
  597. }
  598. Tfhd::Tfhd(Box& aBox, Trex& aTrex)
  599. : Trex(aTrex)
  600. {
  601. MOZ_ASSERT(aBox.IsType("tfhd"));
  602. MOZ_ASSERT(aBox.Parent()->IsType("traf"));
  603. MOZ_ASSERT(aBox.Parent()->Parent()->IsType("moof"));
  604. BoxReader reader(aBox);
  605. if (!reader->CanReadType<uint32_t>()) {
  606. return;
  607. }
  608. mFlags = reader->ReadU32();
  609. size_t need = sizeof(uint32_t) /* trackid */;
  610. uint8_t flag[] = { 1, 2, 8, 0x10, 0x20, 0 };
  611. for (size_t i = 0; flag[i]; i++) {
  612. if (mFlags & flag[i]) {
  613. need += sizeof(uint32_t);
  614. }
  615. }
  616. if (reader->Remaining() < need) {
  617. return;
  618. }
  619. mBaseDataOffset =
  620. mFlags & 1 ? reader->ReadU32() : aBox.Parent()->Parent()->Offset();
  621. mTrackId = reader->ReadU32();
  622. if (mFlags & 2) {
  623. mDefaultSampleDescriptionIndex = reader->ReadU32();
  624. }
  625. if (mFlags & 8) {
  626. mDefaultSampleDuration = reader->ReadU32();
  627. }
  628. if (mFlags & 0x10) {
  629. mDefaultSampleSize = reader->ReadU32();
  630. }
  631. if (mFlags & 0x20) {
  632. mDefaultSampleFlags = reader->ReadU32();
  633. }
  634. mValid = true;
  635. }
  636. Tfdt::Tfdt(Box& aBox)
  637. {
  638. BoxReader reader(aBox);
  639. if (!reader->CanReadType<uint32_t>()) {
  640. return;
  641. }
  642. uint32_t flags = reader->ReadU32();
  643. uint8_t version = flags >> 24;
  644. size_t need = version ? sizeof(uint64_t) : sizeof(uint32_t) ;
  645. if (reader->Remaining() < need) {
  646. return;
  647. }
  648. if (version == 0) {
  649. mBaseMediaDecodeTime = reader->ReadU32();
  650. } else if (version == 1) {
  651. mBaseMediaDecodeTime = reader->ReadU64();
  652. }
  653. reader->DiscardRemaining();
  654. mValid = true;
  655. }
  656. Edts::Edts(Box& aBox)
  657. : mMediaStart(0)
  658. , mEmptyOffset(0)
  659. {
  660. Box child = aBox.FirstChild();
  661. if (!child.IsType("elst")) {
  662. return;
  663. }
  664. BoxReader reader(child);
  665. if (!reader->CanReadType<uint32_t>()) {
  666. return;
  667. }
  668. uint32_t flags = reader->ReadU32();
  669. uint8_t version = flags >> 24;
  670. size_t need =
  671. sizeof(uint32_t) + 2*(version ? sizeof(int64_t) : sizeof(uint32_t));
  672. if (reader->Remaining() < need) {
  673. return;
  674. }
  675. bool emptyEntry = false;
  676. uint32_t entryCount = reader->ReadU32();
  677. for (uint32_t i = 0; i < entryCount; i++) {
  678. uint64_t segment_duration;
  679. int64_t media_time;
  680. if (version == 1) {
  681. segment_duration = reader->ReadU64();
  682. media_time = reader->Read64();
  683. } else {
  684. segment_duration = reader->ReadU32();
  685. media_time = reader->Read32();
  686. }
  687. if (media_time == -1 && i) {
  688. break;
  689. } else if (media_time == -1) {
  690. mEmptyOffset = segment_duration;
  691. emptyEntry = true;
  692. } else if (i > 1 || (i > 0 && !emptyEntry)) {
  693. break;
  694. } else {
  695. mMediaStart = media_time;
  696. }
  697. reader->ReadU32(); // media_rate_integer and media_rate_fraction
  698. }
  699. }
  700. Saiz::Saiz(Box& aBox, AtomType aDefaultType)
  701. : mAuxInfoType(aDefaultType)
  702. , mAuxInfoTypeParameter(0)
  703. {
  704. BoxReader reader(aBox);
  705. if (!reader->CanReadType<uint32_t>()) {
  706. return;
  707. }
  708. uint32_t flags = reader->ReadU32();
  709. uint8_t version = flags >> 24;
  710. size_t need =
  711. ((flags & 1) ? 2*sizeof(uint32_t) : 0) + sizeof(uint8_t) + sizeof(uint32_t);
  712. if (reader->Remaining() < need) {
  713. return;
  714. }
  715. if (flags & 1) {
  716. mAuxInfoType = reader->ReadU32();
  717. mAuxInfoTypeParameter = reader->ReadU32();
  718. }
  719. uint8_t defaultSampleInfoSize = reader->ReadU8();
  720. uint32_t count = reader->ReadU32();
  721. if (defaultSampleInfoSize) {
  722. for (int i = 0; i < count; i++) {
  723. mSampleInfoSize.AppendElement(defaultSampleInfoSize);
  724. }
  725. } else {
  726. if (!reader->ReadArray(mSampleInfoSize, count)) {
  727. return;
  728. }
  729. }
  730. mValid = true;
  731. }
  732. Saio::Saio(Box& aBox, AtomType aDefaultType)
  733. : mAuxInfoType(aDefaultType)
  734. , mAuxInfoTypeParameter(0)
  735. {
  736. BoxReader reader(aBox);
  737. if (!reader->CanReadType<uint32_t>()) {
  738. return;
  739. }
  740. uint32_t flags = reader->ReadU32();
  741. uint8_t version = flags >> 24;
  742. size_t need = ((flags & 1) ? (2*sizeof(uint32_t)) : 0) + sizeof(uint32_t);
  743. if (reader->Remaining() < need) {
  744. return;
  745. }
  746. if (flags & 1) {
  747. mAuxInfoType = reader->ReadU32();
  748. mAuxInfoTypeParameter = reader->ReadU32();
  749. }
  750. size_t count = reader->ReadU32();
  751. need = (version ? sizeof(uint64_t) : sizeof(uint32_t)) * count;
  752. if (reader->Remaining() < count) {
  753. return;
  754. }
  755. mOffsets.SetCapacity(count);
  756. if (version == 0) {
  757. for (size_t i = 0; i < count; i++) {
  758. mOffsets.AppendElement(reader->ReadU32());
  759. }
  760. } else {
  761. for (size_t i = 0; i < count; i++) {
  762. mOffsets.AppendElement(reader->ReadU64());
  763. }
  764. }
  765. mValid = true;
  766. }
  767. #undef LOG
  768. }
  769.