Bug 1098126 - MoofParser forced moof read; r=mattwoodrow
☠☠ backed out by ea02960b7856 ☠ ☠
authorAnthony Jones <ajones@mozilla.com>
Fri, 05 Dec 2014 14:17:23 -0800
changeset 218537 55dba2167b365f6b98af513ff57ed79740271170
parent 218536 73c2707c4f6028dc5cf63f8862ad5f4329d31f35
child 218538 21aab02fb41c511bb7ef8ed1cbd76cc9f6649111
push id52575
push userajones@mozilla.com
push dateFri, 05 Dec 2014 22:17:36 +0000
treeherdermozilla-inbound@7cf7a6ea28c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1098126
milestone37.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 1098126 - MoofParser forced moof read; r=mattwoodrow
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;