Bug 1120079 - Do not call Range Removal algorithm after endOfStream. r=cajbir, a=sledru
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 16 Jan 2015 23:49:02 +1100
changeset 242932 2a36e0243edd
parent 242931 3e5d8c21f3a2
child 242933 9bb138f23d58
push id4342
push userryanvm@gmail.com
push date2015-01-20 16:03 +0000
treeherdermozilla-beta@fae52bd681e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir, sledru
bugs1120079
milestone36.0
Bug 1120079 - Do not call Range Removal algorithm after endOfStream. r=cajbir, a=sledru
dom/media/mediasource/MediaSource.cpp
dom/media/mediasource/MediaSource.h
dom/media/mediasource/MediaSourceDecoder.cpp
dom/media/mediasource/MediaSourceDecoder.h
dom/media/mediasource/SourceBuffer.cpp
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -184,25 +184,25 @@ MediaSource::SetDuration(double aDuratio
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   if (mReadyState != MediaSourceReadyState::Open ||
       mSourceBuffers->AnyUpdating()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
-  SetDuration(aDuration);
+  SetDuration(aDuration, MSRangeRemovalAction::RUN);
 }
 
 void
-MediaSource::SetDuration(double aDuration)
+MediaSource::SetDuration(double aDuration, MSRangeRemovalAction aAction)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_API("MediaSource(%p)::SetDuration(aDuration=%f)", this, aDuration);
-  mDecoder->SetMediaSourceDuration(aDuration);
+  mDecoder->SetMediaSourceDuration(aDuration, aAction);
 }
 
 already_AddRefed<SourceBuffer>
 MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = mozilla::IsTypeSupported(aType);
   MSE_API("MediaSource(%p)::AddSourceBuffer(aType=%s)%s",
@@ -280,17 +280,18 @@ MediaSource::EndOfStream(const Optional<
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   SetReadyState(MediaSourceReadyState::Ended);
   mSourceBuffers->Ended();
   mDecoder->Ended();
   if (!aError.WasPassed()) {
-    mDecoder->SetMediaSourceDuration(mSourceBuffers->GetHighestBufferedEndTime());
+    mDecoder->SetMediaSourceDuration(mSourceBuffers->GetHighestBufferedEndTime(),
+                                     MSRangeRemovalAction::SKIP);
     if (aRv.Failed()) {
       return;
     }
     // TODO:
     //   Notify media element that all data is now available.
     return;
   }
   switch (aError.Value()) {
--- a/dom/media/mediasource/MediaSource.h
+++ b/dom/media/mediasource/MediaSource.h
@@ -24,16 +24,21 @@ struct JSContext;
 class JSObject;
 class nsPIDOMWindow;
 
 namespace mozilla {
 
 class ErrorResult;
 template <typename T> class AsyncEventRunner;
 
+enum MSRangeRemovalAction: uint8_t {
+  RUN = 0,
+  SKIP = 1
+};
+
 namespace dom {
 
 class GlobalObject;
 class SourceBuffer;
 class SourceBufferList;
 template <typename T> class Optional;
 
 #define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID \
@@ -124,17 +129,17 @@ private:
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   void DurationChange(double aOldDuration, double aNewDuration);
 
   void InitializationEvent();
 
   // SetDuration with no checks.
-  void SetDuration(double aDuration);
+  void SetDuration(double aDuration, MSRangeRemovalAction aAction);
 
   nsRefPtr<SourceBufferList> mSourceBuffers;
   nsRefPtr<SourceBufferList> mActiveSourceBuffers;
 
   nsRefPtr<MediaSourceDecoder> mDecoder;
   // Ensures the media element remains alive to dispatch progress and
   // durationchanged events.
   nsRefPtr<HTMLMediaElement> mMediaElement;
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -168,19 +168,19 @@ bool
 MediaSourceDecoder::IsExpectingMoreData()
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   return !mReader->IsEnded();
 }
 
 class DurationChangedRunnable : public nsRunnable {
 public:
-  explicit DurationChangedRunnable(MediaSourceDecoder* aDecoder,
-                                   double aOldDuration,
-                                   double aNewDuration)
+  DurationChangedRunnable(MediaSourceDecoder* aDecoder,
+                          double aOldDuration,
+                          double aNewDuration)
     : mDecoder(aDecoder)
     , mOldDuration(aOldDuration)
     , mNewDuration(aNewDuration)
   { }
 
   NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
     mDecoder->DurationChanged(mOldDuration, mNewDuration);
     return NS_OK;
@@ -213,37 +213,48 @@ MediaSourceDecoder::SetDecodedDuration(i
   if (!mMediaSource || !IsNaN(mMediaSourceDuration)) {
     return;
   }
   double duration = aDuration;
   // A duration of -1 is +Infinity.
   if (aDuration >= 0) {
     duration /= USECS_PER_S;
   }
-  SetMediaSourceDuration(duration);
+  // No need to call Range Removal algorithm as this is called following
+  // ReadMetadata and nothing has been added to the source buffers yet.
+  SetMediaSourceDuration(duration, MSRangeRemovalAction::SKIP);
 }
 
 void
-MediaSourceDecoder::SetMediaSourceDuration(double aDuration)
+MediaSourceDecoder::SetMediaSourceDuration(double aDuration, MSRangeRemovalAction aAction)
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   double oldDuration = mMediaSourceDuration;
   if (aDuration >= 0) {
     mDecoderStateMachine->SetDuration(aDuration * USECS_PER_S);
     mMediaSourceDuration = aDuration;
   } else {
     mDecoderStateMachine->SetDuration(INT64_MAX);
     mMediaSourceDuration = PositiveInfinity<double>();
   }
-  if (NS_IsMainThread()) {
-    DurationChanged(oldDuration, mMediaSourceDuration);
+  if (aAction == MSRangeRemovalAction::SKIP) {
+    if (NS_IsMainThread()) {
+      MediaDecoder::DurationChanged();
+    } else {
+      nsCOMPtr<nsIRunnable> task = NS_NewRunnableMethod(this, &MediaDecoder::DurationChanged);
+      NS_DispatchToMainThread(task);
+    }
   } else {
-    nsRefPtr<nsIRunnable> task =
-      new DurationChangedRunnable(this, oldDuration, mMediaSourceDuration);
-    NS_DispatchToMainThread(task);
+    if (NS_IsMainThread()) {
+      DurationChanged(oldDuration, mMediaSourceDuration);
+    } else {
+      nsRefPtr<nsIRunnable> task =
+        new DurationChangedRunnable(this, oldDuration, mMediaSourceDuration);
+      NS_DispatchToMainThread(task);
+    }
   }
 }
 
 double
 MediaSourceDecoder::GetMediaSourceDuration()
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   return mMediaSourceDuration;
--- a/dom/media/mediasource/MediaSourceDecoder.h
+++ b/dom/media/mediasource/MediaSourceDecoder.h
@@ -16,16 +16,17 @@
 class nsIStreamListener;
 
 namespace mozilla {
 
 class MediaResource;
 class MediaDecoderStateMachine;
 class SourceBufferDecoder;
 class TrackBuffer;
+enum MSRangeRemovalAction : uint8_t;
 
 namespace dom {
 
 class HTMLMediaElement;
 class MediaSource;
 
 } // namespace dom
 
@@ -51,17 +52,17 @@ public:
   void AddTrackBuffer(TrackBuffer* aTrackBuffer);
   void RemoveTrackBuffer(TrackBuffer* aTrackBuffer);
   void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo);
 
   void Ended();
   bool IsExpectingMoreData() MOZ_OVERRIDE;
 
   void SetDecodedDuration(int64_t aDuration);
-  void SetMediaSourceDuration(double aDuration);
+  void SetMediaSourceDuration(double aDuration, MSRangeRemovalAction aAction);
   double GetMediaSourceDuration();
   void DurationChanged(double aOldDuration, double aNewDuration);
 
   // Called whenever a TrackBuffer has new data appended or a new decoder
   // initializes.  Safe to call from any thread.
   void NotifyTimeRangesChanged();
 
   // Indicates the point in time at which the reader should consider
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -327,17 +327,17 @@ SourceBuffer::AbortUpdating()
 }
 
 void
 SourceBuffer::CheckEndTime()
 {
   // Check if we need to update mMediaSource duration
   double endTime = GetBufferedEnd();
   if (endTime > mMediaSource->Duration()) {
-    mMediaSource->SetDuration(endTime);
+    mMediaSource->SetDuration(endTime, MSRangeRemovalAction::SKIP);
   }
 }
 
 void
 SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
 {
   MSE_DEBUG("SourceBuffer(%p)::AppendData(aLength=%u)", this, aLength);
   if (!PrepareAppend(aRv)) {