Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / media / cdm / ppapi / cdm_wrapper.h
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
43   virtual ~CdmWrapper() {};
44
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(
86       uint32_t link_mask,
87       uint32_t output_protection_mask) = 0;
88
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;
103
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.
109
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;
115
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(
119       uint32_t promise_id,
120       const char* web_session_id,
121       uint32_t web_session_id_size) = 0;
122
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;
129
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;
135
136  protected:
137   CdmWrapper() {}
138
139  private:
140   DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
141 };
142
143 // Template class that does the CdmWrapper -> CdmInterface conversion. Default
144 // implementations are provided. Any methods that need special treatment should
145 // be specialized.
146 template <class CdmInterface>
147 class CdmWrapperImpl : public CdmWrapper {
148  public:
149   static CdmWrapper* Create(const char* key_system,
150                             uint32_t key_system_size,
151                             GetCdmHostFunc get_cdm_host_func,
152                             void* user_data) {
153     void* cdm_instance = ::CreateCdmInstance(
154         CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func,
155         user_data);
156     if (!cdm_instance)
157       return NULL;
158
159     return new CdmWrapperImpl<CdmInterface>(
160         static_cast<CdmInterface*>(cdm_instance));
161   }
162
163   virtual ~CdmWrapperImpl() {
164     cdm_->Destroy();
165   }
166
167   // Returns true if |data| is prefixed with |header| and has data after the
168   // |header|.
169   bool HasHeader(const uint8* data,
170                  int data_length,
171                  const std::string& header) {
172     return static_cast<size_t>(data_length) > header.length() &&
173            std::equal(data, data + header.length(), header.begin());
174   }
175
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,
188                           init_data_type,
189                           init_data_type_size,
190                           init_data + strlen(kPersistentSessionHeader),
191                           init_data_size - strlen(kPersistentSessionHeader),
192                           cdm::kPersistent);
193       return;
194     }
195
196     cdm_->CreateSession(promise_id,
197                         init_data_type,
198                         init_data_type_size,
199                         init_data,
200                         init_data_size,
201                         session_type);
202   }
203
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);
208   }
209
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,
216                         web_session_id,
217                         web_session_id_size,
218                         response,
219                         response_size);
220   }
221
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);
226     return true;
227   }
228
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);
233   }
234
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);
239     return true;
240   }
241
242   virtual void TimerExpired(void* context) OVERRIDE {
243     cdm_->TimerExpired(context);
244   }
245
246   virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
247                               cdm::DecryptedBlock* decrypted_buffer) OVERRIDE {
248     return cdm_->Decrypt(encrypted_buffer, decrypted_buffer);
249   }
250
251   virtual cdm::Status InitializeAudioDecoder(
252       const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE {
253     return cdm_->InitializeAudioDecoder(audio_decoder_config);
254   }
255
256   virtual cdm::Status InitializeVideoDecoder(
257       const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE {
258     return cdm_->InitializeVideoDecoder(video_decoder_config);
259   }
260
261   virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE {
262     cdm_->DeinitializeDecoder(decoder_type);
263   }
264
265   virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE {
266     cdm_->ResetDecoder(decoder_type);
267   }
268
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);
273   }
274
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);
279   }
280
281   virtual void OnPlatformChallengeResponse(
282       const cdm::PlatformChallengeResponse& response) OVERRIDE {
283     cdm_->OnPlatformChallengeResponse(response);
284   }
285
286   virtual void OnQueryOutputProtectionStatus(
287       uint32_t link_mask,
288       uint32_t output_protection_mask) OVERRIDE {
289     cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask);
290   }
291
292   uint32_t CreateSessionId() {
293     return next_session_id_++;
294   }
295
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));
300   }
301
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())
306       return 0;
307     uint32_t promise_id = it->second;
308     promise_to_session_id_map_.erase(it);
309     return promise_id;
310   }
311
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));
317   }
318
319   uint32_t LookupSessionId(std::string web_session_id) {
320     return web_session_to_session_id_map_.find(web_session_id)->second;
321   }
322
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();
327          ++it) {
328       if (it->second == session_id)
329         return it->first;
330     }
331     PP_NOTREACHED();
332     return std::string();
333   }
334
335   virtual void DropWebSessionId(std::string web_session_id) {
336     web_session_to_session_id_map_.erase(web_session_id);
337   }
338
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())
344       return false;
345     web_session_id->swap(it->second);
346     promises_needing_usable_keys_event_.erase(it);
347     return true;
348   }
349
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)));
355   }
356
357   virtual void ConvertInputBuffer(const cdm::InputBuffer& v2,
358                                   cdm::InputBuffer_1* v1) {
359     v1->data = v2.data;
360     v1->data_size = v2.data_size;
361     v1->data_offset = 0;
362     v1->key_id = v2.key_id;
363     v1->key_id_size = v2.key_id_size;
364     v1->iv = v2.iv;
365     v1->iv_size = v2.iv_size;
366     v1->subsamples = v2.subsamples;
367     v1->num_subsamples = v2.num_subsamples;
368     v1->timestamp = v2.timestamp;
369   }
370
371   virtual std::string ConvertInitDataTypeToContentType(
372       const std::string& init_data_type) const {
373     if (init_data_type == "cenc")
374       return "video/mp4";
375     if (init_data_type == "webm")
376       return "video/webm";
377     return init_data_type;
378   }
379
380  private:
381   CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm), next_session_id_(100) {
382     PP_DCHECK(cdm_);
383   }
384
385   CdmInterface* cdm_;
386
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_;
390
391   std::map<uint32_t, std::string> promises_needing_usable_keys_event_;
392
393   DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl);
394 };
395
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.
405
406 template <>
407 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CreateSession(
408     uint32_t promise_id,
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(),
421                       init_data,
422                       init_data_size);
423 }
424
425 template <>
426 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::LoadSession(
427     uint32_t promise_id,
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);
437 }
438
439 template <>
440 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::UpdateSession(
441     uint32_t promise_id,
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);
454 }
455
456 template <>
457 void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CloseSession(
458     uint32_t promise_id,
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);
465 }
466
467 template <>
468 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::RemoveSession(
469     uint32_t promise_id,
470     const char* web_session_id,
471     uint32_t web_session_id_size) {
472   return false;
473 }
474
475 template <>
476 bool CdmWrapperImpl<cdm::ContentDecryptionModule_4>::GetUsableKeyIds(
477     uint32_t promise_id,
478     const char* web_session_id,
479     uint32_t web_session_id_size) {
480   return false;
481 }
482
483 template <>
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);
490 }
491
492 template <>
493 cdm::Status
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);
500 }
501
502 template <>
503 cdm::Status
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);
510 }
511
512 // Overrides for the cdm::Host_5 methods.
513 // TODO(jrummell): Remove these once Host_5 interface is removed.
514
515 template <>
516 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::CreateSession(
517     uint32_t promise_id,
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),
535                         cdm::kPersistent);
536     return;
537   }
538
539   cdm_->CreateSession(promise_id,
540                       converted_init_data_type.data(),
541                       converted_init_data_type.length(),
542                       init_data,
543                       init_data_size,
544                       session_type);
545 }
546
547 template <>
548 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::LoadSession(
549     uint32_t promise_id,
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);
557 }
558
559 template <>
560 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::UpdateSession(
561     uint32_t promise_id,
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);
570   cdm_->UpdateSession(
571       promise_id, web_session_id, web_session_id_size, response, response_size);
572 }
573
574 template <>
575 void CdmWrapperImpl<cdm::ContentDecryptionModule_5>::CloseSession(
576     uint32_t promise_id,
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);
580 }
581
582 template <>
583 bool CdmWrapperImpl<cdm::ContentDecryptionModule_5>::RemoveSession(
584     uint32_t promise_id,
585     const char* web_session_id,
586     uint32_t web_session_id_size) {
587   return false;
588 }
589
590 template <>
591 bool CdmWrapperImpl<cdm::ContentDecryptionModule_5>::GetUsableKeyIds(
592     uint32_t promise_id,
593     const char* web_session_id,
594     uint32_t web_session_id_size) {
595   return false;
596 }
597
598 template <>
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);
605 }
606
607 template <>
608 cdm::Status
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);
615 }
616
617 template <>
618 cdm::Status
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);
625 }
626
627 CdmWrapper* CdmWrapper::Create(const char* key_system,
628                                uint32_t key_system_size,
629                                GetCdmHostFunc get_cdm_host_func,
630                                void* user_data) {
631   COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
632                      cdm::ContentDecryptionModule_6::kVersion,
633                  update_code_below);
634
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().
639   PP_DCHECK(
640       !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion +
641                                       1) &&
642       IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) &&
643       IsSupportedCdmInterfaceVersion(
644           cdm::ContentDecryptionModule_4::kVersion) &&
645       !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule_4::kVersion -
646                                       1));
647
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);
652   if (cdm_wrapper)
653     return cdm_wrapper;
654
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);
659   if (cdm_wrapper)
660     return cdm_wrapper;
661
662   cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_4>::Create(
663       key_system, key_system_size, get_cdm_host_func, user_data);
664   return cdm_wrapper;
665 }
666
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
669 // does not have.
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);
674
675 }  // namespace media
676
677 #endif  // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_