Backed out changesets ae63e2dda6e0, a9ca0113db3c, and d0a6757e24bd (bug 1097823) for bustage.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 08 Dec 2014 15:00:02 -0500
changeset 218735 09ca5cf1876ff10d25546da446c68101d36ef3ce
parent 218734 ae63e2dda6e095f8220aec861300d4626eef0b34
child 218736 f1f48ccb2d4e2ca9226c01fe31a271ebdd8b64a0
child 218745 dad75f61e5d132ab4fbe25fb4ca62acf85e958d4
push id27942
push userryanvm@gmail.com
push dateMon, 08 Dec 2014 20:46:16 +0000
treeherdermozilla-central@f1f48ccb2d4e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1097823
milestone37.0a1
backs outae63e2dda6e095f8220aec861300d4626eef0b34
a9ca0113db3c74d8a134077bb1d524e3ed070e2e
d0a6757e24bdcf9f4eeb9d185b020741b25c29a9
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
Backed out changesets ae63e2dda6e0, a9ca0113db3c, and d0a6757e24bd (bug 1097823) for bustage. DONTBUILD CLOSED TREE
dom/media/MediaDataDecodedListener.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderReader.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/MediaPromise.h
dom/media/MediaTaskQueue.cpp
dom/media/MediaTaskQueue.h
dom/media/mediasource/MediaSourceReader.cpp
dom/media/mediasource/MediaSourceReader.h
dom/media/moz.build
dom/media/omx/MediaCodecReader.cpp
dom/media/webm/WebMReader.cpp
--- a/dom/media/MediaDataDecodedListener.h
+++ b/dom/media/MediaDataDecodedListener.h
@@ -15,16 +15,18 @@ namespace mozilla {
 class MediaDecoderStateMachine;
 class MediaData;
 
 // A RequestSampleCallback implementation that forwards samples onto the
 // MediaDecoderStateMachine via tasks that run on the supplied task queue.
 template<class Target>
 class MediaDataDecodedListener : public RequestSampleCallback {
 public:
+  using RequestSampleCallback::NotDecodedReason;
+
   MediaDataDecodedListener(Target* aTarget,
                            MediaTaskQueue* aTaskQueue)
     : mMonitor("MediaDataDecodedListener")
     , mTaskQueue(aTaskQueue)
     , mTarget(aTarget)
   {
     MOZ_ASSERT(aTarget);
     MOZ_ASSERT(aTaskQueue);
@@ -45,18 +47,17 @@ public:
     if (!mTarget || !mTaskQueue) {
       // We've been shutdown, abort.
       return;
     }
     RefPtr<nsIRunnable> task(new DeliverVideoTask(aSample, mTarget));
     mTaskQueue->Dispatch(task);
   }
 
-  virtual void OnNotDecoded(MediaData::Type aType,
-                            MediaDecoderReader::NotDecodedReason aReason) MOZ_OVERRIDE {
+  virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) MOZ_OVERRIDE {
     MonitorAutoLock lock(mMonitor);
     if (!mTarget || !mTaskQueue) {
       // We've been shutdown, abort.
       return;
     }
     RefPtr<nsIRunnable> task(new DeliverNotDecodedTask(aType, aReason, mTarget));
     mTaskQueue->Dispatch(task);
   }
@@ -127,17 +128,17 @@ private:
   private:
     nsRefPtr<VideoData> mSample;
     RefPtr<Target> mTarget;
   };
 
   class DeliverNotDecodedTask : public nsRunnable {
   public:
     DeliverNotDecodedTask(MediaData::Type aType,
-                          MediaDecoderReader::NotDecodedReason aReason,
+                          RequestSampleCallback::NotDecodedReason aReason,
                           Target* aTarget)
       : mType(aType)
       , mReason(aReason)
       , mTarget(aTarget)
     {
       MOZ_COUNT_CTOR(DeliverNotDecodedTask);
     }
   protected:
@@ -147,17 +148,17 @@ private:
     }
   public:
     NS_METHOD Run() {
       mTarget->OnNotDecoded(mType, mReason);
       return NS_OK;
     }
   private:
     MediaData::Type mType;
-    MediaDecoderReader::NotDecodedReason mReason;
+    RequestSampleCallback::NotDecodedReason mReason;
     RefPtr<Target> mTarget;
   };
 
   Monitor mMonitor;
   RefPtr<MediaTaskQueue> mTaskQueue;
   RefPtr<Target> mTarget;
 };
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -456,16 +456,17 @@ MediaDecoder::MediaDecoder() :
   MOZ_COUNT_CTOR(MediaDecoder);
   MOZ_ASSERT(NS_IsMainThread());
   MediaMemoryTracker::AddMediaDecoder(this);
 #ifdef PR_LOGGING
   if (!gMediaDecoderLog) {
     gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
   }
 #endif
+
   mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
 }
 
 bool MediaDecoder::Init(MediaDecoderOwner* aOwner)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mOwner = aOwner;
   mVideoFrameContainer = aOwner->GetVideoFrameContainer();
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -22,26 +22,16 @@ namespace mozilla {
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gMediaDecoderLog;
 #define DECODER_LOG(x, ...) \
   PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, ("Decoder=%p " x, mDecoder, ##__VA_ARGS__))
 #else
 #define DECODER_LOG(x, ...)
 #endif
 
-PRLogModuleInfo* gMediaPromiseLog;
-
-void
-EnsureMediaPromiseLog()
-{
-  if (!gMediaPromiseLog) {
-    gMediaPromiseLog = PR_NewLogModule("MediaPromise");
-  }
-}
-
 class VideoQueueMemoryFunctor : public nsDequeFunctor {
 public:
   VideoQueueMemoryFunctor() : mSize(0) {}
 
   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
 
   virtual void* operator()(void* aObject) {
     const VideoData* v = static_cast<const VideoData*>(aObject);
@@ -74,17 +64,16 @@ MediaDecoderReader::MediaDecoderReader(A
   , mIgnoreAudioOutputFormat(false)
   , mStartTime(-1)
   , mTaskQueueIsBorrowed(false)
   , mAudioDiscontinuity(false)
   , mVideoDiscontinuity(false)
   , mShutdown(false)
 {
   MOZ_COUNT_CTOR(MediaDecoderReader);
-  EnsureMediaPromiseLog();
 }
 
 MediaDecoderReader::~MediaDecoderReader()
 {
   MOZ_ASSERT(mShutdown);
   ResetDecode();
   MOZ_COUNT_DTOR(MediaDecoderReader);
 }
@@ -210,17 +199,17 @@ MediaDecoderReader::RequestVideoData(boo
   if (VideoQueue().GetSize() > 0) {
     nsRefPtr<VideoData> v = VideoQueue().PopFront();
     if (v && mVideoDiscontinuity) {
       v->mDiscontinuity = true;
       mVideoDiscontinuity = false;
     }
     GetCallback()->OnVideoDecoded(v);
   } else if (VideoQueue().IsFinished()) {
-    GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, END_OF_STREAM);
+    GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::END_OF_STREAM);
   }
 }
 
 void
 MediaDecoderReader::RequestAudioData()
 {
   while (AudioQueue().GetSize() == 0 &&
          !AudioQueue().IsFinished()) {
@@ -243,17 +232,17 @@ MediaDecoderReader::RequestAudioData()
     nsRefPtr<AudioData> a = AudioQueue().PopFront();
     if (mAudioDiscontinuity) {
       a->mDiscontinuity = true;
       mAudioDiscontinuity = false;
     }
     GetCallback()->OnAudioDecoded(a);
     return;
   } else if (AudioQueue().IsFinished()) {
-    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, END_OF_STREAM);
+    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::END_OF_STREAM);
     return;
   }
 }
 
 void
 MediaDecoderReader::SetCallback(RequestSampleCallback* aCallback)
 {
   mSampleDecodedCallback = aCallback;
@@ -313,23 +302,22 @@ AudioDecodeRendezvous::OnAudioDecoded(Au
   MonitorAutoLock mon(mMonitor);
   mSample = aSample;
   mStatus = NS_OK;
   mHaveResult = true;
   mon.NotifyAll();
 }
 
 void
-AudioDecodeRendezvous::OnNotDecoded(MediaData::Type aType,
-                                    MediaDecoderReader::NotDecodedReason aReason)
+AudioDecodeRendezvous::OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason)
 {
   MOZ_ASSERT(aType == MediaData::AUDIO_DATA);
   MonitorAutoLock mon(mMonitor);
   mSample = nullptr;
-  mStatus = aReason == MediaDecoderReader::DECODE_ERROR ? NS_ERROR_FAILURE : NS_OK;
+  mStatus = aReason == DECODE_ERROR ? NS_ERROR_FAILURE : NS_OK;
   mHaveResult = true;
   mon.NotifyAll();
 }
 
 void
 AudioDecodeRendezvous::Reset()
 {
   MonitorAutoLock mon(mMonitor);
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -25,23 +25,16 @@ class SharedDecoderManager;
 // Encapsulates the decoding and reading of media data. Reading can either
 // synchronous and done on the calling "decode" thread, or asynchronous and
 // performed on a background thread, with the result being returned by
 // callback. Never hold the decoder monitor when calling into this class.
 // Unless otherwise specified, methods and fields of this class can only
 // be accessed on the decode task queue.
 class MediaDecoderReader {
 public:
-  enum NotDecodedReason {
-    END_OF_STREAM,
-    DECODE_ERROR,
-    WAITING_FOR_DATA,
-    CANCELED
-  };
-
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
 
   explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder);
 
   // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
   // on failure.
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0;
 
@@ -292,51 +285,58 @@ private:
 // Interface that callers to MediaDecoderReader::Request{Audio,Video}Data()
 // must implement to receive the requested samples asynchronously.
 // This object is refcounted, and cycles must be broken by calling
 // BreakCycles() during shutdown.
 class RequestSampleCallback {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RequestSampleCallback)
 
+  enum NotDecodedReason {
+    END_OF_STREAM,
+    DECODE_ERROR,
+    WAITING_FOR_DATA,
+    CANCELED
+  };
+
   // Receives the result of a RequestAudioData() call.
   virtual void OnAudioDecoded(AudioData* aSample) = 0;
 
   // Receives the result of a RequestVideoData() call.
   virtual void OnVideoDecoded(VideoData* aSample) = 0;
 
   // Called when a RequestAudioData() or RequestVideoData() call can't be
   // fulfiled. The reason is passed as aReason.
-  virtual void OnNotDecoded(MediaData::Type aType,
-                            MediaDecoderReader::NotDecodedReason aReason) = 0;
+  virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) = 0;
 
   virtual void OnSeekCompleted(nsresult aResult) = 0;
 
   // Called during shutdown to break any reference cycles.
   virtual void BreakCycles() = 0;
 
 protected:
   virtual ~RequestSampleCallback() {}
 };
 
 // A RequestSampleCallback implementation that can be passed to the
 // MediaDecoderReader to block the thread requesting an audio sample until
 // the audio decode is complete. This is used to adapt the asynchronous
 // model of the MediaDecoderReader to a synchronous model.
 class AudioDecodeRendezvous : public RequestSampleCallback {
 public:
+  using RequestSampleCallback::NotDecodedReason;
+
   AudioDecodeRendezvous();
   ~AudioDecodeRendezvous();
 
   // RequestSampleCallback implementation. Called when decode is complete.
   // Note: aSample is null at end of stream.
   virtual void OnAudioDecoded(AudioData* aSample) MOZ_OVERRIDE;
   virtual void OnVideoDecoded(VideoData* aSample) MOZ_OVERRIDE {}
-  virtual void OnNotDecoded(MediaData::Type aType,
-                            MediaDecoderReader::NotDecodedReason aReason) MOZ_OVERRIDE;
+  virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) MOZ_OVERRIDE;
   virtual void OnSeekCompleted(nsresult aResult) MOZ_OVERRIDE {};
   virtual void BreakCycles() MOZ_OVERRIDE {};
   void Reset();
 
   // Returns failure on error, or NS_OK.
   // If *aSample is null, EOS has been reached.
   nsresult Await(nsRefPtr<AudioData>& aSample);
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -800,56 +800,56 @@ MediaDecoderStateMachine::Push(VideoData
     UpdateReadyState();
     DispatchDecodeTasksIfNeeded();
     mDecoder->GetReentrantMonitor().NotifyAll();
   }
 }
 
 void
 MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
-                                       MediaDecoderReader::NotDecodedReason aReason)
+                                       RequestSampleCallback::NotDecodedReason aReason)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   SAMPLE_LOG("OnNotDecoded (aType=%u, aReason=%u)", aType, aReason);
   bool isAudio = aType == MediaData::AUDIO_DATA;
   MOZ_ASSERT_IF(!isAudio, aType == MediaData::VIDEO_DATA);
 
   // This callback means that the pending request is dead.
   if (isAudio) {
     mAudioRequestPending = false;
   } else {
     mVideoRequestPending = false;
   }
 
   // If this is a decode error, delegate to the generic error path.
-  if (aReason == MediaDecoderReader::DECODE_ERROR) {
+  if (aReason == RequestSampleCallback::DECODE_ERROR) {
     DecodeError();
     return;
   }
 
   // If the decoder is waiting for data, we need to make sure that the requests
   // are cleared, which happened above. Additionally, if we're out of decoded
   // samples, we need to switch to buffering mode.
-  if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
+  if (aReason == RequestSampleCallback::WAITING_FOR_DATA) {
     bool outOfSamples = isAudio ? !AudioQueue().GetSize() : !VideoQueue().GetSize();
     if (outOfSamples) {
       StartBuffering();
     }
 
     return;
   }
 
-  if (aReason == MediaDecoderReader::CANCELED) {
+  if (aReason == RequestSampleCallback::CANCELED) {
     DispatchDecodeTasksIfNeeded();
     return;
   }
 
   // This is an EOS. Finish off the queue, and then handle things based on our
   // state.
-  MOZ_ASSERT(aReason == MediaDecoderReader::END_OF_STREAM);
+  MOZ_ASSERT(aReason == RequestSampleCallback::END_OF_STREAM);
   if (!isAudio && mState == DECODER_STATE_SEEKING &&
       mCurrentSeekTarget.IsValid() && mFirstVideoFrameAfterSeek) {
     // Null sample. Hit end of stream. If we have decoded a frame,
     // insert it into the queue so that we have something to display.
     // We make sure to do this before invoking VideoQueue().Finish()
     // below.
     VideoQueue().Push(mFirstVideoFrameAfterSeek);
     mFirstVideoFrameAfterSeek = nullptr;
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -368,17 +368,17 @@ public:
   // decoded we preroll, until playback starts. The first time playback starts
   // the state machine is free to return to prerolling normally. Note
   // "prerolling" in this context refers to when we decode and buffer decoded
   // samples in advance of when they're needed for playback.
   void SetMinimizePrerollUntilPlaybackStarts();
 
   void OnAudioDecoded(AudioData* aSample);
   void OnVideoDecoded(VideoData* aSample);
-  void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
+  void OnNotDecoded(MediaData::Type aType, RequestSampleCallback::NotDecodedReason aReason);
   void OnSeekCompleted(nsresult aResult);
 
 private:
   void AcquireMonitorAndInvokeDecodeError();
 
 protected:
   virtual ~MediaDecoderStateMachine();
 
deleted file mode 100644
--- a/dom/media/MediaPromise.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#if !defined(MediaPromise_h_)
-#define MediaPromise_h_
-
-#include "prlog.h"
-
-#include "mozilla/DebugOnly.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/Monitor.h"
-
-#include "MediaTaskQueue.h"
-#include "nsIEventTarget.h"
-
-/* Polyfill __func__ on MSVC for consumers to pass to the MediaPromise API. */
-#ifdef _MSC_VER
-#define __func__ __FUNCTION__
-#endif
-
-namespace mozilla {
-
-extern PRLogModuleInfo* gMediaPromiseLog;
-void EnsureMediaPromiseLog();
-
-#define PROMISE_LOG(x, ...) \
-  MOZ_ASSERT(gMediaPromiseLog); \
-  PR_LOG(gMediaPromiseLog, PR_LOG_DEBUG, (x, ##__VA_ARGS__))
-
-/*
- * A promise manages an asynchronous request that may or may not be able to be
- * fulfilled immediately. When an API returns a promise, the consumer may attach
- * callbacks to be invoked (asynchronously, on a specified thread) when the
- * request is either completed (resolved) or cannot be completed (rejected).
- *
- * By default, resolve and reject callbacks are always invoked on the same thread
- * where Then() was invoked.
- */
-template<typename T> class MediaPromiseHolder;
-template<typename ResolveValueT, typename RejectValueT>
-class MediaPromise
-{
-public:
-  typedef ResolveValueT ResolveValueType;
-  typedef RejectValueT RejectValueType;
-
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPromise)
-  MediaPromise(const char* aCreationSite)
-    : mCreationSite(aCreationSite)
-    , mMutex("MediaPromise Mutex")
-  {
-    MOZ_COUNT_CTOR(MediaPromise);
-    PROMISE_LOG("%s creating MediaPromise (%p)", mCreationSite, this);
-  }
-
-protected:
-
-  /*
-   * A ThenValue tracks a single consumer waiting on the promise. When a consumer
-   * invokes promise->Then(...), a ThenValue is created. Once the Promise is
-   * resolved or rejected, a ThenValueRunnable is dispatched, which invokes the
-   * resolve/reject method and then deletes the ThenValue.
-   */
-  class ThenValueBase
-  {
-  public:
-    class ThenValueRunnable : public nsRunnable
-    {
-    public:
-      ThenValueRunnable(ThenValueBase* aThenValue, ResolveValueType aResolveValue)
-        : mThenValue(aThenValue)
-      {
-        MOZ_COUNT_CTOR(ThenValueRunnable);
-        mResolveValue.emplace(aResolveValue);
-      }
-
-      ThenValueRunnable(ThenValueBase* aThenValue, RejectValueType aRejectValue)
-        : mThenValue(aThenValue)
-      {
-        MOZ_COUNT_CTOR(ThenValueRunnable);
-        mRejectValue.emplace(aRejectValue);
-      }
-
-      ~ThenValueRunnable()
-      {
-        MOZ_COUNT_DTOR(ThenValueRunnable);
-        MOZ_ASSERT(!mThenValue);
-      }
-
-      NS_IMETHODIMP Run()
-      {
-        PROMISE_LOG("ThenValueRunnable::Run() [this=%p]", this);
-        if (mResolveValue.isSome()) {
-          mThenValue->DoResolve(mResolveValue.ref());
-        } else {
-          mThenValue->DoReject(mRejectValue.ref());
-        }
-
-        delete mThenValue;
-        mThenValue = nullptr;
-        return NS_OK;
-      }
-
-    private:
-      ThenValueBase* mThenValue;
-      Maybe<ResolveValueType> mResolveValue;
-      Maybe<RejectValueType> mRejectValue;
-    };
-
-    ThenValueBase(const char* aCallSite) : mCallSite(aCallSite)
-    {
-      MOZ_COUNT_CTOR(ThenValueBase);
-    }
-
-    virtual void Dispatch(MediaPromise *aPromise) = 0;
-
-  protected:
-    // This may only be deleted by ThenValueRunnable::Run.
-    virtual ~ThenValueBase() { MOZ_COUNT_DTOR(ThenValueBase); }
-
-    virtual void DoResolve(ResolveValueType aResolveValue) = 0;
-    virtual void DoReject(RejectValueType aRejectValue) = 0;
-
-    const char* mCallSite;
-  };
-
-  template<typename TargetType, typename ThisType,
-           typename ResolveMethodType, typename RejectMethodType>
-  class ThenValue : public ThenValueBase
-  {
-  public:
-    ThenValue(TargetType* aResponseTarget, ThisType* aThisVal,
-              ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
-              const char* aCallSite)
-      : ThenValueBase(aCallSite)
-      , mResponseTarget(aResponseTarget)
-      , mThisVal(aThisVal)
-      , mResolveMethod(aResolveMethod)
-      , mRejectMethod(aRejectMethod) {}
-
-    void Dispatch(MediaPromise *aPromise) MOZ_OVERRIDE
-    {
-      aPromise->mMutex.AssertCurrentThreadOwns();
-      MOZ_ASSERT(!aPromise->IsPending());
-      bool resolved = aPromise->mResolveValue.isSome();
-      nsRefPtr<nsRunnable> runnable =
-        resolved ? new (typename ThenValueBase::ThenValueRunnable)(this, aPromise->mResolveValue.ref())
-                 : new (typename ThenValueBase::ThenValueRunnable)(this, aPromise->mRejectValue.ref());
-      PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
-                  resolved ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
-                  runnable.get(), aPromise, this);
-      DebugOnly<nsresult> rv = DoDispatch(mResponseTarget, runnable);
-      MOZ_ASSERT(NS_SUCCEEDED(rv));
-    }
-
-  protected:
-    virtual void DoResolve(ResolveValueType aResolveValue)
-    {
-      ((*mThisVal).*mResolveMethod)(aResolveValue);
-    }
-
-    virtual void DoReject(RejectValueType aRejectValue)
-    {
-      ((*mThisVal).*mRejectMethod)(aRejectValue);
-    }
-
-    static nsresult DoDispatch(MediaTaskQueue* aTaskQueue, nsIRunnable* aRunnable)
-    {
-      return aTaskQueue->ForceDispatch(aRunnable);
-    }
-
-    static nsresult DoDispatch(nsIEventTarget* aEventTarget, nsIRunnable* aRunnable)
-    {
-      return aEventTarget->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
-    }
-
-    virtual ~ThenValue() {}
-
-  private:
-    nsRefPtr<TargetType> mResponseTarget;
-    nsRefPtr<ThisType> mThisVal;
-    ResolveMethodType mResolveMethod;
-    RejectMethodType mRejectMethod;
-  };
-public:
-
-  template<typename TargetType, typename ThisType,
-           typename ResolveMethodType, typename RejectMethodType>
-  void Then(TargetType* aResponseTarget, ThisType* aThisVal,
-            ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
-            const char* aCallSite)
-  {
-    MutexAutoLock lock(mMutex);
-    ThenValueBase* thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
-                                             RejectMethodType>(aResponseTarget, aThisVal,
-                                                               aResolveMethod, aRejectMethod,
-                                                               aCallSite);
-    PROMISE_LOG("%s invoking Then() [this=%p, thenValue=%p, aThisVal=%p, isPending=%d]",
-                aCallSite, this, thenValue, aThisVal, (int) IsPending());
-    if (!IsPending()) {
-      thenValue->Dispatch(this);
-    } else {
-      mThenValues.AppendElement(thenValue);
-    }
-  }
-
-private:
-  // Resolve and Reject may only be invoked via MediaPromiseHolder.
-  friend class MediaPromiseHolder<MediaPromise<ResolveValueType, RejectValueType>>;
-  void Resolve(ResolveValueType aResolveValue, const char* aResolveSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
-    PROMISE_LOG("%s resolving MediaPromise (%p created at %s)", aResolveSite, this, mCreationSite);
-    mResolveValue.emplace(aResolveValue);
-    DispatchAll();
-  }
-
-  void Reject(RejectValueType aRejectValue, const char* aRejectSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
-    PROMISE_LOG("%s rejecting MediaPromise (%p created at %s)", aRejectSite, this, mCreationSite);
-    mRejectValue.emplace(aRejectValue);
-    DispatchAll();
-  }
-
-protected:
-  bool IsPending() { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
-  void DispatchAll()
-  {
-    mMutex.AssertCurrentThreadOwns();
-    for (size_t i = 0; i < mThenValues.Length(); ++i)
-      mThenValues[i]->Dispatch(this);
-    mThenValues.Clear();
-  }
-
-  ~MediaPromise()
-  {
-    MOZ_COUNT_DTOR(MediaPromise);
-    PROMISE_LOG("MediaPromise::~MediaPromise [this=%p]", this);
-    MOZ_ASSERT(!IsPending());
-  };
-
-  const char* mCreationSite; // For logging
-  Mutex mMutex;
-  Maybe<ResolveValueType> mResolveValue;
-  Maybe<RejectValueType> mRejectValue;
-  nsTArray<ThenValueBase*> mThenValues;
-};
-
-/*
- * Class to encapsulate a promise for a particular role. Use this as the member
- * variable for a class whose method returns a promise.
- */
-template<typename PromiseType>
-class MediaPromiseHolder
-{
-public:
-  MediaPromiseHolder()
-    : mMonitor(nullptr) {}
-
-  ~MediaPromiseHolder() { MOZ_ASSERT(!mPromise); }
-
-  already_AddRefed<PromiseType> Ensure(const char* aMethodName) {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    if (!mPromise) {
-      mPromise = new PromiseType(aMethodName);
-    }
-    nsRefPtr<PromiseType> p = mPromise;
-    return p.forget();
-  }
-
-  // Provide a Monitor that should always be held when accessing this instance.
-  void SetMonitor(Monitor* aMonitor) { mMonitor = aMonitor; }
-
-  bool IsEmpty()
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    return !mPromise;
-  }
-
-  void Resolve(typename PromiseType::ResolveValueType aResolveValue,
-               const char* aMethodName)
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    MOZ_ASSERT(mPromise);
-    mPromise->Resolve(aResolveValue, aMethodName);
-    mPromise = nullptr;
-  }
-
-  void Reject(typename PromiseType::RejectValueType aRejectValue,
-              const char* aMethodName)
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    MOZ_ASSERT(mPromise);
-    mPromise->Reject(aRejectValue, aMethodName);
-    mPromise = nullptr;
-  }
-
-private:
-  Monitor* mMonitor;
-  nsRefPtr<PromiseType> mPromise;
-};
-
-#undef PROMISE_LOG
-
-} // namespace mozilla
-
-#endif
--- a/dom/media/MediaTaskQueue.cpp
+++ b/dom/media/MediaTaskQueue.cpp
@@ -30,34 +30,27 @@ MediaTaskQueue::~MediaTaskQueue()
 nsresult
 MediaTaskQueue::Dispatch(TemporaryRef<nsIRunnable> aRunnable)
 {
   MonitorAutoLock mon(mQueueMonitor);
   return DispatchLocked(aRunnable, AbortIfFlushing);
 }
 
 nsresult
-MediaTaskQueue::ForceDispatch(TemporaryRef<nsIRunnable> aRunnable)
-{
-  MonitorAutoLock mon(mQueueMonitor);
-  return DispatchLocked(aRunnable, Forced);
-}
-
-nsresult
 MediaTaskQueue::DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
                                DispatchMode aMode)
 {
   mQueueMonitor.AssertCurrentThreadOwns();
   if (mIsFlushing && aMode == AbortIfFlushing) {
     return NS_ERROR_ABORT;
   }
   if (mIsShutdown) {
     return NS_ERROR_FAILURE;
   }
-  mTasks.push(TaskQueueEntry(aRunnable, aMode == Forced));
+  mTasks.push(aRunnable);
   if (mIsRunning) {
     return NS_OK;
   }
   RefPtr<nsIRunnable> runner(new Runner(this));
   nsresult rv = mPool->Dispatch(runner, NS_DISPATCH_NORMAL);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to dispatch runnable to run MediaTaskQueue");
     return rv;
@@ -142,47 +135,34 @@ MediaTaskQueue::BeginShutdown()
   mon.NotifyAll();
 }
 
 nsresult
 MediaTaskQueue::FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable)
 {
   MonitorAutoLock mon(mQueueMonitor);
   AutoSetFlushing autoFlush(this);
-  FlushLocked();
+  while (!mTasks.empty()) {
+    mTasks.pop();
+  }
   nsresult rv = DispatchLocked(aRunnable, IgnoreFlushing);
   NS_ENSURE_SUCCESS(rv, rv);
   AwaitIdleLocked();
   return NS_OK;
 }
 
 void
 MediaTaskQueue::Flush()
 {
   MonitorAutoLock mon(mQueueMonitor);
   AutoSetFlushing autoFlush(this);
-  FlushLocked();
-  AwaitIdleLocked();
-}
-
-void
-MediaTaskQueue::FlushLocked()
-{
-  mQueueMonitor.AssertCurrentThreadOwns();
-  MOZ_ASSERT(mIsFlushing);
-
-  // Clear the tasks, but preserve those with mForceDispatch by re-appending
-  // them to the queue.
-  size_t numTasks = mTasks.size();
-  for (size_t i = 0; i < numTasks; ++i) {
-    if (mTasks.front().mForceDispatch) {
-      mTasks.push(mTasks.front());
-    }
+  while (!mTasks.empty()) {
     mTasks.pop();
   }
+  AwaitIdleLocked();
 }
 
 bool
 MediaTaskQueue::IsEmpty()
 {
   MonitorAutoLock mon(mQueueMonitor);
   return mTasks.empty();
 }
@@ -206,17 +186,17 @@ MediaTaskQueue::Runner::Run()
     MonitorAutoLock mon(mQueue->mQueueMonitor);
     MOZ_ASSERT(mQueue->mIsRunning);
     mQueue->mRunningThread = NS_GetCurrentThread();
     if (mQueue->mTasks.size() == 0) {
       mQueue->mIsRunning = false;
       mon.NotifyAll();
       return NS_OK;
     }
-    event = mQueue->mTasks.front().mRunnable;
+    event = mQueue->mTasks.front();
     mQueue->mTasks.pop();
   }
   MOZ_ASSERT(event);
 
   // Note that dropping the queue monitor before running the task, and
   // taking the monitor again after the task has run ensures we have memory
   // fences enforced. This means that if the object we're calling wasn't
   // designed to be threadsafe, it will be, provided we're only calling it
--- a/dom/media/MediaTaskQueue.h
+++ b/dom/media/MediaTaskQueue.h
@@ -29,20 +29,16 @@ class MediaTaskQueue MOZ_FINAL {
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTaskQueue)
 
   explicit MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool);
 
   nsresult Dispatch(TemporaryRef<nsIRunnable> aRunnable);
 
-  // This should only be used for things that absolutely can't afford to be
-  // flushed. Normal operations should use Dispatch.
-  nsresult ForceDispatch(TemporaryRef<nsIRunnable> aRunnable);
-
   nsresult SyncDispatch(TemporaryRef<nsIRunnable> aRunnable);
 
   nsresult FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable);
 
   // Removes all pending tasks from the task queue, and blocks until
   // the currently running task (if any) finishes.
   void Flush();
 
@@ -67,37 +63,28 @@ public:
 
 private:
 
   // Blocks until all task finish executing. Called internally by methods
   // that need to wait until the task queue is idle.
   // mQueueMonitor must be held.
   void AwaitIdleLocked();
 
-  enum DispatchMode { AbortIfFlushing, IgnoreFlushing, Forced };
+  enum DispatchMode { AbortIfFlushing, IgnoreFlushing };
 
   nsresult DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
                           DispatchMode aMode);
-  void FlushLocked();
 
   RefPtr<SharedThreadPool> mPool;
 
   // Monitor that protects the queue and mIsRunning;
   Monitor mQueueMonitor;
 
-  struct TaskQueueEntry {
-    RefPtr<nsIRunnable> mRunnable;
-    bool mForceDispatch;
-
-    TaskQueueEntry(TemporaryRef<nsIRunnable> aRunnable, bool aForceDispatch = false)
-      : mRunnable(aRunnable), mForceDispatch(aForceDispatch) {}
-  };
-
   // Queue of tasks to run.
-  std::queue<TaskQueueEntry> mTasks;
+  std::queue<RefPtr<nsIRunnable>> mTasks;
 
   // The thread currently running the task queue. We store a reference
   // to this so that IsCurrentThreadIn() can tell if the current thread
   // is the thread currently running in the task queue.
   RefPtr<nsIThread> mRunningThread;
 
   // True if we've dispatched an event to the pool to execute events from
   // the queue.
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -95,17 +95,17 @@ MediaSourceReader::IsWaitingMediaResourc
 }
 
 void
 MediaSourceReader::RequestAudioData()
 {
   MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData", this);
   if (!mAudioReader) {
     MSE_DEBUG("MediaSourceReader(%p)::RequestAudioData called with no audio reader", this);
-    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
+    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
     return;
   }
   mAudioIsSeeking = false;
   SwitchAudioReader(mLastAudioTime);
   mAudioReader->RequestAudioData();
 }
 
 void
@@ -134,17 +134,17 @@ MediaSourceReader::OnAudioDecoded(AudioD
 
 void
 MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold)
 {
   MSE_DEBUGV("MediaSourceReader(%p)::RequestVideoData(%d, %lld)",
              this, aSkipToNextKeyframe, aTimeThreshold);
   if (!mVideoReader) {
     MSE_DEBUG("MediaSourceReader(%p)::RequestVideoData called with no video reader", this);
-    GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, DECODE_ERROR);
+    GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::DECODE_ERROR);
     return;
   }
   if (aSkipToNextKeyframe) {
     mTimeThreshold = aTimeThreshold;
     mDropAudioBeforeThreshold = true;
     mDropVideoBeforeThreshold = true;
   }
   mVideoIsSeeking = false;
@@ -172,26 +172,27 @@ MediaSourceReader::OnVideoDecoded(VideoD
   // switching away from.
   if (!mVideoIsSeeking) {
     mLastVideoTime = aSample->mTime + aSample->mDuration;
   }
   GetCallback()->OnVideoDecoded(aSample);
 }
 
 void
-MediaSourceReader::OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason)
+MediaSourceReader::OnNotDecoded(MediaData::Type aType, RequestSampleCallback::NotDecodedReason aReason)
 {
   MSE_DEBUG("MediaSourceReader(%p)::OnNotDecoded aType=%u aReason=%u IsEnded: %d", this, aType, aReason, IsEnded());
-  if (aReason == DECODE_ERROR || aReason == CANCELED) {
+  if (aReason == RequestSampleCallback::DECODE_ERROR ||
+      aReason == RequestSampleCallback::CANCELED) {
     GetCallback()->OnNotDecoded(aType, aReason);
     return;
   }
   // End of stream. Force switching past this stream to another reader by
   // switching to the end of the buffered range.
-  MOZ_ASSERT(aReason == END_OF_STREAM);
+  MOZ_ASSERT(aReason == RequestSampleCallback::END_OF_STREAM);
   nsRefPtr<MediaDecoderReader> reader = aType == MediaData::AUDIO_DATA ?
                                           mAudioReader : mVideoReader;
 
   // Find the closest approximation to the end time for this stream.
   // mLast{Audio,Video}Time differs from the actual end time because of
   // Bug 1065207 - the duration of a WebM fragment is an estimate not the
   // actual duration. In the case of audio time an example of where they
   // differ would be the actual sample duration being small but the
@@ -222,23 +223,23 @@ MediaSourceReader::OnNotDecoded(MediaDat
   }
   if (aType == MediaData::VIDEO_DATA && SwitchVideoReader(*time + EOS_FUZZ_US)) {
     RequestVideoData(false, 0);
     return;
   }
 
   // If the entire MediaSource is done, generate an EndOfStream.
   if (IsEnded()) {
-    GetCallback()->OnNotDecoded(aType, END_OF_STREAM);
+    GetCallback()->OnNotDecoded(aType, RequestSampleCallback::END_OF_STREAM);
     return;
   }
 
   // We don't have the data the caller wants. Tell that we're waiting for JS to
   // give us more data.
-  GetCallback()->OnNotDecoded(aType, WAITING_FOR_DATA);
+  GetCallback()->OnNotDecoded(aType, RequestSampleCallback::WAITING_FOR_DATA);
 }
 
 void
 MediaSourceReader::Shutdown()
 {
   MediaDecoderReader::Shutdown();
   for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
     mTrackBuffers[i]->Shutdown();
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -49,17 +49,17 @@ public:
   void RequestAudioData() MOZ_OVERRIDE;
 
   void OnAudioDecoded(AudioData* aSample);
 
   void RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold) MOZ_OVERRIDE;
 
   void OnVideoDecoded(VideoData* aSample);
 
-  void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason);
+  void OnNotDecoded(MediaData::Type aType, RequestSampleCallback::NotDecodedReason aReason);
 
   void OnSeekCompleted(nsresult aResult);
 
   bool HasVideo() MOZ_OVERRIDE
   {
     return mInfo.HasVideo();
   }
 
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -100,17 +100,16 @@ EXPORTS += [
     'MediaData.h',
     'MediaDataDecodedListener.h',
     'MediaDecoder.h',
     'MediaDecoderOwner.h',
     'MediaDecoderReader.h',
     'MediaDecoderStateMachine.h',
     'MediaInfo.h',
     'MediaMetadataManager.h',
-    'MediaPromise.h',
     'MediaQueue.h',
     'MediaRecorder.h',
     'MediaResource.h',
     'MediaSegment.h',
     'MediaStreamGraph.h',
     'MediaTaskQueue.h',
     'MediaTrack.h',
     'MediaTrackList.h',
--- a/dom/media/omx/MediaCodecReader.cpp
+++ b/dom/media/omx/MediaCodecReader.cpp
@@ -483,17 +483,17 @@ MediaCodecReader::DecodeAudioDataTask()
       if (mAudioTrack.mDiscontinuity) {
         a->mDiscontinuity = true;
         mAudioTrack.mDiscontinuity = false;
       }
       GetCallback()->OnAudioDecoded(a);
     }
   }
   if (AudioQueue().AtEndOfStream()) {
-    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, END_OF_STREAM);
+    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::END_OF_STREAM);
   }
   return result;
 }
 
 bool
 MediaCodecReader::DecodeVideoFrameTask(int64_t aTimeThreshold)
 {
   bool result = DecodeVideoFrameSync(aTimeThreshold);
@@ -503,17 +503,17 @@ MediaCodecReader::DecodeVideoFrameTask(i
       if (mVideoTrack.mDiscontinuity) {
         v->mDiscontinuity = true;
         mVideoTrack.mDiscontinuity = false;
       }
       GetCallback()->OnVideoDecoded(v);
     }
   }
   if (VideoQueue().AtEndOfStream()) {
-    GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, END_OF_STREAM);
+    GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::END_OF_STREAM);
   }
   return result;
 }
 
 bool
 MediaCodecReader::HasAudio()
 {
   return mInfo.mAudio.mHasAudio;
--- a/dom/media/webm/WebMReader.cpp
+++ b/dom/media/webm/WebMReader.cpp
@@ -738,17 +738,17 @@ bool WebMReader::DecodeOpus(const unsign
   if (channels > 8) {
     return false;
   }
 
   if (mPaddingDiscarded) {
     // Discard padding should be used only on the final packet, so
     // decoding after a padding discard is invalid.
     LOG(PR_LOG_DEBUG, ("Opus error, discard padding on interstitial packet"));
-    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
+    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
     return false;
   }
 
   // Maximum value is 63*2880, so there's no chance of overflow.
   int32_t frames_number = opus_packet_get_nb_frames(aData, aLength);
   if (frames_number <= 0) {
     return false; // Invalid packet header.
   }
@@ -792,30 +792,30 @@ bool WebMReader::DecodeOpus(const unsign
     mSkip -= skipFrames;
   }
 
   int64_t discardPadding = 0;
   (void) nestegg_packet_discard_padding(aPacket, &discardPadding);
   if (discardPadding < 0) {
     // Negative discard padding is invalid.
     LOG(PR_LOG_DEBUG, ("Opus error, negative discard padding"));
-    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
+    GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
     return false;
   }
   if (discardPadding > 0) {
     CheckedInt64 discardFrames = UsecsToFrames(discardPadding / NS_PER_USEC,
                                                mInfo.mAudio.mRate);
     if (!discardFrames.isValid()) {
       NS_WARNING("Int overflow in DiscardPadding");
       return false;
     }
     if (discardFrames.value() > frames) {
       // Discarding more than the entire packet is invalid.
       LOG(PR_LOG_DEBUG, ("Opus error, discard padding larger than packet"));
-      GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
+      GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
       return false;
     }
     LOG(PR_LOG_DEBUG, ("Opus decoder discarding %d of %d frames",
                        int32_t(discardFrames.value()), frames));
     // Padding discard is only supposed to happen on the final packet.
     // Record the discard so we can return an error if another packet is
     // decoded.
     mPaddingDiscarded = true;