• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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