--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -13,85 +13,94 @@
#include "base/time.h"
namespace mozilla {
namespace gmp {
ChromiumCDMChild::ChromiumCDMChild(GMPContentChild* aPlugin)
: mPlugin(aPlugin)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
}
void
ChromiumCDMChild::Init(cdm::ContentDecryptionModule_8* aCDM)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
mCDM = aCDM;
MOZ_ASSERT(mCDM);
}
void
ChromiumCDMChild::TimerExpired(void* aContext)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::TimerExpired(context=0x%p)", aContext);
if (mCDM) {
mCDM->TimerExpired(aContext);
}
}
cdm::Buffer*
ChromiumCDMChild::Allocate(uint32_t aCapacity)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::Allocate(capacity=%" PRIu32 ")", aCapacity);
return new WidevineBuffer(aCapacity);
}
void
ChromiumCDMChild::SetTimer(int64_t aDelayMs, void* aContext)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::SetTimer(delay=%" PRId64 ", context=0x%p)",
aDelayMs,
aContext);
RefPtr<ChromiumCDMChild> self(this);
SetTimerOnMainThread(NewGMPTask([self, aContext]() {
self->TimerExpired(aContext);
}), aDelayMs);
}
cdm::Time
ChromiumCDMChild::GetCurrentWallTime()
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
return base::Time::Now().ToDoubleT();
}
void
ChromiumCDMChild::OnResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdSize)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%" PRIu32
", sid=%s)",
aPromiseId,
aSessionId);
Unused << SendOnResolveNewSessionPromise(aPromiseId,
nsCString(aSessionId, aSessionIdSize));
}
void ChromiumCDMChild::OnResolvePromise(uint32_t aPromiseId)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnResolvePromise(pid=%" PRIu32 ")", aPromiseId);
Unused << SendOnResolvePromise(aPromiseId);
}
void
ChromiumCDMChild::OnRejectPromise(uint32_t aPromiseId,
cdm::Error aError,
uint32_t aSystemCode,
const char* aErrorMessage,
uint32_t aErrorMessageSize)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnRejectPromise(pid=%" PRIu32 ", err=%" PRIu32
" code=%" PRIu32 ", msg='%s')",
aPromiseId,
aError,
aSystemCode,
aErrorMessage);
Unused << SendOnRejectPromise(aPromiseId,
static_cast<uint32_t>(aError),
@@ -103,16 +112,17 @@ void
ChromiumCDMChild::OnSessionMessage(const char* aSessionId,
uint32_t aSessionIdSize,
cdm::MessageType aMessageType,
const char* aMessage,
uint32_t aMessageSize,
const char* aLegacyDestinationUrl,
uint32_t aLegacyDestinationUrlLength)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnSessionMessage(sid=%s, type=%" PRIu32
" size=%" PRIu32 ")",
aSessionId,
aMessageType,
aMessageSize);
nsTArray<uint8_t> message;
message.AppendElements(aMessage, aMessageSize);
Unused << SendOnSessionMessage(nsCString(aSessionId, aSessionIdSize),
@@ -142,16 +152,17 @@ ToString(const cdm::KeyInformation* aKey
void
ChromiumCDMChild::OnSessionKeysChange(const char *aSessionId,
uint32_t aSessionIdSize,
bool aHasAdditionalUsableKey,
const cdm::KeyInformation* aKeysInfo,
uint32_t aKeysInfoCount)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnSessionKeysChange(sid=%s) keys={%s}",
aSessionId,
ToString(aKeysInfo, aKeysInfoCount).get());
nsTArray<CDMKeyInformation> keys;
keys.SetCapacity(aKeysInfoCount);
for (uint32_t i = 0; i < aKeysInfoCount; i++) {
const cdm::KeyInformation& key = aKeysInfo[i];
@@ -163,76 +174,88 @@ ChromiumCDMChild::OnSessionKeysChange(co
keys);
}
void
ChromiumCDMChild::OnExpirationChange(const char* aSessionId,
uint32_t aSessionIdSize,
cdm::Time aNewExpiryTime)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnExpirationChange(sid=%s, time=%lf)",
aSessionId,
aNewExpiryTime);
Unused << SendOnExpirationChange(nsCString(aSessionId, aSessionIdSize),
aNewExpiryTime);
}
void
ChromiumCDMChild::OnSessionClosed(const char* aSessionId,
uint32_t aSessionIdSize)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnSessionClosed(sid=%s)", aSessionId);
Unused << SendOnSessionClosed(nsCString(aSessionId, aSessionIdSize));
}
void
ChromiumCDMChild::OnLegacySessionError(const char* aSessionId,
uint32_t aSessionIdLength,
cdm::Error aError,
uint32_t aSystemCode,
const char* aErrorMessage,
uint32_t aErrorMessageLength)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnLegacySessionError(sid=%s, error=%" PRIu32
" msg='%s')",
aSessionId,
aError,
aErrorMessage);
Unused << SendOnLegacySessionError(
nsCString(aSessionId, aSessionIdLength),
static_cast<uint32_t>(aError),
aSystemCode,
nsCString(aErrorMessage, aErrorMessageLength));
}
cdm::FileIO*
ChromiumCDMChild::CreateFileIO(cdm::FileIOClient * aClient)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::CreateFileIO()");
return nullptr;
}
+bool
+ChromiumCDMChild::IsOnMessageLoopThread()
+{
+ return mPlugin && mPlugin->GMPMessageLoop() == MessageLoop::current();
+}
+
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvInit(const bool& aAllowDistinctiveIdentifier,
const bool& aAllowPersistentState)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvInit(distinctiveId=%d, persistentState=%d)",
aAllowDistinctiveIdentifier,
aAllowPersistentState);
if (mCDM) {
mCDM->Initialize(aAllowDistinctiveIdentifier, aAllowPersistentState);
}
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvSetServerCertificate(const uint32_t& aPromiseId,
nsTArray<uint8_t>&& aServerCert)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvSetServerCertificate() certlen=%zu",
aServerCert.Length());
if (mCDM) {
mCDM->SetServerCertificate(aPromiseId,
aServerCert.Elements(),
aServerCert.Length());
}
return IPC_OK();
@@ -240,16 +263,17 @@ ChromiumCDMChild::RecvSetServerCertifica
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvCreateSessionAndGenerateRequest(
const uint32_t& aPromiseId,
const uint32_t& aSessionType,
const uint32_t& aInitDataType,
nsTArray<uint8_t>&& aInitData)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvCreateSessionAndGenerateRequest("
"pid=%" PRIu32 ", sessionType=%" PRIu32 ", initDataType=%" PRIu32
") initDataLen=%zu",
aPromiseId,
aSessionType,
aInitDataType,
aInitData.Length());
MOZ_ASSERT(aSessionType <= cdm::SessionType::kPersistentKeyRelease);
@@ -264,16 +288,17 @@ ChromiumCDMChild::RecvCreateSessionAndGe
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvUpdateSession(const uint32_t& aPromiseId,
const nsCString& aSessionId,
nsTArray<uint8_t>&& aResponse)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvUpdateSession(pid=%" PRIu32
", sid=%s) responseLen=%zu",
aPromiseId,
aSessionId.get(),
aResponse.Length());
if (mCDM) {
mCDM->UpdateSession(aPromiseId,
aSessionId.get(),
@@ -283,41 +308,44 @@ ChromiumCDMChild::RecvUpdateSession(cons
}
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvCloseSession(const uint32_t& aPromiseId,
const nsCString& aSessionId)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvCloseSession(pid=%" PRIu32 ", sid=%s)",
aPromiseId,
aSessionId.get());
if (mCDM) {
mCDM->CloseSession(aPromiseId, aSessionId.get(), aSessionId.Length());
}
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvRemoveSession(const uint32_t& aPromiseId,
const nsCString& aSessionId)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvRemoveSession(pid=%" PRIu32 ", sid=%s)",
aPromiseId,
aSessionId.get());
if (mCDM) {
mCDM->RemoveSession(aPromiseId, aSessionId.get(), aSessionId.Length());
}
return IPC_OK();
}
void
ChromiumCDMChild::DecryptFailed(uint32_t aId, cdm::Status aStatus)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
Unused << SendDecrypted(aId, aStatus, nsTArray<uint8_t>());
}
static void
InitInputBuffer(const CDMInputBuffer& aBuffer,
nsTArray<cdm::SubsampleEntry>& aSubSamples,
cdm::InputBuffer& aInputBuffer)
{
@@ -341,16 +369,17 @@ InitInputBuffer(const CDMInputBuffer& aB
}
aInputBuffer.timestamp = aBuffer.mTimestamp();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDecrypt(const uint32_t& aId,
const CDMInputBuffer& aBuffer)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDecrypt()");
if (!mCDM) {
GMP_LOG("ChromiumCDMChild::RecvDecrypt() no CDM");
DecryptFailed(aId, cdm::kDecryptError);
return IPC_OK();
}
if (aBuffer.mClearBytes().Length() != aBuffer.mCipherBytes().Length()) {
GMP_LOG("ChromiumCDMChild::RecvDecrypt() clear/cipher bytes length doesn't "
@@ -384,46 +413,76 @@ ChromiumCDMChild::RecvDecrypt(const uint
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvInitializeVideoDecoder(
const CDMVideoDecoderConfig& aConfig)
{
- GMP_LOG("ChromiumCDMChild::RecvInitializeVideoDecoder()");
+ MOZ_ASSERT(IsOnMessageLoopThread());
+ MOZ_ASSERT(!mDecoderInitialized);
+ cdm::VideoDecoderConfig config;
+ config.codec =
+ static_cast<cdm::VideoDecoderConfig::VideoCodec>(aConfig.mCodec());
+ config.profile =
+ static_cast<cdm::VideoDecoderConfig::VideoCodecProfile>(aConfig.mProfile());
+ config.format = static_cast<cdm::VideoFormat>(aConfig.mFormat());
+ config.coded_size = { aConfig.mImageWidth(), aConfig.mImageHeight() };
+ nsTArray<uint8_t> extraData(aConfig.mExtraData());
+ config.extra_data = extraData.Elements();
+ config.extra_data_size = extraData.Length();
+ cdm::Status status = mCDM->InitializeVideoDecoder(config);
+ GMP_LOG("ChromiumCDMChild::RecvInitializeVideoDecoder() status=%u", status);
+ Unused << SendOnDecoderInitDone(status);
+ mDecoderInitialized = status == cdm::kSuccess;
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDeinitializeVideoDecoder()
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDeinitializeVideoDecoder()");
+ MOZ_ASSERT(mDecoderInitialized);
+ if (mDecoderInitialized) {
+ mDecoderInitialized = false;
+ mCDM->DeinitializeDecoder(cdm::kStreamTypeVideo);
+ }
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvResetVideoDecoder()
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvResetVideoDecoder()");
+ if (mDecoderInitialized) {
+ mCDM->ResetDecoder(cdm::kStreamTypeVideo);
+ }
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDecryptAndDecodeFrame(const CDMInputBuffer& aBuffer)
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDecryptAndDecodeFrame()");
+ MOZ_ASSERT(mDecoderInitialized);
return IPC_OK();
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDestroy()
{
+ MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDestroy()");
+ MOZ_ASSERT(!mDecoderInitialized);
+
if (mCDM) {
mCDM->Destroy();
mCDM = nullptr;
}
Unused << Send__delete__(this);
return IPC_OK();
--- a/dom/media/gmp/ChromiumCDMChild.h
+++ b/dom/media/gmp/ChromiumCDMChild.h
@@ -69,16 +69,18 @@ public:
void EnableOutputProtection(uint32_t aDesiredProtectionMask) override {}
void QueryOutputProtectionStatus() override {}
void OnDeferredInitializationDone(cdm::StreamType aStreamType,
cdm::Status aDecoderStatus) override {}
cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override;
protected:
~ChromiumCDMChild() {}
+ bool IsOnMessageLoopThread();
+
ipc::IPCResult RecvInit(const bool& aAllowDistinctiveIdentifier,
const bool& aAllowPersistentState) override;
ipc::IPCResult RecvSetServerCertificate(
const uint32_t& aPromiseId,
nsTArray<uint8_t>&& aServerCert) override;
ipc::IPCResult RecvCreateSessionAndGenerateRequest(
const uint32_t& aPromiseId,
const uint32_t& aSessionType,
@@ -100,14 +102,16 @@ protected:
ipc::IPCResult RecvDecryptAndDecodeFrame(
const CDMInputBuffer& aBuffer) override;
ipc::IPCResult RecvDestroy() override;
void DecryptFailed(uint32_t aId, cdm::Status aStatus);
GMPContentChild* mPlugin = nullptr;
cdm::ContentDecryptionModule_8* mCDM = nullptr;
+
+ bool mDecoderInitialized = false;
};
} // namespace gmp
} // namespace mozilla
#endif // ChromiumCDMChild_h_
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -463,10 +463,42 @@ ChromiumCDMParent::RecvShutdown()
}
void
ChromiumCDMParent::ActorDestroy(ActorDestroyReason aWhy)
{
GMP_LOG("ChromiumCDMParent::ActorDestroy(this=%p, reason=%d)", this, aWhy);
}
+RefPtr<MediaDataDecoder::InitPromise>
+ChromiumCDMParent::InitializeVideoDecoder(
+ const gmp::CDMVideoDecoderConfig& aConfig)
+{
+ if (!SendInitializeVideoDecoder(aConfig)) {
+ return MediaDataDecoder::InitPromise::CreateAndReject(
+ MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Failed to send init video decoder to CDM")),
+ __func__);
+ }
+
+ return mInitVideoDecoderPromise.Ensure(__func__);
+}
+
+ipc::IPCResult
+ChromiumCDMParent::RecvOnDecoderInitDone(const uint32_t& aStatus)
+{
+ GMP_LOG("ChromiumCDMParent::RecvOnDecoderInitDone(this=%p, status=%u)",
+ this,
+ aStatus);
+ if (aStatus == static_cast<uint32_t>(cdm::kSuccess)) {
+ mInitVideoDecoderPromise.ResolveIfExists(TrackInfo::kVideoTrack, __func__);
+ } else {
+ mInitVideoDecoderPromise.RejectIfExists(
+ MediaResult(
+ NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("CDM init decode failed with %" PRIu32, aStatus)),
+ __func__);
+ }
+ return IPC_OK();
+}
+
} // namespace gmp
} // namespace mozilla
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -1,23 +1,24 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef ChromiumCDMParent_h_
#define ChromiumCDMParent_h_
+#include "DecryptJob.h"
#include "GMPCrashHelper.h"
#include "GMPCrashHelperHolder.h"
#include "GMPMessageUtils.h"
#include "mozilla/gmp/PChromiumCDMParent.h"
#include "mozilla/RefPtr.h"
#include "nsDataHashtable.h"
-#include "DecryptJob.h"
+#include "PlatformDecoderModule.h"
namespace mozilla {
class MediaRawData;
class ChromiumCDMProxy;
namespace gmp {
@@ -54,16 +55,18 @@ public:
void CloseSession(const nsCString& aSessionId, uint32_t aPromiseId);
void RemoveSession(const nsCString& aSessionId, uint32_t aPromiseId);
RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample);
// TODO: Add functions for clients to send data to CDM, and
// a Close() function.
+ RefPtr<MediaDataDecoder::InitPromise> InitializeVideoDecoder(
+ const gmp::CDMVideoDecoderConfig& aConfig);
protected:
~ChromiumCDMParent() {}
ipc::IPCResult Recv__delete__() override;
ipc::IPCResult RecvOnResolveNewSessionPromise(
const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
@@ -84,16 +87,17 @@ protected:
ipc::IPCResult RecvOnSessionClosed(const nsCString& aSessionId) override;
ipc::IPCResult RecvOnLegacySessionError(const nsCString& aSessionId,
const uint32_t& aError,
const uint32_t& aSystemCode,
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;
void ActorDestroy(ActorDestroyReason aWhy) override;
void RejectPromise(uint32_t aPromiseId,
nsresult aError,
const nsCString& aErrorMessage);
@@ -103,14 +107,16 @@ protected:
const uint32_t mPluginId;
GMPContentParent* mContentParent;
// Note: this pointer is a weak reference because otherwise it would cause
// a cycle, as ChromiumCDMProxy has a strong reference to the
// ChromiumCDMParent.
ChromiumCDMProxy* mProxy = nullptr;
nsDataHashtable<nsUint32HashKey, uint32_t> mPromiseToCreateSessionToken;
nsTArray<RefPtr<DecryptJob>> mDecrypts;
+
+ MozPromiseHolder<MediaDataDecoder::InitPromise> mInitVideoDecoderPromise;
};
} // namespace gmp
} // namespace mozilla
#endif // ChromiumCDMParent_h_
--- a/dom/media/gmp/PChromiumCDM.ipdl
+++ b/dom/media/gmp/PChromiumCDM.ipdl
@@ -76,16 +76,18 @@ parent:
async OnLegacySessionError(nsCString aSessionId,
uint32_t aError,
uint32_t aSystemCode,
nsCString aMessage);
// Return values of cdm::ContentDecryptionModule8::Decrypt
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 Shutdown();
};
} // namespace gmp
--- a/dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.cpp
+++ b/dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.cpp
@@ -1,38 +1,95 @@
/* -*- 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/. */
#include "ChromiumCDMVideoDecoder.h"
+#include "ChromiumCDMProxy.h"
+#include "content_decryption_module.h"
#include "GMPService.h"
#include "GMPVideoDecoder.h"
+#include "MP4Decoder.h"
+#include "VPXDecoder.h"
namespace mozilla {
ChromiumCDMVideoDecoder::ChromiumCDMVideoDecoder(
const GMPVideoDecoderParams& aParams,
CDMProxy* aCDMProxy)
- : mConfig(aParams.mConfig)
+ : mCDMParent(aCDMProxy->AsChromiumCDMProxy()->GetCDMParent())
+ , mConfig(aParams.mConfig)
, mCrashHelper(aParams.mCrashHelper)
, mGMPThread(GetGMPAbstractThread())
, mImageContainer(aParams.mImageContainer)
{
}
ChromiumCDMVideoDecoder::~ChromiumCDMVideoDecoder()
{
}
+static uint32_t
+ToCDMH264Profile(uint8_t aProfile)
+{
+ switch (aProfile) {
+ case 66:
+ return cdm::VideoDecoderConfig::kH264ProfileBaseline;
+ case 77:
+ return cdm::VideoDecoderConfig::kH264ProfileMain;
+ case 88:
+ return cdm::VideoDecoderConfig::kH264ProfileExtended;
+ case 100:
+ return cdm::VideoDecoderConfig::kH264ProfileHigh;
+ case 110:
+ return cdm::VideoDecoderConfig::kH264ProfileHigh10;
+ case 122:
+ return cdm::VideoDecoderConfig::kH264ProfileHigh422;
+ case 144:
+ return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
+ }
+ return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
+}
+
RefPtr<MediaDataDecoder::InitPromise>
ChromiumCDMVideoDecoder::Init()
{
- return InitPromise::CreateAndResolve(TrackInfo::kUndefinedTrack, __func__);
+ if (!mCDMParent) {
+ // Must have failed to get the CDMParent from the ChromiumCDMProxy
+ // in our constructor; the MediaKeys must have shut down the CDM
+ // before we had a chance to start up the decoder.
+ return InitPromise::CreateAndReject(
+ NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
+ }
+
+ gmp::CDMVideoDecoderConfig config;
+ if (MP4Decoder::IsH264(mConfig.mMimeType)) {
+ config.mCodec() = cdm::VideoDecoderConfig::kCodecH264;
+ config.mProfile() =
+ ToCDMH264Profile(mConfig.mExtraData->SafeElementAt(1, 0));
+ config.mExtraData() = *mConfig.mExtraData;
+ } else if (VPXDecoder::IsVP8(mConfig.mMimeType)) {
+ config.mCodec() = cdm::VideoDecoderConfig::kCodecVp8;
+ config.mProfile() = cdm::VideoDecoderConfig::kProfileNotNeeded;
+ } else if (VPXDecoder::IsVP9(mConfig.mMimeType)) {
+ config.mCodec() = cdm::VideoDecoderConfig::kCodecVp9;
+ config.mProfile() = cdm::VideoDecoderConfig::kProfileNotNeeded;
+ } else {
+ return MediaDataDecoder::InitPromise::CreateAndReject(
+ NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
+ }
+ config.mImageWidth() = mConfig.mImage.width;
+ config.mImageHeight() = mConfig.mImage.height;
+
+ RefPtr<gmp::ChromiumCDMParent> cdm = mCDMParent;
+ return InvokeAsync(mGMPThread, __func__, [cdm, config]() {
+ return cdm->InitializeVideoDecoder(config);
+ });
}
RefPtr<MediaDataDecoder::DecodePromise>
ChromiumCDMVideoDecoder::Decode(MediaRawData* aSample)
{
return DecodePromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, RESULT_DETAIL("Unimplemented")),
__func__);
--- a/dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.h
+++ b/dom/media/platforms/agnostic/eme/ChromiumCDMVideoDecoder.h
@@ -3,16 +3,17 @@
/* 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/. */
#ifndef ChromiumCDMVideoDecoder_h_
#define ChromiumCDMVideoDecoder_h_
#include "PlatformDecoderModule.h"
+#include "ChromiumCDMParent.h"
namespace mozilla {
class CDMProxy;
struct GMPVideoDecoderParams;
class ChromiumCDMVideoDecoder : public MediaDataDecoder
{
@@ -28,16 +29,17 @@ public:
const char* GetDescriptionName() const override
{
return "Chromium CDM video decoder";
}
private:
~ChromiumCDMVideoDecoder();
+ RefPtr<gmp::ChromiumCDMParent> mCDMParent;
const VideoInfo mConfig;
RefPtr<GMPCrashHelper> mCrashHelper;
RefPtr<AbstractThread> mGMPThread;
RefPtr<layers::ImageContainer> mImageContainer;
MozPromiseHolder<InitPromise> mInitPromise;
};
} // mozilla