cdm_wrapper.h revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/cdm/ppapi/api/content_decryption_module.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/cdm/ppapi/cdm_helpers.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/cpp/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CdmWrapper wraps different versions of ContentDecryptionModule interfaces and 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exposes a common interface to the caller. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The caller should call CdmWrapper::Create() to create a CDM instance. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CdmWrapper will first try to create a CDM instance that supports the latest 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CDM interface (ContentDecryptionModule). If such an instance cannot be 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that supports an older version of CDM interface (e.g. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calls to corresponding ContentDecryptionModule calls. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that CdmWrapper interface always reflects the latest state of content 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private). 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Since this file is highly templated and default implementations are short 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (just a shim layer in most cases), everything is done in this header file. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CdmWrapper { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static CdmWrapper* Create(const char* key_system, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_system_size, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCdmHostFunc get_cdm_host_func, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~CdmWrapper() {}; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual cdm::Status GenerateKeyRequest(const char* type, 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int type_size, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8_t* init_data, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int init_data_size) = 0; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual cdm::Status AddKey(const char* session_id, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int session_id_size, 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8_t* key, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_size, 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const uint8_t* key_id, 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int key_id_size) = 0; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual cdm::Status CancelKeyRequest(const char* session_id, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int session_id_size) = 0; 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void TimerExpired(void* context) = 0; 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::DecryptedBlock* decrypted_buffer) = 0; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual cdm::Status InitializeAudioDecoder( 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::AudioDecoderConfig& audio_decoder_config) = 0; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual cdm::Status InitializeVideoDecoder( 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::VideoDecoderConfig& video_decoder_config) = 0; 59 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0; 60 virtual void ResetDecoder(cdm::StreamType decoder_type) = 0; 61 virtual cdm::Status DecryptAndDecodeFrame( 62 const cdm::InputBuffer& encrypted_buffer, 63 cdm::VideoFrame* video_frame) = 0; 64 virtual cdm::Status DecryptAndDecodeSamples( 65 const cdm::InputBuffer& encrypted_buffer, 66 cdm::AudioFrames* audio_frames) = 0; 67 virtual void OnPlatformChallengeResponse( 68 const cdm::PlatformChallengeResponse& response) = 0; 69 virtual void OnQueryOutputProtectionStatus( 70 uint32_t link_mask, 71 uint32_t output_protection_mask) = 0; 72 73 protected: 74 CdmWrapper() {}; 75 76 private: 77 DISALLOW_COPY_AND_ASSIGN(CdmWrapper); 78}; 79 80// Template class that does the CdmWrapper -> CdmInterface conversion. Default 81// implementations are provided. Any methods that need special treatment should 82// be specialized. 83template <class CdmInterface> 84class CdmWrapperImpl : public CdmWrapper { 85 public: 86 static CdmWrapper* Create(const char* key_system, 87 int key_system_size, 88 GetCdmHostFunc get_cdm_host_func, 89 void* user_data) { 90 void* cdm_instance = ::CreateCdmInstance( 91 CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func, 92 user_data); 93 if (!cdm_instance) 94 return NULL; 95 96 return new CdmWrapperImpl<CdmInterface>( 97 static_cast<CdmInterface*>(cdm_instance)); 98 } 99 100 virtual ~CdmWrapperImpl() { 101 cdm_->Destroy(); 102 } 103 104 virtual cdm::Status GenerateKeyRequest(const char* type, 105 int type_size, 106 const uint8_t* init_data, 107 int init_data_size) OVERRIDE { 108 return cdm_->GenerateKeyRequest(type, type_size, init_data, init_data_size); 109 } 110 111 virtual cdm::Status AddKey(const char* session_id, 112 int session_id_size, 113 const uint8_t* key, 114 int key_size, 115 const uint8_t* key_id, 116 int key_id_size) OVERRIDE { 117 return cdm_->AddKey( 118 session_id, session_id_size, key, key_size, key_id, key_id_size); 119 } 120 121 virtual cdm::Status CancelKeyRequest(const char* session_id, 122 int session_id_size) OVERRIDE { 123 return cdm_->CancelKeyRequest(session_id, session_id_size); 124 } 125 126 virtual void TimerExpired(void* context) OVERRIDE { 127 cdm_->TimerExpired(context); 128 } 129 130 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, 131 cdm::DecryptedBlock* decrypted_buffer) OVERRIDE { 132 return cdm_->Decrypt(encrypted_buffer, decrypted_buffer); 133 } 134 135 virtual cdm::Status InitializeAudioDecoder( 136 const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE { 137 return cdm_->InitializeAudioDecoder(audio_decoder_config); 138 } 139 140 virtual cdm::Status InitializeVideoDecoder( 141 const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE { 142 return cdm_->InitializeVideoDecoder(video_decoder_config); 143 } 144 145 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE { 146 cdm_->DeinitializeDecoder(decoder_type); 147 } 148 149 virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE { 150 cdm_->ResetDecoder(decoder_type); 151 } 152 153 virtual cdm::Status DecryptAndDecodeFrame( 154 const cdm::InputBuffer& encrypted_buffer, 155 cdm::VideoFrame* video_frame) OVERRIDE { 156 return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); 157 } 158 159 virtual cdm::Status DecryptAndDecodeSamples( 160 const cdm::InputBuffer& encrypted_buffer, 161 cdm::AudioFrames* audio_frames) OVERRIDE { 162 return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); 163 } 164 165 virtual void OnPlatformChallengeResponse( 166 const cdm::PlatformChallengeResponse& response) OVERRIDE { 167 cdm_->OnPlatformChallengeResponse(response); 168 } 169 170 virtual void OnQueryOutputProtectionStatus( 171 uint32_t link_mask, 172 uint32_t output_protection_mask) OVERRIDE { 173 cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask); 174 } 175 176 private: 177 CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) { 178 PP_DCHECK(cdm_); 179 } 180 181 CdmInterface* cdm_; 182 183 DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl); 184}; 185 186// Specializations for ContentDecryptionModule_1. 187 188template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: 189 OnPlatformChallengeResponse( 190 const cdm::PlatformChallengeResponse& response) { 191 PP_NOTREACHED(); 192} 193 194template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: 195 OnQueryOutputProtectionStatus(uint32_t link_mask, 196 uint32_t output_protection_mask) { 197 PP_NOTREACHED(); 198} 199 200template <> cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: 201 DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer, 202 cdm::AudioFrames* audio_frames) { 203 AudioFramesImpl audio_frames_1; 204 cdm::Status status = 205 cdm_->DecryptAndDecodeSamples(encrypted_buffer, &audio_frames_1); 206 if (status != cdm::kSuccess) 207 return status; 208 209 audio_frames->SetFrameBuffer(audio_frames_1.PassFrameBuffer()); 210 audio_frames->SetFormat(cdm::kAudioFormatS16); 211 return cdm::kSuccess; 212} 213 214CdmWrapper* CdmWrapper::Create(const char* key_system, 215 int key_system_size, 216 GetCdmHostFunc get_cdm_host_func, 217 void* user_data) { 218 // Try to create the CDM using the latest CDM interface version. 219 CdmWrapper* cdm_adapter = 220 CdmWrapperImpl<cdm::ContentDecryptionModule>::Create( 221 key_system, key_system_size, get_cdm_host_func, user_data); 222 if (cdm_adapter) 223 return cdm_adapter; 224 225 // Try to see if the CDM supports older version(s) of CDM interface(s). 226 cdm_adapter = CdmWrapperImpl<cdm::ContentDecryptionModule_1>::Create( 227 key_system, key_system_size, get_cdm_host_func, user_data); 228 return cdm_adapter; 229} 230 231// When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain 232// stub implementations for new or modified methods which the older CDM 233// interface does not have. 234COMPILE_ASSERT(cdm::ContentDecryptionModule_2::kVersion == 235 cdm::ContentDecryptionModule::kVersion, 236 ensure_cdm_wrapper_templates_have_old_version_support); 237 238} // namespace media 239 240#endif // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_ 241