Bug 1298271 - Make BoxReader use AutoByteReader - r=jya draft
authorGerald Squelart <gsquelart@mozilla.com>
Fri, 26 Aug 2016 18:14:24 +1000
changeset 406348 6deba02ac553303b0a2b694c24bfcb54c2e732b1
parent 406087 54fca3168a70d951e6012baea4bf0544827cae11
child 529631 96a08e8e8ae8676d7cea280ea237aa590fa54d75
push id27695
push usergsquelart@mozilla.com
push dateSat, 27 Aug 2016 01:07:33 +0000
reviewersjya
bugs1298271
milestone51.0a1
Bug 1298271 - Make BoxReader use AutoByteReader - r=jya This is done by moving FlacFrameParsers' AutoByteReader to a more public spot in libstagefright's bindings. Using AutoByteReader means there is no more need for explicit calls to DiscardRemaining(); which means our parsers relying on BoxReader will be more lenient about boxes that are larger than needed. MozReview-Commit-ID: 3EERU749WYB
dom/media/flac/FlacFrameParser.cpp
media/libstagefright/binding/Box.cpp
media/libstagefright/binding/MoofParser.cpp
media/libstagefright/binding/SinfParser.cpp
media/libstagefright/binding/include/mp4_demuxer/Box.h
media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
--- a/dom/media/flac/FlacFrameParser.cpp
+++ b/dom/media/flac/FlacFrameParser.cpp
@@ -5,33 +5,21 @@
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FlacFrameParser.h"
 #include "mp4_demuxer/ByteReader.h"
 #include "nsTArray.h"
 #include "OggCodecState.h"
 #include "VideoUtils.h"
 
+using mp4_demuxer::AutoByteReader;
+
 namespace mozilla
 {
 
-class MOZ_RAII AutoByteReader : public mp4_demuxer::ByteReader
-{
-public:
-  AutoByteReader(const uint8_t* aData, size_t aSize)
-    : mp4_demuxer::ByteReader(aData, aSize)
-  {
-
-  }
-  ~AutoByteReader()
-  {
-    DiscardRemaining();
-  }
-};
-
 #define OGG_FLAC_METADATA_TYPE_STREAMINFO 0x7F
 #define FLAC_STREAMINFO_SIZE   34
 
 #define BITMASK(x) ((1ULL << x)-1)
 
 enum
 {
   FLAC_METADATA_TYPE_STREAMINFO = 0,
--- a/media/libstagefright/binding/Box.cpp
+++ b/media/libstagefright/binding/Box.cpp
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mp4_demuxer/Box.h"
 #include "mp4_demuxer/Stream.h"
 #include "mozilla/EndianUtils.h"
+#include "mozilla/Unused.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 namespace mp4_demuxer {
 
 // Limit reads to 32MiB max.
 // static
@@ -136,20 +137,22 @@ Box::FirstChild() const
 {
   MOZ_ASSERT(IsAvailable());
   if (mChildOffset == mRange.mEnd) {
     return Box();
   }
   return Box(mContext, mChildOffset, this);
 }
 
-bool
-Box::Read(nsTArray<uint8_t>* aDest)
+nsTArray<uint8_t>
+Box::Read()
 {
-  return Read(aDest, mRange);
+  nsTArray<uint8_t> out;
+  Unused << Read(&out, mRange);
+  return out;
 }
 
 bool
 Box::Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange)
 {
   int64_t length;
   if (!mContext->mSource->Length(&length)) {
     // The HTTP server didn't give us a length to work with.
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -639,18 +639,17 @@ Tkhd::Tkhd(Box& aBox)
   } 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();
   }
-  // More stuff that we don't care about
-  reader->DiscardRemaining();
+  // We don't care about whatever else may be in the box.
   mValid = true;
 }
 
 Mvhd::Mvhd(Box& aBox)
 {
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Mdhd, "Incomplete Box (missing flags)");
@@ -672,21 +671,19 @@ Mvhd::Mvhd(Box& aBox)
     mTimescale = reader->ReadU32();
     mDuration = reader->ReadU32();
   } else if (version == 1) {
     mCreationTime = reader->ReadU64();
     mModificationTime = reader->ReadU64();
     mTimescale = reader->ReadU32();
     mDuration = reader->ReadU64();
   } else {
-    reader->DiscardRemaining();
     return;
   }
-  // More stuff that we don't care about
-  reader->DiscardRemaining();
+  // We don't care about whatever else may be in the box.
   if (mTimescale) {
     mValid = true;
   }
 }
 
 Mdhd::Mdhd(Box& aBox)
   : Mvhd(aBox)
 {
@@ -768,17 +765,16 @@ Tfdt::Tfdt(Box& aBox)
         (uint64_t)reader->Remaining(), (uint64_t)need);
     return;
   }
   if (version == 0) {
     mBaseMediaDecodeTime = reader->ReadU32();
   } else if (version == 1) {
     mBaseMediaDecodeTime = reader->ReadU64();
   }
-  reader->DiscardRemaining();
   mValid = true;
 }
 
 Edts::Edts(Box& aBox)
   : mMediaStart(0)
   , mEmptyOffset(0)
 {
   Box child = aBox.FirstChild();
@@ -849,31 +845,28 @@ Saiz::Saiz(Box& aBox, AtomType aDefaultT
     mAuxInfoType = reader->ReadU32();
     mAuxInfoTypeParameter = reader->ReadU32();
   }
   uint8_t defaultSampleInfoSize = reader->ReadU8();
   uint32_t count = reader->ReadU32();
   if (defaultSampleInfoSize) {
     if (!mSampleInfoSize.SetCapacity(count, fallible)) {
       LOG(Saiz, "OOM");
-      reader->DiscardRemaining();
       return;
     }
     for (int i = 0; i < count; i++) {
       MOZ_ALWAYS_TRUE(mSampleInfoSize.AppendElement(defaultSampleInfoSize,
                                                     fallible));
     }
   } else {
     if (!reader->ReadArray(mSampleInfoSize, count)) {
       LOG(Saiz, "Incomplete Box (OOM or missing count:%u)", count);
-      reader->DiscardRemaining();
       return;
     }
   }
-  reader->DiscardRemaining();
   mValid = true;
 }
 
 Saio::Saio(Box& aBox, AtomType aDefaultType)
   : mAuxInfoType(aDefaultType)
   , mAuxInfoTypeParameter(0)
 {
   BoxReader reader(aBox);
@@ -897,17 +890,16 @@ Saio::Saio(Box& aBox, AtomType aDefaultT
   need = (version ? sizeof(uint64_t) : sizeof(uint32_t)) * count;
   if (reader->Remaining() < need) {
     LOG(Saio, "Incomplete Box (have:%lld need:%lld)",
         (uint64_t)reader->Remaining(), (uint64_t)need);
     return;
   }
   if (!mOffsets.SetCapacity(count, fallible)) {
     LOG(Saiz, "OOM");
-    reader->DiscardRemaining();
     return;
   }
   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++) {
--- a/media/libstagefright/binding/SinfParser.cpp
+++ b/media/libstagefright/binding/SinfParser.cpp
@@ -36,18 +36,16 @@ SinfParser::ParseSchm(Box& aBox)
   BoxReader reader(aBox);
 
   if (reader->Remaining() < 8) {
     return;
   }
 
   mozilla::Unused << reader->ReadU32(); // flags -- ignore
   mSinf.mDefaultEncryptionType = reader->ReadU32();
-
-  reader->DiscardRemaining();
 }
 
 void
 SinfParser::ParseSchi(Box& aBox)
 {
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("tenc")) {
       ParseTenc(box);
--- a/media/libstagefright/binding/include/mp4_demuxer/Box.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/Box.h
@@ -43,40 +43,42 @@ public:
   uint64_t Length() const { return mRange.mEnd - mRange.mStart; }
   uint64_t NextOffset() const { return mRange.mEnd; }
   const MediaByteRange& Range() const { return mRange; }
   const Box* Parent() const { return mParent; }
   bool IsType(const char* aType) const { return mType == AtomType(aType); }
 
   Box Next() const;
   Box FirstChild() const;
-  bool Read(nsTArray<uint8_t>* aDest);
+  nsTArray<uint8_t> Read();
   bool Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange);
 
   static const uint64_t kMAX_BOX_READ;
 
 private:
   bool Contains(MediaByteRange aRange) const;
   BoxContext* mContext;
   mozilla::MediaByteRange mRange;
   uint64_t mBodyOffset;
   uint64_t mChildOffset;
   AtomType mType;
   const Box* mParent;
 };
 
+// BoxReader takes a copy of a box contents and serves through an AutoByteReader.
+MOZ_RAII
 class BoxReader
 {
 public:
   explicit BoxReader(Box& aBox)
+    : mBuffer(aBox.Read())
+    , mReader(mBuffer.Elements(), mBuffer.Length())
   {
-    aBox.Read(&mBuffer);
-    mReader.SetData(mBuffer);
   }
-  ByteReader* operator->() { return &mReader; }
-  ByteReader mReader;
+  AutoByteReader* operator->() { return &mReader; }
 
 private:
   nsTArray<uint8_t> mBuffer;
+  AutoByteReader mReader;
 };
 }
 
 #endif
--- a/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
@@ -52,17 +52,18 @@ public:
   }
 
   size_t Offset()
   {
     return mLength - mRemaining;
   }
 
   // Make it explicit if we're not using the extra bytes.
-  void DiscardRemaining() {
+  void DiscardRemaining()
+  {
     mRemaining = 0;
   }
 
   size_t Remaining() const { return mRemaining; }
 
   bool CanRead8() { return mRemaining >= 1; }
 
   uint8_t ReadU8()
@@ -344,11 +345,29 @@ public:
     return true;
   }
 
 private:
   const uint8_t* mPtr;
   size_t mRemaining;
   size_t mLength;
 };
-}
+
+// A ByteReader that automatically discards remaining data before destruction.
+class MOZ_RAII AutoByteReader : public ByteReader
+{
+public:
+  AutoByteReader(const uint8_t* aData, size_t aSize)
+    : ByteReader(aData, aSize)
+  {
+  }
+  ~AutoByteReader()
+  {
+    ByteReader::DiscardRemaining();
+  }
+
+  // Prevent unneeded DiscardRemaining() calls.
+  void DiscardRemaining() = delete;
+};
+
+} // namespace mp4_demuxer
 
 #endif