Bug 1362912. P2 - fix the callers. draft
authorJW Wang <jwwang@mozilla.com>
Tue, 09 May 2017 23:31:32 +0800
changeset 575315 fc6a2748dcd08000a22693799d097ba6ca0eb0ce
parent 575314 0d0b1aeb9e2ff5211dc8411526ee214a01549299
child 575347 03c098991e9614434525ae133a051fd5964d6758
push id58024
push userjwwang@mozilla.com
push dateWed, 10 May 2017 08:12:21 +0000
bugs1362912
milestone55.0a1
Bug 1362912. P2 - fix the callers. MozReview-Commit-ID: LdYcIWAFDUn
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
dom/media/MediaFormatReader.cpp
dom/media/gmp/GMPServiceParent.cpp
dom/media/gtest/TestMozPromise.cpp
dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
dom/media/platforms/omx/OmxDataDecoder.cpp
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -49,18 +49,21 @@ MediaDecoderReaderWrapper::RequestAudioD
   MOZ_ASSERT(!mShutdown);
 
   int64_t startTime = StartTime().ToMicroseconds();
   return InvokeAsync(mReader->OwnerThread(), mReader.get(),
                      __func__, &MediaDecoderReader::RequestAudioData)
     ->Then(mOwnerThread, __func__,
            [startTime] (AudioData* aAudio) {
              aAudio->AdjustForStartTime(startTime);
+             return AudioDataPromise::CreateAndResolve(aAudio, __func__);
            },
-           [] (const MediaResult& aError) {});
+           [] (const MediaResult& aError) {
+             return AudioDataPromise::CreateAndReject(aError, __func__);
+           });
 }
 
 RefPtr<MediaDecoderReaderWrapper::VideoDataPromise>
 MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
                                             media::TimeUnit aTimeThreshold)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mShutdown);
@@ -72,18 +75,21 @@ MediaDecoderReaderWrapper::RequestVideoD
   int64_t startTime = StartTime().ToMicroseconds();
   return InvokeAsync(
     mReader->OwnerThread(), mReader.get(), __func__,
     &MediaDecoderReader::RequestVideoData,
     aSkipToNextKeyframe, aTimeThreshold)
   ->Then(mOwnerThread, __func__,
          [startTime] (VideoData* aVideo) {
            aVideo->AdjustForStartTime(startTime);
+           return VideoDataPromise::CreateAndResolve(aVideo, __func__);
          },
-         [] (const MediaResult& aError) {});
+         [] (const MediaResult& aError) {
+           return VideoDataPromise::CreateAndReject(aError, __func__);
+         });
 }
 
 RefPtr<MediaDecoderReader::SeekPromise>
 MediaDecoderReaderWrapper::Seek(const SeekTarget& aTarget)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   SeekTarget adjustedTarget = aTarget;
   adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime());
@@ -126,27 +132,35 @@ RefPtr<ShutdownPromise>
 MediaDecoderReaderWrapper::Shutdown()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   mShutdown = true;
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::Shutdown);
 }
 
-void
+RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
 MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder* aMetadata)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   if (mShutdown) {
-    return;
+    return MetadataPromise::CreateAndReject(
+      NS_ERROR_DOM_MEDIA_ABORT_ERR, __func__);
   }
 
   if (mStartTime.isNothing()) {
     mStartTime.emplace(aMetadata->mInfo.mStartTime);
   }
+  return MetadataPromise::CreateAndResolve(aMetadata, __func__);
+}
+
+RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
+MediaDecoderReaderWrapper::OnMetadataNotRead(const MediaResult& aError)
+{
+  return MetadataPromise::CreateAndReject(aError, __func__);
 }
 
 void
 MediaDecoderReaderWrapper::SetVideoBlankDecode(bool aIsBlankDecode)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<bool>(mReader, &MediaDecoderReader::SetVideoNullDecode,
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -85,18 +85,18 @@ public:
   }
 
   void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }
 
   void SetVideoBlankDecode(bool aIsBlankDecode);
 
 private:
   ~MediaDecoderReaderWrapper();
-  void OnMetadataRead(MetadataHolder* aMetadata);
-  void OnMetadataNotRead() {}
+  RefPtr<MetadataPromise> OnMetadataRead(MetadataHolder* aMetadata);
+  RefPtr<MetadataPromise> OnMetadataNotRead(const MediaResult& aError);
 
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReader> mReader;
 
   bool mShutdown = false;
   Maybe<media::TimeUnit> mStartTime;
 };
 
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -565,18 +565,19 @@ public:
     return mDecoder->SupportDecoderRecycling();
   }
   RefPtr<ShutdownPromise> Shutdown() override
   {
     RefPtr<MediaDataDecoder> decoder = mDecoder.forget();
     RefPtr<Token> token = mToken.forget();
     return decoder->Shutdown()->Then(
       AbstractThread::GetCurrent(), __func__,
-      [token]() {},
-      [token]() { MOZ_RELEASE_ASSERT(false, "Can't reach here"); });
+      [token]() {
+        return ShutdownPromise::CreateAndResolve(true, __func__);
+      });
   }
 
 private:
   RefPtr<MediaDataDecoder> mDecoder;
   RefPtr<Token> mToken;
 };
 
 void
@@ -884,30 +885,42 @@ public:
 
   RefPtr<SeekPromise> Seek(const TimeUnit& aTime) override
   {
     RefPtr<Wrapper> self = this;
     return InvokeAsync(
              mTaskQueue, __func__,
              [self, aTime]() { return self->mTrackDemuxer->Seek(aTime); })
       ->Then(mTaskQueue, __func__,
-             [self]() { self->UpdateRandomAccessPoint(); },
-             [self]() { self->UpdateRandomAccessPoint(); });
+             [self](const TimeUnit& aTime) {
+               self->UpdateRandomAccessPoint();
+               return SeekPromise::CreateAndResolve(aTime, __func__);
+             },
+             [self](const MediaResult& aError) {
+               self->UpdateRandomAccessPoint();
+               return SeekPromise::CreateAndReject(aError, __func__);
+             });
   }
 
   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples) override
   {
     RefPtr<Wrapper> self = this;
     return InvokeAsync(mTaskQueue, __func__,
                        [self, aNumSamples]() {
                          return self->mTrackDemuxer->GetSamples(aNumSamples);
                        })
       ->Then(mTaskQueue, __func__,
-             [self]() { self->UpdateRandomAccessPoint(); },
-             [self]() { self->UpdateRandomAccessPoint(); });
+             [self](RefPtr<SamplesHolder> aSamples) {
+               self->UpdateRandomAccessPoint();
+               return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
+             },
+             [self](const MediaResult& aError) {
+               self->UpdateRandomAccessPoint();
+               return SamplesPromise::CreateAndReject(aError, __func__);
+             });
   }
 
   bool GetSamplesMayBlock() const override
   {
     return mGetSamplesMayBlock;
   }
 
   void Reset() override
@@ -933,18 +946,24 @@ public:
     RefPtr<Wrapper> self = this;
     return InvokeAsync(
              mTaskQueue, __func__,
              [self, aTimeThreshold]()  {
                return self->mTrackDemuxer->SkipToNextRandomAccessPoint(
                  aTimeThreshold);
              })
       ->Then(mTaskQueue, __func__,
-             [self]() { self->UpdateRandomAccessPoint(); },
-             [self]() { self->UpdateRandomAccessPoint(); });
+             [self](uint32_t aVal) {
+               self->UpdateRandomAccessPoint();
+               return SkipAccessPointPromise::CreateAndResolve(aVal, __func__);
+             },
+             [self](const SkipFailureHolder& aError) {
+               self->UpdateRandomAccessPoint();
+               return SkipAccessPointPromise::CreateAndReject(aError, __func__);
+             });
   }
 
   TimeIntervals GetBuffered() override
   {
     MutexAutoLock lock(mMutex);
     return mBuffered;
   }
 
@@ -992,30 +1011,33 @@ private:
     MutexAutoLock lock(mMutex);
     mBuffered = mTrackDemuxer->GetBuffered();
   }
 };
 
 RefPtr<MediaDataDemuxer::InitPromise>
 MediaFormatReader::DemuxerProxy::Init()
 {
+  using InitPromise = MediaDataDemuxer::InitPromise;
+
   RefPtr<Data> data = mData;
   RefPtr<AutoTaskQueue> taskQueue = mTaskQueue;
   return InvokeAsync(mTaskQueue, __func__,
                      [data, taskQueue]() {
                        if (!data->mDemuxer) {
-                         return MediaDataDemuxer::InitPromise::CreateAndReject(
+                         return InitPromise::CreateAndReject(
                            NS_ERROR_DOM_MEDIA_CANCELED, __func__);
                        }
                        return data->mDemuxer->Init();
                      })
     ->Then(taskQueue, __func__,
            [data, taskQueue]() {
              if (!data->mDemuxer) { // Was shutdown.
-               return;
+               return InitPromise::CreateAndReject(
+                   NS_ERROR_DOM_MEDIA_CANCELED, __func__);
              }
              data->mNumAudioTrack =
                data->mDemuxer->GetNumberTracks(TrackInfo::kAudioTrack);
              if (data->mNumAudioTrack) {
                RefPtr<MediaTrackDemuxer> d =
                  data->mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
                if (d) {
                  RefPtr<Wrapper> wrapper =
@@ -1038,18 +1060,21 @@ MediaFormatReader::DemuxerProxy::Init()
              }
              data->mCrypto = data->mDemuxer->GetCrypto();
              data->mSeekable = data->mDemuxer->IsSeekable();
              data->mSeekableOnlyInBufferedRange =
                data->mDemuxer->IsSeekableOnlyInBufferedRanges();
              data->mShouldComputeStartTime =
                data->mDemuxer->ShouldComputeStartTime();
              data->mInitDone = true;
+             return InitPromise::CreateAndResolve(NS_OK, __func__);
            },
-           []() {});
+           [](const MediaResult& aError) {
+             return InitPromise::CreateAndReject(aError, __func__);
+           });
 }
 
 RefPtr<MediaFormatReader::NotifyDataArrivedPromise>
 MediaFormatReader::DemuxerProxy::NotifyDataArrived()
 {
   RefPtr<Data> data = mData;
   return InvokeAsync(mTaskQueue, __func__, [data]() {
     if (!data->mDemuxer) {
@@ -1609,26 +1634,30 @@ MediaFormatReader::OnDemuxFailed(TrackTy
       NotifyError(aTrack, aError);
       break;
   }
 }
 
 void
 MediaFormatReader::DoDemuxVideo()
 {
+  using SamplesPromise = MediaTrackDemuxer::SamplesPromise;
+
   auto p = mVideo.mTrackDemuxer->GetSamples(1);
 
   if (mVideo.mFirstDemuxedSampleTime.isNothing()) {
     RefPtr<MediaFormatReader> self = this;
     p = p->Then(OwnerThread(), __func__,
                 [self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
                   self->OnFirstDemuxCompleted(TrackInfo::kVideoTrack, aSamples);
+                  return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
                 },
                 [self] (const MediaResult& aError) {
                   self->OnFirstDemuxFailed(TrackInfo::kVideoTrack, aError);
+                  return SamplesPromise::CreateAndReject(aError, __func__);
                 });
   }
 
   p->Then(OwnerThread(), __func__, this,
           &MediaFormatReader::OnVideoDemuxCompleted,
           &MediaFormatReader::OnVideoDemuxFailed)
    ->Track(mVideo.mDemuxRequest);
 }
@@ -1682,26 +1711,30 @@ MediaFormatReader::RequestAudioData()
   ScheduleUpdate(TrackInfo::kAudioTrack);
 
   return p;
 }
 
 void
 MediaFormatReader::DoDemuxAudio()
 {
+  using SamplesPromise = MediaTrackDemuxer::SamplesPromise;
+
   auto p = mAudio.mTrackDemuxer->GetSamples(1);
 
   if (mAudio.mFirstDemuxedSampleTime.isNothing()) {
     RefPtr<MediaFormatReader> self = this;
     p = p->Then(OwnerThread(), __func__,
                 [self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
                   self->OnFirstDemuxCompleted(TrackInfo::kAudioTrack, aSamples);
+                  return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
                 },
                 [self] (const MediaResult& aError) {
                   self->OnFirstDemuxFailed(TrackInfo::kAudioTrack, aError);
+                  return SamplesPromise::CreateAndReject(aError, __func__);
                 });
   }
 
   p->Then(OwnerThread(), __func__, this,
           &MediaFormatReader::OnAudioDemuxCompleted,
           &MediaFormatReader::OnAudioDemuxFailed)
    ->Track(mAudio.mDemuxRequest);
 }
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -643,25 +643,27 @@ GeckoMediaPluginServiceParent::AsyncAddP
   nsString dir(aDirectory);
   RefPtr<GeckoMediaPluginServiceParent> self = this;
   return InvokeAsync(
            thread, this, __func__,
            &GeckoMediaPluginServiceParent::AddOnGMPThread, dir)
     ->Then(
       mMainThread,
       __func__,
-      [dir, self]() -> void {
+      [dir, self](bool aVal) {
         LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s succeeded",
               NS_ConvertUTF16toUTF8(dir).get()));
         MOZ_ASSERT(NS_IsMainThread());
         self->UpdateContentProcessGMPCapabilities();
+        return GenericPromise::CreateAndResolve(aVal, __func__);
       },
-      [dir]() -> void {
+      [dir](nsresult aResult) {
         LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s failed",
               NS_ConvertUTF16toUTF8(dir).get()));
+        return GenericPromise::CreateAndReject(aResult, __func__);
       });
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::AddPluginDirectory(const nsAString& aDirectory)
 {
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<GenericPromise> p = AsyncAddPluginDirectory(aDirectory);
@@ -869,25 +871,27 @@ GeckoMediaPluginServiceParent::AddOnGMPT
   RefPtr<GMPParent> gmp = CreateGMPParent(mMainThread);
   if (!gmp) {
     NS_WARNING("Can't Create GMPParent");
     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   RefPtr<GeckoMediaPluginServiceParent> self(this);
   return gmp->Init(this, directory)->Then(thread, __func__,
-    [gmp, self, dir]() -> void {
+    [gmp, self, dir](bool aVal) {
       LOGD(("%s::%s: %s Succeeded", __CLASS__, __FUNCTION__, dir.get()));
       {
         MutexAutoLock lock(self->mMutex);
         self->mPlugins.AppendElement(gmp);
       }
+      return GenericPromise::CreateAndResolve(aVal, __func__);
     },
-    [dir]() -> void {
+    [dir](nsresult aResult) {
       LOGD(("%s::%s: %s Failed", __CLASS__, __FUNCTION__, dir.get()));
+      return GenericPromise::CreateAndReject(aResult, __func__);
     });
 }
 
 void
 GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory,
                                                  const bool aDeleteFromDisk,
                                                  const bool aCanDefer)
 {
--- a/dom/media/gtest/TestMozPromise.cpp
+++ b/dom/media/gtest/TestMozPromise.cpp
@@ -83,17 +83,17 @@ template<typename FunctionType>
 void
 RunOnTaskQueue(TaskQueue* aQueue, FunctionType aFun)
 {
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(aFun);
   aQueue->Dispatch(r.forget());
 }
 
 // std::function can't come soon enough. :-(
-#define DO_FAIL []()->void { EXPECT_TRUE(false); }
+#define DO_FAIL []() { EXPECT_TRUE(false); return TestPromise::CreateAndReject(0, __func__); }
 
 TEST(MozPromise, BasicResolve)
 {
   AutoTaskQueue atq;
   RefPtr<TaskQueue> queue = atq.Queue();
   RunOnTaskQueue(queue, [queue] () -> void {
     TestPromise::CreateAndResolve(42, __func__)->Then(queue, __func__,
       [queue] (int aResolveValue) -> void { EXPECT_EQ(aResolveValue, 42); queue->BeginShutdown(); },
@@ -180,17 +180,21 @@ TEST(MozPromise, CompletionPromises)
   bool invokedPass = false;
   AutoTaskQueue atq;
   RefPtr<TaskQueue> queue = atq.Queue();
   RunOnTaskQueue(queue, [queue, &invokedPass] () -> void {
     TestPromise::CreateAndResolve(40, __func__)
     ->Then(queue, __func__,
       [] (int aVal) -> RefPtr<TestPromise> { return TestPromise::CreateAndResolve(aVal + 10, __func__); },
       DO_FAIL)
-    ->Then(queue, __func__, [&invokedPass] () -> void { invokedPass = true; }, DO_FAIL)
+    ->Then(queue, __func__,
+           [&invokedPass] (int aVal) {
+             invokedPass = true;
+             return TestPromise::CreateAndResolve(aVal, __func__);
+           }, DO_FAIL)
     ->Then(queue, __func__,
       [queue] (int aVal) -> RefPtr<TestPromise> {
         RefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
         nsCOMPtr<nsIRunnable> resolver = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(aVal - 8), 10);
         queue->Dispatch(resolver.forget());
         return RefPtr<TestPromise>(p);
       },
       DO_FAIL)
@@ -217,17 +221,17 @@ TEST(MozPromise, PromiseAllResolve)
     TestPromise::All(queue, promises)->Then(queue, __func__,
       [queue] (const nsTArray<int>& aResolveValues) -> void {
         EXPECT_EQ(aResolveValues.Length(), 3UL);
         EXPECT_EQ(aResolveValues[0], 22);
         EXPECT_EQ(aResolveValues[1], 32);
         EXPECT_EQ(aResolveValues[2], 42);
         queue->BeginShutdown();
       },
-      DO_FAIL
+      []() { EXPECT_TRUE(false); }
     );
   });
 }
 
 TEST(MozPromise, PromiseAllReject)
 {
   AutoTaskQueue atq;
   RefPtr<TaskQueue> queue = atq.Queue();
@@ -236,17 +240,17 @@ TEST(MozPromise, PromiseAllReject)
     nsTArray<RefPtr<TestPromise>> promises;
     promises.AppendElement(TestPromise::CreateAndResolve(22, __func__));
     promises.AppendElement(TestPromise::CreateAndReject(32.0, __func__));
     promises.AppendElement(TestPromise::CreateAndResolve(42, __func__));
    // Ensure that more than one rejection doesn't cause a crash (bug #1207312)
     promises.AppendElement(TestPromise::CreateAndReject(52.0, __func__));
 
     TestPromise::All(queue, promises)->Then(queue, __func__,
-      DO_FAIL,
+      []() { EXPECT_TRUE(false); },
       [queue] (float aRejectValue) -> void {
         EXPECT_EQ(aRejectValue, 32.0);
         queue->BeginShutdown();
       }
     );
   });
 }
 
@@ -260,18 +264,21 @@ TEST(MozPromise, Chaining)
 
   RunOnTaskQueue(queue, [queue, &holder] () {
     auto p = TestPromise::CreateAndResolve(42, __func__);
     const size_t kIterations = 100;
     for (size_t i = 0; i < kIterations; ++i) {
       p = p->Then(queue, __func__,
         [] (int aVal) {
           EXPECT_EQ(aVal, 42);
+          return TestPromise::CreateAndResolve(aVal, __func__);
         },
-        [] () {}
+        [] (double aVal) {
+          return TestPromise::CreateAndReject(aVal, __func__);
+        }
       );
 
       if (i == kIterations / 2) {
         p->Then(queue, __func__,
           [queue, &holder] () {
             holder.Disconnect();
             queue->BeginShutdown();
           },
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -168,18 +168,22 @@ public:
     mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
     mThroughputLimiter.Flush();
     for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) {
       nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data();
       holder->DisconnectIfExists();
       iter.Remove();
     }
     RefPtr<SamplesWaitingForKey> k = mSamplesWaitingForKey;
-    return mDecoder->Flush()->Then(mTaskQueue, __func__,
-                                   [k]() { k->Flush(); });
+    return mDecoder->Flush()->Then(
+      mTaskQueue, __func__,
+      [k]() {
+        k->Flush();
+        return FlushPromise::CreateAndResolve(true, __func__);
+      });
   }
 
   RefPtr<DecodePromise> Drain() override
   {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
     MOZ_ASSERT(mDecodePromise.IsEmpty() && !mDecodeRequest.Exists(),
                "Must wait for decoding to complete");
--- a/dom/media/platforms/omx/OmxDataDecoder.cpp
+++ b/dom/media/platforms/omx/OmxDataDecoder.cpp
@@ -236,18 +236,19 @@ OmxDataDecoder::DoAsyncShutdown()
   // Flush to all ports, so all buffers can be returned from component.
   RefPtr<OmxDataDecoder> self = this;
   mOmxLayer->SendCommand(OMX_CommandFlush, OMX_ALL, nullptr)
     ->Then(mOmxTaskQueue, __func__,
            [self] () -> RefPtr<OmxCommandPromise> {
              LOGL("DoAsyncShutdown: flush complete");
              return self->mOmxLayer->SendCommand(OMX_CommandStateSet, OMX_StateIdle, nullptr);
            },
-           [self] () {
+           [self] (const OmxCommandFailureHolder& aError) {
              self->mOmxLayer->Shutdown();
+             return OmxCommandPromise::CreateAndReject(aError, __func__);
            })
     ->Then(mOmxTaskQueue, __func__,
            [self] () -> RefPtr<OmxCommandPromise> {
              RefPtr<OmxCommandPromise> p =
                self->mOmxLayer->SendCommand(OMX_CommandStateSet, OMX_StateLoaded, nullptr);
 
              // According to spec 3.1.1.2.2.1:
              // OMX_StateLoaded needs to be sent before releasing buffers.
@@ -258,18 +259,19 @@ OmxDataDecoder::DoAsyncShutdown()
              // in layer, it needs to wait before the layer returns the
              // buffers.
              LOGL("DoAsyncShutdown: releasing buffers...");
              self->ReleaseBuffers(OMX_DirInput);
              self->ReleaseBuffers(OMX_DirOutput);
 
              return p;
            },
-           [self] () {
+           [self] (const OmxCommandFailureHolder& aError) {
              self->mOmxLayer->Shutdown();
+             return OmxCommandPromise::CreateAndReject(aError, __func__);
            })
     ->Then(mOmxTaskQueue, __func__,
            [self] () {
              LOGL("DoAsyncShutdown: OMX_StateLoaded, it is safe to shutdown omx");
              self->mOmxLayer->Shutdown();
              self->mWatchManager.Shutdown();
              self->mOmxLayer = nullptr;
              self->mMediaDataHelper = nullptr;
@@ -781,18 +783,19 @@ OmxDataDecoder::PortSettingsChanged()
                // Allocate new port buffers.
                nsresult rv = self->AllocateBuffers(def.eDir);
                if (NS_FAILED(rv)) {
                  self->NotifyError(OMX_ErrorUndefined, __func__);
                }
 
                return p;
              },
-             [self] () {
+             [self] (const OmxCommandFailureHolder& aError) {
                self->NotifyError(OMX_ErrorUndefined, __func__);
+               return OmxCommandPromise::CreateAndReject(aError, __func__);
              })
       ->Then(mOmxTaskQueue, __func__,
              [self] () {
                LOGL("PortSettingsChanged: port settings changed complete");
                // finish port setting changed.
                self->mPortSettingsChanged = -1;
                self->FillAndEmptyBuffers();
              },