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.
5 #ifndef MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
6 #define MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
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"
20 // CdmWrapper wraps different versions of ContentDecryptionModule interfaces and
21 // exposes a common interface to the caller.
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.
31 // Note that CdmWrapper interface always reflects the latest state of content
32 // decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private).
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.
38 static CdmWrapper* Create(const char* key_system,
39 uint32_t key_system_size,
40 GetCdmHostFunc get_cdm_host_func,
43 virtual ~CdmWrapper() {};
45 virtual void CreateSession(uint32_t promise_id,
46 const char* init_data_type,
47 uint32_t init_data_type_size,
48 const uint8_t* init_data,
49 uint32_t init_data_size,
50 cdm::SessionType session_type) = 0;
51 virtual void LoadSession(uint32_t promise_id,
52 const char* web_session_id,
53 uint32_t web_session_id_size) = 0;
54 virtual void UpdateSession(uint32_t promise_id,
55 const char* web_session_id,
56 uint32_t web_session_id_size,
57 const uint8_t* response,
58 uint32_t response_size) = 0;
59 virtual void CloseSession(uint32_t promise_id,
60 const char* web_session_id,
61 uint32_t web_session_id_size) = 0;
62 virtual bool RemoveSession(uint32_t promise_id,
63 const char* web_session_id,
64 uint32_t web_session_id_size) = 0;
65 virtual bool GetUsableKeyIds(uint32_t promise_id,
66 const char* web_session_id,
67 uint32_t web_session_id_size) = 0;
68 virtual void TimerExpired(void* context) = 0;
69 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
70 cdm::DecryptedBlock* decrypted_buffer) = 0;
71 virtual cdm::Status InitializeAudioDecoder(
72 const cdm::AudioDecoderConfig& audio_decoder_config) = 0;
73 virtual cdm::Status InitializeVideoDecoder(
74 const cdm::VideoDecoderConfig& video_decoder_config) = 0;
75 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0;
76 virtual void ResetDecoder(cdm::StreamType decoder_type) = 0;
77 virtual cdm::Status DecryptAndDecodeFrame(
78 const cdm::InputBuffer& encrypted_buffer,
79 cdm::VideoFrame* video_frame) = 0;
80 virtual cdm::Status DecryptAndDecodeSamples(
81 const cdm::InputBuffer& encrypted_buffer,
82 cdm::AudioFrames* audio_frames) = 0;
83 virtual void OnPlatformChallengeResponse(
84 const cdm::PlatformChallengeResponse& response) = 0;
85 virtual void OnQueryOutputProtectionStatus(
87 uint32_t output_protection_mask) = 0;
89 // Helper function for the cdm::Host_4 methods. Calls to CreateSession(),
90 // LoadSession(), UpdateSession(), and ReleaseSession() pass in promise ids,
91 // but the CDM interface needs session ids. For create and load, we need to
92 // create a new session_id to pass to the CDM. For update and release, we need
93 // to look up |web_session_id| and convert it into the existing |session_id|.
94 // Since the callbacks don't come through this interface, cdm_adapter needs to
95 // create the mapping (and delete it on release).
96 // TODO(jrummell): Remove these once Host_4 interface is removed.
97 virtual uint32_t LookupPromiseId(uint32_t session_id) = 0;
98 virtual void AssignWebSessionId(uint32_t session_id,
99 const char* web_session_id,
100 uint32_t web_session_id_size) = 0;
101 virtual std::string LookupWebSessionId(uint32_t session_id) = 0;
102 virtual void DropWebSessionId(std::string web_session_id) = 0;
104 // Helper functions for the cdm::Host_4 and cdm::Host_5 methods.
105 // CDMs using cdm::Host_6 will call OnSessionUsableKeys() as necessary when
106 // resolving LoadSession() and UpdateSession(). This needs to be simulated
107 // for the older CDMs. These must not be called for cdm::Host_6 and later.
108 // TODO(jrummell): Remove these once Host_4 and Host_5 interfaces are removed.
110 // Query whether a SessionUsableKeys event is necessary for the specified
111 // |promise_id|. Returns true if needed and |web_session_id| is updated,
112 // otherwise returns false.
113 virtual bool SessionUsableKeysEventNeeded(uint32_t promise_id,
114 std::string* web_session_id) = 0;
116 // Used to indicate that a SessionUsableKeys event is required for the
117 // specified |promise_id| and associated |web_session_id|.
118 virtual void SetSessionUsableKeysEventNeeded(
120 const char* web_session_id,
121 uint32_t web_session_id_size) = 0;
123 // cdm::Host_6 introduces InputBuffer_2 (aka InputBuffer). cdm::Host_4 and
124 // cdm::Host_5 methods still use InputBuffer_1, so this helper function
125 // converts InputBuffer_2 to InputBuffer_1.
126 // TODO(jrummell): Remove these once Host_4 and Host_5 interfaces are removed.
127 virtual void ConvertInputBuffer(const cdm::InputBuffer& v2,
128 cdm::InputBuffer_1* v1) = 0;
130 // Prior to CDM_6, |init_data_type| was a content type. This helper convererts
131 // an |init_data_type| to a content type.
132 // TODO(sandersd): Remove once Host_4 and Host_5 interfaces are removed.
133 virtual std::string ConvertInitDataTypeToContentType(
134 const std::string& init_data_type) const = 0;
140 DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
143 // Template class that does the CdmWrapper -> CdmInterface conversion. Default
144 // implementations are provided. Any methods that need special treatment should
146 template <class CdmInterface>
147 class CdmWrapperImpl : public CdmWrapper {
149 static CdmWrapper* Create(const char* key_system,
150 uint32_t key_system_size,
151 GetCdmHostFunc get_cdm_host_func,
153 void* cdm_instance = ::CreateCdmInstance(
154 CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func,
159 return new CdmWrapperImpl<CdmInterface>(
160 static_cast<CdmInterface*>(cdm_instance));
163 virtual ~CdmWrapperImpl() {
167 // Returns true if |data| is prefixed with |header| and has data after the
169 bool HasHeader(const uint8* data,
171 const std::string& header) {
172 return static_cast<size_t>(data_length) > header.length() &&
173 std::equal(data, data + header.length(), header.begin());
176 virtual void CreateSession(uint32_t promise_id,
177 const char* init_data_type,
178 uint32_t init_data_type_size,
179 const uint8_t* init_data,
180 uint32_t init_data_size,
181 cdm::SessionType session_type) OVERRIDE {
182 // TODO(jrummell): Remove this code once |session_type| is passed through
183 // Pepper. When removing, add the header back in for CDM4.
184 PP_DCHECK(session_type == cdm::kTemporary);
185 const char kPersistentSessionHeader[] = "PERSISTENT|";
186 if (HasHeader(init_data, init_data_size, kPersistentSessionHeader)) {
187 cdm_->CreateSession(promise_id,
190 init_data + strlen(kPersistentSessionHeader),
191 init_data_size - strlen(kPersistentSessionHeader),
196 cdm_->CreateSession(promise_id,
204 virtual void LoadSession(uint32_t promise_id,
205 const char* web_session_id,
206 uint32_t web_session_id_size) OVERRIDE {
207 cdm_->LoadSession(promise_id, web_session_id, web_session_id_size);
210 virtual void UpdateSession(uint32_t promise_id,
211 const char* web_session_id,
212 uint32_t web_session_id_size,
213 const uint8_t* response,
214 uint32_t response_size) OVERRIDE {
215 cdm_->UpdateSession(promise_id,
222 virtual bool GetUsableKeyIds(uint32_t promise_id,
223 const char* web_session_id,
224 uint32_t web_session_id_size) OVERRIDE {
225 cdm_->GetUsableKeyIds(promise_id, web_session_id, web_session_id_size);
229 virtual void CloseSession(uint32_t promise_id,
230 const char* web_session_id,
231 uint32_t web_session_id_size) OVERRIDE {
232 cdm_->CloseSession(promise_id, web_session_id, web_session_id_size);
235 virtual bool RemoveSession(uint32_t promise_id,
236 const char* web_session_id,
237 uint32_t web_session_id_size) OVERRIDE {
238 cdm_->RemoveSession(promise_id, web_session_id, web_session_id_size);
242 virtual void TimerExpired(void* context) OVERRIDE {
243 cdm_->TimerExpired(context);
246 virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
247 cdm::DecryptedBlock* decrypted_buffer) OVERRIDE {
248 return cdm_->Decrypt(encrypted_buffer, decrypted_buffer);
251 virtual cdm::Status InitializeAudioDecoder(
252 const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE {
253 return cdm_->InitializeAudioDecoder(audio_decoder_config);
256 virtual cdm::Status InitializeVideoDecoder(
257 const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE {
258 return cdm_->InitializeVideoDecoder(video_decoder_config);
261 virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE {
262 cdm_->DeinitializeDecoder(decoder_type);
265 virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE {
266 cdm_->ResetDecoder(decoder_type);
269 virtual cdm::Status DecryptAndDecodeFrame(
270 const cdm::InputBuffer& encrypted_buffer,
271 cdm::VideoFrame* video_frame) OVERRIDE {
272 return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame);
275 virtual cdm::Status DecryptAndDecodeSamples(
276 const cdm::InputBuffer& encrypted_buffer,
277 cdm::AudioFrames* audio_frames) OVERRIDE {
278 return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames);
281 virtual void OnPlatformChallengeResponse(
282 const cdm::PlatformChallengeResponse& response) OVERRIDE {
283 cdm_->OnPlatformChallengeResponse(response);
286 virtual void OnQueryOutputProtectionStatus(
288 uint32_t output_protection_mask) OVERRIDE {
289 cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask);
292 uint32_t CreateSessionId() {
293 return next_session_id_++;
296 void RegisterPromise(uint32_t session_id, uint32_t promise_id) {
297 PP_DCHECK(promise_to_session_id_map_.find(session_id) ==
298 promise_to_session_id_map_.end());
299 promise_to_session_id_map_.insert(std::make_pair(session_id, promise_id));
302 virtual uint32_t LookupPromiseId(uint32_t session_id) {
303 std::map<uint32_t, uint32_t>::iterator it =
304 promise_to_session_id_map_.find(session_id);
305 if (it == promise_to_session_id_map_.end())
307 uint32_t promise_id = it->second;
308 promise_to_session_id_map_.erase(it);
312 virtual void AssignWebSessionId(uint32_t session_id,
313 const char* web_session_id,
314 uint32_t web_session_id_size) {
315 web_session_to_session_id_map_.insert(std::make_pair(
316 std::string(web_session_id, web_session_id_size), session_id));
319 uint32_t LookupSessionId(std::string web_session_id) {
320 return web_session_to_session_id_map_.find(web_session_id)->second;
323 virtual std::string LookupWebSessionId(uint32_t session_id) {
324 std::map<std::string, uint32_t>::iterator it;
325 for (it = web_session_to_session_id_map_.begin();
326 it != web_session_to_session_id_map_.end();
328 if (it->second == session_id)
332 return std::string();
335 virtual void DropWebSessionId(std::string web_session_id) {
336 web_session_to_session_id_map_.erase(web_session_id);
339 virtual bool SessionUsableKeysEventNeeded(uint32_t promise_id,
340 std::string* web_session_id) {
341 std::map<uint32_t, std::string>::iterator it =
342 promises_needing_usable_keys_event_.find(promise_id);
343 if (it == promises_needing_usable_keys_event_.end())
345 web_session_id->swap(it->second);
346 promises_needing_usable_keys_event_.erase(it);
350 virtual void SetSessionUsableKeysEventNeeded(uint32_t promise_id,
351 const char* web_session_id,
352 uint32_t web_session_id_size) {
353 promises_needing_usable_keys_event_.insert(std::make_pair(
354 promise_id, std::string(web_session_id, web_session_id_size)));
357 virtual void ConvertInputBuffer(const cdm::InputBuffer& v2,
358 cdm::InputBuffer_1* v1) {
360 v1->data_size = v2.data_size;
362 v1->key_id = v2.key_id;
363 v1->key_id_size = v2.key_id_size;
365 v1->iv_size = v2.iv_size;
366 v1->subsamples = v2.subsamples;
367 v1->num_subsamples = v2.num_subsamples;
368 v1->timestamp = v2.timestamp;
371 virtual std::string ConvertInitDataTypeToContentType(
372 const std::string& init_data_type) const {
373 if (init_data_type == "cenc")
375 if (init_data_type == "webm")
377 return init_data_type;
381 CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm), next_session_id_(100) {
387 std::map<uint32_t, uint32_t> promise_to_session_id_map_;
388 uint32_t next_session_id_;
389 std::map<std::string, uint32_t> web_session_to_session_id_map_;
391 std::map<uint32_t, std::string> promises_needing_usable_keys_event_;
393 DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl);
396 // Overrides for the cdm::Host_4 methods. Calls to CreateSession(),
397 // LoadSession(), UpdateSession(), and ReleaseSession() pass in promise ids,
398 // but the CDM interface needs session ids. For create and load, we need to
399 // create a new session_id to pass to the CDM. For update and release, we need
400 // to look up |web_session_id| and convert it into the existing |session_id|.
401 // Since the callbacks don't come through this interface, cdm_adapter needs to
402 // create the mapping (and delete it on release). Finally, for create, we need
403 // to translate |init_data_type| to a MIME type.
404 // TODO(jrummell): Remove these once Host_4 interface is removed.
407 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CreateSession(
409 const char* init_data_type,
410 uint32_t init_data_type_size,
411 const uint8_t* init_data,
412 uint32_t init_data_size,
413 cdm::SessionType session_type) {
414 uint32_t session_id = CreateSessionId();
415 RegisterPromise(session_id, promise_id);
416 std::string converted_init_data_type = ConvertInitDataTypeToContentType(
417 std::string(init_data_type, init_data_type_size));
418 cdm_->CreateSession(session_id,
419 converted_init_data_type.data(),
420 converted_init_data_type.length(),
426 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::LoadSession(
428 const char* web_session_id,
429 uint32_t web_session_id_size) {
430 uint32_t session_id = CreateSessionId();
431 RegisterPromise(session_id, promise_id);
432 // As CDM_4 doesn't support OnSessionUsableKeysChange(), make sure to generate
433 // one when the promise is resolved. This may be overly aggressive.
434 SetSessionUsableKeysEventNeeded(
435 promise_id, web_session_id, web_session_id_size);
436 cdm_->LoadSession(session_id, web_session_id, web_session_id_size);
440 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::UpdateSession(
442 const char* web_session_id,
443 uint32_t web_session_id_size,
444 const uint8_t* response,
445 uint32_t response_size) {
446 std::string web_session_str(web_session_id, web_session_id_size);
447 uint32_t session_id = LookupSessionId(web_session_str);
448 RegisterPromise(session_id, promise_id);
449 // As CDM_4 doesn't support OnSessionUsableKeysChange(), make sure to generate
450 // one when the promise is resolved. This may be overly aggressive.
451 SetSessionUsableKeysEventNeeded(
452 promise_id, web_session_id, web_session_id_size);
453 cdm_->UpdateSession(session_id, response, response_size);
457 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CloseSession(
459 const char* web_session_id,
460 uint32_t web_session_id_size) {
461 std::string web_session_str(web_session_id, web_session_id_size);
462 uint32_t session_id = LookupSessionId(web_session_str);
463 RegisterPromise(session_id, promise_id);
464 cdm_->ReleaseSession(session_id);
468 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::RemoveSession(
470 const char* web_session_id,
471 uint32_t web_session_id_size) {
476 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::GetUsableKeyIds(
478 const char* web_session_id,
479 uint32_t web_session_id_size) {
484 cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_4>::Decrypt(
485 const cdm::InputBuffer& encrypted_buffer,
486 cdm::DecryptedBlock* decrypted_buffer) {
487 cdm::InputBuffer_1 buffer;
488 ConvertInputBuffer(encrypted_buffer, &buffer);
489 return cdm_->Decrypt(buffer, decrypted_buffer);
494 CdmWrapperImpl<cdm::ContentDecryptionModule_4>::DecryptAndDecodeFrame(
495 const cdm::InputBuffer& encrypted_buffer,
496 cdm::VideoFrame* video_frame) {
497 cdm::InputBuffer_1 buffer;
498 ConvertInputBuffer(encrypted_buffer, &buffer);
499 return cdm_->DecryptAndDecodeFrame(buffer, video_frame);
504 CdmWrapperImpl<cdm::ContentDecryptionModule_4>::DecryptAndDecodeSamples(
505 const cdm::InputBuffer& encrypted_buffer,
506 cdm::AudioFrames* audio_frames) {
507 cdm::InputBuffer_1 buffer;
508 ConvertInputBuffer(encrypted_buffer, &buffer);
509 return cdm_->DecryptAndDecodeSamples(buffer, audio_frames);
512 // Overrides for the cdm::Host_5 methods.
513 // TODO(jrummell): Remove these once Host_5 interface is removed.
516 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::CreateSession(
518 const char* init_data_type,
519 uint32_t init_data_type_size,
520 const uint8_t* init_data,
521 uint32_t init_data_size,
522 cdm::SessionType session_type) {
523 std::string converted_init_data_type = ConvertInitDataTypeToContentType(
524 std::string(init_data_type, init_data_type_size));
525 // TODO(jrummell): Remove this code once |session_type| is passed through
526 // Pepper. When removing, add the header back in for CDM4.
527 PP_DCHECK(session_type == cdm::kTemporary);
528 const char kPersistentSessionHeader[] = "PERSISTENT|";
529 if (HasHeader(init_data, init_data_size, kPersistentSessionHeader)) {
530 cdm_->CreateSession(promise_id,
531 converted_init_data_type.data(),
532 converted_init_data_type.length(),
533 init_data + strlen(kPersistentSessionHeader),
534 init_data_size - strlen(kPersistentSessionHeader),
539 cdm_->CreateSession(promise_id,
540 converted_init_data_type.data(),
541 converted_init_data_type.length(),
548 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::LoadSession(
550 const char* web_session_id,
551 uint32_t web_session_id_size) {
552 // As CDM_5 doesn't support OnSessionUsableKeysChange(), make sure to generate
553 // one when the promise is resolved. This may be overly aggressive.
554 SetSessionUsableKeysEventNeeded(
555 promise_id, web_session_id, web_session_id_size);
556 cdm_->LoadSession(promise_id, web_session_id, web_session_id_size);
560 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::UpdateSession(
562 const char* web_session_id,
563 uint32_t web_session_id_size,
564 const uint8_t* response,
565 uint32_t response_size) {
566 // As CDM_5 doesn't support OnSessionUsableKeysChange(), make sure to generate
567 // one when the promise is resolved. This may be overly aggressive.
568 SetSessionUsableKeysEventNeeded(
569 promise_id, web_session_id, web_session_id_size);
571 promise_id, web_session_id, web_session_id_size, response, response_size);
575 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::CloseSession(
577 const char* web_session_id,
578 uint32_t web_session_id_size) {
579 cdm_->ReleaseSession(promise_id, web_session_id, web_session_id_size);
583 bool CdmWrapperImpl<cdm::ContentDecryptionModule_5>::RemoveSession(
585 const char* web_session_id,
586 uint32_t web_session_id_size) {
591 bool CdmWrapperImpl<cdm::ContentDecryptionModule_5>::GetUsableKeyIds(
593 const char* web_session_id,
594 uint32_t web_session_id_size) {
599 cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_5>::Decrypt(
600 const cdm::InputBuffer& encrypted_buffer,
601 cdm::DecryptedBlock* decrypted_buffer) {
602 cdm::InputBuffer_1 buffer;
603 ConvertInputBuffer(encrypted_buffer, &buffer);
604 return cdm_->Decrypt(buffer, decrypted_buffer);
609 CdmWrapperImpl<cdm::ContentDecryptionModule_5>::DecryptAndDecodeFrame(
610 const cdm::InputBuffer& encrypted_buffer,
611 cdm::VideoFrame* video_frame) {
612 cdm::InputBuffer_1 buffer;
613 ConvertInputBuffer(encrypted_buffer, &buffer);
614 return cdm_->DecryptAndDecodeFrame(buffer, video_frame);
619 CdmWrapperImpl<cdm::ContentDecryptionModule_5>::DecryptAndDecodeSamples(
620 const cdm::InputBuffer& encrypted_buffer,
621 cdm::AudioFrames* audio_frames) {
622 cdm::InputBuffer_1 buffer;
623 ConvertInputBuffer(encrypted_buffer, &buffer);
624 return cdm_->DecryptAndDecodeSamples(buffer, audio_frames);
627 CdmWrapper* CdmWrapper::Create(const char* key_system,
628 uint32_t key_system_size,
629 GetCdmHostFunc get_cdm_host_func,
631 COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
632 cdm::ContentDecryptionModule_6::kVersion,
635 // Ensure IsSupportedCdmInterfaceVersion() matches this implementation.
636 // Always update this DCHECK when updating this function.
637 // If this check fails, update this function and DCHECK or update
638 // IsSupportedCdmInterfaceVersion().
640 !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion +
642 IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) &&
643 IsSupportedCdmInterfaceVersion(
644 cdm::ContentDecryptionModule_4::kVersion) &&
645 !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule_4::kVersion -
648 // Try to create the CDM using the latest CDM interface version.
649 CdmWrapper* cdm_wrapper =
650 CdmWrapperImpl<cdm::ContentDecryptionModule>::Create(
651 key_system, key_system_size, get_cdm_host_func, user_data);
655 // If |cdm_wrapper| is NULL, try to create the CDM using older supported
656 // versions of the CDM interface.
657 cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_5>::Create(
658 key_system, key_system_size, get_cdm_host_func, user_data);
662 cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_4>::Create(
663 key_system, key_system_size, get_cdm_host_func, user_data);
667 // When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain
668 // stub implementations for new or modified methods that the older CDM interface
670 // Also update supported_cdm_versions.h.
671 COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
672 cdm::ContentDecryptionModule_6::kVersion,
673 ensure_cdm_wrapper_templates_have_old_version_support);
677 #endif // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_