From 89c1dfed1699bb2972ba1bbc6351f42aeab559d8 Mon Sep 17 00:00:00 2001 From: alwu Date: Tue, 24 Oct 2023 23:18:01 +0000 Subject: [PATCH] Bug 1844169 - part6 : map normal Widevine key system to Widevine experiment key system. r=jolin Our EME system works like this, First, the content process stores some cached capabilities for different key systems, which tells what codecs they support, and whether hw decryption works or not. Then in the content process, we would compare those capabilies to the one that website requests by using EME API, to see if that is any matching. What this patch is going to do is, if website uses `com.widevine.alpha` with hardware decryption request, then we would check those experiment key system to see if they support (because they are used for hardware decryption only). Therefore, we would be able to support two cases for hardware decryption, (1) use experiment key system explicitly (2) use normal key system but requests an explicit robustness for hardware decryption [1]. [1] Example test page (you can add robustness on setting) https://integration.widevine.com/player Differential Revision: https://phabricator.services.mozilla.com/D190639 --- dom/media/eme/CDMProxy.h | 2 ++ dom/media/eme/EMEUtils.cpp | 19 ++++++++++++++ dom/media/eme/EMEUtils.h | 5 ++++ dom/media/eme/KeySystemConfig.cpp | 12 +++++++++ dom/media/eme/KeySystemConfig.h | 4 +++ dom/media/eme/MediaKeySystemAccess.cpp | 7 +++++- dom/media/eme/MediaKeys.cpp | 8 ++++-- dom/media/eme/mediafoundation/WMFCDMProxy.cpp | 7 ++++++ dom/media/eme/mediafoundation/WMFCDMProxy.h | 2 ++ dom/media/ipc/MFCDMParent.cpp | 25 +++++++++++++------ dom/media/platforms/PDMFactory.cpp | 4 ++- 11 files changed, 84 insertions(+), 11 deletions(-) diff --git a/dom/media/eme/CDMProxy.h b/dom/media/eme/CDMProxy.h index e638be335895..db72eeb4b7fb 100644 --- a/dom/media/eme/CDMProxy.h +++ b/dom/media/eme/CDMProxy.h @@ -253,6 +253,8 @@ class CDMProxy { virtual WMFCDMProxy* AsWMFCDMProxy() { return nullptr; } #endif + virtual bool IsHardwareDecryptionSupported() const { return false; } + protected: // Main thread only. CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem, diff --git a/dom/media/eme/EMEUtils.cpp b/dom/media/eme/EMEUtils.cpp index 39dd61602bf8..c60989189965 100644 --- a/dom/media/eme/EMEUtils.cpp +++ b/dom/media/eme/EMEUtils.cpp @@ -109,4 +109,23 @@ const char* ToMediaKeyStatusStr(dom::MediaKeyStatus aStatus) { #undef ENUM_TO_STR +bool IsHardwareDecryptionSupported( + const dom::MediaKeySystemConfiguration& aConfig) { + bool supportHardwareDecryption = false; + for (const auto& capabilities : aConfig.mAudioCapabilities) { + if (capabilities.mRobustness.EqualsLiteral("HW_SECURE_ALL")) { + supportHardwareDecryption = true; + break; + } + } + for (const auto& capabilities : aConfig.mVideoCapabilities) { + if (capabilities.mRobustness.EqualsLiteral("3000") || + capabilities.mRobustness.EqualsLiteral("HW_SECURE_ALL")) { + supportHardwareDecryption = true; + break; + } + } + return supportHardwareDecryption; +} + } // namespace mozilla diff --git a/dom/media/eme/EMEUtils.h b/dom/media/eme/EMEUtils.h index 94a5e1625e7a..848f6d53e427 100644 --- a/dom/media/eme/EMEUtils.h +++ b/dom/media/eme/EMEUtils.h @@ -9,6 +9,7 @@ #include "mozilla/Logging.h" #include "mozilla/dom/MediaKeyStatusMapBinding.h" +#include "mozilla/dom/MediaKeySystemAccessBinding.h" #include "nsString.h" #include "nsTArray.h" @@ -73,6 +74,10 @@ CDMType ToCDMTypeTelemetryEnum(const nsString& aKeySystem); const char* ToMediaKeyStatusStr(dom::MediaKeyStatus aStatus); +// Return true if given config supports hardware decryption (SL3000 or L1). +bool IsHardwareDecryptionSupported( + const dom::MediaKeySystemConfiguration& aConfig); + } // namespace mozilla #endif // EME_LOG_H_ diff --git a/dom/media/eme/KeySystemConfig.cpp b/dom/media/eme/KeySystemConfig.cpp index ab5459a638b4..92064f213a41 100644 --- a/dom/media/eme/KeySystemConfig.cpp +++ b/dom/media/eme/KeySystemConfig.cpp @@ -199,6 +199,18 @@ bool KeySystemConfig::CreateKeySystemConfigs( return false; } +bool KeySystemConfig::IsSameKeySystem(const nsAString& aKeySystem) const { +#ifdef MOZ_WMF_CDM + // We want to map Widevine experiment key system to normal Widevine key system + // as well. + if (IsWidevineExperimentKeySystemAndSupported(mKeySystem)) { + return mKeySystem.Equals(aKeySystem) || + aKeySystem.EqualsLiteral(kWidevineKeySystemName); + } +#endif + return mKeySystem.Equals(aKeySystem); +} + #ifdef DEBUG nsString KeySystemConfig::GetDebugInfo() const { nsString debugInfo; diff --git a/dom/media/eme/KeySystemConfig.h b/dom/media/eme/KeySystemConfig.h index 43a41584d452..aa642c43a591 100644 --- a/dom/media/eme/KeySystemConfig.h +++ b/dom/media/eme/KeySystemConfig.h @@ -159,6 +159,10 @@ struct KeySystemConfig { nsString GetDebugInfo() const; #endif + // Return true if the given key system is equal to `mKeySystem`, or it can be + // mapped to the same key system + bool IsSameKeySystem(const nsAString& aKeySystem) const; + nsString mKeySystem; nsTArray mInitDataTypes; Requirement mPersistentState = Requirement::NotAllowed; diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp index 740cf2b51f14..085e9aa63081 100644 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ b/dom/media/eme/MediaKeySystemAccess.cpp @@ -193,7 +193,7 @@ static bool GetKeySystemConfigs( nsTArray& aOutKeySystemConfig) { bool foundConfigs = false; for (auto& config : GetSupportedKeySystems()) { - if (config.mKeySystem.Equals(aKeySystem)) { + if (config.IsSameKeySystem(aKeySystem)) { aOutKeySystemConfig.AppendElement(std::move(config)); foundConfigs = true; } @@ -729,6 +729,11 @@ static bool GetSupportedConfig( MediaKeySystemConfiguration& aOutConfig, DecoderDoctorDiagnostics* aDiagnostics, bool aInPrivateBrowsing, const std::function& aDeprecationLogFn) { +#ifdef DEBUG + EME_LOG("Compare implementation '%s'\n with request '%s'", + NS_ConvertUTF16toUTF8(aKeySystem.GetDebugInfo()).get(), + ToCString(aCandidate).get()); +#endif // Let accumulated configuration be a new MediaKeySystemConfiguration // dictionary. MediaKeySystemConfiguration config; diff --git a/dom/media/eme/MediaKeys.cpp b/dom/media/eme/MediaKeys.cpp index 51b94b1c60ca..f2905561a532 100644 --- a/dom/media/eme/MediaKeys.cpp +++ b/dom/media/eme/MediaKeys.cpp @@ -428,7 +428,10 @@ class MediaKeysGMPCrashHelper : public GMPCrashHelper { }; already_AddRefed MediaKeys::CreateCDMProxy() { - EME_LOG("MediaKeys[%p]::CreateCDMProxy()", this); + const bool isHardwareDecryptionSupported = + IsHardwareDecryptionSupported(mConfig); + EME_LOG("MediaKeys[%p]::CreateCDMProxy(), isHardwareDecryptionSupported=%d", + this, isHardwareDecryptionSupported); RefPtr proxy; #ifdef MOZ_WIDGET_ANDROID if (IsWidevineKeySystem(mKeySystem)) { @@ -440,7 +443,8 @@ already_AddRefed MediaKeys::CreateCDMProxy() { #endif #ifdef MOZ_WMF_CDM if (IsPlayReadyKeySystemAndSupported(mKeySystem) || - IsWidevineExperimentKeySystemAndSupported(mKeySystem)) { + IsWidevineExperimentKeySystemAndSupported(mKeySystem) || + (IsWidevineKeySystem(mKeySystem) && isHardwareDecryptionSupported)) { proxy = new WMFCDMProxy(this, mKeySystem, mConfig); } else #endif diff --git a/dom/media/eme/mediafoundation/WMFCDMProxy.cpp b/dom/media/eme/mediafoundation/WMFCDMProxy.cpp index 210983e0bbd7..9b154e44b790 100644 --- a/dom/media/eme/mediafoundation/WMFCDMProxy.cpp +++ b/dom/media/eme/mediafoundation/WMFCDMProxy.cpp @@ -8,6 +8,7 @@ #include "mozilla/dom/MediaKeySession.h" #include "mozilla/dom/MediaKeySystemAccessBinding.h" +#include "mozilla/EMEUtils.h" #include "mozilla/WMFCDMProxyCallback.h" #include "WMFCDMImpl.h" #include "WMFCDMProxyCallback.h" @@ -103,6 +104,8 @@ WMFCDMProxy::GenerateMFCDMMediaCapabilities( const dom::Sequence& aCapabilities) { CopyableTArray outCapabilites; for (const auto& capabilities : aCapabilities) { + EME_LOG("WMFCDMProxy::Init %p, robustness=%s", this, + NS_ConvertUTF16toUTF8(capabilities.mRobustness).get()); outCapabilites.AppendElement(MFCDMMediaCapability{ capabilities.mContentType, capabilities.mRobustness}); } @@ -308,6 +311,10 @@ void WMFCDMProxy::OnExpirationChange(const nsAString& aSessionId, } } +bool WMFCDMProxy::IsHardwareDecryptionSupported() const { + return mozilla::IsHardwareDecryptionSupported(mConfig); +} + uint64_t WMFCDMProxy::GetCDMProxyId() const { MOZ_DIAGNOSTIC_ASSERT(mCDM); return mCDM->Id(); diff --git a/dom/media/eme/mediafoundation/WMFCDMProxy.h b/dom/media/eme/mediafoundation/WMFCDMProxy.h index f967ac4a88e5..bbfed106dc4f 100644 --- a/dom/media/eme/mediafoundation/WMFCDMProxy.h +++ b/dom/media/eme/mediafoundation/WMFCDMProxy.h @@ -110,6 +110,8 @@ class WMFCDMProxy : public CDMProxy { WMFCDMProxy* AsWMFCDMProxy() override { return this; } + bool IsHardwareDecryptionSupported() const override; + // Can only be called after initialization succeeded. uint64_t GetCDMProxyId() const; diff --git a/dom/media/ipc/MFCDMParent.cpp b/dom/media/ipc/MFCDMParent.cpp index 7b03254a5fc1..261b8d0128ad 100644 --- a/dom/media/ipc/MFCDMParent.cpp +++ b/dom/media/ipc/MFCDMParent.cpp @@ -286,6 +286,13 @@ static nsString GetOriginalKeySystem(const nsString& aKeySystem) { return aKeySystem; } +static nsString MapKeySystem(const nsString& aKeySystem) { + if (IsWidevineKeySystem(aKeySystem)) { + return nsString(u"com.widevine.alpha.experiment"); + } + return aKeySystem; +} + void MFCDMParent::Register() { MOZ_ASSERT(!sRegisteredCDMs.Contains(this->mId)); sRegisteredCDMs.InsertOrUpdate(this->mId, this); @@ -310,7 +317,8 @@ MFCDMParent::MFCDMParent(const nsAString& aKeySystem, mExpirationEvents(aManagerThread) { // TODO : add ClearKey CDM support MOZ_ASSERT(IsPlayReadyKeySystemAndSupported(aKeySystem) || - IsWidevineExperimentKeySystemAndSupported(aKeySystem)); + IsWidevineExperimentKeySystemAndSupported(aKeySystem) || + IsWidevineKeySystem(mKeySystem)); MOZ_ASSERT(aManager); MOZ_ASSERT(aManagerThread); MOZ_ASSERT(XRE_IsUtilityProcess()); @@ -374,7 +382,8 @@ LPCWSTR MFCDMParent::GetCDMLibraryName() const { if (IsPlayReadyKeySystemAndSupported(mKeySystem)) { return L""; } - if (IsWidevineExperimentKeySystemAndSupported(mKeySystem)) { + if (IsWidevineExperimentKeySystemAndSupported(mKeySystem) || + IsWidevineKeySystem(mKeySystem)) { // TODO : return real Widevine Dll name in bug 1858546 return L""; } @@ -423,7 +432,8 @@ HRESULT MFCDMParent::LoadFactory() { // ".ContentDecryptionModuleFactory". In addition, when querying // factory, need to use original Widevine key system name. nsString stringId; - if (IsWidevineExperimentKeySystemAndSupported(mKeySystem)) { + if (IsWidevineExperimentKeySystemAndSupported(mKeySystem) || + IsWidevineKeySystem(mKeySystem)) { stringId.AppendLiteral("com.widevine.alpha.ContentDecryptionModuleFactory"); } MFCDM_PARENT_LOG("Query factory by classId '%s", @@ -533,7 +543,8 @@ static bool IsKeySystemHWSecure( } } } - if (IsWidevineExperimentKeySystemAndSupported(aKeySystem)) { + if (IsWidevineExperimentKeySystemAndSupported(aKeySystem) || + IsWidevineKeySystem(aKeySystem)) { // We only support Widevine HWDRM. return true; } @@ -696,9 +707,9 @@ mozilla::ipc::IPCResult MFCDMParent::RecvInit( MOZ_ASSERT(mFactory->IsTypeSupported(GetOriginalKeySystem(mKeySystem).get(), nullptr)); - MFCDM_REJECT_IF_FAILED( - CreateContentDecryptionModule(mFactory, mKeySystem, aParams, mCDM), - NS_ERROR_FAILURE); + MFCDM_REJECT_IF_FAILED(CreateContentDecryptionModule( + mFactory, MapKeySystem(mKeySystem), aParams, mCDM), + NS_ERROR_FAILURE); MOZ_ASSERT(mCDM); MFCDM_PARENT_LOG("Created a CDM!"); diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index 6eef653efa39..54d1cdfa14e9 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -799,7 +799,9 @@ void PDMFactory::SetCDMProxy(CDMProxy* aProxy) { #endif #ifdef MOZ_WMF_CDM if (IsPlayReadyKeySystemAndSupported(aProxy->KeySystem()) || - IsWidevineExperimentKeySystemAndSupported(aProxy->KeySystem())) { + IsWidevineExperimentKeySystemAndSupported(aProxy->KeySystem()) || + (IsWidevineKeySystem(aProxy->KeySystem()) && + aProxy->IsHardwareDecryptionSupported())) { mEMEPDM = RemoteDecoderModule::Create( RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM); return;