Bug 1315850 - Implement CDM video decoder flush. r=jya draft
authorChris Pearce <cpearce@mozilla.com>
Tue, 14 Feb 2017 22:42:26 +1300
changeset 504174 8ee1ae28a36779484717c6b105ef7730dd1896b3
parent 504173 b7f162515a1a32b2c344c11d0fa5c7004cec2e15
child 504175 3f9636503523f0c6effab15fa89cce25a961a0b4
push id50748
push userbmo:cpearce@mozilla.com
push dateFri, 24 Mar 2017 01:10:17 +0000
reviewersjya
bugs1315850
milestone55.0a1
Bug 1315850 - Implement CDM video decoder flush. r=jya MozReview-Commit-ID: 3CzwfOCXGP
dom/media/gmp/ChromiumCDMChild.cpp
dom/media/gmp/ChromiumCDMParent.cpp
dom/media/gmp/ChromiumCDMParent.h
dom/media/gmp/PChromiumCDM.ipdl
dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.cpp
--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -454,16 +454,17 @@ ChromiumCDMChild::RecvDeinitializeVideoD
 mozilla::ipc::IPCResult
 ChromiumCDMChild::RecvResetVideoDecoder()
 {
   MOZ_ASSERT(IsOnMessageLoopThread());
   GMP_LOG("ChromiumCDMChild::RecvResetVideoDecoder()");
   if (mDecoderInitialized) {
     mCDM->ResetDecoder(cdm::kStreamTypeVideo);
   }
+  Unused << SendResetVideoDecoderComplete();
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ChromiumCDMChild::RecvDecryptAndDecodeFrame(const CDMInputBuffer& aBuffer)
 {
   MOZ_ASSERT(IsOnMessageLoopThread());
   GMP_LOG("ChromiumCDMChild::RecvDecryptAndDecodeFrame()");
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -440,16 +440,19 @@ ChromiumCDMParent::RecvDecrypted(const u
     }
   }
   return IPC_OK();
 }
 
 ipc::IPCResult
 ChromiumCDMParent::RecvDecoded(const CDMVideoFrame& aFrame)
 {
+  if (mDecodePromise.IsEmpty()) {
+    return IPC_OK();
+  }
   VideoData::YCbCrBuffer b;
   nsTArray<uint8_t> data;
   data = aFrame.mData();
 
   if (data.IsEmpty()) {
     mDecodePromise.ResolveIfExists(nsTArray<RefPtr<MediaData>>(), __func__);
     return IPC_OK();
   }
@@ -581,10 +584,29 @@ ChromiumCDMParent::DecryptAndDecodeFrame
       MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                   "Failed to send decrypt to CDM process."),
       __func__);
   }
 
   return mDecodePromise.Ensure(__func__);
 }
 
+RefPtr<MediaDataDecoder::FlushPromise>
+ChromiumCDMParent::FlushVideoDecoder()
+{
+  mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
+  if (!SendResetVideoDecoder()) {
+    return MediaDataDecoder::FlushPromise::CreateAndReject(
+      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "Failed to send flush to CDM."),
+      __func__);
+  }
+  return mFlushDecoderPromise.Ensure(__func__);
+}
+
+ipc::IPCResult
+ChromiumCDMParent::RecvResetVideoDecoderComplete()
+{
+  mFlushDecoderPromise.Resolve(true, __func__);
+  return IPC_OK();
+}
+
 } // namespace gmp
 } // namespace mozilla
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -64,16 +64,18 @@ public:
   RefPtr<MediaDataDecoder::InitPromise> InitializeVideoDecoder(
     const gmp::CDMVideoDecoderConfig& aConfig,
     const VideoInfo& aInfo,
     RefPtr<layers::ImageContainer> aImageContainer);
 
   RefPtr<MediaDataDecoder::DecodePromise> DecryptAndDecodeFrame(
     MediaRawData* aSample);
 
+  RefPtr<MediaDataDecoder::FlushPromise> FlushVideoDecoder();
+
 protected:
   ~ChromiumCDMParent() {}
 
   ipc::IPCResult Recv__delete__() override;
   ipc::IPCResult RecvOnResolveNewSessionPromise(
     const uint32_t& aPromiseId,
     const nsCString& aSessionId) override;
   ipc::IPCResult RecvOnResolvePromise(const uint32_t& aPromiseId) override;
@@ -97,16 +99,17 @@ protected:
                                           const nsCString& aMessage) override;
   ipc::IPCResult RecvDecrypted(const uint32_t& aId,
                                const uint32_t& aStatus,
                                nsTArray<uint8_t>&& aData) override;
   ipc::IPCResult RecvOnDecoderInitDone(const uint32_t& aStatus) override;
   ipc::IPCResult RecvDecoded(const CDMVideoFrame& aFrame) override;
   ipc::IPCResult RecvDecodeFailed(const uint32_t& aStatus) override;
   ipc::IPCResult RecvShutdown() override;
+  ipc::IPCResult RecvResetVideoDecoderComplete() override;
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void RejectPromise(uint32_t aPromiseId,
                      nsresult aError,
                      const nsCString& aErrorMessage);
 
   void ResolvePromise(uint32_t aPromiseId);
 
@@ -120,14 +123,16 @@ protected:
   nsTArray<RefPtr<DecryptJob>> mDecrypts;
 
   MozPromiseHolder<MediaDataDecoder::InitPromise> mInitVideoDecoderPromise;
   MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
 
   RefPtr<layers::ImageContainer> mImageContainer;
   VideoInfo mVideoInfo;
   uint64_t mLastStreamOffset = 0;
+
+  MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushDecoderPromise;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // ChromiumCDMParent_h_
--- a/dom/media/gmp/PChromiumCDM.ipdl
+++ b/dom/media/gmp/PChromiumCDM.ipdl
@@ -82,13 +82,15 @@ parent:
   async Decrypted(uint32_t aId, uint32_t aStatus, uint8_t[] aData);
 
   async OnDecoderInitDone(uint32_t aStatus);
 
   // Return values of cdm::ContentDecryptionModule8::DecryptAndDecodeFrame
   async Decoded(CDMVideoFrame aFrame);
   async DecodeFailed(uint32_t aStatus);
 
+  async ResetVideoDecoderComplete();
+
   async Shutdown();
 };
 
 } // namespace gmp
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.cpp
+++ b/dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.cpp
@@ -112,19 +112,20 @@ ChromiumCDMVideoDecoder::Decode(MediaRaw
   return InvokeAsync(mGMPThread, __func__, [cdm, sample]() {
     return cdm->DecryptAndDecodeFrame(sample);
   });
 }
 
 RefPtr<MediaDataDecoder::FlushPromise>
 ChromiumCDMVideoDecoder::Flush()
 {
-  return FlushPromise::CreateAndReject(
-    MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, RESULT_DETAIL("Unimplemented")),
-    __func__);
+  MOZ_ASSERT(mCDMParent);
+  RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
+  return InvokeAsync(
+    mGMPThread, __func__, [cdm]() { return cdm->FlushVideoDecoder(); });
 }
 
 RefPtr<MediaDataDecoder::DecodePromise>
 ChromiumCDMVideoDecoder::Drain()
 {
   return DecodePromise::CreateAndReject(
     MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, RESULT_DETAIL("Unimplemented")),
     __func__);