Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc

Issue 22362007: Relocate last remnants of webkit/renderer/media code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make chromeos crypto dep explicit. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include <cstring>
6 #include <map>
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/c/pp_stdint.h"
15 #include "ppapi/c/private/pp_content_decryptor.h"
16 #include "ppapi/cpp/completion_callback.h"
17 #include "ppapi/cpp/core.h"
18 #include "ppapi/cpp/dev/buffer_dev.h"
19 #include "ppapi/cpp/instance.h"
20 #include "ppapi/cpp/logging.h"
21 #include "ppapi/cpp/module.h"
22 #include "ppapi/cpp/pass_ref.h"
23 #include "ppapi/cpp/private/content_decryptor_private.h"
24 #include "ppapi/cpp/resource.h"
25 #include "ppapi/cpp/var.h"
26 #include "ppapi/cpp/var_array_buffer.h"
27 #include "ppapi/utility/completion_callback_factory.h"
28 #include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
29 #include "webkit/renderer/media/crypto/ppapi/linked_ptr.h"
30
31 #if defined(CHECK_DOCUMENT_URL)
32 #include "ppapi/cpp/dev/url_util_dev.h"
33 #include "ppapi/cpp/instance_handle.h"
34 #endif // defined(CHECK_DOCUMENT_URL)
35
36 namespace {
37
38 bool IsMainThread() {
39 return pp::Module::Get()->core()->IsMainThread();
40 }
41
42 // Posts a task to run |cb| on the main thread. The task is posted even if the
43 // current thread is the main thread.
44 void PostOnMain(pp::CompletionCallback cb) {
45 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
46 }
47
48 // Ensures |cb| is called on the main thread, either because the current thread
49 // is the main thread or by posting it to the main thread.
50 void CallOnMain(pp::CompletionCallback cb) {
51 // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
52 // off the main thread yet. Remove this once the change lands.
53 if (IsMainThread())
54 cb.Run(PP_OK);
55 else
56 PostOnMain(cb);
57 }
58
59 // Configures a cdm::InputBuffer. |subsamples| must exist as long as
60 // |input_buffer| is in use.
61 void ConfigureInputBuffer(
62 const pp::Buffer_Dev& encrypted_buffer,
63 const PP_EncryptedBlockInfo& encrypted_block_info,
64 std::vector<cdm::SubsampleEntry>* subsamples,
65 cdm::InputBuffer* input_buffer) {
66 PP_DCHECK(subsamples);
67 PP_DCHECK(!encrypted_buffer.is_null());
68
69 input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
70 input_buffer->data_size = encrypted_block_info.data_size;
71 PP_DCHECK(encrypted_buffer.size() >=
72 static_cast<uint32_t>(input_buffer->data_size));
73 input_buffer->data_offset = encrypted_block_info.data_offset;
74
75 PP_DCHECK(encrypted_block_info.key_id_size <=
76 arraysize(encrypted_block_info.key_id));
77 input_buffer->key_id_size = encrypted_block_info.key_id_size;
78 input_buffer->key_id = input_buffer->key_id_size > 0 ?
79 encrypted_block_info.key_id : NULL;
80
81 PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
82 input_buffer->iv_size = encrypted_block_info.iv_size;
83 input_buffer->iv = encrypted_block_info.iv_size > 0 ?
84 encrypted_block_info.iv : NULL;
85
86 input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
87 if (encrypted_block_info.num_subsamples > 0) {
88 subsamples->reserve(encrypted_block_info.num_subsamples);
89
90 for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
91 subsamples->push_back(cdm::SubsampleEntry(
92 encrypted_block_info.subsamples[i].clear_bytes,
93 encrypted_block_info.subsamples[i].cipher_bytes));
94 }
95
96 input_buffer->subsamples = &(*subsamples)[0];
97 }
98
99 input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
100 }
101
102 PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
103 switch (status) {
104 case cdm::kSuccess:
105 return PP_DECRYPTRESULT_SUCCESS;
106 case cdm::kNoKey:
107 return PP_DECRYPTRESULT_DECRYPT_NOKEY;
108 case cdm::kNeedMoreData:
109 return PP_DECRYPTRESULT_NEEDMOREDATA;
110 case cdm::kDecryptError:
111 return PP_DECRYPTRESULT_DECRYPT_ERROR;
112 case cdm::kDecodeError:
113 return PP_DECRYPTRESULT_DECODE_ERROR;
114 default:
115 PP_NOTREACHED();
116 return PP_DECRYPTRESULT_DECODE_ERROR;
117 }
118 }
119
120 PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
121 cdm::VideoFormat format) {
122 switch (format) {
123 case cdm::kYv12:
124 return PP_DECRYPTEDFRAMEFORMAT_YV12;
125 case cdm::kI420:
126 return PP_DECRYPTEDFRAMEFORMAT_I420;
127 default:
128 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
129 }
130 }
131
132 cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
133 PP_AudioCodec codec) {
134 switch (codec) {
135 case PP_AUDIOCODEC_VORBIS:
136 return cdm::AudioDecoderConfig::kCodecVorbis;
137 case PP_AUDIOCODEC_AAC:
138 return cdm::AudioDecoderConfig::kCodecAac;
139 default:
140 return cdm::AudioDecoderConfig::kUnknownAudioCodec;
141 }
142 }
143
144 cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
145 PP_VideoCodec codec) {
146 switch (codec) {
147 case PP_VIDEOCODEC_VP8:
148 return cdm::VideoDecoderConfig::kCodecVp8;
149 case PP_VIDEOCODEC_H264:
150 return cdm::VideoDecoderConfig::kCodecH264;
151 default:
152 return cdm::VideoDecoderConfig::kUnknownVideoCodec;
153 }
154 }
155
156 cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
157 PP_VideoCodecProfile profile) {
158 switch (profile) {
159 case PP_VIDEOCODECPROFILE_VP8_MAIN:
160 return cdm::VideoDecoderConfig::kVp8ProfileMain;
161 case PP_VIDEOCODECPROFILE_H264_BASELINE:
162 return cdm::VideoDecoderConfig::kH264ProfileBaseline;
163 case PP_VIDEOCODECPROFILE_H264_MAIN:
164 return cdm::VideoDecoderConfig::kH264ProfileMain;
165 case PP_VIDEOCODECPROFILE_H264_EXTENDED:
166 return cdm::VideoDecoderConfig::kH264ProfileExtended;
167 case PP_VIDEOCODECPROFILE_H264_HIGH:
168 return cdm::VideoDecoderConfig::kH264ProfileHigh;
169 case PP_VIDEOCODECPROFILE_H264_HIGH_10:
170 return cdm::VideoDecoderConfig::kH264ProfileHigh10;
171 case PP_VIDEOCODECPROFILE_H264_HIGH_422:
172 return cdm::VideoDecoderConfig::kH264ProfileHigh422;
173 case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
174 return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
175 default:
176 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
177 }
178 }
179
180 cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
181 PP_DecryptedFrameFormat format) {
182 switch (format) {
183 case PP_DECRYPTEDFRAMEFORMAT_YV12:
184 return cdm::kYv12;
185 case PP_DECRYPTEDFRAMEFORMAT_I420:
186 return cdm::kI420;
187 default:
188 return cdm::kUnknownVideoFormat;
189 }
190 }
191
192 cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
193 PP_DecryptorStreamType stream_type) {
194 switch (stream_type) {
195 case PP_DECRYPTORSTREAMTYPE_AUDIO:
196 return cdm::kStreamTypeAudio;
197 case PP_DECRYPTORSTREAMTYPE_VIDEO:
198 return cdm::kStreamTypeVideo;
199 }
200
201 PP_NOTREACHED();
202 return cdm::kStreamTypeVideo;
203 }
204
205 } // namespace
206
207 namespace webkit_media {
208
209 // cdm::Buffer implementation that provides access to memory owned by a
210 // pp::Buffer_Dev.
211 // This class holds a reference to the Buffer_Dev throughout its lifetime.
212 // TODO(xhwang): Find a better name. It's confusing to have PpbBuffer,
213 // pp::Buffer_Dev and PPB_Buffer_Dev.
214 class PpbBuffer : public cdm::Buffer {
215 public:
216 static PpbBuffer* Create(const pp::Buffer_Dev& buffer, uint32_t buffer_id) {
217 PP_DCHECK(buffer.data());
218 PP_DCHECK(buffer.size());
219 PP_DCHECK(buffer_id);
220 return new PpbBuffer(buffer, buffer_id);
221 }
222
223 // cdm::Buffer implementation.
224 virtual void Destroy() OVERRIDE { delete this; }
225
226 virtual int32_t Capacity() const OVERRIDE { return buffer_.size(); }
227
228 virtual uint8_t* Data() OVERRIDE {
229 return static_cast<uint8_t*>(buffer_.data());
230 }
231
232 virtual void SetSize(int32_t size) OVERRIDE {
233 PP_DCHECK(size >= 0);
234 PP_DCHECK(size < Capacity());
235 if (size < 0 || size > Capacity()) {
236 size_ = 0;
237 return;
238 }
239
240 size_ = size;
241 }
242
243 virtual int32_t Size() const OVERRIDE { return size_; }
244
245 pp::Buffer_Dev buffer_dev() const { return buffer_; }
246
247 uint32_t buffer_id() const { return buffer_id_; }
248
249 private:
250 PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id)
251 : buffer_(buffer),
252 buffer_id_(buffer_id),
253 size_(0) {}
254 virtual ~PpbBuffer() {}
255
256 pp::Buffer_Dev buffer_;
257 uint32_t buffer_id_;
258 int32_t size_;
259
260 DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
261 };
262
263 class PpbBufferAllocator {
264 public:
265 explicit PpbBufferAllocator(pp::Instance* instance)
266 : instance_(instance),
267 next_buffer_id_(1) {}
268 ~PpbBufferAllocator() {}
269
270 cdm::Buffer* Allocate(int32_t capacity);
271
272 // Releases the buffer with |buffer_id|. A buffer can be recycled after
273 // it is released.
274 void Release(uint32_t buffer_id);
275
276 private:
277 typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap;
278 typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> >
279 FreeBufferMap;
280
281 // Always pad new allocated buffer so that we don't need to reallocate
282 // buffers frequently if requested sizes fluctuate slightly.
283 static const int kBufferPadding = 512;
284
285 // Maximum number of free buffers we can keep when allocating new buffers.
286 static const int kFreeLimit = 3;
287
288 pp::Buffer_Dev AllocateNewBuffer(int capacity);
289
290 pp::Instance* const instance_;
291 uint32_t next_buffer_id_;
292 AllocatedBufferMap allocated_buffers_;
293 FreeBufferMap free_buffers_;
294
295 DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
296 };
297
298 cdm::Buffer* PpbBufferAllocator::Allocate(int32_t capacity) {
299 PP_DCHECK(IsMainThread());
300
301 if (capacity <= 0)
302 return NULL;
303
304 pp::Buffer_Dev buffer;
305 uint32_t buffer_id = 0;
306
307 // Reuse a buffer in the free list if there is one that fits |capacity|.
308 // Otherwise, create a new one.
309 FreeBufferMap::iterator found = free_buffers_.lower_bound(capacity);
310 if (found == free_buffers_.end()) {
311 // TODO(xhwang): Report statistics about how many new buffers are allocated.
312 buffer = AllocateNewBuffer(capacity);
313 if (buffer.is_null())
314 return NULL;
315 buffer_id = next_buffer_id_++;
316 } else {
317 buffer = found->second.second;
318 buffer_id = found->second.first;
319 free_buffers_.erase(found);
320 }
321
322 allocated_buffers_.insert(std::make_pair(buffer_id, buffer));
323
324 return PpbBuffer::Create(buffer, buffer_id);
325 }
326
327 void PpbBufferAllocator::Release(uint32_t buffer_id) {
328 if (!buffer_id)
329 return;
330
331 AllocatedBufferMap::iterator found = allocated_buffers_.find(buffer_id);
332 if (found == allocated_buffers_.end())
333 return;
334
335 pp::Buffer_Dev& buffer = found->second;
336 free_buffers_.insert(
337 std::make_pair(buffer.size(), std::make_pair(buffer_id, buffer)));
338
339 allocated_buffers_.erase(found);
340 }
341
342 pp::Buffer_Dev PpbBufferAllocator::AllocateNewBuffer(int32_t capacity) {
343 // Destroy the smallest buffer before allocating a new bigger buffer if the
344 // number of free buffers exceeds a limit. This mechanism helps avoid ending
345 // up with too many small buffers, which could happen if the size to be
346 // allocated keeps increasing.
347 if (free_buffers_.size() >= static_cast<uint32_t>(kFreeLimit))
348 free_buffers_.erase(free_buffers_.begin());
349
350 // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
351 // That's why we try to avoid AllocateNewBuffer() as much as we can.
352 return pp::Buffer_Dev(instance_, capacity + kBufferPadding);
353 }
354
355 class DecryptedBlockImpl : public cdm::DecryptedBlock {
356 public:
357 DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
358 virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); }
359
360 virtual void SetDecryptedBuffer(cdm::Buffer* buffer) OVERRIDE {
361 buffer_ = static_cast<PpbBuffer*>(buffer);
362 }
363 virtual cdm::Buffer* DecryptedBuffer() OVERRIDE { return buffer_; }
364
365 virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
366 timestamp_ = timestamp;
367 }
368 virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
369
370 private:
371 PpbBuffer* buffer_;
372 int64_t timestamp_;
373
374 DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
375 };
376
377 class VideoFrameImpl : public cdm::VideoFrame {
378 public:
379 VideoFrameImpl();
380 virtual ~VideoFrameImpl();
381
382 virtual void SetFormat(cdm::VideoFormat format) OVERRIDE {
383 format_ = format;
384 }
385 virtual cdm::VideoFormat Format() const OVERRIDE { return format_; }
386
387 virtual void SetSize(cdm::Size size) OVERRIDE { size_ = size; }
388 virtual cdm::Size Size() const OVERRIDE { return size_; }
389
390 virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) OVERRIDE {
391 frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
392 }
393 virtual cdm::Buffer* FrameBuffer() OVERRIDE { return frame_buffer_; }
394
395 virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
396 int32_t offset) OVERRIDE {
397 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
398 PP_DCHECK(offset >= 0);
399 plane_offsets_[plane] = offset;
400 }
401 virtual int32_t PlaneOffset(VideoPlane plane) OVERRIDE {
402 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
403 return plane_offsets_[plane];
404 }
405
406 virtual void SetStride(VideoPlane plane, int32_t stride) OVERRIDE {
407 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
408 strides_[plane] = stride;
409 }
410 virtual int32_t Stride(VideoPlane plane) OVERRIDE {
411 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
412 return strides_[plane];
413 }
414
415 virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
416 timestamp_ = timestamp;
417 }
418 virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
419
420 private:
421 // The video buffer format.
422 cdm::VideoFormat format_;
423
424 // Width and height of the video frame.
425 cdm::Size size_;
426
427 // The video frame buffer.
428 PpbBuffer* frame_buffer_;
429
430 // Array of data pointers to each plane in the video frame buffer.
431 int32_t plane_offsets_[kMaxPlanes];
432
433 // Array of strides for each plane, typically greater or equal to the width
434 // of the surface divided by the horizontal sampling period. Note that
435 // strides can be negative.
436 int32_t strides_[kMaxPlanes];
437
438 // Presentation timestamp in microseconds.
439 int64_t timestamp_;
440
441 DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
442 };
443
444 VideoFrameImpl::VideoFrameImpl()
445 : format_(cdm::kUnknownVideoFormat),
446 frame_buffer_(NULL),
447 timestamp_(0) {
448 for (int32_t i = 0; i < kMaxPlanes; ++i) {
449 plane_offsets_[i] = 0;
450 strides_[i] = 0;
451 }
452 }
453
454 VideoFrameImpl::~VideoFrameImpl() {
455 if (frame_buffer_)
456 frame_buffer_->Destroy();
457 }
458
459 class AudioFramesImpl : public cdm::AudioFrames {
460 public:
461 AudioFramesImpl() : buffer_(NULL) {}
462 virtual ~AudioFramesImpl() {
463 if (buffer_)
464 buffer_->Destroy();
465 }
466
467 // AudioFrames implementation.
468 virtual void SetFrameBuffer(cdm::Buffer* buffer) OVERRIDE {
469 buffer_ = static_cast<PpbBuffer*>(buffer);
470 }
471 virtual cdm::Buffer* FrameBuffer() OVERRIDE {
472 return buffer_;
473 }
474
475 private:
476 PpbBuffer* buffer_;
477
478 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
479 };
480
481 // GetCdmHostFunc implementation.
482 void* GetCdmHost(int host_interface_version, void* user_data);
483
484 // A wrapper class for abstracting away PPAPI interaction and threading for a
485 // Content Decryption Module (CDM).
486 class CdmWrapper : public pp::Instance,
487 public pp::ContentDecryptor_Private,
488 public cdm::Host {
489 public:
490 CdmWrapper(PP_Instance instance, pp::Module* module);
491 virtual ~CdmWrapper();
492
493 // pp::Instance implementation.
494 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
495 return true;
496 }
497
498 // PPP_ContentDecryptor_Private implementation.
499 // Note: Results of calls to these methods must be reported through the
500 // PPB_ContentDecryptor_Private interface.
501 virtual void GenerateKeyRequest(const std::string& key_system,
502 const std::string& type,
503 pp::VarArrayBuffer init_data) OVERRIDE;
504 virtual void AddKey(const std::string& session_id,
505 pp::VarArrayBuffer key,
506 pp::VarArrayBuffer init_data) OVERRIDE;
507 virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
508 virtual void Decrypt(
509 pp::Buffer_Dev encrypted_buffer,
510 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
511 virtual void InitializeAudioDecoder(
512 const PP_AudioDecoderConfig& decoder_config,
513 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
514 virtual void InitializeVideoDecoder(
515 const PP_VideoDecoderConfig& decoder_config,
516 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
517 virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
518 uint32_t request_id) OVERRIDE;
519 virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
520 uint32_t request_id) OVERRIDE;
521 virtual void DecryptAndDecode(
522 PP_DecryptorStreamType decoder_type,
523 pp::Buffer_Dev encrypted_buffer,
524 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
525
526 // cdm::Host implementation.
527 virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE;
528 virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
529 virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
530 virtual void SendKeyMessage(
531 const char* session_id, int32_t session_id_length,
532 const char* message, int32_t message_length,
533 const char* default_url, int32_t default_url_length) OVERRIDE;
534 virtual void SendKeyError(const char* session_id,
535 int32_t session_id_length,
536 cdm::MediaKeyError error_code,
537 uint32_t system_code) OVERRIDE;
538 virtual void GetPrivateData(int32_t* instance,
539 GetPrivateInterface* get_interface) OVERRIDE;
540
541 private:
542 struct SessionInfo {
543 SessionInfo(const std::string& key_system_in,
544 const std::string& session_id_in)
545 : key_system(key_system_in),
546 session_id(session_id_in) {}
547 const std::string key_system;
548 const std::string session_id;
549 };
550
551 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
552 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
553 typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;
554
555 bool CreateCdmInstance(const std::string& key_system);
556
557 void SendUnknownKeyError(const std::string& key_system,
558 const std::string& session_id);
559
560 void SendKeyAdded(const std::string& key_system,
561 const std::string& session_id);
562
563 void SendKeyErrorInternal(const std::string& key_system,
564 const std::string& session_id,
565 cdm::MediaKeyError error_code,
566 uint32_t system_code);
567
568 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
569 // <code>callback_factory_</code> to ensure that calls into
570 // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
571 void KeyAdded(int32_t result, const SessionInfo& session_info);
572 void KeyMessage(int32_t result,
573 const SessionInfo& session_info,
574 const std::vector<uint8>& message,
575 const std::string& default_url);
576 void KeyError(int32_t result,
577 const SessionInfo& session_info,
578 cdm::MediaKeyError error_code,
579 uint32_t system_code);
580 void DeliverBlock(int32_t result,
581 const cdm::Status& status,
582 const LinkedDecryptedBlock& decrypted_block,
583 const PP_DecryptTrackingInfo& tracking_info);
584 void DecoderInitializeDone(int32_t result,
585 PP_DecryptorStreamType decoder_type,
586 uint32_t request_id,
587 bool success);
588 void DecoderDeinitializeDone(int32_t result,
589 PP_DecryptorStreamType decoder_type,
590 uint32_t request_id);
591 void DecoderResetDone(int32_t result,
592 PP_DecryptorStreamType decoder_type,
593 uint32_t request_id);
594 void DeliverFrame(int32_t result,
595 const cdm::Status& status,
596 const LinkedVideoFrame& video_frame,
597 const PP_DecryptTrackingInfo& tracking_info);
598 void DeliverSamples(int32_t result,
599 const cdm::Status& status,
600 const LinkedAudioFrames& audio_frames,
601 const PP_DecryptTrackingInfo& tracking_info);
602
603 // Helper for SetTimer().
604 void TimerExpired(int32_t result, void* context);
605
606 bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
607
608 PpbBufferAllocator allocator_;
609 pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
610 cdm::ContentDecryptionModule* cdm_;
611 std::string key_system_;
612
613 DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
614 };
615
616 CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
617 : pp::Instance(instance),
618 pp::ContentDecryptor_Private(this),
619 allocator_(this),
620 cdm_(NULL) {
621 callback_factory_.Initialize(this);
622 }
623
624 CdmWrapper::~CdmWrapper() {
625 if (cdm_)
626 cdm_->Destroy();
627 }
628
629 bool CdmWrapper::CreateCdmInstance(const std::string& key_system) {
630 PP_DCHECK(!cdm_);
631 cdm_ = static_cast<cdm::ContentDecryptionModule*>(
632 ::CreateCdmInstance(cdm::kCdmInterfaceVersion,
633 key_system.data(), key_system.size(),
634 GetCdmHost, this));
635
636 return (cdm_ != NULL);
637 }
638
639 void CdmWrapper::GenerateKeyRequest(const std::string& key_system,
640 const std::string& type,
641 pp::VarArrayBuffer init_data) {
642 PP_DCHECK(!key_system.empty());
643 PP_DCHECK(key_system_.empty() || key_system_ == key_system);
644
645 #if defined(CHECK_DOCUMENT_URL)
646 PP_URLComponents_Dev url_components = {};
647 pp::Var href = pp::URLUtil_Dev::Get()->GetDocumentURL(
648 pp::InstanceHandle(pp_instance()), &url_components);
649 PP_DCHECK(href.is_string());
650 PP_DCHECK(!href.AsString().empty());
651 PP_DCHECK(url_components.host.begin);
652 PP_DCHECK(0 < url_components.host.len);
653 #endif // defined(CHECK_DOCUMENT_URL)
654
655 if (!cdm_) {
656 if (!CreateCdmInstance(key_system)) {
657 SendUnknownKeyError(key_system, std::string());
658 return;
659 }
660 }
661 PP_DCHECK(cdm_);
662
663 // Must be set here in case the CDM synchronously calls a cdm::Host method.
664 // Clear below on error.
665 // TODO(ddorwin): Set/clear key_system_ & cdm_ at same time; clear both on
666 // error below.
667 key_system_ = key_system;
668 cdm::Status status = cdm_->GenerateKeyRequest(
669 type.data(), type.size(),
670 static_cast<const uint8_t*>(init_data.Map()),
671 init_data.ByteLength());
672 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
673 if (status != cdm::kSuccess) {
674 key_system_.clear(); // See comment above.
675 return;
676 }
677
678 key_system_ = key_system;
679 }
680
681 void CdmWrapper::AddKey(const std::string& session_id,
682 pp::VarArrayBuffer key,
683 pp::VarArrayBuffer init_data) {
684 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
685 if (!cdm_) {
686 SendUnknownKeyError(key_system_, session_id);
687 return;
688 }
689
690 const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
691 int key_size = key.ByteLength();
692 const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
693 int init_data_size = init_data.ByteLength();
694 PP_DCHECK(!init_data_ptr == !init_data_size);
695
696 if (!key_ptr || key_size <= 0) {
697 SendUnknownKeyError(key_system_, session_id);
698 return;
699 }
700
701 cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
702 key_ptr, key_size,
703 init_data_ptr, init_data_size);
704 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
705 if (status != cdm::kSuccess) {
706 SendUnknownKeyError(key_system_, session_id);
707 return;
708 }
709
710 SendKeyAdded(key_system_, session_id);
711 }
712
713 void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
714 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
715 if (!cdm_) {
716 SendUnknownKeyError(key_system_, session_id);
717 return;
718 }
719
720 cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
721 session_id.size());
722 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
723 if (status != cdm::kSuccess)
724 SendUnknownKeyError(key_system_, session_id);
725 }
726
727 // Note: In the following decryption/decoding related functions, errors are NOT
728 // reported via KeyError, but are reported via corresponding PPB calls.
729
730 void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
731 const PP_EncryptedBlockInfo& encrypted_block_info) {
732 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
733 PP_DCHECK(!encrypted_buffer.is_null());
734
735 // Release a buffer that the caller indicated it is finished with.
736 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
737
738 cdm::Status status = cdm::kDecryptError;
739 LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
740
741 if (cdm_) {
742 cdm::InputBuffer input_buffer;
743 std::vector<cdm::SubsampleEntry> subsamples;
744 ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
745 &input_buffer);
746 status = cdm_->Decrypt(input_buffer, decrypted_block.get());
747 PP_DCHECK(status != cdm::kSuccess ||
748 (decrypted_block->DecryptedBuffer() &&
749 decrypted_block->DecryptedBuffer()->Size()));
750 }
751
752 CallOnMain(callback_factory_.NewCallback(
753 &CdmWrapper::DeliverBlock,
754 status,
755 decrypted_block,
756 encrypted_block_info.tracking_info));
757 }
758
759 void CdmWrapper::InitializeAudioDecoder(
760 const PP_AudioDecoderConfig& decoder_config,
761 pp::Buffer_Dev extra_data_buffer) {
762 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
763
764 cdm::Status status = cdm::kSessionError;
765 if (cdm_) {
766 cdm::AudioDecoderConfig cdm_decoder_config;
767 cdm_decoder_config.codec =
768 PpAudioCodecToCdmAudioCodec(decoder_config.codec);
769 cdm_decoder_config.channel_count = decoder_config.channel_count;
770 cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
771 cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
772 cdm_decoder_config.extra_data =
773 static_cast<uint8_t*>(extra_data_buffer.data());
774 cdm_decoder_config.extra_data_size =
775 static_cast<int32_t>(extra_data_buffer.size());
776 status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
777 }
778
779 CallOnMain(callback_factory_.NewCallback(
780 &CdmWrapper::DecoderInitializeDone,
781 PP_DECRYPTORSTREAMTYPE_AUDIO,
782 decoder_config.request_id,
783 status == cdm::kSuccess));
784 }
785
786 void CdmWrapper::InitializeVideoDecoder(
787 const PP_VideoDecoderConfig& decoder_config,
788 pp::Buffer_Dev extra_data_buffer) {
789 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
790
791 cdm::Status status = cdm::kSessionError;
792 if (cdm_) {
793 cdm::VideoDecoderConfig cdm_decoder_config;
794 cdm_decoder_config.codec =
795 PpVideoCodecToCdmVideoCodec(decoder_config.codec);
796 cdm_decoder_config.profile =
797 PpVCProfileToCdmVCProfile(decoder_config.profile);
798 cdm_decoder_config.format =
799 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
800 cdm_decoder_config.coded_size.width = decoder_config.width;
801 cdm_decoder_config.coded_size.height = decoder_config.height;
802 cdm_decoder_config.extra_data =
803 static_cast<uint8_t*>(extra_data_buffer.data());
804 cdm_decoder_config.extra_data_size =
805 static_cast<int32_t>(extra_data_buffer.size());
806 status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
807 }
808
809 CallOnMain(callback_factory_.NewCallback(
810 &CdmWrapper::DecoderInitializeDone,
811 PP_DECRYPTORSTREAMTYPE_VIDEO,
812 decoder_config.request_id,
813 status == cdm::kSuccess));
814 }
815
816 void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
817 uint32_t request_id) {
818 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
819 if (cdm_) {
820 cdm_->DeinitializeDecoder(
821 PpDecryptorStreamTypeToCdmStreamType(decoder_type));
822 }
823
824 CallOnMain(callback_factory_.NewCallback(
825 &CdmWrapper::DecoderDeinitializeDone,
826 decoder_type,
827 request_id));
828 }
829
830 void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
831 uint32_t request_id) {
832 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
833 if (cdm_)
834 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
835
836 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone,
837 decoder_type,
838 request_id));
839 }
840
841 void CdmWrapper::DecryptAndDecode(
842 PP_DecryptorStreamType decoder_type,
843 pp::Buffer_Dev encrypted_buffer,
844 const PP_EncryptedBlockInfo& encrypted_block_info) {
845 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
846
847 // Release a buffer that the caller indicated it is finished with.
848 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
849
850 cdm::InputBuffer input_buffer;
851 std::vector<cdm::SubsampleEntry> subsamples;
852 if (cdm_ && !encrypted_buffer.is_null()) {
853 ConfigureInputBuffer(encrypted_buffer,
854 encrypted_block_info,
855 &subsamples,
856 &input_buffer);
857 }
858
859 cdm::Status status = cdm::kDecodeError;
860
861 switch (decoder_type) {
862 case PP_DECRYPTORSTREAMTYPE_VIDEO: {
863 LinkedVideoFrame video_frame(new VideoFrameImpl());
864 if (cdm_)
865 status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
866 CallOnMain(callback_factory_.NewCallback(
867 &CdmWrapper::DeliverFrame,
868 status,
869 video_frame,
870 encrypted_block_info.tracking_info));
871 return;
872 }
873
874 case PP_DECRYPTORSTREAMTYPE_AUDIO: {
875 LinkedAudioFrames audio_frames(new AudioFramesImpl());
876 if (cdm_) {
877 status = cdm_->DecryptAndDecodeSamples(input_buffer,
878 audio_frames.get());
879 }
880 CallOnMain(callback_factory_.NewCallback(
881 &CdmWrapper::DeliverSamples,
882 status,
883 audio_frames,
884 encrypted_block_info.tracking_info));
885 return;
886 }
887
888 default:
889 PP_NOTREACHED();
890 return;
891 }
892 }
893
894 cdm::Buffer* CdmWrapper::Allocate(int32_t capacity) {
895 return allocator_.Allocate(capacity);
896 }
897
898 void CdmWrapper::SetTimer(int64_t delay_ms, void* context) {
899 // NOTE: doesn't really need to run on the main thread; could just as well run
900 // on a helper thread if |cdm_| were thread-friendly and care was taken. We
901 // only use CallOnMainThread() here to get delayed-execution behavior.
902 pp::Module::Get()->core()->CallOnMainThread(
903 delay_ms,
904 callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context),
905 PP_OK);
906 }
907
908 void CdmWrapper::TimerExpired(int32_t result, void* context) {
909 PP_DCHECK(result == PP_OK);
910 cdm_->TimerExpired(context);
911 }
912
913 double CdmWrapper::GetCurrentWallTimeInSeconds() {
914 return pp::Module::Get()->core()->GetTime();
915 }
916
917 void CdmWrapper::SendKeyMessage(
918 const char* session_id, int32_t session_id_length,
919 const char* message, int32_t message_length,
920 const char* default_url, int32_t default_url_length) {
921 PP_DCHECK(!key_system_.empty());
922 PostOnMain(callback_factory_.NewCallback(
923 &CdmWrapper::KeyMessage,
924 SessionInfo(key_system_,
925 std::string(session_id, session_id_length)),
926 std::vector<uint8>(message, message + message_length),
927 std::string(default_url, default_url_length)));
928 }
929
930 void CdmWrapper::SendKeyError(const char* session_id,
931 int32_t session_id_length,
932 cdm::MediaKeyError error_code,
933 uint32_t system_code) {
934 SendKeyErrorInternal(key_system_,
935 std::string(session_id, session_id_length),
936 error_code,
937 system_code);
938 }
939
940 void CdmWrapper::GetPrivateData(int32_t* instance,
941 cdm::Host::GetPrivateInterface* get_interface) {
942 *instance = pp_instance();
943 *get_interface = pp::Module::Get()->get_browser_interface();
944 }
945
946 void CdmWrapper::SendUnknownKeyError(const std::string& key_system,
947 const std::string& session_id) {
948 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0);
949 }
950
951 void CdmWrapper::SendKeyAdded(const std::string& key_system,
952 const std::string& session_id) {
953 PostOnMain(callback_factory_.NewCallback(
954 &CdmWrapper::KeyAdded,
955 SessionInfo(key_system_, session_id)));
956 }
957
958 void CdmWrapper::SendKeyErrorInternal(const std::string& key_system,
959 const std::string& session_id,
960 cdm::MediaKeyError error_code,
961 uint32_t system_code) {
962 PP_DCHECK(!key_system.empty());
963 PostOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
964 SessionInfo(key_system_, session_id),
965 error_code,
966 system_code));
967 }
968
969 void CdmWrapper::KeyAdded(int32_t result, const SessionInfo& session_info) {
970 PP_DCHECK(result == PP_OK);
971 PP_DCHECK(!session_info.key_system.empty());
972 pp::ContentDecryptor_Private::KeyAdded(session_info.key_system,
973 session_info.session_id);
974 }
975
976 void CdmWrapper::KeyMessage(int32_t result,
977 const SessionInfo& session_info,
978 const std::vector<uint8>& message,
979 const std::string& default_url) {
980 PP_DCHECK(result == PP_OK);
981 PP_DCHECK(!session_info.key_system.empty());
982
983 pp::VarArrayBuffer message_array_buffer(message.size());
984 if (message.size() > 0) {
985 memcpy(message_array_buffer.Map(), message.data(), message.size());
986 }
987
988 pp::ContentDecryptor_Private::KeyMessage(
989 session_info.key_system, session_info.session_id,
990 message_array_buffer, default_url);
991 }
992
993 void CdmWrapper::KeyError(int32_t result,
994 const SessionInfo& session_info,
995 cdm::MediaKeyError error_code,
996 uint32_t system_code) {
997 PP_DCHECK(result == PP_OK);
998 PP_DCHECK(!session_info.key_system.empty());
999 pp::ContentDecryptor_Private::KeyError(
1000 session_info.key_system, session_info.session_id,
1001 error_code, system_code);
1002 }
1003
1004 void CdmWrapper::DeliverBlock(int32_t result,
1005 const cdm::Status& status,
1006 const LinkedDecryptedBlock& decrypted_block,
1007 const PP_DecryptTrackingInfo& tracking_info) {
1008 PP_DCHECK(result == PP_OK);
1009 PP_DecryptedBlockInfo decrypted_block_info;
1010 decrypted_block_info.tracking_info = tracking_info;
1011 decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
1012 decrypted_block_info.tracking_info.buffer_id = 0;
1013 decrypted_block_info.data_size = 0;
1014 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
1015
1016 pp::Buffer_Dev buffer;
1017
1018 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
1019 PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
1020 if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
1021 PP_NOTREACHED();
1022 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
1023 } else {
1024 PpbBuffer* ppb_buffer =
1025 static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
1026 buffer = ppb_buffer->buffer_dev();
1027 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
1028 decrypted_block_info.data_size = ppb_buffer->Size();
1029 }
1030 }
1031
1032 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
1033 }
1034
1035 void CdmWrapper::DecoderInitializeDone(int32_t result,
1036 PP_DecryptorStreamType decoder_type,
1037 uint32_t request_id,
1038 bool success) {
1039 PP_DCHECK(result == PP_OK);
1040 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
1041 request_id,
1042 success);
1043 }
1044
1045 void CdmWrapper::DecoderDeinitializeDone(int32_t result,
1046 PP_DecryptorStreamType decoder_type,
1047 uint32_t request_id) {
1048 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
1049 request_id);
1050 }
1051
1052 void CdmWrapper::DecoderResetDone(int32_t result,
1053 PP_DecryptorStreamType decoder_type,
1054 uint32_t request_id) {
1055 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
1056 }
1057
1058 void CdmWrapper::DeliverFrame(
1059 int32_t result,
1060 const cdm::Status& status,
1061 const LinkedVideoFrame& video_frame,
1062 const PP_DecryptTrackingInfo& tracking_info) {
1063 PP_DCHECK(result == PP_OK);
1064 PP_DecryptedFrameInfo decrypted_frame_info;
1065 decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
1066 decrypted_frame_info.tracking_info.buffer_id = 0;
1067 decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
1068
1069 pp::Buffer_Dev buffer;
1070
1071 if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
1072 if (!IsValidVideoFrame(video_frame)) {
1073 PP_NOTREACHED();
1074 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
1075 } else {
1076 PpbBuffer* ppb_buffer =
1077 static_cast<PpbBuffer*>(video_frame->FrameBuffer());
1078
1079 buffer = ppb_buffer->buffer_dev();
1080
1081 decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
1082 decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
1083 decrypted_frame_info.format =
1084 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
1085 decrypted_frame_info.width = video_frame->Size().width;
1086 decrypted_frame_info.height = video_frame->Size().height;
1087 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
1088 video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
1089 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
1090 video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
1091 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
1092 video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
1093 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
1094 video_frame->Stride(cdm::VideoFrame::kYPlane);
1095 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
1096 video_frame->Stride(cdm::VideoFrame::kUPlane);
1097 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
1098 video_frame->Stride(cdm::VideoFrame::kVPlane);
1099 }
1100 }
1101 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
1102 }
1103
1104 void CdmWrapper::DeliverSamples(int32_t result,
1105 const cdm::Status& status,
1106 const LinkedAudioFrames& audio_frames,
1107 const PP_DecryptTrackingInfo& tracking_info) {
1108 PP_DCHECK(result == PP_OK);
1109
1110 PP_DecryptedBlockInfo decrypted_block_info;
1111 decrypted_block_info.tracking_info = tracking_info;
1112 decrypted_block_info.tracking_info.timestamp = 0;
1113 decrypted_block_info.tracking_info.buffer_id = 0;
1114 decrypted_block_info.data_size = 0;
1115 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
1116
1117 pp::Buffer_Dev buffer;
1118
1119 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
1120 PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
1121 if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
1122 PP_NOTREACHED();
1123 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
1124 } else {
1125 PpbBuffer* ppb_buffer =
1126 static_cast<PpbBuffer*>(audio_frames->FrameBuffer());
1127 buffer = ppb_buffer->buffer_dev();
1128 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
1129 decrypted_block_info.data_size = ppb_buffer->Size();
1130 }
1131 }
1132
1133 pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_block_info);
1134 }
1135
1136 bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
1137 if (!video_frame.get() ||
1138 !video_frame->FrameBuffer() ||
1139 (video_frame->Format() != cdm::kI420 &&
1140 video_frame->Format() != cdm::kYv12)) {
1141 return false;
1142 }
1143
1144 PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());
1145
1146 for (int i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
1147 int plane_height = (i == cdm::VideoFrame::kYPlane) ?
1148 video_frame->Size().height : (video_frame->Size().height + 1) / 2;
1149 cdm::VideoFrame::VideoPlane plane =
1150 static_cast<cdm::VideoFrame::VideoPlane>(i);
1151 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
1152 plane_height * video_frame->Stride(plane)) {
1153 return false;
1154 }
1155 }
1156
1157 return true;
1158 }
1159
1160 void* GetCdmHost(int host_interface_version, void* user_data) {
1161 if (!host_interface_version || !user_data)
1162 return NULL;
1163
1164 if (host_interface_version != cdm::kHostInterfaceVersion)
1165 return NULL;
1166
1167 CdmWrapper* cdm_wrapper = static_cast<CdmWrapper*>(user_data);
1168 return static_cast<cdm::Host*>(cdm_wrapper);
1169 }
1170
1171 // This object is the global object representing this plugin library as long
1172 // as it is loaded.
1173 class CdmWrapperModule : public pp::Module {
1174 public:
1175 CdmWrapperModule() : pp::Module() {
1176 // This function blocks the renderer thread (PluginInstance::Initialize()).
1177 // Move this call to other places if this may be a concern in the future.
1178 INITIALIZE_CDM_MODULE();
1179 }
1180 virtual ~CdmWrapperModule() {
1181 DeinitializeCdmModule();
1182 }
1183
1184 virtual pp::Instance* CreateInstance(PP_Instance instance) {
1185 return new CdmWrapper(instance, this);
1186 }
1187 };
1188
1189 } // namespace webkit_media
1190
1191 namespace pp {
1192
1193 // Factory function for your specialization of the Module object.
1194 Module* CreateModule() {
1195 return new webkit_media::CdmWrapperModule();
1196 }
1197
1198 } // namespace pp
OLDNEW
« no previous file with comments | « webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc ('k') | webkit/renderer/media/crypto/ppapi/clear_key_cdm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698