Bug 1098126 - MoofParser forced moof read. r=mattwoodrow, a=sledru
authorAnthony Jones <ajones@mozilla.com>
Tue, 16 Dec 2014 18:10:45 +1300
changeset 242462 0b89600c76dbcebf7a3175991643eb771f409bb4
parent 242461 32cfcdbc5dd7994eb1ed84c814ce8c4f18ccc246
child 242463 a409b87264ea59f945208eb669e82f5a30f6f7ec
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, sledru
bugs1098126
milestone36.0a2
Bug 1098126 - MoofParser forced moof read. r=mattwoodrow, a=sledru
media/libstagefright/binding/Index.cpp
media/libstagefright/binding/MoofParser.cpp
media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
--- a/media/libstagefright/binding/Index.cpp
+++ b/media/libstagefright/binding/Index.cpp
@@ -107,18 +107,21 @@ MP4Sample* SampleIterator::GetNext()
 MP4Sample* SampleIterator::Get()
 {
   if (!mIndex->mMoofParser) {
     return nullptr;
   }
 
   nsTArray<Moof>& moofs = mIndex->mMoofParser->mMoofs;
   while (true) {
-    if (mCurrentMoof >= moofs.Length()) {
-      return nsAutoPtr<MP4Sample>();
+    if (mCurrentMoof == moofs.Length()) {
+      if (!mIndex->mMoofParser->BlockingReadNextMoof()) {
+        return nsAutoPtr<MP4Sample>();
+      }
+      MOZ_ASSERT(mCurrentMoof < moofs.Length());
     }
     if (mCurrentSample < moofs[mCurrentMoof].mIndex.Length()) {
       break;
     }
     mCurrentSample = 0;
     ++mCurrentMoof;
   }
   Sample& s = moofs[mCurrentMoof].mIndex[mCurrentSample];
@@ -149,16 +152,19 @@ void SampleIterator::Seek(Microseconds a
     nsAutoPtr<MP4Sample> sample(Get());
     if (sample->composition_timestamp > aTime) {
       break;
     }
     if (sample->is_sync_point) {
       syncMoof = mCurrentMoof;
       syncSample = mCurrentSample;
     }
+    if (sample->composition_timestamp == aTime) {
+      break;
+    }
     Next();
   }
   mCurrentMoof = syncMoof;
   mCurrentSample = syncSample;
 }
 
 Index::Index(const stagefright::Vector<MediaSource::Indice>& aIndex,
              Stream* aSource, uint32_t aTrackId)
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -7,22 +7,27 @@
 
 namespace mp4_demuxer
 {
 
 using namespace stagefright;
 using namespace mozilla;
 
 void
-MoofParser::RebuildFragmentedIndex(const nsTArray<MediaByteRange>& aByteRanges)
+MoofParser::RebuildFragmentedIndex(
+  const nsTArray<mozilla::MediaByteRange>& aByteRanges)
 {
   BoxContext context(mSource, aByteRanges);
+  RebuildFragmentedIndex(context);
+}
 
-  Box box(&context, mOffset);
-  for (; box.IsAvailable(); box = box.Next()) {
+void
+MoofParser::RebuildFragmentedIndex(BoxContext& aContext)
+{
+  for (Box box(&aContext, mOffset); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("moov")) {
       mInitRange = MediaByteRange(0, box.Range().mEnd);
       ParseMoov(box);
     } else if (box.IsType("moof")) {
       Moof moof(box, mTrex, mMdhd, mEdts);
 
       if (!mMoofs.IsEmpty()) {
         // Stitch time ranges together in the case of a (hopefully small) time
@@ -31,16 +36,66 @@ MoofParser::RebuildFragmentedIndex(const
       }
 
       mMoofs.AppendElement(moof);
     }
     mOffset = box.NextOffset();
   }
 }
 
+class BlockingStream : public Stream {
+public:
+  BlockingStream(Stream* aStream) : mStream(aStream)
+  {
+  }
+
+  bool ReadAt(int64_t offset, void* data, size_t size, size_t* bytes_read)
+    MOZ_OVERRIDE
+  {
+    return mStream->ReadAt(offset, data, size, bytes_read);
+  }
+
+  bool CachedReadAt(int64_t offset, void* data, size_t size, size_t* bytes_read)
+    MOZ_OVERRIDE
+  {
+    return mStream->ReadAt(offset, data, size, bytes_read);
+  }
+
+  virtual bool Length(int64_t* size) MOZ_OVERRIDE
+  {
+    return mStream->Length(size);
+  }
+
+private:
+  nsRefPtr<Stream> mStream;
+};
+
+bool
+MoofParser::BlockingReadNextMoof()
+{
+  nsTArray<MediaByteRange> byteRanges;
+  int64_t size;
+  bool hasSize = mSource->Length(&size);
+  byteRanges.AppendElement(
+    MediaByteRange(0,hasSize ? size : std::numeric_limits<int64_t>::max()));
+  mp4_demuxer::BlockingStream* stream = new BlockingStream(mSource);
+
+  BoxContext context(stream, byteRanges);
+  for (Box box(&context, mOffset); box.IsAvailable(); box = box.Next()) {
+    if (box.IsType("moof")) {
+      byteRanges.Clear();
+      byteRanges.AppendElement(MediaByteRange(mOffset, box.Range().mEnd));
+      RebuildFragmentedIndex(context);
+      return true;
+    }
+  }
+  return false;
+}
+
+
 Interval<Microseconds>
 MoofParser::GetCompositionRange(const nsTArray<MediaByteRange>& aByteRanges)
 {
   Interval<Microseconds> compositionRange;
   BoxContext context(mSource, aByteRanges);
   for (size_t i = 0; i < mMoofs.Length(); i++) {
     Moof& moof = mMoofs[i];
     Box box(&context, moof.mRange.mStart);
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -7,16 +7,17 @@
 
 #include "mp4_demuxer/mp4_demuxer.h"
 #include "MediaResource.h"
 
 namespace mp4_demuxer {
 
 class Stream;
 class Box;
+class BoxContext;
 class Moof;
 
 class Tkhd
 {
 public:
   Tkhd()
     : mCreationTime(0)
     , mModificationTime(0)
@@ -136,24 +137,27 @@ public:
   MoofParser(Stream* aSource, uint32_t aTrackId)
     : mSource(aSource), mOffset(0), mTrex(aTrackId)
   {
     // Setting the mTrex.mTrackId to 0 is a nasty work around for calculating
     // the composition range for MSE. We need an array of tracks.
   }
   void RebuildFragmentedIndex(
     const nsTArray<mozilla::MediaByteRange>& aByteRanges);
+  void RebuildFragmentedIndex(BoxContext& aContext);
   Interval<Microseconds> GetCompositionRange(
     const nsTArray<mozilla::MediaByteRange>& aByteRanges);
   bool ReachedEnd();
   void ParseMoov(Box& aBox);
   void ParseTrak(Box& aBox);
   void ParseMdia(Box& aBox, Tkhd& aTkhd);
   void ParseMvex(Box& aBox);
 
+  bool BlockingReadNextMoof();
+
   mozilla::MediaByteRange mInitRange;
   nsRefPtr<Stream> mSource;
   uint64_t mOffset;
   nsTArray<uint64_t> mMoofOffsets;
   Mdhd mMdhd;
   Trex mTrex;
   Tfdt mTfdt;
   Edts mEdts;