ClearKeyCDM.cpp (7362B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ClearKeyCDM.h" 8 9 #include "ClearKeyUtils.h" 10 11 using namespace cdm; 12 13 ClearKeyCDM::ClearKeyCDM(Host_11* aHost) { 14 mHost = aHost; 15 mSessionManager = new ClearKeySessionManager(mHost); 16 } 17 18 void ClearKeyCDM::Initialize(bool aAllowDistinctiveIdentifier, 19 bool aAllowPersistentState, 20 bool aUseHardwareSecureCodecs) { 21 mSessionManager->Init(aAllowDistinctiveIdentifier, aAllowPersistentState); 22 // We call mHost->OnInitialized() in the session manager once it has 23 // initialized. 24 } 25 26 void ClearKeyCDM::GetStatusForPolicy(uint32_t aPromiseId, 27 const Policy& aPolicy) { 28 // Pretend the device is HDCP 2.1 compliant. 29 const cdm::HdcpVersion kDeviceHdcpVersion = cdm::kHdcpVersion2_1; 30 if (aPolicy.min_hdcp_version <= kDeviceHdcpVersion) { 31 mHost->OnResolveKeyStatusPromise(aPromiseId, KeyStatus::kUsable); 32 } else { 33 mHost->OnResolveKeyStatusPromise(aPromiseId, KeyStatus::kOutputRestricted); 34 } 35 } 36 void ClearKeyCDM::SetServerCertificate(uint32_t aPromiseId, 37 const uint8_t* aServerCertificateData, 38 uint32_t aServerCertificateDataSize) { 39 mSessionManager->SetServerCertificate(aPromiseId, aServerCertificateData, 40 aServerCertificateDataSize); 41 } 42 43 void ClearKeyCDM::CreateSessionAndGenerateRequest(uint32_t aPromiseId, 44 SessionType aSessionType, 45 InitDataType aInitDataType, 46 const uint8_t* aInitData, 47 uint32_t aInitDataSize) { 48 mSessionManager->CreateSession(aPromiseId, aInitDataType, aInitData, 49 aInitDataSize, aSessionType); 50 } 51 52 void ClearKeyCDM::LoadSession(uint32_t aPromiseId, SessionType aSessionType, 53 const char* aSessionId, uint32_t aSessionIdSize) { 54 mSessionManager->LoadSession(aPromiseId, aSessionId, aSessionIdSize); 55 } 56 57 void ClearKeyCDM::UpdateSession(uint32_t aPromiseId, const char* aSessionId, 58 uint32_t aSessionIdSize, 59 const uint8_t* aResponse, 60 uint32_t aResponseSize) { 61 mSessionManager->UpdateSession(aPromiseId, aSessionId, aSessionIdSize, 62 aResponse, aResponseSize); 63 } 64 65 void ClearKeyCDM::CloseSession(uint32_t aPromiseId, const char* aSessionId, 66 uint32_t aSessionIdSize) { 67 mSessionManager->CloseSession(aPromiseId, aSessionId, aSessionIdSize); 68 } 69 70 void ClearKeyCDM::RemoveSession(uint32_t aPromiseId, const char* aSessionId, 71 uint32_t aSessionIdSize) { 72 mSessionManager->RemoveSession(aPromiseId, aSessionId, aSessionIdSize); 73 } 74 75 void ClearKeyCDM::TimerExpired(void* aContext) { 76 // Clearkey is not interested in timers, so this method has not been 77 // implemented. 78 assert(false); 79 } 80 81 Status ClearKeyCDM::Decrypt(const InputBuffer_2& aEncryptedBuffer, 82 DecryptedBlock* aDecryptedBuffer) { 83 if (mIsProtectionQueryEnabled) { 84 // Piggyback this check onto Decrypt calls. If Clearkey implements a timer 85 // based approach for firing events, we could instead trigger the check 86 // using that mechanism. 87 mSessionManager->QueryOutputProtectionStatusIfNeeded(); 88 } 89 return mSessionManager->Decrypt(aEncryptedBuffer, aDecryptedBuffer); 90 } 91 92 Status ClearKeyCDM::InitializeAudioDecoder( 93 const AudioDecoderConfig_2& aAudioDecoderConfig) { 94 // Audio decoding is not supported by Clearkey because Widevine doesn't 95 // support it and Clearkey's raison d'etre is to provide test coverage 96 // for paths that Widevine will exercise in the wild. 97 return Status::kDecodeError; 98 } 99 100 Status ClearKeyCDM::InitializeVideoDecoder( 101 const VideoDecoderConfig_2& aVideoDecoderConfig) { 102 #ifdef ENABLE_WMF 103 mVideoDecoder = new VideoDecoder(mHost); 104 return mVideoDecoder->InitDecode(aVideoDecoderConfig); 105 #else 106 return Status::kDecodeError; 107 #endif 108 } 109 110 void ClearKeyCDM::DeinitializeDecoder(StreamType aDecoderType) { 111 #ifdef ENABLE_WMF 112 if (aDecoderType == StreamType::kStreamTypeVideo) { 113 mVideoDecoder->DecodingComplete(); 114 mVideoDecoder = nullptr; 115 } 116 #endif 117 } 118 119 void ClearKeyCDM::ResetDecoder(StreamType aDecoderType) { 120 #ifdef ENABLE_WMF 121 if (aDecoderType == StreamType::kStreamTypeVideo) { 122 mVideoDecoder->Reset(); 123 } 124 #endif 125 } 126 127 Status ClearKeyCDM::DecryptAndDecodeFrame(const InputBuffer_2& aEncryptedBuffer, 128 VideoFrame* aVideoFrame) { 129 #ifdef ENABLE_WMF 130 if (mIsProtectionQueryEnabled) { 131 // Piggyback this check onto Decrypt + Decode. If Clearkey implements a 132 // timer based approach for firing events, we could instead trigger the 133 // check using that mechanism. 134 mSessionManager->QueryOutputProtectionStatusIfNeeded(); 135 } 136 return mVideoDecoder->Decode(aEncryptedBuffer, aVideoFrame); 137 #else 138 return Status::kDecodeError; 139 #endif 140 } 141 142 Status ClearKeyCDM::DecryptAndDecodeSamples( 143 const InputBuffer_2& aEncryptedBuffer, AudioFrames* aAudioFrame) { 144 // Audio decoding is not supported by Clearkey because Widevine doesn't 145 // support it and Clearkey's raison d'etre is to provide test coverage 146 // for paths that Widevine will exercise in the wild. 147 return Status::kDecodeError; 148 } 149 150 void ClearKeyCDM::OnPlatformChallengeResponse( 151 const PlatformChallengeResponse& aResponse) { 152 // This function should never be called and is not supported. 153 assert(false); 154 } 155 156 void ClearKeyCDM::OnQueryOutputProtectionStatus( 157 QueryResult aResult, uint32_t aLinkMask, uint32_t aOutputProtectionMask) { 158 // The higher level GMP machinery should not forward us query information 159 // unless we've requested it (even if mutiple CDMs exist at once and some 160 // others are reqeusting this info). If this assert fires we're violating 161 // that. 162 MOZ_ASSERT(mIsProtectionQueryEnabled, 163 "Should only receive a protection status " 164 "mIsProtectionQueryEnabled is true"); 165 // The session manager handles the guts of this for ClearKey. 166 mSessionManager->OnQueryOutputProtectionStatus(aResult, aLinkMask, 167 aOutputProtectionMask); 168 } 169 170 void ClearKeyCDM::OnStorageId(uint32_t aVersion, const uint8_t* aStorageId, 171 uint32_t aStorageIdSize) { 172 // This function should never be called and is not supported. 173 assert(false); 174 } 175 176 void ClearKeyCDM::Destroy() { 177 mSessionManager->DecryptingComplete(); 178 #ifdef ENABLE_WMF 179 // If we have called 'DeinitializeDecoder' mVideoDecoder will be null. 180 if (mVideoDecoder) { 181 mVideoDecoder->DecodingComplete(); 182 } 183 #endif 184 delete this; 185 } 186 187 void ClearKeyCDM::EnableProtectionQuery() { 188 MOZ_ASSERT(!mIsProtectionQueryEnabled, 189 "Should not be called more than once per CDM"); 190 mIsProtectionQueryEnabled = true; 191 }