summaryrefslogtreecommitdiffstats
path: root/dom/media/ipc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/ipc/MFCDMChild.cpp34
-rw-r--r--dom/media/ipc/MFCDMChild.h3
-rw-r--r--dom/media/ipc/MFCDMParent.cpp229
-rw-r--r--dom/media/ipc/MFCDMParent.h12
-rw-r--r--dom/media/ipc/MFMediaEngineChild.cpp33
-rw-r--r--dom/media/ipc/MFMediaEngineChild.h9
-rw-r--r--dom/media/ipc/MFMediaEngineParent.cpp15
-rw-r--r--dom/media/ipc/MFMediaEngineParent.h2
-rw-r--r--dom/media/ipc/MediaIPCUtils.h3
-rw-r--r--dom/media/ipc/PMFCDM.ipdl11
-rw-r--r--dom/media/ipc/PMFMediaEngine.ipdl2
-rw-r--r--dom/media/ipc/RemoteMediaDataDecoder.cpp17
-rw-r--r--dom/media/ipc/RemoteMediaDataDecoder.h16
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