Bug 1214997 - Use MozPromise in MediaCodecProxy and OMXCodecProxy r=bwu
authorSotaro Ikeda <sotaro.ikeda.g@gmail.com>
Tue, 10 Nov 2015 05:42:42 -0800
changeset 272004 c0ccc4c5af5e108c24b6b81c4a24502efc4cac65
parent 272003 a675fc80caa9e744573d199d5d52cd84ab75ac7e
child 272005 d17561ee96dcdf1874202740352f9552843b5c68
push id29659
push usercbook@mozilla.com
push dateWed, 11 Nov 2015 11:43:09 +0000
treeherdermozilla-central@84a7cf29f4f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbwu
bugs1214997
milestone45.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 1214997 - Use MozPromise in MediaCodecProxy and OMXCodecProxy r=bwu
dom/media/omx/MediaCodecProxy.cpp
dom/media/omx/MediaCodecProxy.h
dom/media/omx/MediaCodecReader.cpp
dom/media/omx/MediaCodecReader.h
dom/media/omx/MediaOmxReader.cpp
dom/media/omx/OMXCodecProxy.cpp
dom/media/omx/OMXCodecProxy.h
dom/media/omx/OmxDecoder.cpp
dom/media/omx/OmxDecoder.h
dom/media/omx/RtspOmxReader.cpp
dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
dom/media/platforms/gonk/GonkVideoDecoderManager.h
--- a/dom/media/omx/MediaCodecProxy.cpp
+++ b/dom/media/omx/MediaCodecProxy.cpp
@@ -71,34 +71,30 @@ struct MediaCodecInterfaceWrapper
     return sOutputGraphicBufferStub.GetOutputGraphicBuffer(aMediaCodec, aIndex, aGraphicBuffer);
   }
 
 };
 
 sp<MediaCodecProxy>
 MediaCodecProxy::CreateByType(sp<ALooper> aLooper,
                               const char *aMime,
-                              bool aEncoder,
-                              wp<CodecResourceListener> aListener)
+                              bool aEncoder)
 {
   sp<MediaCodecProxy> codec = new MediaCodecProxy(aLooper,
                                                   aMime,
-                                                  aEncoder,
-                                                  aListener);
+                                                  aEncoder);
   return codec;
 }
 
 MediaCodecProxy::MediaCodecProxy(sp<ALooper> aLooper,
                                  const char *aMime,
-                                 bool aEncoder,
-                                 wp<CodecResourceListener> aListener)
+                                 bool aEncoder)
   : mCodecLooper(aLooper)
   , mCodecMime(aMime)
   , mCodecEncoder(aEncoder)
-  , mListener(aListener)
   , mMediaCodecLock("MediaCodecProxy::mMediaCodecLock")
   , mPendingRequestMediaResource(false)
 {
   MOZ_ASSERT(mCodecLooper != nullptr, "ALooper should not be nullptr.");
 }
 
 MediaCodecProxy::~MediaCodecProxy()
 {
@@ -115,40 +111,42 @@ MediaCodecProxy::AllocateAudioMediaCodec
   if (strncasecmp(mCodecMime.get(), "audio/", 6) == 0) {
     if (allocateCodec()) {
       return true;
     }
   }
   return false;
 }
 
-bool
+RefPtr<MediaCodecProxy::CodecPromise>
 MediaCodecProxy::AsyncAllocateVideoMediaCodec()
 {
   if (mResourceClient || mCodec.get()) {
-    return false;
+    return CodecPromise::CreateAndReject(true, __func__);
   }
 
   if (strncasecmp(mCodecMime.get(), "video/", 6) != 0) {
-    return false;
+    return CodecPromise::CreateAndReject(true, __func__);
   }
   // request video codec
   mozilla::MediaSystemResourceType type =
     mCodecEncoder ? mozilla::MediaSystemResourceType::VIDEO_ENCODER :
                     mozilla::MediaSystemResourceType::VIDEO_DECODER;
   mResourceClient = new mozilla::MediaSystemResourceClient(type);
   mResourceClient->SetListener(this);
   mResourceClient->Acquire();
 
-  return true;
+  RefPtr<CodecPromise> p = mCodecPromise.Ensure(__func__);
+  return p.forget();
 }
 
 void
 MediaCodecProxy::ReleaseMediaCodec()
 {
+  mCodecPromise.RejectIfExists(true, __func__);
   releaseCodec();
 
   if (!mResourceClient) {
     return;
   }
 
   mozilla::MonitorAutoLock mon(mMediaCodecLock);
   if (mPendingRequestMediaResource) {
@@ -473,46 +471,34 @@ MediaCodecProxy::getCapability(uint32_t 
 // Called on ImageBridge thread
 void
 MediaCodecProxy::ResourceReserved()
 {
   MCP_LOG("resourceReserved");
   // Create MediaCodec
   if (!allocateCodec()) {
     ReleaseMediaCodec();
-    // Notification
-    sp<CodecResourceListener> listener = mListener.promote();
-    if (listener != nullptr) {
-      listener->codecCanceled();
-    }
+    mCodecPromise.RejectIfExists(true, __func__);
     return;
   }
 
   // Notify initialization waiting.
   mozilla::MonitorAutoLock mon(mMediaCodecLock);
   mPendingRequestMediaResource = false;
   mon.NotifyAll();
 
-  // Notification
-  sp<CodecResourceListener> listener = mListener.promote();
-  if (listener != nullptr) {
-    listener->codecReserved();
-  }
+  mCodecPromise.ResolveIfExists(true, __func__);
 }
 
 // Called on ImageBridge thread
 void
 MediaCodecProxy::ResourceReserveFailed()
 {
   ReleaseMediaCodec();
-  // Notification
-  sp<CodecResourceListener> listener = mListener.promote();
-  if (listener != nullptr) {
-    listener->codecCanceled();
-  }
+  mCodecPromise.RejectIfExists(true, __func__);
 }
 
 bool MediaCodecProxy::Prepare()
 {
 
   if (start() != OK) {
     MCP_LOG("Couldn't start MediaCodec");
     return false;
--- a/dom/media/omx/MediaCodecProxy.h
+++ b/dom/media/omx/MediaCodecProxy.h
@@ -9,43 +9,31 @@
 
 #include <nsString.h>
 #include <stagefright/MediaCodec.h>
 #include <stagefright/MediaBuffer.h>
 #include <utils/threads.h>
 
 #include "mozilla/media/MediaSystemResourceClient.h"
 #include "mozilla/Monitor.h"
+#include "mozilla/MozPromise.h"
 #include "mozilla/RefPtr.h"
 
 namespace android {
 // This class is intended to be a proxy for MediaCodec with codec resource
 // management. Basically user can use it like MediaCodec, but need to handle
 // the listener when Codec is reserved for Async case. A good example is
 // MediaCodecReader.cpp. Another useage is to use configure(), Prepare(),
 // Input(), and Output(). It is used in GonkVideoDecoderManager.cpp which
 // doesn't need to handle the buffers for codec.
 class MediaCodecProxy : public RefBase
                       , public mozilla::MediaSystemResourceReservationListener
 {
 public:
-  /* Codec resource notification listener.
-   * All functions are called on the Binder thread.
-   */
-  struct CodecResourceListener : public virtual RefBase {
-    /* The codec resource is reserved and can be granted.
-     * The client can allocate the requested resource.
-     */
-    virtual void codecReserved() = 0;
-    /* The codec resource is not reserved any more.
-     * The client should release the resource as soon as possible if the
-     * resource is still being held.
-     */
-    virtual void codecCanceled() = 0;
-  };
+  typedef mozilla::MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> CodecPromise;
 
   enum Capability {
     kEmptyCapability        = 0x00000000,
     kCanExposeGraphicBuffer = 0x00000001,
   };
 
   enum {
     kKeyBufferIndex = 'bfin',
@@ -53,18 +41,17 @@ public:
 
   // Check whether MediaCodec has been allocated.
   bool allocated() const;
 
   // Static MediaCodec methods
   // Only support MediaCodec::CreateByType()
   static sp<MediaCodecProxy> CreateByType(sp<ALooper> aLooper,
                                           const char *aMime,
-                                          bool aEncoder,
-                                          wp<CodecResourceListener> aListener=nullptr);
+                                          bool aEncoder);
 
   // MediaCodec methods
   status_t configure(const sp<AMessage> &aFormat,
                      const sp<Surface> &aNativeWindow,
                      const sp<ICrypto> &aCrypto,
                      uint32_t aFlags);
 
   status_t start();
@@ -137,17 +124,17 @@ public:
   bool UpdateOutputBuffers();
 
   void ReleaseMediaBuffer(MediaBuffer* abuffer);
 
   // It allocates audio MediaCodec synchronously.
   bool AllocateAudioMediaCodec();
 
   // It allocates video MediaCodec asynchronously.
-  bool AsyncAllocateVideoMediaCodec();
+  RefPtr<CodecPromise> AsyncAllocateVideoMediaCodec();
 
   // Free the OMX codec so others can allocate it.
   void ReleaseMediaCodec();
 
 protected:
   virtual ~MediaCodecProxy();
 
   // MediaResourceReservationListener
@@ -158,31 +145,29 @@ private:
   // Forbidden
   MediaCodecProxy() = delete;
   MediaCodecProxy(const MediaCodecProxy &) = delete;
   const MediaCodecProxy &operator=(const MediaCodecProxy &) = delete;
 
   // Constructor for MediaCodecProxy::CreateByType
   MediaCodecProxy(sp<ALooper> aLooper,
                   const char *aMime,
-                  bool aEncoder,
-                  wp<CodecResourceListener> aListener);
+                  bool aEncoder);
 
   // Allocate Codec Resource
   bool allocateCodec();
   // Release Codec Resource
   void releaseCodec();
 
   // MediaCodec Parameter
   sp<ALooper> mCodecLooper;
   nsCString mCodecMime;
   bool mCodecEncoder;
 
-  // Codec Resource Notification Listener
-  wp<CodecResourceListener> mListener;
+  mozilla::MozPromiseHolder<CodecPromise> mCodecPromise;
 
   // Media Resource Management
   RefPtr<mozilla::MediaSystemResourceClient> mResourceClient;
 
   // MediaCodec instance
   mutable RWLock mCodecLock;
   sp<MediaCodec> mCodec;
 
--- a/dom/media/omx/MediaCodecReader.cpp
+++ b/dom/media/omx/MediaCodecReader.cpp
@@ -63,43 +63,16 @@ IsValidDurationUs(int64_t aDuration)
 }
 
 inline bool
 IsValidTimestampUs(int64_t aTimestamp)
 {
   return aTimestamp >= INT64_C(0);
 }
 
-MediaCodecReader::VideoResourceListener::VideoResourceListener(
-  MediaCodecReader* aReader)
-  : mReader(aReader)
-{
-}
-
-MediaCodecReader::VideoResourceListener::~VideoResourceListener()
-{
-  mReader = nullptr;
-}
-
-void
-MediaCodecReader::VideoResourceListener::codecReserved()
-{
-  if (mReader) {
-    mReader->VideoCodecReserved();
-  }
-}
-
-void
-MediaCodecReader::VideoResourceListener::codecCanceled()
-{
-  if (mReader) {
-    mReader->VideoCodecCanceled();
-  }
-}
-
 MediaCodecReader::TrackInputCopier::~TrackInputCopier()
 {
 }
 
 bool
 MediaCodecReader::TrackInputCopier::Copy(MediaBuffer* aSourceBuffer,
                                          sp<ABuffer> aCodecBuffer)
 {
@@ -271,17 +244,16 @@ MediaCodecReader::MediaCodecReader(Abstr
   , mExtractor(nullptr)
   , mTextureClientIndexesLock("MediaCodecReader::mTextureClientIndexesLock")
   , mColorConverterBufferSize(0)
   , mParserMonitor("MediaCodecReader::mParserMonitor")
   , mParseDataFromCache(true)
   , mNextParserPosition(INT64_C(0))
   , mParsedDataLength(INT64_C(0))
 {
-  mVideoListener = new VideoResourceListener(this);
 }
 
 MediaCodecReader::~MediaCodecReader()
 {
 }
 
 void
 MediaCodecReader::ReleaseMediaResources()
@@ -1106,16 +1078,17 @@ MediaCodecReader::ReallocateExtractorRes
 }
 
 void
 MediaCodecReader::ReleaseCriticalResources()
 {
   mMediaResourceRequest.DisconnectIfExists();
   mMediaResourcePromise.RejectIfExists(true, __func__);
   mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);
+  mVideoCodecRequest.DisconnectIfExists();
 
   ResetDecode();
   // Before freeing a video codec, all video buffers needed to be released
   // even from graphics pipeline.
   VideoFrameContainer* videoframe = mDecoder->GetVideoFrameContainer();
   if (videoframe) {
     videoframe->ClearCurrentFrame();
   }
@@ -1308,46 +1281,45 @@ MediaCodecReader::CreateTaskQueues()
 }
 
 RefPtr<MediaOmxCommonReader::MediaResourcePromise>
 MediaCodecReader::CreateMediaCodecs()
 {
   bool isWaiting = false;
   RefPtr<MediaResourcePromise> p = mMediaResourcePromise.Ensure(__func__);
 
-  if (!CreateMediaCodec(mLooper, mAudioTrack, isWaiting, nullptr)) {
+  if (!CreateMediaCodec(mLooper, mAudioTrack, isWaiting)) {
     mMediaResourcePromise.Reject(true, __func__);
     return p;
   }
 
-  if (!CreateMediaCodec(mLooper, mVideoTrack, isWaiting, mVideoListener)) {
+  if (!CreateMediaCodec(mLooper, mVideoTrack, isWaiting)) {
     mMediaResourcePromise.Reject(true, __func__);
     return p;
   }
 
   if (!isWaiting) {
     // No MediaCodec allocation wait.
     mMediaResourcePromise.Resolve(true, __func__);
   }
 
   return p;
 }
 
 bool
 MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
                                    Track& aTrack,
-                                   bool& aIsWaiting,
-                                   wp<MediaCodecProxy::CodecResourceListener> aListener)
+                                   bool& aIsWaiting)
 {
   if (aTrack.mSource != nullptr && aTrack.mCodec == nullptr) {
     sp<MetaData> sourceFormat = aTrack.mSource->getFormat();
 
     const char* mime;
     if (sourceFormat->findCString(kKeyMIMEType, &mime)) {
-      aTrack.mCodec = MediaCodecProxy::CreateByType(aLooper, mime, false, aListener);
+      aTrack.mCodec = MediaCodecProxy::CreateByType(aLooper, mime, false);
     }
 
     if (aTrack.mCodec == nullptr) {
       NS_WARNING("Couldn't create MediaCodecProxy");
       return false;
     }
 
     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
@@ -1375,23 +1347,27 @@ MediaCodecReader::CreateMediaCodec(sp<AL
       // Pending configure() and start() to codecReserved() if the creation
       // should be asynchronous.
       if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)){
         NS_WARNING("Couldn't create and configure MediaCodec synchronously");
         DestroyMediaCodec(aTrack);
         return false;
       }
     } else if (aTrack.mType == Track::kVideo) {
-      if (aTrack.mCodec->AsyncAllocateVideoMediaCodec()) {
-        aIsWaiting = true;
-      } else {
-        NS_WARNING("Couldn't request MediaCodec asynchronously");
-        DestroyMediaCodec(aTrack);
-        return false;
-      }
+      aIsWaiting = true;
+      RefPtr<MediaCodecReader> self = this;
+      mVideoCodecRequest.Begin(aTrack.mCodec->AsyncAllocateVideoMediaCodec()
+        ->Then(OwnerThread(), __func__,
+          [self] (bool) -> void {
+            self->mVideoCodecRequest.Complete();
+            self->mMediaResourcePromise.ResolveIfExists(true, __func__);
+          }, [self] (bool) -> void {
+            self->mVideoCodecRequest.Complete();
+            self->mMediaResourcePromise.RejectIfExists(true, __func__);
+          }));
     }
   }
 
   return true;
 }
 
 bool
 MediaCodecReader::ConfigureMediaCodec(Track& aTrack)
@@ -1943,23 +1919,10 @@ MediaCodecReader::GetColorConverterBuffe
 
 void
 MediaCodecReader::ClearColorConverterBuffer()
 {
   mColorConverterBuffer = nullptr;
   mColorConverterBufferSize = 0;
 }
 
-// Called on Binder thread.
-void
-MediaCodecReader::VideoCodecReserved()
-{
-  mMediaResourcePromise.ResolveIfExists(true, __func__);
-}
-
-// Called on Binder thread.
-void
-MediaCodecReader::VideoCodecCanceled()
-{
-  mMediaResourcePromise.RejectIfExists(true, __func__);
-}
 
 } // namespace mozilla
--- a/dom/media/omx/MediaCodecReader.h
+++ b/dom/media/omx/MediaCodecReader.h
@@ -156,57 +156,33 @@ protected:
     Track(const Track &rhs) = delete;
     const Track &operator=(const Track&) = delete;
   };
 
   // Receive a message from MessageHandler.
   // Called on MediaCodecReader::mLooper thread.
   void onMessageReceived(const android::sp<android::AMessage>& aMessage);
 
-  // Receive a notify from ResourceListener.
-  // Called on Binder thread.
-  virtual void VideoCodecReserved();
-  virtual void VideoCodecCanceled();
-
   virtual bool CreateExtractor();
 
   virtual void HandleResourceAllocated();
 
   android::sp<android::MediaExtractor> mExtractor;
 
   MozPromiseHolder<MediaDecoderReader::MetadataPromise> mMetadataPromise;
   // XXX Remove after bug 1168008 land.
   MozPromiseRequestHolder<MediaResourcePromise> mMediaResourceRequest;
   MozPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
 
+  MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
+
 private:
   virtual bool HasAudio() override;
   virtual bool HasVideo() override;
 
-  // An intermediary class that can be managed by android::sp<T>.
-  // Redirect codecReserved() and codecCanceled() to MediaCodecReader.
-  class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
-  {
-  public:
-    VideoResourceListener(MediaCodecReader* aReader);
-    ~VideoResourceListener();
-
-    virtual void codecReserved();
-    virtual void codecCanceled();
-
-  private:
-    // Forbidden
-    VideoResourceListener() = delete;
-    VideoResourceListener(const VideoResourceListener& rhs) = delete;
-    const VideoResourceListener& operator=(const VideoResourceListener& rhs) = delete;
-
-    MediaCodecReader* mReader;
-  };
-  friend class VideoResourceListener;
-
   class VorbisInputCopier : public TrackInputCopier
   {
     virtual bool Copy(android::MediaBuffer* aSourceBuffer,
                       android::sp<android::ABuffer> aCodecBuffer);
   };
 
   struct AudioTrack : public Track
   {
@@ -333,20 +309,19 @@ private:
   void DestroyLooper();
 
   void DestroyExtractor();
 
   bool CreateMediaSources();
   void DestroyMediaSources();
 
   RefPtr<MediaResourcePromise> CreateMediaCodecs();
-  static bool CreateMediaCodec(android::sp<android::ALooper>& aLooper,
-                               Track& aTrack,
-                               bool& aIsWaiting,
-                               android::wp<android::MediaCodecProxy::CodecResourceListener> aListener);
+  bool CreateMediaCodec(android::sp<android::ALooper>& aLooper,
+                        Track& aTrack,
+                        bool& aIsWaiting);
   static bool ConfigureMediaCodec(Track& aTrack);
   void DestroyMediaCodecs();
   static void DestroyMediaCodec(Track& aTrack);
 
   bool CreateTaskQueues();
   void ShutdownTaskQueues();
   void DecodeVideoFrameTask(int64_t aTimeThreshold);
   void DecodeVideoFrameSync(int64_t aTimeThreshold);
@@ -391,18 +366,16 @@ private:
                                            void* aClosure);
   void TextureClientRecycleCallback(TextureClient* aClient);
   void WaitFenceAndReleaseOutputBuffer();
 
   void ReleaseRecycledTextureClients();
 
   void ReleaseAllTextureClients();
 
-  android::sp<VideoResourceListener> mVideoListener;
-
   android::sp<android::ALooper> mLooper;
   android::sp<android::MetaData> mMetaData;
 
   Mutex mTextureClientIndexesLock;
   nsDataHashtable<nsPtrHashKey<TextureClient>, size_t> mTextureClientIndexes;
 
   // media tracks
   AudioTrack mAudioTrack;
--- a/dom/media/omx/MediaOmxReader.cpp
+++ b/dom/media/omx/MediaOmxReader.cpp
@@ -195,17 +195,17 @@ nsresult MediaOmxReader::InitOmxDecoder(
 
     sp<DataSource> dataSource = new MediaStreamSource(mDecoder->GetResource());
     dataSource->initCheck();
 
     mExtractor = MediaExtractor::Create(dataSource);
     if (!mExtractor.get()) {
       return NS_ERROR_FAILURE;
     }
-    mOmxDecoder = new OmxDecoder(mDecoder);
+    mOmxDecoder = new OmxDecoder(mDecoder, OwnerThread());
     if (!mOmxDecoder->Init(mExtractor)) {
       return NS_ERROR_FAILURE;
     }
     mStreamSource = static_cast<MediaStreamSource*>(dataSource.get());
   }
   return NS_OK;
 }
 
--- a/dom/media/omx/OMXCodecProxy.cpp
+++ b/dom/media/omx/OMXCodecProxy.cpp
@@ -60,16 +60,17 @@ OMXCodecProxy::OMXCodecProxy(
       mSource(source),
       mState(ResourceState::START)
 {
 }
 
 OMXCodecProxy::~OMXCodecProxy()
 {
   mState = ResourceState::END;
+  mCodecPromise.RejectIfExists(true, __func__);
 
   if (mOMXCodec.get()) {
     wp<MediaSource> tmp = mOMXCodec;
     mOMXCodec.clear();
     while (tmp.promote() != nullptr) {
         // this value come from stagefrigh's AwesomePlayer.
         usleep(1000);
     }
@@ -82,77 +83,60 @@ OMXCodecProxy::~OMXCodecProxy()
     mResourceClient = nullptr;
   }
 
   mSource.clear();
   free(mComponentName);
   mComponentName = nullptr;
 }
 
-void OMXCodecProxy::setListener(const wp<CodecResourceListener>& listener)
-{
-  Mutex::Autolock autoLock(mLock);
-  mListener = listener;
-}
-
-void OMXCodecProxy::notifyResourceReserved()
-{
-  sp<CodecResourceListener> listener = mListener.promote();
-  if (listener != nullptr) {
-    listener->codecReserved();
-  }
-}
-
-void OMXCodecProxy::notifyResourceCanceled()
-{
-  sp<CodecResourceListener> listener = mListener.promote();
-  if (listener != nullptr) {
-    listener->codecCanceled();
-  }
-}
-
-void OMXCodecProxy::requestResource()
+RefPtr<OMXCodecProxy::CodecPromise>
+OMXCodecProxy::requestResource()
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mResourceClient) {
-    return;
+    return CodecPromise::CreateAndReject(true, __func__);
   }
   mState = ResourceState::WAITING;
 
   mozilla::MediaSystemResourceType type = mIsEncoder ? mozilla::MediaSystemResourceType::VIDEO_ENCODER :
                                                  mozilla::MediaSystemResourceType::VIDEO_DECODER;
   mResourceClient = new mozilla::MediaSystemResourceClient(type);
   mResourceClient->SetListener(this);
   mResourceClient->Acquire();
+
+  RefPtr<CodecPromise> p = mCodecPromise.Ensure(__func__);
+  return p.forget();
 }
 
 // Called on ImageBridge thread
 void
 OMXCodecProxy::ResourceReserved()
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mState != ResourceState::WAITING) {
+    mCodecPromise.RejectIfExists(true, __func__);
     return;
   }
 
   const char *mime;
   if (!mSrcMeta->findCString(kKeyMIMEType, &mime)) {
     mState = ResourceState::END;
-    notifyResourceCanceled();
+    mCodecPromise.RejectIfExists(true, __func__);
     return;
   }
 
   if (!strncasecmp(mime, "video/", 6)) {
     sp<MediaSource> codec;
     mOMXCodec = OMXCodec::Create(mOMX, mSrcMeta, mIsEncoder, mSource, mComponentName, mFlags, mNativeWindow);
     if (mOMXCodec == nullptr) {
       mState = ResourceState::END;
-      notifyResourceCanceled();
+      mCodecPromise.RejectIfExists(true, __func__);
       return;
     }
     // Check if this video is sized such that we're comfortable
     // possibly using an OMX decoder.
     int32_t maxWidth, maxHeight;
     char propValue[PROPERTY_VALUE_MAX];
     property_get("ro.moz.omx.hw.max_width", propValue, "-1");
     maxWidth = atoi(propValue);
@@ -163,87 +147,93 @@ OMXCodecProxy::ResourceReserved()
     if (maxWidth > 0 && maxHeight > 0 &&
         !(mOMXCodec->getFormat()->findInt32(kKeyWidth, &width) &&
           mOMXCodec->getFormat()->findInt32(kKeyHeight, &height) &&
           width * height <= maxWidth * maxHeight)) {
       printf_stderr("Failed to get video size, or it was too large for HW decoder (<w=%d, h=%d> but <maxW=%d, maxH=%d>)",
                     width, height, maxWidth, maxHeight);
       mOMXCodec.clear();
       mState = ResourceState::END;
-      notifyResourceCanceled();
+      mCodecPromise.RejectIfExists(true, __func__);
       return;
     }
 
     if (mOMXCodec->start() != OK) {
       NS_WARNING("Couldn't start OMX video source");
       mOMXCodec.clear();
       mState = ResourceState::END;
-      notifyResourceCanceled();
+      mCodecPromise.RejectIfExists(true, __func__);
       return;
     }
   }
 
   mState = ResourceState::ACQUIRED;
-  notifyResourceReserved();
+  mCodecPromise.ResolveIfExists(true, __func__);
 }
 
 // Called on ImageBridge thread
 void
 OMXCodecProxy::ResourceReserveFailed()
 {
   Mutex::Autolock autoLock(mLock);
   mState = ResourceState::NOT_ACQUIRED;
+  mCodecPromise.RejectIfExists(true, __func__);
 }
 
-status_t OMXCodecProxy::start(MetaData *params)
+status_t
+OMXCodecProxy::start(MetaData *params)
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mState != ResourceState::ACQUIRED) {
     return NO_INIT;
   }
   CHECK(mOMXCodec.get() != nullptr);
   return mOMXCodec->start();
 }
 
-status_t OMXCodecProxy::stop()
+status_t
+OMXCodecProxy::stop()
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mState != ResourceState::ACQUIRED) {
     return NO_INIT;
   }
   CHECK(mOMXCodec.get() != nullptr);
   return mOMXCodec->stop();
 }
 
-sp<MetaData> OMXCodecProxy::getFormat()
+sp<MetaData>
+OMXCodecProxy::getFormat()
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mState != ResourceState::ACQUIRED) {
     sp<MetaData> meta = new MetaData;
     return meta;
   }
   CHECK(mOMXCodec.get() != nullptr);
   return mOMXCodec->getFormat();
 }
 
-status_t OMXCodecProxy::read(MediaBuffer **buffer, const ReadOptions *options)
+status_t
+OMXCodecProxy::read(MediaBuffer **buffer, const ReadOptions *options)
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mState != ResourceState::ACQUIRED) {
     return NO_INIT;
   }
   CHECK(mOMXCodec.get() != nullptr);
   return mOMXCodec->read(buffer, options);
 }
 
-status_t OMXCodecProxy::pause()
+status_t
+OMXCodecProxy::pause()
 {
   Mutex::Autolock autoLock(mLock);
 
   if (mState != ResourceState::ACQUIRED) {
     return NO_INIT;
   }
   CHECK(mOMXCodec.get() != nullptr);
   return mOMXCodec->pause();
--- a/dom/media/omx/OMXCodecProxy.h
+++ b/dom/media/omx/OMXCodecProxy.h
@@ -9,40 +9,28 @@
 
 #include <android/native_window.h>
 #include <media/IOMX.h>
 #include <stagefright/MediaBuffer.h>
 #include <stagefright/MediaSource.h>
 #include <utils/threads.h>
 
 #include "mozilla/media/MediaSystemResourceClient.h"
+#include "mozilla/MozPromise.h"
 #include "mozilla/RefPtr.h"
 
 namespace android {
 
 struct MetaData;
 
 class OMXCodecProxy : public MediaSource
                     , public mozilla::MediaSystemResourceReservationListener
 {
 public:
-  /* Codec resource notification listener.
-   * All functions are called on the Binder thread.
-   */
-  struct CodecResourceListener : public virtual RefBase {
-    /* The codec resource is reserved and can be granted.
-     * The client can allocate the requested resource.
-     */
-    virtual void codecReserved() = 0;
-    /* The codec resource is not reserved any more.
-     * The client should release the resource as soon as possible if the
-     * resource is still being held.
-     */
-    virtual void codecCanceled() = 0;
-  };
+  typedef mozilla::MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> CodecPromise;
 
   // Enumeration for the valid resource allcoation states
   enum class ResourceState : int8_t {
     START,
     WAITING,
     ACQUIRED,
     NOT_ACQUIRED,
     END
@@ -51,19 +39,17 @@ public:
   static sp<OMXCodecProxy> Create(
           const sp<IOMX> &omx,
           const sp<MetaData> &meta, bool createEncoder,
           const sp<MediaSource> &source,
           const char *matchComponentName = nullptr,
           uint32_t flags = 0,
           const sp<ANativeWindow> &nativeWindow = nullptr);
 
-    void setListener(const wp<CodecResourceListener>& listener);
-
-    void requestResource();
+    RefPtr<CodecPromise> requestResource();
 
     // MediaSystemResourceReservationListener
     void ResourceReserved() override;
     void ResourceReserveFailed() override;
 
     // MediaSource
     virtual status_t start(MetaData *params = nullptr);
     virtual status_t stop();
@@ -82,21 +68,16 @@ protected:
         bool createEncoder,
         const sp<MediaSource> &source,
         const char *matchComponentName,
         uint32_t flags,
         const sp<ANativeWindow> &nativeWindow);
 
     virtual ~OMXCodecProxy();
 
-    void notifyResourceReserved();
-    void notifyResourceCanceled();
-
-    void notifyStatusChangedLocked();
-
 private:
     OMXCodecProxy(const OMXCodecProxy &);
     OMXCodecProxy &operator=(const OMXCodecProxy &);
 
     Mutex mLock;
 
     sp<IOMX> mOMX;
     sp<MetaData> mSrcMeta;
@@ -107,16 +88,14 @@ private:
     sp<ANativeWindow> mNativeWindow;
 
     sp<MediaSource> mSource;
 
     sp<MediaSource> mOMXCodec;
 
     RefPtr<mozilla::MediaSystemResourceClient> mResourceClient;
     ResourceState mState;
-
-    // Codec Resource Notification Listener
-    wp<CodecResourceListener> mListener;
+    mozilla::MozPromiseHolder<CodecPromise> mCodecPromise;
 };
 
 } // namespace android
 
 #endif  // OMX_CODEC_PROXY_DECODER_H_
--- a/dom/media/omx/OmxDecoder.cpp
+++ b/dom/media/omx/OmxDecoder.cpp
@@ -41,17 +41,18 @@ PRLogModuleInfo *gOmxDecoderLog;
 #define LOG(type, msg...) MOZ_LOG(gOmxDecoderLog, type, (msg))
 
 using namespace MPAPI;
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace android;
 
-OmxDecoder::OmxDecoder(AbstractMediaDecoder *aDecoder) :
+OmxDecoder::OmxDecoder(AbstractMediaDecoder *aDecoder,
+                       mozilla::TaskQueue* aTaskQueue) :
   mDecoder(aDecoder),
   mDisplayWidth(0),
   mDisplayHeight(0),
   mVideoWidth(0),
   mVideoHeight(0),
   mVideoColorFormat(0),
   mVideoStride(0),
   mVideoSliceHeight(0),
@@ -59,16 +60,17 @@ OmxDecoder::OmxDecoder(AbstractMediaDeco
   mAudioChannels(-1),
   mAudioSampleRate(-1),
   mDurationUs(-1),
   mLastSeekTime(-1),
   mVideoBuffer(nullptr),
   mAudioBuffer(nullptr),
   mIsVideoSeeking(false),
   mAudioMetadataRead(false),
+  mTaskQueue(aTaskQueue),
   mAudioPaused(false),
   mVideoPaused(false)
 {
   mLooper = new ALooper;
   mLooper->setName("OmxDecoder");
 
   mReflector = new AHandlerReflector<OmxDecoder>(this);
   // Register AMessage handler to ALooper.
@@ -84,35 +86,27 @@ OmxDecoder::~OmxDecoder()
   ReleaseMediaResources();
 
   // unregister AMessage handler from ALooper.
   mLooper->unregisterHandler(mReflector->id());
   // Stop ALooper thread.
   mLooper->stop();
 }
 
-void OmxDecoder::codecReserved()
-{
-  mMediaResourcePromise.ResolveIfExists(true, __func__);
-}
-void OmxDecoder::codecCanceled()
-{
-  mMediaResourcePromise.RejectIfExists(true, __func__);
-}
-
 static sp<IOMX> sOMX = nullptr;
 static sp<IOMX> GetOMX()
 {
   if(sOMX.get() == nullptr) {
     sOMX = new OMX;
     }
   return sOMX;
 }
 
-bool OmxDecoder::Init(sp<MediaExtractor>& extractor) {
+bool
+OmxDecoder::Init(sp<MediaExtractor>& extractor) {
   if (!gOmxDecoderLog) {
     gOmxDecoderLog = PR_NewLogModule("OmxDecoder");
   }
 
   sp<MetaData> meta = extractor->getMetaData();
 
   ssize_t audioTrackIndex = -1;
   ssize_t videoTrackIndex = -1;
@@ -152,17 +146,18 @@ bool OmxDecoder::Init(sp<MediaExtractor>
     // mAudioTrack is be used by OMXCodec. For offloaded audio track, using same
     // object gives undetermined behavior. So get a new track
     mAudioOffloadTrack = extractor->getTrack(audioTrackIndex);
 #endif
   }
   return true;
 }
 
-bool OmxDecoder::EnsureMetadata() {
+bool
+OmxDecoder::EnsureMetadata() {
   // calculate duration
   int64_t totalDurationUs = 0;
   int64_t durationUs = 0;
   if (mVideoTrack.get() && mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
     if (durationUs > totalDurationUs)
       totalDurationUs = durationUs;
   }
   if (mAudioTrack.get()) {
@@ -212,17 +207,18 @@ bool OmxDecoder::EnsureMetadata() {
 
 static bool isInEmulator()
 {
   char propQemu[PROPERTY_VALUE_MAX];
   property_get("ro.kernel.qemu", propQemu, "");
   return !strncmp(propQemu, "1", 1);
 }
 
-RefPtr<mozilla::MediaOmxCommonReader::MediaResourcePromise> OmxDecoder::AllocateMediaResources()
+RefPtr<mozilla::MediaOmxCommonReader::MediaResourcePromise>
+OmxDecoder::AllocateMediaResources()
 {
   RefPtr<MediaResourcePromise> p = mMediaResourcePromise.Ensure(__func__);
 
   if ((mVideoTrack != nullptr) && (mVideoSource == nullptr)) {
     // OMXClient::connect() always returns OK and abort's fatally if
     // it can't connect.
     OMXClient client;
     DebugOnly<status_t> err = client.connect();
@@ -269,19 +265,26 @@ RefPtr<mozilla::MediaOmxCommonReader::Me
                                 nullptr,
                                 flags,
                                 mNativeWindowClient);
     if (mVideoSource == nullptr) {
       NS_WARNING("Couldn't create OMX video source");
       mMediaResourcePromise.Reject(true, __func__);
       return p;
     } else {
-      sp<OMXCodecProxy::CodecResourceListener> listener = this;
-      mVideoSource->setListener(listener);
-      mVideoSource->requestResource();
+      sp<OmxDecoder> self = this;
+      mVideoCodecRequest.Begin(mVideoSource->requestResource()
+        ->Then(OwnerThread(), __func__,
+          [self] (bool) -> void {
+            self->mVideoCodecRequest.Complete();
+            self->mMediaResourcePromise.ResolveIfExists(true, __func__);
+          }, [self] (bool) -> void {
+            self->mVideoCodecRequest.Complete();
+            self->mMediaResourcePromise.RejectIfExists(true, __func__);
+          }));
     }
   }
 
   if ((mAudioTrack != nullptr) && (mAudioSource == nullptr)) {
     // OMXClient::connect() always returns OK and abort's fatally if
     // it can't connect.
     OMXClient client;
     DebugOnly<status_t> err = client.connect();
@@ -332,17 +335,19 @@ RefPtr<mozilla::MediaOmxCommonReader::Me
   if (!mVideoSource.get()) {
     // No resource allocation wait.
     mMediaResourcePromise.Resolve(true, __func__);
   }
   return p;
 }
 
 
-void OmxDecoder::ReleaseMediaResources() {
+void
+OmxDecoder::ReleaseMediaResources() {
+  mVideoCodecRequest.DisconnectIfExists();
   mMediaResourcePromise.RejectIfExists(true, __func__);
 
   ReleaseVideoBuffer();
   ReleaseAudioBuffer();
 
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
     MOZ_ASSERT(mPendingRecycleTexutreClients.empty());
@@ -382,17 +387,18 @@ void OmxDecoder::ReleaseMediaResources()
   mNativeWindowClient.clear();
   mNativeWindow.clear();
 
   // Reset this variable to make the first seek go to the previous keyframe
   // when resuming
   mLastSeekTime = -1;
 }
 
-bool OmxDecoder::SetVideoFormat() {
+bool
+OmxDecoder::SetVideoFormat() {
   const char *componentName;
 
   if (!mVideoSource->getFormat()->findInt32(kKeyWidth, &mVideoWidth) ||
       !mVideoSource->getFormat()->findInt32(kKeyHeight, &mVideoHeight) ||
       !mVideoSource->getFormat()->findCString(kKeyDecoderComponent, &componentName) ||
       !mVideoSource->getFormat()->findInt32(kKeyColorFormat, &mVideoColorFormat) ) {
     return false;
   }
@@ -438,86 +444,95 @@ bool OmxDecoder::SetVideoFormat() {
 
   LOG(LogLevel::Debug, "display width: %d display height %d width: %d height: %d component: %s format: %d stride: %d sliceHeight: %d rotation: %d",
       mDisplayWidth, mDisplayHeight, mVideoWidth, mVideoHeight, componentName,
       mVideoColorFormat, mVideoStride, mVideoSliceHeight, mVideoRotation);
 
   return true;
 }
 
-bool OmxDecoder::SetAudioFormat() {
+bool
+OmxDecoder::SetAudioFormat() {
   // If the format changed, update our cached info.
   if (!mAudioSource->getFormat()->findInt32(kKeyChannelCount, &mAudioChannels) ||
       !mAudioSource->getFormat()->findInt32(kKeySampleRate, &mAudioSampleRate)) {
     return false;
   }
 
   LOG(LogLevel::Debug, "channelCount: %d sampleRate: %d",
       mAudioChannels, mAudioSampleRate);
 
   return true;
 }
 
-void OmxDecoder::ReleaseDecoder()
+void
+OmxDecoder::ReleaseDecoder()
 {
   mDecoder = nullptr;
 }
 
-void OmxDecoder::ReleaseVideoBuffer() {
+void
+OmxDecoder::ReleaseVideoBuffer() {
   if (mVideoBuffer) {
     mVideoBuffer->release();
     mVideoBuffer = nullptr;
   }
 }
 
-void OmxDecoder::ReleaseAudioBuffer() {
+void
+OmxDecoder::ReleaseAudioBuffer() {
   if (mAudioBuffer) {
     mAudioBuffer->release();
     mAudioBuffer = nullptr;
   }
 }
 
-void OmxDecoder::PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void
+OmxDecoder::PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   void *y = aData;
   void *u = static_cast<uint8_t *>(y) + mVideoStride * mVideoSliceHeight;
   void *v = static_cast<uint8_t *>(u) + mVideoStride/2 * mVideoSliceHeight/2;
 
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
               u, mVideoStride/2, mVideoWidth/2, mVideoHeight/2, 0, 0,
               v, mVideoStride/2, mVideoWidth/2, mVideoHeight/2, 0, 0);
 }
 
-void OmxDecoder::CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void
+OmxDecoder::CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               aData, mVideoStride, mVideoWidth, mVideoHeight, 1, 1,
               aData, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 3,
               aData, mVideoStride, mVideoWidth/2, mVideoHeight/2, 2, 3);
 }
 
-void OmxDecoder::SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void
+OmxDecoder::SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   void *y = aData;
   void *uv = static_cast<uint8_t *>(y) + (mVideoStride * mVideoSliceHeight);
 
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
               uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 1,
               uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 1, 1);
 }
 
-void OmxDecoder::SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void
+OmxDecoder::SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   SemiPlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
   aFrame->Cb.mOffset = 1;
   aFrame->Cr.mOffset = 0;
 }
 
-bool OmxDecoder::ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+bool
+OmxDecoder::ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
 
   aFrame->mGraphicBuffer = nullptr;
 
   switch (mVideoColorFormat) {
   case OMX_COLOR_FormatYUV420Planar:
     PlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
     break;
@@ -532,23 +547,25 @@ bool OmxDecoder::ToVideoFrame(VideoFrame
     break;
   default:
     LOG(LogLevel::Debug, "Unknown video color format %08x", mVideoColorFormat);
     return false;
   }
   return true;
 }
 
-bool OmxDecoder::ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize, int32_t aAudioChannels, int32_t aAudioSampleRate)
+bool
+OmxDecoder::ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize, int32_t aAudioChannels, int32_t aAudioSampleRate)
 {
   aFrame->Set(aTimeUs, static_cast<char *>(aData) + aDataOffset, aSize, aAudioChannels, aAudioSampleRate);
   return true;
 }
 
-bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
+bool
+OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
                            bool aKeyframeSkip, bool aDoSeek)
 {
   if (!mVideoSource.get())
     return false;
 
   ReleaseVideoBuffer();
 
   status_t err;
@@ -576,17 +593,17 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
       findNextBuffer = false;
       if (mIsVideoSeeking) {
         err = mVideoSource->read(&mVideoBuffer, &options);
         Mutex::Autolock autoLock(mSeekLock);
         mIsVideoSeeking = false;
         PostReleaseVideoBuffer(nullptr, FenceHandle());
       }
       else {
-	err = mVideoSource->read(&mVideoBuffer);
+        err = mVideoSource->read(&mVideoBuffer);
       }
 
       // If there is no next Keyframe, jump to the previous key frame.
       if (err == ERROR_END_OF_STREAM && seekMode == MediaSource::ReadOptions::SEEK_NEXT_SYNC) {
         seekMode = MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC;
         findNextBuffer = true;
         {
           Mutex::Autolock autoLock(mSeekLock);
@@ -696,17 +713,18 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
     // regardless, don't keep trying to decode if the decoder doesn't want to.
     LOG(LogLevel::Debug, "OmxDecoder::ReadVideo failed, err=%d", err);
     return false;
   }
 
   return true;
 }
 
-bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
+bool
+OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
 {
   status_t err;
 
   if (mAudioMetadataRead && aSeekTimeUs == -1) {
     // Use the data read into the buffer during metadata time
     err = OK;
   }
   else {
@@ -755,17 +773,18 @@ bool OmxDecoder::ReadAudio(AudioFrame *a
   else if (err != OK) {
     LOG(LogLevel::Debug, "OmxDecoder::ReadAudio failed, err=%d", err);
     return false;
   }
 
   return true;
 }
 
-nsresult OmxDecoder::Play()
+nsresult
+OmxDecoder::Play()
 {
   if (!mVideoPaused && !mAudioPaused) {
     return NS_OK;
   }
 
   if (mVideoPaused && mVideoSource.get() && mVideoSource->start() != OK) {
     return NS_ERROR_UNEXPECTED;
   }
@@ -782,17 +801,18 @@ nsresult OmxDecoder::Play()
 // AOSP didn't give implementation on OMXCodec::Pause() and not define
 // OMXCodec::Start() should be called for resuming the decoding. Currently
 // it is customized by a specific open source repository only.
 // ToDo The one not supported OMXCodec::Pause() should return error code here,
 // so OMXCodec::Start() doesn't be called again for resuming. But if someone
 // implement the OMXCodec::Pause() and need a following OMXCodec::Read() with
 // seek option (define in MediaSource.h) then it is still not supported here.
 // We need to fix it until it is really happened.
-void OmxDecoder::Pause()
+void
+OmxDecoder::Pause()
 {
   /* The implementation of OMXCodec::pause is flawed.
    * OMXCodec::start will not restore from the paused state and result in
    * buffer timeout which causes timeouts in mochitests.
    * Since there is not power consumption problem in emulator, we will just
    * return when running in emulator to fix timeouts in mochitests.
    */
   if (isInEmulator()) {
@@ -808,17 +828,18 @@ void OmxDecoder::Pause()
   }
 
   if (mAudioSource.get() && mAudioSource->pause() == OK) {
     mAudioPaused = true;
   }
 }
 
 // Called on ALooper thread.
-void OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
+void
+OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
 {
   switch (msg->what()) {
     case kNotifyPostReleaseVideoBuffer:
     {
       Mutex::Autolock autoLock(mSeekLock);
       // Free pending video buffers when OmxDecoder is not seeking video.
       // If OmxDecoder is seeking video, the buffers are freed on seek exit.
       if (!mIsVideoSeeking) {
@@ -827,32 +848,34 @@ void OmxDecoder::onMessageReceived(const
       break;
     }
     default:
       TRESPASS();
       break;
   }
 }
 
-void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle)
+void
+OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle)
 {
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
     if (aBuffer) {
       mPendingVideoBuffers.push(BufferItem(aBuffer, aReleaseFenceHandle));
     }
   }
 
   sp<AMessage> notify =
             new AMessage(kNotifyPostReleaseVideoBuffer, mReflector->id());
   // post AMessage to OmxDecoder via ALooper.
   notify->post();
 }
 
-void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
+void
+OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
 {
   Vector<BufferItem> releasingVideoBuffers;
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
 
     int size = mPendingVideoBuffers.size();
     for (int i = 0; i < size; i++) {
       releasingVideoBuffers.push(mPendingVideoBuffers[i]);
@@ -882,17 +905,18 @@ void OmxDecoder::ReleaseAllPendingVideoB
     metaData->setInt32(kKeyRendered, 1);
 #endif
     // Return MediaBuffer to OMXCodec.
     buffer->release();
   }
   releasingVideoBuffers.clear();
 }
 
-void OmxDecoder::RecycleCallbackImp(TextureClient* aClient)
+void
+OmxDecoder::RecycleCallbackImp(TextureClient* aClient)
 {
   aClient->ClearRecycleCallback();
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
     if (mPendingRecycleTexutreClients.find(aClient) == mPendingRecycleTexutreClients.end()) {
       printf_stderr("OmxDecoder::RecycleCallbackImp -- TextureClient is not pending recycle\n");
       return;
     }
--- a/dom/media/omx/OmxDecoder.h
+++ b/dom/media/omx/OmxDecoder.h
@@ -15,17 +15,17 @@
 #include "OMXCodecProxy.h"
 
 namespace android {
 class OmxDecoder;
 };
 
 namespace android {
 
-class OmxDecoder : public OMXCodecProxy::CodecResourceListener {
+class OmxDecoder : public RefBase {
   typedef MPAPI::AudioFrame AudioFrame;
   typedef MPAPI::VideoFrame VideoFrame;
   typedef mozilla::MP3FrameParser MP3FrameParser;
   typedef mozilla::MediaResource MediaResource;
   typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
   typedef mozilla::layers::FenceHandle FenceHandle;
   typedef mozilla::layers::TextureClient TextureClient;
   typedef mozilla::MediaOmxCommonReader::MediaResourcePromise MediaResourcePromise;
@@ -114,16 +114,19 @@ class OmxDecoder : public OMXCodecProxy:
   // deliver a message to a wrapped object(OmxDecoder).
   // AHandlerReflector is similar to Handler in android Java.
   // http://developer.android.com/reference/android/os/Handler.html
   sp<AHandlerReflector<OmxDecoder> > mReflector;
 
   // 'true' if a read from the audio stream was done while reading the metadata
   bool mAudioMetadataRead;
 
+  RefPtr<mozilla::TaskQueue> mTaskQueue;
+
+  mozilla::MozPromiseRequestHolder<OMXCodecProxy::CodecPromise> mVideoCodecRequest;
   mozilla::MozPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
 
   void ReleaseVideoBuffer();
   void ReleaseAudioBuffer();
   // Call with mSeekLock held.
   void ReleaseAllPendingVideoBuffersLocked();
 
   void PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
@@ -133,23 +136,24 @@ class OmxDecoder : public OMXCodecProxy:
   bool ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
   bool ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize,
                     int32_t aAudioChannels, int32_t aAudioSampleRate);
 
   //True if decoder is in a paused state
   bool mAudioPaused;
   bool mVideoPaused;
 
-public:
-  explicit OmxDecoder(AbstractMediaDecoder *aDecoder);
-  ~OmxDecoder();
+  mozilla::TaskQueue* OwnerThread() const
+  {
+    return mTaskQueue;
+  }
 
-  // OMXCodecProxy::CodecResourceListener
-  virtual void codecReserved();
-  virtual void codecCanceled();
+public:
+  explicit OmxDecoder(AbstractMediaDecoder *aDecoder, mozilla::TaskQueue* aTaskQueue);
+  ~OmxDecoder();
 
   // The MediaExtractor provides essential information for creating OMXCodec
   // instance. Such as video/audio codec, we can retrieve them through the
   // MediaExtractor::getTrackMetaData().
   // In general cases, the extractor is created by a sp<DataSource> which
   // connect to a MediaResource like ChannelMediaResource.
   // Data is read from the MediaResource to create a suitable extractor which
   // extracts data from a container.
--- a/dom/media/omx/RtspOmxReader.cpp
+++ b/dom/media/omx/RtspOmxReader.cpp
@@ -19,17 +19,17 @@ namespace mozilla {
 
 nsresult RtspOmxReader::InitOmxDecoder()
 {
   if (!mOmxDecoder.get()) {
     NS_ASSERTION(mDecoder, "RtspOmxReader mDecoder is null.");
     NS_ASSERTION(mDecoder->GetResource(),
                  "RtspOmxReader mDecoder->GetResource() is null.");
     mExtractor = new RtspExtractor(mRtspResource);
-    mOmxDecoder = new OmxDecoder(mDecoder);
+    mOmxDecoder = new OmxDecoder(mDecoder, OwnerThread());
     if (!mOmxDecoder->Init(mExtractor)) {
       return NS_ERROR_FAILURE;
     }
   }
   return NS_OK;
 }
 
 RefPtr<MediaDecoderReader::SeekPromise>
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
@@ -65,17 +65,17 @@ GonkAudioDecoderManager::Init()
 bool
 GonkAudioDecoderManager::InitMediaCodecProxy()
 {
   status_t rv = OK;
   if (!InitLoopers(MediaData::AUDIO_DATA)) {
     return false;
   }
 
-  mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, nullptr);
+  mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false);
   if (!mDecoder.get()) {
     return false;
   }
   if (!mDecoder->AllocateAudioMediaCodec())
   {
     mDecoder = nullptr;
     return false;
   }
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
@@ -57,18 +57,16 @@ GonkVideoDecoderManager::GonkVideoDecode
   mDisplayHeight = aConfig.mDisplay.height;
   mInfo.mVideo = aConfig;
 
   mCodecSpecificData = aConfig.mCodecSpecificConfig;
   nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
   nsIntSize frameSize(mVideoWidth, mVideoHeight);
   mPicture = pictureRect;
   mInitialFrame = frameSize;
-  mVideoListener = new VideoResourceListener();
-
 }
 
 GonkVideoDecoderManager::~GonkVideoDecoderManager()
 {
   MOZ_COUNT_DTOR(GonkVideoDecoderManager);
 }
 
 nsresult
@@ -114,34 +112,33 @@ GonkVideoDecoderManager::Init()
   }
 
   if (!InitLoopers(MediaData::VIDEO_DATA)) {
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   RefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
   android::sp<GonkVideoDecoderManager> self = this;
-  mVideoCodecRequest.Begin(mVideoListener->Init()
+  mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false);
+
+  uint32_t capability = MediaCodecProxy::kEmptyCapability;
+  if (mDecoder->getCapability(&capability) == OK && (capability &
+      MediaCodecProxy::kCanExposeGraphicBuffer)) {
+    mNativeWindow = new GonkNativeWindow();
+  }
+
+  mVideoCodecRequest.Begin(mDecoder->AsyncAllocateVideoMediaCodec()
     ->Then(mReaderTaskQueue, __func__,
       [self] (bool) -> void {
         self->mVideoCodecRequest.Complete();
         self->codecReserved();
       }, [self] (bool) -> void {
         self->mVideoCodecRequest.Complete();
         self->codecCanceled();
       }));
-  mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
-
-  uint32_t capability = MediaCodecProxy::kEmptyCapability;
-  if (mDecoder->getCapability(&capability) == OK && (capability &
-      MediaCodecProxy::kCanExposeGraphicBuffer)) {
-    mNativeWindow = new GonkNativeWindow();
-  }
-
-  mDecoder->AsyncAllocateVideoMediaCodec();
 
   return p;
 }
 
 nsresult
 GonkVideoDecoderManager::CreateVideoData(MediaBuffer* aBuffer,
                                          int64_t aStreamOffset,
                                          VideoData **v)
@@ -649,36 +646,16 @@ GonkVideoDecoderManager::onMessageReceiv
     default:
     {
       GonkDecoderManager::onMessageReceived(aMessage);
       break;
     }
   }
 }
 
-GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener()
-{
-}
-
-GonkVideoDecoderManager::VideoResourceListener::~VideoResourceListener()
-{
-}
-
-void
-GonkVideoDecoderManager::VideoResourceListener::codecReserved()
-{
-  mVideoCodecPromise.Resolve(true, __func__);
-}
-
-void
-GonkVideoDecoderManager::VideoResourceListener::codecCanceled()
-{
-  mVideoCodecPromise.Reject(true, __func__);
-}
-
 uint8_t *
 GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
 {
   // Allocate a temporary YUV420Planer buffer.
   size_t yuv420p_y_size = aWidth * aHeight;
   size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
   size_t yuv420p_v_size = yuv420p_u_size;
   size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.h
@@ -32,18 +32,16 @@ class TextureClient;
 class TextureClientRecycleAllocator;
 } // namespace mozilla::layers
 
 class GonkVideoDecoderManager : public GonkDecoderManager {
 typedef android::MediaCodecProxy MediaCodecProxy;
 typedef mozilla::layers::TextureClient TextureClient;
 
 public:
-  typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> MediaResourcePromise;
-
   GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
                           const VideoInfo& aConfig);
 
   virtual ~GonkVideoDecoderManager();
 
   RefPtr<InitPromise> Init() override;
 
   nsresult Output(int64_t aStreamOffset,
@@ -75,39 +73,16 @@ private:
     int32_t mCropLeft = 0;
     int32_t mCropTop = 0;
     int32_t mCropRight = 0;
     int32_t mCropBottom = 0;
   };
 
   void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
 
-  class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
-  {
-  public:
-    VideoResourceListener();
-    ~VideoResourceListener();
-
-    RefPtr<MediaResourcePromise> Init()
-    {
-      RefPtr<MediaResourcePromise> p = mVideoCodecPromise.Ensure(__func__);
-      return p.forget();
-    }
-
-    void codecReserved() override;
-    void codecCanceled() override;
-
-  private:
-    // Forbidden
-    VideoResourceListener(const VideoResourceListener &rhs) = delete;
-    const VideoResourceListener &operator=(const VideoResourceListener &rhs) = delete;
-
-    MozPromiseHolder<MediaResourcePromise> mVideoCodecPromise;
-  };
-
   bool SetVideoFormat();
 
   nsresult CreateVideoData(MediaBuffer* aBuffer, int64_t aStreamOffset, VideoData** aOutData);
   already_AddRefed<VideoData> CreateVideoDataFromGraphicBuffer(android::MediaBuffer* aSource,
                                                                gfx::IntRect& aPicture);
   already_AddRefed<VideoData> CreateVideoDataFromDataBuffer(android::MediaBuffer* aSource,
                                                             gfx::IntRect& aPicture);
 
@@ -127,18 +102,17 @@ private:
   uint32_t mDisplayHeight;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
 
   RefPtr<layers::ImageContainer> mImageContainer;
   RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator;
 
   MediaInfo mInfo;
-  android::sp<VideoResourceListener> mVideoListener;
-  MozPromiseRequestHolder<MediaResourcePromise> mVideoCodecRequest;
+  MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
   FrameInfo mFrameInfo;
 
   // color converter
   android::I420ColorConverterHelper mColorConverter;
   nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
   size_t mColorConverterBufferSize;
 
   android::sp<android::GonkNativeWindow> mNativeWindow;