cdm_wrapper.h revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/cdm/ppapi/api/content_decryption_module.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/cdm/ppapi/cdm_helpers.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/cpp/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CdmWrapper wraps different versions of ContentDecryptionModule interfaces and
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exposes a common interface to the caller.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The caller should call CdmWrapper::Create() to create a CDM instance.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CdmWrapper will first try to create a CDM instance that supports the latest
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CDM interface (ContentDecryptionModule). If such an instance cannot be
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that supports an older version of CDM interface (e.g.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calls to corresponding ContentDecryptionModule calls.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that CdmWrapper interface always reflects the latest state of content
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private).
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Since this file is highly templated and default implementations are short
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (just a shim layer in most cases), everything is done in this header file.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CdmWrapper {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static CdmWrapper* Create(const char* key_system,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            int key_system_size,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            GetCdmHostFunc get_cdm_host_func,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            void* user_data);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CdmWrapper() {};
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual cdm::Status GenerateKeyRequest(const char* type,
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         int type_size,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const uint8_t* init_data,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int init_data_size) = 0;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual cdm::Status AddKey(const char* session_id,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int session_id_size,
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const uint8_t* key,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int key_size,
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             const uint8_t* key_id,
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             int key_id_size) = 0;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual cdm::Status CancelKeyRequest(const char* session_id,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       int session_id_size) = 0;
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void TimerExpired(void* context) = 0;
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              cdm::DecryptedBlock* decrypted_buffer) = 0;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual cdm::Status InitializeAudioDecoder(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const cdm::AudioDecoderConfig& audio_decoder_config) = 0;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual cdm::Status InitializeVideoDecoder(
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const cdm::VideoDecoderConfig& video_decoder_config) = 0;
59  virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0;
60  virtual void ResetDecoder(cdm::StreamType decoder_type) = 0;
61  virtual cdm::Status DecryptAndDecodeFrame(
62      const cdm::InputBuffer& encrypted_buffer,
63      cdm::VideoFrame* video_frame) = 0;
64  virtual cdm::Status DecryptAndDecodeSamples(
65      const cdm::InputBuffer& encrypted_buffer,
66      cdm::AudioFrames* audio_frames) = 0;
67  virtual void OnPlatformChallengeResponse(
68      const cdm::PlatformChallengeResponse& response) = 0;
69  virtual void OnQueryOutputProtectionStatus(
70      uint32_t link_mask,
71      uint32_t output_protection_mask) = 0;
72
73 protected:
74  CdmWrapper() {};
75
76 private:
77  DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
78};
79
80// Template class that does the CdmWrapper -> CdmInterface conversion. Default
81// implementations are provided. Any methods that need special treatment should
82// be specialized.
83template <class CdmInterface>
84class CdmWrapperImpl : public CdmWrapper {
85 public:
86  static CdmWrapper* Create(const char* key_system,
87                            int key_system_size,
88                            GetCdmHostFunc get_cdm_host_func,
89                            void* user_data) {
90    void* cdm_instance = ::CreateCdmInstance(
91        CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func,
92        user_data);
93    if (!cdm_instance)
94      return NULL;
95
96    return new CdmWrapperImpl<CdmInterface>(
97        static_cast<CdmInterface*>(cdm_instance));
98  }
99
100  virtual ~CdmWrapperImpl() {
101    cdm_->Destroy();
102  }
103
104  virtual cdm::Status GenerateKeyRequest(const char* type,
105                                         int type_size,
106                                         const uint8_t* init_data,
107                                         int init_data_size) OVERRIDE {
108    return cdm_->GenerateKeyRequest(type, type_size, init_data, init_data_size);
109  }
110
111  virtual cdm::Status AddKey(const char* session_id,
112                             int session_id_size,
113                             const uint8_t* key,
114                             int key_size,
115                             const uint8_t* key_id,
116                             int key_id_size) OVERRIDE {
117    return cdm_->AddKey(
118        session_id, session_id_size, key, key_size, key_id, key_id_size);
119  }
120
121  virtual cdm::Status CancelKeyRequest(const char* session_id,
122                                       int session_id_size) OVERRIDE {
123    return cdm_->CancelKeyRequest(session_id, session_id_size);
124  }
125
126  virtual void TimerExpired(void* context) OVERRIDE {
127    cdm_->TimerExpired(context);
128  }
129
130  virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
131                              cdm::DecryptedBlock* decrypted_buffer) OVERRIDE {
132    return cdm_->Decrypt(encrypted_buffer, decrypted_buffer);
133  }
134
135  virtual cdm::Status InitializeAudioDecoder(
136      const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE {
137    return cdm_->InitializeAudioDecoder(audio_decoder_config);
138  }
139
140  virtual cdm::Status InitializeVideoDecoder(
141      const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE {
142    return cdm_->InitializeVideoDecoder(video_decoder_config);
143  }
144
145  virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE {
146    cdm_->DeinitializeDecoder(decoder_type);
147  }
148
149  virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE {
150    cdm_->ResetDecoder(decoder_type);
151  }
152
153  virtual cdm::Status DecryptAndDecodeFrame(
154      const cdm::InputBuffer& encrypted_buffer,
155      cdm::VideoFrame* video_frame) OVERRIDE {
156    return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame);
157  }
158
159  virtual cdm::Status DecryptAndDecodeSamples(
160      const cdm::InputBuffer& encrypted_buffer,
161      cdm::AudioFrames* audio_frames) OVERRIDE {
162    return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames);
163  }
164
165  virtual void OnPlatformChallengeResponse(
166      const cdm::PlatformChallengeResponse& response) OVERRIDE {
167    cdm_->OnPlatformChallengeResponse(response);
168  }
169
170  virtual void OnQueryOutputProtectionStatus(
171      uint32_t link_mask,
172      uint32_t output_protection_mask) OVERRIDE {
173    cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask);
174  }
175
176 private:
177  CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) {
178    PP_DCHECK(cdm_);
179  }
180
181  CdmInterface* cdm_;
182
183  DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl);
184};
185
186// Specializations for ContentDecryptionModule_1.
187
188template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
189    OnPlatformChallengeResponse(
190        const cdm::PlatformChallengeResponse& response) {
191  PP_NOTREACHED();
192}
193
194template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
195    OnQueryOutputProtectionStatus(uint32_t link_mask,
196                                  uint32_t output_protection_mask) {
197  PP_NOTREACHED();
198}
199
200template <> cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
201    DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer,
202                            cdm::AudioFrames* audio_frames) {
203  AudioFramesImpl audio_frames_1;
204  cdm::Status status =
205      cdm_->DecryptAndDecodeSamples(encrypted_buffer, &audio_frames_1);
206  if (status != cdm::kSuccess)
207    return status;
208
209  audio_frames->SetFrameBuffer(audio_frames_1.PassFrameBuffer());
210  audio_frames->SetFormat(cdm::kAudioFormatS16);
211  return cdm::kSuccess;
212}
213
214CdmWrapper* CdmWrapper::Create(const char* key_system,
215                               int key_system_size,
216                               GetCdmHostFunc get_cdm_host_func,
217                               void* user_data) {
218  // Try to create the CDM using the latest CDM interface version.
219  CdmWrapper* cdm_adapter =
220      CdmWrapperImpl<cdm::ContentDecryptionModule>::Create(
221          key_system, key_system_size, get_cdm_host_func, user_data);
222  if (cdm_adapter)
223    return cdm_adapter;
224
225  // Try to see if the CDM supports older version(s) of CDM interface(s).
226  cdm_adapter = CdmWrapperImpl<cdm::ContentDecryptionModule_1>::Create(
227      key_system, key_system_size, get_cdm_host_func, user_data);
228  return cdm_adapter;
229}
230
231// When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain
232// stub implementations for new or modified methods which the older CDM
233// interface does not have.
234COMPILE_ASSERT(cdm::ContentDecryptionModule_2::kVersion ==
235                   cdm::ContentDecryptionModule::kVersion,
236               ensure_cdm_wrapper_templates_have_old_version_support);
237
238}  // namespace media
239
240#endif  // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
241