Bug 1125776: Part10. Handle concurrent aborts. r=mattwoodrow
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 04 Feb 2015 20:20:16 +1100
changeset 227445 3c4dc1b74b7f
parent 227444 e05a56284a00
child 227446 e1128d8612ff
push id28230
push userryanvm@gmail.com
push dateWed, 04 Feb 2015 19:42:59 +0000
treeherdermozilla-central@3cda3997f45d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1125776
milestone38.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 1125776: Part10. Handle concurrent aborts. r=mattwoodrow Under some circumstances, it was possible for a cancelled queued task to run and the following one would have been cancelled. Also add more robust handling in cancelling the trackbuffer initialization task.
dom/media/mediasource/MediaSource.cpp
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/SourceBuffer.h
dom/media/mediasource/TrackBuffer.cpp
dom/media/mediasource/TrackBuffer.h
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -243,21 +243,21 @@ MediaSource::RemoveSourceBuffer(SourceBu
 {
   MOZ_ASSERT(NS_IsMainThread());
   SourceBuffer* sourceBuffer = &aSourceBuffer;
   MSE_API("MediaSource(%p)::RemoveSourceBuffer(aSourceBuffer=%p)", this, sourceBuffer);
   if (!mSourceBuffers->Contains(sourceBuffer)) {
     aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return;
   }
-  if (sourceBuffer->Updating()) {
-    // TODO:
-    // abort stream append loop (if running)
-    sourceBuffer->Abort();
-  }
+
+  sourceBuffer->AbortBufferAppend();
+  // TODO:
+  // abort stream append loop (if running)
+
   // TODO:
   // For all sourceBuffer audioTracks, videoTracks, textTracks:
   //     set sourceBuffer to null
   //     remove sourceBuffer video, audio, text Tracks from MediaElement tracks
   //     remove sourceBuffer video, audio, text Tracks and fire "removetrack" at affected lists
   //     fire "removetrack" at modified MediaElement track lists
   // If removed enabled/selected, fire "change" at affected MediaElement list.
   if (mActiveSourceBuffers->Contains(sourceBuffer)) {
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -41,34 +41,37 @@ extern PRLogModuleInfo* GetMediaSourceAP
 namespace mozilla {
 
 namespace dom {
 
 class AppendDataRunnable : public nsRunnable {
 public:
   AppendDataRunnable(SourceBuffer* aSourceBuffer,
                      LargeDataBuffer* aData,
-                     double aTimestampOffset)
+                     double aTimestampOffset,
+                     uint32_t aUpdateID)
   : mSourceBuffer(aSourceBuffer)
   , mData(aData)
   , mTimestampOffset(aTimestampOffset)
+  , mUpdateID(aUpdateID)
   {
   }
 
   NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
 
-    mSourceBuffer->AppendData(mData, mTimestampOffset);
+    mSourceBuffer->AppendData(mData, mTimestampOffset, mUpdateID);
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<SourceBuffer> mSourceBuffer;
   nsRefPtr<LargeDataBuffer> mData;
   double mTimestampOffset;
+  uint32_t mUpdateID;
 };
 
 class RangeRemovalRunnable : public nsRunnable {
 public:
   RangeRemovalRunnable(SourceBuffer* aSourceBuffer,
                      double aStart,
                      double aEnd)
   : mSourceBuffer(aSourceBuffer)
@@ -209,32 +212,33 @@ SourceBuffer::Abort(ErrorResult& aRv)
   if (!IsAttached()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
-  Abort();
+  AbortBufferAppend();
   mTrackBuffer->ResetParserState();
   mAppendWindowStart = 0;
   mAppendWindowEnd = PositiveInfinity<double>();
-
+  // Discard the current decoder so no new data will be added to it.
   MSE_DEBUG("SourceBuffer(%p)::Abort() Discarding decoder", this);
-  mTrackBuffer->DiscardDecoder();
+  mTrackBuffer->DiscardCurrentDecoder();
 }
 
 void
-SourceBuffer::Abort()
+SourceBuffer::AbortBufferAppend()
 {
   if (mUpdating) {
-    // abort any pending buffer append.
-    mTrackBuffer->Abort();
+    mPendingAppend.DisconnectIfExists();
     // TODO: Abort segment parser loop, and stream append loop algorithms.
+    // cancel any pending buffer append.
+    mTrackBuffer->AbortAppendData();
     AbortUpdating();
   }
 }
 
 void
 SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -286,17 +290,17 @@ SourceBuffer::DoRangeRemoval(double aSta
   StopUpdating();
 }
 
 void
 SourceBuffer::Detach()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::Detach", this);
-  Abort();
+  AbortBufferAppend();
   if (mTrackBuffer) {
     mTrackBuffer->Detach();
   }
   mTrackBuffer = nullptr;
   mMediaSource = nullptr;
 }
 
 void
@@ -311,16 +315,17 @@ SourceBuffer::Ended()
 SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
   , mMediaSource(aMediaSource)
   , mAppendWindowStart(0)
   , mAppendWindowEnd(PositiveInfinity<double>())
   , mTimestampOffset(0)
   , mAppendMode(SourceBufferAppendMode::Segments)
   , mUpdating(false)
+  , mUpdateID(0)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aMediaSource);
   mEvictionThreshold = Preferences::GetUint("media.mediasource.eviction_threshold",
                                             75 * (1 << 20));
   mTrackBuffer = new TrackBuffer(aMediaSource->GetDecoder(), aType);
   MSE_DEBUG("SourceBuffer(%p)::SourceBuffer: Create mTrackBuffer=%p",
             this, mTrackBuffer.get());
@@ -362,16 +367,17 @@ SourceBuffer::QueueAsyncSimpleEvent(cons
 }
 
 void
 SourceBuffer::StartUpdating()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mUpdating);
   mUpdating = true;
+  mUpdateID++;
   QueueAsyncSimpleEvent("updatestart");
 }
 
 void
 SourceBuffer::StopUpdating()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mUpdating) {
@@ -419,49 +425,52 @@ SourceBuffer::AppendData(const uint8_t* 
   if (!data) {
     return;
   }
   StartUpdating();
 
   MOZ_ASSERT(mAppendMode == SourceBufferAppendMode::Segments,
              "We don't handle timestampOffset for sequence mode yet");
   nsRefPtr<nsIRunnable> task =
-    new AppendDataRunnable(this, data, mTimestampOffset);
+    new AppendDataRunnable(this, data, mTimestampOffset, mUpdateID);
   NS_DispatchToMainThread(task);
 }
 
 void
-SourceBuffer::AppendData(LargeDataBuffer* aData, double aTimestampOffset)
+SourceBuffer::AppendData(LargeDataBuffer* aData, double aTimestampOffset,
+                         uint32_t aUpdateID)
 {
-  if (!mUpdating) {
+  if (!mUpdating || aUpdateID != mUpdateID) {
     // The buffer append algorithm has been interrupted by abort().
     //
     // If the sequence appendBuffer(), abort(), appendBuffer() occurs before
     // the first StopUpdating() runnable runs, then a second StopUpdating()
     // runnable will be scheduled, but still only one (the first) will queue
     // events.
     return;
   }
 
   MOZ_ASSERT(mMediaSource);
+  MOZ_ASSERT(!mPendingAppend.Exists());
 
   if (!aData->Length()) {
     StopUpdating();
     return;
   }
 
-  mTrackBuffer->AppendData(aData, aTimestampOffset * USECS_PER_S)
-                    ->Then(NS_GetCurrentThread(), __func__, this,
-                           &SourceBuffer::AppendDataCompletedWithSuccess,
-                           &SourceBuffer::AppendDataErrored);
+  mPendingAppend.Begin(mTrackBuffer->AppendData(aData, aTimestampOffset * USECS_PER_S)
+                       ->RefableThen(NS_GetCurrentThread(), __func__, this,
+                                     &SourceBuffer::AppendDataCompletedWithSuccess,
+                                     &SourceBuffer::AppendDataErrored));
 }
 
 void
 SourceBuffer::AppendDataCompletedWithSuccess(bool aGotMedia)
 {
+  mPendingAppend.Complete();
   if (!mUpdating) {
     // The buffer append algorithm has been interrupted by abort().
     return;
   }
 
   if (mTrackBuffer->HasInitSegment()) {
     mMediaSource->QueueInitializationEvent();
   }
@@ -471,20 +480,21 @@ SourceBuffer::AppendDataCompletedWithSuc
   }
 
   StopUpdating();
 }
 
 void
 SourceBuffer::AppendDataErrored(nsresult aError)
 {
+  mPendingAppend.Complete();
   switch (aError) {
     case NS_ERROR_ABORT:
-      // Nothing further to do as the handling of the events is being done
-      // by Abort().
+      // Nothing further to do as the trackbuffer has been shutdown.
+      // or append was aborted and abort() has handled all the events.
       break;
     default:
       AppendError(true);
       break;
   }
 }
 
 void
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SourceBuffer_h_
 #define mozilla_dom_SourceBuffer_h_
 
+#include "MediaPromise.h"
 #include "MediaSource.h"
 #include "js/RootingAPI.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/SourceBufferBinding.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/mozalloc.h"
@@ -27,16 +28,17 @@ class JSObject;
 struct JSContext;
 
 namespace mozilla {
 
 class ErrorResult;
 class LargeDataBuffer;
 class TrackBuffer;
 template <typename T> class AsyncEventRunner;
+typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> TrackBufferAppendPromise;
 
 namespace dom {
 
 class TimeRanges;
 
 class SourceBuffer MOZ_FINAL : public DOMEventTargetHelper
 {
 public:
@@ -75,17 +77,17 @@ public:
   }
 
   void SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv);
 
   void AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv);
   void AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv);
 
   void Abort(ErrorResult& aRv);
-  void Abort();
+  void AbortBufferAppend();
 
   void Remove(double aStart, double aEnd, ErrorResult& aRv);
   /** End WebIDL Methods. */
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBuffer, DOMEventTargetHelper)
 
   SourceBuffer(MediaSource* aMediaSource, const nsACString& aType);
@@ -134,17 +136,18 @@ private:
 
   // If the media segment contains data beyond the current duration,
   // then run the duration change algorithm with new duration set to the
   // maximum of the current duration and the group end timestamp.
   void CheckEndTime();
 
   // Shared implementation of AppendBuffer overloads.
   void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
-  void AppendData(LargeDataBuffer* aData, double aTimestampOffset);
+  void AppendData(LargeDataBuffer* aData, double aTimestampOffset,
+                  uint32_t aAppendID);
 
   // Implement the "Append Error Algorithm".
   // Will call endOfStream() with "decode" error if aDecodeError is true.
   // 3.5.3 Append Error Algorithm
   // http://w3c.github.io/media-source/#sourcebuffer-append-error
   void AppendError(bool aDecoderError);
 
   // Implements the "Prepare Append Algorithm". Returns LargeDataBuffer object
@@ -164,14 +167,21 @@ private:
 
   double mAppendWindowStart;
   double mAppendWindowEnd;
 
   double mTimestampOffset;
 
   SourceBufferAppendMode mAppendMode;
   bool mUpdating;
+
+  // Each time mUpdating is set to true, mUpdateID will be incremented.
+  // This allows for a queued AppendData task to identify if it was earlier
+  // aborted and another AppendData queued.
+  uint32_t mUpdateID;
+
+  MediaPromiseConsumerHolder<TrackBufferAppendPromise> mPendingAppend;
 };
 
 } // namespace dom
 
 } // namespace mozilla
 #endif /* mozilla_dom_SourceBuffer_h_ */
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -117,16 +117,17 @@ private:
   nsAutoTArray<nsRefPtr<SourceBufferDecoder>,1> mDecoders;
 };
 
 nsRefPtr<ShutdownPromise>
 TrackBuffer::Shutdown()
 {
   mParentDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mShutdown = true;
+  mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
 
   MOZ_ASSERT(mShutdownPromise.IsEmpty());
   nsRefPtr<ShutdownPromise> p = mShutdownPromise.Ensure(__func__);
 
   RefPtr<MediaTaskQueue> queue = mTaskQueue;
   mTaskQueue = nullptr;
   queue->BeginShutdown()
        ->Then(mParentDecoder->GetReader()->GetTaskQueue(), __func__, this,
@@ -143,28 +144,31 @@ TrackBuffer::ContinueShutdown()
     mDecoders[0]->GetReader()->Shutdown()
                 ->Then(mParentDecoder->GetReader()->GetTaskQueue(), __func__, this,
                        &TrackBuffer::ContinueShutdown, &TrackBuffer::ContinueShutdown);
     mShutdownDecoders.AppendElement(mDecoders[0]);
     mDecoders.RemoveElementAt(0);
     return;
   }
 
+  mCurrentDecoder = nullptr;
   mInitializedDecoders.Clear();
   mParentDecoder = nullptr;
 
   mShutdownPromise.Resolve(true, __func__);
 }
 
-nsRefPtr<TrackBuffer::InitializationPromise>
+nsRefPtr<TrackBufferAppendPromise>
 TrackBuffer::AppendData(LargeDataBuffer* aData, int64_t aTimestampOffset)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInitializationPromise.IsEmpty());
+
   DecodersToInitialize decoders(this);
-  nsRefPtr<InitializationPromise> p = mInitializationPromise.Ensure(__func__);
+  nsRefPtr<TrackBufferAppendPromise> p = mInitializationPromise.Ensure(__func__);
   bool hadInitData = mParser->HasInitData();
   bool hadCompleteInitData = mParser->HasCompleteInitData();
   nsRefPtr<LargeDataBuffer> oldInit = mParser->InitData();
   bool newInitData = mParser->IsInitSegmentPresent(aData);
 
   // TODO: Run more of the buffer append algorithm asynchronously.
   if (newInitData) {
     MSE_DEBUG("TrackBuffer(%p)::AppendData: New initialization segment.", this);
@@ -434,17 +438,17 @@ TrackBuffer::Buffered(dom::TimeRanges* a
 }
 
 already_AddRefed<SourceBufferDecoder>
 TrackBuffer::NewDecoder(int64_t aTimestampOffset)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mParentDecoder);
 
-  DiscardDecoder();
+  DiscardCurrentDecoder();
 
   nsRefPtr<SourceBufferDecoder> decoder = mParentDecoder->CreateSubDecoder(mType, aTimestampOffset);
   if (!decoder) {
     return nullptr;
   }
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   mCurrentDecoder = decoder;
   mDecoders.AppendElement(decoder);
@@ -483,23 +487,31 @@ TrackBuffer::InitializeDecoder(SourceBuf
 {
   // ReadMetadata may block the thread waiting on data, so we must be able
   // to leave the monitor while we call it. For the rest of this function
   // we want to hold the monitor though, since we run on a different task queue
   // from the reader and interact heavily with it.
   mParentDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
 
+  if (mCurrentDecoder != aDecoder) {
+    MSE_DEBUG("TrackBuffer(%p) append was cancelled. Aborting initialization.",
+              this);
+    // If we reached this point, the SourceBuffer would have disconnected
+    // the promise. So no need to reject it.
+    return;
+  }
+
   // We may be shut down at any time by the reader on another thread. So we need
   // to check for this each time we acquire the monitor. If that happens, we
   // need to abort immediately, because the reader has forgotten about us, and
   // important pieces of our state (like mTaskQueue) have also been torn down.
   if (mShutdown) {
     MSE_DEBUG("TrackBuffer(%p) was shut down. Aborting initialization.", this);
-    mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
+    RemoveDecoder(aDecoder);
     return;
   }
 
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   MediaDecoderReader* reader = aDecoder->GetReader();
   MSE_DEBUG("TrackBuffer(%p): Initializing subdecoder %p reader %p",
             this, aDecoder, reader);
 
@@ -527,17 +539,16 @@ TrackBuffer::InitializeDecoder(SourceBuf
     nsRefPtr<LargeDataBuffer> emptyBuffer = new LargeDataBuffer;
     aDecoder->GetResource()->AppendData(emptyBuffer);
   }
   // HACK END.
 
   reader->SetIdle();
   if (mShutdown) {
     MSE_DEBUG("TrackBuffer(%p) was shut down while reading metadata. Aborting initialization.", this);
-    mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
     return;
   }
 
   if (NS_SUCCEEDED(rv) && reader->IsWaitingOnCDMResource()) {
     mWaitingDecoders.AppendElement(aDecoder);
     return;
   }
 
@@ -572,20 +583,27 @@ TrackBuffer::InitializeDecoder(SourceBuf
     return;
   }
 }
 
 void
 TrackBuffer::CompleteInitializeDecoder(SourceBufferDecoder* aDecoder)
 {
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
+  if (mCurrentDecoder != aDecoder) {
+    MSE_DEBUG("TrackBuffer(%p) append was cancelled. Aborting initialization.",
+              this);
+    // If we reached this point, the SourceBuffer would have disconnected
+    // the promise. So no need to reject it.
+    return;
+  }
+
   if (mShutdown) {
-    MSE_DEBUG("TrackBuffer(%p) was shut down while reading metadata. Aborting initialization.", this);
+    MSE_DEBUG("TrackBuffer(%p) was shut down. Aborting initialization.", this);
     RemoveDecoder(aDecoder);
-    mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
     return;
   }
 
   if (!RegisterDecoder(aDecoder)) {
     MSE_DEBUG("TrackBuffer(%p): Reader %p not activated",
               this, aDecoder->GetReader());
     RemoveDecoder(aDecoder);
     mInitializationPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
@@ -643,22 +661,20 @@ TrackBuffer::RegisterDecoder(SourceBuffe
     return false;
   }
   mInitializedDecoders.AppendElement(aDecoder);
   mParentDecoder->NotifyTimeRangesChanged();
   return true;
 }
 
 void
-TrackBuffer::DiscardDecoder()
+TrackBuffer::DiscardCurrentDecoder()
 {
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
-  if (mCurrentDecoder) {
-    mCurrentDecoder->GetResource()->Ended();
-  }
+  EndCurrentDecoder();
   mCurrentDecoder = nullptr;
 }
 
 void
 TrackBuffer::EndCurrentDecoder()
 {
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   if (mCurrentDecoder) {
@@ -666,20 +682,18 @@ TrackBuffer::EndCurrentDecoder()
   }
 }
 
 void
 TrackBuffer::Detach()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mCurrentDecoder) {
-    DiscardDecoder();
+    DiscardCurrentDecoder();
   }
-  // Cancel the promise should the current decoder hadn't be initialized yet.
-  mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
 }
 
 bool
 TrackBuffer::HasInitSegment()
 {
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   return mParser->HasCompleteInitData();
 }
@@ -736,23 +750,27 @@ void
 TrackBuffer::ResetParserState()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mParser->HasInitData() && !mParser->HasCompleteInitData()) {
     // We have an incomplete init segment pending. reset current parser and
     // discard the current decoder.
     mParser = ContainerParser::CreateForMIMEType(mType);
-    DiscardDecoder();
+    DiscardCurrentDecoder();
   }
 }
 
 void
-TrackBuffer::Abort()
+TrackBuffer::AbortAppendData()
 {
+  DiscardCurrentDecoder();
+  // The SourceBuffer would have disconnected its promise.
+  // However we must ensure that the MediaPromiseHolder handle all pending
+  // promises.
   mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
 }
 
 const nsTArray<nsRefPtr<SourceBufferDecoder>>&
 TrackBuffer::Decoders()
 {
   // XXX assert OnDecodeThread
   return mInitializedDecoders;
@@ -834,17 +852,17 @@ TrackBuffer::RemoveDecoder(SourceBufferD
     ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
     // There should be no other references to the decoder. Assert that
     // we aren't using it in the MediaSourceReader.
     MOZ_ASSERT(!mParentDecoder->IsActiveReader(aDecoder->GetReader()));
     mInitializedDecoders.RemoveElement(aDecoder);
     mDecoders.RemoveElement(aDecoder);
 
     if (mCurrentDecoder == aDecoder) {
-      DiscardDecoder();
+      DiscardCurrentDecoder();
     }
   }
   aDecoder->GetReader()->GetTaskQueue()->Dispatch(task);
 }
 
 bool
 TrackBuffer::RangeRemoval(int64_t aStart, int64_t aEnd)
 {
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -2,18 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_TRACKBUFFER_H_
 #define MOZILLA_TRACKBUFFER_H_
 
+#include "SourceBuffer.h"
 #include "SourceBufferDecoder.h"
-#include "MediaPromise.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Maybe.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nscore.h"
 
@@ -28,27 +28,25 @@ namespace dom {
 class TimeRanges;
 
 } // namespace dom
 
 class TrackBuffer MOZ_FINAL {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffer);
 
-  typedef MediaPromise<bool, nsresult, /* IsExclusive = */ false> InitializationPromise;
-
   TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& aType);
 
   nsRefPtr<ShutdownPromise> Shutdown();
 
   // Append data to the current decoder.  Also responsible for calling
   // NotifyDataArrived on the decoder to keep buffered range computation up
   // to date.  Returns false if the append failed.
-  nsRefPtr<InitializationPromise> AppendData(LargeDataBuffer* aData,
-                                             int64_t aTimestampOffset /* microseconds */);
+  nsRefPtr<TrackBufferAppendPromise> AppendData(LargeDataBuffer* aData,
+                                                int64_t aTimestampOffset /* microseconds */);
 
   // Evicts data held in the current decoders SourceBufferResource from the
   // start of the buffer through to aPlaybackTime. aThreshold is used to
   // bound the data being evicted. It will not evict more than aThreshold
   // bytes. aBufferStartTime contains the new start time of the current
   // decoders buffered data after the eviction. Returns true if data was
   // evicted.
   bool EvictData(double aPlaybackTime, uint32_t aThreshold, double* aBufferStartTime);
@@ -59,17 +57,17 @@ public:
 
   // Returns the highest end time of all of the buffered ranges in the
   // decoders managed by this TrackBuffer, and returns the union of the
   // decoders buffered ranges in aRanges. This may be called on any thread.
   double Buffered(dom::TimeRanges* aRanges);
 
   // Mark the current decoder's resource as ended, clear mCurrentDecoder and
   // reset mLast{Start,End}Timestamp.
-  void DiscardDecoder();
+  void DiscardCurrentDecoder();
   // Mark the current decoder's resource as ended.
   void EndCurrentDecoder();
 
   void Detach();
 
   // Returns true if an init segment has been appended.
   bool HasInitSegment();
 
@@ -99,17 +97,17 @@ public:
   // Runs MSE range removal algorithm.
   // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
   // Implementation is only partial, we can only trim a buffer.
   // Returns true if data was evicted.
   // Times are in microseconds.
   bool RangeRemoval(int64_t aStart, int64_t aEnd);
 
   // Abort any pending appendBuffer by rejecting any pending promises.
-  void Abort();
+  void AbortAppendData();
 
 #ifdef MOZ_EME
   nsresult SetCDMProxy(CDMProxy* aProxy);
 #endif
 
 #if defined(DEBUG)
   void Dump(const char* aPath);
 #endif
@@ -200,14 +198,14 @@ private:
   // Protected by mParentDecoder's monitor.
   MediaInfo mInfo;
 
   void ContinueShutdown();
   MediaPromiseHolder<ShutdownPromise> mShutdownPromise;
   bool mDecoderPerSegment;
   bool mShutdown;
 
-  MediaPromiseHolder<InitializationPromise> mInitializationPromise;
+  MediaPromiseHolder<TrackBufferAppendPromise> mInitializationPromise;
 
 };
 
 } // namespace mozilla
 #endif /* MOZILLA_TRACKBUFFER_H_ */