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/ppapi/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
~CdmWrapper()43 virtual ~CdmWrapper() {};
44
45 // TODO(jrummell): Remove return value when CDM4/5 are removed.
46 virtual bool SetServerCertificate(uint32_t promise_id,
47 const uint8_t* server_certificate_data,
48 uint32_t server_certificate_data_size) = 0;
49 virtual void CreateSession(uint32_t promise_id,
50 const char* init_data_type,
51 uint32_t init_data_type_size,
52 const uint8_t* init_data,
53 uint32_t init_data_size,
54 cdm::SessionType session_type) = 0;
55 virtual void LoadSession(uint32_t promise_id,
56 const char* web_session_id,
57 uint32_t web_session_id_size) = 0;
58 virtual void UpdateSession(uint32_t promise_id,
59 const char* web_session_id,
60 uint32_t web_session_id_size,
61 const uint8_t* response,
62 uint32_t response_size) = 0;
63 // TODO(jrummell): Remove return value when CDM4/5 are removed.
64 virtual bool CloseSession(uint32_t promise_id,
65 const char* web_session_id,
66 uint32_t web_session_id_size) = 0;
67 virtual void RemoveSession(uint32_t promise_id,
68 const char* web_session_id,
69 uint32_t web_session_id_size) = 0;
70 // TODO(jrummell): Remove return value when CDM4/5 are removed.
71 virtual bool GetUsableKeyIds(uint32_t promise_id,
72 const char* web_session_id,
73 uint32_t web_session_id_size) = 0;
74 virtual void TimerExpired(void* context) = 0;
75 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
76 cdm::DecryptedBlock* decrypted_buffer) = 0;
77 virtual cdm::Status InitializeAudioDecoder(
78 const cdm::AudioDecoderConfig& audio_decoder_config) = 0;
79 virtual cdm::Status InitializeVideoDecoder(
80 const cdm::VideoDecoderConfig& video_decoder_config) = 0;
81 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0;
82 virtual void ResetDecoder(cdm::StreamType decoder_type) = 0;
83 virtual cdm::Status DecryptAndDecodeFrame(
84 const cdm::InputBuffer& encrypted_buffer,
85 cdm::VideoFrame* video_frame) = 0;
86 virtual cdm::Status DecryptAndDecodeSamples(
87 const cdm::InputBuffer& encrypted_buffer,
88 cdm::AudioFrames* audio_frames) = 0;
89 virtual void OnPlatformChallengeResponse(
90 const cdm::PlatformChallengeResponse& response) = 0;
91 virtual void OnQueryOutputProtectionStatus(
92 uint32_t link_mask,
93 uint32_t output_protection_mask) = 0;
94
95 // Helper function for the cdm::Host_4 methods. Calls to CreateSession(),
96 // LoadSession(), UpdateSession(), and ReleaseSession() pass in promise ids,
97 // but the CDM interface needs session ids. For create and load, we need to
98 // create a new session_id to pass to the CDM. For update and release, we need
99 // to look up |web_session_id| and convert it into the existing |session_id|.
100 // Since the callbacks don't come through this interface, cdm_adapter needs to
101 // create the mapping (and delete it on release).
102 // TODO(jrummell): Remove these once Host_4 interface is removed.
103 virtual uint32_t LookupPromiseId(uint32_t session_id) = 0;
104 virtual void AssignWebSessionId(uint32_t session_id,
105 const char* web_session_id,
106 uint32_t web_session_id_size) = 0;
107 virtual std::string LookupWebSessionId(uint32_t session_id) = 0;
108 virtual void DropWebSessionId(std::string web_session_id) = 0;
109
110 // Helper functions for the cdm::Host_4 methods.
111 // CDMs using cdm::Host_6 will call OnSessionUsableKeys() as necessary when
112 // resolving LoadSession() and UpdateSession(). This needs to be simulated
113 // for the older CDMs. These must not be called for cdm::Host_6 and later.
114 // TODO(jrummell): Remove these once Host_4 interface is removed.
115
116 // Query whether a SessionUsableKeys event is necessary for the specified
117 // |promise_id|. Returns true if needed and |web_session_id| is updated,
118 // otherwise returns false.
119 virtual bool SessionUsableKeysEventNeeded(uint32_t promise_id,
120 std::string* web_session_id) = 0;
121
122 // Used to indicate that a SessionUsableKeys event is required for the
123 // specified |promise_id| and associated |web_session_id|.
124 virtual void SetSessionUsableKeysEventNeeded(
125 uint32_t promise_id,
126 const char* web_session_id,
127 uint32_t web_session_id_size) = 0;
128
129 // cdm::Host_6 introduces InputBuffer_2 (aka InputBuffer). cdm::Host_4
130 // methods still use InputBuffer_1, so this helper function
131 // converts InputBuffer_2 to InputBuffer_1.
132 // TODO(jrummell): Remove these once Host_4 interfaces is removed.
133 virtual void ConvertInputBuffer(const cdm::InputBuffer& v2,
134 cdm::InputBuffer_1* v1) = 0;
135
136 // Prior to CDM_6, |init_data_type| was a content type. This helper convererts
137 // an |init_data_type| to a content type.
138 // TODO(sandersd): Remove once Host_4 interface is removed.
139 virtual std::string ConvertInitDataTypeToContentType(
140 const std::string& init_data_type) const = 0;
141
142 protected:
CdmWrapper()143 CdmWrapper() {}
144
145 private:
146 DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
147 };
148
149 // Template class that does the CdmWrapper -> CdmInterface conversion. Default
150 // implementations are provided. Any methods that need special treatment should
151 // be specialized.
152 template <class CdmInterface>
153 class CdmWrapperImpl : public CdmWrapper {
154 public:
Create(const char * key_system,uint32_t key_system_size,GetCdmHostFunc get_cdm_host_func,void * user_data)155 static CdmWrapper* Create(const char* key_system,
156 uint32_t key_system_size,
157 GetCdmHostFunc get_cdm_host_func,
158 void* user_data) {
159 void* cdm_instance = ::CreateCdmInstance(
160 CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func,
161 user_data);
162 if (!cdm_instance)
163 return NULL;
164
165 return new CdmWrapperImpl<CdmInterface>(
166 static_cast<CdmInterface*>(cdm_instance));
167 }
168
~CdmWrapperImpl()169 virtual ~CdmWrapperImpl() {
170 cdm_->Destroy();
171 }
172
173 // Returns true if |data| is prefixed with |header| and has data after the
174 // |header|.
HasHeader(const uint8 * data,int data_length,const std::string & header)175 bool HasHeader(const uint8* data,
176 int data_length,
177 const std::string& header) {
178 return static_cast<size_t>(data_length) > header.length() &&
179 std::equal(data, data + header.length(), header.begin());
180 }
181
SetServerCertificate(uint32_t promise_id,const uint8_t * server_certificate_data,uint32_t server_certificate_data_size)182 virtual bool SetServerCertificate(
183 uint32_t promise_id,
184 const uint8_t* server_certificate_data,
185 uint32_t server_certificate_data_size) OVERRIDE {
186 cdm_->SetServerCertificate(
187 promise_id, server_certificate_data, server_certificate_data_size);
188 return true;
189 }
190
CreateSession(uint32_t promise_id,const char * init_data_type,uint32_t init_data_type_size,const uint8_t * init_data,uint32_t init_data_size,cdm::SessionType session_type)191 virtual void CreateSession(uint32_t promise_id,
192 const char* init_data_type,
193 uint32_t init_data_type_size,
194 const uint8_t* init_data,
195 uint32_t init_data_size,
196 cdm::SessionType session_type) OVERRIDE {
197 // TODO(jrummell): Remove this code once |session_type| is passed through
198 // Pepper. When removing, add the header back in for CDM4.
199 PP_DCHECK(session_type == cdm::kTemporary);
200 const char kPersistentSessionHeader[] = "PERSISTENT|";
201 if (HasHeader(init_data, init_data_size, kPersistentSessionHeader)) {
202 cdm_->CreateSession(promise_id,
203 init_data_type,
204 init_data_type_size,
205 init_data + strlen(kPersistentSessionHeader),
206 init_data_size - strlen(kPersistentSessionHeader),
207 cdm::kPersistent);
208 return;
209 }
210
211 cdm_->CreateSession(promise_id,
212 init_data_type,
213 init_data_type_size,
214 init_data,
215 init_data_size,
216 session_type);
217 }
218
LoadSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)219 virtual void LoadSession(uint32_t promise_id,
220 const char* web_session_id,
221 uint32_t web_session_id_size) OVERRIDE {
222 cdm_->LoadSession(promise_id, web_session_id, web_session_id_size);
223 }
224
UpdateSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size,const uint8_t * response,uint32_t response_size)225 virtual void UpdateSession(uint32_t promise_id,
226 const char* web_session_id,
227 uint32_t web_session_id_size,
228 const uint8_t* response,
229 uint32_t response_size) OVERRIDE {
230 cdm_->UpdateSession(promise_id,
231 web_session_id,
232 web_session_id_size,
233 response,
234 response_size);
235 }
236
CloseSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)237 virtual bool CloseSession(uint32_t promise_id,
238 const char* web_session_id,
239 uint32_t web_session_id_size) OVERRIDE {
240 cdm_->CloseSession(promise_id, web_session_id, web_session_id_size);
241 return true;
242 }
243
RemoveSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)244 virtual void RemoveSession(uint32_t promise_id,
245 const char* web_session_id,
246 uint32_t web_session_id_size) OVERRIDE {
247 cdm_->RemoveSession(promise_id, web_session_id, web_session_id_size);
248 }
249
GetUsableKeyIds(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)250 virtual bool GetUsableKeyIds(uint32_t promise_id,
251 const char* web_session_id,
252 uint32_t web_session_id_size) OVERRIDE {
253 cdm_->GetUsableKeyIds(promise_id, web_session_id, web_session_id_size);
254 return true;
255 }
256
TimerExpired(void * context)257 virtual void TimerExpired(void* context) OVERRIDE {
258 cdm_->TimerExpired(context);
259 }
260
Decrypt(const cdm::InputBuffer & encrypted_buffer,cdm::DecryptedBlock * decrypted_buffer)261 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
262 cdm::DecryptedBlock* decrypted_buffer) OVERRIDE {
263 return cdm_->Decrypt(encrypted_buffer, decrypted_buffer);
264 }
265
InitializeAudioDecoder(const cdm::AudioDecoderConfig & audio_decoder_config)266 virtual cdm::Status InitializeAudioDecoder(
267 const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE {
268 return cdm_->InitializeAudioDecoder(audio_decoder_config);
269 }
270
InitializeVideoDecoder(const cdm::VideoDecoderConfig & video_decoder_config)271 virtual cdm::Status InitializeVideoDecoder(
272 const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE {
273 return cdm_->InitializeVideoDecoder(video_decoder_config);
274 }
275
DeinitializeDecoder(cdm::StreamType decoder_type)276 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE {
277 cdm_->DeinitializeDecoder(decoder_type);
278 }
279
ResetDecoder(cdm::StreamType decoder_type)280 virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE {
281 cdm_->ResetDecoder(decoder_type);
282 }
283
DecryptAndDecodeFrame(const cdm::InputBuffer & encrypted_buffer,cdm::VideoFrame * video_frame)284 virtual cdm::Status DecryptAndDecodeFrame(
285 const cdm::InputBuffer& encrypted_buffer,
286 cdm::VideoFrame* video_frame) OVERRIDE {
287 return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame);
288 }
289
DecryptAndDecodeSamples(const cdm::InputBuffer & encrypted_buffer,cdm::AudioFrames * audio_frames)290 virtual cdm::Status DecryptAndDecodeSamples(
291 const cdm::InputBuffer& encrypted_buffer,
292 cdm::AudioFrames* audio_frames) OVERRIDE {
293 return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames);
294 }
295
OnPlatformChallengeResponse(const cdm::PlatformChallengeResponse & response)296 virtual void OnPlatformChallengeResponse(
297 const cdm::PlatformChallengeResponse& response) OVERRIDE {
298 cdm_->OnPlatformChallengeResponse(response);
299 }
300
OnQueryOutputProtectionStatus(uint32_t link_mask,uint32_t output_protection_mask)301 virtual void OnQueryOutputProtectionStatus(
302 uint32_t link_mask,
303 uint32_t output_protection_mask) OVERRIDE {
304 cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask);
305 }
306
CreateSessionId()307 uint32_t CreateSessionId() {
308 return next_session_id_++;
309 }
310
RegisterPromise(uint32_t session_id,uint32_t promise_id)311 void RegisterPromise(uint32_t session_id, uint32_t promise_id) {
312 PP_DCHECK(promise_to_session_id_map_.find(session_id) ==
313 promise_to_session_id_map_.end());
314 promise_to_session_id_map_.insert(std::make_pair(session_id, promise_id));
315 }
316
LookupPromiseId(uint32_t session_id)317 virtual uint32_t LookupPromiseId(uint32_t session_id) {
318 std::map<uint32_t, uint32_t>::iterator it =
319 promise_to_session_id_map_.find(session_id);
320 if (it == promise_to_session_id_map_.end())
321 return 0;
322 uint32_t promise_id = it->second;
323 promise_to_session_id_map_.erase(it);
324 return promise_id;
325 }
326
AssignWebSessionId(uint32_t session_id,const char * web_session_id,uint32_t web_session_id_size)327 virtual void AssignWebSessionId(uint32_t session_id,
328 const char* web_session_id,
329 uint32_t web_session_id_size) {
330 web_session_to_session_id_map_.insert(std::make_pair(
331 std::string(web_session_id, web_session_id_size), session_id));
332 }
333
LookupSessionId(std::string web_session_id)334 uint32_t LookupSessionId(std::string web_session_id) {
335 return web_session_to_session_id_map_.find(web_session_id)->second;
336 }
337
LookupWebSessionId(uint32_t session_id)338 virtual std::string LookupWebSessionId(uint32_t session_id) {
339 std::map<std::string, uint32_t>::iterator it;
340 for (it = web_session_to_session_id_map_.begin();
341 it != web_session_to_session_id_map_.end();
342 ++it) {
343 if (it->second == session_id)
344 return it->first;
345 }
346 PP_NOTREACHED();
347 return std::string();
348 }
349
DropWebSessionId(std::string web_session_id)350 virtual void DropWebSessionId(std::string web_session_id) {
351 web_session_to_session_id_map_.erase(web_session_id);
352 }
353
SessionUsableKeysEventNeeded(uint32_t promise_id,std::string * web_session_id)354 virtual bool SessionUsableKeysEventNeeded(uint32_t promise_id,
355 std::string* web_session_id) {
356 std::map<uint32_t, std::string>::iterator it =
357 promises_needing_usable_keys_event_.find(promise_id);
358 if (it == promises_needing_usable_keys_event_.end())
359 return false;
360 web_session_id->swap(it->second);
361 promises_needing_usable_keys_event_.erase(it);
362 return true;
363 }
364
SetSessionUsableKeysEventNeeded(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)365 virtual void SetSessionUsableKeysEventNeeded(uint32_t promise_id,
366 const char* web_session_id,
367 uint32_t web_session_id_size) {
368 promises_needing_usable_keys_event_.insert(std::make_pair(
369 promise_id, std::string(web_session_id, web_session_id_size)));
370 }
371
ConvertInputBuffer(const cdm::InputBuffer & v2,cdm::InputBuffer_1 * v1)372 virtual void ConvertInputBuffer(const cdm::InputBuffer& v2,
373 cdm::InputBuffer_1* v1) {
374 v1->data = v2.data;
375 v1->data_size = v2.data_size;
376 v1->data_offset = 0;
377 v1->key_id = v2.key_id;
378 v1->key_id_size = v2.key_id_size;
379 v1->iv = v2.iv;
380 v1->iv_size = v2.iv_size;
381 v1->subsamples = v2.subsamples;
382 v1->num_subsamples = v2.num_subsamples;
383 v1->timestamp = v2.timestamp;
384 }
385
ConvertInitDataTypeToContentType(const std::string & init_data_type)386 virtual std::string ConvertInitDataTypeToContentType(
387 const std::string& init_data_type) const {
388 if (init_data_type == "cenc")
389 return "video/mp4";
390 if (init_data_type == "webm")
391 return "video/webm";
392 return init_data_type;
393 }
394
395 private:
CdmWrapperImpl(CdmInterface * cdm)396 CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm), next_session_id_(100) {
397 PP_DCHECK(cdm_);
398 }
399
400 CdmInterface* cdm_;
401
402 std::map<uint32_t, uint32_t> promise_to_session_id_map_;
403 uint32_t next_session_id_;
404 std::map<std::string, uint32_t> web_session_to_session_id_map_;
405
406 std::map<uint32_t, std::string> promises_needing_usable_keys_event_;
407
408 DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl);
409 };
410
411 // Overrides for the cdm::Host_4 methods. Calls to CreateSession(),
412 // LoadSession(), UpdateSession(), and ReleaseSession() pass in promise ids,
413 // but the CDM interface needs session ids. For create and load, we need to
414 // create a new session_id to pass to the CDM. For update and release, we need
415 // to look up |web_session_id| and convert it into the existing |session_id|.
416 // Since the callbacks don't come through this interface, cdm_adapter needs to
417 // create the mapping (and delete it on release). Finally, for create, we need
418 // to translate |init_data_type| to a MIME type.
419 // TODO(jrummell): Remove these once Host_4 interface is removed.
420
421 template <>
SetServerCertificate(uint32_t promise_id,const uint8_t * server_certificate_data,uint32_t server_certificate_data_size)422 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::SetServerCertificate(
423 uint32_t promise_id,
424 const uint8_t* server_certificate_data,
425 uint32_t server_certificate_data_size) {
426 return false;
427 }
428
429 template <>
CreateSession(uint32_t promise_id,const char * init_data_type,uint32_t init_data_type_size,const uint8_t * init_data,uint32_t init_data_size,cdm::SessionType session_type)430 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CreateSession(
431 uint32_t promise_id,
432 const char* init_data_type,
433 uint32_t init_data_type_size,
434 const uint8_t* init_data,
435 uint32_t init_data_size,
436 cdm::SessionType session_type) {
437 uint32_t session_id = CreateSessionId();
438 RegisterPromise(session_id, promise_id);
439 std::string converted_init_data_type = ConvertInitDataTypeToContentType(
440 std::string(init_data_type, init_data_type_size));
441 cdm_->CreateSession(session_id,
442 converted_init_data_type.data(),
443 converted_init_data_type.length(),
444 init_data,
445 init_data_size);
446 }
447
448 template <>
LoadSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)449 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::LoadSession(
450 uint32_t promise_id,
451 const char* web_session_id,
452 uint32_t web_session_id_size) {
453 uint32_t session_id = CreateSessionId();
454 RegisterPromise(session_id, promise_id);
455 // As CDM_4 doesn't support OnSessionUsableKeysChange(), make sure to generate
456 // one when the promise is resolved. This may be overly aggressive.
457 SetSessionUsableKeysEventNeeded(
458 promise_id, web_session_id, web_session_id_size);
459 cdm_->LoadSession(session_id, web_session_id, web_session_id_size);
460 }
461
462 template <>
UpdateSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size,const uint8_t * response,uint32_t response_size)463 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::UpdateSession(
464 uint32_t promise_id,
465 const char* web_session_id,
466 uint32_t web_session_id_size,
467 const uint8_t* response,
468 uint32_t response_size) {
469 std::string web_session_str(web_session_id, web_session_id_size);
470 uint32_t session_id = LookupSessionId(web_session_str);
471 RegisterPromise(session_id, promise_id);
472 // As CDM_4 doesn't support OnSessionUsableKeysChange(), make sure to generate
473 // one when the promise is resolved. This may be overly aggressive.
474 SetSessionUsableKeysEventNeeded(
475 promise_id, web_session_id, web_session_id_size);
476 cdm_->UpdateSession(session_id, response, response_size);
477 }
478
479 template <>
CloseSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)480 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CloseSession(
481 uint32_t promise_id,
482 const char* web_session_id,
483 uint32_t web_session_id_size) {
484 return false;
485 }
486
487 template <>
RemoveSession(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)488 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::RemoveSession(
489 uint32_t promise_id,
490 const char* web_session_id,
491 uint32_t web_session_id_size) {
492 std::string web_session_str(web_session_id, web_session_id_size);
493 uint32_t session_id = LookupSessionId(web_session_str);
494 RegisterPromise(session_id, promise_id);
495 cdm_->ReleaseSession(session_id);
496 }
497
498 template <>
GetUsableKeyIds(uint32_t promise_id,const char * web_session_id,uint32_t web_session_id_size)499 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::GetUsableKeyIds(
500 uint32_t promise_id,
501 const char* web_session_id,
502 uint32_t web_session_id_size) {
503 return false;
504 }
505
506 template <>
Decrypt(const cdm::InputBuffer & encrypted_buffer,cdm::DecryptedBlock * decrypted_buffer)507 cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_4>::Decrypt(
508 const cdm::InputBuffer& encrypted_buffer,
509 cdm::DecryptedBlock* decrypted_buffer) {
510 cdm::InputBuffer_1 buffer;
511 ConvertInputBuffer(encrypted_buffer, &buffer);
512 return cdm_->Decrypt(buffer, decrypted_buffer);
513 }
514
515 template <>
516 cdm::Status
DecryptAndDecodeFrame(const cdm::InputBuffer & encrypted_buffer,cdm::VideoFrame * video_frame)517 CdmWrapperImpl<cdm::ContentDecryptionModule_4>::DecryptAndDecodeFrame(
518 const cdm::InputBuffer& encrypted_buffer,
519 cdm::VideoFrame* video_frame) {
520 cdm::InputBuffer_1 buffer;
521 ConvertInputBuffer(encrypted_buffer, &buffer);
522 return cdm_->DecryptAndDecodeFrame(buffer, video_frame);
523 }
524
525 template <>
526 cdm::Status
DecryptAndDecodeSamples(const cdm::InputBuffer & encrypted_buffer,cdm::AudioFrames * audio_frames)527 CdmWrapperImpl<cdm::ContentDecryptionModule_4>::DecryptAndDecodeSamples(
528 const cdm::InputBuffer& encrypted_buffer,
529 cdm::AudioFrames* audio_frames) {
530 cdm::InputBuffer_1 buffer;
531 ConvertInputBuffer(encrypted_buffer, &buffer);
532 return cdm_->DecryptAndDecodeSamples(buffer, audio_frames);
533 }
534
Create(const char * key_system,uint32_t key_system_size,GetCdmHostFunc get_cdm_host_func,void * user_data)535 CdmWrapper* CdmWrapper::Create(const char* key_system,
536 uint32_t key_system_size,
537 GetCdmHostFunc get_cdm_host_func,
538 void* user_data) {
539 COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
540 cdm::ContentDecryptionModule_6::kVersion,
541 update_code_below);
542
543 // Ensure IsSupportedCdmInterfaceVersion() matches this implementation.
544 // Always update this DCHECK when updating this function.
545 // If this check fails, update this function and DCHECK or update
546 // IsSupportedCdmInterfaceVersion().
547 PP_DCHECK(
548 !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion +
549 1) &&
550 IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) &&
551 IsSupportedCdmInterfaceVersion(
552 cdm::ContentDecryptionModule_4::kVersion) &&
553 !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule_4::kVersion -
554 1));
555
556 // Try to create the CDM using the latest CDM interface version.
557 CdmWrapper* cdm_wrapper =
558 CdmWrapperImpl<cdm::ContentDecryptionModule>::Create(
559 key_system, key_system_size, get_cdm_host_func, user_data);
560 if (cdm_wrapper)
561 return cdm_wrapper;
562
563 // If |cdm_wrapper| is NULL, try to create the CDM using older supported
564 // versions of the CDM interface.
565 cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_4>::Create(
566 key_system, key_system_size, get_cdm_host_func, user_data);
567 return cdm_wrapper;
568 }
569
570 // When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain
571 // stub implementations for new or modified methods that the older CDM interface
572 // does not have.
573 // Also update supported_cdm_versions.h.
574 COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
575 cdm::ContentDecryptionModule_6::kVersion,
576 ensure_cdm_wrapper_templates_have_old_version_support);
577
578 } // namespace media
579
580 #endif // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
581