Bug 1387798 - move initialized codes out of box constructor to another function which could be able to return error. r?kinetik draft
authorAlfredo.Yang <ayang@mozilla.com>
Fri, 13 Oct 2017 10:13:28 +0800
changeset 680633 c9049137b12f6159d525debad5cff22c75505a7e
parent 680632 1c63e97b185612360c98e815c573288c3206c33b
child 680634 1865a5258248f7bb80004ab71a286f15b37659b5
child 681371 00131d123a85706c395c05454c82952a858d60cf
push id84566
push userbmo:ayang@mozilla.com
push dateMon, 16 Oct 2017 00:30:33 +0000
reviewerskinetik
bugs1387798
milestone58.0a1
Bug 1387798 - move initialized codes out of box constructor to another function which could be able to return error. r?kinetik MozReview-Commit-ID: 5LJVCTYIT7o
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
@@ -701,196 +701,241 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, 
 
   *aDecodeTime = decodeTime;
 
   return true;
 }
 
 Tkhd::Tkhd(Box& aBox)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Tkhd::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Tkhd, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   uint8_t version = flags >> 24;
   size_t need =
     3*(version ? sizeof(int64_t) : sizeof(int32_t)) + 2*sizeof(int32_t);
   if (reader->Remaining() < need) {
     LOG(Tkhd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   if (version == 0) {
     mCreationTime = reader->ReadU32();
     mModificationTime = reader->ReadU32();
     mTrackId = reader->ReadU32();
     uint32_t reserved = reader->ReadU32();
     NS_ASSERTION(!reserved, "reserved should be 0");
     mDuration = reader->ReadU32();
   } else if (version == 1) {
     mCreationTime = reader->ReadU64();
     mModificationTime = reader->ReadU64();
     mTrackId = reader->ReadU32();
     uint32_t reserved = reader->ReadU32();
     NS_ASSERTION(!reserved, "reserved should be 0");
     mDuration = reader->ReadU64();
   }
-  // We don't care about whatever else may be in the box.
-  mValid = true;
+  return true;
 }
 
 Mvhd::Mvhd(Box& aBox)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Mvhd::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Mdhd, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   uint8_t version = flags >> 24;
   size_t need =
     3*(version ? sizeof(int64_t) : sizeof(int32_t)) + sizeof(uint32_t);
   if (reader->Remaining() < need) {
     LOG(Mvhd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
 
   if (version == 0) {
     mCreationTime = reader->ReadU32();
     mModificationTime = reader->ReadU32();
     mTimescale = reader->ReadU32();
     mDuration = reader->ReadU32();
   } else if (version == 1) {
     mCreationTime = reader->ReadU64();
     mModificationTime = reader->ReadU64();
     mTimescale = reader->ReadU32();
     mDuration = reader->ReadU64();
   } else {
-    return;
+    return false;
   }
-  // We don't care about whatever else may be in the box.
-  if (mTimescale) {
-    mValid = true;
-  }
+  return true;
 }
 
 Mdhd::Mdhd(Box& aBox)
   : Mvhd(aBox)
 {
 }
 
 Trex::Trex(Box& aBox)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Trex::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
   if (reader->Remaining() < 6*sizeof(uint32_t)) {
     LOG(Trex, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)6*sizeof(uint32_t));
-    return;
+    return false;
   }
   mFlags = reader->ReadU32();
   mTrackId = reader->ReadU32();
   mDefaultSampleDescriptionIndex = reader->ReadU32();
   mDefaultSampleDuration = reader->ReadU32();
   mDefaultSampleSize = reader->ReadU32();
   mDefaultSampleFlags = reader->ReadU32();
-  mValid = true;
+  return true;
 }
 
 Tfhd::Tfhd(Box& aBox, Trex& aTrex)
   : Trex(aTrex)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Tfhd::Parse(Box& aBox)
+{
   MOZ_ASSERT(aBox.IsType("tfhd"));
   MOZ_ASSERT(aBox.Parent()->IsType("traf"));
   MOZ_ASSERT(aBox.Parent()->Parent()->IsType("moof"));
 
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Tfhd, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   mFlags = reader->ReadU32();
   size_t need = sizeof(uint32_t) /* trackid */;
   uint8_t flag[] = { 1, 2, 8, 0x10, 0x20, 0 };
   uint8_t flagSize[] = { sizeof(uint64_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t) };
   for (size_t i = 0; flag[i]; i++) {
     if (mFlags & flag[i]) {
       need += flagSize[i];
     }
   }
   if (reader->Remaining() < need) {
     LOG(Tfhd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   mTrackId = reader->ReadU32();
   mBaseDataOffset =
     mFlags & 1 ? reader->ReadU64() : aBox.Parent()->Parent()->Offset();
   if (mFlags & 2) {
     mDefaultSampleDescriptionIndex = reader->ReadU32();
   }
   if (mFlags & 8) {
     mDefaultSampleDuration = reader->ReadU32();
   }
   if (mFlags & 0x10) {
     mDefaultSampleSize = reader->ReadU32();
   }
   if (mFlags & 0x20) {
     mDefaultSampleFlags = reader->ReadU32();
   }
-  mValid = true;
+
+  return true;
 }
 
 Tfdt::Tfdt(Box& aBox)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Tfdt::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Tfdt, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   uint8_t version = flags >> 24;
   size_t need = version ? sizeof(uint64_t) : sizeof(uint32_t) ;
   if (reader->Remaining() < need) {
     LOG(Tfdt, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   if (version == 0) {
     mBaseMediaDecodeTime = reader->ReadU32();
   } else if (version == 1) {
     mBaseMediaDecodeTime = reader->ReadU64();
   }
-  mValid = true;
+  return true;
 }
 
 Edts::Edts(Box& aBox)
   : mMediaStart(0)
   , mEmptyOffset(0)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Edts::Parse(Box& aBox)
+{
   Box child = aBox.FirstChild();
   if (!child.IsType("elst")) {
-    return;
+    return false;
   }
 
   BoxReader reader(child);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Edts, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   uint8_t version = flags >> 24;
   size_t need =
     sizeof(uint32_t) + 2*(version ? sizeof(int64_t) : sizeof(uint32_t));
   if (reader->Remaining() < need) {
     LOG(Edts, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   bool emptyEntry = false;
   uint32_t entryCount = reader->ReadU32();
   for (uint32_t i = 0; i < entryCount; i++) {
     uint64_t segment_duration;
     int64_t media_time;
     if (version == 1) {
       segment_duration = reader->ReadU64();
@@ -907,215 +952,247 @@ Edts::Edts(Box& aBox)
     } else if (i > 1 || (i > 0 && !emptyEntry)) {
       LOG(Edts, "More than one edit entry, not handled. A/V sync will be wrong");
       break;
     } else {
       mMediaStart = media_time;
     }
     reader->ReadU32(); // media_rate_integer and media_rate_fraction
   }
+
+  return true;
 }
 
 Saiz::Saiz(Box& aBox, AtomType aDefaultType)
   : mAuxInfoType(aDefaultType)
   , mAuxInfoTypeParameter(0)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Saiz::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Saiz, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   uint8_t version = flags >> 24;
   size_t need =
     ((flags & 1) ? 2*sizeof(uint32_t) : 0) + sizeof(uint8_t) + sizeof(uint32_t);
   if (reader->Remaining() < need) {
     LOG(Saiz, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   if (flags & 1) {
     mAuxInfoType = reader->ReadU32();
     mAuxInfoTypeParameter = reader->ReadU32();
   }
   uint8_t defaultSampleInfoSize = reader->ReadU8();
   uint32_t count = reader->ReadU32();
   if (defaultSampleInfoSize) {
     if (!mSampleInfoSize.SetLength(count, fallible)) {
       LOG(Saiz, "OOM");
-      return;
+      return false;
     }
     memset(mSampleInfoSize.Elements(), defaultSampleInfoSize, mSampleInfoSize.Length());
   } else {
     if (!reader->ReadArray(mSampleInfoSize, count)) {
       LOG(Saiz, "Incomplete Box (OOM or missing count:%u)", count);
-      return;
+      return false;
     }
   }
-  mValid = true;
+  return true;
 }
 
 Saio::Saio(Box& aBox, AtomType aDefaultType)
   : mAuxInfoType(aDefaultType)
   , mAuxInfoTypeParameter(0)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Saio::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Saio, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
   uint32_t flags = reader->ReadU32();
   uint8_t version = flags >> 24;
   size_t need = ((flags & 1) ? (2*sizeof(uint32_t)) : 0) + sizeof(uint32_t);
   if (reader->Remaining() < need) {
     LOG(Saio, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   if (flags & 1) {
     mAuxInfoType = reader->ReadU32();
     mAuxInfoTypeParameter = reader->ReadU32();
   }
   size_t count = reader->ReadU32();
   need = (version ? sizeof(uint64_t) : sizeof(uint32_t)) * count;
   if (reader->Remaining() < need) {
     LOG(Saio, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   if (!mOffsets.SetCapacity(count, fallible)) {
     LOG(Saiz, "OOM");
-    return;
+    return false;
   }
   if (version == 0) {
     for (size_t i = 0; i < count; i++) {
       MOZ_ALWAYS_TRUE(mOffsets.AppendElement(reader->ReadU32(), fallible));
     }
   } else {
     for (size_t i = 0; i < count; i++) {
       MOZ_ALWAYS_TRUE(mOffsets.AppendElement(reader->ReadU64(), fallible));
     }
   }
-  mValid = true;
+  return true;
 }
 
 Sbgp::Sbgp(Box& aBox)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Sbgp::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
 
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Sbgp, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
 
   uint32_t flags = reader->ReadU32();
   const uint8_t version = flags >> 24;
   flags = flags & 0xffffff;
 
   // Make sure we have enough bytes to read as far as the count.
   uint32_t need = (version == 1 ? sizeof(uint32_t) : 0) + sizeof(uint32_t) * 2;
   if (reader->Remaining() < need) {
     LOG(Sbgp, "Incomplete Box (have:%" PRIu64 ", need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
 
   mGroupingType = reader->ReadU32();
 
   if (version == 1) {
     mGroupingTypeParam = reader->Read32();
   }
 
   uint32_t count = reader->ReadU32();
 
   // Make sure we can read all the entries.
   need = sizeof(uint32_t) * 2 * count;
   if (reader->Remaining() < need) {
     LOG(Sbgp, "Incomplete Box (have:%" PRIu64 ", need:%" PRIu64 "). Failed to read entries",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
 
   for (uint32_t i = 0; i < count; i++) {
     uint32_t sampleCount = reader->ReadU32();
     uint32_t groupDescriptionIndex = reader->ReadU32();
 
     SampleToGroupEntry entry(sampleCount, groupDescriptionIndex);
     if (!mEntries.AppendElement(entry, mozilla::fallible)) {
       LOG(Sbgp, "OOM");
-      return;
+      return false;
     }
   }
-
-  mValid = true;
+  return true;
 }
 
 Sgpd::Sgpd(Box& aBox)
 {
+  if (Parse(aBox)) {
+    mValid = true;
+  }
+}
+
+bool
+Sgpd::Parse(Box& aBox)
+{
   BoxReader reader(aBox);
 
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Sgpd, "Incomplete Box (missing flags)");
-    return;
+    return false;
   }
 
   uint32_t flags = reader->ReadU32();
   const uint8_t version = flags >> 24;
   flags = flags & 0xffffff;
 
   uint32_t need = ((flags & 1) ? sizeof(uint32_t) : 0) + sizeof(uint32_t) * 2;
   if (reader->Remaining() < need) {
     LOG(Sgpd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
 
   mGroupingType = reader->ReadU32();
 
   const uint32_t entrySize = sizeof(uint32_t) + kKeyIdSize;
   uint32_t defaultLength = 0;
 
   if (version == 1) {
     defaultLength = reader->ReadU32();
     if (defaultLength < entrySize && defaultLength != 0) {
-      return;
+      return false;
     }
   }
 
   uint32_t count = reader->ReadU32();
 
   // Make sure we have sufficient remaining bytes to read the entries.
   need =
     count * (sizeof(uint32_t) * (version == 1 && defaultLength == 0 ? 2 : 1) +
              kKeyIdSize * sizeof(uint8_t));
   if (reader->Remaining() < need) {
     LOG(Sgpd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 "). Failed to read entries",
         (uint64_t)reader->Remaining(), (uint64_t)need);
-    return;
+    return false;
   }
   for (uint32_t i = 0; i < count; ++i) {
     if (version == 1 && defaultLength == 0) {
       uint32_t descriptionLength = reader->ReadU32();
       if (descriptionLength < entrySize) {
-        return;
+        return false;
       }
     }
 
     CencSampleEncryptionInfoEntry entry;
     bool valid = entry.Init(reader);
     if (!valid) {
-      return;
+      return false;
     }
     if (!mEntries.AppendElement(entry, mozilla::fallible)) {
       LOG(Sgpd, "OOM");
-      return;
+      return false;
     }
   }
-
-  mValid = true;
+  return true;
 }
 
 bool CencSampleEncryptionInfoEntry::Init(BoxReader& aReader)
 {
   // Skip a reserved byte.
   aReader->ReadU8();
 
   uint8_t possiblePatternInfo = aReader->ReadU8();
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -38,28 +38,34 @@ public:
     int64_t remainder = aTimescaleUnits % mTimescale;
     return major * 1000000ll + remainder * 1000000ll / mTimescale;
   }
 
   uint64_t mCreationTime;
   uint64_t mModificationTime;
   uint32_t mTimescale;
   uint64_t mDuration;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class Tkhd : public Mvhd
 {
 public:
   Tkhd()
     : mTrackId(0)
   {
   }
   explicit Tkhd(Box& aBox);
 
   uint32_t mTrackId;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class Mdhd : public Mvhd
 {
 public:
   Mdhd() = default;
   explicit Mdhd(Box& aBox);
 };
@@ -80,42 +86,51 @@ public:
   explicit Trex(Box& aBox);
 
   uint32_t mFlags;
   uint32_t mTrackId;
   uint32_t mDefaultSampleDescriptionIndex;
   uint32_t mDefaultSampleDuration;
   uint32_t mDefaultSampleSize;
   uint32_t mDefaultSampleFlags;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class Tfhd : public Trex
 {
 public:
   explicit Tfhd(Trex& aTrex)
     : Trex(aTrex)
     , mBaseDataOffset(0)
   {
     mValid = aTrex.IsValid();
   }
   Tfhd(Box& aBox, Trex& aTrex);
 
   uint64_t mBaseDataOffset;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class Tfdt : public Atom
 {
 public:
   Tfdt()
     : mBaseMediaDecodeTime(0)
   {
   }
   explicit Tfdt(Box& aBox);
 
   uint64_t mBaseMediaDecodeTime;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class Edts : public Atom
 {
 public:
   Edts()
     : mMediaStart(0)
     , mEmptyOffset(0)
@@ -125,16 +140,19 @@ public:
   virtual bool IsValid()
   {
     // edts is optional
     return true;
   }
 
   int64_t mMediaStart;
   int64_t mEmptyOffset;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 struct Sample
 {
   mozilla::MediaByteRange mByteRange;
   mozilla::MediaByteRange mCencRange;
   Microseconds mDecodeTime;
   Interval<Microseconds> mCompositionRange;
@@ -144,26 +162,32 @@ struct Sample
 class Saiz final : public Atom
 {
 public:
   Saiz(Box& aBox, AtomType aDefaultType);
 
   AtomType mAuxInfoType;
   uint32_t mAuxInfoTypeParameter;
   FallibleTArray<uint8_t> mSampleInfoSize;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class Saio final : public Atom
 {
 public:
   Saio(Box& aBox, AtomType aDefaultType);
 
   AtomType mAuxInfoType;
   uint32_t mAuxInfoTypeParameter;
   FallibleTArray<uint64_t> mOffsets;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 struct SampleToGroupEntry
 {
 public:
   static const uint32_t kTrackGroupDescriptionIndexBase = 0;
   static const uint32_t kFragmentGroupDescriptionIndexBase = 0x10000;
 
@@ -180,16 +204,19 @@ public:
 class Sbgp final : public Atom // SampleToGroup box.
 {
 public:
   explicit Sbgp(Box& aBox);
 
   AtomType mGroupingType;
   uint32_t mGroupingTypeParam;
   FallibleTArray<SampleToGroupEntry> mEntries;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 struct CencSampleEncryptionInfoEntry final
 {
 public:
   CencSampleEncryptionInfoEntry() { }
 
   bool Init(BoxReader& aReader);
@@ -201,16 +228,19 @@ public:
 
 class Sgpd final : public Atom // SampleGroupDescription box.
 {
 public:
   explicit Sgpd(Box& aBox);
 
   AtomType mGroupingType;
   FallibleTArray<CencSampleEncryptionInfoEntry> mEntries;
+
+protected:
+  bool Parse(Box& aBox);
 };
 
 class AuxInfo {
 public:
   AuxInfo(int64_t aMoofOffset, Saiz& aSaiz, Saio& aSaio);
 
 private:
   int64_t mMoofOffset;