blob: 77c2248e257cb11395a1f725028b09e2af85289a [file] [log] [blame]
[email protected]e5aeef02012-08-17 00:18:431// Copyright (c) 2012 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
[email protected]9264e1502012-09-18 19:53:015#include <cstring>
6#include <string>
[email protected]d341e332012-08-28 18:57:407#include <vector>
[email protected]e5aeef02012-08-17 00:18:438
[email protected]9264e1502012-09-18 19:53:019#include "base/basictypes.h"
10#include "base/compiler_specific.h"
[email protected]e5aeef02012-08-17 00:18:4311#include "ppapi/c/pp_errors.h"
12#include "ppapi/c/pp_stdint.h"
[email protected]98ad9782012-08-22 04:06:2213#include "ppapi/c/private/pp_content_decryptor.h"
[email protected]e5aeef02012-08-17 00:18:4314#include "ppapi/cpp/completion_callback.h"
15#include "ppapi/cpp/core.h"
16#include "ppapi/cpp/instance.h"
17#include "ppapi/cpp/logging.h"
18#include "ppapi/cpp/module.h"
19#include "ppapi/cpp/pass_ref.h"
20#include "ppapi/cpp/resource.h"
21#include "ppapi/cpp/var.h"
22#include "ppapi/cpp/var_array_buffer.h"
23#include "ppapi/cpp/dev/buffer_dev.h"
24#include "ppapi/cpp/private/content_decryptor_private.h"
25#include "ppapi/utility/completion_callback_factory.h"
[email protected]d341e332012-08-28 18:57:4026#include "webkit/media/crypto/ppapi/content_decryption_module.h"
[email protected]bf5f1682012-10-23 04:31:4327#include "webkit/media/crypto/ppapi/linked_ptr.h"
[email protected]e5aeef02012-08-17 00:18:4328
29namespace {
30
[email protected]d341e332012-08-28 18:57:4031// This must be consistent with MediaKeyError defined in the spec:
32// http://goo.gl/rbdnR
33// TODO(xhwang): Add PP_MediaKeyError enum to avoid later static_cast in
34// PluginInstance.
35enum MediaKeyError {
36 kUnknownError = 1,
37 kClientError,
38 kServiceError,
39 kOutputError,
40 kHardwareChangeError,
41 kDomainError
[email protected]e5aeef02012-08-17 00:18:4342};
43
[email protected]98ad9782012-08-22 04:06:2244bool IsMainThread() {
45 return pp::Module::Get()->core()->IsMainThread();
46}
47
[email protected]e5aeef02012-08-17 00:18:4348void CallOnMain(pp::CompletionCallback cb) {
[email protected]98ad9782012-08-22 04:06:2249 // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
50 // off the main thread yet. Remove this once the change lands.
51 if (IsMainThread())
52 cb.Run(PP_OK);
53 else
54 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
[email protected]e5aeef02012-08-17 00:18:4355}
56
[email protected]181d9c12012-10-03 22:53:4857// Configures a cdm::InputBuffer. |subsamples| must exist as long as
58// |input_buffer| is in use.
59void ConfigureInputBuffer(
60 const pp::Buffer_Dev& encrypted_buffer,
61 const PP_EncryptedBlockInfo& encrypted_block_info,
62 std::vector<cdm::SubsampleEntry>* subsamples,
63 cdm::InputBuffer* input_buffer) {
64 PP_DCHECK(subsamples);
[email protected]741c28f2012-10-18 07:02:2565 PP_DCHECK(!encrypted_buffer.is_null());
66
[email protected]181d9c12012-10-03 22:53:4867 input_buffer->data = reinterpret_cast<uint8_t*>(encrypted_buffer.data());
68 input_buffer->data_size = encrypted_buffer.size();
69 input_buffer->data_offset = encrypted_block_info.data_offset;
70 input_buffer->key_id = encrypted_block_info.key_id;
71 input_buffer->key_id_size = encrypted_block_info.key_id_size;
72 input_buffer->iv = encrypted_block_info.iv;
73 input_buffer->iv_size = encrypted_block_info.iv_size;
74 input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
75
76 if (encrypted_block_info.num_subsamples > 0) {
77 subsamples->reserve(encrypted_block_info.num_subsamples);
78
79 for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
80 subsamples->push_back(cdm::SubsampleEntry(
81 encrypted_block_info.subsamples[i].clear_bytes,
82 encrypted_block_info.subsamples[i].cipher_bytes));
83 }
84
85 input_buffer->subsamples = &(*subsamples)[0];
86 }
87
88 input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
89}
90
[email protected]8f5a9a52012-10-23 20:49:2091PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
92 switch (status) {
93 case cdm::kSuccess:
94 return PP_DECRYPTRESULT_SUCCESS;
95 case cdm::kNoKey:
96 return PP_DECRYPTRESULT_DECRYPT_NOKEY;
97 case cdm::kNeedMoreData:
98 return PP_DECRYPTRESULT_NEEDMOREDATA;
99 case cdm::kDecryptError:
100 return PP_DECRYPTRESULT_DECRYPT_ERROR;
101 case cdm::kDecodeError:
102 return PP_DECRYPTRESULT_DECODE_ERROR;
103 default:
104 PP_NOTREACHED();
105 return PP_DECRYPTRESULT_DECODE_ERROR;
106 }
107}
108
[email protected]e9d3a1022012-10-11 23:43:55109PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
[email protected]181d9c12012-10-03 22:53:48110 cdm::VideoFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20111 switch (format) {
112 case cdm::kYv12:
113 return PP_DECRYPTEDFRAMEFORMAT_YV12;
114 case cdm::kI420:
115 return PP_DECRYPTEDFRAMEFORMAT_I420;
116 default:
117 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
118 }
[email protected]e9d3a1022012-10-11 23:43:55119}
120
[email protected]c999b3b72012-10-19 22:33:46121cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
122 PP_AudioCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20123 switch (codec) {
124 case PP_AUDIOCODEC_VORBIS:
125 return cdm::AudioDecoderConfig::kCodecVorbis;
126 default:
127 return cdm::AudioDecoderConfig::kUnknownAudioCodec;
128 }
[email protected]c999b3b72012-10-19 22:33:46129}
130
[email protected]e9d3a1022012-10-11 23:43:55131cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
132 PP_VideoCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20133 switch (codec) {
134 case PP_VIDEOCODEC_VP8:
135 return cdm::VideoDecoderConfig::kCodecVP8;
136 default:
137 return cdm::VideoDecoderConfig::kUnknownVideoCodec;
138 }
[email protected]e9d3a1022012-10-11 23:43:55139}
140
141cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
142 PP_VideoCodecProfile profile) {
[email protected]8f5a9a52012-10-23 20:49:20143 switch (profile) {
144 case PP_VIDEOCODECPROFILE_VP8_MAIN:
145 return cdm::VideoDecoderConfig::kVp8ProfileMain;
146 default:
147 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
148 }
[email protected]e9d3a1022012-10-11 23:43:55149}
150
151cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
152 PP_DecryptedFrameFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20153 switch (format) {
154 case PP_DECRYPTEDFRAMEFORMAT_YV12:
155 return cdm::kYv12;
156 case PP_DECRYPTEDFRAMEFORMAT_I420:
157 return cdm::kI420;
158 default:
159 return cdm::kUnknownVideoFormat;
160 }
[email protected]181d9c12012-10-03 22:53:48161}
162
[email protected]bf5f1682012-10-23 04:31:43163cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
164 PP_DecryptorStreamType stream_type) {
165 switch (stream_type) {
166 case PP_DECRYPTORSTREAMTYPE_AUDIO:
167 return cdm::kStreamTypeAudio;
168 case PP_DECRYPTORSTREAMTYPE_VIDEO:
169 return cdm::kStreamTypeVideo;
170 }
171
172 PP_NOTREACHED();
173 return cdm::kStreamTypeVideo;
174}
175
[email protected]e5aeef02012-08-17 00:18:43176} // namespace
177
[email protected]d341e332012-08-28 18:57:40178namespace webkit_media {
[email protected]e5aeef02012-08-17 00:18:43179
[email protected]9264e1502012-09-18 19:53:01180// Provides access to memory owned by a pp::Buffer_Dev created by
181// PpbBufferAllocator::Allocate(). This class holds a reference to the
182// Buffer_Dev throughout its lifetime.
183class PpbBuffer : public cdm::Buffer {
184 public:
185 // cdm::Buffer methods.
186 virtual void Destroy() OVERRIDE { delete this; }
187
[email protected]7ed56ed2012-10-02 02:43:27188 virtual uint8_t* data() OVERRIDE {
[email protected]9264e1502012-09-18 19:53:01189 return static_cast<uint8_t*>(buffer_.data());
190 }
191
192 virtual int32_t size() const OVERRIDE { return buffer_.size(); }
193
194 pp::Buffer_Dev buffer_dev() const { return buffer_; }
195
196 private:
197 explicit PpbBuffer(pp::Buffer_Dev buffer) : buffer_(buffer) {}
198 virtual ~PpbBuffer() {}
199
200 pp::Buffer_Dev buffer_;
201
202 friend class PpbBufferAllocator;
203
204 DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
205};
206
207class PpbBufferAllocator : public cdm::Allocator {
208 public:
209 explicit PpbBufferAllocator(pp::Instance* instance);
210 virtual ~PpbBufferAllocator();
211
212 // cdm::Allocator methods.
213 // Allocates a pp::Buffer_Dev of the specified size and wraps it in a
214 // PpbBuffer, which it returns. The caller own the returned buffer and must
215 // free it by calling ReleaseBuffer(). Returns NULL on failure.
216 virtual cdm::Buffer* Allocate(int32_t size) OVERRIDE;
217
218 private:
219 pp::Instance* const instance_;
220
221 DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
222};
223
[email protected]7ed56ed2012-10-02 02:43:27224class DecryptedBlockImpl : public cdm::DecryptedBlock {
225 public:
226 DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
227 virtual ~DecryptedBlockImpl();
228
229 virtual void set_buffer(cdm::Buffer* buffer) OVERRIDE;
230 virtual cdm::Buffer* buffer() OVERRIDE;
231
232 virtual void set_timestamp(int64_t timestamp) OVERRIDE;
233 virtual int64_t timestamp() const OVERRIDE;
234
235 private:
236 PpbBuffer* buffer_;
237 int64_t timestamp_;
238
239 DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
240};
241
[email protected]9264e1502012-09-18 19:53:01242class KeyMessageImpl : public cdm::KeyMessage {
243 public:
244 KeyMessageImpl() : message_(NULL) {}
245 virtual ~KeyMessageImpl();
246
247 // cdm::KeyMessage methods.
248 virtual void set_session_id(const char* session_id, int32_t length) OVERRIDE;
249 virtual const char* session_id() const OVERRIDE;
250 virtual int32_t session_id_length() const OVERRIDE;
251
252 virtual void set_message(cdm::Buffer* message) OVERRIDE;
[email protected]7ed56ed2012-10-02 02:43:27253 virtual cdm::Buffer* message() OVERRIDE;
[email protected]9264e1502012-09-18 19:53:01254
255 virtual void set_default_url(const char* default_url,
256 int32_t length) OVERRIDE;
257 virtual const char* default_url() const OVERRIDE;
258 virtual int32_t default_url_length() const OVERRIDE;
259
260 std::string session_id_string() const { return session_id_; }
261 std::string default_url_string() const { return default_url_; }
262
263 private:
264 PpbBuffer* message_;
265 std::string session_id_;
266 std::string default_url_;
267
268 DISALLOW_COPY_AND_ASSIGN(KeyMessageImpl);
269};
270
[email protected]7ed56ed2012-10-02 02:43:27271DecryptedBlockImpl::~DecryptedBlockImpl() {
272 if (buffer_)
273 buffer_->Destroy();
274}
[email protected]9264e1502012-09-18 19:53:01275
[email protected]7ed56ed2012-10-02 02:43:27276void DecryptedBlockImpl::set_buffer(cdm::Buffer* buffer) {
277 buffer_ = static_cast<PpbBuffer*>(buffer);
278}
[email protected]9264e1502012-09-18 19:53:01279
[email protected]7ed56ed2012-10-02 02:43:27280cdm::Buffer* DecryptedBlockImpl::buffer() {
281 return buffer_;
282}
[email protected]9264e1502012-09-18 19:53:01283
[email protected]7ed56ed2012-10-02 02:43:27284void DecryptedBlockImpl::set_timestamp(int64_t timestamp) {
285 timestamp_ = timestamp;
286}
[email protected]9264e1502012-09-18 19:53:01287
[email protected]7ed56ed2012-10-02 02:43:27288int64_t DecryptedBlockImpl::timestamp() const {
289 return timestamp_;
290}
[email protected]9264e1502012-09-18 19:53:01291
[email protected]181d9c12012-10-03 22:53:48292class VideoFrameImpl : public cdm::VideoFrame {
293 public:
294 VideoFrameImpl();
295 virtual ~VideoFrameImpl();
296
297 virtual void set_format(cdm::VideoFormat format) OVERRIDE;
298 virtual cdm::VideoFormat format() const OVERRIDE;
299
[email protected]d0ec47492012-10-13 05:01:46300 virtual void set_size(cdm::Size size) OVERRIDE;
301 virtual cdm::Size size() const OVERRIDE;
302
[email protected]181d9c12012-10-03 22:53:48303 virtual void set_frame_buffer(cdm::Buffer* frame_buffer) OVERRIDE;
304 virtual cdm::Buffer* frame_buffer() OVERRIDE;
305
306 virtual void set_plane_offset(cdm::VideoFrame::VideoPlane plane,
307 int32_t offset) OVERRIDE;
308 virtual int32_t plane_offset(VideoPlane plane) OVERRIDE;
309
310 virtual void set_stride(VideoPlane plane, int32_t stride) OVERRIDE;
311 virtual int32_t stride(VideoPlane plane) OVERRIDE;
312
313 virtual void set_timestamp(int64_t timestamp) OVERRIDE;
314 virtual int64_t timestamp() const OVERRIDE;
315
316 private:
317 // The video buffer format.
318 cdm::VideoFormat format_;
319
[email protected]d0ec47492012-10-13 05:01:46320 // Width and height of the video frame.
321 cdm::Size size_;
322
[email protected]181d9c12012-10-03 22:53:48323 // The video frame buffer.
324 PpbBuffer* frame_buffer_;
325
326 // Array of data pointers to each plane in the video frame buffer.
327 int32_t plane_offsets_[kMaxPlanes];
328
329 // Array of strides for each plane, typically greater or equal to the width
330 // of the surface divided by the horizontal sampling period. Note that
331 // strides can be negative.
332 int32_t strides_[kMaxPlanes];
333
334 // Presentation timestamp in microseconds.
335 int64_t timestamp_;
336};
337
[email protected]9264e1502012-09-18 19:53:01338KeyMessageImpl::~KeyMessageImpl() {
339 if (message_)
340 message_->Destroy();
341}
342
343void KeyMessageImpl::set_session_id(const char* session_id, int32_t length) {
344 session_id_.assign(session_id, length);
345}
346
347const char* KeyMessageImpl::session_id() const {
348 return session_id_.c_str();
349}
350
351int32_t KeyMessageImpl::session_id_length() const {
352 return session_id_.length();
353}
354
355void KeyMessageImpl::set_message(cdm::Buffer* buffer) {
356 message_ = static_cast<PpbBuffer*>(buffer);
357}
358
[email protected]7ed56ed2012-10-02 02:43:27359cdm::Buffer* KeyMessageImpl::message() {
[email protected]9264e1502012-09-18 19:53:01360 return message_;
361}
362
363void KeyMessageImpl::set_default_url(const char* default_url, int32_t length) {
364 default_url_.assign(default_url, length);
365}
366
367const char* KeyMessageImpl::default_url() const {
368 return default_url_.c_str();
369}
370
371int32_t KeyMessageImpl::default_url_length() const {
372 return default_url_.length();
373}
374
[email protected]181d9c12012-10-03 22:53:48375VideoFrameImpl::VideoFrameImpl()
376 : format_(cdm::kUnknownVideoFormat),
377 frame_buffer_(NULL),
378 timestamp_(0) {
379 for (int32_t i = 0; i < kMaxPlanes; ++i) {
380 plane_offsets_[i] = 0;
381 strides_[i] = 0;
382 }
383}
384
385VideoFrameImpl::~VideoFrameImpl() {
386 if (frame_buffer_)
387 frame_buffer_->Destroy();
388}
389
390void VideoFrameImpl::set_format(cdm::VideoFormat format) {
391 format_ = format;
392}
393
394cdm::VideoFormat VideoFrameImpl::format() const {
395 return format_;
396}
397
[email protected]d0ec47492012-10-13 05:01:46398void VideoFrameImpl::set_size(cdm::Size size) {
399 size_ = size;
400}
401
402cdm::Size VideoFrameImpl::size() const {
403 return size_;
404}
405
[email protected]181d9c12012-10-03 22:53:48406void VideoFrameImpl::set_frame_buffer(cdm::Buffer* frame_buffer) {
407 frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
408}
409
410cdm::Buffer* VideoFrameImpl::frame_buffer() {
411 return frame_buffer_;
412}
413
414void VideoFrameImpl::set_plane_offset(cdm::VideoFrame::VideoPlane plane,
415 int32_t offset) {
[email protected]d0ec47492012-10-13 05:01:46416 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
[email protected]181d9c12012-10-03 22:53:48417 PP_DCHECK(offset >= 0);
418 plane_offsets_[plane] = offset;
419}
420
421int32_t VideoFrameImpl::plane_offset(VideoPlane plane) {
[email protected]d0ec47492012-10-13 05:01:46422 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
[email protected]181d9c12012-10-03 22:53:48423 return plane_offsets_[plane];
424}
425
426void VideoFrameImpl::set_stride(VideoPlane plane, int32_t stride) {
[email protected]d0ec47492012-10-13 05:01:46427 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
[email protected]181d9c12012-10-03 22:53:48428 strides_[plane] = stride;
429}
430
431int32_t VideoFrameImpl::stride(VideoPlane plane) {
[email protected]d0ec47492012-10-13 05:01:46432 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
[email protected]181d9c12012-10-03 22:53:48433 return strides_[plane];
434}
435
436void VideoFrameImpl::set_timestamp(int64_t timestamp) {
437 timestamp_ = timestamp;
438}
439
440int64_t VideoFrameImpl::timestamp() const {
441 return timestamp_;
442}
443
[email protected]e5aeef02012-08-17 00:18:43444// A wrapper class for abstracting away PPAPI interaction and threading for a
445// Content Decryption Module (CDM).
[email protected]d341e332012-08-28 18:57:40446class CdmWrapper : public pp::Instance,
[email protected]f5c9b938e2012-10-10 12:24:07447 public pp::ContentDecryptor_Private,
448 public cdm::CdmHost {
[email protected]e5aeef02012-08-17 00:18:43449 public:
[email protected]d341e332012-08-28 18:57:40450 CdmWrapper(PP_Instance instance, pp::Module* module);
451 virtual ~CdmWrapper();
[email protected]d341e332012-08-28 18:57:40452 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
453 return true;
454 }
[email protected]e5aeef02012-08-17 00:18:43455
456 // PPP_ContentDecryptor_Private methods
[email protected]d40797c2012-10-04 04:36:14457 // Note: Results of calls to these methods must be reported through the
458 // PPB_ContentDecryptor_Private interface.
[email protected]ea4ff802012-09-13 01:36:44459 virtual void GenerateKeyRequest(const std::string& key_system,
[email protected]e5aeef02012-08-17 00:18:43460 pp::VarArrayBuffer init_data) OVERRIDE;
[email protected]ea4ff802012-09-13 01:36:44461 virtual void AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22462 pp::VarArrayBuffer key,
463 pp::VarArrayBuffer init_data) OVERRIDE;
[email protected]ea4ff802012-09-13 01:36:44464 virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
465 virtual void Decrypt(
[email protected]98ad9782012-08-22 04:06:22466 pp::Buffer_Dev encrypted_buffer,
467 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
[email protected]c999b3b72012-10-19 22:33:46468 virtual void InitializeAudioDecoder(
469 const PP_AudioDecoderConfig& decoder_config,
470 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
[email protected]e9d3a1022012-10-11 23:43:55471 virtual void InitializeVideoDecoder(
472 const PP_VideoDecoderConfig& decoder_config,
473 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
[email protected]23de87452012-10-12 07:03:09474 virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
475 uint32_t request_id) OVERRIDE;
476 virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
477 uint32_t request_id) OVERRIDE;
[email protected]467434d2012-10-12 10:48:53478 virtual void DecryptAndDecode(
479 PP_DecryptorStreamType decoder_type,
480 pp::Buffer_Dev encrypted_buffer,
481 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
[email protected]e5aeef02012-08-17 00:18:43482
[email protected]f5c9b938e2012-10-10 12:24:07483 // CdmHost methods.
484 virtual void SetTimer(int64 delay_ms) OVERRIDE;
485 virtual double GetCurrentWallTimeMs() OVERRIDE;
486
[email protected]e5aeef02012-08-17 00:18:43487 private:
[email protected]7ed56ed2012-10-02 02:43:27488 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
[email protected]9264e1502012-09-18 19:53:01489 typedef linked_ptr<KeyMessageImpl> LinkedKeyMessage;
[email protected]181d9c12012-10-03 22:53:48490 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
[email protected]e5aeef02012-08-17 00:18:43491
492 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
493 // <code>callback_factory_</code> to ensure that calls into
494 // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
[email protected]d341e332012-08-28 18:57:40495 void KeyAdded(int32_t result, const std::string& session_id);
[email protected]9264e1502012-09-18 19:53:01496 void KeyMessage(int32_t result, const LinkedKeyMessage& message);
[email protected]d341e332012-08-28 18:57:40497 void KeyError(int32_t result, const std::string& session_id);
498 void DeliverBlock(int32_t result,
499 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:27500 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:40501 const PP_DecryptTrackingInfo& tracking_info);
[email protected]c999b3b72012-10-19 22:33:46502 void DecoderInitializeDone(int32_t result,
503 PP_DecryptorStreamType decoder_type,
504 uint32_t request_id,
505 bool success);
[email protected]23de87452012-10-12 07:03:09506 void DecoderDeinitializeDone(int32_t result,
507 PP_DecryptorStreamType decoder_type,
508 uint32_t request_id);
509 void DecoderResetDone(int32_t result,
510 PP_DecryptorStreamType decoder_type,
511 uint32_t request_id);
[email protected]181d9c12012-10-03 22:53:48512 void DeliverFrame(int32_t result,
513 const cdm::Status& status,
514 const LinkedVideoFrame& video_frame,
515 const PP_DecryptTrackingInfo& tracking_info);
[email protected]e5aeef02012-08-17 00:18:43516
[email protected]f5c9b938e2012-10-10 12:24:07517 // Helper for SetTimer().
518 void TimerExpired(int32 result);
519
[email protected]9264e1502012-09-18 19:53:01520 PpbBufferAllocator allocator_;
[email protected]d341e332012-08-28 18:57:40521 pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
522 cdm::ContentDecryptionModule* cdm_;
523 std::string key_system_;
[email protected]e5aeef02012-08-17 00:18:43524};
525
[email protected]9264e1502012-09-18 19:53:01526PpbBufferAllocator::PpbBufferAllocator(pp::Instance* instance)
527 : instance_(instance) {
528}
529
530PpbBufferAllocator::~PpbBufferAllocator() {
531}
532
533cdm::Buffer* PpbBufferAllocator::Allocate(int32_t size) {
534 PP_DCHECK(size > 0);
[email protected]bf5f1682012-10-23 04:31:43535 PP_DCHECK(IsMainThread());
[email protected]9264e1502012-09-18 19:53:01536
537 pp::Buffer_Dev buffer(instance_, size);
538 if (buffer.is_null())
539 return NULL;
540
541 return new PpbBuffer(buffer);
542}
543
[email protected]d341e332012-08-28 18:57:40544CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
[email protected]e5aeef02012-08-17 00:18:43545 : pp::Instance(instance),
[email protected]d341e332012-08-28 18:57:40546 pp::ContentDecryptor_Private(this),
[email protected]9264e1502012-09-18 19:53:01547 allocator_(this),
[email protected]d341e332012-08-28 18:57:40548 cdm_(NULL) {
[email protected]e5aeef02012-08-17 00:18:43549 callback_factory_.Initialize(this);
550}
551
[email protected]d341e332012-08-28 18:57:40552CdmWrapper::~CdmWrapper() {
553 if (cdm_)
554 DestroyCdmInstance(cdm_);
555}
556
[email protected]ea4ff802012-09-13 01:36:44557void CdmWrapper::GenerateKeyRequest(const std::string& key_system,
[email protected]e5aeef02012-08-17 00:18:43558 pp::VarArrayBuffer init_data) {
[email protected]d341e332012-08-28 18:57:40559 PP_DCHECK(!key_system.empty());
[email protected]e5aeef02012-08-17 00:18:43560
[email protected]d341e332012-08-28 18:57:40561 if (!cdm_) {
[email protected]f5c9b938e2012-10-10 12:24:07562 cdm_ = CreateCdmInstance(&allocator_, this);
[email protected]d341e332012-08-28 18:57:40563 if (!cdm_)
[email protected]ea4ff802012-09-13 01:36:44564 return;
[email protected]d341e332012-08-28 18:57:40565 }
[email protected]e5aeef02012-08-17 00:18:43566
[email protected]9264e1502012-09-18 19:53:01567 LinkedKeyMessage key_request(new KeyMessageImpl());
[email protected]d341e332012-08-28 18:57:40568 cdm::Status status = cdm_->GenerateKeyRequest(
569 reinterpret_cast<const uint8_t*>(init_data.Map()),
570 init_data.ByteLength(),
[email protected]9264e1502012-09-18 19:53:01571 key_request.get());
[email protected]0b959582012-10-01 23:13:27572 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]d341e332012-08-28 18:57:40573 if (status != cdm::kSuccess ||
[email protected]9264e1502012-09-18 19:53:01574 !key_request->message() ||
575 key_request->message()->size() == 0) {
[email protected]d341e332012-08-28 18:57:40576 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
577 std::string()));
[email protected]ea4ff802012-09-13 01:36:44578 return;
[email protected]d341e332012-08-28 18:57:40579 }
580
581 // TODO(xhwang): Remove unnecessary CallOnMain calls here and below once we
582 // only support out-of-process.
583 // If running out-of-process, PPB calls will always behave asynchronously
584 // since IPC is involved. In that case, if we are already on main thread,
585 // we don't need to use CallOnMain to help us call PPB call on main thread,
586 // or to help call PPB asynchronously.
587 key_system_ = key_system;
588 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyMessage,
589 key_request));
[email protected]e5aeef02012-08-17 00:18:43590}
591
[email protected]ea4ff802012-09-13 01:36:44592void CdmWrapper::AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22593 pp::VarArrayBuffer key,
594 pp::VarArrayBuffer init_data) {
[email protected]d341e332012-08-28 18:57:40595 const uint8_t* key_ptr = reinterpret_cast<const uint8_t*>(key.Map());
596 int key_size = key.ByteLength();
597 const uint8_t* init_data_ptr =
598 reinterpret_cast<const uint8_t*>(init_data.Map());
599 int init_data_size = init_data.ByteLength();
[email protected]e5aeef02012-08-17 00:18:43600
[email protected]d341e332012-08-28 18:57:40601 if (!key_ptr || key_size <= 0 || !init_data_ptr || init_data_size <= 0)
[email protected]ea4ff802012-09-13 01:36:44602 return;
[email protected]e5aeef02012-08-17 00:18:43603
[email protected]d341e332012-08-28 18:57:40604 PP_DCHECK(cdm_);
605 cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
606 key_ptr, key_size,
607 init_data_ptr, init_data_size);
[email protected]0b959582012-10-01 23:13:27608 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]d341e332012-08-28 18:57:40609 if (status != cdm::kSuccess) {
610 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
611 session_id));
[email protected]ea4ff802012-09-13 01:36:44612 return;
[email protected]d341e332012-08-28 18:57:40613 }
614
615 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyAdded, session_id));
[email protected]e5aeef02012-08-17 00:18:43616}
617
[email protected]ea4ff802012-09-13 01:36:44618void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
[email protected]d341e332012-08-28 18:57:40619 PP_DCHECK(cdm_);
[email protected]d341e332012-08-28 18:57:40620 cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
621 session_id.size());
[email protected]0b959582012-10-01 23:13:27622 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]d341e332012-08-28 18:57:40623 if (status != cdm::kSuccess) {
624 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
625 session_id));
[email protected]d341e332012-08-28 18:57:40626 }
[email protected]e5aeef02012-08-17 00:18:43627}
628
[email protected]ea4ff802012-09-13 01:36:44629void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
[email protected]98ad9782012-08-22 04:06:22630 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]e5aeef02012-08-17 00:18:43631 PP_DCHECK(!encrypted_buffer.is_null());
[email protected]d341e332012-08-28 18:57:40632 PP_DCHECK(cdm_);
[email protected]e5aeef02012-08-17 00:18:43633
[email protected]d341e332012-08-28 18:57:40634 cdm::InputBuffer input_buffer;
[email protected]d341e332012-08-28 18:57:40635 std::vector<cdm::SubsampleEntry> subsamples;
[email protected]181d9c12012-10-03 22:53:48636 ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
637 &input_buffer);
[email protected]98ad9782012-08-22 04:06:22638
[email protected]7ed56ed2012-10-02 02:43:27639 LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
640 cdm::Status status = cdm_->Decrypt(input_buffer, decrypted_block.get());
[email protected]d341e332012-08-28 18:57:40641
642 CallOnMain(callback_factory_.NewCallback(
643 &CdmWrapper::DeliverBlock,
644 status,
[email protected]7ed56ed2012-10-02 02:43:27645 decrypted_block,
[email protected]d341e332012-08-28 18:57:40646 encrypted_block_info.tracking_info));
[email protected]e5aeef02012-08-17 00:18:43647}
648
[email protected]c999b3b72012-10-19 22:33:46649void CdmWrapper::InitializeAudioDecoder(
650 const PP_AudioDecoderConfig& decoder_config,
651 pp::Buffer_Dev extra_data_buffer) {
652 PP_DCHECK(cdm_);
653 cdm::AudioDecoderConfig cdm_decoder_config;
654 cdm_decoder_config.codec = PpAudioCodecToCdmAudioCodec(decoder_config.codec);
655 cdm_decoder_config.channel_count = decoder_config.channel_count;
656 cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
657 cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
658 cdm_decoder_config.extra_data =
659 static_cast<uint8_t*>(extra_data_buffer.data());
660 cdm_decoder_config.extra_data_size =
661 static_cast<int32_t>(extra_data_buffer.size());
662 cdm::Status status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
663
664 CallOnMain(callback_factory_.NewCallback(
665 &CdmWrapper::DecoderInitializeDone,
666 PP_DECRYPTORSTREAMTYPE_AUDIO,
667 decoder_config.request_id,
668 status == cdm::kSuccess));
669}
670
[email protected]e9d3a1022012-10-11 23:43:55671void CdmWrapper::InitializeVideoDecoder(
672 const PP_VideoDecoderConfig& decoder_config,
673 pp::Buffer_Dev extra_data_buffer) {
674 PP_DCHECK(cdm_);
675 cdm::VideoDecoderConfig cdm_decoder_config;
676 cdm_decoder_config.codec = PpVideoCodecToCdmVideoCodec(decoder_config.codec);
677 cdm_decoder_config.profile =
678 PpVCProfileToCdmVCProfile(decoder_config.profile);
679 cdm_decoder_config.format =
680 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
681 cdm_decoder_config.coded_size.width = decoder_config.width;
682 cdm_decoder_config.coded_size.height = decoder_config.height;
683 cdm_decoder_config.extra_data =
684 static_cast<uint8_t*>(extra_data_buffer.data());
685 cdm_decoder_config.extra_data_size =
686 static_cast<int32_t>(extra_data_buffer.size());
687 cdm::Status status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
688
689 CallOnMain(callback_factory_.NewCallback(
[email protected]c999b3b72012-10-19 22:33:46690 &CdmWrapper::DecoderInitializeDone,
691 PP_DECRYPTORSTREAMTYPE_VIDEO,
692 decoder_config.request_id,
693 status == cdm::kSuccess));
[email protected]e9d3a1022012-10-11 23:43:55694}
695
[email protected]23de87452012-10-12 07:03:09696void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
697 uint32_t request_id) {
[email protected]bf5f1682012-10-23 04:31:43698 cdm_->DeinitializeDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
[email protected]23de87452012-10-12 07:03:09699 CallOnMain(callback_factory_.NewCallback(
700 &CdmWrapper::DecoderDeinitializeDone,
701 decoder_type,
702 request_id));
703}
704
705void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
706 uint32_t request_id) {
[email protected]bf5f1682012-10-23 04:31:43707 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
[email protected]23de87452012-10-12 07:03:09708 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone,
709 decoder_type,
710 request_id));
711}
712
[email protected]467434d2012-10-12 10:48:53713void CdmWrapper::DecryptAndDecode(
714 PP_DecryptorStreamType decoder_type,
715 pp::Buffer_Dev encrypted_buffer,
716 const PP_EncryptedBlockInfo& encrypted_block_info) {
717 // TODO(tomfinegan): Remove this check when audio decoding is added.
718 PP_DCHECK(decoder_type == PP_DECRYPTORSTREAMTYPE_VIDEO);
[email protected]181d9c12012-10-03 22:53:48719 PP_DCHECK(cdm_);
720
721 cdm::InputBuffer input_buffer;
722 std::vector<cdm::SubsampleEntry> subsamples;
[email protected]741c28f2012-10-18 07:02:25723 if (!encrypted_buffer.is_null()) {
724 ConfigureInputBuffer(encrypted_buffer,
725 encrypted_block_info,
726 &subsamples,
727 &input_buffer);
728 }
[email protected]181d9c12012-10-03 22:53:48729
730 LinkedVideoFrame video_frame(new VideoFrameImpl());
[email protected]d40797c2012-10-04 04:36:14731 cdm::Status status = cdm_->DecryptAndDecodeFrame(input_buffer,
[email protected]181d9c12012-10-03 22:53:48732 video_frame.get());
733 CallOnMain(callback_factory_.NewCallback(
734 &CdmWrapper::DeliverFrame,
735 status,
736 video_frame,
[email protected]467434d2012-10-12 10:48:53737 encrypted_block_info.tracking_info));
[email protected]d341e332012-08-28 18:57:40738}
739
[email protected]f5c9b938e2012-10-10 12:24:07740void CdmWrapper::SetTimer(int64 delay_ms) {
741 // NOTE: doesn't really need to run on the main thread; could just as well run
742 // on a helper thread if |cdm_| were thread-friendly and care was taken. We
743 // only use CallOnMainThread() here to get delayed-execution behavior.
744 pp::Module::Get()->core()->CallOnMainThread(
745 delay_ms,
746 callback_factory_.NewCallback(&CdmWrapper::TimerExpired),
747 PP_OK);
748}
749
750void CdmWrapper::TimerExpired(int32 result) {
751 PP_DCHECK(result == PP_OK);
752 bool populated;
[email protected]d4a260b52012-10-11 22:10:04753 LinkedKeyMessage key_message(new KeyMessageImpl());
754 cdm_->TimerExpired(key_message.get(), &populated);
[email protected]f5c9b938e2012-10-10 12:24:07755 if (!populated)
756 return;
[email protected]d4a260b52012-10-11 22:10:04757 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyMessage,
758 key_message));
[email protected]f5c9b938e2012-10-10 12:24:07759}
760
761double CdmWrapper::GetCurrentWallTimeMs() {
762 // TODO(fischman): figure out whether this requires an IPC round-trip per
763 // call, and if that's a problem for the frequency of calls. If it is,
764 // optimize by proactively sending wall-time across the IPC boundary on some
765 // existing calls, or add a periodic task to update a plugin-side clock.
766 return pp::Module::Get()->core()->GetTime();
767}
768
[email protected]d341e332012-08-28 18:57:40769void CdmWrapper::KeyAdded(int32_t result, const std::string& session_id) {
[email protected]f5c9b938e2012-10-10 12:24:07770 PP_DCHECK(result == PP_OK);
[email protected]d341e332012-08-28 18:57:40771 pp::ContentDecryptor_Private::KeyAdded(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43772}
773
[email protected]d341e332012-08-28 18:57:40774void CdmWrapper::KeyMessage(int32_t result,
[email protected]9264e1502012-09-18 19:53:01775 const LinkedKeyMessage& key_message) {
[email protected]f5c9b938e2012-10-10 12:24:07776 PP_DCHECK(result == PP_OK);
[email protected]9264e1502012-09-18 19:53:01777 pp::Buffer_Dev message_buffer =
778 static_cast<const PpbBuffer*>(key_message->message())->buffer_dev();
[email protected]d341e332012-08-28 18:57:40779 pp::ContentDecryptor_Private::KeyMessage(
780 key_system_,
[email protected]9264e1502012-09-18 19:53:01781 key_message->session_id_string(),
[email protected]d341e332012-08-28 18:57:40782 message_buffer,
[email protected]9264e1502012-09-18 19:53:01783 key_message->default_url_string());
[email protected]e5aeef02012-08-17 00:18:43784}
785
[email protected]d341e332012-08-28 18:57:40786// TODO(xhwang): Support MediaKeyError (see spec: http://goo.gl/rbdnR) in CDM
787// interface and in this function.
788void CdmWrapper::KeyError(int32_t result, const std::string& session_id) {
[email protected]f5c9b938e2012-10-10 12:24:07789 PP_DCHECK(result == PP_OK);
[email protected]d341e332012-08-28 18:57:40790 pp::ContentDecryptor_Private::KeyError(key_system_,
791 session_id,
792 kUnknownError,
793 0);
[email protected]e5aeef02012-08-17 00:18:43794}
795
[email protected]d341e332012-08-28 18:57:40796void CdmWrapper::DeliverBlock(int32_t result,
797 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:27798 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:40799 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:07800 PP_DCHECK(result == PP_OK);
[email protected]d341e332012-08-28 18:57:40801 PP_DecryptedBlockInfo decrypted_block_info;
[email protected]181d9c12012-10-03 22:53:48802 decrypted_block_info.tracking_info = tracking_info;
[email protected]7ed56ed2012-10-02 02:43:27803 decrypted_block_info.tracking_info.timestamp = decrypted_block->timestamp();
[email protected]8f5a9a52012-10-23 20:49:20804 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
[email protected]d341e332012-08-28 18:57:40805
[email protected]8f5a9a52012-10-23 20:49:20806 pp::Buffer_Dev buffer;
807
808 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
809 PP_DCHECK(decrypted_block.get() && decrypted_block->buffer());
810 if (!decrypted_block.get() || !decrypted_block->buffer()) {
[email protected]d341e332012-08-28 18:57:40811 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
[email protected]8f5a9a52012-10-23 20:49:20812 } else {
813 buffer = static_cast<PpbBuffer*>(decrypted_block->buffer())->buffer_dev();
814 }
[email protected]d341e332012-08-28 18:57:40815 }
816
[email protected]4bc37112012-09-21 19:49:25817 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
[email protected]e5aeef02012-08-17 00:18:43818}
819
[email protected]c999b3b72012-10-19 22:33:46820void CdmWrapper::DecoderInitializeDone(int32_t result,
821 PP_DecryptorStreamType decoder_type,
822 uint32_t request_id,
823 bool success) {
824 PP_DCHECK(result == PP_OK);
825 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
826 request_id,
827 success);
[email protected]e9d3a1022012-10-11 23:43:55828}
829
[email protected]23de87452012-10-12 07:03:09830void CdmWrapper::DecoderDeinitializeDone(int32_t result,
831 PP_DecryptorStreamType decoder_type,
832 uint32_t request_id) {
833 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
834 request_id);
835}
836
837void CdmWrapper::DecoderResetDone(int32_t result,
838 PP_DecryptorStreamType decoder_type,
839 uint32_t request_id) {
840 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
841}
842
[email protected]181d9c12012-10-03 22:53:48843void CdmWrapper::DeliverFrame(
844 int32_t result,
845 const cdm::Status& status,
846 const LinkedVideoFrame& video_frame,
847 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:07848 PP_DCHECK(result == PP_OK);
[email protected]181d9c12012-10-03 22:53:48849 PP_DecryptedFrameInfo decrypted_frame_info;
850 decrypted_frame_info.tracking_info = tracking_info;
[email protected]8f5a9a52012-10-23 20:49:20851 decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
[email protected]181d9c12012-10-03 22:53:48852
[email protected]8f5a9a52012-10-23 20:49:20853 pp::Buffer_Dev buffer;
[email protected]741c28f2012-10-18 07:02:25854
[email protected]8f5a9a52012-10-23 20:49:20855 if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
856 PP_DCHECK(video_frame.get() && video_frame->frame_buffer());
857 PP_DCHECK(video_frame->format() == cdm::kI420 ||
858 video_frame->format() == cdm::kYv12);
[email protected]741c28f2012-10-18 07:02:25859
[email protected]8f5a9a52012-10-23 20:49:20860 decrypted_frame_info.format =
861 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->format());
[email protected]741c28f2012-10-18 07:02:25862
[email protected]8f5a9a52012-10-23 20:49:20863 if (!video_frame.get() ||
864 !video_frame->frame_buffer() ||
865 (decrypted_frame_info.format != PP_DECRYPTEDFRAMEFORMAT_YV12 &&
866 decrypted_frame_info.format != PP_DECRYPTEDFRAMEFORMAT_I420)) {
867 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
868 } else {
869 buffer = static_cast<PpbBuffer*>(
870 video_frame->frame_buffer())->buffer_dev();
[email protected]d0ec47492012-10-13 05:01:46871 decrypted_frame_info.width = video_frame->size().width;
872 decrypted_frame_info.height = video_frame->size().height;
[email protected]181d9c12012-10-03 22:53:48873 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]8f5a9a52012-10-23 20:49:20874 video_frame->plane_offset(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:48875 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]8f5a9a52012-10-23 20:49:20876 video_frame->plane_offset(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:48877 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]8f5a9a52012-10-23 20:49:20878 video_frame->plane_offset(cdm::VideoFrame::kVPlane);
[email protected]181d9c12012-10-03 22:53:48879 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]8f5a9a52012-10-23 20:49:20880 video_frame->stride(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:48881 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]8f5a9a52012-10-23 20:49:20882 video_frame->stride(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:48883 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]8f5a9a52012-10-23 20:49:20884 video_frame->stride(cdm::VideoFrame::kVPlane);
885 }
[email protected]181d9c12012-10-03 22:53:48886 }
887
[email protected]181d9c12012-10-03 22:53:48888 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
889}
890
891
[email protected]e5aeef02012-08-17 00:18:43892// This object is the global object representing this plugin library as long
893// as it is loaded.
[email protected]9264e1502012-09-18 19:53:01894class CdmWrapperModule : public pp::Module {
[email protected]e5aeef02012-08-17 00:18:43895 public:
[email protected]9264e1502012-09-18 19:53:01896 CdmWrapperModule() : pp::Module() {}
897 virtual ~CdmWrapperModule() {}
[email protected]e5aeef02012-08-17 00:18:43898
899 virtual pp::Instance* CreateInstance(PP_Instance instance) {
[email protected]d341e332012-08-28 18:57:40900 return new CdmWrapper(instance, this);
[email protected]e5aeef02012-08-17 00:18:43901 }
902};
903
[email protected]d341e332012-08-28 18:57:40904} // namespace webkit_media
905
[email protected]e5aeef02012-08-17 00:18:43906namespace pp {
907
908// Factory function for your specialization of the Module object.
909Module* CreateModule() {
[email protected]9264e1502012-09-18 19:53:01910 return new webkit_media::CdmWrapperModule();
[email protected]e5aeef02012-08-17 00:18:43911}
912
913} // namespace pp