Bug 1118528 - Use fuzzy comparisons in MediaSourceReader::HaveData. r=cajbir
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 12 Jan 2015 09:47:56 +1300
changeset 248984 6f70785ed447f102427cc01a76cdb1ddfe14fce6
parent 248983 c9177ec839af085abfe9390c947e1a277a3a5e80
child 248985 7e4003516dd5f56463945c8e06515f28abefa83c
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs1118528
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 1118528 - Use fuzzy comparisons in MediaSourceReader::HaveData. r=cajbir
dom/html/TimeRanges.cpp
dom/html/TimeRanges.h
dom/media/mediasource/MediaSourceReader.cpp
dom/media/mediasource/MediaSourceReader.h
--- a/dom/html/TimeRanges.cpp
+++ b/dom/html/TimeRanges.cpp
@@ -151,20 +151,20 @@ TimeRanges::Intersection(const TimeRange
       j += 1;
     }
   }
 
   mRanges = intersection;
 }
 
 TimeRanges::index_type
-TimeRanges::Find(double aTime)
+TimeRanges::Find(double aTime, double aError /* = 0 */)
 {
   for (index_type i = 0; i < mRanges.Length(); ++i) {
-    if (aTime >= mRanges[i].mStart && aTime < mRanges[i].mEnd) {
+    if (aTime < mRanges[i].mEnd && (aTime + aError) >= mRanges[i].mStart) {
       return i;
     }
   }
   return NoIndex;
 }
 
 JSObject*
 TimeRanges::WrapObject(JSContext* aCx)
--- a/dom/html/TimeRanges.h
+++ b/dom/html/TimeRanges.h
@@ -86,17 +86,17 @@ private:
   };
 
   nsAutoTArray<TimeRange,4> mRanges;
 
 public:
   typedef nsTArray<TimeRange>::index_type index_type;
   static const index_type NoIndex = index_type(-1);
 
-  index_type Find(double aTime);
+  index_type Find(double aTime, double aError = 0);
 
   bool Contains(double aStart, double aEnd) {
     index_type target = Find(aStart);
     if (target == NoIndex) {
       return false;
     }
 
     return mRanges[target].mEnd >= aEnd;
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -198,17 +198,17 @@ MediaSourceReader::OnAudioNotDecoded(Not
   MOZ_ASSERT(aReason == END_OF_STREAM);
   if (mAudioReader) {
     AdjustEndTime(&mLastAudioTime, mAudioReader);
   }
 
   // See if we can find a different reader that can pick up where we left off. We use the
   // EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
   // 1065207.
-  if (SwitchAudioReader(mLastAudioTime + EOS_FUZZ_US)) {
+  if (SwitchAudioReader(mLastAudioTime, EOS_FUZZ_US)) {
     mAudioReader->RequestAudioData()->Then(GetTaskQueue(), __func__, this,
                                            &MediaSourceReader::OnAudioDecoded,
                                            &MediaSourceReader::OnAudioNotDecoded);
     return;
   }
 
   // If the entire MediaSource is done, generate an EndOfStream.
   if (IsEnded()) {
@@ -288,17 +288,17 @@ MediaSourceReader::OnVideoNotDecoded(Not
   MOZ_ASSERT(aReason == END_OF_STREAM);
   if (mVideoReader) {
     AdjustEndTime(&mLastVideoTime, mVideoReader);
   }
 
   // See if we can find a different reader that can pick up where we left off. We use the
   // EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
   // 1065207.
-  if (SwitchVideoReader(mLastVideoTime + EOS_FUZZ_US)) {
+  if (SwitchVideoReader(mLastVideoTime, EOS_FUZZ_US)) {
     mVideoReader->RequestVideoData(false, 0)
                 ->Then(GetTaskQueue(), __func__, this,
                        &MediaSourceReader::OnVideoDecoded,
                        &MediaSourceReader::OnVideoNotDecoded);
     return;
   }
 
   // If the entire MediaSource is done, generate an EndOfStream.
@@ -366,75 +366,77 @@ MediaSourceReader::BreakCycles()
   for (uint32_t i = 0; i < mShutdownTrackBuffers.Length(); ++i) {
     mShutdownTrackBuffers[i]->BreakCycles();
   }
   mShutdownTrackBuffers.Clear();
 }
 
 already_AddRefed<MediaDecoderReader>
 MediaSourceReader::SelectReader(int64_t aTarget,
+                                int64_t aError,
                                 const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders)
 {
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
 
   // Consider decoders in order of newest to oldest, as a newer decoder
   // providing a given buffered range is expected to replace an older one.
   for (int32_t i = aTrackDecoders.Length() - 1; i >= 0; --i) {
     nsRefPtr<MediaDecoderReader> newReader = aTrackDecoders[i]->GetReader();
 
     nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
     aTrackDecoders[i]->GetBuffered(ranges);
-    if (ranges->Find(double(aTarget) / USECS_PER_S) == dom::TimeRanges::NoIndex) {
+    if (ranges->Find(double(aTarget) / USECS_PER_S,
+                     double(aError) / USECS_PER_S) == dom::TimeRanges::NoIndex) {
       MSE_DEBUGV("MediaSourceReader(%p)::SelectReader(%lld) newReader=%p target not in ranges=%s",
                  this, aTarget, newReader.get(), DumpTimeRanges(ranges).get());
       continue;
     }
 
     return newReader.forget();
   }
 
   return nullptr;
 }
 
 bool
 MediaSourceReader::HaveData(int64_t aTarget, MediaData::Type aType)
 {
   TrackBuffer* trackBuffer = aType == MediaData::AUDIO_DATA ? mAudioTrack : mVideoTrack;
   MOZ_ASSERT(trackBuffer);
-  nsRefPtr<MediaDecoderReader> reader = SelectReader(aTarget, trackBuffer->Decoders());
+  nsRefPtr<MediaDecoderReader> reader = SelectReader(aTarget, EOS_FUZZ_US, trackBuffer->Decoders());
   return !!reader;
 }
 
 bool
-MediaSourceReader::SwitchAudioReader(int64_t aTarget)
+MediaSourceReader::SwitchAudioReader(int64_t aTarget, int64_t aError)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   // XXX: Can't handle adding an audio track after ReadMetadata.
   if (!mAudioTrack) {
     return false;
   }
-  nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget, mAudioTrack->Decoders());
+  nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget, aError, mAudioTrack->Decoders());
   if (newReader && newReader != mAudioReader) {
     mAudioReader->SetIdle();
     mAudioReader = newReader;
     MSE_DEBUGV("MediaSourceReader(%p)::SwitchAudioReader switched reader to %p", this, mAudioReader.get());
     return true;
   }
   return false;
 }
 
 bool
-MediaSourceReader::SwitchVideoReader(int64_t aTarget)
+MediaSourceReader::SwitchVideoReader(int64_t aTarget, int64_t aError)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   // XXX: Can't handle adding a video track after ReadMetadata.
   if (!mVideoTrack) {
     return false;
   }
-  nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget, mVideoTrack->Decoders());
+  nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget, aError, mVideoTrack->Decoders());
   if (newReader && newReader != mVideoReader) {
     mVideoReader->SetIdle();
     mVideoReader = newReader;
     MSE_DEBUGV("MediaSourceReader(%p)::SwitchVideoReader switched reader to %p", this, mVideoReader.get());
     return true;
   }
   return false;
 }
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -125,22 +125,26 @@ public:
   // Return true if the Ended method has been called
   bool IsEnded();
 
 #ifdef MOZ_EME
   nsresult SetCDMProxy(CDMProxy* aProxy);
 #endif
 
 private:
-  bool SwitchAudioReader(int64_t aTarget);
-  bool SwitchVideoReader(int64_t aTarget);
+  // Switch the current audio/video reader to the reader that
+  // contains aTarget (or up to aError after target). Both
+  // aTarget and aError are in microseconds.
+  bool SwitchAudioReader(int64_t aTarget, int64_t aError = 0);
+  bool SwitchVideoReader(int64_t aTarget, int64_t aError = 0);
 
   // Return a reader from the set available in aTrackDecoders that has data
   // available in the range requested by aTarget.
   already_AddRefed<MediaDecoderReader> SelectReader(int64_t aTarget,
+                                                    int64_t aError,
                                                     const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
   bool HaveData(int64_t aTarget, MediaData::Type aType);
 
   void AttemptSeek();
   void FinalizeSeek();
 
   nsRefPtr<MediaDecoderReader> mAudioReader;
   nsRefPtr<MediaDecoderReader> mVideoReader;