content_decryptor_delegate.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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. 4 5#include "content/renderer/pepper/content_decryptor_delegate.h" 6 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" 28 29using ppapi::ArrayBufferVar; 30using ppapi::PpapiGlobals; 31using ppapi::ScopedPPResource; 32using ppapi::StringVar; 33using ppapi::thunk::EnterResourceNoLock; 34using ppapi::thunk::PPB_Buffer_API; 35 36namespace content { 37 38namespace { 39 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. 44bool MakeBufferResource(PP_Instance instance, 45 const uint8* data, uint32_t size, 46 scoped_refptr<PPB_Buffer_Impl>* resource) { 47 TRACE_EVENT0("eme", "ContentDecryptorDelegate - MakeBufferResource"); 48 DCHECK(resource); 49 50 if (!data || !size) { 51 DCHECK(!data && !size); 52 resource = NULL; 53 return true; 54 } 55 56 scoped_refptr<PPB_Buffer_Impl> buffer( 57 PPB_Buffer_Impl::CreateResource(instance, size)); 58 if (!buffer.get()) 59 return false; 60 61 BufferAutoMapper mapper(buffer.get()); 62 if (!mapper.data() || mapper.size() < size) 63 return false; 64 memcpy(mapper.data(), data, size); 65 66 *resource = buffer; 67 return true; 68} 69 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. 73template <uint32_t array_size> 74bool CopyStringToArray(const std::string& str, uint8 (&array)[array_size]) { 75 if (array_size < str.size()) 76 return false; 77 78 memcpy(array, str.data(), str.size()); 79 return true; 80} 81 82// Fills the |block_info| with information from |encrypted_buffer|. 83// 84// Returns true if |block_info| is successfully filled. Returns false 85// otherwise. 86static bool MakeEncryptedBlockInfo( 87 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 88 uint32_t request_id, 89 PP_EncryptedBlockInfo* block_info) { 90 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and 91 // anywhere else. 92 memset(block_info, 0, sizeof(*block_info)); 93 block_info->tracking_info.request_id = request_id; 94 95 // EOS buffers need a request ID and nothing more. 96 if (encrypted_buffer->end_of_stream()) 97 return true; 98 99 DCHECK(encrypted_buffer->data_size()) 100 << "DecryptConfig is set on an empty buffer"; 101 102 block_info->tracking_info.timestamp = 103 encrypted_buffer->timestamp().InMicroseconds(); 104 block_info->data_size = encrypted_buffer->data_size(); 105 106 const media::DecryptConfig* decrypt_config = 107 encrypted_buffer->decrypt_config(); 108 block_info->data_offset = decrypt_config->data_offset(); 109 110 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || 111 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) 112 return false; 113 114 block_info->key_id_size = decrypt_config->key_id().size(); 115 block_info->iv_size = decrypt_config->iv().size(); 116 117 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) 118 return false; 119 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; 126 } 127 128 return true; 129} 130 131PP_AudioCodec MediaAudioCodecToPpAudioCodec(media::AudioCodec codec) { 132 switch (codec) { 133 case media::kCodecVorbis: 134 return PP_AUDIOCODEC_VORBIS; 135 case media::kCodecAAC: 136 return PP_AUDIOCODEC_AAC; 137 default: 138 return PP_AUDIOCODEC_UNKNOWN; 139 } 140} 141 142PP_VideoCodec MediaVideoCodecToPpVideoCodec(media::VideoCodec codec) { 143 switch (codec) { 144 case media::kCodecVP8: 145 return PP_VIDEOCODEC_VP8; 146 case media::kCodecH264: 147 return PP_VIDEOCODEC_H264; 148 default: 149 return PP_VIDEOCODEC_UNKNOWN; 150 } 151} 152 153PP_VideoCodecProfile MediaVideoCodecProfileToPpVideoCodecProfile( 154 media::VideoCodecProfile profile) { 155 switch (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; 172 default: 173 return PP_VIDEOCODECPROFILE_UNKNOWN; 174 } 175} 176 177PP_DecryptedFrameFormat MediaVideoFormatToPpDecryptedFrameFormat( 178 media::VideoFrame::Format format) { 179 switch (format) { 180 case media::VideoFrame::YV12: 181 return PP_DECRYPTEDFRAMEFORMAT_YV12; 182 case media::VideoFrame::I420: 183 return PP_DECRYPTEDFRAMEFORMAT_I420; 184 default: 185 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN; 186 } 187} 188 189media::Decryptor::Status PpDecryptResultToMediaDecryptorStatus( 190 PP_DecryptResult result) { 191 switch (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; 202 default: 203 NOTREACHED(); 204 return media::Decryptor::kError; 205 } 206} 207 208PP_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; 215 default: 216 NOTREACHED(); 217 return PP_DECRYPTORSTREAMTYPE_VIDEO; 218 } 219} 220 221} // namespace 222 223ContentDecryptorDelegate::ContentDecryptorDelegate( 224 PP_Instance pp_instance, 225 const PPP_ContentDecryptor_Private* plugin_decryption_interface) 226 : pp_instance_(pp_instance), 227 plugin_decryption_interface_(plugin_decryption_interface), 228 next_decryption_request_id_(1), 229 pending_audio_decrypt_request_id_(0), 230 pending_video_decrypt_request_id_(0), 231 pending_audio_decoder_init_request_id_(0), 232 pending_video_decoder_init_request_id_(0), 233 pending_audio_decode_request_id_(0), 234 pending_video_decode_request_id_(0), 235 weak_ptr_factory_(this), 236 weak_this_(weak_ptr_factory_.GetWeakPtr()), 237 audio_sample_format_(media::kUnknownSampleFormat), 238 audio_samples_per_second_(0), 239 audio_channel_count_(0), 240 audio_bytes_per_frame_(0) { 241} 242 243ContentDecryptorDelegate::~ContentDecryptorDelegate() { 244} 245 246void ContentDecryptorDelegate::Initialize(const std::string& key_system, 247 bool can_challenge_platform) { 248 DCHECK(!key_system.empty()); 249 DCHECK(key_system_.empty()); 250 key_system_ = key_system; 251 252 plugin_decryption_interface_->Initialize( 253 pp_instance_, 254 StringVar::StringToPPVar(key_system_), 255 PP_FromBool(can_challenge_platform)); 256} 257 258void ContentDecryptorDelegate::SetKeyEventCallbacks( 259 const media::KeyAddedCB& key_added_cb, 260 const media::KeyErrorCB& key_error_cb, 261 const media::KeyMessageCB& key_message_cb) { 262 key_added_cb_ = key_added_cb; 263 key_error_cb_ = key_error_cb; 264 key_message_cb_ = key_message_cb; 265} 266 267bool ContentDecryptorDelegate::GenerateKeyRequest(const std::string& type, 268 const uint8* init_data, 269 int init_data_length) { 270 PP_Var init_data_array = 271 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( 272 init_data_length, init_data); 273 274 plugin_decryption_interface_->GenerateKeyRequest( 275 pp_instance_, 276 StringVar::StringToPPVar(type), 277 init_data_array); 278 return true; 279} 280 281bool ContentDecryptorDelegate::AddKey(const std::string& session_id, 282 const uint8* key, 283 int key_length, 284 const uint8* init_data, 285 int init_data_length) { 286 PP_Var key_array = 287 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(key_length, 288 key); 289 PP_Var init_data_array = 290 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( 291 init_data_length, init_data); 292 293 plugin_decryption_interface_->AddKey( 294 pp_instance_, 295 StringVar::StringToPPVar(session_id), 296 key_array, 297 init_data_array); 298 return true; 299} 300 301bool ContentDecryptorDelegate::CancelKeyRequest(const std::string& session_id) { 302 plugin_decryption_interface_->CancelKeyRequest( 303 pp_instance_, 304 StringVar::StringToPPVar(session_id)); 305 return true; 306} 307 308// TODO(xhwang): Remove duplication of code in Decrypt(), 309// DecryptAndDecodeAudio() and DecryptAndDecodeVideo(). 310bool ContentDecryptorDelegate::Decrypt( 311 media::Decryptor::StreamType stream_type, 312 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 313 const media::Decryptor::DecryptCB& decrypt_cb) { 314 DVLOG(3) << "Decrypt() - stream_type: " << stream_type; 315 // |{audio|video}_input_resource_| is not being used by the plugin 316 // now because there is only one pending audio/video decrypt request at any 317 // time. This is enforced by the media pipeline. 318 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; 319 if (!MakeMediaBufferResource( 320 stream_type, encrypted_buffer, &encrypted_resource) || 321 !encrypted_resource.get()) { 322 return false; 323 } 324 ScopedPPResource pp_resource(encrypted_resource.get()); 325 326 const uint32_t request_id = next_decryption_request_id_++; 327 DVLOG(2) << "Decrypt() - request_id " << request_id; 328 329 PP_EncryptedBlockInfo block_info = {}; 330 DCHECK(encrypted_buffer->decrypt_config()); 331 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { 332 return false; 333 } 334 335 // There is only one pending decrypt request at any time per stream. This is 336 // enforced by the media pipeline. 337 switch (stream_type) { 338 case media::Decryptor::kAudio: 339 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); 340 DCHECK(pending_audio_decrypt_cb_.is_null()); 341 pending_audio_decrypt_request_id_ = request_id; 342 pending_audio_decrypt_cb_ = decrypt_cb; 343 break; 344 case media::Decryptor::kVideo: 345 DCHECK_EQ(pending_video_decrypt_request_id_, 0u); 346 DCHECK(pending_video_decrypt_cb_.is_null()); 347 pending_video_decrypt_request_id_ = request_id; 348 pending_video_decrypt_cb_ = decrypt_cb; 349 break; 350 default: 351 NOTREACHED(); 352 return false; 353 } 354 355 SetBufferToFreeInTrackingInfo(&block_info.tracking_info); 356 357 plugin_decryption_interface_->Decrypt(pp_instance_, 358 pp_resource, 359 &block_info); 360 return true; 361} 362 363bool ContentDecryptorDelegate::CancelDecrypt( 364 media::Decryptor::StreamType stream_type) { 365 DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type; 366 367 media::Decryptor::DecryptCB decrypt_cb; 368 switch (stream_type) { 369 case media::Decryptor::kAudio: 370 // Release the shared memory as it can still be in use by the plugin. 371 // The next Decrypt() call will need to allocate a new shared memory 372 // buffer. 373 audio_input_resource_ = NULL; 374 pending_audio_decrypt_request_id_ = 0; 375 decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_); 376 break; 377 case media::Decryptor::kVideo: 378 // Release the shared memory as it can still be in use by the plugin. 379 // The next Decrypt() call will need to allocate a new shared memory 380 // buffer. 381 video_input_resource_ = NULL; 382 pending_video_decrypt_request_id_ = 0; 383 decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_); 384 break; 385 default: 386 NOTREACHED(); 387 return false; 388 } 389 390 if (!decrypt_cb.is_null()) 391 decrypt_cb.Run(media::Decryptor::kSuccess, NULL); 392 393 return true; 394} 395 396bool ContentDecryptorDelegate::InitializeAudioDecoder( 397 const media::AudioDecoderConfig& decoder_config, 398 const media::Decryptor::DecoderInitCB& init_cb) { 399 PP_AudioDecoderConfig pp_decoder_config; 400 pp_decoder_config.codec = 401 MediaAudioCodecToPpAudioCodec(decoder_config.codec()); 402 pp_decoder_config.channel_count = 403 media::ChannelLayoutToChannelCount(decoder_config.channel_layout()); 404 pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel(); 405 pp_decoder_config.samples_per_second = decoder_config.samples_per_second(); 406 pp_decoder_config.request_id = next_decryption_request_id_++; 407 408 audio_sample_format_ = decoder_config.sample_format(); 409 audio_samples_per_second_ = pp_decoder_config.samples_per_second; 410 audio_channel_count_ = pp_decoder_config.channel_count; 411 audio_bytes_per_frame_ = decoder_config.bytes_per_frame(); 412 413 scoped_refptr<PPB_Buffer_Impl> extra_data_resource; 414 if (!MakeBufferResource(pp_instance_, 415 decoder_config.extra_data(), 416 decoder_config.extra_data_size(), 417 &extra_data_resource)) { 418 return false; 419 } 420 ScopedPPResource pp_resource(extra_data_resource.get()); 421 422 DCHECK_EQ(pending_audio_decoder_init_request_id_, 0u); 423 DCHECK(pending_audio_decoder_init_cb_.is_null()); 424 pending_audio_decoder_init_request_id_ = pp_decoder_config.request_id; 425 pending_audio_decoder_init_cb_ = init_cb; 426 427 plugin_decryption_interface_->InitializeAudioDecoder(pp_instance_, 428 &pp_decoder_config, 429 pp_resource); 430 return true; 431} 432 433bool ContentDecryptorDelegate::InitializeVideoDecoder( 434 const media::VideoDecoderConfig& decoder_config, 435 const media::Decryptor::DecoderInitCB& init_cb) { 436 PP_VideoDecoderConfig pp_decoder_config; 437 pp_decoder_config.codec = 438 MediaVideoCodecToPpVideoCodec(decoder_config.codec()); 439 pp_decoder_config.profile = 440 MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile()); 441 pp_decoder_config.format = 442 MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format()); 443 pp_decoder_config.width = decoder_config.coded_size().width(); 444 pp_decoder_config.height = decoder_config.coded_size().height(); 445 pp_decoder_config.request_id = next_decryption_request_id_++; 446 447 scoped_refptr<PPB_Buffer_Impl> extra_data_resource; 448 if (!MakeBufferResource(pp_instance_, 449 decoder_config.extra_data(), 450 decoder_config.extra_data_size(), 451 &extra_data_resource)) { 452 return false; 453 } 454 ScopedPPResource pp_resource(extra_data_resource.get()); 455 456 DCHECK_EQ(pending_video_decoder_init_request_id_, 0u); 457 DCHECK(pending_video_decoder_init_cb_.is_null()); 458 pending_video_decoder_init_request_id_ = pp_decoder_config.request_id; 459 pending_video_decoder_init_cb_ = init_cb; 460 461 natural_size_ = decoder_config.natural_size(); 462 463 plugin_decryption_interface_->InitializeVideoDecoder(pp_instance_, 464 &pp_decoder_config, 465 pp_resource); 466 return true; 467} 468 469bool ContentDecryptorDelegate::DeinitializeDecoder( 470 media::Decryptor::StreamType stream_type) { 471 CancelDecode(stream_type); 472 473 natural_size_ = gfx::Size(); 474 475 // TODO(tomfinegan): Add decoder deinitialize request tracking, and get 476 // stream type from media stack. 477 plugin_decryption_interface_->DeinitializeDecoder( 478 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0); 479 return true; 480} 481 482bool ContentDecryptorDelegate::ResetDecoder( 483 media::Decryptor::StreamType stream_type) { 484 CancelDecode(stream_type); 485 486 // TODO(tomfinegan): Add decoder reset request tracking. 487 plugin_decryption_interface_->ResetDecoder( 488 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0); 489 return true; 490} 491 492bool ContentDecryptorDelegate::DecryptAndDecodeAudio( 493 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 494 const media::Decryptor::AudioDecodeCB& audio_decode_cb) { 495 // |audio_input_resource_| is not being used by the plugin now 496 // because there is only one pending audio decode request at any time. 497 // This is enforced by the media pipeline. 498 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; 499 if (!MakeMediaBufferResource(media::Decryptor::kAudio, 500 encrypted_buffer, 501 &encrypted_resource)) { 502 return false; 503 } 504 505 // The resource should not be NULL for non-EOS buffer. 506 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get()) 507 return false; 508 509 const uint32_t request_id = next_decryption_request_id_++; 510 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; 511 512 PP_EncryptedBlockInfo block_info = {}; 513 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { 514 return false; 515 } 516 517 SetBufferToFreeInTrackingInfo(&block_info.tracking_info); 518 519 // There is only one pending audio decode request at any time. This is 520 // enforced by the media pipeline. If this DCHECK is violated, our buffer 521 // reuse policy is not valid, and we may have race problems for the shared 522 // buffer. 523 DCHECK_EQ(pending_audio_decode_request_id_, 0u); 524 DCHECK(pending_audio_decode_cb_.is_null()); 525 pending_audio_decode_request_id_ = request_id; 526 pending_audio_decode_cb_ = audio_decode_cb; 527 528 ScopedPPResource pp_resource(encrypted_resource.get()); 529 plugin_decryption_interface_->DecryptAndDecode(pp_instance_, 530 PP_DECRYPTORSTREAMTYPE_AUDIO, 531 pp_resource, 532 &block_info); 533 return true; 534} 535 536bool ContentDecryptorDelegate::DecryptAndDecodeVideo( 537 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 538 const media::Decryptor::VideoDecodeCB& video_decode_cb) { 539 // |video_input_resource_| is not being used by the plugin now 540 // because there is only one pending video decode request at any time. 541 // This is enforced by the media pipeline. 542 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; 543 if (!MakeMediaBufferResource(media::Decryptor::kVideo, 544 encrypted_buffer, 545 &encrypted_resource)) { 546 return false; 547 } 548 549 // The resource should not be 0 for non-EOS buffer. 550 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get()) 551 return false; 552 553 const uint32_t request_id = next_decryption_request_id_++; 554 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; 555 TRACE_EVENT_ASYNC_BEGIN0( 556 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); 557 558 PP_EncryptedBlockInfo block_info = {}; 559 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { 560 return false; 561 } 562 563 SetBufferToFreeInTrackingInfo(&block_info.tracking_info); 564 565 // Only one pending video decode request at any time. This is enforced by the 566 // media pipeline. If this DCHECK is violated, our buffer 567 // reuse policy is not valid, and we may have race problems for the shared 568 // buffer. 569 DCHECK_EQ(pending_video_decode_request_id_, 0u); 570 DCHECK(pending_video_decode_cb_.is_null()); 571 pending_video_decode_request_id_ = request_id; 572 pending_video_decode_cb_ = video_decode_cb; 573 574 // TODO(tomfinegan): Need to get stream type from media stack. 575 ScopedPPResource pp_resource(encrypted_resource.get()); 576 plugin_decryption_interface_->DecryptAndDecode(pp_instance_, 577 PP_DECRYPTORSTREAMTYPE_VIDEO, 578 pp_resource, 579 &block_info); 580 return true; 581} 582 583void ContentDecryptorDelegate::NeedKey(PP_Var key_system_var, 584 PP_Var session_id_var, 585 PP_Var init_data_var) { 586 // TODO(ddorwin): Remove from PPB_ContentDecryptor_Private. 587 NOTREACHED(); 588} 589 590void ContentDecryptorDelegate::KeyAdded(PP_Var key_system_var, 591 PP_Var session_id_var) { 592 if (key_added_cb_.is_null()) 593 return; 594 595 StringVar* session_id_string = StringVar::FromPPVar(session_id_var); 596 if (!session_id_string) { 597 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); 598 return; 599 } 600 601 key_added_cb_.Run(session_id_string->value()); 602} 603 604void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var, 605 PP_Var session_id_var, 606 PP_Var message_var, 607 PP_Var default_url_var) { 608 if (key_message_cb_.is_null()) 609 return; 610 611 StringVar* session_id_string = StringVar::FromPPVar(session_id_var); 612 613 ArrayBufferVar* message_array_buffer = 614 ArrayBufferVar::FromPPVar(message_var); 615 616 std::vector<uint8> message; 617 if (message_array_buffer) { 618 const uint8* data = static_cast<const uint8*>(message_array_buffer->Map()); 619 message.assign(data, data + message_array_buffer->ByteLength()); 620 } 621 622 StringVar* default_url_string = StringVar::FromPPVar(default_url_var); 623 624 if (!session_id_string || !default_url_string) { 625 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); 626 return; 627 } 628 629 key_message_cb_.Run(session_id_string->value(), 630 message, 631 default_url_string->value()); 632} 633 634void ContentDecryptorDelegate::KeyError(PP_Var key_system_var, 635 PP_Var session_id_var, 636 int32_t media_error, 637 int32_t system_code) { 638 if (key_error_cb_.is_null()) 639 return; 640 641 StringVar* session_id_string = StringVar::FromPPVar(session_id_var); 642 if (!session_id_string) { 643 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); 644 return; 645 } 646 647 key_error_cb_.Run(session_id_string->value(), 648 static_cast<media::MediaKeys::KeyError>(media_error), 649 system_code); 650} 651 652void ContentDecryptorDelegate::DecoderInitializeDone( 653 PP_DecryptorStreamType decoder_type, 654 uint32_t request_id, 655 PP_Bool success) { 656 if (decoder_type == PP_DECRYPTORSTREAMTYPE_AUDIO) { 657 // If the request ID is not valid or does not match what's saved, do 658 // nothing. 659 if (request_id == 0 || 660 request_id != pending_audio_decoder_init_request_id_) 661 return; 662 663 DCHECK(!pending_audio_decoder_init_cb_.is_null()); 664 pending_audio_decoder_init_request_id_ = 0; 665 base::ResetAndReturn( 666 &pending_audio_decoder_init_cb_).Run(PP_ToBool(success)); 667 } else { 668 if (request_id == 0 || 669 request_id != pending_video_decoder_init_request_id_) 670 return; 671 672 if (!success) 673 natural_size_ = gfx::Size(); 674 675 DCHECK(!pending_video_decoder_init_cb_.is_null()); 676 pending_video_decoder_init_request_id_ = 0; 677 base::ResetAndReturn( 678 &pending_video_decoder_init_cb_).Run(PP_ToBool(success)); 679 } 680} 681 682void ContentDecryptorDelegate::DecoderDeinitializeDone( 683 PP_DecryptorStreamType decoder_type, 684 uint32_t request_id) { 685 // TODO(tomfinegan): Add decoder stop completion handling. 686} 687 688void ContentDecryptorDelegate::DecoderResetDone( 689 PP_DecryptorStreamType decoder_type, 690 uint32_t request_id) { 691 // TODO(tomfinegan): Add decoder reset completion handling. 692} 693 694void ContentDecryptorDelegate::DeliverBlock( 695 PP_Resource decrypted_block, 696 const PP_DecryptedBlockInfo* block_info) { 697 DCHECK(block_info); 698 699 FreeBuffer(block_info->tracking_info.buffer_id); 700 701 const uint32_t request_id = block_info->tracking_info.request_id; 702 DVLOG(2) << "DeliverBlock() - request_id: " << request_id; 703 704 // If the request ID is not valid or does not match what's saved, do nothing. 705 if (request_id == 0) { 706 DVLOG(1) << "DeliverBlock() - invalid request_id " << request_id; 707 return; 708 } 709 710 media::Decryptor::DecryptCB decrypt_cb; 711 if (request_id == pending_audio_decrypt_request_id_) { 712 DCHECK(!pending_audio_decrypt_cb_.is_null()); 713 pending_audio_decrypt_request_id_ = 0; 714 decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_); 715 } else if (request_id == pending_video_decrypt_request_id_) { 716 DCHECK(!pending_video_decrypt_cb_.is_null()); 717 pending_video_decrypt_request_id_ = 0; 718 decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_); 719 } else { 720 DVLOG(1) << "DeliverBlock() - request_id " << request_id << " not found"; 721 return; 722 } 723 724 media::Decryptor::Status status = 725 PpDecryptResultToMediaDecryptorStatus(block_info->result); 726 if (status != media::Decryptor::kSuccess) { 727 decrypt_cb.Run(status, NULL); 728 return; 729 } 730 731 EnterResourceNoLock<PPB_Buffer_API> enter(decrypted_block, true); 732 if (!enter.succeeded()) { 733 decrypt_cb.Run(media::Decryptor::kError, NULL); 734 return; 735 } 736 BufferAutoMapper mapper(enter.object()); 737 if (!mapper.data() || !mapper.size() || 738 mapper.size() < block_info->data_size) { 739 decrypt_cb.Run(media::Decryptor::kError, NULL); 740 return; 741 } 742 743 // TODO(tomfinegan): Find a way to take ownership of the shared memory 744 // managed by the PPB_Buffer_Dev, and avoid the extra copy. 745 scoped_refptr<media::DecoderBuffer> decrypted_buffer( 746 media::DecoderBuffer::CopyFrom( 747 static_cast<uint8*>(mapper.data()), block_info->data_size)); 748 decrypted_buffer->set_timestamp(base::TimeDelta::FromMicroseconds( 749 block_info->tracking_info.timestamp)); 750 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); 751} 752 753// Use a non-class-member function here so that if for some reason 754// ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, 755// we can still get the shared memory unmapped. 756static void BufferNoLongerNeeded( 757 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, 758 base::Closure buffer_no_longer_needed_cb) { 759 ppb_buffer->Unmap(); 760 buffer_no_longer_needed_cb.Run(); 761} 762 763// Enters |resource|, maps shared memory and returns pointer of mapped data. 764// Returns NULL if any error occurs. 765static uint8* GetMappedBuffer(PP_Resource resource, 766 scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) { 767 EnterResourceNoLock<PPB_Buffer_API> enter(resource, true); 768 if (!enter.succeeded()) 769 return NULL; 770 771 uint8* mapped_data = static_cast<uint8*>(enter.object()->Map()); 772 if (!enter.object()->IsMapped() || !mapped_data) 773 return NULL; 774 775 uint32_t mapped_size = 0; 776 if (!enter.object()->Describe(&mapped_size) || !mapped_size) { 777 enter.object()->Unmap(); 778 return NULL; 779 } 780 781 *ppb_buffer = static_cast<PPB_Buffer_Impl*>(enter.object()); 782 783 return mapped_data; 784} 785 786void ContentDecryptorDelegate::DeliverFrame( 787 PP_Resource decrypted_frame, 788 const PP_DecryptedFrameInfo* frame_info) { 789 DCHECK(frame_info); 790 791 const uint32_t request_id = frame_info->tracking_info.request_id; 792 DVLOG(2) << "DeliverFrame() - request_id: " << request_id; 793 794 // If the request ID is not valid or does not match what's saved, do nothing. 795 if (request_id == 0 || request_id != pending_video_decode_request_id_) { 796 DVLOG(1) << "DeliverFrame() - request_id " << request_id << " not found"; 797 FreeBuffer(frame_info->tracking_info.buffer_id); 798 return; 799 } 800 801 TRACE_EVENT_ASYNC_END0( 802 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); 803 804 DCHECK(!pending_video_decode_cb_.is_null()); 805 pending_video_decode_request_id_ = 0; 806 media::Decryptor::VideoDecodeCB video_decode_cb = 807 base::ResetAndReturn(&pending_video_decode_cb_); 808 809 media::Decryptor::Status status = 810 PpDecryptResultToMediaDecryptorStatus(frame_info->result); 811 if (status != media::Decryptor::kSuccess) { 812 DCHECK(!frame_info->tracking_info.buffer_id); 813 video_decode_cb.Run(status, NULL); 814 return; 815 } 816 817 scoped_refptr<PPB_Buffer_Impl> ppb_buffer; 818 uint8* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer); 819 if (!frame_data) { 820 FreeBuffer(frame_info->tracking_info.buffer_id); 821 video_decode_cb.Run(media::Decryptor::kError, NULL); 822 return; 823 } 824 825 gfx::Size frame_size(frame_info->width, frame_info->height); 826 DCHECK_EQ(frame_info->format, PP_DECRYPTEDFRAMEFORMAT_YV12); 827 828 scoped_refptr<media::VideoFrame> decoded_frame = 829 media::VideoFrame::WrapExternalYuvData( 830 media::VideoFrame::YV12, 831 frame_size, 832 gfx::Rect(frame_size), 833 natural_size_, 834 frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y], 835 frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U], 836 frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V], 837 frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y], 838 frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_U], 839 frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V], 840 base::TimeDelta::FromMicroseconds( 841 frame_info->tracking_info.timestamp), 842 media::BindToLoop( 843 base::MessageLoopProxy::current(), 844 base::Bind(&BufferNoLongerNeeded, 845 ppb_buffer, 846 base::Bind(&ContentDecryptorDelegate::FreeBuffer, 847 weak_this_, 848 frame_info->tracking_info.buffer_id)))); 849 850 video_decode_cb.Run(media::Decryptor::kSuccess, decoded_frame); 851} 852 853void ContentDecryptorDelegate::DeliverSamples( 854 PP_Resource audio_frames, 855 const PP_DecryptedBlockInfo* block_info) { 856 DCHECK(block_info); 857 858 FreeBuffer(block_info->tracking_info.buffer_id); 859 860 const uint32_t request_id = block_info->tracking_info.request_id; 861 DVLOG(2) << "DeliverSamples() - request_id: " << request_id; 862 863 // If the request ID is not valid or does not match what's saved, do nothing. 864 if (request_id == 0 || request_id != pending_audio_decode_request_id_) { 865 DVLOG(1) << "DeliverSamples() - request_id " << request_id << " not found"; 866 return; 867 } 868 869 DCHECK(!pending_audio_decode_cb_.is_null()); 870 pending_audio_decode_request_id_ = 0; 871 media::Decryptor::AudioDecodeCB audio_decode_cb = 872 base::ResetAndReturn(&pending_audio_decode_cb_); 873 874 const media::Decryptor::AudioBuffers empty_frames; 875 876 media::Decryptor::Status status = 877 PpDecryptResultToMediaDecryptorStatus(block_info->result); 878 if (status != media::Decryptor::kSuccess) { 879 audio_decode_cb.Run(status, empty_frames); 880 return; 881 } 882 883 media::Decryptor::AudioBuffers audio_frame_list; 884 if (!DeserializeAudioFrames(audio_frames, 885 block_info->data_size, 886 &audio_frame_list)) { 887 NOTREACHED() << "CDM did not serialize the buffer correctly."; 888 audio_decode_cb.Run(media::Decryptor::kError, empty_frames); 889 return; 890 } 891 892 audio_decode_cb.Run(media::Decryptor::kSuccess, audio_frame_list); 893} 894 895// TODO(xhwang): Try to remove duplicate logic here and in CancelDecrypt(). 896void ContentDecryptorDelegate::CancelDecode( 897 media::Decryptor::StreamType stream_type) { 898 switch (stream_type) { 899 case media::Decryptor::kAudio: 900 // Release the shared memory as it can still be in use by the plugin. 901 // The next DecryptAndDecode() call will need to allocate a new shared 902 // memory buffer. 903 audio_input_resource_ = NULL; 904 pending_audio_decode_request_id_ = 0; 905 if (!pending_audio_decode_cb_.is_null()) 906 base::ResetAndReturn(&pending_audio_decode_cb_).Run( 907 media::Decryptor::kSuccess, media::Decryptor::AudioBuffers()); 908 break; 909 case media::Decryptor::kVideo: 910 // Release the shared memory as it can still be in use by the plugin. 911 // The next DecryptAndDecode() call will need to allocate a new shared 912 // memory buffer. 913 video_input_resource_ = NULL; 914 pending_video_decode_request_id_ = 0; 915 if (!pending_video_decode_cb_.is_null()) 916 base::ResetAndReturn(&pending_video_decode_cb_).Run( 917 media::Decryptor::kSuccess, NULL); 918 break; 919 default: 920 NOTREACHED(); 921 } 922} 923 924bool ContentDecryptorDelegate::MakeMediaBufferResource( 925 media::Decryptor::StreamType stream_type, 926 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 927 scoped_refptr<PPB_Buffer_Impl>* resource) { 928 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); 929 930 // End of stream buffers are represented as null resources. 931 if (encrypted_buffer->end_of_stream()) { 932 *resource = NULL; 933 return true; 934 } 935 936 DCHECK(stream_type == media::Decryptor::kAudio || 937 stream_type == media::Decryptor::kVideo); 938 scoped_refptr<PPB_Buffer_Impl>& media_resource = 939 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ : 940 video_input_resource_; 941 942 const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size()); 943 if (!media_resource.get() || media_resource->size() < data_size) { 944 // Either the buffer hasn't been created yet, or we have one that isn't big 945 // enough to fit |size| bytes. 946 947 // Media resource size starts from |kMinimumMediaBufferSize| and grows 948 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, 949 // which is usually expensive. Since input media buffers are compressed, 950 // they are usually small (compared to outputs). The over-allocated memory 951 // should be negligible. 952 const uint32_t kMinimumMediaBufferSize = 1024; 953 uint32_t media_resource_size = 954 media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize; 955 while (media_resource_size < data_size) 956 media_resource_size *= 2; 957 958 DVLOG(2) << "Size of media buffer for " 959 << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video") 960 << " stream bumped to " << media_resource_size 961 << " bytes to fit input."; 962 media_resource = PPB_Buffer_Impl::CreateResource(pp_instance_, 963 media_resource_size); 964 if (!media_resource.get()) 965 return false; 966 } 967 968 BufferAutoMapper mapper(media_resource.get()); 969 if (!mapper.data() || mapper.size() < data_size) { 970 media_resource = NULL; 971 return false; 972 } 973 memcpy(mapper.data(), encrypted_buffer->data(), data_size); 974 975 *resource = media_resource; 976 return true; 977} 978 979void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { 980 if (buffer_id) 981 free_buffers_.push(buffer_id); 982} 983 984void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( 985 PP_DecryptTrackingInfo* tracking_info) { 986 DCHECK_EQ(tracking_info->buffer_id, 0u); 987 988 if (free_buffers_.empty()) 989 return; 990 991 tracking_info->buffer_id = free_buffers_.front(); 992 free_buffers_.pop(); 993} 994 995bool ContentDecryptorDelegate::DeserializeAudioFrames( 996 PP_Resource audio_frames, 997 size_t data_size, 998 media::Decryptor::AudioBuffers* frames) { 999 DCHECK(frames); 1000 EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true); 1001 if (!enter.succeeded()) 1002 return false; 1003 1004 BufferAutoMapper mapper(enter.object()); 1005 if (!mapper.data() || !mapper.size() || 1006 mapper.size() < static_cast<uint32_t>(data_size)) 1007 return false; 1008 1009 // TODO(jrummell): Pass ownership of data() directly to AudioBuffer to avoid 1010 // the copy. Since it is possible to get multiple buffers, it would need to be 1011 // sliced and ref counted appropriately. http://crbug.com/255576. 1012 const uint8* cur = static_cast<uint8*>(mapper.data()); 1013 size_t bytes_left = data_size; 1014 1015 do { 1016 int64 timestamp = 0; 1017 int64 frame_size = -1; 1018 const size_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size); 1019 1020 if (bytes_left < kHeaderSize) 1021 return false; 1022 1023 memcpy(×tamp, cur, sizeof(timestamp)); 1024 cur += sizeof(timestamp); 1025 bytes_left -= sizeof(timestamp); 1026 1027 memcpy(&frame_size, cur, sizeof(frame_size)); 1028 cur += sizeof(frame_size); 1029 bytes_left -= sizeof(frame_size); 1030 1031 // We should *not* have empty frames in the list. 1032 if (frame_size <= 0 || 1033 bytes_left < base::checked_numeric_cast<size_t>(frame_size)) { 1034 return false; 1035 } 1036 1037 const uint8* data[] = {cur}; 1038 int frame_count = frame_size / audio_bytes_per_frame_; 1039 scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom( 1040 audio_sample_format_, 1041 audio_channel_count_, 1042 frame_count, 1043 data, 1044 base::TimeDelta::FromMicroseconds(timestamp), 1045 base::TimeDelta::FromMicroseconds(audio_samples_per_second_ / 1046 frame_count)); 1047 frames->push_back(frame); 1048 1049 cur += frame_size; 1050 bytes_left -= frame_size; 1051 } while (bytes_left > 0); 1052 1053 return true; 1054} 1055 1056} // namespace content 1057