Backed out 5 changesets (bug 1898588) for bustages on MediaData.cpp . CLOSED TREE

Backed out changeset d23ba62a5165 (bug 1898588)
Backed out changeset dd7a777b034f (bug 1898588)
Backed out changeset 62c4a3361e00 (bug 1898588)
Backed out changeset 2643cfcd1ba7 (bug 1898588)
Backed out changeset 940fca861f93 (bug 1898588)
This commit is contained in:
Narcis Beleuzu 2024-05-29 02:15:25 +03:00
parent 45f04dc15a
commit 0cf79ef540
18 changed files with 229 additions and 303 deletions

View File

@ -597,53 +597,15 @@ void MediaRawDataWriter::PopFront(size_t aSize) {
const char* CryptoSchemeToString(const CryptoScheme& aScheme) {
switch (aScheme) {
case CryptoScheme::None:
return "none";
return "None";
case CryptoScheme::Cenc:
return "cenc";
return "Cenc";
case CryptoScheme::Cbcs:
return "cbcs";
case CryptoScheme::Cbcs_1_9:
return "cbcs-1-9";
return "Cbcs";
default:
MOZ_ASSERT_UNREACHABLE("not supported scheme!");
return "not supported scheme!";
MOZ_ASSERT_UNREACHABLE();
return "";
}
}
nsCString CryptoSchemeSetToString(const CryptoSchemeSet& aSchemes) {
nsAutoCString rv;
if (aSchemes.contains(CryptoScheme::Cenc)) {
rv.AppendLiteral("cenc");
}
if (aSchemes.contains(CryptoScheme::Cbcs)) {
if (!rv.IsEmpty()) {
rv.AppendLiteral("/");
}
rv.AppendLiteral("cbcs");
}
if (aSchemes.contains(CryptoScheme::Cbcs_1_9)) {
if (!rv.IsEmpty()) {
rv.AppendLiteral("/");
}
rv.AppendLiteral("cbcs-1-9");
}
if (rv.IsEmpty()) {
rv.AppendLiteral("none");
}
return rv;
}
CryptoScheme StringToCryptoScheme(const nsAString& aString) {
if (aString.EqualsLiteral("cenc")) {
return CryptoScheme::Cenc;
}
if (aString.EqualsLiteral("cbcs")) {
return CryptoScheme::Cbcs;
}
if (aString.EqualsLiteral("cbcs-1-9")) {
return CryptoScheme::Cbcs_1_9;
}
return CryptoScheme::None;
}
} // namespace mozilla

View File

@ -13,7 +13,6 @@
# include "SharedBuffer.h"
# include "TimeUnits.h"
# include "mozilla/CheckedInt.h"
# include "mozilla/EnumSet.h"
# include "mozilla/Maybe.h"
# include "mozilla/PodOperations.h"
# include "mozilla/RefPtr.h"
@ -582,18 +581,13 @@ class VideoData : public MediaData {
media::TimeUnit mNextKeyFrameTime;
};
// See https://w3c.github.io/encrypted-media/#scheme-cenc
enum class CryptoScheme : uint8_t {
None,
Cenc,
Cbcs,
Cbcs_1_9,
};
using CryptoSchemeSet = EnumSet<CryptoScheme, uint8_t>;
const char* CryptoSchemeToString(const CryptoScheme& aScheme);
nsCString CryptoSchemeSetToString(const CryptoSchemeSet& aSchemes);
CryptoScheme StringToCryptoScheme(const nsAString& aString);
class CryptoTrack {
public:

View File

@ -152,6 +152,19 @@ bool IsHardwareDecryptionSupported(const KeySystemConfig& aConfig) {
return false;
}
const char* EncryptionSchemeStr(const CryptoScheme& aScheme) {
switch (aScheme) {
case CryptoScheme::None:
return "none";
case CryptoScheme::Cenc:
return "cenc";
case CryptoScheme::Cbcs:
return "cbcs";
default:
return "not-defined!";
}
}
#ifdef MOZ_WMF_CDM
void MFCDMCapabilitiesIPDLToKeySystemConfig(
const MFCDMCapabilitiesIPDL& aCDMConfig,
@ -171,27 +184,23 @@ void MFCDMCapabilitiesIPDLToKeySystemConfig(
!aKeySystemConfig.mVideoRobustness.Contains(c.robustness())) {
aKeySystemConfig.mVideoRobustness.AppendElement(c.robustness());
}
CryptoSchemeSet schemes;
for (const auto& scheme : c.encryptionSchemes()) {
schemes += scheme;
}
aKeySystemConfig.mMP4.SetCanDecryptAndDecode(
NS_ConvertUTF16toUTF8(c.contentType()), Some(schemes));
NS_ConvertUTF16toUTF8(c.contentType()));
}
for (const auto& c : aCDMConfig.audioCapabilities()) {
if (!c.robustness().IsEmpty() &&
!aKeySystemConfig.mAudioRobustness.Contains(c.robustness())) {
aKeySystemConfig.mAudioRobustness.AppendElement(c.robustness());
}
CryptoSchemeSet schemes;
for (const auto& scheme : c.encryptionSchemes()) {
schemes += scheme;
}
aKeySystemConfig.mMP4.SetCanDecryptAndDecode(
NS_ConvertUTF16toUTF8(c.contentType()), Some(schemes));
NS_ConvertUTF16toUTF8(c.contentType()));
}
aKeySystemConfig.mPersistentState = aCDMConfig.persistentState();
aKeySystemConfig.mDistinctiveIdentifier = aCDMConfig.distinctiveID();
for (const auto& scheme : aCDMConfig.encryptionSchemes()) {
aKeySystemConfig.mEncryptionSchemes.AppendElement(
NS_ConvertUTF8toUTF16(EncryptionSchemeStr(scheme)));
}
aKeySystemConfig.mIsHDCP22Compatible = aCDMConfig.isHDCP22Compatible()
? *aCDMConfig.isHDCP22Compatible()
: false;

View File

@ -92,6 +92,8 @@ bool IsHardwareDecryptionSupported(
const dom::MediaKeySystemConfiguration& aConfig);
bool IsHardwareDecryptionSupported(const KeySystemConfig& aConfig);
const char* EncryptionSchemeStr(const CryptoScheme& aScheme);
#ifdef MOZ_WMF_CDM
void MFCDMCapabilitiesIPDLToKeySystemConfig(
const MFCDMCapabilitiesIPDL& aCDMConfig, KeySystemConfig& aKeySystemConfig);

View File

@ -79,6 +79,9 @@ bool KeySystemConfig::Supports(const nsAString& aKeySystem) {
config->mPersistentState = Requirement::Optional;
config->mDistinctiveIdentifier = Requirement::NotAllowed;
config->mSessionTypes.AppendElement(SessionType::Temporary);
config->mEncryptionSchemes.AppendElement(u"cenc"_ns);
config->mEncryptionSchemes.AppendElement(u"cbcs"_ns);
config->mEncryptionSchemes.AppendElement(u"cbcs-1-9"_ns);
if (StaticPrefs::media_clearkey_persistent_license_enabled()) {
config->mSessionTypes.AppendElement(SessionType::PersistentLicense);
}
@ -134,6 +137,9 @@ bool KeySystemConfig::Supports(const nsAString& aKeySystem) {
config->mAudioRobustness.AppendElement(u"SW_SECURE_CRYPTO"_ns);
config->mVideoRobustness.AppendElement(u"SW_SECURE_CRYPTO"_ns);
config->mVideoRobustness.AppendElement(u"SW_SECURE_DECODE"_ns);
config->mEncryptionSchemes.AppendElement(u"cenc"_ns);
config->mEncryptionSchemes.AppendElement(u"cbcs"_ns);
config->mEncryptionSchemes.AppendElement(u"cbcs-1-9"_ns);
#if defined(MOZ_WIDGET_ANDROID)
// MediaDrm.isCryptoSchemeSupported only allows passing
@ -362,6 +368,14 @@ nsString KeySystemConfig::GetDebugInfo() const {
debugInfo.AppendLiteral(",");
}
}
debugInfo.AppendLiteral(" scheme=[");
for (size_t idx = 0; idx < mEncryptionSchemes.Length(); idx++) {
debugInfo.Append(mEncryptionSchemes[idx]);
if (idx + 1 < mEncryptionSchemes.Length()) {
debugInfo.AppendLiteral(",");
}
}
debugInfo.AppendLiteral("]");
debugInfo.AppendLiteral(" MP4={");
debugInfo.Append(NS_ConvertUTF8toUTF16(mMP4.GetDebugInfo()));
debugInfo.AppendLiteral("}");

View File

@ -7,7 +7,6 @@
#ifndef DOM_MEDIA_EME_KEYSYSTEMCONFIG_H_
#define DOM_MEDIA_EME_KEYSYSTEMCONFIG_H_
#include "MediaData.h"
#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/MozPromise.h"
@ -81,52 +80,38 @@ struct KeySystemConfig {
return !mCodecsDecoded.IsEmpty() || !mCodecsDecrypted.IsEmpty();
}
// True if a codec and scheme pair can be decrypted and decoded
bool DecryptsAndDecodes(
const EMECodecString& aCodec,
const Maybe<CryptoScheme>& aScheme = Nothing()) const {
return CheckCodecAndSchemePair(mCodecsDecoded, aCodec, aScheme);
// CDM decrypts and decodes using a DRM robust decoder, and passes decoded
// samples back to Gecko for rendering.
bool DecryptsAndDecodes(const EMECodecString& aCodec) const {
return mCodecsDecoded.Contains(aCodec);
}
// True if a codec and scheme pair can be decrypted
bool Decrypts(const EMECodecString& aCodec,
const Maybe<CryptoScheme>& aScheme = Nothing()) const {
return CheckCodecAndSchemePair(mCodecsDecrypted, aCodec, aScheme);
// CDM decrypts and passes the decrypted samples back to Gecko for decoding.
bool Decrypts(const EMECodecString& aCodec) const {
return mCodecsDecrypted.Contains(aCodec);
}
void SetCanDecryptAndDecode(
const EMECodecString& aCodec,
const Maybe<CryptoSchemeSet>& aSchemes = Nothing{}) {
void SetCanDecryptAndDecode(const EMECodecString& aCodec) {
// Can't both decrypt and decrypt-and-decode a codec.
MOZ_ASSERT(!ContainsDecryptedOnlyCodec(aCodec));
MOZ_ASSERT(!Decrypts(aCodec));
// Prevent duplicates.
MOZ_ASSERT(!ContainsDecryptedAndDecodedCodec(aCodec));
mCodecsDecoded.AppendElement(CodecSchemePair{aCodec, aSchemes});
MOZ_ASSERT(!DecryptsAndDecodes(aCodec));
mCodecsDecoded.AppendElement(aCodec);
}
void SetCanDecrypt(const EMECodecString& aCodec,
const Maybe<CryptoSchemeSet>& aSchemes = Nothing{}) {
void SetCanDecrypt(const EMECodecString& aCodec) {
// Prevent duplicates.
MOZ_ASSERT(!ContainsDecryptedOnlyCodec(aCodec));
MOZ_ASSERT(!Decrypts(aCodec));
// Can't both decrypt and decrypt-and-decode a codec.
MOZ_ASSERT(!ContainsDecryptedAndDecodedCodec(aCodec));
mCodecsDecrypted.AppendElement(CodecSchemePair{aCodec, aSchemes});
MOZ_ASSERT(!DecryptsAndDecodes(aCodec));
mCodecsDecrypted.AppendElement(aCodec);
}
EMECodecString GetDebugInfo() const {
EMECodecString info;
info.AppendLiteral("decoding-and-decrypting:[");
for (size_t idx = 0; idx < mCodecsDecoded.Length(); idx++) {
const auto& cur = mCodecsDecoded[idx];
info.Append(cur.first);
if (cur.second) {
info.AppendLiteral("(");
info.Append(CryptoSchemeSetToString(*cur.second));
info.AppendLiteral(")");
} else {
info.AppendLiteral("(all)");
}
info.Append(mCodecsDecoded[idx]);
if (idx + 1 < mCodecsDecoded.Length()) {
info.AppendLiteral(",");
}
@ -134,15 +119,7 @@ struct KeySystemConfig {
info.AppendLiteral("],");
info.AppendLiteral("decrypting-only:[");
for (size_t idx = 0; idx < mCodecsDecrypted.Length(); idx++) {
const auto& cur = mCodecsDecrypted[idx];
info.Append(cur.first);
if (cur.second) {
info.AppendLiteral("(");
info.Append(CryptoSchemeSetToString(*cur.second));
info.AppendLiteral(")");
} else {
info.AppendLiteral("(all)");
}
info.Append(mCodecsDecrypted[idx]);
if (idx + 1 < mCodecsDecrypted.Length()) {
info.AppendLiteral(",");
}
@ -152,38 +129,8 @@ struct KeySystemConfig {
}
private:
using CodecSchemePair = std::pair<EMECodecString, Maybe<CryptoSchemeSet>>;
// These two arrays are exclusive, the codec in one array can't appear on
// another array. If CryptoSchemeSet is nothing, that means the codec has
// support for all schemes, which is our default. Setting CryptoSchemeSet
// explicitly can restrict avaiable schemes for a codec.
nsTArray<CodecSchemePair> mCodecsDecoded;
nsTArray<CodecSchemePair> mCodecsDecrypted;
bool ContainsDecryptedOnlyCodec(const EMECodecString& aCodec) const {
return std::any_of(
mCodecsDecrypted.begin(), mCodecsDecrypted.end(),
[&](const auto& aPair) { return aPair.first.Equals(aCodec); });
}
bool ContainsDecryptedAndDecodedCodec(const EMECodecString& aCodec) const {
return std::any_of(
mCodecsDecoded.begin(), mCodecsDecoded.end(),
[&](const auto& aPair) { return aPair.first.Equals(aCodec); });
}
bool CheckCodecAndSchemePair(const nsTArray<CodecSchemePair>& aArray,
const EMECodecString& aCodec,
const Maybe<CryptoScheme>& aScheme) const {
return std::any_of(aArray.begin(), aArray.end(), [&](const auto& aPair) {
if (!aPair.first.Equals(aCodec)) {
return false;
}
// No scheme is specified, which means accepting all schemes.
if (!aPair.second || !aScheme) {
return true;
}
return aPair.second->contains(*aScheme);
});
}
nsTArray<EMECodecString> mCodecsDecoded;
nsTArray<EMECodecString> mCodecsDecrypted;
};
// Return true if given key system is supported on the current device.
@ -207,6 +154,7 @@ struct KeySystemConfig {
mSessionTypes = aOther.mSessionTypes.Clone();
mVideoRobustness = aOther.mVideoRobustness.Clone();
mAudioRobustness = aOther.mAudioRobustness.Clone();
mEncryptionSchemes = aOther.mEncryptionSchemes.Clone();
mMP4 = aOther.mMP4;
mWebM = aOther.mWebM;
}
@ -221,6 +169,7 @@ struct KeySystemConfig {
mSessionTypes = aOther.mSessionTypes.Clone();
mVideoRobustness = aOther.mVideoRobustness.Clone();
mAudioRobustness = aOther.mAudioRobustness.Clone();
mEncryptionSchemes = aOther.mEncryptionSchemes.Clone();
mMP4 = aOther.mMP4;
mWebM = aOther.mWebM;
return *this;
@ -237,6 +186,7 @@ struct KeySystemConfig {
nsTArray<SessionType> mSessionTypes;
nsTArray<nsString> mVideoRobustness;
nsTArray<nsString> mAudioRobustness;
nsTArray<nsString> mEncryptionSchemes;
ContainerSupport mMP4;
ContainerSupport mWebM;
bool mIsHDCP22Compatible = false;

View File

@ -319,18 +319,17 @@ static bool CanDecryptAndDecode(
CodecType aCodecType,
const KeySystemConfig::ContainerSupport& aContainerSupport,
const nsTArray<KeySystemConfig::EMECodecString>& aCodecs,
const Maybe<CryptoScheme>& aScheme,
DecoderDoctorDiagnostics* aDiagnostics) {
MOZ_ASSERT(aCodecType != Invalid);
for (const KeySystemConfig::EMECodecString& codec : aCodecs) {
MOZ_ASSERT(!codec.IsEmpty());
if (aContainerSupport.DecryptsAndDecodes(codec, aScheme)) {
if (aContainerSupport.DecryptsAndDecodes(codec)) {
// GMP can decrypt-and-decode this codec.
continue;
}
if (aContainerSupport.Decrypts(codec, aScheme)) {
if (aContainerSupport.Decrypts(codec)) {
IgnoredErrorResult rv;
MediaSource::IsTypeSupported(aContentType, aDiagnostics, rv);
if (!rv.Failed()) {
@ -362,18 +361,29 @@ static bool CanDecryptAndDecode(
return true;
}
// https://w3c.github.io/encrypted-media/#dom-mediakeysystemmediacapability-encryptionscheme
// This convert `encryptionScheme` to the type of CryptoScheme, so that we can
// further check whether the scheme is supported or not in our media pipeline.
Maybe<CryptoScheme> ConvertEncryptionSchemeStrToScheme(
const nsString& aEncryptionScheme) {
// Returns if an encryption scheme is supported per:
// https://github.com/WICG/encrypted-media-encryption-scheme/blob/master/explainer.md
// To be supported the scheme should be one of:
// - null
// - missing (which will result in the nsString being set to void and thus null)
// - one of the schemes supported by the CDM
// If the pref to enable this behavior is not set, then the value should be
// empty/null, as the dict member will not be exposed. In this case we will
// always report support as we would before this feature was implemented.
static bool SupportsEncryptionScheme(
const nsString& aEncryptionScheme,
const nsTArray<nsString>& aSupportedEncryptionSchemes) {
MOZ_ASSERT(
DOMStringIsNull(aEncryptionScheme) ||
StaticPrefs::media_eme_encrypted_media_encryption_scheme_enabled(),
"Encryption scheme checking support must be preffed on for "
"encryptionScheme to be a non-null string");
if (DOMStringIsNull(aEncryptionScheme)) {
// "A missing or null value indicates that any encryption scheme is
// acceptable."
return Nothing();
return true;
}
auto scheme = StringToCryptoScheme(aEncryptionScheme);
return Some(scheme);
return aSupportedEncryptionSchemes.Contains(aEncryptionScheme);
}
static bool ToSessionType(const nsAString& aSessionType,
@ -468,8 +478,7 @@ static bool IsParameterUnrecognized(const nsAString& aContentType) {
return false;
}
// 3.2.2.3 Get Supported Capabilities for Audio/Video Type
// https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
// 3.1.1.3 Get Supported Capabilities for Audio/Video Type
static Sequence<MediaKeySystemMediaCapability> GetSupportedCapabilities(
const CodecType aCodecType,
const nsTArray<MediaKeySystemMediaCapability>& aRequestedCapabilities,
@ -658,20 +667,6 @@ static Sequence<MediaKeySystemMediaCapability> GetSupportedCapabilities(
NS_ConvertUTF16toUTF8(encryptionScheme).get());
continue;
}
// If encryption scheme is non-null and is not recognized or not supported
// by implementation, continue to the next iteration.
const auto scheme = ConvertEncryptionSchemeStrToScheme(encryptionScheme);
if (scheme && *scheme == CryptoScheme::None) {
EME_LOG(
"MediaKeySystemConfiguration (label='%s') "
"MediaKeySystemMediaCapability('%s','%s','%s') unsupported; "
"unsupported scheme string.",
NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(),
NS_ConvertUTF16toUTF8(contentTypeString).get(),
NS_ConvertUTF16toUTF8(robustness).get(),
NS_ConvertUTF16toUTF8(encryptionScheme).get());
continue;
}
// If robustness is not the empty string and contains an unrecognized
// value or a value not supported by implementation, continue to the
// next iteration. String comparison is case-sensitive.
@ -703,6 +698,22 @@ static Sequence<MediaKeySystemMediaCapability> GetSupportedCapabilities(
// Note: specified robustness requirements are satisfied.
}
// If preffed on: "In the Get Supported Capabilities for Audio/Video Type
// algorithm, implementations must skip capabilities specifying unsupported
// encryption schemes."
if (!SupportsEncryptionScheme(encryptionScheme,
aKeySystem.mEncryptionSchemes)) {
EME_LOG(
"MediaKeySystemConfiguration (label='%s') "
"MediaKeySystemMediaCapability('%s','%s','%s') unsupported; "
"encryption scheme unsupported by CDM requested.",
NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(),
NS_ConvertUTF16toUTF8(contentTypeString).get(),
NS_ConvertUTF16toUTF8(robustness).get(),
NS_ConvertUTF16toUTF8(encryptionScheme).get());
continue;
}
// If the user agent and implementation definitely support playback of
// encrypted media data for the combination of container, media types,
// robustness and local accumulated configuration in combination with
@ -710,7 +721,7 @@ static Sequence<MediaKeySystemMediaCapability> GetSupportedCapabilities(
const auto& containerSupport =
supportedInMP4 ? aKeySystem.mMP4 : aKeySystem.mWebM;
if (!CanDecryptAndDecode(aKeySystem.mKeySystem, contentTypeString,
majorType, containerSupport, codecs, scheme,
majorType, containerSupport, codecs,
aDiagnostics)) {
EME_LOG(
"MediaKeySystemConfiguration (label='%s') "

View File

@ -92,18 +92,16 @@ WMFCDMCapabilites::GetCapabilities(
NS_ConvertUTF16toUTF8(capabilities.keySystem()).get(),
capabilities.isHardwareDecryption());
for (const auto& v : capabilities.videoCapabilities()) {
for (const auto& scheme : v.encryptionSchemes()) {
EME_LOG("capabilities: video=%s, scheme=%s",
NS_ConvertUTF16toUTF8(v.contentType()).get(),
CryptoSchemeToString(scheme));
}
EME_LOG("capabilities: video=%s",
NS_ConvertUTF16toUTF8(v.contentType()).get());
}
for (const auto& a : capabilities.audioCapabilities()) {
for (const auto& scheme : a.encryptionSchemes()) {
EME_LOG("capabilities: audio=%s, scheme=%s",
NS_ConvertUTF16toUTF8(a.contentType()).get(),
CryptoSchemeToString(scheme));
}
EME_LOG("capabilities: audio=%s",
NS_ConvertUTF16toUTF8(a.contentType()).get());
}
for (const auto& v : capabilities.encryptionSchemes()) {
EME_LOG("capabilities: encryptionScheme=%s",
EncryptionSchemeStr(v));
}
KeySystemConfig* config = outConfigs.AppendElement();
MFCDMCapabilitiesIPDLToKeySystemConfig(capabilities, *config);

View File

@ -6,7 +6,6 @@
#include "WMFCDMProxy.h"
#include "MediaData.h"
#include "mozilla/dom/MediaKeysBinding.h"
#include "mozilla/dom/MediaKeySession.h"
#include "mozilla/dom/MediaKeySystemAccessBinding.h"
@ -123,16 +122,12 @@ WMFCDMProxy::GenerateMFCDMMediaCapabilities(
EME_LOG("WMFCDMProxy::Init %p, robustness=%s", this,
NS_ConvertUTF16toUTF8(capabilities.mRobustness).get());
outCapabilites.AppendElement(MFCDMMediaCapability{
capabilities.mContentType,
{StringToCryptoScheme(capabilities.mEncryptionScheme)},
capabilities.mRobustness});
capabilities.mContentType, capabilities.mRobustness});
} else {
EME_LOG("WMFCDMProxy::Init %p, force to robustness=%s", this,
NS_ConvertUTF16toUTF8(*forcedRobustness).get());
outCapabilites.AppendElement(MFCDMMediaCapability{
capabilities.mContentType,
{StringToCryptoScheme(capabilities.mEncryptionScheme)},
*forcedRobustness});
outCapabilites.AppendElement(
MFCDMMediaCapability{capabilities.mContentType, *forcedRobustness});
}
}
return outCapabilites;

View File

@ -341,7 +341,6 @@ bool ChromiumCDMParent::InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer,
encryptionScheme = cdm::EncryptionScheme::kCenc;
break;
case CryptoScheme::Cbcs:
case CryptoScheme::Cbcs_1_9:
encryptionScheme = cdm::EncryptionScheme::kCbcs;
break;
default:

View File

@ -848,113 +848,27 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem,
KeySystemConfig::EME_CODEC_VP9, KeySystemConfig::EME_CODEC_HEVC,
KeySystemConfig::EME_CODEC_AV1});
// Collect schemes supported by all video codecs.
static nsTArray<CryptoScheme> kSchemes({
CryptoScheme::Cenc,
CryptoScheme::Cbcs,
});
// Remember supported video codecs, which will be used when collecting audio
// codec support.
// Remember supported video codecs.
// It will be used when collecting audio codec and encryption scheme
// support.
nsTArray<KeySystemConfig::EMECodecString> supportedVideoCodecs;
if (aFlags.contains(CapabilitesFlag::NeedClearLeadCheck)) {
for (const auto& codec : kVideoCodecs) {
if (codec == KeySystemConfig::EME_CODEC_HEVC &&
!StaticPrefs::media_wmf_hevc_enabled()) {
continue;
}
CryptoSchemeSet supportedScheme;
for (const auto& scheme : kSchemes) {
nsAutoString additionalFeature(u"encryption-type=");
// If we don't specify 'encryption-iv-size', it would use 8 bytes IV as
// default [1]. If it's not supported, then we will try 16 bytes later.
// Since PlayReady 4.0 [2], 8 and 16 bytes IV are both supported. But
// We're not sure if Widevine supports both or not.
// [1]
// https://learn.microsoft.com/en-us/windows/win32/api/mfmediaengine/nf-mfmediaengine-imfextendeddrmtypesupport-istypesupportedex
// [2]
// https://learn.microsoft.com/en-us/playready/packaging/content-encryption-modes#initialization-vectors-ivs
if (scheme == CryptoScheme::Cenc) {
additionalFeature.AppendLiteral(u"cenc-clearlead,");
} else {
additionalFeature.AppendLiteral(u"cbcs-clearlead,");
}
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");
if (rv) {
supportedScheme += scheme;
break;
}
// Try 16 bytes IV.
additionalFeature.AppendLiteral(u"encryption-iv-size=16,");
rv = FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec),
nsCString(""), additionalFeature,
isHardwareDecryption);
MFCDM_PARENT_SLOG("clearlead %s IV 16 bytes %s %s",
CryptoSchemeToString(scheme), codec.get(),
rv ? "supported" : "not supported");
if (rv) {
supportedScheme += scheme;
break;
}
}
// Add a capability if supported scheme exists
if (!supportedScheme.isEmpty()) {
MFCDMMediaCapability* c =
aCapabilitiesOut.videoCapabilities().AppendElement();
c->contentType() = NS_ConvertUTF8toUTF16(codec);
c->robustness() =
GetRobustnessStringForKeySystem(aKeySystem, isHardwareDecryption);
if (supportedScheme.contains(CryptoScheme::Cenc)) {
c->encryptionSchemes().AppendElement(CryptoScheme::Cenc);
MFCDM_PARENT_SLOG("%s: +video:%s (cenc)", __func__, codec.get());
}
if (supportedScheme.contains(CryptoScheme::Cbcs)) {
c->encryptionSchemes().AppendElement(CryptoScheme::Cbcs);
MFCDM_PARENT_SLOG("%s: +video:%s (cbcs)", __func__, codec.get());
}
supportedVideoCodecs.AppendElement(codec);
}
for (const auto& codec : kVideoCodecs) {
if (codec == KeySystemConfig::EME_CODEC_HEVC &&
!StaticPrefs::media_wmf_hevc_enabled()) {
continue;
}
} else {
// Non clearlead situation for video codecs
for (const auto& codec : kVideoCodecs) {
if (codec == KeySystemConfig::EME_CODEC_HEVC &&
!StaticPrefs::media_wmf_hevc_enabled()) {
continue;
}
if (FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec),
KeySystemConfig::EMECodecString(""), nsString(u""),
isHardwareDecryption)) {
MFCDMMediaCapability* c =
aCapabilitiesOut.videoCapabilities().AppendElement();
c->contentType() = NS_ConvertUTF8toUTF16(codec);
c->robustness() =
GetRobustnessStringForKeySystem(aKeySystem, isHardwareDecryption);
// '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
c->encryptionSchemes().AppendElement(CryptoScheme::Cenc);
MFCDM_PARENT_SLOG("%s: +video:%s (cenc)", __func__, codec.get());
// Check cbcs scheme support
if (FactorySupports(
factory, aKeySystem, convertCodecToFourCC(codec),
KeySystemConfig::EMECodecString(""),
nsString(u"encryption-type=cbcs,encryption-iv-size=16,"),
isHardwareDecryption)) {
c->encryptionSchemes().AppendElement(CryptoScheme::Cbcs);
MFCDM_PARENT_SLOG("%s: +video:%s (cbcs)", __func__, codec.get());
}
supportedVideoCodecs.AppendElement(codec);
}
if (FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec),
KeySystemConfig::EMECodecString(""), nsString(u""),
isHardwareDecryption)) {
MFCDMMediaCapability* c =
aCapabilitiesOut.videoCapabilities().AppendElement();
c->contentType() = NS_ConvertUTF8toUTF16(codec);
c->robustness() =
GetRobustnessStringForKeySystem(aKeySystem, isHardwareDecryption);
MFCDM_PARENT_SLOG("%s: +video:%s", __func__, codec.get());
supportedVideoCodecs.AppendElement(codec);
}
}
if (supportedVideoCodecs.IsEmpty()) {
// Return a capabilities with no codec supported.
return;
@ -980,11 +894,95 @@ void MFCDMParent::GetCapabilities(const nsString& aKeySystem,
c->contentType() = NS_ConvertUTF8toUTF16(codec);
c->robustness() = GetRobustnessStringForKeySystem(
aKeySystem, false /* aIsHWSecure */, false /* isVideo */);
c->encryptionSchemes().AppendElement(CryptoScheme::Cenc);
MFCDM_PARENT_SLOG("%s: +audio:%s", __func__, codec.get());
}
}
// '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__);
}
// 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;
}
}
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 (aFlags.contains(CapabilitesFlag::NeedClearLeadCheck)) {
nsTArray<KeySystemConfig::EMECodecString> noClearLeadCodecs;
for (const auto& codec : supportedVideoCodecs) {
bool foundSupportedScheme = false;
for (const auto& scheme : aCapabilitiesOut.encryptionSchemes()) {
nsAutoString additionalFeature(u"encryption-type=");
// If we don't specify 'encryption-iv-size', it would use 8 bytes IV as
// default [1]. If it's not supported, then we will try 16 bytes later.
// Since PlayReady 4.0 [2], 8 and 16 bytes IV are both supported. But
// We're not sure if Widevine supports both or not.
// [1]
// https://learn.microsoft.com/en-us/windows/win32/api/mfmediaengine/nf-mfmediaengine-imfextendeddrmtypesupport-istypesupportedex
// [2]
// https://learn.microsoft.com/en-us/playready/packaging/content-encryption-modes#initialization-vectors-ivs
if (scheme == CryptoScheme::Cenc) {
additionalFeature.AppendLiteral(u"cenc-clearlead,");
} else {
additionalFeature.AppendLiteral(u"cbcs-clearlead,");
}
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");
if (rv) {
foundSupportedScheme = true;
break;
}
// Try 16 bytes IV.
additionalFeature.AppendLiteral(u"encryption-iv-size=16,");
rv = FactorySupports(factory, aKeySystem, convertCodecToFourCC(codec),
nsCString(""), additionalFeature,
isHardwareDecryption);
MFCDM_PARENT_SLOG("clearlead %s IV 16 bytes %s %s",
CryptoSchemeToString(scheme), codec.get(),
rv ? "supported" : "not supported");
if (rv) {
foundSupportedScheme = true;
break;
}
}
// Failed on all schemes, add the codec to the list and remove it later.
if (!foundSupportedScheme) {
noClearLeadCodecs.AppendElement(codec);
}
}
for (const auto& codec : noClearLeadCodecs) {
MFCDM_PARENT_SLOG("%s: -video:%s", __func__, codec.get());
aCapabilitiesOut.videoCapabilities().RemoveElementsBy(
[&codec](const MFCDMMediaCapability& aCapbilities) {
return aCapbilities.contentType() == NS_ConvertUTF8toUTF16(codec);
});
supportedVideoCodecs.RemoveElement(codec);
}
}
// 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

View File

@ -29,9 +29,9 @@ struct ParamTraits<mozilla::KeySystemConfig::SessionType>
template <>
struct ParamTraits<mozilla::CryptoScheme>
: public ContiguousEnumSerializerInclusive<
mozilla::CryptoScheme, mozilla::CryptoScheme::None,
mozilla::CryptoScheme::Cbcs_1_9> {};
: public ContiguousEnumSerializerInclusive<mozilla::CryptoScheme,
mozilla::CryptoScheme::None,
mozilla::CryptoScheme::Cbcs> {};
template <>
struct ParamTraits<mozilla::dom::MediaKeyMessageType>

View File

@ -46,7 +46,6 @@ struct MFCDMKeyExpiration {
// For GetCapabilities()
struct MFCDMMediaCapability {
nsString contentType;
CryptoScheme[] encryptionSchemes;
nsString robustness;
};
@ -56,6 +55,7 @@ struct MFCDMCapabilitiesIPDL {
MFCDMMediaCapability[] audioCapabilities;
MFCDMMediaCapability[] videoCapabilities;
SessionType[] sessionTypes;
CryptoScheme[] encryptionSchemes;
Requirement distinctiveID;
Requirement persistentState;
bool? isHDCP22Compatible;

View File

@ -108,7 +108,6 @@ RefPtr<MediaDataDecoder::InitPromise> ChromiumCDMVideoDecoder::Init() {
config.mEncryptionScheme() = cdm::EncryptionScheme::kCenc;
break;
case CryptoScheme::Cbcs:
case CryptoScheme::Cbcs_1_9:
config.mEncryptionScheme() = cdm::EncryptionScheme::kCbcs;
break;
default:

View File

@ -967,9 +967,7 @@ static CryptoInfoResult GetCryptoInfoFromSample(const MediaRawData* aSample) {
}
static bool supportsCBCS = java::CodecProxy::SupportsCBCS();
if ((cryptoObj.mCryptoScheme == CryptoScheme::Cbcs ||
cryptoObj.mCryptoScheme == CryptoScheme::Cbcs_1_9) &&
!supportsCBCS) {
if (cryptoObj.mCryptoScheme == CryptoScheme::Cbcs && !supportsCBCS) {
return CryptoInfoResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR);
}
@ -1016,7 +1014,6 @@ static CryptoInfoResult GetCryptoInfoFromSample(const MediaRawData* aSample) {
tempIV.AppendElements(cryptoObj.mIV);
break;
case CryptoScheme::Cbcs:
case CryptoScheme::Cbcs_1_9:
mode = java::sdk::MediaCodec::CRYPTO_MODE_AES_CBC;
MOZ_ASSERT(cryptoObj.mConstantIV.Length() <= kExpectedIVLength);
tempIV.AppendElements(cryptoObj.mConstantIV);

View File

@ -400,8 +400,7 @@ HRESULT MFMediaEngineStream::AddEncryptAttributes(
if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cenc) {
protectionScheme = MFSampleEncryptionProtectionScheme::
MF_SAMPLE_ENCRYPTION_PROTECTION_SCHEME_AES_CTR;
} else if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs ||
aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs_1_9) {
} else if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs) {
protectionScheme = MFSampleEncryptionProtectionScheme::
MF_SAMPLE_ENCRYPTION_PROTECTION_SCHEME_AES_CBC;
} else {

View File

@ -222,18 +222,16 @@ void UtilityAudioDecoderChild::GetKeySystemCapabilities(
EME_LOG("Received capabilities for %s",
NS_ConvertUTF16toUTF8(capabilities.keySystem()).get());
for (const auto& v : capabilities.videoCapabilities()) {
for (const auto& scheme : v.encryptionSchemes()) {
EME_LOG(" capabilities: video=%s, scheme=%s",
NS_ConvertUTF16toUTF8(v.contentType()).get(),
CryptoSchemeToString(scheme));
}
EME_LOG(" capabilities: video=%s",
NS_ConvertUTF16toUTF8(v.contentType()).get());
}
for (const auto& a : capabilities.audioCapabilities()) {
for (const auto& scheme : a.encryptionSchemes()) {
EME_LOG(" capabilities: audio=%s, scheme=%s",
NS_ConvertUTF16toUTF8(a.contentType()).get(),
CryptoSchemeToString(scheme));
}
EME_LOG(" capabilities: audio=%s",
NS_ConvertUTF16toUTF8(a.contentType()).get());
}
for (const auto& e : capabilities.encryptionSchemes()) {
EME_LOG(" capabilities: encryptionScheme=%s",
EncryptionSchemeStr(e));
}
auto* info = cdmInfo.AppendElement(fallible);
if (!info) {

View File

@ -1169,6 +1169,7 @@ var snapshotFormatters = {
capabilities.persistent = findElementInArray(array, "persistent");
capabilities.distinctive = findElementInArray(array, "distinctive");
capabilities.sessionType = findElementInArray(array, "sessionType");
capabilities.scheme = findElementInArray(array, "scheme");
capabilities.codec = getSupportedCodecs(array);
return JSON.stringify(capabilities);
}