commit 5536bc805c2cb95644f15e828c0ae18fd70e9408
parent 39d07234cfea49c813053b01908d35626d75f1c5
Author: alwu <alwu@mozilla.com>
Date: Thu, 16 Oct 2025 19:00:37 +0000
Bug 1994550 - part1 : set CBCS related encryption information properly. r=jolin
For CBCS, the value of the crypto byte block and the skip byte block are
crucial, and it is also common to see the use of a constant IV for CBCS
for simplicity. This patch sets those attributes properly for the Media
Foundation Media Engine.
Differential Revision: https://phabricator.services.mozilla.com/D268803
Diffstat:
3 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/dom/media/ipc/PMediaDecoderParams.ipdlh b/dom/media/ipc/PMediaDecoderParams.ipdlh
@@ -22,9 +22,12 @@ struct MediaDataIPDL
struct CryptoInfo {
CryptoScheme mEncryptionScheme;
uint8_t[] mIV;
+ uint8_t[] mConstantIV;
uint8_t[] mKeyId;
uint32_t[] mClearBytes;
uint32_t[] mCipherBytes;
+ uint8_t mCryptByteBlock;
+ uint8_t mSkipByteBlock;
};
} // namespace mozilla
diff --git a/dom/media/ipc/RemoteMediaData.cpp b/dom/media/ipc/RemoteMediaData.cpp
@@ -154,9 +154,12 @@ bool ArrayOfRemoteMediaRawData::Fill(
? Some(CryptoInfo{
entry->mCrypto.mCryptoScheme,
entry->mCrypto.mIV,
+ entry->mCrypto.mConstantIV,
entry->mCrypto.mKeyId,
entry->mCrypto.mPlainSizes,
entry->mCrypto.mEncryptedSizes,
+ entry->mCrypto.mCryptByteBlock,
+ entry->mCrypto.mSkipByteBlock,
})
: Nothing()});
}
@@ -219,10 +222,13 @@ already_AddRefed<MediaRawData> ArrayOfRemoteMediaRawData::ElementAt(
CryptoSample& cypto = rawData->GetWritableCrypto();
cypto.mCryptoScheme = sample.mCryptoConfig->mEncryptionScheme();
cypto.mIV = std::move(sample.mCryptoConfig->mIV());
+ cypto.mConstantIV = std::move(sample.mCryptoConfig->mConstantIV());
cypto.mIVSize = cypto.mIV.Length();
cypto.mKeyId = std::move(sample.mCryptoConfig->mKeyId());
cypto.mPlainSizes = std::move(sample.mCryptoConfig->mClearBytes());
cypto.mEncryptedSizes = std::move(sample.mCryptoConfig->mCipherBytes());
+ cypto.mCryptByteBlock = sample.mCryptoConfig->mCryptByteBlock();
+ cypto.mSkipByteBlock = sample.mCryptoConfig->mSkipByteBlock();
}
perfRecorder.Record();
return rawData.forget();
diff --git a/dom/media/platforms/wmf/MFMediaEngineStream.cpp b/dom/media/platforms/wmf/MFMediaEngineStream.cpp
@@ -366,10 +366,10 @@ HRESULT MFMediaEngineStream::CreateInputSample(IMFSample** aSample) {
MOZ_ASSERT(mRawDataQueueForFeedingEngine.GetSize() != 0);
RefPtr<MediaRawData> data = mRawDataQueueForFeedingEngine.PopFront();
SLOGV("CreateInputSample, pop data [%" PRId64 ", %" PRId64
- "] (duration=%" PRId64 ", kf=%d), queue size=%zu",
+ "] (duration=%" PRId64 ", kf=%d, encrypted=%d), queue size=%zu",
data->mTime.ToMicroseconds(), data->GetEndTime().ToMicroseconds(),
data->mDuration.ToMicroseconds(), data->mKeyframe,
- mRawDataQueueForFeedingEngine.GetSize());
+ data->mCrypto.IsEncrypted(), mRawDataQueueForFeedingEngine.GetSize());
PROFILER_MARKER(
nsPrintfCString(
"pop %s (stream=%" PRIu64 ")",
@@ -414,12 +414,26 @@ HRESULT MFMediaEngineStream::AddEncryptAttributes(
// Scheme
MFSampleEncryptionProtectionScheme protectionScheme;
if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cenc) {
+ SLOG("Set CENC encryption");
protectionScheme = MFSampleEncryptionProtectionScheme::
MF_SAMPLE_ENCRYPTION_PROTECTION_SCHEME_AES_CTR;
} else if (aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs ||
aCryptoConfig.mCryptoScheme == CryptoScheme::Cbcs_1_9) {
protectionScheme = MFSampleEncryptionProtectionScheme::
MF_SAMPLE_ENCRYPTION_PROTECTION_SCHEME_AES_CBC;
+ SLOG("Set CBC pattern encryption, crypt=%u, skip=%u",
+ aCryptoConfig.mCryptByteBlock, aCryptoConfig.mSkipByteBlock);
+ // Only need to set them when they are non-zero. See
+ // https://learn.microsoft.com/en-us/windows/win32/medfound/mfsampleextension-encryption-cryptbyteblock
+ // https://learn.microsoft.com/en-us/windows/win32/medfound/mfsampleextension-encryption-skipbyteblock
+ if (aCryptoConfig.mCryptByteBlock > 0 && aCryptoConfig.mSkipByteBlock > 0) {
+ RETURN_IF_FAILED(
+ aSample->SetUINT32(MFSampleExtension_Encryption_CryptByteBlock,
+ aCryptoConfig.mCryptByteBlock));
+ RETURN_IF_FAILED(
+ aSample->SetUINT32(MFSampleExtension_Encryption_SkipByteBlock,
+ aCryptoConfig.mSkipByteBlock));
+ }
} else {
SLOG("Unexpected encryption scheme");
return MF_E_UNEXPECTED;
@@ -439,10 +453,22 @@ HRESULT MFMediaEngineStream::AddEncryptAttributes(
// to store last key id and set it in CDM to refresh the decryptor.
// IV
- RETURN_IF_FAILED(aSample->SetBlob(
- MFSampleExtension_Encryption_SampleID,
- reinterpret_cast<const uint8_t*>(aCryptoConfig.mIV.Elements()),
- aCryptoConfig.mIVSize));
+ if (aCryptoConfig.mIVSize != 0) {
+ // Per-sample IV, usually seen in CENC.
+ SLOG("Use sample IV for decryption, IV size=%u", aCryptoConfig.mIVSize);
+ RETURN_IF_FAILED(aSample->SetBlob(
+ MFSampleExtension_Encryption_SampleID,
+ reinterpret_cast<const uint8_t*>(aCryptoConfig.mIV.Elements()),
+ aCryptoConfig.mIVSize));
+ } else {
+ // A constant IV for all samples, usually seen in CBCS.
+ SLOG("Use constant IV for decryption, constantIV length=%zu",
+ aCryptoConfig.mConstantIV.Length());
+ RETURN_IF_FAILED(aSample->SetBlob(
+ MFSampleExtension_Encryption_SampleID,
+ reinterpret_cast<const uint8_t*>(aCryptoConfig.mConstantIV.Elements()),
+ aCryptoConfig.mConstantIV.Length()));
+ }
// Subsample entries.
MOZ_ASSERT(aCryptoConfig.mEncryptedSizes.Length() ==