cdm_wrapper.h revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 "base/basictypes.h" 9#include "media/cdm/ppapi/api/content_decryption_module.h" 10#include "media/cdm/ppapi/cdm_helpers.h" 11#include "media/cdm/ppapi/supported_cdm_versions.h" 12#include "ppapi/cpp/logging.h" 13 14namespace media { 15 16// CdmWrapper wraps different versions of ContentDecryptionModule interfaces and 17// exposes a common interface to the caller. 18// 19// The caller should call CdmWrapper::Create() to create a CDM instance. 20// CdmWrapper will first try to create a CDM instance that supports the latest 21// CDM interface (ContentDecryptionModule). If such an instance cannot be 22// created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM 23// that supports an older version of CDM interface (e.g. 24// ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper 25// calls to corresponding ContentDecryptionModule calls. 26// 27// Note that CdmWrapper interface always reflects the latest state of content 28// decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private). 29// 30// Since this file is highly templated and default implementations are short 31// (just a shim layer in most cases), everything is done in this header file. 32class CdmWrapper { 33 public: 34 static CdmWrapper* Create(const char* key_system, 35 uint32_t key_system_size, 36 GetCdmHostFunc get_cdm_host_func, 37 void* user_data); 38 39 virtual ~CdmWrapper() {}; 40 41 virtual cdm::Status GenerateKeyRequest(const char* type, 42 uint32_t type_size, 43 const uint8_t* init_data, 44 uint32_t init_data_size) = 0; 45 virtual cdm::Status AddKey(const char* session_id, 46 uint32_t session_id_size, 47 const uint8_t* key, 48 uint32_t key_size, 49 const uint8_t* key_id, 50 uint32_t key_id_size) = 0; 51 virtual cdm::Status CancelKeyRequest(const char* session_id, 52 uint32_t session_id_size) = 0; 53 virtual void TimerExpired(void* context) = 0; 54 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, 55 cdm::DecryptedBlock* decrypted_buffer) = 0; 56 virtual cdm::Status InitializeAudioDecoder( 57 const cdm::AudioDecoderConfig& audio_decoder_config) = 0; 58 virtual cdm::Status InitializeVideoDecoder( 59 const cdm::VideoDecoderConfig& video_decoder_config) = 0; 60 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0; 61 virtual void ResetDecoder(cdm::StreamType decoder_type) = 0; 62 virtual cdm::Status DecryptAndDecodeFrame( 63 const cdm::InputBuffer& encrypted_buffer, 64 cdm::VideoFrame* video_frame) = 0; 65 virtual cdm::Status DecryptAndDecodeSamples( 66 const cdm::InputBuffer& encrypted_buffer, 67 cdm::AudioFrames* audio_frames) = 0; 68 virtual void OnPlatformChallengeResponse( 69 const cdm::PlatformChallengeResponse& response) = 0; 70 virtual void OnQueryOutputProtectionStatus( 71 uint32_t link_mask, 72 uint32_t output_protection_mask) = 0; 73 74 protected: 75 CdmWrapper() {}; 76 77 private: 78 DISALLOW_COPY_AND_ASSIGN(CdmWrapper); 79}; 80 81// Template class that does the CdmWrapper -> CdmInterface conversion. Default 82// implementations are provided. Any methods that need special treatment should 83// be specialized. 84template <class CdmInterface> 85class CdmWrapperImpl : public CdmWrapper { 86 public: 87 static CdmWrapper* Create(const char* key_system, 88 uint32_t key_system_size, 89 GetCdmHostFunc get_cdm_host_func, 90 void* user_data) { 91 void* cdm_instance = ::CreateCdmInstance( 92 CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func, 93 user_data); 94 if (!cdm_instance) 95 return NULL; 96 97 return new CdmWrapperImpl<CdmInterface>( 98 static_cast<CdmInterface*>(cdm_instance)); 99 } 100 101 virtual ~CdmWrapperImpl() { 102 cdm_->Destroy(); 103 } 104 105 virtual cdm::Status GenerateKeyRequest(const char* type, 106 uint32_t type_size, 107 const uint8_t* init_data, 108 uint32_t init_data_size) OVERRIDE { 109 return cdm_->GenerateKeyRequest(type, type_size, init_data, init_data_size); 110 } 111 112 virtual cdm::Status AddKey(const char* session_id, 113 uint32_t session_id_size, 114 const uint8_t* key, 115 uint32_t key_size, 116 const uint8_t* key_id, 117 uint32_t key_id_size) OVERRIDE { 118 return cdm_->AddKey( 119 session_id, session_id_size, key, key_size, key_id, key_id_size); 120 } 121 122 virtual cdm::Status CancelKeyRequest(const char* session_id, 123 uint32_t session_id_size) OVERRIDE { 124 return cdm_->CancelKeyRequest(session_id, session_id_size); 125 } 126 127 virtual void TimerExpired(void* context) OVERRIDE { 128 cdm_->TimerExpired(context); 129 } 130 131 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, 132 cdm::DecryptedBlock* decrypted_buffer) OVERRIDE { 133 return cdm_->Decrypt(encrypted_buffer, decrypted_buffer); 134 } 135 136 virtual cdm::Status InitializeAudioDecoder( 137 const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE { 138 return cdm_->InitializeAudioDecoder(audio_decoder_config); 139 } 140 141 virtual cdm::Status InitializeVideoDecoder( 142 const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE { 143 return cdm_->InitializeVideoDecoder(video_decoder_config); 144 } 145 146 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE { 147 cdm_->DeinitializeDecoder(decoder_type); 148 } 149 150 virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE { 151 cdm_->ResetDecoder(decoder_type); 152 } 153 154 virtual cdm::Status DecryptAndDecodeFrame( 155 const cdm::InputBuffer& encrypted_buffer, 156 cdm::VideoFrame* video_frame) OVERRIDE { 157 return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); 158 } 159 160 virtual cdm::Status DecryptAndDecodeSamples( 161 const cdm::InputBuffer& encrypted_buffer, 162 cdm::AudioFrames* audio_frames) OVERRIDE { 163 return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); 164 } 165 166 virtual void OnPlatformChallengeResponse( 167 const cdm::PlatformChallengeResponse& response) OVERRIDE { 168 cdm_->OnPlatformChallengeResponse(response); 169 } 170 171 virtual void OnQueryOutputProtectionStatus( 172 uint32_t link_mask, 173 uint32_t output_protection_mask) OVERRIDE { 174 cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask); 175 } 176 177 private: 178 CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) { 179 PP_DCHECK(cdm_); 180 } 181 182 CdmInterface* cdm_; 183 184 DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl); 185}; 186 187// Specializations for ContentDecryptionModule_1. 188 189template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: 190 OnPlatformChallengeResponse( 191 const cdm::PlatformChallengeResponse& response) { 192 PP_NOTREACHED(); 193} 194 195template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: 196 OnQueryOutputProtectionStatus(uint32_t link_mask, 197 uint32_t output_protection_mask) { 198 PP_NOTREACHED(); 199} 200 201template <> cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: 202 DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer, 203 cdm::AudioFrames* audio_frames) { 204 AudioFramesImpl audio_frames_1; 205 cdm::Status status = 206 cdm_->DecryptAndDecodeSamples(encrypted_buffer, &audio_frames_1); 207 if (status != cdm::kSuccess) 208 return status; 209 210 audio_frames->SetFrameBuffer(audio_frames_1.PassFrameBuffer()); 211 audio_frames->SetFormat(cdm::kAudioFormatS16); 212 return cdm::kSuccess; 213} 214 215CdmWrapper* CdmWrapper::Create(const char* key_system, 216 uint32_t key_system_size, 217 GetCdmHostFunc get_cdm_host_func, 218 void* user_data) { 219 COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion == 220 cdm::ContentDecryptionModule_2::kVersion, 221 update_code_below); 222 223 // Ensure IsSupportedCdmInterfaceVersion matches this implementation. 224 // Always update this DCHECK when updating this function. 225 // If this check fails, update this function and DCHECK or update 226 // IsSupportedCdmInterfaceVersion. 227 PP_DCHECK( 228 !IsSupportedCdmInterfaceVersion( 229 cdm::ContentDecryptionModule::kVersion + 1) && 230 IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) && 231 IsSupportedCdmInterfaceVersion( 232 cdm::ContentDecryptionModule_1::kVersion) && 233 !IsSupportedCdmInterfaceVersion( 234 cdm::ContentDecryptionModule_1::kVersion - 1)); 235 236 // Try to create the CDM using the latest CDM interface version. 237 CdmWrapper* cdm_wrapper = 238 CdmWrapperImpl<cdm::ContentDecryptionModule>::Create( 239 key_system, key_system_size, get_cdm_host_func, user_data); 240 if (cdm_wrapper) 241 return cdm_wrapper; 242 243 // Try to see if the CDM supports older version(s) of the CDM interface. 244 cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_1>::Create( 245 key_system, key_system_size, get_cdm_host_func, user_data); 246 return cdm_wrapper; 247} 248 249// When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain 250// stub implementations for new or modified methods that the older CDM interface 251// does not have. 252// Also update supported_cdm_versions.h. 253COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion == 254 cdm::ContentDecryptionModule_2::kVersion, 255 ensure_cdm_wrapper_templates_have_old_version_support); 256 257} // namespace media 258 259#endif // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ 260