Bug 1125776: Part10. Handle concurrent aborts. r=mattwoodrow a=lmandel
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 04 Feb 2015 20:20:16 +1100
changeset 249841 bfb746be073770753b82b4a741377ceb1a18b248
parent 249840 378dac73d66dd37fc4bb794800ffff7ba46549f0
child 249842 d2675abc9228bf1a17d507f805eba01571dbed83
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)
reviewersmattwoodrow, lmandel
bugs1125776
milestone37.0a2
Bug 1125776: Part10. Handle concurrent aborts. r=mattwoodrow a=lmandel 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_ */