Bug 1171330: P6. Make RangeRemoval use promises. r=cajbir
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 11 Jun 2015 15:55:12 +1000
changeset 248270 cd08ea9d91939991327b01020d53e9d7f4b1e02f
parent 248269 5d30edb9048a289f28c7ef6dd13d4a53fb0170d8
child 248271 2aef130d13cd0760ed3d74a38527ea3d25970b22
push id28893
push userkwierso@gmail.com
push dateFri, 12 Jun 2015 00:02:58 +0000
treeherderautoland@8cf9d3e497f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs1171330
milestone41.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 1171330: P6. Make RangeRemoval use promises. r=cajbir
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/SourceBuffer.h
dom/media/mediasource/SourceBufferContentManager.h
dom/media/mediasource/TrackBuffer.cpp
dom/media/mediasource/TrackBuffer.h
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -53,44 +53,16 @@ public:
     return NS_OK;
   }
 
 private:
   nsRefPtr<SourceBuffer> mSourceBuffer;
   uint32_t mUpdateID;
 };
 
-class RangeRemovalRunnable : public nsRunnable {
-public:
-  RangeRemovalRunnable(SourceBuffer* aSourceBuffer,
-                       double aStart,
-                       double aEnd)
-  : mSourceBuffer(aSourceBuffer)
-  , mStart(aStart)
-  , mEnd(aEnd)
-  { }
-
-  NS_IMETHOD Run() override final {
-
-    if (!mSourceBuffer->mUpdating) {
-      // abort was called in between.
-      return NS_OK;
-    }
-    mSourceBuffer->DoRangeRemoval(mStart, mEnd);
-    mSourceBuffer->StopUpdating();
-
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<SourceBuffer> mSourceBuffer;
-  double mStart;
-  double mEnd;
-};
-
 void
 SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SetMode(aMode=%d)", aMode);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
@@ -240,39 +212,30 @@ SourceBuffer::Remove(double aStart, doub
       aEnd <= aStart || IsNaN(aEnd)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
   }
 
-  StartUpdating();
-  nsCOMPtr<nsIRunnable> task = new RangeRemovalRunnable(this, aStart, aEnd);
-  NS_DispatchToMainThread(task);
+  RangeRemoval(aStart, aEnd);
 }
 
 void
 SourceBuffer::RangeRemoval(double aStart, double aEnd)
 {
   StartUpdating();
-  DoRangeRemoval(aStart, aEnd);
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
-  NS_DispatchToMainThread(task);
-}
 
-void
-SourceBuffer::DoRangeRemoval(double aStart, double aEnd)
-{
-  MSE_DEBUG("DoRangeRemoval(%f, %f)", aStart, aEnd);
-  if (mContentManager && !IsInfinite(aStart)) {
-    mContentManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
-                                  TimeUnit::FromSeconds(aEnd));
-  }
+  nsRefPtr<SourceBuffer> self = this;
+  mContentManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
+                                TimeUnit::FromSeconds(aEnd))
+    ->Then(AbstractThread::MainThread(), __func__,
+           [self] (bool) { self->StopUpdating(); },
+           []() { MOZ_ASSERT(false); });
 }
 
 void
 SourceBuffer::Detach()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("Detach");
   AbortBufferAppend();
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -112,34 +112,31 @@ public:
   // Evict data in the source buffer in the given time range.
   void Evict(double aStart, double aEnd);
 
   double GetBufferedStart();
   double GetBufferedEnd();
 
   // Runs the range removal algorithm as defined by the MSE spec.
   void RangeRemoval(double aStart, double aEnd);
-  // Actually remove data between aStart and aEnd
-  void DoRangeRemoval(double aStart, double aEnd);
 
   bool IsActive() const
   {
     return mActive;
   }
 
 #if defined(DEBUG)
   void Dump(const char* aPath);
 #endif
 
 private:
   ~SourceBuffer();
 
   friend class AsyncEventRunner<SourceBuffer>;
   friend class BufferAppendRunnable;
-  friend class RangeRemovalRunnable;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   // Update mUpdating and fire the appropriate events.
   void StartUpdating();
   void StopUpdating();
   void AbortUpdating();
 
--- a/dom/media/mediasource/SourceBufferContentManager.h
+++ b/dom/media/mediasource/SourceBufferContentManager.h
@@ -19,16 +19,17 @@ namespace mozilla {
 using media::TimeUnit;
 using media::TimeIntervals;
 
 class SourceBufferContentManager {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SourceBufferContentManager);
 
   typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> AppendPromise;
+  typedef AppendPromise RangeRemovalPromise;
 
   static already_AddRefed<SourceBufferContentManager>
   CreateManager(MediaSourceDecoder* aParentDecoder, const nsACString& aType);
 
   // Add data to the end of the input buffer.
   // Returns false if the append failed.
   virtual bool
   AppendData(MediaLargeByteBuffer* aData, TimeUnit aTimestampOffset) = 0;
@@ -43,17 +44,17 @@ public:
 
   // Run MSE Reset Parser State Algorithm.
   // 3.5.2 Reset Parser State
   // http://w3c.github.io/media-source/#sourcebuffer-reset-parser-state
   virtual void ResetParserState() = 0;
 
   // Runs MSE range removal algorithm.
   // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
-  virtual bool RangeRemoval(TimeUnit aStart, TimeUnit aEnd) = 0;
+  virtual nsRefPtr<RangeRemovalPromise> RangeRemoval(TimeUnit aStart, TimeUnit aEnd) = 0;
 
   enum class EvictDataResult : int8_t
   {
     NO_DATA_EVICTED,
     DATA_EVICTED,
     CANT_EVICT,
   };
 
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -1086,36 +1086,36 @@ TrackBuffer::RemoveDecoder(SourceBufferD
     // we aren't using it in the MediaSourceReader.
     MOZ_ASSERT(!mParentDecoder->IsActiveReader(aDecoder->GetReader()));
     mInitializedDecoders.RemoveElement(aDecoder);
     mDecoders.RemoveElement(aDecoder);
   }
   aDecoder->GetReader()->TaskQueue()->Dispatch(task.forget());
 }
 
-bool
+nsRefPtr<TrackBuffer::RangeRemovalPromise>
 TrackBuffer::RangeRemoval(TimeUnit aStart, TimeUnit aEnd)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
 
   TimeIntervals buffered = Buffered();
   TimeUnit bufferedStart = buffered.GetStart();
   TimeUnit bufferedEnd = buffered.GetEnd();
 
   if (!buffered.Length() || aStart > bufferedEnd || aEnd < bufferedStart) {
     // Nothing to remove.
-    return false;
+    return RangeRemovalPromise::CreateAndResolve(false, __func__);
   }
 
   if (aStart > bufferedStart && aEnd < bufferedEnd) {
     // TODO. We only handle trimming and removal from the start.
     NS_WARNING("RangeRemoval unsupported arguments. "
                "Can only handle trimming (trim left or trim right");
-    return false;
+    return RangeRemovalPromise::CreateAndResolve(false, __func__);
   }
 
   nsTArray<SourceBufferDecoder*> decoders;
   decoders.AppendElements(mInitializedDecoders);
 
   if (aStart <= bufferedStart && aEnd < bufferedEnd) {
     // Evict data from beginning.
     for (size_t i = 0; i < decoders.Length(); ++i) {
@@ -1131,17 +1131,17 @@ TrackBuffer::RangeRemoval(TimeUnit aStar
         MSE_DEBUG("removing some bufferedEnd=%f offset=%lld size=%lld",
                   buffered.GetEnd().ToSeconds(), offset,
                   decoders[i]->GetResource()->GetSize());
         if (offset > 0) {
           ErrorResult rv;
           decoders[i]->GetResource()->EvictData(offset, offset, rv);
           if (NS_WARN_IF(rv.Failed())) {
             rv.SuppressException();
-            return false;
+            return RangeRemovalPromise::CreateAndResolve(false, __func__);
           }
         }
       }
       decoders[i]->GetReader()->NotifyDataRemoved();
     }
   } else {
     // Only trimming existing buffers.
     for (size_t i = 0; i < decoders.Length(); ++i) {
@@ -1153,17 +1153,17 @@ TrackBuffer::RangeRemoval(TimeUnit aStar
       }
       decoders[i]->GetReader()->NotifyDataRemoved();
     }
   }
 
   RemoveEmptyDecoders(decoders);
 
   NotifyTimeRangesChanged();
-  return true;
+  return RangeRemovalPromise::CreateAndResolve(true, __func__);
 }
 
 void
 TrackBuffer::AdjustDecodersTimestampOffset(TimeUnit aOffset)
 {
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   for (uint32_t i = 0; i < mDecoders.Length(); i++) {
     mDecoders[i]->SetTimestampOffset(mDecoders[i]->GetTimestampOffset() + aOffset.ToMicroseconds());
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -43,17 +43,17 @@ public:
   // bytes. aBufferStartTime contains the new start time of the current
   // decoders buffered data after the eviction.
   EvictDataResult EvictData(TimeUnit aPlaybackTime, uint32_t aThreshold, TimeUnit* aBufferStartTime) override;
 
   // Evicts data held in all the decoders SourceBufferResource from the start
   // of the buffer through to aTime.
   void EvictBefore(TimeUnit aTime) override;
 
-  bool RangeRemoval(TimeUnit aStart, TimeUnit aEnd) override;
+  nsRefPtr<RangeRemovalPromise> RangeRemoval(TimeUnit aStart, TimeUnit aEnd) override;
 
   void AbortAppendData() override;
 
   int64_t GetSize() override;
 
   void ResetParserState() override;
 
   // Returns the union of the decoders buffered ranges in aRanges.