Bug 1109431 - Apply TimestampsFuzzyEqual rounding to the buffered ranges returned from multiple decoders. r=ajones
☠☠ backed out by e96e649cb487 ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 11 Dec 2014 10:52:57 +1300
changeset 219110 0b71e08f9d349250f0e6371e69c4dcc22d96cfa6
parent 219109 e278ad9face80b30191e821cc4c80cce3d88f0d8
child 219111 c395ddeb9e91b4a5baf12ffbce50d7d3d7725ec6
push id52729
push usermwoodrow@mozilla.com
push dateWed, 10 Dec 2014 22:37:10 +0000
treeherdermozilla-inbound@0b71e08f9d34 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersajones
bugs1109431
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 1109431 - Apply TimestampsFuzzyEqual rounding to the buffered ranges returned from multiple decoders. r=ajones
dom/html/TimeRanges.cpp
dom/html/TimeRanges.h
dom/media/mediasource/ContainerParser.cpp
dom/media/mediasource/ContainerParser.h
dom/media/mediasource/TrackBuffer.cpp
--- a/dom/html/TimeRanges.cpp
+++ b/dom/html/TimeRanges.cpp
@@ -93,49 +93,49 @@ TimeRanges::GetEndTime()
 {
   if (mRanges.IsEmpty()) {
     return -1.0;
   }
   return mRanges[mRanges.Length() - 1].mEnd;
 }
 
 void
-TimeRanges::Normalize()
+TimeRanges::Normalize(double aError)
 {
   if (mRanges.Length() >= 2) {
     nsAutoTArray<TimeRange,4> normalized;
 
     mRanges.Sort(CompareTimeRanges());
 
     // This merges the intervals.
     TimeRange current(mRanges[0]);
     for (uint32_t i = 1; i < mRanges.Length(); i++) {
       if (current.mStart <= mRanges[i].mStart &&
           current.mEnd >= mRanges[i].mEnd) {
         continue;
       }
-      if (current.mEnd >= mRanges[i].mStart) {
+      if (current.mEnd + aError >= mRanges[i].mStart) {
         current.mEnd = mRanges[i].mEnd;
       } else {
         normalized.AppendElement(current);
         current = mRanges[i];
       }
     }
 
     normalized.AppendElement(current);
 
     mRanges = normalized;
   }
 }
 
 void
-TimeRanges::Union(const TimeRanges* aOtherRanges)
+TimeRanges::Union(const TimeRanges* aOtherRanges, double aError)
 {
   mRanges.AppendElements(aOtherRanges->mRanges);
-  Normalize();
+  Normalize(aError);
 }
 
 void
 TimeRanges::Intersection(const TimeRanges* aOtherRanges)
 {
   nsAutoTArray<TimeRange,4> intersection;
 
   const nsTArray<TimeRange>& otherRanges = aOtherRanges->mRanges;
--- a/dom/html/TimeRanges.h
+++ b/dom/html/TimeRanges.h
@@ -37,20 +37,20 @@ public:
 
   // Returns the start time of the first range, or -1 if no ranges exist.
   double GetStartTime();
 
   // Returns the end time of the last range, or -1 if no ranges exist.
   double GetEndTime();
 
   // See http://www.whatwg.org/html/#normalized-timeranges-object
-  void Normalize();
+  void Normalize(double aError = 0.0);
 
   // Mutate this TimeRange to be the union of this and aOtherRanges.
-  void Union(const TimeRanges* aOtherRanges);
+  void Union(const TimeRanges* aOtherRanges, double aError);
 
   // Mutate this TimeRange to be the intersection of this and aOtherRanges.
   void Intersection(const TimeRanges* aOtherRanges);
 
   JSObject* WrapObject(JSContext* aCx);
 
   uint32_t Length() const
   {
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -58,32 +58,41 @@ ContainerParser::ParseStartAndEndTimesta
   return false;
 }
 
 bool
 ContainerParser::TimestampsFuzzyEqual(int64_t aLhs, int64_t aRhs)
 {
   NS_WARNING("Using default ContainerParser::TimestampFuzzyEquals implementation");
   return aLhs == aRhs;
+  return llabs(aLhs - aRhs) <= GetRoundingError();
+}
+
+int64_t
+ContainerParser::GetRoundingError()
+{
+  NS_WARNING("Using default ContainerParser::GetRoundingError implementation");
+  return 0;
 }
 
 const nsTArray<uint8_t>&
 ContainerParser::InitData()
 {
   MOZ_ASSERT(mHasInitData);
   return mInitData;
 }
 
 class WebMContainerParser : public ContainerParser {
 public:
   WebMContainerParser()
     : mParser(0), mOffset(0)
   {}
 
   static const unsigned NS_PER_USEC = 1000;
+  static const unsigned USEC_PER_SEC = 1000000;
 
   bool IsInitSegmentPresent(const uint8_t* aData, uint32_t aLength)
   {
     ContainerParser::IsInitSegmentPresent(aData, aLength);
     // XXX: This is overly primitive, needs to collect data as it's appended
     // to the SB and handle, rather than assuming everything is present in a
     // single aData segment.
     // 0x1a45dfa3 // EBML
@@ -177,20 +186,20 @@ public:
               this, aStart, aEnd, mapping[0].mSyncOffset, mapping[endIdx].mEndOffset, mapping.Length(), endIdx);
 
     mapping.RemoveElementsAt(0, endIdx + 1);
     mOverlappedMapping.AppendElements(mapping);
 
     return true;
   }
 
-  bool TimestampsFuzzyEqual(int64_t aLhs, int64_t aRhs)
+  int64_t GetRoundingError()
   {
     int64_t error = mParser.GetTimecodeScale() / NS_PER_USEC;
-    return llabs(aLhs - aRhs) <= error * 2;
+    return error * 2;
   }
 
 private:
   WebMBufferedParser mParser;
   nsTArray<WebMTimeDataOffset> mOverlappedMapping;
   int64_t mOffset;
 };
 
@@ -271,19 +280,19 @@ public:
     }
     aStart = compositionRange.start;
     aEnd = compositionRange.end;
     MSE_DEBUG("MP4ContainerParser(%p)::ParseStartAndEndTimestamps: [%lld, %lld]",
               this, aStart, aEnd);
     return true;
   }
 
-  bool TimestampsFuzzyEqual(int64_t aLhs, int64_t aRhs)
+  int64_t GetRoundingError()
   {
-    return llabs(aLhs - aRhs) <= 1000;
+    return 1000;
   }
 
 private:
   nsRefPtr<mp4_demuxer::BufferStream> mStream;
   nsAutoPtr<mp4_demuxer::MoofParser> mParser;
 };
 
 /*static*/ ContainerParser*
--- a/dom/media/mediasource/ContainerParser.h
+++ b/dom/media/mediasource/ContainerParser.h
@@ -30,17 +30,19 @@ public:
   // segment.  aData may not start on a parser sync boundary.  Return true
   // if aStart and aEnd have been updated.
   virtual bool ParseStartAndEndTimestamps(const uint8_t* aData, uint32_t aLength,
                                           int64_t& aStart, int64_t& aEnd);
 
   // Compare aLhs and rHs, considering any error that may exist in the
   // timestamps from the format's base representation.  Return true if aLhs
   // == aRhs within the error epsilon.
-  virtual bool TimestampsFuzzyEqual(int64_t aLhs, int64_t aRhs);
+  bool TimestampsFuzzyEqual(int64_t aLhs, int64_t aRhs);
+
+  virtual int64_t GetRoundingError();
 
   const nsTArray<uint8_t>& InitData();
 
   bool HasInitData()
   {
     return mHasInitData;
   }
 
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -311,17 +311,17 @@ TrackBuffer::Buffered(dom::TimeRanges* a
 
   double highestEndTime = 0;
 
   for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
     nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
     mDecoders[i]->GetBuffered(r);
     if (r->Length() > 0) {
       highestEndTime = std::max(highestEndTime, r->GetEndTime());
-      aRanges->Union(r);
+      aRanges->Union(r, double(mParser->GetRoundingError()) / USECS_PER_S);
     }
   }
 
   return highestEndTime;
 }
 
 already_AddRefed<SourceBufferDecoder>
 TrackBuffer::NewDecoder()