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