Bug 1143491: Parse all trun boxes in MP4 fragments, not only the first one. r=jya
authorMartin Storsjö <martin@martin.st>
Mon, 23 Mar 2015 11:39:27 +0200
changeset 264085 1b7d0845db2ad0ba4d8b888991a6f73bc85954ee
parent 264084 24f54332e22e8eb3fa3d2a290d21e16ac8231051
child 264086 6e7d781ad81ed484f777934e1a6e2ef89f7f7992
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1143491
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1143491: Parse all trun boxes in MP4 fragments, not only the first one. r=jya
media/libstagefright/binding/MoofParser.cpp
media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -333,21 +333,28 @@ Moof::ParseTraf(Box& aBox, Trex& aTrex, 
       } else if (box.IsType("saio")) {
         mSaios.AppendElement(Saio(box, aSinf.mDefaultEncryptionType));
       }
     }
   }
   if (aTrex.mTrackId && tfhd.mTrackId != aTrex.mTrackId) {
     return;
   }
-  // Now search for TRUN box.
+  if (!tfdt.IsValid()) {
+    LOG(Moof, "Invalid tfdt dependency");
+    return;
+  }
+  // Now search for TRUN boxes.
+  uint64_t decodeTime = tfdt.mBaseMediaDecodeTime;
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("trun")) {
-      ParseTrun(box, tfhd, tfdt, aMdhd, aEdts, aIsAudio);
-      if (IsValid()) {
+      if (ParseTrun(box, tfhd, aMdhd, aEdts, &decodeTime, aIsAudio)) {
+        mValid = true;
+      } else {
+        mValid = false;
         break;
       }
     }
   }
 }
 
 void
 Moof::FixRounding(const Moof& aMoof) {
@@ -366,69 +373,66 @@ public:
   }
   bool
   LessThan(Sample* const aA, Sample* const aB) const
   {
     return aA->mCompositionRange.start < aB->mCompositionRange.start;
   }
 };
 
-void
-Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd, Edts& aEdts, bool aIsAudio)
+bool
+Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mdhd& aMdhd, Edts& aEdts, uint64_t* aDecodeTime, bool aIsAudio)
 {
-  if (!aTfhd.IsValid() || !aTfdt.IsValid() ||
-      !aMdhd.IsValid() || !aEdts.IsValid()) {
-    LOG(Moof, "Invalid dependencies: aTfhd(%d) aTfdt(%d) aMdhd(%d) aEdts(%d)",
-        aTfhd.IsValid(), aTfdt.IsValid(), aMdhd.IsValid(), !aEdts.IsValid());
-    return;
+  if (!aTfhd.IsValid() || !aMdhd.IsValid() || !aEdts.IsValid()) {
+    LOG(Moof, "Invalid dependencies: aTfhd(%d) aMdhd(%d) aEdts(%d)",
+        aTfhd.IsValid(), aMdhd.IsValid(), !aEdts.IsValid());
+    return false;
   }
 
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Moof, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   if ((flags & 0x404) == 0x404) {
     // Can't use these flags together
     reader->DiscardRemaining();
-    mValid = true;
-    return;
+    return true;
   }
   uint8_t version = flags >> 24;
 
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Moof, "Incomplete Box (missing sampleCount)");
-    return;
+    return false;
   }
   uint32_t sampleCount = reader->ReadU32();
   if (sampleCount == 0) {
-    mValid = true;
-    return;
+    return true;
   }
 
   size_t need =
     ((flags & 1) ? sizeof(uint32_t) : 0) +
     ((flags & 4) ? sizeof(uint32_t) : 0);
   uint16_t flag[] = { 0x100, 0x200, 0x400, 0x800, 0 };
   for (size_t i = 0; flag[i]; i++) {
     if (flags & flag[i]) {
       need += sizeof(uint32_t) * sampleCount;
     }
   }
   if (reader->Remaining() < need) {
     LOG(Moof, "Incomplete Box (have:%lld need:%lld)",
         reader->Remaining(), need);
-    return;
+    return false;
   }
 
   uint64_t offset = aTfhd.mBaseDataOffset + (flags & 1 ? reader->ReadU32() : 0);
   bool hasFirstSampleFlags = flags & 4;
   uint32_t firstSampleFlags = hasFirstSampleFlags ? reader->ReadU32() : 0;
-  uint64_t decodeTime = aTfdt.mBaseMediaDecodeTime;
+  uint64_t decodeTime = *aDecodeTime;
   nsTArray<Interval<Microseconds>> timeRanges;
   for (size_t i = 0; i < sampleCount; i++) {
     uint32_t sampleDuration =
       flags & 0x100 ? reader->ReadU32() : aTfhd.mDefaultSampleDuration;
     uint32_t sampleSize =
       flags & 0x200 ? reader->ReadU32() : aTfhd.mDefaultSampleSize;
     uint32_t sampleFlags =
       flags & 0x400 ? reader->ReadU32() : hasFirstSampleFlags && i == 0
@@ -467,17 +471,18 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, 
 
   for (size_t i = 0; i < ctsOrder.Length(); i++) {
     if (i + 1 < ctsOrder.Length()) {
       ctsOrder[i]->mCompositionRange.end = ctsOrder[i + 1]->mCompositionRange.start;
     }
   }
   mTimeRange = Interval<Microseconds>(ctsOrder[0]->mCompositionRange.start,
       ctsOrder.LastElement()->mCompositionRange.end);
-  mValid = true;
+  *aDecodeTime = decodeTime;
+  return true;
 }
 
 Tkhd::Tkhd(Box& aBox)
 {
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Tkhd, "Incomplete Box (missing flags)");
     return;
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -177,17 +177,18 @@ public:
   Interval<Microseconds> mTimeRange;
   nsTArray<Sample> mIndex;
 
   nsTArray<Saiz> mSaizs;
   nsTArray<Saio> mSaios;
 
 private:
   void ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, bool aIsAudio);
-  void ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd, Edts& aEdts, bool aIsAudio);
+  // aDecodeTime is updated to the end of the parsed TRUN on return.
+  bool ParseTrun(Box& aBox, Tfhd& aTfhd, Mdhd& aMdhd, Edts& aEdts, uint64_t* aDecodeTime, bool aIsAudio);
   void ParseSaiz(Box& aBox);
   void ParseSaio(Box& aBox);
   bool ProcessCenc();
   uint64_t mMaxRoundingError;
 };
 
 class MoofParser
 {