1 // 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.
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/instance.h"
19 #include "ppapi/cpp/logging.h"
20 #include "ppapi/cpp/module.h"
21 #include "ppapi/cpp/pass_ref.h"
22 #include "ppapi/cpp/resource.h"
23 #include "ppapi/cpp/var.h"
24 #include "ppapi/cpp/var_array_buffer.h"
25 #include "ppapi/cpp/dev/buffer_dev.h"
26 #include "ppapi/cpp/private/content_decryptor_private.h"
27 #include "ppapi/utility/completion_callback_factory.h"
28 #include "webkit/media/crypto/ppapi/cdm/content_decryption_module.h"
29 #include "webkit/media/crypto/ppapi/linked_ptr.h"
31 #if defined(CHECK_ORIGIN_URL)
32 #include "ppapi/cpp/private/instance_private.h"
33 #include "ppapi/cpp/private/var_private.h"
34 #endif // defined(CHECK_ORIGIN_URL)
39 return pp::Module::Get()->core()->IsMainThread();
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
);
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.
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());
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
;
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
;
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
;
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
);
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
));
96 input_buffer
->subsamples
= &(*subsamples
)[0];
99 input_buffer
->timestamp
= encrypted_block_info
.tracking_info
.timestamp
;
102 PP_DecryptResult
CdmStatusToPpDecryptResult(cdm::Status status
) {
105 return PP_DECRYPTRESULT_SUCCESS
;
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
;
116 return PP_DECRYPTRESULT_DECODE_ERROR
;
120 PP_DecryptedFrameFormat
CdmVideoFormatToPpDecryptedFrameFormat(
121 cdm::VideoFormat format
) {
124 return PP_DECRYPTEDFRAMEFORMAT_YV12
;
126 return PP_DECRYPTEDFRAMEFORMAT_I420
;
128 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN
;
132 cdm::AudioDecoderConfig::AudioCodec
PpAudioCodecToCdmAudioCodec(
133 PP_AudioCodec codec
) {
135 case PP_AUDIOCODEC_VORBIS
:
136 return cdm::AudioDecoderConfig::kCodecVorbis
;
137 case PP_AUDIOCODEC_AAC
:
138 return cdm::AudioDecoderConfig::kCodecAac
;
140 return cdm::AudioDecoderConfig::kUnknownAudioCodec
;
144 cdm::VideoDecoderConfig::VideoCodec
PpVideoCodecToCdmVideoCodec(
145 PP_VideoCodec codec
) {
147 case PP_VIDEOCODEC_VP8
:
148 return cdm::VideoDecoderConfig::kCodecVp8
;
149 case PP_VIDEOCODEC_H264
:
150 return cdm::VideoDecoderConfig::kCodecH264
;
152 return cdm::VideoDecoderConfig::kUnknownVideoCodec
;
156 cdm::VideoDecoderConfig::VideoCodecProfile
PpVCProfileToCdmVCProfile(
157 PP_VideoCodecProfile 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
;
176 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile
;
180 cdm::VideoFormat
PpDecryptedFrameFormatToCdmVideoFormat(
181 PP_DecryptedFrameFormat format
) {
183 case PP_DECRYPTEDFRAMEFORMAT_YV12
:
185 case PP_DECRYPTEDFRAMEFORMAT_I420
:
188 return cdm::kUnknownVideoFormat
;
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
;
202 return cdm::kStreamTypeVideo
;
207 namespace webkit_media
{
209 // cdm::Buffer implementation that provides access to memory owned by a
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
{
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
);
223 // cdm::Buffer implementation.
224 virtual void Destroy() OVERRIDE
{ delete this; }
226 virtual int32_t Capacity() const OVERRIDE
{ return buffer_
.size(); }
228 virtual uint8_t* Data() OVERRIDE
{
229 return static_cast<uint8_t*>(buffer_
.data());
232 virtual void SetSize(int32_t size
) OVERRIDE
{
233 PP_DCHECK(size
>= 0);
234 PP_DCHECK(size
< Capacity());
235 if (size
< 0 || size
> Capacity()) {
243 virtual int32_t Size() const OVERRIDE
{ return size_
; }
245 pp::Buffer_Dev
buffer_dev() const { return buffer_
; }
247 uint32_t buffer_id() const { return buffer_id_
; }
250 PpbBuffer(pp::Buffer_Dev buffer
, uint32_t buffer_id
)
252 buffer_id_(buffer_id
),
254 virtual ~PpbBuffer() {}
256 pp::Buffer_Dev buffer_
;
260 DISALLOW_COPY_AND_ASSIGN(PpbBuffer
);
263 class PpbBufferAllocator
{
265 explicit PpbBufferAllocator(pp::Instance
* instance
)
266 : instance_(instance
),
267 next_buffer_id_(1) {}
268 ~PpbBufferAllocator() {}
270 cdm::Buffer
* Allocate(int32_t capacity
);
272 // Releases the buffer with |buffer_id|. A buffer can be recycled after
274 void Release(uint32_t buffer_id
);
277 typedef std::map
<uint32_t, pp::Buffer_Dev
> AllocatedBufferMap
;
278 typedef std::multimap
<int, std::pair
<uint32_t, pp::Buffer_Dev
> >
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;
285 // Maximum number of free buffers we can keep when allocating new buffers.
286 static const int kFreeLimit
= 3;
288 pp::Buffer_Dev
AllocateNewBuffer(int capacity
);
290 pp::Instance
* const instance_
;
291 uint32_t next_buffer_id_
;
292 AllocatedBufferMap allocated_buffers_
;
293 FreeBufferMap free_buffers_
;
295 DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator
);
298 cdm::Buffer
* PpbBufferAllocator::Allocate(int32_t capacity
) {
299 PP_DCHECK(IsMainThread());
304 pp::Buffer_Dev buffer
;
305 uint32_t buffer_id
= 0;
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())
315 buffer_id
= next_buffer_id_
++;
317 buffer
= found
->second
.second
;
318 buffer_id
= found
->second
.first
;
319 free_buffers_
.erase(found
);
322 allocated_buffers_
.insert(std::make_pair(buffer_id
, buffer
));
324 return PpbBuffer::Create(buffer
, buffer_id
);
327 void PpbBufferAllocator::Release(uint32_t buffer_id
) {
331 AllocatedBufferMap::iterator found
= allocated_buffers_
.find(buffer_id
);
332 if (found
== allocated_buffers_
.end())
335 pp::Buffer_Dev
& buffer
= found
->second
;
336 free_buffers_
.insert(
337 std::make_pair(buffer
.size(), std::make_pair(buffer_id
, buffer
)));
339 allocated_buffers_
.erase(found
);
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());
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
);
355 class DecryptedBlockImpl
: public cdm::DecryptedBlock
{
357 DecryptedBlockImpl() : buffer_(NULL
), timestamp_(0) {}
358 virtual ~DecryptedBlockImpl() { if (buffer_
) buffer_
->Destroy(); }
360 virtual void SetDecryptedBuffer(cdm::Buffer
* buffer
) OVERRIDE
{
361 buffer_
= static_cast<PpbBuffer
*>(buffer
);
363 virtual cdm::Buffer
* DecryptedBuffer() OVERRIDE
{ return buffer_
; }
365 virtual void SetTimestamp(int64_t timestamp
) OVERRIDE
{
366 timestamp_
= timestamp
;
368 virtual int64_t Timestamp() const OVERRIDE
{ return timestamp_
; }
374 DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl
);
377 class VideoFrameImpl
: public cdm::VideoFrame
{
380 virtual ~VideoFrameImpl();
382 virtual void SetFormat(cdm::VideoFormat format
) OVERRIDE
{
385 virtual cdm::VideoFormat
Format() const OVERRIDE
{ return format_
; }
387 virtual void SetSize(cdm::Size size
) OVERRIDE
{ size_
= size
; }
388 virtual cdm::Size
Size() const OVERRIDE
{ return size_
; }
390 virtual void SetFrameBuffer(cdm::Buffer
* frame_buffer
) OVERRIDE
{
391 frame_buffer_
= static_cast<PpbBuffer
*>(frame_buffer
);
393 virtual cdm::Buffer
* FrameBuffer() OVERRIDE
{ return frame_buffer_
; }
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
;
401 virtual int32_t PlaneOffset(VideoPlane plane
) OVERRIDE
{
402 PP_DCHECK(0 <= plane
&& plane
< kMaxPlanes
);
403 return plane_offsets_
[plane
];
406 virtual void SetStride(VideoPlane plane
, int32_t stride
) OVERRIDE
{
407 PP_DCHECK(0 <= plane
&& plane
< kMaxPlanes
);
408 strides_
[plane
] = stride
;
410 virtual int32_t Stride(VideoPlane plane
) OVERRIDE
{
411 PP_DCHECK(0 <= plane
&& plane
< kMaxPlanes
);
412 return strides_
[plane
];
415 virtual void SetTimestamp(int64_t timestamp
) OVERRIDE
{
416 timestamp_
= timestamp
;
418 virtual int64_t Timestamp() const OVERRIDE
{ return timestamp_
; }
421 // The video buffer format.
422 cdm::VideoFormat format_
;
424 // Width and height of the video frame.
427 // The video frame buffer.
428 PpbBuffer
* frame_buffer_
;
430 // Array of data pointers to each plane in the video frame buffer.
431 int32_t plane_offsets_
[kMaxPlanes
];
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
];
438 // Presentation timestamp in microseconds.
441 DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl
);
444 VideoFrameImpl::VideoFrameImpl()
445 : format_(cdm::kUnknownVideoFormat
),
448 for (int32_t i
= 0; i
< kMaxPlanes
; ++i
) {
449 plane_offsets_
[i
] = 0;
454 VideoFrameImpl::~VideoFrameImpl() {
456 frame_buffer_
->Destroy();
459 class AudioFramesImpl
: public cdm::AudioFrames
{
461 AudioFramesImpl() : buffer_(NULL
) {}
462 virtual ~AudioFramesImpl() {
467 // AudioFrames implementation.
468 virtual void SetFrameBuffer(cdm::Buffer
* buffer
) OVERRIDE
{
469 buffer_
= static_cast<PpbBuffer
*>(buffer
);
471 virtual cdm::Buffer
* FrameBuffer() OVERRIDE
{
478 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl
);
481 // GetCdmHostFunc implementation.
482 void* GetCdmHost(int host_interface_version
, void* user_data
);
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
,
490 CdmWrapper(PP_Instance instance
, pp::Module
* module
);
491 virtual ~CdmWrapper();
493 // pp::Instance implementation.
494 virtual bool Init(uint32_t argc
, const char* argn
[], const char* argv
[]) {
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
;
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
;
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
;
551 typedef linked_ptr
<DecryptedBlockImpl
> LinkedDecryptedBlock
;
552 typedef linked_ptr
<VideoFrameImpl
> LinkedVideoFrame
;
553 typedef linked_ptr
<AudioFramesImpl
> LinkedAudioFrames
;
555 bool CreateCdmInstance(const std::string
& key_system
);
557 void SendUnknownKeyError(const std::string
& key_system
,
558 const std::string
& session_id
);
560 void SendKeyAdded(const std::string
& key_system
,
561 const std::string
& session_id
);
563 void SendKeyErrorInternal(const std::string
& key_system
,
564 const std::string
& session_id
,
565 cdm::MediaKeyError error_code
,
566 uint32_t system_code
);
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::string
& 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
,
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
);
603 // Helper for SetTimer().
604 void TimerExpired(int32_t result
, void* context
);
606 bool IsValidVideoFrame(const LinkedVideoFrame
& video_frame
);
608 PpbBufferAllocator allocator_
;
609 pp::CompletionCallbackFactory
<CdmWrapper
> callback_factory_
;
610 cdm::ContentDecryptionModule
* cdm_
;
611 std::string key_system_
;
613 DISALLOW_COPY_AND_ASSIGN(CdmWrapper
);
616 CdmWrapper::CdmWrapper(PP_Instance instance
, pp::Module
* module
)
617 : pp::Instance(instance
),
618 pp::ContentDecryptor_Private(this),
621 callback_factory_
.Initialize(this);
624 CdmWrapper::~CdmWrapper() {
629 bool CdmWrapper::CreateCdmInstance(const std::string
& key_system
) {
631 cdm_
= static_cast<cdm::ContentDecryptionModule
*>(
632 ::CreateCdmInstance(cdm::kCdmInterfaceVersion
,
633 key_system
.data(), key_system
.size(),
636 return (cdm_
!= NULL
);
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
);
645 #if defined(CHECK_ORIGIN_URL)
646 pp::InstancePrivate
instance_private(pp_instance());
647 pp::VarPrivate window
= instance_private
.GetWindowObject();
648 std::string origin
= window
.GetProperty("top").GetProperty("location")
649 .GetProperty("origin").AsString();
650 PP_DCHECK(origin
!= "null");
651 #endif // defined(CHECK_ORIGIN_URL)
654 if (!CreateCdmInstance(key_system
)) {
655 SendUnknownKeyError(key_system
, std::string());
661 // Must be set here in case the CDM synchronously calls a cdm::Host method.
662 // Clear below on error.
663 // TODO(ddorwin): Set/clear key_system_ & cdm_ at same time; clear both on
665 key_system_
= key_system
;
666 cdm::Status status
= cdm_
->GenerateKeyRequest(
667 type
.data(), type
.size(),
668 static_cast<const uint8_t*>(init_data
.Map()),
669 init_data
.ByteLength());
670 PP_DCHECK(status
== cdm::kSuccess
|| status
== cdm::kSessionError
);
671 if (status
!= cdm::kSuccess
) {
672 key_system_
.clear(); // See comment above.
676 key_system_
= key_system
;
679 void CdmWrapper::AddKey(const std::string
& session_id
,
680 pp::VarArrayBuffer key
,
681 pp::VarArrayBuffer init_data
) {
682 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
684 SendUnknownKeyError(key_system_
, session_id
);
688 const uint8_t* key_ptr
= static_cast<const uint8_t*>(key
.Map());
689 int key_size
= key
.ByteLength();
690 const uint8_t* init_data_ptr
= static_cast<const uint8_t*>(init_data
.Map());
691 int init_data_size
= init_data
.ByteLength();
692 PP_DCHECK(!init_data_ptr
== !init_data_size
);
694 if (!key_ptr
|| key_size
<= 0) {
695 SendUnknownKeyError(key_system_
, session_id
);
699 cdm::Status status
= cdm_
->AddKey(session_id
.data(), session_id
.size(),
701 init_data_ptr
, init_data_size
);
702 PP_DCHECK(status
== cdm::kSuccess
|| status
== cdm::kSessionError
);
703 if (status
!= cdm::kSuccess
) {
704 SendUnknownKeyError(key_system_
, session_id
);
708 SendKeyAdded(key_system_
, session_id
);
711 void CdmWrapper::CancelKeyRequest(const std::string
& session_id
) {
712 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
714 SendUnknownKeyError(key_system_
, session_id
);
718 cdm::Status status
= cdm_
->CancelKeyRequest(session_id
.data(),
720 PP_DCHECK(status
== cdm::kSuccess
|| status
== cdm::kSessionError
);
721 if (status
!= cdm::kSuccess
)
722 SendUnknownKeyError(key_system_
, session_id
);
725 // Note: In the following decryption/decoding related functions, errors are NOT
726 // reported via KeyError, but are reported via corresponding PPB calls.
728 void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer
,
729 const PP_EncryptedBlockInfo
& encrypted_block_info
) {
730 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
731 PP_DCHECK(!encrypted_buffer
.is_null());
733 // Release a buffer that the caller indicated it is finished with.
734 allocator_
.Release(encrypted_block_info
.tracking_info
.buffer_id
);
736 cdm::Status status
= cdm::kDecryptError
;
737 LinkedDecryptedBlock
decrypted_block(new DecryptedBlockImpl());
740 cdm::InputBuffer input_buffer
;
741 std::vector
<cdm::SubsampleEntry
> subsamples
;
742 ConfigureInputBuffer(encrypted_buffer
, encrypted_block_info
, &subsamples
,
744 status
= cdm_
->Decrypt(input_buffer
, decrypted_block
.get());
745 PP_DCHECK(status
!= cdm::kSuccess
||
746 (decrypted_block
->DecryptedBuffer() &&
747 decrypted_block
->DecryptedBuffer()->Size()));
750 CallOnMain(callback_factory_
.NewCallback(
751 &CdmWrapper::DeliverBlock
,
754 encrypted_block_info
.tracking_info
));
757 void CdmWrapper::InitializeAudioDecoder(
758 const PP_AudioDecoderConfig
& decoder_config
,
759 pp::Buffer_Dev extra_data_buffer
) {
760 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
762 cdm::Status status
= cdm::kSessionError
;
764 cdm::AudioDecoderConfig cdm_decoder_config
;
765 cdm_decoder_config
.codec
=
766 PpAudioCodecToCdmAudioCodec(decoder_config
.codec
);
767 cdm_decoder_config
.channel_count
= decoder_config
.channel_count
;
768 cdm_decoder_config
.bits_per_channel
= decoder_config
.bits_per_channel
;
769 cdm_decoder_config
.samples_per_second
= decoder_config
.samples_per_second
;
770 cdm_decoder_config
.extra_data
=
771 static_cast<uint8_t*>(extra_data_buffer
.data());
772 cdm_decoder_config
.extra_data_size
=
773 static_cast<int32_t>(extra_data_buffer
.size());
774 status
= cdm_
->InitializeAudioDecoder(cdm_decoder_config
);
777 CallOnMain(callback_factory_
.NewCallback(
778 &CdmWrapper::DecoderInitializeDone
,
779 PP_DECRYPTORSTREAMTYPE_AUDIO
,
780 decoder_config
.request_id
,
781 status
== cdm::kSuccess
));
784 void CdmWrapper::InitializeVideoDecoder(
785 const PP_VideoDecoderConfig
& decoder_config
,
786 pp::Buffer_Dev extra_data_buffer
) {
787 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
789 cdm::Status status
= cdm::kSessionError
;
791 cdm::VideoDecoderConfig cdm_decoder_config
;
792 cdm_decoder_config
.codec
=
793 PpVideoCodecToCdmVideoCodec(decoder_config
.codec
);
794 cdm_decoder_config
.profile
=
795 PpVCProfileToCdmVCProfile(decoder_config
.profile
);
796 cdm_decoder_config
.format
=
797 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config
.format
);
798 cdm_decoder_config
.coded_size
.width
= decoder_config
.width
;
799 cdm_decoder_config
.coded_size
.height
= decoder_config
.height
;
800 cdm_decoder_config
.extra_data
=
801 static_cast<uint8_t*>(extra_data_buffer
.data());
802 cdm_decoder_config
.extra_data_size
=
803 static_cast<int32_t>(extra_data_buffer
.size());
804 status
= cdm_
->InitializeVideoDecoder(cdm_decoder_config
);
807 CallOnMain(callback_factory_
.NewCallback(
808 &CdmWrapper::DecoderInitializeDone
,
809 PP_DECRYPTORSTREAMTYPE_VIDEO
,
810 decoder_config
.request_id
,
811 status
== cdm::kSuccess
));
814 void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type
,
815 uint32_t request_id
) {
816 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
818 cdm_
->DeinitializeDecoder(
819 PpDecryptorStreamTypeToCdmStreamType(decoder_type
));
822 CallOnMain(callback_factory_
.NewCallback(
823 &CdmWrapper::DecoderDeinitializeDone
,
828 void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type
,
829 uint32_t request_id
) {
830 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
832 cdm_
->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type
));
834 CallOnMain(callback_factory_
.NewCallback(&CdmWrapper::DecoderResetDone
,
839 void CdmWrapper::DecryptAndDecode(
840 PP_DecryptorStreamType decoder_type
,
841 pp::Buffer_Dev encrypted_buffer
,
842 const PP_EncryptedBlockInfo
& encrypted_block_info
) {
843 PP_DCHECK(cdm_
); // GenerateKeyRequest() should have succeeded.
845 // Release a buffer that the caller indicated it is finished with.
846 allocator_
.Release(encrypted_block_info
.tracking_info
.buffer_id
);
848 cdm::InputBuffer input_buffer
;
849 std::vector
<cdm::SubsampleEntry
> subsamples
;
850 if (cdm_
&& !encrypted_buffer
.is_null()) {
851 ConfigureInputBuffer(encrypted_buffer
,
852 encrypted_block_info
,
857 cdm::Status status
= cdm::kDecodeError
;
859 switch (decoder_type
) {
860 case PP_DECRYPTORSTREAMTYPE_VIDEO
: {
861 LinkedVideoFrame
video_frame(new VideoFrameImpl());
863 status
= cdm_
->DecryptAndDecodeFrame(input_buffer
, video_frame
.get());
864 CallOnMain(callback_factory_
.NewCallback(
865 &CdmWrapper::DeliverFrame
,
868 encrypted_block_info
.tracking_info
));
872 case PP_DECRYPTORSTREAMTYPE_AUDIO
: {
873 LinkedAudioFrames
audio_frames(new AudioFramesImpl());
875 status
= cdm_
->DecryptAndDecodeSamples(input_buffer
,
878 CallOnMain(callback_factory_
.NewCallback(
879 &CdmWrapper::DeliverSamples
,
882 encrypted_block_info
.tracking_info
));
892 cdm::Buffer
* CdmWrapper::Allocate(int32_t capacity
) {
893 return allocator_
.Allocate(capacity
);
896 void CdmWrapper::SetTimer(int64_t delay_ms
, void* context
) {
897 // NOTE: doesn't really need to run on the main thread; could just as well run
898 // on a helper thread if |cdm_| were thread-friendly and care was taken. We
899 // only use CallOnMainThread() here to get delayed-execution behavior.
900 pp::Module::Get()->core()->CallOnMainThread(
902 callback_factory_
.NewCallback(&CdmWrapper::TimerExpired
, context
),
906 void CdmWrapper::TimerExpired(int32_t result
, void* context
) {
907 PP_DCHECK(result
== PP_OK
);
908 cdm_
->TimerExpired(context
);
911 double CdmWrapper::GetCurrentWallTimeInSeconds() {
912 return pp::Module::Get()->core()->GetTime();
915 void CdmWrapper::SendKeyMessage(
916 const char* session_id
, int32_t session_id_length
,
917 const char* message
, int32_t message_length
,
918 const char* default_url
, int32_t default_url_length
) {
919 PP_DCHECK(!key_system_
.empty());
920 PostOnMain(callback_factory_
.NewCallback(
921 &CdmWrapper::KeyMessage
,
922 SessionInfo(key_system_
,
923 std::string(session_id
, session_id_length
)),
924 std::string(message
, message_length
),
925 std::string(default_url
, default_url_length
)));
928 void CdmWrapper::SendKeyError(const char* session_id
,
929 int32_t session_id_length
,
930 cdm::MediaKeyError error_code
,
931 uint32_t system_code
) {
932 SendKeyErrorInternal(key_system_
,
933 std::string(session_id
, session_id_length
),
938 void CdmWrapper::GetPrivateData(int32_t* instance
,
939 cdm::Host::GetPrivateInterface
* get_interface
) {
940 *instance
= pp_instance();
941 *get_interface
= pp::Module::Get()->get_browser_interface();
944 void CdmWrapper::SendUnknownKeyError(const std::string
& key_system
,
945 const std::string
& session_id
) {
946 SendKeyErrorInternal(key_system
, session_id
, cdm::kUnknownError
, 0);
949 void CdmWrapper::SendKeyAdded(const std::string
& key_system
,
950 const std::string
& session_id
) {
951 PostOnMain(callback_factory_
.NewCallback(
952 &CdmWrapper::KeyAdded
,
953 SessionInfo(key_system_
, session_id
)));
956 void CdmWrapper::SendKeyErrorInternal(const std::string
& key_system
,
957 const std::string
& session_id
,
958 cdm::MediaKeyError error_code
,
959 uint32_t system_code
) {
960 PP_DCHECK(!key_system
.empty());
961 PostOnMain(callback_factory_
.NewCallback(&CdmWrapper::KeyError
,
962 SessionInfo(key_system_
, session_id
),
967 void CdmWrapper::KeyAdded(int32_t result
, const SessionInfo
& session_info
) {
968 PP_DCHECK(result
== PP_OK
);
969 PP_DCHECK(!session_info
.key_system
.empty());
970 pp::ContentDecryptor_Private::KeyAdded(session_info
.key_system
,
971 session_info
.session_id
);
974 void CdmWrapper::KeyMessage(int32_t result
,
975 const SessionInfo
& session_info
,
976 const std::string
& message
,
977 const std::string
& default_url
) {
978 PP_DCHECK(result
== PP_OK
);
979 PP_DCHECK(!session_info
.key_system
.empty());
981 pp::VarArrayBuffer
message_array_buffer(message
.size());
982 if (message
.size() > 0) {
983 memcpy(message_array_buffer
.Map(), message
.data(), message
.size());
986 pp::ContentDecryptor_Private::KeyMessage(
987 session_info
.key_system
, session_info
.session_id
,
988 message_array_buffer
, default_url
);
991 void CdmWrapper::KeyError(int32_t result
,
992 const SessionInfo
& session_info
,
993 cdm::MediaKeyError error_code
,
994 uint32_t system_code
) {
995 PP_DCHECK(result
== PP_OK
);
996 PP_DCHECK(!session_info
.key_system
.empty());
997 pp::ContentDecryptor_Private::KeyError(
998 session_info
.key_system
, session_info
.session_id
,
999 error_code
, system_code
);
1002 void CdmWrapper::DeliverBlock(int32_t result
,
1003 const cdm::Status
& status
,
1004 const LinkedDecryptedBlock
& decrypted_block
,
1005 const PP_DecryptTrackingInfo
& tracking_info
) {
1006 PP_DCHECK(result
== PP_OK
);
1007 PP_DecryptedBlockInfo decrypted_block_info
;
1008 decrypted_block_info
.tracking_info
= tracking_info
;
1009 decrypted_block_info
.tracking_info
.timestamp
= decrypted_block
->Timestamp();
1010 decrypted_block_info
.tracking_info
.buffer_id
= 0;
1011 decrypted_block_info
.data_size
= 0;
1012 decrypted_block_info
.result
= CdmStatusToPpDecryptResult(status
);
1014 pp::Buffer_Dev buffer
;
1016 if (decrypted_block_info
.result
== PP_DECRYPTRESULT_SUCCESS
) {
1017 PP_DCHECK(decrypted_block
.get() && decrypted_block
->DecryptedBuffer());
1018 if (!decrypted_block
.get() || !decrypted_block
->DecryptedBuffer()) {
1020 decrypted_block_info
.result
= PP_DECRYPTRESULT_DECRYPT_ERROR
;
1022 PpbBuffer
* ppb_buffer
=
1023 static_cast<PpbBuffer
*>(decrypted_block
->DecryptedBuffer());
1024 buffer
= ppb_buffer
->buffer_dev();
1025 decrypted_block_info
.tracking_info
.buffer_id
= ppb_buffer
->buffer_id();
1026 decrypted_block_info
.data_size
= ppb_buffer
->Size();
1030 pp::ContentDecryptor_Private::DeliverBlock(buffer
, decrypted_block_info
);
1033 void CdmWrapper::DecoderInitializeDone(int32_t result
,
1034 PP_DecryptorStreamType decoder_type
,
1035 uint32_t request_id
,
1037 PP_DCHECK(result
== PP_OK
);
1038 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type
,
1043 void CdmWrapper::DecoderDeinitializeDone(int32_t result
,
1044 PP_DecryptorStreamType decoder_type
,
1045 uint32_t request_id
) {
1046 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type
,
1050 void CdmWrapper::DecoderResetDone(int32_t result
,
1051 PP_DecryptorStreamType decoder_type
,
1052 uint32_t request_id
) {
1053 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type
, request_id
);
1056 void CdmWrapper::DeliverFrame(
1058 const cdm::Status
& status
,
1059 const LinkedVideoFrame
& video_frame
,
1060 const PP_DecryptTrackingInfo
& tracking_info
) {
1061 PP_DCHECK(result
== PP_OK
);
1062 PP_DecryptedFrameInfo decrypted_frame_info
;
1063 decrypted_frame_info
.tracking_info
.request_id
= tracking_info
.request_id
;
1064 decrypted_frame_info
.tracking_info
.buffer_id
= 0;
1065 decrypted_frame_info
.result
= CdmStatusToPpDecryptResult(status
);
1067 pp::Buffer_Dev buffer
;
1069 if (decrypted_frame_info
.result
== PP_DECRYPTRESULT_SUCCESS
) {
1070 if (!IsValidVideoFrame(video_frame
)) {
1072 decrypted_frame_info
.result
= PP_DECRYPTRESULT_DECODE_ERROR
;
1074 PpbBuffer
* ppb_buffer
=
1075 static_cast<PpbBuffer
*>(video_frame
->FrameBuffer());
1077 buffer
= ppb_buffer
->buffer_dev();
1079 decrypted_frame_info
.tracking_info
.timestamp
= video_frame
->Timestamp();
1080 decrypted_frame_info
.tracking_info
.buffer_id
= ppb_buffer
->buffer_id();
1081 decrypted_frame_info
.format
=
1082 CdmVideoFormatToPpDecryptedFrameFormat(video_frame
->Format());
1083 decrypted_frame_info
.width
= video_frame
->Size().width
;
1084 decrypted_frame_info
.height
= video_frame
->Size().height
;
1085 decrypted_frame_info
.plane_offsets
[PP_DECRYPTEDFRAMEPLANES_Y
] =
1086 video_frame
->PlaneOffset(cdm::VideoFrame::kYPlane
);
1087 decrypted_frame_info
.plane_offsets
[PP_DECRYPTEDFRAMEPLANES_U
] =
1088 video_frame
->PlaneOffset(cdm::VideoFrame::kUPlane
);
1089 decrypted_frame_info
.plane_offsets
[PP_DECRYPTEDFRAMEPLANES_V
] =
1090 video_frame
->PlaneOffset(cdm::VideoFrame::kVPlane
);
1091 decrypted_frame_info
.strides
[PP_DECRYPTEDFRAMEPLANES_Y
] =
1092 video_frame
->Stride(cdm::VideoFrame::kYPlane
);
1093 decrypted_frame_info
.strides
[PP_DECRYPTEDFRAMEPLANES_U
] =
1094 video_frame
->Stride(cdm::VideoFrame::kUPlane
);
1095 decrypted_frame_info
.strides
[PP_DECRYPTEDFRAMEPLANES_V
] =
1096 video_frame
->Stride(cdm::VideoFrame::kVPlane
);
1099 pp::ContentDecryptor_Private::DeliverFrame(buffer
, decrypted_frame_info
);
1102 void CdmWrapper::DeliverSamples(int32_t result
,
1103 const cdm::Status
& status
,
1104 const LinkedAudioFrames
& audio_frames
,
1105 const PP_DecryptTrackingInfo
& tracking_info
) {
1106 PP_DCHECK(result
== PP_OK
);
1108 PP_DecryptedBlockInfo decrypted_block_info
;
1109 decrypted_block_info
.tracking_info
= tracking_info
;
1110 decrypted_block_info
.tracking_info
.timestamp
= 0;
1111 decrypted_block_info
.tracking_info
.buffer_id
= 0;
1112 decrypted_block_info
.data_size
= 0;
1113 decrypted_block_info
.result
= CdmStatusToPpDecryptResult(status
);
1115 pp::Buffer_Dev buffer
;
1117 if (decrypted_block_info
.result
== PP_DECRYPTRESULT_SUCCESS
) {
1118 PP_DCHECK(audio_frames
.get() && audio_frames
->FrameBuffer());
1119 if (!audio_frames
.get() || !audio_frames
->FrameBuffer()) {
1121 decrypted_block_info
.result
= PP_DECRYPTRESULT_DECRYPT_ERROR
;
1123 PpbBuffer
* ppb_buffer
=
1124 static_cast<PpbBuffer
*>(audio_frames
->FrameBuffer());
1125 buffer
= ppb_buffer
->buffer_dev();
1126 decrypted_block_info
.tracking_info
.buffer_id
= ppb_buffer
->buffer_id();
1127 decrypted_block_info
.data_size
= ppb_buffer
->Size();
1131 pp::ContentDecryptor_Private::DeliverSamples(buffer
, decrypted_block_info
);
1134 bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame
& video_frame
) {
1135 if (!video_frame
.get() ||
1136 !video_frame
->FrameBuffer() ||
1137 (video_frame
->Format() != cdm::kI420
&&
1138 video_frame
->Format() != cdm::kYv12
)) {
1142 PpbBuffer
* ppb_buffer
= static_cast<PpbBuffer
*>(video_frame
->FrameBuffer());
1144 for (int i
= 0; i
< cdm::VideoFrame::kMaxPlanes
; ++i
) {
1145 int plane_height
= (i
== cdm::VideoFrame::kYPlane
) ?
1146 video_frame
->Size().height
: (video_frame
->Size().height
+ 1) / 2;
1147 cdm::VideoFrame::VideoPlane plane
=
1148 static_cast<cdm::VideoFrame::VideoPlane
>(i
);
1149 if (ppb_buffer
->Size() < video_frame
->PlaneOffset(plane
) +
1150 plane_height
* video_frame
->Stride(plane
)) {
1158 void* GetCdmHost(int host_interface_version
, void* user_data
) {
1159 if (!host_interface_version
|| !user_data
)
1162 if (host_interface_version
!= cdm::kHostInterfaceVersion
)
1165 CdmWrapper
* cdm_wrapper
= static_cast<CdmWrapper
*>(user_data
);
1166 return static_cast<cdm::Host
*>(cdm_wrapper
);
1169 // This object is the global object representing this plugin library as long
1171 class CdmWrapperModule
: public pp::Module
{
1173 CdmWrapperModule() : pp::Module() {
1174 // This function blocks the renderer thread (PluginInstance::Initialize()).
1175 // Move this call to other places if this may be a concern in the future.
1176 INITIALIZE_CDM_MODULE();
1178 virtual ~CdmWrapperModule() {
1179 DeinitializeCdmModule();
1182 virtual pp::Instance
* CreateInstance(PP_Instance instance
) {
1183 return new CdmWrapper(instance
, this);
1187 } // namespace webkit_media
1191 // Factory function for your specialization of the Module object.
1192 Module
* CreateModule() {
1193 return new webkit_media::CdmWrapperModule();