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