cdm_wrapper.h revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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 "base/basictypes.h"
9#include "media/cdm/ppapi/api/content_decryption_module.h"
10#include "media/cdm/ppapi/cdm_helpers.h"
11#include "ppapi/cpp/logging.h"
12
13namespace media {
14
15// CdmWrapper wraps different versions of ContentDecryptionModule interfaces and
16// exposes a common interface to the caller.
17//
18// The caller should call CdmWrapper::Create() to create a CDM instance.
19// CdmWrapper will first try to create a CDM instance that supports the latest
20// CDM interface (ContentDecryptionModule). If such an instance cannot be
21// created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM
22// that supports an older version of CDM interface (e.g.
23// ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper
24// calls to corresponding ContentDecryptionModule calls.
25//
26// Note that CdmWrapper interface always reflects the latest state of content
27// decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private).
28//
29// Since this file is highly templated and default implementations are short
30// (just a shim layer in most cases), everything is done in this header file.
31class CdmWrapper {
32 public:
33  static CdmWrapper* Create(const char* key_system,
34                            int key_system_size,
35                            GetCdmHostFunc get_cdm_host_func,
36                            void* user_data);
37
38  virtual ~CdmWrapper() {};
39
40  virtual cdm::Status GenerateKeyRequest(const char* type,
41                                         int type_size,
42                                         const uint8_t* init_data,
43                                         int init_data_size) = 0;
44  virtual cdm::Status AddKey(const char* session_id,
45                             int session_id_size,
46                             const uint8_t* key,
47                             int key_size,
48                             const uint8_t* key_id,
49                             int key_id_size) = 0;
50  virtual cdm::Status CancelKeyRequest(const char* session_id,
51                                       int session_id_size) = 0;
52  virtual void TimerExpired(void* context) = 0;
53  virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
54                              cdm::DecryptedBlock* decrypted_buffer) = 0;
55  virtual cdm::Status InitializeAudioDecoder(
56      const cdm::AudioDecoderConfig& audio_decoder_config) = 0;
57  virtual cdm::Status InitializeVideoDecoder(
58      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