Bug 1315850 - Implement CDM video decoder flush. r=jya
MozReview-Commit-ID: 3CzwfOCXGP
--- 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__);