From 46cbfd3c6b7a85f6825433e5525c3a3ae949f50b Mon Sep 17 00:00:00 2001 From: Edwin Flores Date: Thu, 26 Mar 2015 22:57:36 +1300 Subject: [PATCH] Bug 1147689 - Pass the session ID(s) of an encrypted frame into EME CDMs - r=cpearce --- dom/media/eme/CDMCaps.cpp | 11 ++++ dom/media/eme/CDMCaps.h | 3 ++ dom/media/eme/CDMProxy.cpp | 8 +++ dom/media/eme/CDMProxy.h | 3 ++ dom/media/fmp4/MP4Reader.cpp | 12 +++++ dom/media/gmp/GMPDecryptorParent.cpp | 3 +- dom/media/gmp/GMPEncryptedBufferDataImpl.cpp | 51 +++++++++++++++++-- dom/media/gmp/GMPEncryptedBufferDataImpl.h | 17 +++++++ dom/media/gmp/GMPTypes.ipdlh | 1 + dom/media/gmp/gmp-api/gmp-decryption.h | 14 +++++ .../binding/include/mp4_demuxer/DecoderData.h | 3 ++ 11 files changed, 121 insertions(+), 5 deletions(-) diff --git a/dom/media/eme/CDMCaps.cpp b/dom/media/eme/CDMCaps.cpp index 99b665875337..6af54c4356d9 100644 --- a/dom/media/eme/CDMCaps.cpp +++ b/dom/media/eme/CDMCaps.cpp @@ -194,4 +194,15 @@ CDMCaps::AutoLock::GetKeyStatusesForSession(const nsAString& aSessionId, } } +void +CDMCaps::AutoLock::GetSessionIdsForKeyId(const CencKeyId& aKeyId, + nsTArray& aOutSessionIds) +{ + for (const auto& keyStatus : mData.mKeyStatuses) { + if (keyStatus.mId == aKeyId) { + aOutSessionIds.AppendElement(NS_ConvertUTF16toUTF8(keyStatus.mSessionId)); + } + } +} + } // namespace mozilla diff --git a/dom/media/eme/CDMCaps.h b/dom/media/eme/CDMCaps.h index d4aeeb4f9bf4..ad9ad16331c3 100644 --- a/dom/media/eme/CDMCaps.h +++ b/dom/media/eme/CDMCaps.h @@ -68,6 +68,9 @@ public: void GetKeyStatusesForSession(const nsAString& aSessionId, nsTArray& aOutKeyStatuses); + void GetSessionIdsForKeyId(const CencKeyId& aKeyId, + nsTArray& aOutSessionIds); + // Sets the capabilities of the CDM. aCaps is the logical OR of the // GMP_EME_CAP_* flags from gmp-decryption.h. void SetCaps(uint64_t aCaps); diff --git a/dom/media/eme/CDMProxy.cpp b/dom/media/eme/CDMProxy.cpp index fffd646e291b..14350e54b31a 100644 --- a/dom/media/eme/CDMProxy.cpp +++ b/dom/media/eme/CDMProxy.cpp @@ -591,6 +591,14 @@ CDMProxy::gmp_Decrypted(uint32_t aId, NS_WARNING("GMPDecryptorChild returned incorrect job ID"); } +void +CDMProxy::GetSessionIdsForKeyId(const nsTArray& aKeyId, + nsTArray& aSessionIds) +{ + CDMCaps::AutoLock caps(Capabilites()); + caps.GetSessionIdsForKeyId(aKeyId, aSessionIds); +} + void CDMProxy::Terminated() { diff --git a/dom/media/eme/CDMProxy.h b/dom/media/eme/CDMProxy.h index 69a8230d460b..336db0ef8e78 100644 --- a/dom/media/eme/CDMProxy.h +++ b/dom/media/eme/CDMProxy.h @@ -166,6 +166,9 @@ public: // Main thread only. void OnKeyStatusesChange(const nsAString& aSessionId); + void GetSessionIdsForKeyId(const nsTArray& aKeyId, + nsTArray& aSessionIds); + #ifdef DEBUG bool IsOnGMPThread(); #endif diff --git a/dom/media/fmp4/MP4Reader.cpp b/dom/media/fmp4/MP4Reader.cpp index 795e262cd796..7e8d2b44d165 100644 --- a/dom/media/fmp4/MP4Reader.cpp +++ b/dom/media/fmp4/MP4Reader.cpp @@ -749,6 +749,18 @@ MP4Reader::Update(TrackType aTrack) mFoundSPSForTelemetry = AccumulateSPSTelemetry(extradata); } + if (sample && sample->mMp4Sample && sample->mMp4Sample->crypto.valid) { + CryptoSample& crypto = sample->mMp4Sample->crypto; + MOZ_ASSERT(crypto.session_ids.IsEmpty()); + + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + + nsRefPtr proxy = mDecoder->GetCDMProxy(); + MOZ_ASSERT(proxy); + + proxy->GetSessionIdsForKeyId(crypto.key, crypto.session_ids); + } + if (sample) { decoder.mDecoder->Input(sample->mMp4Sample.forget()); if (aTrack == kVideo) { diff --git a/dom/media/gmp/GMPDecryptorParent.cpp b/dom/media/gmp/GMPDecryptorParent.cpp index 72f2a5675c8b..2405f93dd2e6 100644 --- a/dom/media/gmp/GMPDecryptorParent.cpp +++ b/dom/media/gmp/GMPDecryptorParent.cpp @@ -147,7 +147,8 @@ GMPDecryptorParent::Decrypt(uint32_t aId, GMPDecryptionData data(aCrypto.key, aCrypto.iv, aCrypto.plain_sizes, - aCrypto.encrypted_sizes); + aCrypto.encrypted_sizes, + aCrypto.session_ids); unused << SendDecrypt(aId, aBuffer, data); } diff --git a/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp b/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp index 090591bbc2a5..b823fb2cd087 100644 --- a/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp +++ b/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp @@ -14,15 +14,17 @@ GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const CryptoSample& aCryp , mIV(aCrypto.iv) , mClearBytes(aCrypto.plain_sizes) , mCipherBytes(aCrypto.encrypted_sizes) + , mSessionIdList(aCrypto.session_ids) { } GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const GMPDecryptionData& aData) + : mKeyId(aData.mKeyId()) + , mIV(aData.mIV()) + , mClearBytes(aData.mClearBytes()) + , mCipherBytes(aData.mCipherBytes()) + , mSessionIdList(aData.mSessionIds()) { - mKeyId = aData.mKeyId(); - mIV = aData.mIV(); - mClearBytes = aData.mClearBytes(); - mCipherBytes = aData.mCipherBytes(); MOZ_ASSERT(mClearBytes.Length() == mCipherBytes.Length()); } @@ -37,6 +39,7 @@ GMPEncryptedBufferDataImpl::RelinquishData(GMPDecryptionData& aData) aData.mIV() = Move(mIV); aData.mClearBytes() = Move(mClearBytes); aData.mCipherBytes() = Move(mCipherBytes); + mSessionIdList.RelinquishData(aData.mSessionIds()); } const uint8_t* @@ -75,6 +78,12 @@ GMPEncryptedBufferDataImpl::CipherBytes() const return mCipherBytes.Elements(); } +const GMPStringList* +GMPEncryptedBufferDataImpl::SessionIds() const +{ + return &mSessionIdList; +} + uint32_t GMPEncryptedBufferDataImpl::NumSubsamples() const { @@ -84,5 +93,39 @@ GMPEncryptedBufferDataImpl::NumSubsamples() const return std::min(mClearBytes.Length(), mCipherBytes.Length()); } +GMPStringListImpl::GMPStringListImpl(const nsTArray& aStrings) + : mStrings(aStrings) +{ +} + +const uint32_t +GMPStringListImpl::Size() const +{ + return mStrings.Length(); +} + +void +GMPStringListImpl::StringAt(uint32_t aIndex, + const char** aOutString, + uint32_t *aOutLength) const +{ + if (NS_WARN_IF(aIndex >= Size())) { + return; + } + + *aOutString = mStrings[aIndex].BeginReading(); + *aOutLength = mStrings[aIndex].Length(); +} + +void +GMPStringListImpl::RelinquishData(nsTArray& aStrings) +{ + aStrings = Move(mStrings); +} + +GMPStringListImpl::~GMPStringListImpl() +{ +} + } // namespace gmp } // namespace mozilla diff --git a/dom/media/gmp/GMPEncryptedBufferDataImpl.h b/dom/media/gmp/GMPEncryptedBufferDataImpl.h index 168bcf5c1894..bd720cd80ab0 100644 --- a/dom/media/gmp/GMPEncryptedBufferDataImpl.h +++ b/dom/media/gmp/GMPEncryptedBufferDataImpl.h @@ -14,6 +14,20 @@ namespace mozilla { namespace gmp { +class GMPStringListImpl : public GMPStringList +{ +public: + GMPStringListImpl(const nsTArray& aStrings); + virtual const uint32_t Size() const override; + virtual void StringAt(uint32_t aIndex, + const char** aOutString, uint32_t *aOutLength) const override; + virtual ~GMPStringListImpl() override; + void RelinquishData(nsTArray& aStrings); + +private: + nsTArray mStrings; +}; + class GMPEncryptedBufferDataImpl : public GMPEncryptedBufferMetadata { private: typedef mp4_demuxer::CryptoSample CryptoSample; @@ -31,12 +45,15 @@ public: virtual uint32_t NumSubsamples() const override; virtual const uint16_t* ClearBytes() const override; virtual const uint32_t* CipherBytes() const override; + virtual const GMPStringList* SessionIds() const override; private: nsTArray mKeyId; nsTArray mIV; nsTArray mClearBytes; nsTArray mCipherBytes; + + GMPStringListImpl mSessionIdList; }; class GMPBufferImpl : public GMPBuffer { diff --git a/dom/media/gmp/GMPTypes.ipdlh b/dom/media/gmp/GMPTypes.ipdlh index df5122e714dd..7189c887a4f9 100644 --- a/dom/media/gmp/GMPTypes.ipdlh +++ b/dom/media/gmp/GMPTypes.ipdlh @@ -14,6 +14,7 @@ struct GMPDecryptionData { uint8_t[] mIV; uint16_t[] mClearBytes; uint32_t[] mCipherBytes; + nsCString[] mSessionIds; }; struct GMPVideoEncodedFrameData diff --git a/dom/media/gmp/gmp-api/gmp-decryption.h b/dom/media/gmp/gmp-api/gmp-decryption.h index fa1b41bf0e6f..160f577c27fc 100644 --- a/dom/media/gmp/gmp-api/gmp-decryption.h +++ b/dom/media/gmp/gmp-api/gmp-decryption.h @@ -19,6 +19,16 @@ #include "gmp-platform.h" +class GMPStringList { +public: + virtual const uint32_t Size() const = 0; + + virtual void StringAt(uint32_t aIndex, + const char** aOutString, uint32_t* aOutLength) const = 0; + + virtual ~GMPStringList() { } +}; + class GMPEncryptedBufferMetadata { public: // Key ID to identify the decryption key. @@ -41,6 +51,10 @@ public: virtual const uint32_t* CipherBytes() const = 0; virtual ~GMPEncryptedBufferMetadata() {} + + // The set of MediaKeySession IDs associated with this decryption key in + // the current stream. + virtual const GMPStringList* SessionIds() const = 0; }; class GMPBuffer { diff --git a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h index a55a92021991..74840d5a3d1a 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h +++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h @@ -11,6 +11,7 @@ #include "nsRefPtr.h" #include "nsString.h" #include "nsTArray.h" +#include "nsString.h" namespace stagefright { @@ -83,6 +84,8 @@ public: nsTArray plain_sizes; nsTArray encrypted_sizes; nsTArray iv; + + nsTArray session_ids; }; class TrackConfig