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.
5 #include "content/renderer/pepper/content_decryptor_delegate.h"
7 #include "base/callback_helpers.h"
8 #include "base/debug/trace_event.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/safe_numerics.h"
11 #include "content/renderer/pepper/ppb_buffer_impl.h"
12 #include "media/base/audio_buffer.h"
13 #include "media/base/audio_decoder_config.h"
14 #include "media/base/bind_to_loop.h"
15 #include "media/base/channel_layout.h"
16 #include "media/base/data_buffer.h"
17 #include "media/base/decoder_buffer.h"
18 #include "media/base/decrypt_config.h"
19 #include "media/base/video_decoder_config.h"
20 #include "media/base/video_frame.h"
21 #include "media/base/video_util.h"
22 #include "ppapi/shared_impl/scoped_pp_resource.h"
23 #include "ppapi/shared_impl/var.h"
24 #include "ppapi/shared_impl/var_tracker.h"
25 #include "ppapi/thunk/enter.h"
26 #include "ppapi/thunk/ppb_buffer_api.h"
27 #include "ui/gfx/rect.h"
29 using ppapi::ArrayBufferVar;
30 using ppapi::PpapiGlobals;
31 using ppapi::ScopedPPResource;
32 using ppapi::StringVar;
33 using ppapi::thunk::EnterResourceNoLock;
34 using ppapi::thunk::PPB_Buffer_API;
40 // Fills |resource| with a PPB_Buffer_Impl and copies |data| into the buffer
41 // resource. The |*resource|, if valid, will be in the ResourceTracker with a
42 // reference-count of 0. If |data| is NULL, sets |*resource| to NULL. Returns
43 // true upon success and false if any error happened.
44 bool MakeBufferResource(PP_Instance instance,
45 const uint8* data, uint32_t size,
46 scoped_refptr<PPB_Buffer_Impl>* resource) {
47 TRACE_EVENT0("eme", "ContentDecryptorDelegate - MakeBufferResource");
51 DCHECK(!data && !size);
56 scoped_refptr<PPB_Buffer_Impl> buffer(
57 PPB_Buffer_Impl::CreateResource(instance, size));
61 BufferAutoMapper mapper(buffer.get());
62 if (!mapper.data() || mapper.size() < size)
64 memcpy(mapper.data(), data, size);
70 // Copies the content of |str| into |array|.
71 // Returns true if copy succeeded. Returns false if copy failed, e.g. if the
72 // |array_size| is smaller than the |str| length.
73 template <uint32_t array_size>
74 bool CopyStringToArray(const std::string& str, uint8 (&array)[array_size]) {
75 if (array_size < str.size())
78 memcpy(array, str.data(), str.size());
82 // Fills the |block_info| with information from |encrypted_buffer|.
84 // Returns true if |block_info| is successfully filled. Returns false
86 static bool MakeEncryptedBlockInfo(
87 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
89 PP_EncryptedBlockInfo* block_info) {
90 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and
92 memset(block_info, 0, sizeof(*block_info));
93 block_info->tracking_info.request_id = request_id;
95 // EOS buffers need a request ID and nothing more.
96 if (encrypted_buffer->end_of_stream())
99 DCHECK(encrypted_buffer->data_size())
100 << "DecryptConfig is set on an empty buffer";
102 block_info->tracking_info.timestamp =
103 encrypted_buffer->timestamp().InMicroseconds();
104 block_info->data_size = encrypted_buffer->data_size();
106 const media::DecryptConfig* decrypt_config =
107 encrypted_buffer->decrypt_config();
108 block_info->data_offset = decrypt_config->data_offset();
110 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) ||
111 !CopyStringToArray(decrypt_config->iv(), block_info->iv))
114 block_info->key_id_size = decrypt_config->key_id().size();
115 block_info->iv_size = decrypt_config->iv().size();
117 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples))
120 block_info->num_subsamples = decrypt_config->subsamples().size();
121 for (uint32_t i = 0; i < block_info->num_subsamples; ++i) {
122 block_info->subsamples[i].clear_bytes =
123 decrypt_config->subsamples()[i].clear_bytes;
124 block_info->subsamples[i].cipher_bytes =
125 decrypt_config->subsamples()[i].cypher_bytes;
131 PP_AudioCodec MediaAudioCodecToPpAudioCodec(media::AudioCodec codec) {
133 case media::kCodecVorbis:
134 return PP_AUDIOCODEC_VORBIS;
135 case media::kCodecAAC:
136 return PP_AUDIOCODEC_AAC;
138 return PP_AUDIOCODEC_UNKNOWN;
142 PP_VideoCodec MediaVideoCodecToPpVideoCodec(media::VideoCodec codec) {
144 case media::kCodecVP8:
145 return PP_VIDEOCODEC_VP8;
146 case media::kCodecH264:
147 return PP_VIDEOCODEC_H264;
149 return PP_VIDEOCODEC_UNKNOWN;
153 PP_VideoCodecProfile MediaVideoCodecProfileToPpVideoCodecProfile(
154 media::VideoCodecProfile profile) {
156 case media::VP8PROFILE_MAIN:
157 return PP_VIDEOCODECPROFILE_VP8_MAIN;
158 case media::H264PROFILE_BASELINE:
159 return PP_VIDEOCODECPROFILE_H264_BASELINE;
160 case media::H264PROFILE_MAIN:
161 return PP_VIDEOCODECPROFILE_H264_MAIN;
162 case media::H264PROFILE_EXTENDED:
163 return PP_VIDEOCODECPROFILE_H264_EXTENDED;
164 case media::H264PROFILE_HIGH:
165 return PP_VIDEOCODECPROFILE_H264_HIGH;
166 case media::H264PROFILE_HIGH10PROFILE:
167 return PP_VIDEOCODECPROFILE_H264_HIGH_10;
168 case media::H264PROFILE_HIGH422PROFILE:
169 return PP_VIDEOCODECPROFILE_H264_HIGH_422;
170 case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
171 return PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE;
173 return PP_VIDEOCODECPROFILE_UNKNOWN;
177 PP_DecryptedFrameFormat MediaVideoFormatToPpDecryptedFrameFormat(
178 media::VideoFrame::Format format) {
180 case media::VideoFrame::YV12:
181 return PP_DECRYPTEDFRAMEFORMAT_YV12;
182 case media::VideoFrame::I420:
183 return PP_DECRYPTEDFRAMEFORMAT_I420;
185 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
189 media::Decryptor::Status PpDecryptResultToMediaDecryptorStatus(
190 PP_DecryptResult result) {
192 case PP_DECRYPTRESULT_SUCCESS:
193 return media::Decryptor::kSuccess;
194 case PP_DECRYPTRESULT_DECRYPT_NOKEY:
195 return media::Decryptor::kNoKey;
196 case PP_DECRYPTRESULT_NEEDMOREDATA:
197 return media::Decryptor::kNeedMoreData;
198 case PP_DECRYPTRESULT_DECRYPT_ERROR:
199 return media::Decryptor::kError;
200 case PP_DECRYPTRESULT_DECODE_ERROR:
201 return media::Decryptor::kError;
204 return media::Decryptor::kError;
208 PP_DecryptorStreamType MediaDecryptorStreamTypeToPpStreamType(
209 media::Decryptor::StreamType stream_type) {
210 switch (stream_type) {
211 case media::Decryptor::kAudio:
212 return PP_DECRYPTORSTREAMTYPE_AUDIO;
213 case media::Decryptor::kVideo:
214 return PP_DECRYPTORSTREAMTYPE_VIDEO;
217 return PP_DECRYPTORSTREAMTYPE_VIDEO;
221 media::SampleFormat PpDecryptedSampleFormatToMediaSampleFormat(
222 PP_DecryptedSampleFormat result) {
224 case PP_DECRYPTEDSAMPLEFORMAT_U8:
225 return media::kSampleFormatU8;
226 case PP_DECRYPTEDSAMPLEFORMAT_S16:
227 return media::kSampleFormatS16;
228 case PP_DECRYPTEDSAMPLEFORMAT_S32:
229 return media::kSampleFormatS32;
230 case PP_DECRYPTEDSAMPLEFORMAT_F32:
231 return media::kSampleFormatF32;
232 case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16:
233 return media::kSampleFormatPlanarS16;
234 case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32:
235 return media::kSampleFormatPlanarF32;
238 return media::kUnknownSampleFormat;
244 ContentDecryptorDelegate::ContentDecryptorDelegate(
245 PP_Instance pp_instance,
246 const PPP_ContentDecryptor_Private* plugin_decryption_interface)
247 : pp_instance_(pp_instance),
248 plugin_decryption_interface_(plugin_decryption_interface),
249 next_decryption_request_id_(1),
250 pending_audio_decrypt_request_id_(0),
251 pending_video_decrypt_request_id_(0),
252 pending_audio_decoder_init_request_id_(0),
253 pending_video_decoder_init_request_id_(0),
254 pending_audio_decode_request_id_(0),
255 pending_video_decode_request_id_(0),
256 audio_samples_per_second_(0),
257 audio_channel_count_(0),
258 weak_ptr_factory_(this) {
259 weak_this_ = weak_ptr_factory_.GetWeakPtr();
262 ContentDecryptorDelegate::~ContentDecryptorDelegate() {
265 void ContentDecryptorDelegate::Initialize(const std::string& key_system,
266 bool can_challenge_platform) {
267 DCHECK(!key_system.empty());
268 DCHECK(key_system_.empty());
269 key_system_ = key_system;
271 plugin_decryption_interface_->Initialize(
273 StringVar::StringToPPVar(key_system_),
274 PP_FromBool(can_challenge_platform));
277 void ContentDecryptorDelegate::SetKeyEventCallbacks(
278 const media::KeyAddedCB& key_added_cb,
279 const media::KeyErrorCB& key_error_cb,
280 const media::KeyMessageCB& key_message_cb) {
281 key_added_cb_ = key_added_cb;
282 key_error_cb_ = key_error_cb;
283 key_message_cb_ = key_message_cb;
286 bool ContentDecryptorDelegate::GenerateKeyRequest(const std::string& type,
287 const uint8* init_data,
288 int init_data_length) {
289 PP_Var init_data_array =
290 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
291 init_data_length, init_data);
293 plugin_decryption_interface_->GenerateKeyRequest(
295 StringVar::StringToPPVar(type),
300 bool ContentDecryptorDelegate::AddKey(const std::string& session_id,
303 const uint8* init_data,
304 int init_data_length) {
306 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(key_length,
308 PP_Var init_data_array =
309 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
310 init_data_length, init_data);
312 plugin_decryption_interface_->AddKey(
314 StringVar::StringToPPVar(session_id),
320 bool ContentDecryptorDelegate::CancelKeyRequest(const std::string& session_id) {
321 plugin_decryption_interface_->CancelKeyRequest(
323 StringVar::StringToPPVar(session_id));
327 // TODO(xhwang): Remove duplication of code in Decrypt(),
328 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo().
329 bool ContentDecryptorDelegate::Decrypt(
330 media::Decryptor::StreamType stream_type,
331 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
332 const media::Decryptor::DecryptCB& decrypt_cb) {
333 DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
334 // |{audio|video}_input_resource_| is not being used by the plugin
335 // now because there is only one pending audio/video decrypt request at any
336 // time. This is enforced by the media pipeline.
337 scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
338 if (!MakeMediaBufferResource(
339 stream_type, encrypted_buffer, &encrypted_resource) ||
340 !encrypted_resource.get()) {
343 ScopedPPResource pp_resource(encrypted_resource.get());
345 const uint32_t request_id = next_decryption_request_id_++;
346 DVLOG(2) << "Decrypt() - request_id " << request_id;
348 PP_EncryptedBlockInfo block_info = {};
349 DCHECK(encrypted_buffer->decrypt_config());
350 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
354 // There is only one pending decrypt request at any time per stream. This is
355 // enforced by the media pipeline.
356 switch (stream_type) {
357 case media::Decryptor::kAudio:
358 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u);
359 DCHECK(pending_audio_decrypt_cb_.is_null());
360 pending_audio_decrypt_request_id_ = request_id;
361 pending_audio_decrypt_cb_ = decrypt_cb;
363 case media::Decryptor::kVideo:
364 DCHECK_EQ(pending_video_decrypt_request_id_, 0u);
365 DCHECK(pending_video_decrypt_cb_.is_null());
366 pending_video_decrypt_request_id_ = request_id;
367 pending_video_decrypt_cb_ = decrypt_cb;
374 SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
376 plugin_decryption_interface_->Decrypt(pp_instance_,
382 bool ContentDecryptorDelegate::CancelDecrypt(
383 media::Decryptor::StreamType stream_type) {
384 DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type;
386 media::Decryptor::DecryptCB decrypt_cb;
387 switch (stream_type) {
388 case media::Decryptor::kAudio:
389 // Release the shared memory as it can still be in use by the plugin.
390 // The next Decrypt() call will need to allocate a new shared memory
392 audio_input_resource_ = NULL;
393 pending_audio_decrypt_request_id_ = 0;
394 decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_);
396 case media::Decryptor::kVideo:
397 // Release the shared memory as it can still be in use by the plugin.
398 // The next Decrypt() call will need to allocate a new shared memory
400 video_input_resource_ = NULL;
401 pending_video_decrypt_request_id_ = 0;
402 decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_);
409 if (!decrypt_cb.is_null())
410 decrypt_cb.Run(media::Decryptor::kSuccess, NULL);
415 bool ContentDecryptorDelegate::InitializeAudioDecoder(
416 const media::AudioDecoderConfig& decoder_config,
417 const media::Decryptor::DecoderInitCB& init_cb) {
418 PP_AudioDecoderConfig pp_decoder_config;
419 pp_decoder_config.codec =
420 MediaAudioCodecToPpAudioCodec(decoder_config.codec());
421 pp_decoder_config.channel_count =
422 media::ChannelLayoutToChannelCount(decoder_config.channel_layout());
423 pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel();
424 pp_decoder_config.samples_per_second = decoder_config.samples_per_second();
425 pp_decoder_config.request_id = next_decryption_request_id_++;
427 audio_samples_per_second_ = pp_decoder_config.samples_per_second;
428 audio_channel_count_ = pp_decoder_config.channel_count;
430 scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
431 if (!MakeBufferResource(pp_instance_,
432 decoder_config.extra_data(),
433 decoder_config.extra_data_size(),
434 &extra_data_resource)) {
437 ScopedPPResource pp_resource(extra_data_resource.get());
439 DCHECK_EQ(pending_audio_decoder_init_request_id_, 0u);
440 DCHECK(pending_audio_decoder_init_cb_.is_null());
441 pending_audio_decoder_init_request_id_ = pp_decoder_config.request_id;
442 pending_audio_decoder_init_cb_ = init_cb;
444 plugin_decryption_interface_->InitializeAudioDecoder(pp_instance_,
450 bool ContentDecryptorDelegate::InitializeVideoDecoder(
451 const media::VideoDecoderConfig& decoder_config,
452 const media::Decryptor::DecoderInitCB& init_cb) {
453 PP_VideoDecoderConfig pp_decoder_config;
454 pp_decoder_config.codec =
455 MediaVideoCodecToPpVideoCodec(decoder_config.codec());
456 pp_decoder_config.profile =
457 MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile());
458 pp_decoder_config.format =
459 MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format());
460 pp_decoder_config.width = decoder_config.coded_size().width();
461 pp_decoder_config.height = decoder_config.coded_size().height();
462 pp_decoder_config.request_id = next_decryption_request_id_++;
464 scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
465 if (!MakeBufferResource(pp_instance_,
466 decoder_config.extra_data(),
467 decoder_config.extra_data_size(),
468 &extra_data_resource)) {
471 ScopedPPResource pp_resource(extra_data_resource.get());
473 DCHECK_EQ(pending_video_decoder_init_request_id_, 0u);
474 DCHECK(pending_video_decoder_init_cb_.is_null());
475 pending_video_decoder_init_request_id_ = pp_decoder_config.request_id;
476 pending_video_decoder_init_cb_ = init_cb;
478 natural_size_ = decoder_config.natural_size();
480 plugin_decryption_interface_->InitializeVideoDecoder(pp_instance_,
486 bool ContentDecryptorDelegate::DeinitializeDecoder(
487 media::Decryptor::StreamType stream_type) {
488 CancelDecode(stream_type);
490 natural_size_ = gfx::Size();
492 // TODO(tomfinegan): Add decoder deinitialize request tracking, and get
493 // stream type from media stack.
494 plugin_decryption_interface_->DeinitializeDecoder(
495 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
499 bool ContentDecryptorDelegate::ResetDecoder(
500 media::Decryptor::StreamType stream_type) {
501 CancelDecode(stream_type);
503 // TODO(tomfinegan): Add decoder reset request tracking.
504 plugin_decryption_interface_->ResetDecoder(
505 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
509 bool ContentDecryptorDelegate::DecryptAndDecodeAudio(
510 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
511 const media::Decryptor::AudioDecodeCB& audio_decode_cb) {
512 // |audio_input_resource_| is not being used by the plugin now
513 // because there is only one pending audio decode request at any time.
514 // This is enforced by the media pipeline.
515 scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
516 if (!MakeMediaBufferResource(media::Decryptor::kAudio,
518 &encrypted_resource)) {
522 // The resource should not be NULL for non-EOS buffer.
523 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
526 const uint32_t request_id = next_decryption_request_id_++;
527 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id;
529 PP_EncryptedBlockInfo block_info = {};
530 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
534 SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
536 // There is only one pending audio decode request at any time. This is
537 // enforced by the media pipeline. If this DCHECK is violated, our buffer
538 // reuse policy is not valid, and we may have race problems for the shared
540 DCHECK_EQ(pending_audio_decode_request_id_, 0u);
541 DCHECK(pending_audio_decode_cb_.is_null());
542 pending_audio_decode_request_id_ = request_id;
543 pending_audio_decode_cb_ = audio_decode_cb;
545 ScopedPPResource pp_resource(encrypted_resource.get());
546 plugin_decryption_interface_->DecryptAndDecode(pp_instance_,
547 PP_DECRYPTORSTREAMTYPE_AUDIO,
553 bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
554 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
555 const media::Decryptor::VideoDecodeCB& video_decode_cb) {
556 // |video_input_resource_| is not being used by the plugin now
557 // because there is only one pending video decode request at any time.
558 // This is enforced by the media pipeline.
559 scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
560 if (!MakeMediaBufferResource(media::Decryptor::kVideo,
562 &encrypted_resource)) {
566 // The resource should not be 0 for non-EOS buffer.
567 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
570 const uint32_t request_id = next_decryption_request_id_++;
571 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id;
572 TRACE_EVENT_ASYNC_BEGIN0(
573 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
575 PP_EncryptedBlockInfo block_info = {};
576 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
580 SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
582 // Only one pending video decode request at any time. This is enforced by the
583 // media pipeline. If this DCHECK is violated, our buffer
584 // reuse policy is not valid, and we may have race problems for the shared
586 DCHECK_EQ(pending_video_decode_request_id_, 0u);
587 DCHECK(pending_video_decode_cb_.is_null());
588 pending_video_decode_request_id_ = request_id;
589 pending_video_decode_cb_ = video_decode_cb;
591 // TODO(tomfinegan): Need to get stream type from media stack.
592 ScopedPPResource pp_resource(encrypted_resource.get());
593 plugin_decryption_interface_->DecryptAndDecode(pp_instance_,
594 PP_DECRYPTORSTREAMTYPE_VIDEO,
600 void ContentDecryptorDelegate::NeedKey(PP_Var key_system_var,
601 PP_Var session_id_var,
602 PP_Var init_data_var) {
603 // TODO(ddorwin): Remove from PPB_ContentDecryptor_Private.
607 void ContentDecryptorDelegate::KeyAdded(PP_Var key_system_var,
608 PP_Var session_id_var) {
609 if (key_added_cb_.is_null())
612 StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
613 if (!session_id_string) {
614 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
618 key_added_cb_.Run(session_id_string->value());
621 void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var,
622 PP_Var session_id_var,
624 PP_Var default_url_var) {
625 if (key_message_cb_.is_null())
628 StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
630 ArrayBufferVar* message_array_buffer =
631 ArrayBufferVar::FromPPVar(message_var);
633 std::vector<uint8> message;
634 if (message_array_buffer) {
635 const uint8* data = static_cast<const uint8*>(message_array_buffer->Map());
636 message.assign(data, data + message_array_buffer->ByteLength());
639 StringVar* default_url_string = StringVar::FromPPVar(default_url_var);
641 if (!session_id_string || !default_url_string) {
642 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
646 key_message_cb_.Run(session_id_string->value(),
648 default_url_string->value());
651 void ContentDecryptorDelegate::KeyError(PP_Var key_system_var,
652 PP_Var session_id_var,
654 int32_t system_code) {
655 if (key_error_cb_.is_null())
658 StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
659 if (!session_id_string) {
660 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
664 key_error_cb_.Run(session_id_string->value(),
665 static_cast<media::MediaKeys::KeyError>(media_error),
669 void ContentDecryptorDelegate::DecoderInitializeDone(
670 PP_DecryptorStreamType decoder_type,
673 if (decoder_type == PP_DECRYPTORSTREAMTYPE_AUDIO) {
674 // If the request ID is not valid or does not match what's saved, do
676 if (request_id == 0 ||
677 request_id != pending_audio_decoder_init_request_id_)
680 DCHECK(!pending_audio_decoder_init_cb_.is_null());
681 pending_audio_decoder_init_request_id_ = 0;
682 base::ResetAndReturn(
683 &pending_audio_decoder_init_cb_).Run(PP_ToBool(success));
685 if (request_id == 0 ||
686 request_id != pending_video_decoder_init_request_id_)
690 natural_size_ = gfx::Size();
692 DCHECK(!pending_video_decoder_init_cb_.is_null());
693 pending_video_decoder_init_request_id_ = 0;
694 base::ResetAndReturn(
695 &pending_video_decoder_init_cb_).Run(PP_ToBool(success));
699 void ContentDecryptorDelegate::DecoderDeinitializeDone(
700 PP_DecryptorStreamType decoder_type,
701 uint32_t request_id) {
702 // TODO(tomfinegan): Add decoder stop completion handling.
705 void ContentDecryptorDelegate::DecoderResetDone(
706 PP_DecryptorStreamType decoder_type,
707 uint32_t request_id) {
708 // TODO(tomfinegan): Add decoder reset completion handling.
711 void ContentDecryptorDelegate::DeliverBlock(
712 PP_Resource decrypted_block,
713 const PP_DecryptedBlockInfo* block_info) {
716 FreeBuffer(block_info->tracking_info.buffer_id);
718 const uint32_t request_id = block_info->tracking_info.request_id;
719 DVLOG(2) << "DeliverBlock() - request_id: " << request_id;
721 // If the request ID is not valid or does not match what's saved, do nothing.
722 if (request_id == 0) {
723 DVLOG(1) << "DeliverBlock() - invalid request_id " << request_id;
727 media::Decryptor::DecryptCB decrypt_cb;
728 if (request_id == pending_audio_decrypt_request_id_) {
729 DCHECK(!pending_audio_decrypt_cb_.is_null());
730 pending_audio_decrypt_request_id_ = 0;
731 decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_);
732 } else if (request_id == pending_video_decrypt_request_id_) {
733 DCHECK(!pending_video_decrypt_cb_.is_null());
734 pending_video_decrypt_request_id_ = 0;
735 decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_);
737 DVLOG(1) << "DeliverBlock() - request_id " << request_id << " not found";
741 media::Decryptor::Status status =
742 PpDecryptResultToMediaDecryptorStatus(block_info->result);
743 if (status != media::Decryptor::kSuccess) {
744 decrypt_cb.Run(status, NULL);
748 EnterResourceNoLock<PPB_Buffer_API> enter(decrypted_block, true);
749 if (!enter.succeeded()) {
750 decrypt_cb.Run(media::Decryptor::kError, NULL);
753 BufferAutoMapper mapper(enter.object());
754 if (!mapper.data() || !mapper.size() ||
755 mapper.size() < block_info->data_size) {
756 decrypt_cb.Run(media::Decryptor::kError, NULL);
760 // TODO(tomfinegan): Find a way to take ownership of the shared memory
761 // managed by the PPB_Buffer_Dev, and avoid the extra copy.
762 scoped_refptr<media::DecoderBuffer> decrypted_buffer(
763 media::DecoderBuffer::CopyFrom(
764 static_cast<uint8*>(mapper.data()), block_info->data_size));
765 decrypted_buffer->set_timestamp(base::TimeDelta::FromMicroseconds(
766 block_info->tracking_info.timestamp));
767 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer);
770 // Use a non-class-member function here so that if for some reason
771 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback,
772 // we can still get the shared memory unmapped.
773 static void BufferNoLongerNeeded(
774 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer,
775 base::Closure buffer_no_longer_needed_cb) {
777 buffer_no_longer_needed_cb.Run();
780 // Enters |resource|, maps shared memory and returns pointer of mapped data.
781 // Returns NULL if any error occurs.
782 static uint8* GetMappedBuffer(PP_Resource resource,
783 scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) {
784 EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
785 if (!enter.succeeded())
788 uint8* mapped_data = static_cast<uint8*>(enter.object()->Map());
789 if (!enter.object()->IsMapped() || !mapped_data)
792 uint32_t mapped_size = 0;
793 if (!enter.object()->Describe(&mapped_size) || !mapped_size) {
794 enter.object()->Unmap();
798 *ppb_buffer = static_cast<PPB_Buffer_Impl*>(enter.object());
803 void ContentDecryptorDelegate::DeliverFrame(
804 PP_Resource decrypted_frame,
805 const PP_DecryptedFrameInfo* frame_info) {
808 const uint32_t request_id = frame_info->tracking_info.request_id;
809 DVLOG(2) << "DeliverFrame() - request_id: " << request_id;
811 // If the request ID is not valid or does not match what's saved, do nothing.
812 if (request_id == 0 || request_id != pending_video_decode_request_id_) {
813 DVLOG(1) << "DeliverFrame() - request_id " << request_id << " not found";
814 FreeBuffer(frame_info->tracking_info.buffer_id);
818 TRACE_EVENT_ASYNC_END0(
819 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
821 DCHECK(!pending_video_decode_cb_.is_null());
822 pending_video_decode_request_id_ = 0;
823 media::Decryptor::VideoDecodeCB video_decode_cb =
824 base::ResetAndReturn(&pending_video_decode_cb_);
826 media::Decryptor::Status status =
827 PpDecryptResultToMediaDecryptorStatus(frame_info->result);
828 if (status != media::Decryptor::kSuccess) {
829 DCHECK(!frame_info->tracking_info.buffer_id);
830 video_decode_cb.Run(status, NULL);
834 scoped_refptr<PPB_Buffer_Impl> ppb_buffer;
835 uint8* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer);
837 FreeBuffer(frame_info->tracking_info.buffer_id);
838 video_decode_cb.Run(media::Decryptor::kError, NULL);
842 gfx::Size frame_size(frame_info->width, frame_info->height);
843 DCHECK_EQ(frame_info->format, PP_DECRYPTEDFRAMEFORMAT_YV12);
845 scoped_refptr<media::VideoFrame> decoded_frame =
846 media::VideoFrame::WrapExternalYuvData(
847 media::VideoFrame::YV12,
849 gfx::Rect(frame_size),
851 frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y],
852 frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U],
853 frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V],
854 frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y],
855 frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_U],
856 frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V],
857 base::TimeDelta::FromMicroseconds(
858 frame_info->tracking_info.timestamp),
860 base::MessageLoopProxy::current(),
861 base::Bind(&BufferNoLongerNeeded,
863 base::Bind(&ContentDecryptorDelegate::FreeBuffer,
865 frame_info->tracking_info.buffer_id))));
867 video_decode_cb.Run(media::Decryptor::kSuccess, decoded_frame);
870 void ContentDecryptorDelegate::DeliverSamples(
871 PP_Resource audio_frames,
872 const PP_DecryptedSampleInfo* sample_info) {
875 FreeBuffer(sample_info->tracking_info.buffer_id);
877 const uint32_t request_id = sample_info->tracking_info.request_id;
878 DVLOG(2) << "DeliverSamples() - request_id: " << request_id;
880 // If the request ID is not valid or does not match what's saved, do nothing.
881 if (request_id == 0 || request_id != pending_audio_decode_request_id_) {
882 DVLOG(1) << "DeliverSamples() - request_id " << request_id << " not found";
886 DCHECK(!pending_audio_decode_cb_.is_null());
887 pending_audio_decode_request_id_ = 0;
888 media::Decryptor::AudioDecodeCB audio_decode_cb =
889 base::ResetAndReturn(&pending_audio_decode_cb_);
891 const media::Decryptor::AudioBuffers empty_frames;
893 media::Decryptor::Status status =
894 PpDecryptResultToMediaDecryptorStatus(sample_info->result);
895 if (status != media::Decryptor::kSuccess) {
896 audio_decode_cb.Run(status, empty_frames);
900 media::SampleFormat sample_format =
901 PpDecryptedSampleFormatToMediaSampleFormat(sample_info->format);
903 media::Decryptor::AudioBuffers audio_frame_list;
904 if (!DeserializeAudioFrames(audio_frames,
905 sample_info->data_size,
907 &audio_frame_list)) {
908 NOTREACHED() << "CDM did not serialize the buffer correctly.";
909 audio_decode_cb.Run(media::Decryptor::kError, empty_frames);
913 audio_decode_cb.Run(media::Decryptor::kSuccess, audio_frame_list);
916 // TODO(xhwang): Try to remove duplicate logic here and in CancelDecrypt().
917 void ContentDecryptorDelegate::CancelDecode(
918 media::Decryptor::StreamType stream_type) {
919 switch (stream_type) {
920 case media::Decryptor::kAudio:
921 // Release the shared memory as it can still be in use by the plugin.
922 // The next DecryptAndDecode() call will need to allocate a new shared
924 audio_input_resource_ = NULL;
925 pending_audio_decode_request_id_ = 0;
926 if (!pending_audio_decode_cb_.is_null())
927 base::ResetAndReturn(&pending_audio_decode_cb_).Run(
928 media::Decryptor::kSuccess, media::Decryptor::AudioBuffers());
930 case media::Decryptor::kVideo:
931 // Release the shared memory as it can still be in use by the plugin.
932 // The next DecryptAndDecode() call will need to allocate a new shared
934 video_input_resource_ = NULL;
935 pending_video_decode_request_id_ = 0;
936 if (!pending_video_decode_cb_.is_null())
937 base::ResetAndReturn(&pending_video_decode_cb_).Run(
938 media::Decryptor::kSuccess, NULL);
945 bool ContentDecryptorDelegate::MakeMediaBufferResource(
946 media::Decryptor::StreamType stream_type,
947 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
948 scoped_refptr<PPB_Buffer_Impl>* resource) {
949 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource");
951 // End of stream buffers are represented as null resources.
952 if (encrypted_buffer->end_of_stream()) {
957 DCHECK(stream_type == media::Decryptor::kAudio ||
958 stream_type == media::Decryptor::kVideo);
959 scoped_refptr<PPB_Buffer_Impl>& media_resource =
960 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ :
961 video_input_resource_;
963 const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size());
964 if (!media_resource.get() || media_resource->size() < data_size) {
965 // Either the buffer hasn't been created yet, or we have one that isn't big
966 // enough to fit |size| bytes.
968 // Media resource size starts from |kMinimumMediaBufferSize| and grows
969 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl,
970 // which is usually expensive. Since input media buffers are compressed,
971 // they are usually small (compared to outputs). The over-allocated memory
972 // should be negligible.
973 const uint32_t kMinimumMediaBufferSize = 1024;
974 uint32_t media_resource_size =
975 media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize;
976 while (media_resource_size < data_size)
977 media_resource_size *= 2;
979 DVLOG(2) << "Size of media buffer for "
980 << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video")
981 << " stream bumped to " << media_resource_size
982 << " bytes to fit input.";
983 media_resource = PPB_Buffer_Impl::CreateResource(pp_instance_,
984 media_resource_size);
985 if (!media_resource.get())
989 BufferAutoMapper mapper(media_resource.get());
990 if (!mapper.data() || mapper.size() < data_size) {
991 media_resource = NULL;
994 memcpy(mapper.data(), encrypted_buffer->data(), data_size);
996 *resource = media_resource;
1000 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) {
1002 free_buffers_.push(buffer_id);
1005 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo(
1006 PP_DecryptTrackingInfo* tracking_info) {
1007 DCHECK_EQ(tracking_info->buffer_id, 0u);
1009 if (free_buffers_.empty())
1012 tracking_info->buffer_id = free_buffers_.front();
1013 free_buffers_.pop();
1016 bool ContentDecryptorDelegate::DeserializeAudioFrames(
1017 PP_Resource audio_frames,
1019 media::SampleFormat sample_format,
1020 media::Decryptor::AudioBuffers* frames) {
1022 EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true);
1023 if (!enter.succeeded())
1026 BufferAutoMapper mapper(enter.object());
1027 if (!mapper.data() || !mapper.size() ||
1028 mapper.size() < static_cast<uint32_t>(data_size))
1031 // TODO(jrummell): Pass ownership of data() directly to AudioBuffer to avoid
1032 // the copy. Since it is possible to get multiple buffers, it would need to be
1033 // sliced and ref counted appropriately. http://crbug.com/255576.
1034 const uint8* cur = static_cast<uint8*>(mapper.data());
1035 size_t bytes_left = data_size;
1037 const int audio_bytes_per_frame =
1038 media::SampleFormatToBytesPerChannel(sample_format) *
1039 audio_channel_count_;
1041 // Allocate space for the channel pointers given to AudioBuffer.
1042 std::vector<const uint8*> channel_ptrs(
1043 audio_channel_count_, static_cast<const uint8*>(NULL));
1045 int64 timestamp = 0;
1046 int64 frame_size = -1;
1047 const size_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
1049 if (bytes_left < kHeaderSize)
1052 memcpy(×tamp, cur, sizeof(timestamp));
1053 cur += sizeof(timestamp);
1054 bytes_left -= sizeof(timestamp);
1056 memcpy(&frame_size, cur, sizeof(frame_size));
1057 cur += sizeof(frame_size);
1058 bytes_left -= sizeof(frame_size);
1060 // We should *not* have empty frames in the list.
1061 if (frame_size <= 0 ||
1062 bytes_left < base::checked_numeric_cast<size_t>(frame_size)) {
1066 // Setup channel pointers. AudioBuffer::CopyFrom() will only use the first
1067 // one in the case of interleaved data.
1068 const int size_per_channel = frame_size / audio_channel_count_;
1069 for (int i = 0; i < audio_channel_count_; ++i)
1070 channel_ptrs[i] = cur + i * size_per_channel;
1072 const int frame_count = frame_size / audio_bytes_per_frame;
1073 scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
1075 audio_channel_count_,
1078 base::TimeDelta::FromMicroseconds(timestamp),
1079 base::TimeDelta::FromMicroseconds(audio_samples_per_second_ /
1081 frames->push_back(frame);
1084 bytes_left -= frame_size;
1085 } while (bytes_left > 0);
1090 } // namespace content