| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ | |
| 6 #define MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <queue> | |
| 10 #include <string> | |
| 11 | |
| 12 #include "base/basictypes.h" | |
| 13 #include "media/cdm/api/content_decryption_module.h" | |
| 14 #include "media/cdm/ppapi/cdm_helpers.h" | |
| 15 #include "media/cdm/ppapi/supported_cdm_versions.h" | |
| 16 #include "ppapi/cpp/logging.h" | |
| 17 | |
| 18 namespace media { | |
| 19 | |
| 20 // CdmWrapper wraps different versions of ContentDecryptionModule interfaces and | |
| 21 // exposes a common interface to the caller. | |
| 22 // | |
| 23 // The caller should call CdmWrapper::Create() to create a CDM instance. | |
| 24 // CdmWrapper will first try to create a CDM instance that supports the latest | |
| 25 // CDM interface (ContentDecryptionModule). If such an instance cannot be | |
| 26 // created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM | |
| 27 // that supports an older version of CDM interface (e.g. | |
| 28 // ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper | |
| 29 // calls to corresponding ContentDecryptionModule calls. | |
| 30 // | |
| 31 // Note that CdmWrapper interface always reflects the latest state of content | |
| 32 // decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private). | |
| 33 // | |
| 34 // Since this file is highly templated and default implementations are short | |
| 35 // (just a shim layer in most cases), everything is done in this header file. | |
| 36 class CdmWrapper { | |
| 37 public: | |
| 38 static CdmWrapper* Create(const char* key_system, | |
| 39 uint32_t key_system_size, | |
| 40 GetCdmHostFunc get_cdm_host_func, | |
| 41 void* user_data); | |
| 42 | |
| 43 virtual ~CdmWrapper() {}; | |
| 44 | |
| 45 virtual void Initialize(bool allow_distinctive_identifier, | |
| 46 bool allow_persistent_state) = 0; | |
| 47 virtual void SetServerCertificate(uint32_t promise_id, | |
| 48 const uint8_t* server_certificate_data, | |
| 49 uint32_t server_certificate_data_size) = 0; | |
| 50 virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, | |
| 51 cdm::SessionType session_type, | |
| 52 cdm::InitDataType init_data_type, | |
| 53 const uint8_t* init_data, | |
| 54 uint32_t init_data_size) = 0; | |
| 55 virtual void LoadSession(uint32_t promise_id, | |
| 56 cdm::SessionType session_type, | |
| 57 const char* session_id, | |
| 58 uint32_t session_id_size) = 0; | |
| 59 virtual void UpdateSession(uint32_t promise_id, | |
| 60 const char* session_id, | |
| 61 uint32_t session_id_size, | |
| 62 const uint8_t* response, | |
| 63 uint32_t response_size) = 0; | |
| 64 virtual void CloseSession(uint32_t promise_id, | |
| 65 const char* session_id, | |
| 66 uint32_t session_id_size) = 0; | |
| 67 virtual void RemoveSession(uint32_t promise_id, | |
| 68 const char* session_id, | |
| 69 uint32_t session_id_size) = 0; | |
| 70 virtual void TimerExpired(void* context) = 0; | |
| 71 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, | |
| 72 cdm::DecryptedBlock* decrypted_buffer) = 0; | |
| 73 virtual cdm::Status InitializeAudioDecoder( | |
| 74 const cdm::AudioDecoderConfig& audio_decoder_config) = 0; | |
| 75 virtual cdm::Status InitializeVideoDecoder( | |
| 76 const cdm::VideoDecoderConfig& video_decoder_config) = 0; | |
| 77 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0; | |
| 78 virtual void ResetDecoder(cdm::StreamType decoder_type) = 0; | |
| 79 virtual cdm::Status DecryptAndDecodeFrame( | |
| 80 const cdm::InputBuffer& encrypted_buffer, | |
| 81 cdm::VideoFrame* video_frame) = 0; | |
| 82 virtual cdm::Status DecryptAndDecodeSamples( | |
| 83 const cdm::InputBuffer& encrypted_buffer, | |
| 84 cdm::AudioFrames* audio_frames) = 0; | |
| 85 virtual void OnPlatformChallengeResponse( | |
| 86 const cdm::PlatformChallengeResponse& response) = 0; | |
| 87 virtual void OnQueryOutputProtectionStatus( | |
| 88 cdm::QueryResult result, | |
| 89 uint32_t link_mask, | |
| 90 uint32_t output_protection_mask) = 0; | |
| 91 | |
| 92 protected: | |
| 93 CdmWrapper() {} | |
| 94 | |
| 95 private: | |
| 96 DISALLOW_COPY_AND_ASSIGN(CdmWrapper); | |
| 97 }; | |
| 98 | |
| 99 // Template class that does the CdmWrapper -> CdmInterface conversion. Default | |
| 100 // implementations are provided. Any methods that need special treatment should | |
| 101 // be specialized. | |
| 102 template <class CdmInterface> | |
| 103 class CdmWrapperImpl : public CdmWrapper { | |
| 104 public: | |
| 105 static CdmWrapper* Create(const char* key_system, | |
| 106 uint32_t key_system_size, | |
| 107 GetCdmHostFunc get_cdm_host_func, | |
| 108 void* user_data) { | |
| 109 void* cdm_instance = ::CreateCdmInstance( | |
| 110 CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func, | |
| 111 user_data); | |
| 112 if (!cdm_instance) | |
| 113 return NULL; | |
| 114 | |
| 115 return new CdmWrapperImpl<CdmInterface>( | |
| 116 static_cast<CdmInterface*>(cdm_instance)); | |
| 117 } | |
| 118 | |
| 119 ~CdmWrapperImpl() override { | |
| 120 cdm_->Destroy(); | |
| 121 } | |
| 122 | |
| 123 void Initialize(bool allow_distinctive_identifier, | |
| 124 bool allow_persistent_state) override { | |
| 125 cdm_->Initialize(allow_distinctive_identifier, allow_persistent_state); | |
| 126 } | |
| 127 | |
| 128 void SetServerCertificate( | |
| 129 uint32_t promise_id, | |
| 130 const uint8_t* server_certificate_data, | |
| 131 uint32_t server_certificate_data_size) override { | |
| 132 cdm_->SetServerCertificate( | |
| 133 promise_id, server_certificate_data, server_certificate_data_size); | |
| 134 } | |
| 135 | |
| 136 void CreateSessionAndGenerateRequest( | |
| 137 uint32_t promise_id, | |
| 138 cdm::SessionType session_type, | |
| 139 cdm::InitDataType init_data_type, | |
| 140 const uint8_t* init_data, | |
| 141 uint32_t init_data_size) override { | |
| 142 cdm_->CreateSessionAndGenerateRequest( | |
| 143 promise_id, session_type, init_data_type, init_data, init_data_size); | |
| 144 } | |
| 145 | |
| 146 void LoadSession(uint32_t promise_id, | |
| 147 cdm::SessionType session_type, | |
| 148 const char* session_id, | |
| 149 uint32_t session_id_size) override { | |
| 150 cdm_->LoadSession(promise_id, session_type, session_id, session_id_size); | |
| 151 } | |
| 152 | |
| 153 void UpdateSession(uint32_t promise_id, | |
| 154 const char* session_id, | |
| 155 uint32_t session_id_size, | |
| 156 const uint8_t* response, | |
| 157 uint32_t response_size) override { | |
| 158 cdm_->UpdateSession(promise_id, session_id, session_id_size, response, | |
| 159 response_size); | |
| 160 } | |
| 161 | |
| 162 void CloseSession(uint32_t promise_id, | |
| 163 const char* session_id, | |
| 164 uint32_t session_id_size) override { | |
| 165 cdm_->CloseSession(promise_id, session_id, session_id_size); | |
| 166 } | |
| 167 | |
| 168 void RemoveSession(uint32_t promise_id, | |
| 169 const char* session_id, | |
| 170 uint32_t session_id_size) override { | |
| 171 cdm_->RemoveSession(promise_id, session_id, session_id_size); | |
| 172 } | |
| 173 | |
| 174 void TimerExpired(void* context) override { | |
| 175 cdm_->TimerExpired(context); | |
| 176 } | |
| 177 | |
| 178 cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, | |
| 179 cdm::DecryptedBlock* decrypted_buffer) override { | |
| 180 return cdm_->Decrypt(encrypted_buffer, decrypted_buffer); | |
| 181 } | |
| 182 | |
| 183 cdm::Status InitializeAudioDecoder( | |
| 184 const cdm::AudioDecoderConfig& audio_decoder_config) override { | |
| 185 return cdm_->InitializeAudioDecoder(audio_decoder_config); | |
| 186 } | |
| 187 | |
| 188 cdm::Status InitializeVideoDecoder( | |
| 189 const cdm::VideoDecoderConfig& video_decoder_config) override { | |
| 190 return cdm_->InitializeVideoDecoder(video_decoder_config); | |
| 191 } | |
| 192 | |
| 193 void DeinitializeDecoder(cdm::StreamType decoder_type) override { | |
| 194 cdm_->DeinitializeDecoder(decoder_type); | |
| 195 } | |
| 196 | |
| 197 void ResetDecoder(cdm::StreamType decoder_type) override { | |
| 198 cdm_->ResetDecoder(decoder_type); | |
| 199 } | |
| 200 | |
| 201 cdm::Status DecryptAndDecodeFrame( | |
| 202 const cdm::InputBuffer& encrypted_buffer, | |
| 203 cdm::VideoFrame* video_frame) override { | |
| 204 return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); | |
| 205 } | |
| 206 | |
| 207 cdm::Status DecryptAndDecodeSamples( | |
| 208 const cdm::InputBuffer& encrypted_buffer, | |
| 209 cdm::AudioFrames* audio_frames) override { | |
| 210 return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); | |
| 211 } | |
| 212 | |
| 213 void OnPlatformChallengeResponse( | |
| 214 const cdm::PlatformChallengeResponse& response) override { | |
| 215 cdm_->OnPlatformChallengeResponse(response); | |
| 216 } | |
| 217 | |
| 218 void OnQueryOutputProtectionStatus( | |
| 219 cdm::QueryResult result, | |
| 220 uint32_t link_mask, | |
| 221 uint32_t output_protection_mask) override { | |
| 222 cdm_->OnQueryOutputProtectionStatus(result, link_mask, | |
| 223 output_protection_mask); | |
| 224 } | |
| 225 | |
| 226 private: | |
| 227 CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) { | |
| 228 PP_DCHECK(cdm_); | |
| 229 } | |
| 230 | |
| 231 CdmInterface* cdm_; | |
| 232 | |
| 233 DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl); | |
| 234 }; | |
| 235 | |
| 236 // Overrides for the cdm::Host_7 methods. | |
| 237 // TODO(jrummell): Remove these once Host_7 interface is removed. | |
| 238 | |
| 239 template <> | |
| 240 void CdmWrapperImpl<cdm::ContentDecryptionModule_7>::Initialize( | |
| 241 bool allow_distinctive_identifier, | |
| 242 bool allow_persistent_state) { | |
| 243 } | |
| 244 | |
| 245 template <> | |
| 246 void CdmWrapperImpl<cdm::ContentDecryptionModule_7>:: | |
| 247 CreateSessionAndGenerateRequest(uint32_t promise_id, | |
| 248 cdm::SessionType session_type, | |
| 249 cdm::InitDataType init_data_type, | |
| 250 const uint8_t* init_data, | |
| 251 uint32_t init_data_size) { | |
| 252 std::string init_data_type_as_string = "unknown"; | |
| 253 switch (init_data_type) { | |
| 254 case cdm::kCenc: | |
| 255 init_data_type_as_string = "cenc"; | |
| 256 break; | |
| 257 case cdm::kKeyIds: | |
| 258 init_data_type_as_string = "keyids"; | |
| 259 break; | |
| 260 case cdm::kWebM: | |
| 261 init_data_type_as_string = "webm"; | |
| 262 break; | |
| 263 } | |
| 264 | |
| 265 cdm_->CreateSessionAndGenerateRequest( | |
| 266 promise_id, session_type, &init_data_type_as_string[0], | |
| 267 init_data_type_as_string.length(), init_data, init_data_size); | |
| 268 } | |
| 269 | |
| 270 CdmWrapper* CdmWrapper::Create(const char* key_system, | |
| 271 uint32_t key_system_size, | |
| 272 GetCdmHostFunc get_cdm_host_func, | |
| 273 void* user_data) { | |
| 274 static_assert(cdm::ContentDecryptionModule::kVersion == | |
| 275 cdm::ContentDecryptionModule_8::kVersion, | |
| 276 "update the code below"); | |
| 277 | |
| 278 // Ensure IsSupportedCdmInterfaceVersion() matches this implementation. | |
| 279 // Always update this DCHECK when updating this function. | |
| 280 // If this check fails, update this function and DCHECK or update | |
| 281 // IsSupportedCdmInterfaceVersion(). | |
| 282 PP_DCHECK(!IsSupportedCdmInterfaceVersion( | |
| 283 cdm::ContentDecryptionModule_8::kVersion + 1) && | |
| 284 IsSupportedCdmInterfaceVersion( | |
| 285 cdm::ContentDecryptionModule_8::kVersion) && | |
| 286 IsSupportedCdmInterfaceVersion( | |
| 287 cdm::ContentDecryptionModule_7::kVersion) && | |
| 288 !IsSupportedCdmInterfaceVersion( | |
| 289 cdm::ContentDecryptionModule_7::kVersion - 1)); | |
| 290 | |
| 291 // Try to create the CDM using the latest CDM interface version. | |
| 292 CdmWrapper* cdm_wrapper = | |
| 293 CdmWrapperImpl<cdm::ContentDecryptionModule>::Create( | |
| 294 key_system, key_system_size, get_cdm_host_func, user_data); | |
| 295 | |
| 296 // If |cdm_wrapper| is NULL, try to create the CDM using older supported | |
| 297 // versions of the CDM interface here. | |
| 298 if (!cdm_wrapper) { | |
| 299 cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_7>::Create( | |
| 300 key_system, key_system_size, get_cdm_host_func, user_data); | |
| 301 } | |
| 302 | |
| 303 return cdm_wrapper; | |
| 304 } | |
| 305 | |
| 306 // When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain | |
| 307 // stub implementations for new or modified methods that the older CDM interface | |
| 308 // does not have. | |
| 309 // Also update supported_cdm_versions.h. | |
| 310 static_assert(cdm::ContentDecryptionModule::kVersion == | |
| 311 cdm::ContentDecryptionModule_8::kVersion, | |
| 312 "ensure cdm wrapper templates have old version support"); | |
| 313 | |
| 314 } // namespace media | |
| 315 | |
| 316 #endif // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ | |
| OLD | NEW |