Bug 1061079 - Handle misaligned SourceBuffer appends for MP4; r=kinetik
authorAnthony Jones <ajones@mozilla.com>
Thu, 11 Sep 2014 15:57:35 +1200
changeset 204769 2097b83ffbab847fa200bb891fc0bd3ac98d3463
parent 204768 3331b49ff9e6063c4f2347e2a729631bbbca760a
child 204770 b3f02eb02208092fd717e126b1dad3592b03ac7b
push id27465
push usercbook@mozilla.com
push dateThu, 11 Sep 2014 13:27:15 +0000
treeherdermozilla-central@ef81f73048dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1061079
milestone35.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 1061079 - Handle misaligned SourceBuffer appends for MP4; r=kinetik
content/media/mediasource/SourceBuffer.cpp
--- a/content/media/mediasource/SourceBuffer.cpp
+++ b/content/media/mediasource/SourceBuffer.cpp
@@ -197,17 +197,17 @@ public:
 private:
   WebMBufferedParser mParser;
   nsTArray<WebMTimeDataOffset> mOverlappedMapping;
   int64_t mOffset;
 };
 
 class MP4ContainerParser : public ContainerParser {
 public:
-  MP4ContainerParser() : mTimescale(0) {}
+  MP4ContainerParser() {}
 
   bool IsInitSegmentPresent(const uint8_t* aData, uint32_t aLength)
   {
     ContainerParser::IsInitSegmentPresent(aData, aLength);
     // Each MP4 atom has a chunk size and chunk type. The root chunk in an MP4
     // file is the 'ftyp' atom followed by a file type. We just check for a
     // vaguely valid 'ftyp' atom.
 
@@ -229,51 +229,57 @@ public:
 
     return aData[4] == 'f' && aData[5] == 't' && aData[6] == 'y' &&
            aData[7] == 'p';
   }
 
   virtual bool ParseStartAndEndTimestamps(const uint8_t* aData, uint32_t aLength,
                                           double& aStart, double& aEnd)
   {
-    mp4_demuxer::MoofParser parser(new mp4_demuxer::BufferStream(aData, aLength), 0);
-    parser.mMdhd.mTimescale = mTimescale;
+    bool initSegment = IsInitSegmentPresent(aData, aLength);
+    if (initSegment) {
+      mStream = new mp4_demuxer::BufferStream();
+      mParser = new mp4_demuxer::MoofParser(mStream, 0);
+    } else if (!mStream || !mParser) {
+      return false;
+    }
 
+    mStream->AppendBytes(aData, aLength);
     nsTArray<MediaByteRange> byteRanges;
-    byteRanges.AppendElement(MediaByteRange(0, aLength));
-    parser.RebuildFragmentedIndex(byteRanges);
+    byteRanges.AppendElement(mStream->GetByteRange());
+    mParser->RebuildFragmentedIndex(byteRanges);
 
-    if (IsInitSegmentPresent(aData, aLength)) {
-      const MediaByteRange& range = parser.mInitRange;
+    if (initSegment) {
+      const MediaByteRange& range = mParser->mInitRange;
       MSE_DEBUG("MP4ContainerParser(%p)::ParseStartAndEndTimestamps: Stashed init of %u bytes.",
                 this, range.mEnd - range.mStart);
 
       mInitData.ReplaceElementsAt(0, mInitData.Length(),
                                   aData + range.mStart,
                                   range.mEnd - range.mStart);
     }
 
-    // Persist the timescale for when it is absent in later chunks
-    mTimescale = parser.mMdhd.mTimescale;
+    mp4_demuxer::Interval<mp4_demuxer::Microseconds> compositionRange =
+      mParser->GetCompositionRange(byteRanges);
 
-    mp4_demuxer::Interval<mp4_demuxer::Microseconds> compositionRange =
-        parser.GetCompositionRange();
+    mStream->DiscardBefore(mParser->mOffset);
 
     if (compositionRange.IsNull()) {
       return false;
     }
     aStart = static_cast<double>(compositionRange.start) / USECS_PER_S;
     aEnd = static_cast<double>(compositionRange.end) / USECS_PER_S;
     MSE_DEBUG("MP4ContainerParser(%p)::ParseStartAndEndTimestamps: [%f, %f]",
               this, aStart, aEnd);
     return true;
   }
 
-  private:
-    uint32_t mTimescale;
+private:
+  nsRefPtr<mp4_demuxer::BufferStream> mStream;
+  nsAutoPtr<mp4_demuxer::MoofParser> mParser;
 };
 
 
 /*static*/ ContainerParser*
 ContainerParser::CreateForMIMEType(const nsACString& aType)
 {
   if (aType.LowerCaseEqualsLiteral("video/webm") || aType.LowerCaseEqualsLiteral("audio/webm")) {
     return new WebMContainerParser();