diff options
Diffstat (limited to 'dom/media/ipc')
-rw-r--r-- | dom/media/ipc/MFCDMChild.cpp | 34 | ||||
-rw-r--r-- | dom/media/ipc/MFCDMChild.h | 3 | ||||
-rw-r--r-- | dom/media/ipc/MFCDMParent.cpp | 229 | ||||
-rw-r--r-- | dom/media/ipc/MFCDMParent.h | 12 | ||||
-rw-r--r-- | dom/media/ipc/MFMediaEngineChild.cpp | 33 | ||||
-rw-r--r-- | dom/media/ipc/MFMediaEngineChild.h | 9 | ||||
-rw-r--r-- | dom/media/ipc/MFMediaEngineParent.cpp | 15 | ||||
-rw-r--r-- | dom/media/ipc/MFMediaEngineParent.h | 2 | ||||
-rw-r--r-- | dom/media/ipc/MediaIPCUtils.h | 3 | ||||
-rw-r--r-- | dom/media/ipc/PMFCDM.ipdl | 11 | ||||
-rw-r--r-- | dom/media/ipc/PMFMediaEngine.ipdl | 2 | ||||
-rw-r--r-- | dom/media/ipc/RemoteMediaDataDecoder.cpp | 17 | ||||
-rw-r--r-- | dom/media/ipc/RemoteMediaDataDecoder.h | 16 |
13 files changed, 236 insertions, 150 deletions
diff --git a/dom/media/ipc/MFCDMChild.cpp b/dom/media/ipc/MFCDMChild.cpp index aedae5bc36..2ba2bdaf4e 100644 --- a/dom/media/ipc/MFCDMChild.cpp +++ b/dom/media/ipc/MFCDMChild.cpp @@ -148,7 +148,7 @@ void MFCDMChild::Shutdown() { } RefPtr<MFCDMChild::CapabilitiesPromise> MFCDMChild::GetCapabilities( - bool aIsHWSecured) { + MFCDMCapabilitiesRequest&& aRequest) { MOZ_ASSERT(mManagerThread); if (mShutdown) { @@ -160,23 +160,21 @@ RefPtr<MFCDMChild::CapabilitiesPromise> MFCDMChild::GetCapabilities( return CapabilitiesPromise::CreateAndReject(mState, __func__); } - auto doSend = [self = RefPtr{this}, aIsHWSecured, this]() { - SendGetCapabilities(aIsHWSecured) - ->Then( - mManagerThread, __func__, - [self, this](MFCDMCapabilitiesResult&& aResult) { - if (aResult.type() == MFCDMCapabilitiesResult::Tnsresult) { - mCapabilitiesPromiseHolder.RejectIfExists( - aResult.get_nsresult(), __func__); - return; - } - mCapabilitiesPromiseHolder.ResolveIfExists( - std::move(aResult.get_MFCDMCapabilitiesIPDL()), __func__); - }, - [self, this](const mozilla::ipc::ResponseRejectReason& aReason) { - mCapabilitiesPromiseHolder.RejectIfExists(NS_ERROR_FAILURE, - __func__); - }); + auto doSend = [self = RefPtr{this}, request = std::move(aRequest), this]() { + SendGetCapabilities(request)->Then( + mManagerThread, __func__, + [self, this](MFCDMCapabilitiesResult&& aResult) { + if (aResult.type() == MFCDMCapabilitiesResult::Tnsresult) { + mCapabilitiesPromiseHolder.RejectIfExists(aResult.get_nsresult(), + __func__); + return; + } + mCapabilitiesPromiseHolder.ResolveIfExists( + std::move(aResult.get_MFCDMCapabilitiesIPDL()), __func__); + }, + [self, this](const mozilla::ipc::ResponseRejectReason& aReason) { + mCapabilitiesPromiseHolder.RejectIfExists(NS_ERROR_FAILURE, __func__); + }); }; return InvokeAsync(doSend, __func__, mCapabilitiesPromiseHolder); diff --git a/dom/media/ipc/MFCDMChild.h b/dom/media/ipc/MFCDMChild.h index e62f2b7184..3396b0c790 100644 --- a/dom/media/ipc/MFCDMChild.h +++ b/dom/media/ipc/MFCDMChild.h @@ -25,7 +25,8 @@ class MFCDMChild final : public PMFCDMChild { explicit MFCDMChild(const nsAString& aKeySystem); using CapabilitiesPromise = MozPromise<MFCDMCapabilitiesIPDL, nsresult, true>; - RefPtr<CapabilitiesPromise> GetCapabilities(bool aIsHWSecured); + RefPtr<CapabilitiesPromise> GetCapabilities( + MFCDMCapabilitiesRequest&& aRequest); template <typename PromiseType> already_AddRefed<PromiseType> InvokeAsync( diff --git a/dom/media/ipc/MFCDMParent.cpp b/dom/media/ipc/MFCDMParent.cpp index 2e91048b88..4570fbe838 100644 --- a/dom/media/ipc/MFCDMParent.cpp +++ b/dom/media/ipc/MFCDMParent.cpp @@ -5,6 +5,7 @@ #include "MFCDMParent.h" #include <mfmediaengine.h> +#include <unknwnbase.h> #include <wtypes.h> #define INITGUID // Enable DEFINE_PROPERTYKEY() #include <propkeydef.h> // For DEFINE_PROPERTYKEY() definition @@ -92,6 +93,8 @@ StaticMutex sFactoryMutex; static nsTHashMap<nsStringHashKey, ComPtr<IMFContentDecryptionModuleFactory>> sFactoryMap; static CopyableTArray<MFCDMCapabilitiesIPDL> sCapabilities; +StaticMutex sCapabilitesMutex; +static ComPtr<IUnknown> sMediaEngineClassFactory; // RAIIized PROPVARIANT. See // third_party/libwebrtc/modules/audio_device/win/core_audio_utility_win.h @@ -166,6 +169,11 @@ static nsString GetHdcpPolicy(const dom::HDCPVersion& aMinHdcpVersion) { return nsString(u"hdcp=1"); } +static bool RequireClearLead(const nsString& aKeySystem) { + return aKeySystem.EqualsLiteral(kWidevineExperiment2KeySystemName) || + aKeySystem.EqualsLiteral(kPlayReadyHardwareClearLeadKeySystemName); +} + static void BuildCapabilitiesArray( const nsTArray<MFCDMMediaCapability>& aCapabilities, AutoPropVar& capabilitiesPropOut) { @@ -464,8 +472,10 @@ LPCWSTR MFCDMParent::GetCDMLibraryName(const nsString& aKeySystem) { /* static */ void MFCDMParent::Shutdown() { + StaticMutexAutoLock lock(sCapabilitesMutex); sFactoryMap.Clear(); sCapabilities.Clear(); + sMediaEngineClassFactory.Reset(); } /* static */ @@ -500,10 +510,13 @@ HRESULT MFCDMParent::LoadFactory( NS_ConvertUTF16toUTF8(aKeySystem).get()); ComPtr<IMFContentDecryptionModuleFactory> cdmFactory; if (loadFromPlatform) { + if (!sMediaEngineClassFactory) { + MFCDM_RETURN_IF_FAILED(CoCreateInstance( + CLSID_MFMediaEngineClassFactory, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&sMediaEngineClassFactory))); + } ComPtr<IMFMediaEngineClassFactory4> clsFactory; - MFCDM_RETURN_IF_FAILED(CoCreateInstance(CLSID_MFMediaEngineClassFactory, - nullptr, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&clsFactory))); + MFCDM_RETURN_IF_FAILED(sMediaEngineClassFactory.As(&clsFactory)); MFCDM_RETURN_IF_FAILED(clsFactory->CreateContentDecryptionModuleFactory( MapKeySystem(aKeySystem).get(), IID_PPV_ARGS(&cdmFactory))); aFactoryOut.Swap(cdmFactory); @@ -617,12 +630,8 @@ static bool FactorySupports(ComPtr<IMFContentDecryptionModuleFactory>& aFactory, // use another way to check the capabilities. if (IsPlayReadyKeySystemAndSupported(aKeySystem) && StaticPrefs::media_eme_playready_istypesupportedex()) { - ComPtr<IMFMediaEngineClassFactory> spFactory; ComPtr<IMFExtendedDRMTypeSupport> spDrmTypeSupport; - MFCDM_RETURN_BOOL_IF_FAILED( - CoCreateInstance(CLSID_MFMediaEngineClassFactory, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spFactory))); - MFCDM_RETURN_BOOL_IF_FAILED(spFactory.As(&spDrmTypeSupport)); + MFCDM_RETURN_BOOL_IF_FAILED(sMediaEngineClassFactory.As(&spDrmTypeSupport)); BSTR keySystem = aIsHWSecure ? CreateBSTRFromConstChar(kPlayReadyKeySystemHardware) : CreateBSTRFromConstChar(kPlayReadyKeySystemName); @@ -699,46 +708,55 @@ MFCDMParent::GetAllKeySystemsCapabilities() { new CapabilitiesPromise::Private(__func__); Unused << backgroundTaskQueue->Dispatch(NS_NewRunnableFunction(__func__, [p] { MFCDM_PARENT_SLOG("GetAllKeySystemsCapabilities"); - if (sCapabilities.IsEmpty()) { - enum SecureLevel : bool { - Software = false, - Hardware = true, - }; - const nsTArray<std::pair<nsString, SecureLevel>> kKeySystems{ - std::pair<nsString, SecureLevel>( - NS_ConvertUTF8toUTF16(kPlayReadyKeySystemName), - SecureLevel::Software), - std::pair<nsString, SecureLevel>( - NS_ConvertUTF8toUTF16(kPlayReadyKeySystemHardware), - SecureLevel::Hardware), - std::pair<nsString, SecureLevel>( - NS_ConvertUTF8toUTF16(kPlayReadyHardwareClearLeadKeySystemName), - SecureLevel::Hardware), - std::pair<nsString, SecureLevel>( - NS_ConvertUTF8toUTF16(kWidevineExperimentKeySystemName), - SecureLevel::Hardware), - std::pair<nsString, SecureLevel>( - NS_ConvertUTF8toUTF16(kWidevineExperiment2KeySystemName), - SecureLevel::Hardware), - }; - for (const auto& keySystem : kKeySystems) { - // Only check the capabilites if the relative prefs for the key system - // are ON. - if (IsPlayReadyKeySystemAndSupported(keySystem.first) || - IsWidevineExperimentKeySystemAndSupported(keySystem.first)) { - MFCDMCapabilitiesIPDL* c = sCapabilities.AppendElement(); - GetCapabilities(keySystem.first, keySystem.second, nullptr, *c); + enum SecureLevel : bool { + Software = false, + Hardware = true, + }; + const nsTArray<std::pair<nsString, SecureLevel>> kKeySystems{ + std::pair<nsString, SecureLevel>( + NS_ConvertUTF8toUTF16(kPlayReadyKeySystemName), + SecureLevel::Software), + std::pair<nsString, SecureLevel>( + NS_ConvertUTF8toUTF16(kPlayReadyKeySystemHardware), + SecureLevel::Hardware), + std::pair<nsString, SecureLevel>( + NS_ConvertUTF8toUTF16(kPlayReadyHardwareClearLeadKeySystemName), + SecureLevel::Hardware), + std::pair<nsString, SecureLevel>( + NS_ConvertUTF8toUTF16(kWidevineExperimentKeySystemName), + SecureLevel::Hardware), + std::pair<nsString, SecureLevel>( + NS_ConvertUTF8toUTF16(kWidevineExperiment2KeySystemName), + SecureLevel::Hardware), + }; + + CopyableTArray<MFCDMCapabilitiesIPDL> capabilitiesArr; + for (const auto& keySystem : kKeySystems) { + // Only check the capabilites if the relative prefs for the key system + // are ON. + if (IsPlayReadyKeySystemAndSupported(keySystem.first) || + IsWidevineExperimentKeySystemAndSupported(keySystem.first)) { + MFCDMCapabilitiesIPDL* c = capabilitiesArr.AppendElement(); + CapabilitesFlagSet flags; + if (keySystem.second == SecureLevel::Hardware) { + flags += CapabilitesFlag::HarewareDecryption; + } + flags += CapabilitesFlag::NeedHDCPCheck; + if (RequireClearLead(keySystem.first)) { + flags += CapabilitesFlag::NeedClearLeadCheck; } + GetCapabilities(keySystem.first, flags, nullptr, *c); } } - p->Resolve(sCapabilities, __func__); + + p->Resolve(std::move(capabilitiesArr), __func__); })); return p; } /* static */ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, - const bool aIsHWSecure, + const CapabilitesFlagSet& aFlags, IMFContentDecryptionModuleFactory* aFactory, MFCDMCapabilitiesIPDL& aCapabilitiesOut) { aCapabilitiesOut.keySystem() = aKeySystem; @@ -747,9 +765,12 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, aCapabilitiesOut.persistentState() = KeySystemConfig::Requirement::Required; aCapabilitiesOut.distinctiveID() = KeySystemConfig::Requirement::Required; + const bool isHardwareDecryption = + aFlags.contains(CapabilitesFlag::HarewareDecryption); + aCapabilitiesOut.isHardwareDecryption() = isHardwareDecryption; // Return empty capabilites for SWDRM on Windows 10 because it has the process // leaking problem. - if (!IsWin11OrLater() && !aIsHWSecure) { + if (!IsWin11OrLater() && !isHardwareDecryption) { return; } @@ -758,6 +779,30 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, RETURN_VOID_IF_FAILED(GetOrCreateFactory(aKeySystem, factory)); } + StaticMutexAutoLock lock(sCapabilitesMutex); + for (auto& capabilities : sCapabilities) { + if (capabilities.keySystem().Equals(aKeySystem) && + capabilities.isHardwareDecryption() == isHardwareDecryption) { + MFCDM_PARENT_SLOG( + "Return cached capabilities for %s (hardwareDecryption=%d)", + NS_ConvertUTF16toUTF8(aKeySystem).get(), isHardwareDecryption); + if (capabilities.isHDCP22Compatible().isNothing() && + aFlags.contains(CapabilitesFlag::NeedHDCPCheck)) { + const bool rv = IsHDCPVersionSupported(factory, aKeySystem, + dom::HDCPVersion::_2_2) == NS_OK; + MFCDM_PARENT_SLOG( + "Check HDCP 2.2 compatible (%d) for the cached capabilites", rv); + capabilities.isHDCP22Compatible() = Some(rv); + } + aCapabilitiesOut = capabilities; + return; + } + } + + MFCDM_PARENT_SLOG( + "Query capabilities for %s from the factory (hardwareDecryption=%d)", + NS_ConvertUTF16toUTF8(aKeySystem).get(), isHardwareDecryption); + // Widevine requires codec type to be four CC, PlayReady is fine with both. static auto convertCodecToFourCC = [](const KeySystemConfig::EMECodecString& aCodec) { @@ -809,12 +854,12 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, } if (FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec), KeySystemConfig::EMECodecString(""), nsString(u""), - aIsHWSecure)) { + isHardwareDecryption)) { MFCDMMediaCapability* c = aCapabilitiesOut.videoCapabilities().AppendElement(); c->contentType() = NS_ConvertUTF8toUTF16(codec); c->robustness() = - GetRobustnessStringForKeySystem(aKeySystem, aIsHWSecure); + GetRobustnessStringForKeySystem(aKeySystem, isHardwareDecryption); MFCDM_PARENT_SLOG("%s: +video:%s", __func__, codec.get()); supportedVideoCodecs.AppendElement(codec); } @@ -831,52 +876,51 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, KeySystemConfig::EME_CODEC_VORBIS, }); for (const auto& codec : kAudioCodecs) { - if (FactorySupports( - factory, aKeySystem, convertCodecToFourCC(supportedVideoCodecs[0]), - convertCodecToFourCC(codec), nsString(u""), aIsHWSecure)) { + // Hardware decryption is usually only used for video, so we can just check + // the software capabilities for audio in order to save some time. As the + // media foundation would create a new D3D device everytime when we check + // hardware decryption, which takes way longer time. + if (FactorySupports(factory, aKeySystem, + convertCodecToFourCC(supportedVideoCodecs[0]), + convertCodecToFourCC(codec), nsString(u""), + false /* aIsHWSecure */)) { MFCDMMediaCapability* c = aCapabilitiesOut.audioCapabilities().AppendElement(); c->contentType() = NS_ConvertUTF8toUTF16(codec); - c->robustness() = GetRobustnessStringForKeySystem(aKeySystem, aIsHWSecure, - false /* isVideo */); + c->robustness() = GetRobustnessStringForKeySystem( + aKeySystem, false /* aIsHWSecure */, false /* isVideo */); MFCDM_PARENT_SLOG("%s: +audio:%s", __func__, codec.get()); } } - // Collect schemes supported by all video codecs. - static nsTArray<std::pair<CryptoScheme, nsDependentString>> kSchemes = { - std::pair<CryptoScheme, nsDependentString>( - CryptoScheme::Cenc, u"encryption-type=cenc,encryption-iv-size=8,"), - std::pair<CryptoScheme, nsDependentString>( - CryptoScheme::Cbcs, u"encryption-type=cbcs,encryption-iv-size=16,")}; - for (auto& scheme : kSchemes) { - bool ok = true; - for (auto& codec : supportedVideoCodecs) { - ok &= FactorySupports( - factory, aKeySystem, convertCodecToFourCC(codec), nsCString(""), - scheme.second /* additional feature */, aIsHWSecure); - if (!ok) { - break; - } - } - if (ok) { - aCapabilitiesOut.encryptionSchemes().AppendElement(scheme.first); - MFCDM_PARENT_SLOG("%s: +scheme:%s", __func__, - scheme.first == CryptoScheme::Cenc ? "cenc" : "cbcs"); - } + // 'If value is unspecified, default value of "cenc" is used.' See + // https://learn.microsoft.com/en-us/windows/win32/api/mfmediaengine/nf-mfmediaengine-imfextendeddrmtypesupport-istypesupportedex + if (!supportedVideoCodecs.IsEmpty()) { + aCapabilitiesOut.encryptionSchemes().AppendElement(CryptoScheme::Cenc); + MFCDM_PARENT_SLOG("%s: +scheme:cenc", __func__); } - static auto RequireClearLead = [](const nsString& aKeySystem) { - if (aKeySystem.EqualsLiteral(kWidevineExperiment2KeySystemName) || - aKeySystem.EqualsLiteral(kPlayReadyHardwareClearLeadKeySystemName)) { - return true; + // Check another scheme "cbcs" + static std::pair<CryptoScheme, nsDependentString> kCbcs = + std::pair<CryptoScheme, nsDependentString>( + CryptoScheme::Cbcs, u"encryption-type=cbcs,encryption-iv-size=16,"); + bool ok = true; + for (const auto& codec : supportedVideoCodecs) { + ok &= FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec), + nsCString(""), kCbcs.second /* additional feature */, + isHardwareDecryption); + if (!ok) { + break; } - return false; - }; + } + if (ok) { + aCapabilitiesOut.encryptionSchemes().AppendElement(kCbcs.first); + MFCDM_PARENT_SLOG("%s: +scheme:cbcs", __func__); + } // For key system requires clearlead, every codec needs to have clear support. // If not, then we will remove the codec from supported codec. - if (RequireClearLead(aKeySystem)) { + if (aFlags.contains(CapabilitesFlag::NeedClearLeadCheck)) { for (const auto& scheme : aCapabilitiesOut.encryptionSchemes()) { nsTArray<KeySystemConfig::EMECodecString> noClearLeadCodecs; for (const auto& codec : supportedVideoCodecs) { @@ -894,9 +938,9 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, } else { additionalFeature.AppendLiteral(u"cbcs-clearlead,"); } - bool rv = - FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec), - nsCString(""), additionalFeature, aIsHWSecure); + bool rv = FactorySupports(factory, aKeySystem, + convertCodecToFourCC(codec), nsCString(""), + additionalFeature, isHardwareDecryption); MFCDM_PARENT_SLOG("clearlead %s IV 8 bytes %s %s", CryptoSchemeToString(scheme), codec.get(), rv ? "supported" : "not supported"); @@ -906,7 +950,8 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, // Try 16 bytes IV. additionalFeature.AppendLiteral(u"encryption-iv-size=16,"); rv = FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec), - nsCString(""), additionalFeature, aIsHWSecure); + nsCString(""), additionalFeature, + isHardwareDecryption); MFCDM_PARENT_SLOG("clearlead %s IV 16 bytes %s %s", CryptoSchemeToString(scheme), codec.get(), rv ? "supported" : "not supported"); @@ -926,9 +971,14 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, } } - if (IsHDCPVersionSupported(factory, aKeySystem, dom::HDCPVersion::_2_2) == - NS_OK) { - aCapabilitiesOut.isHDCP22Compatible() = true; + // Only perform HDCP if necessary, "The hdcp query (item 4) has a + // computationally expensive first invocation cost". See + // https://learn.microsoft.com/en-us/windows/win32/api/mfmediaengine/nf-mfmediaengine-imfextendeddrmtypesupport-istypesupportedex + if (aFlags.contains(CapabilitesFlag::NeedHDCPCheck) && + IsHDCPVersionSupported(factory, aKeySystem, dom::HDCPVersion::_2_2) == + NS_OK) { + MFCDM_PARENT_SLOG("Capabilites is compatible with HDCP 2.2"); + aCapabilitiesOut.isHDCP22Compatible() = Some(true); } // TODO: don't hardcode @@ -938,13 +988,24 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem, KeySystemConfig::SessionType::Temporary); aCapabilitiesOut.sessionTypes().AppendElement( KeySystemConfig::SessionType::PersistentLicense); + + // Cache capabilities for reuse. + sCapabilities.AppendElement(aCapabilitiesOut); } mozilla::ipc::IPCResult MFCDMParent::RecvGetCapabilities( - const bool aIsHWSecure, GetCapabilitiesResolver&& aResolver) { + const MFCDMCapabilitiesRequest& aRequest, + GetCapabilitiesResolver&& aResolver) { MFCDM_REJECT_IF(!mFactory, NS_ERROR_DOM_NOT_SUPPORTED_ERR); MFCDMCapabilitiesIPDL capabilities; - GetCapabilities(mKeySystem, aIsHWSecure, mFactory.Get(), capabilities); + CapabilitesFlagSet flags; + if (aRequest.isHardwareDecryption()) { + flags += CapabilitesFlag::HarewareDecryption; + } + if (RequireClearLead(aRequest.keySystem())) { + flags += CapabilitesFlag::NeedClearLeadCheck; + } + GetCapabilities(aRequest.keySystem(), flags, mFactory.Get(), capabilities); aResolver(std::move(capabilities)); return IPC_OK(); } diff --git a/dom/media/ipc/MFCDMParent.h b/dom/media/ipc/MFCDMParent.h index b4ef1b831b..921d86be73 100644 --- a/dom/media/ipc/MFCDMParent.h +++ b/dom/media/ipc/MFCDMParent.h @@ -52,7 +52,8 @@ class MFCDMParent final : public PMFCDMParent { uint64_t Id() const { return mId; } mozilla::ipc::IPCResult RecvGetCapabilities( - const bool aIsHWSecured, GetCapabilitiesResolver&& aResolver); + const MFCDMCapabilitiesRequest& aRequest, + GetCapabilitiesResolver&& aResolver); mozilla::ipc::IPCResult RecvInit(const MFCDMInitParamsIPDL& aParams, InitResolver&& aResolver); @@ -97,6 +98,13 @@ class MFCDMParent final : public PMFCDMParent { private: ~MFCDMParent(); + enum class CapabilitesFlag { + HarewareDecryption, + NeedHDCPCheck, + NeedClearLeadCheck, + }; + using CapabilitesFlagSet = EnumSet<CapabilitesFlag, uint8_t>; + static LPCWSTR GetCDMLibraryName(const nsString& aKeySystem); static HRESULT GetOrCreateFactory( @@ -108,7 +116,7 @@ class MFCDMParent final : public PMFCDMParent { Microsoft::WRL::ComPtr<IMFContentDecryptionModuleFactory>& aFactoryOut); static void GetCapabilities(const nsString& aKeySystem, - const bool aIsHWSecure, + const CapabilitesFlagSet& aFlags, IMFContentDecryptionModuleFactory* aFactory, MFCDMCapabilitiesIPDL& aCapabilitiesOut); diff --git a/dom/media/ipc/MFMediaEngineChild.cpp b/dom/media/ipc/MFMediaEngineChild.cpp index 02013056d5..cc32d15ea4 100644 --- a/dom/media/ipc/MFMediaEngineChild.cpp +++ b/dom/media/ipc/MFMediaEngineChild.cpp @@ -47,20 +47,22 @@ MFMediaEngineChild::MFMediaEngineChild(MFMediaEngineWrapper* aOwner, } RefPtr<GenericNonExclusivePromise> MFMediaEngineChild::Init( - bool aShouldPreload) { + const MediaInfo& aInfo, bool aShouldPreload) { if (!mManagerThread) { return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); } - CLOG("Init"); + CLOG("Init, hasAudio=%d, hasVideo=%d, encrypted=%d", aInfo.HasAudio(), + aInfo.HasVideo(), aInfo.IsEncrypted()); + MOZ_ASSERT(mMediaEngineId == 0); RefPtr<MFMediaEngineChild> self = this; RemoteDecoderManagerChild::LaunchUtilityProcessIfNeeded( RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM) ->Then( mManagerThread, __func__, - [self, this, aShouldPreload](bool) { + [self, this, aShouldPreload, info = aInfo](bool) { RefPtr<RemoteDecoderManagerChild> manager = RemoteDecoderManagerChild::GetSingleton( RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM); @@ -72,8 +74,13 @@ RefPtr<GenericNonExclusivePromise> MFMediaEngineChild::Init( mIPDLSelfRef = this; Unused << manager->SendPMFMediaEngineConstructor(this); - MediaEngineInfoIPDL info(aShouldPreload); - SendInitMediaEngine(info) + + MediaInfoIPDL mediaInfo( + info.HasAudio() ? Some(info.mAudio) : Nothing(), + info.HasVideo() ? Some(info.mVideo) : Nothing()); + + MediaEngineInfoIPDL initInfo(mediaInfo, aShouldPreload); + SendInitMediaEngine(initInfo) ->Then( mManagerThread, __func__, [self, this](uint64_t aId) { @@ -256,9 +263,9 @@ MFMediaEngineWrapper::MFMediaEngineWrapper(ExternalEngineStateMachine* aOwner, mCurrentTimeInSecond(0.0) {} RefPtr<GenericNonExclusivePromise> MFMediaEngineWrapper::Init( - bool aShouldPreload) { + const MediaInfo& aInfo, bool aShouldPreload) { WLOG("Init"); - return mEngine->Init(aShouldPreload); + return mEngine->Init(aInfo, aShouldPreload); } MFMediaEngineWrapper::~MFMediaEngineWrapper() { mEngine->OwnerDestroyed(); } @@ -335,18 +342,6 @@ void MFMediaEngineWrapper::NotifyEndOfStream(TrackInfo::TrackType aType) { [engine = mEngine, aType] { engine->SendNotifyEndOfStream(aType); })); } -void MFMediaEngineWrapper::SetMediaInfo(const MediaInfo& aInfo) { - WLOG("SetMediaInfo, hasAudio=%d, hasVideo=%d, encrypted=%d", aInfo.HasAudio(), - aInfo.HasVideo(), aInfo.IsEncrypted()); - MOZ_ASSERT(IsInited()); - Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction( - "MFMediaEngineWrapper::SetMediaInfo", [engine = mEngine, aInfo] { - MediaInfoIPDL info(aInfo.HasAudio() ? Some(aInfo.mAudio) : Nothing(), - aInfo.HasVideo() ? Some(aInfo.mVideo) : Nothing()); - engine->SendNotifyMediaInfo(info); - })); -} - bool MFMediaEngineWrapper::SetCDMProxy(CDMProxy* aProxy) { #ifdef MOZ_WMF_CDM WMFCDMProxy* proxy = aProxy->AsWMFCDMProxy(); diff --git a/dom/media/ipc/MFMediaEngineChild.h b/dom/media/ipc/MFMediaEngineChild.h index 92de3b9483..13b837b7d8 100644 --- a/dom/media/ipc/MFMediaEngineChild.h +++ b/dom/media/ipc/MFMediaEngineChild.h @@ -32,7 +32,8 @@ class MFMediaEngineChild final : public PMFMediaEngineChild { void OwnerDestroyed(); void IPDLActorDestroyed(); - RefPtr<GenericNonExclusivePromise> Init(bool aShouldPreload); + RefPtr<GenericNonExclusivePromise> Init(const MediaInfo& aInfo, + bool aShouldPreload); void Shutdown(); // Methods for PMFMediaEngineChild @@ -99,7 +100,8 @@ class MFMediaEngineWrapper final : public ExternalPlaybackEngine { ~MFMediaEngineWrapper(); // Methods for ExternalPlaybackEngine - RefPtr<GenericNonExclusivePromise> Init(bool aShouldPreload) override; + RefPtr<GenericNonExclusivePromise> Init(const MediaInfo& aInfo, + bool aShouldPreload) override; void Play() override; void Pause() override; void Seek(const media::TimeUnit& aTargetTime) override; @@ -111,7 +113,7 @@ class MFMediaEngineWrapper final : public ExternalPlaybackEngine { media::TimeUnit GetCurrentPosition() override; void NotifyEndOfStream(TrackInfo::TrackType aType) override; uint64_t Id() const override { return mEngine->Id(); } - void SetMediaInfo(const MediaInfo& aInfo) override; + bool IsInited() const { return mEngine->Id() != 0; } bool SetCDMProxy(CDMProxy* aProxy) override; void NotifyResizing(uint32_t aWidth, uint32_t aHeight) override; @@ -121,7 +123,6 @@ class MFMediaEngineWrapper final : public ExternalPlaybackEngine { private: friend class MFMediaEngineChild; - bool IsInited() const { return mEngine->Id() != 0; } void UpdateCurrentTime(double aCurrentTimeInSecond); void NotifyEvent(ExternalEngineEvent aEvent); void NotifyError(const MediaResult& aError); diff --git a/dom/media/ipc/MFMediaEngineParent.cpp b/dom/media/ipc/MFMediaEngineParent.cpp index 5ed1b71160..3a9670f330 100644 --- a/dom/media/ipc/MFMediaEngineParent.cpp +++ b/dom/media/ipc/MFMediaEngineParent.cpp @@ -338,17 +338,17 @@ mozilla::ipc::IPCResult MFMediaEngineParent::RecvInitMediaEngine( // TODO : really need this? Unused << mMediaEngine->SetPreload(MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC); } + RETURN_PARAM_IF_FAILED(SetMediaInfo(aInfo.mediaInfo()), IPC_OK()); aResolver(mMediaEngineId); return IPC_OK(); } -mozilla::ipc::IPCResult MFMediaEngineParent::RecvNotifyMediaInfo( - const MediaInfoIPDL& aInfo) { +HRESULT MFMediaEngineParent::SetMediaInfo(const MediaInfoIPDL& aInfo) { AssertOnManagerThread(); MOZ_ASSERT(mIsCreatedMediaEngine, "Hasn't created media engine?"); MOZ_ASSERT(!mMediaSource); - LOG("RecvNotifyMediaInfo"); + LOG("SetMediaInfo"); auto errorExit = MakeScopeExit([&] { MediaResult error(NS_ERROR_DOM_MEDIA_FATAL_ERR, @@ -378,9 +378,8 @@ mozilla::ipc::IPCResult MFMediaEngineParent::RecvNotifyMediaInfo( if (aInfo.videoInfo()) { ComPtr<IMFMediaEngineEx> mediaEngineEx; - RETURN_PARAM_IF_FAILED(mMediaEngine.As(&mediaEngineEx), IPC_OK()); - RETURN_PARAM_IF_FAILED(mediaEngineEx->EnableWindowlessSwapchainMode(true), - IPC_OK()); + RETURN_IF_FAILED(mMediaEngine.As(&mediaEngineEx)); + RETURN_IF_FAILED(mediaEngineEx->EnableWindowlessSwapchainMode(true)); LOG("Enabled dcomp swap chain mode"); ENGINE_MARKER("MFMediaEngineParent,EnabledSwapChain"); } @@ -392,7 +391,7 @@ mozilla::ipc::IPCResult MFMediaEngineParent::RecvNotifyMediaInfo( #ifdef MOZ_WMF_CDM if (isEncryted && !mContentProtectionManager) { // We will set the source later when the CDM proxy is ready. - return IPC_OK(); + return S_OK; } if (isEncryted && mContentProtectionManager) { @@ -403,7 +402,7 @@ mozilla::ipc::IPCResult MFMediaEngineParent::RecvNotifyMediaInfo( #endif SetMediaSourceOnEngine(); - return IPC_OK(); + return S_OK; } void MFMediaEngineParent::SetMediaSourceOnEngine() { diff --git a/dom/media/ipc/MFMediaEngineParent.h b/dom/media/ipc/MFMediaEngineParent.h index f606d3c44d..843ac91aaf 100644 --- a/dom/media/ipc/MFMediaEngineParent.h +++ b/dom/media/ipc/MFMediaEngineParent.h @@ -52,7 +52,6 @@ class MFMediaEngineParent final : public PMFMediaEngineParent { // Methods for PMFMediaEngineParent mozilla::ipc::IPCResult RecvInitMediaEngine( const MediaEngineInfoIPDL& aInfo, InitMediaEngineResolver&& aResolver); - mozilla::ipc::IPCResult RecvNotifyMediaInfo(const MediaInfoIPDL& aInfo); mozilla::ipc::IPCResult RecvPlay(); mozilla::ipc::IPCResult RecvPause(); mozilla::ipc::IPCResult RecvSeek(double aTargetTimeInSecond); @@ -69,6 +68,7 @@ class MFMediaEngineParent final : public PMFMediaEngineParent { ~MFMediaEngineParent(); void CreateMediaEngine(); + HRESULT SetMediaInfo(const MediaInfoIPDL& aInfo); void InitializeDXGIDeviceManager(); diff --git a/dom/media/ipc/MediaIPCUtils.h b/dom/media/ipc/MediaIPCUtils.h index fecf41c325..9598e1557f 100644 --- a/dom/media/ipc/MediaIPCUtils.h +++ b/dom/media/ipc/MediaIPCUtils.h @@ -15,6 +15,7 @@ #include "ipc/EnumSerializer.h" #include "mozilla/EnumSet.h" #include "mozilla/GfxMessageUtils.h" +#include "mozilla/dom/WebGLIpdl.h" #include "mozilla/gfx/Rect.h" #include "mozilla/dom/MFCDMSerializers.h" @@ -139,7 +140,7 @@ struct ParamTraits<mozilla::FlacCodecSpecificData> { template <> struct ParamTraits<mozilla::Mp3CodecSpecificData> - : public PlainOldDataSerializer<mozilla::Mp3CodecSpecificData> {}; + : public ParamTraits_TiedFields<mozilla::Mp3CodecSpecificData> {}; template <> struct ParamTraits<mozilla::OpusCodecSpecificData> { diff --git a/dom/media/ipc/PMFCDM.ipdl b/dom/media/ipc/PMFCDM.ipdl index e86b94c217..793cfa3808 100644 --- a/dom/media/ipc/PMFCDM.ipdl +++ b/dom/media/ipc/PMFCDM.ipdl @@ -12,6 +12,7 @@ using mozilla::CryptoScheme from "MediaData.h"; using mozilla::dom::MediaKeyMessageType from "mozilla/dom/MediaKeyMessageEventBinding.h"; using mozilla::dom::MediaKeyStatus from "mozilla/dom/MediaKeyStatusMapBinding.h"; using mozilla::dom::HDCPVersion from "mozilla/dom/MediaKeysBinding.h"; +using mozilla::KeySystemConfigRequest from "mozilla/KeySystemConfig.h"; namespace mozilla { @@ -57,7 +58,8 @@ struct MFCDMCapabilitiesIPDL { CryptoScheme[] encryptionSchemes; Requirement distinctiveID; Requirement persistentState; - bool isHDCP22Compatible; + bool? isHDCP22Compatible; + bool isHardwareDecryption; }; union MFCDMCapabilitiesResult { @@ -95,12 +97,17 @@ union MFCDMSessionResult { nsresult; }; +struct MFCDMCapabilitiesRequest { + nsString keySystem; + bool isHardwareDecryption; +}; + [ManualDealloc] async protocol PMFCDM { manager PRemoteDecoderManager; parent: - async GetCapabilities(bool isHwSecured) returns (MFCDMCapabilitiesResult result); + async GetCapabilities(MFCDMCapabilitiesRequest request) returns (MFCDMCapabilitiesResult result); async Init(MFCDMInitParamsIPDL params) returns (MFCDMInitResult result); async CreateSessionAndGenerateRequest(MFCDMCreateSessionParamsIPDL type) returns (MFCDMSessionResult result); diff --git a/dom/media/ipc/PMFMediaEngine.ipdl b/dom/media/ipc/PMFMediaEngine.ipdl index 8edc44bb81..ebed4e101c 100644 --- a/dom/media/ipc/PMFMediaEngine.ipdl +++ b/dom/media/ipc/PMFMediaEngine.ipdl @@ -17,6 +17,7 @@ namespace mozilla { struct MediaEngineInfoIPDL { + MediaInfoIPDL mediaInfo; bool preload; }; @@ -39,7 +40,6 @@ async protocol PMFMediaEngine parent: // Return 0 if media engine can't be created. async InitMediaEngine(MediaEngineInfoIPDL info) returns (uint64_t id); - async NotifyMediaInfo(MediaInfoIPDL info); async Play(); async Pause(); async Seek(double targetTimeInSecond); diff --git a/dom/media/ipc/RemoteMediaDataDecoder.cpp b/dom/media/ipc/RemoteMediaDataDecoder.cpp index 6db3c0d940..32e1ee6b31 100644 --- a/dom/media/ipc/RemoteMediaDataDecoder.cpp +++ b/dom/media/ipc/RemoteMediaDataDecoder.cpp @@ -18,7 +18,12 @@ namespace mozilla { ##__VA_ARGS__) RemoteMediaDataDecoder::RemoteMediaDataDecoder(RemoteDecoderChild* aChild) - : mChild(aChild) { + : mChild(aChild), + mDescription("RemoteMediaDataDecoder"_ns), + mProcessName("unknown"_ns), + mCodecName("unknown"_ns), + mIsHardwareAccelerated(false), + mConversion(ConversionRequired::kNeedNone) { LOG("%p is created", this); } @@ -48,6 +53,7 @@ RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() { ->Then( RemoteDecoderManagerChild::GetManagerThread(), __func__, [self, this](TrackType aTrack) { + MutexAutoLock lock(mMutex); // If shutdown has started in the meantime shutdown promise may // be resloved before this task. In this case mChild will be null // and the init promise has to be canceled. @@ -127,6 +133,7 @@ RefPtr<ShutdownPromise> RemoteMediaDataDecoder::Shutdown() { bool RemoteMediaDataDecoder::IsHardwareAccelerated( nsACString& aFailureReason) const { + MutexAutoLock lock(mMutex); aFailureReason = mHardwareAcceleratedReason; return mIsHardwareAccelerated; } @@ -145,18 +152,24 @@ void RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime) { MediaDataDecoder::ConversionRequired RemoteMediaDataDecoder::NeedsConversion() const { + MutexAutoLock lock(mMutex); return mConversion; } nsCString RemoteMediaDataDecoder::GetDescriptionName() const { + MutexAutoLock lock(mMutex); return mDescription; } nsCString RemoteMediaDataDecoder::GetProcessName() const { + MutexAutoLock lock(mMutex); return mProcessName; } -nsCString RemoteMediaDataDecoder::GetCodecName() const { return mCodecName; } +nsCString RemoteMediaDataDecoder::GetCodecName() const { + MutexAutoLock lock(mMutex); + return mCodecName; +} #undef LOG diff --git a/dom/media/ipc/RemoteMediaDataDecoder.h b/dom/media/ipc/RemoteMediaDataDecoder.h index 4acc5801f7..5d8612529d 100644 --- a/dom/media/ipc/RemoteMediaDataDecoder.h +++ b/dom/media/ipc/RemoteMediaDataDecoder.h @@ -53,14 +53,16 @@ class RemoteMediaDataDecoder final // destructor when we can guarantee no other threads are accessing it). Only // read from the manager thread. RefPtr<RemoteDecoderChild> mChild; + + mutable Mutex mMutex{"RemoteMediaDataDecoder"}; + // Only ever written/modified during decoder initialisation. - // As such can be accessed from any threads after that. - nsCString mDescription = "RemoteMediaDataDecoder"_ns; - nsCString mProcessName = "unknown"_ns; - nsCString mCodecName = "unknown"_ns; - bool mIsHardwareAccelerated = false; - nsCString mHardwareAcceleratedReason; - ConversionRequired mConversion = ConversionRequired::kNeedNone; + nsCString mDescription MOZ_GUARDED_BY(mMutex); + nsCString mProcessName MOZ_GUARDED_BY(mMutex); + nsCString mCodecName MOZ_GUARDED_BY(mMutex); + bool mIsHardwareAccelerated MOZ_GUARDED_BY(mMutex); + nsCString mHardwareAcceleratedReason MOZ_GUARDED_BY(mMutex); + ConversionRequired mConversion MOZ_GUARDED_BY(mMutex); }; } // namespace mozilla |