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 |