cdm_wrapper.h revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 "media/cdm/ppapi/supported_cdm_versions.h"
12#include "ppapi/cpp/logging.h"
13
14namespace media {
15
16// CdmWrapper wraps different versions of ContentDecryptionModule interfaces and
17// exposes a common interface to the caller.
18//
19// The caller should call CdmWrapper::Create() to create a CDM instance.
20// CdmWrapper will first try to create a CDM instance that supports the latest
21// CDM interface (ContentDecryptionModule). If such an instance cannot be
22// created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM
23// that supports an older version of CDM interface (e.g.
24// ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper
25// calls to corresponding ContentDecryptionModule calls.
26//
27// Note that CdmWrapper interface always reflects the latest state of content
28// decryption related PPAPI APIs (e.g. pp::ContentDecryptor_Private).
29//
30// Since this file is highly templated and default implementations are short
31// (just a shim layer in most cases), everything is done in this header file.
32class CdmWrapper {
33 public:
34  static CdmWrapper* Create(const char* key_system,
35                            uint32_t key_system_size,
36                            GetCdmHostFunc get_cdm_host_func,
37                            void* user_data);
38
39  virtual ~CdmWrapper() {};
40
41  virtual cdm::Status GenerateKeyRequest(const char* type,
42                                         uint32_t type_size,
43                                         const uint8_t* init_data,
44                                         uint32_t init_data_size) = 0;
45  virtual cdm::Status AddKey(const char* session_id,
46                             uint32_t session_id_size,
47                             const uint8_t* key,
48                             uint32_t key_size,
49                             const uint8_t* key_id,
50                             uint32_t key_id_size) = 0;
51  virtual cdm::Status CancelKeyRequest(const char* session_id,
52                                       uint32_t session_id_size) = 0;
53  virtual void TimerExpired(void* context) = 0;
54  virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
55                              cdm::DecryptedBlock* decrypted_buffer) = 0;
56  virtual cdm::Status InitializeAudioDecoder(
57      const cdm::AudioDecoderConfig& audio_decoder_config) = 0;
58  virtual cdm::Status InitializeVideoDecoder(
59      const cdm::VideoDecoderConfig& video_decoder_config) = 0;
60  virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0;
61  virtual void ResetDecoder(cdm::StreamType decoder_type) = 0;
62  virtual cdm::Status DecryptAndDecodeFrame(
63      const cdm::InputBuffer& encrypted_buffer,
64      cdm::VideoFrame* video_frame) = 0;
65  virtual cdm::Status DecryptAndDecodeSamples(
66      const cdm::InputBuffer& encrypted_buffer,
67      cdm::AudioFrames* audio_frames) = 0;
68  virtual void OnPlatformChallengeResponse(
69      const cdm::PlatformChallengeResponse& response) = 0;
70  virtual void OnQueryOutputProtectionStatus(
71      uint32_t link_mask,
72      uint32_t output_protection_mask) = 0;
73
74 protected:
75  CdmWrapper() {};
76
77 private:
78  DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
79};
80
81// Template class that does the CdmWrapper -> CdmInterface conversion. Default
82// implementations are provided. Any methods that need special treatment should
83// be specialized.
84template <class CdmInterface>
85class CdmWrapperImpl : public CdmWrapper {
86 public:
87  static CdmWrapper* Create(const char* key_system,
88                            uint32_t key_system_size,
89                            GetCdmHostFunc get_cdm_host_func,
90                            void* user_data) {
91    void* cdm_instance = ::CreateCdmInstance(
92        CdmInterface::kVersion, key_system, key_system_size, get_cdm_host_func,
93        user_data);
94    if (!cdm_instance)
95      return NULL;
96
97    return new CdmWrapperImpl<CdmInterface>(
98        static_cast<CdmInterface*>(cdm_instance));
99  }
100
101  virtual ~CdmWrapperImpl() {
102    cdm_->Destroy();
103  }
104
105  virtual cdm::Status GenerateKeyRequest(const char* type,
106                                         uint32_t type_size,
107                                         const uint8_t* init_data,
108                                         uint32_t init_data_size) OVERRIDE {
109    return cdm_->GenerateKeyRequest(type, type_size, init_data, init_data_size);
110  }
111
112  virtual cdm::Status AddKey(const char* session_id,
113                             uint32_t session_id_size,
114                             const uint8_t* key,
115                             uint32_t key_size,
116                             const uint8_t* key_id,
117                             uint32_t key_id_size) OVERRIDE {
118    return cdm_->AddKey(
119        session_id, session_id_size, key, key_size, key_id, key_id_size);
120  }
121
122  virtual cdm::Status CancelKeyRequest(const char* session_id,
123                                       uint32_t session_id_size) OVERRIDE {
124    return cdm_->CancelKeyRequest(session_id, session_id_size);
125  }
126
127  virtual void TimerExpired(void* context) OVERRIDE {
128    cdm_->TimerExpired(context);
129  }
130
131  virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
132                              cdm::DecryptedBlock* decrypted_buffer) OVERRIDE {
133    return cdm_->Decrypt(encrypted_buffer, decrypted_buffer);
134  }
135
136  virtual cdm::Status InitializeAudioDecoder(
137      const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE {
138    return cdm_->InitializeAudioDecoder(audio_decoder_config);
139  }
140
141  virtual cdm::Status InitializeVideoDecoder(
142      const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE {
143    return cdm_->InitializeVideoDecoder(video_decoder_config);
144  }
145
146  virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE {
147    cdm_->DeinitializeDecoder(decoder_type);
148  }
149
150  virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE {
151    cdm_->ResetDecoder(decoder_type);
152  }
153
154  virtual cdm::Status DecryptAndDecodeFrame(
155      const cdm::InputBuffer& encrypted_buffer,
156      cdm::VideoFrame* video_frame) OVERRIDE {
157    return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame);
158  }
159
160  virtual cdm::Status DecryptAndDecodeSamples(
161      const cdm::InputBuffer& encrypted_buffer,
162      cdm::AudioFrames* audio_frames) OVERRIDE {
163    return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames);
164  }
165
166  virtual void OnPlatformChallengeResponse(
167      const cdm::PlatformChallengeResponse& response) OVERRIDE {
168    cdm_->OnPlatformChallengeResponse(response);
169  }
170
171  virtual void OnQueryOutputProtectionStatus(
172      uint32_t link_mask,
173      uint32_t output_protection_mask) OVERRIDE {
174    cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask);
175  }
176
177 private:
178  CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) {
179    PP_DCHECK(cdm_);
180  }
181
182  CdmInterface* cdm_;
183
184  DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl);
185};
186
187// Specializations for ContentDecryptionModule_1.
188
189template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
190    OnPlatformChallengeResponse(
191        const cdm::PlatformChallengeResponse& response) {
192  PP_NOTREACHED();
193}
194
195template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
196    OnQueryOutputProtectionStatus(uint32_t link_mask,
197                                  uint32_t output_protection_mask) {
198  PP_NOTREACHED();
199}
200
201template <> cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
202    DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer,
203                            cdm::AudioFrames* audio_frames) {
204  AudioFramesImpl audio_frames_1;
205  cdm::Status status =
206      cdm_->DecryptAndDecodeSamples(encrypted_buffer, &audio_frames_1);
207  if (status != cdm::kSuccess)
208    return status;
209
210  audio_frames->SetFrameBuffer(audio_frames_1.PassFrameBuffer());
211  audio_frames->SetFormat(cdm::kAudioFormatS16);
212  return cdm::kSuccess;
213}
214
215CdmWrapper* CdmWrapper::Create(const char* key_system,
216                               uint32_t key_system_size,
217                               GetCdmHostFunc get_cdm_host_func,
218                               void* user_data) {
219  COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
220                 cdm::ContentDecryptionModule_2::kVersion,
221                 update_code_below);
222
223  // Ensure IsSupportedCdmInterfaceVersion matches this implementation.
224  // Always update this DCHECK when updating this function.
225  // If this check fails, update this function and DCHECK or update
226  // IsSupportedCdmInterfaceVersion.
227  PP_DCHECK(
228      !IsSupportedCdmInterfaceVersion(
229          cdm::ContentDecryptionModule::kVersion + 1) &&
230      IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) &&
231      IsSupportedCdmInterfaceVersion(
232          cdm::ContentDecryptionModule_1::kVersion) &&
233      !IsSupportedCdmInterfaceVersion(
234          cdm::ContentDecryptionModule_1::kVersion - 1));
235
236  // Try to create the CDM using the latest CDM interface version.
237  CdmWrapper* cdm_wrapper =
238      CdmWrapperImpl<cdm::ContentDecryptionModule>::Create(
239          key_system, key_system_size, get_cdm_host_func, user_data);
240  if (cdm_wrapper)
241    return cdm_wrapper;
242
243  // Try to see if the CDM supports older version(s) of the CDM interface.
244  cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_1>::Create(
245      key_system, key_system_size, get_cdm_host_func, user_data);
246  return cdm_wrapper;
247}
248
249// When updating the CdmAdapter, ensure you've updated the CdmWrapper to contain
250// stub implementations for new or modified methods that the older CDM interface
251// does not have.
252// Also update supported_cdm_versions.h.
253COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
254                   cdm::ContentDecryptionModule_2::kVersion,
255               ensure_cdm_wrapper_templates_have_old_version_support);
256
257}  // namespace media
258
259#endif  // MEDIA_CDM_PPAPI_CDM_WRAPPER_H_
260