cdm_adapter.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
1// Copyright 2013 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 "media/cdm/ppapi/cdm_adapter.h" 6 7#include "media/cdm/ppapi/cdm_helpers.h" 8#include "media/cdm/ppapi/supported_cdm_versions.h" 9 10#if defined(CHECK_DOCUMENT_URL) 11#include "ppapi/cpp/dev/url_util_dev.h" 12#include "ppapi/cpp/instance_handle.h" 13#endif // defined(CHECK_DOCUMENT_URL) 14 15namespace { 16 17bool IsMainThread() { 18 return pp::Module::Get()->core()->IsMainThread(); 19} 20 21// Posts a task to run |cb| on the main thread. The task is posted even if the 22// current thread is the main thread. 23void PostOnMain(pp::CompletionCallback cb) { 24 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK); 25} 26 27// Ensures |cb| is called on the main thread, either because the current thread 28// is the main thread or by posting it to the main thread. 29void CallOnMain(pp::CompletionCallback cb) { 30 // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls 31 // off the main thread yet. Remove this once the change lands. 32 if (IsMainThread()) 33 cb.Run(PP_OK); 34 else 35 PostOnMain(cb); 36} 37 38// Configures a cdm::InputBuffer. |subsamples| must exist as long as 39// |input_buffer| is in use. 40void ConfigureInputBuffer( 41 const pp::Buffer_Dev& encrypted_buffer, 42 const PP_EncryptedBlockInfo& encrypted_block_info, 43 std::vector<cdm::SubsampleEntry>* subsamples, 44 cdm::InputBuffer* input_buffer) { 45 PP_DCHECK(subsamples); 46 PP_DCHECK(!encrypted_buffer.is_null()); 47 48 input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data()); 49 input_buffer->data_size = encrypted_block_info.data_size; 50 PP_DCHECK(encrypted_buffer.size() >= input_buffer->data_size); 51 input_buffer->data_offset = encrypted_block_info.data_offset; 52 53 PP_DCHECK(encrypted_block_info.key_id_size <= 54 arraysize(encrypted_block_info.key_id)); 55 input_buffer->key_id_size = encrypted_block_info.key_id_size; 56 input_buffer->key_id = input_buffer->key_id_size > 0 ? 57 encrypted_block_info.key_id : NULL; 58 59 PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv)); 60 input_buffer->iv_size = encrypted_block_info.iv_size; 61 input_buffer->iv = encrypted_block_info.iv_size > 0 ? 62 encrypted_block_info.iv : NULL; 63 64 input_buffer->num_subsamples = encrypted_block_info.num_subsamples; 65 if (encrypted_block_info.num_subsamples > 0) { 66 subsamples->reserve(encrypted_block_info.num_subsamples); 67 68 for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) { 69 subsamples->push_back(cdm::SubsampleEntry( 70 encrypted_block_info.subsamples[i].clear_bytes, 71 encrypted_block_info.subsamples[i].cipher_bytes)); 72 } 73 74 input_buffer->subsamples = &(*subsamples)[0]; 75 } 76 77 input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp; 78} 79 80PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) { 81 switch (status) { 82 case cdm::kSuccess: 83 return PP_DECRYPTRESULT_SUCCESS; 84 case cdm::kNoKey: 85 return PP_DECRYPTRESULT_DECRYPT_NOKEY; 86 case cdm::kNeedMoreData: 87 return PP_DECRYPTRESULT_NEEDMOREDATA; 88 case cdm::kDecryptError: 89 return PP_DECRYPTRESULT_DECRYPT_ERROR; 90 case cdm::kDecodeError: 91 return PP_DECRYPTRESULT_DECODE_ERROR; 92 default: 93 PP_NOTREACHED(); 94 return PP_DECRYPTRESULT_DECODE_ERROR; 95 } 96} 97 98PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat( 99 cdm::VideoFormat format) { 100 switch (format) { 101 case cdm::kYv12: 102 return PP_DECRYPTEDFRAMEFORMAT_YV12; 103 case cdm::kI420: 104 return PP_DECRYPTEDFRAMEFORMAT_I420; 105 default: 106 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN; 107 } 108} 109 110PP_DecryptedSampleFormat CdmAudioFormatToPpDecryptedSampleFormat( 111 cdm::AudioFormat format) { 112 switch (format) { 113 case cdm::kAudioFormatU8: 114 return PP_DECRYPTEDSAMPLEFORMAT_U8; 115 case cdm::kAudioFormatS16: 116 return PP_DECRYPTEDSAMPLEFORMAT_S16; 117 case cdm::kAudioFormatS32: 118 return PP_DECRYPTEDSAMPLEFORMAT_S32; 119 case cdm::kAudioFormatF32: 120 return PP_DECRYPTEDSAMPLEFORMAT_F32; 121 case cdm::kAudioFormatPlanarS16: 122 return PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16; 123 case cdm::kAudioFormatPlanarF32: 124 return PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32; 125 default: 126 return PP_DECRYPTEDSAMPLEFORMAT_UNKNOWN; 127 } 128} 129 130cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec( 131 PP_AudioCodec codec) { 132 switch (codec) { 133 case PP_AUDIOCODEC_VORBIS: 134 return cdm::AudioDecoderConfig::kCodecVorbis; 135 case PP_AUDIOCODEC_AAC: 136 return cdm::AudioDecoderConfig::kCodecAac; 137 default: 138 return cdm::AudioDecoderConfig::kUnknownAudioCodec; 139 } 140} 141 142cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec( 143 PP_VideoCodec codec) { 144 switch (codec) { 145 case PP_VIDEOCODEC_VP8: 146 return cdm::VideoDecoderConfig::kCodecVp8; 147 case PP_VIDEOCODEC_H264: 148 return cdm::VideoDecoderConfig::kCodecH264; 149 default: 150 return cdm::VideoDecoderConfig::kUnknownVideoCodec; 151 } 152} 153 154cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile( 155 PP_VideoCodecProfile profile) { 156 switch (profile) { 157 case PP_VIDEOCODECPROFILE_VP8_MAIN: 158 return cdm::VideoDecoderConfig::kVp8ProfileMain; 159 case PP_VIDEOCODECPROFILE_H264_BASELINE: 160 return cdm::VideoDecoderConfig::kH264ProfileBaseline; 161 case PP_VIDEOCODECPROFILE_H264_MAIN: 162 return cdm::VideoDecoderConfig::kH264ProfileMain; 163 case PP_VIDEOCODECPROFILE_H264_EXTENDED: 164 return cdm::VideoDecoderConfig::kH264ProfileExtended; 165 case PP_VIDEOCODECPROFILE_H264_HIGH: 166 return cdm::VideoDecoderConfig::kH264ProfileHigh; 167 case PP_VIDEOCODECPROFILE_H264_HIGH_10: 168 return cdm::VideoDecoderConfig::kH264ProfileHigh10; 169 case PP_VIDEOCODECPROFILE_H264_HIGH_422: 170 return cdm::VideoDecoderConfig::kH264ProfileHigh422; 171 case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE: 172 return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive; 173 default: 174 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile; 175 } 176} 177 178cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat( 179 PP_DecryptedFrameFormat format) { 180 switch (format) { 181 case PP_DECRYPTEDFRAMEFORMAT_YV12: 182 return cdm::kYv12; 183 case PP_DECRYPTEDFRAMEFORMAT_I420: 184 return cdm::kI420; 185 default: 186 return cdm::kUnknownVideoFormat; 187 } 188} 189 190cdm::StreamType PpDecryptorStreamTypeToCdmStreamType( 191 PP_DecryptorStreamType stream_type) { 192 switch (stream_type) { 193 case PP_DECRYPTORSTREAMTYPE_AUDIO: 194 return cdm::kStreamTypeAudio; 195 case PP_DECRYPTORSTREAMTYPE_VIDEO: 196 return cdm::kStreamTypeVideo; 197 } 198 199 PP_NOTREACHED(); 200 return cdm::kStreamTypeVideo; 201} 202 203} // namespace 204 205namespace media { 206 207CdmAdapter::CdmAdapter(PP_Instance instance, pp::Module* module) 208 : pp::Instance(instance), 209 pp::ContentDecryptor_Private(this), 210#if defined(OS_CHROMEOS) 211 output_protection_(this), 212 platform_verification_(this), 213 challenge_in_progress_(false), 214 output_link_mask_(0), 215 output_protection_mask_(0), 216 query_output_protection_in_progress_(false), 217#endif 218 allocator_(this), 219 cdm_(NULL), 220 deferred_initialize_audio_decoder_(false), 221 deferred_audio_decoder_config_id_(0), 222 deferred_initialize_video_decoder_(false), 223 deferred_video_decoder_config_id_(0) { 224 callback_factory_.Initialize(this); 225} 226 227CdmAdapter::~CdmAdapter() {} 228 229bool CdmAdapter::CreateCdmInstance(const std::string& key_system) { 230 PP_DCHECK(!cdm_); 231 cdm_ = make_linked_ptr(CdmWrapper::Create( 232 key_system.data(), key_system.size(), GetCdmHost, this)); 233 return (cdm_ != NULL); 234} 235 236// No KeyErrors should be reported in this function because they cannot be 237// bubbled up in the WD EME API. Those errors will be reported during session 238// creation (aka GenerateKeyRequest). 239void CdmAdapter::Initialize(const std::string& key_system, 240 bool can_challenge_platform) { 241 PP_DCHECK(!key_system.empty()); 242 PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_)); 243 244 if (!cdm_ && !CreateCdmInstance(key_system)) 245 return; 246 247 PP_DCHECK(cdm_); 248 key_system_ = key_system; 249} 250 251void CdmAdapter::GenerateKeyRequest(const std::string& type, 252 pp::VarArrayBuffer init_data) { 253 // Initialize() doesn't report an error, so GenerateKeyRequest() can be called 254 // even if Initialize() failed. 255 if (!cdm_) { 256 SendUnknownKeyError(key_system_, std::string()); 257 return; 258 } 259 260#if defined(CHECK_DOCUMENT_URL) 261 PP_URLComponents_Dev url_components = {}; 262 pp::Var href = pp::URLUtil_Dev::Get()->GetDocumentURL( 263 pp::InstanceHandle(pp_instance()), &url_components); 264 PP_DCHECK(href.is_string()); 265 PP_DCHECK(!href.AsString().empty()); 266 PP_DCHECK(url_components.host.begin); 267 PP_DCHECK(0 < url_components.host.len); 268#endif // defined(CHECK_DOCUMENT_URL) 269 270 cdm::Status status = cdm_->GenerateKeyRequest( 271 type.data(), type.size(), 272 static_cast<const uint8_t*>(init_data.Map()), 273 init_data.ByteLength()); 274 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); 275 if (status != cdm::kSuccess) 276 SendUnknownKeyError(key_system_, std::string()); 277} 278 279void CdmAdapter::AddKey(const std::string& session_id, 280 pp::VarArrayBuffer key, 281 pp::VarArrayBuffer init_data) { 282 // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions. 283 // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976. 284 if (!cdm_) { 285 SendUnknownKeyError(key_system_, session_id); 286 return; 287 } 288 289 const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map()); 290 const uint32_t key_size = key.ByteLength(); 291 const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map()); 292 const uint32_t init_data_size = init_data.ByteLength(); 293 PP_DCHECK(!init_data_ptr == !init_data_size); 294 295 if (!key_ptr || !key_size) { 296 SendUnknownKeyError(key_system_, session_id); 297 return; 298 } 299 300 cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(), 301 key_ptr, key_size, 302 init_data_ptr, init_data_size); 303 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); 304 if (status != cdm::kSuccess) { 305 SendUnknownKeyError(key_system_, session_id); 306 return; 307 } 308 309 SendKeyAdded(key_system_, session_id); 310} 311 312void CdmAdapter::CancelKeyRequest(const std::string& session_id) { 313 // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions. 314 // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976. 315 if (!cdm_) { 316 SendUnknownKeyError(key_system_, session_id); 317 return; 318 } 319 320 cdm::Status status = cdm_->CancelKeyRequest(session_id.data(), 321 session_id.size()); 322 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); 323 if (status != cdm::kSuccess) 324 SendUnknownKeyError(key_system_, session_id); 325} 326 327// Note: In the following decryption/decoding related functions, errors are NOT 328// reported via KeyError, but are reported via corresponding PPB calls. 329 330void CdmAdapter::Decrypt(pp::Buffer_Dev encrypted_buffer, 331 const PP_EncryptedBlockInfo& encrypted_block_info) { 332 PP_DCHECK(!encrypted_buffer.is_null()); 333 334 // Release a buffer that the caller indicated it is finished with. 335 allocator_.Release(encrypted_block_info.tracking_info.buffer_id); 336 337 cdm::Status status = cdm::kDecryptError; 338 LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl()); 339 340 if (cdm_) { 341 cdm::InputBuffer input_buffer; 342 std::vector<cdm::SubsampleEntry> subsamples; 343 ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples, 344 &input_buffer); 345 status = cdm_->Decrypt(input_buffer, decrypted_block.get()); 346 PP_DCHECK(status != cdm::kSuccess || 347 (decrypted_block->DecryptedBuffer() && 348 decrypted_block->DecryptedBuffer()->Size())); 349 } 350 351 CallOnMain(callback_factory_.NewCallback( 352 &CdmAdapter::DeliverBlock, 353 status, 354 decrypted_block, 355 encrypted_block_info.tracking_info)); 356} 357 358void CdmAdapter::InitializeAudioDecoder( 359 const PP_AudioDecoderConfig& decoder_config, 360 pp::Buffer_Dev extra_data_buffer) { 361 PP_DCHECK(!deferred_initialize_audio_decoder_); 362 PP_DCHECK(deferred_audio_decoder_config_id_ == 0); 363 cdm::Status status = cdm::kSessionError; 364 if (cdm_) { 365 cdm::AudioDecoderConfig cdm_decoder_config; 366 cdm_decoder_config.codec = 367 PpAudioCodecToCdmAudioCodec(decoder_config.codec); 368 cdm_decoder_config.channel_count = decoder_config.channel_count; 369 cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel; 370 cdm_decoder_config.samples_per_second = decoder_config.samples_per_second; 371 cdm_decoder_config.extra_data = 372 static_cast<uint8_t*>(extra_data_buffer.data()); 373 cdm_decoder_config.extra_data_size = extra_data_buffer.size(); 374 status = cdm_->InitializeAudioDecoder(cdm_decoder_config); 375 } 376 377 if (status == cdm::kDeferredInitialization) { 378 deferred_initialize_audio_decoder_ = true; 379 deferred_audio_decoder_config_id_ = decoder_config.request_id; 380 return; 381 } 382 383 CallOnMain(callback_factory_.NewCallback( 384 &CdmAdapter::DecoderInitializeDone, 385 PP_DECRYPTORSTREAMTYPE_AUDIO, 386 decoder_config.request_id, 387 status == cdm::kSuccess)); 388} 389 390void CdmAdapter::InitializeVideoDecoder( 391 const PP_VideoDecoderConfig& decoder_config, 392 pp::Buffer_Dev extra_data_buffer) { 393 PP_DCHECK(!deferred_initialize_video_decoder_); 394 PP_DCHECK(deferred_video_decoder_config_id_ == 0); 395 cdm::Status status = cdm::kSessionError; 396 if (cdm_) { 397 cdm::VideoDecoderConfig cdm_decoder_config; 398 cdm_decoder_config.codec = 399 PpVideoCodecToCdmVideoCodec(decoder_config.codec); 400 cdm_decoder_config.profile = 401 PpVCProfileToCdmVCProfile(decoder_config.profile); 402 cdm_decoder_config.format = 403 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format); 404 cdm_decoder_config.coded_size.width = decoder_config.width; 405 cdm_decoder_config.coded_size.height = decoder_config.height; 406 cdm_decoder_config.extra_data = 407 static_cast<uint8_t*>(extra_data_buffer.data()); 408 cdm_decoder_config.extra_data_size = extra_data_buffer.size(); 409 status = cdm_->InitializeVideoDecoder(cdm_decoder_config); 410 } 411 412 if (status == cdm::kDeferredInitialization) { 413 deferred_initialize_video_decoder_ = true; 414 deferred_video_decoder_config_id_ = decoder_config.request_id; 415 return; 416 } 417 418 CallOnMain(callback_factory_.NewCallback( 419 &CdmAdapter::DecoderInitializeDone, 420 PP_DECRYPTORSTREAMTYPE_VIDEO, 421 decoder_config.request_id, 422 status == cdm::kSuccess)); 423} 424 425void CdmAdapter::DeinitializeDecoder(PP_DecryptorStreamType decoder_type, 426 uint32_t request_id) { 427 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded. 428 if (cdm_) { 429 cdm_->DeinitializeDecoder( 430 PpDecryptorStreamTypeToCdmStreamType(decoder_type)); 431 } 432 433 CallOnMain(callback_factory_.NewCallback( 434 &CdmAdapter::DecoderDeinitializeDone, 435 decoder_type, 436 request_id)); 437} 438 439void CdmAdapter::ResetDecoder(PP_DecryptorStreamType decoder_type, 440 uint32_t request_id) { 441 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded. 442 if (cdm_) 443 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type)); 444 445 CallOnMain(callback_factory_.NewCallback(&CdmAdapter::DecoderResetDone, 446 decoder_type, 447 request_id)); 448} 449 450void CdmAdapter::DecryptAndDecode( 451 PP_DecryptorStreamType decoder_type, 452 pp::Buffer_Dev encrypted_buffer, 453 const PP_EncryptedBlockInfo& encrypted_block_info) { 454 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded. 455 // Release a buffer that the caller indicated it is finished with. 456 allocator_.Release(encrypted_block_info.tracking_info.buffer_id); 457 458 cdm::InputBuffer input_buffer; 459 std::vector<cdm::SubsampleEntry> subsamples; 460 if (cdm_ && !encrypted_buffer.is_null()) { 461 ConfigureInputBuffer(encrypted_buffer, 462 encrypted_block_info, 463 &subsamples, 464 &input_buffer); 465 } 466 467 cdm::Status status = cdm::kDecodeError; 468 469 switch (decoder_type) { 470 case PP_DECRYPTORSTREAMTYPE_VIDEO: { 471 LinkedVideoFrame video_frame(new VideoFrameImpl()); 472 if (cdm_) 473 status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get()); 474 CallOnMain(callback_factory_.NewCallback( 475 &CdmAdapter::DeliverFrame, 476 status, 477 video_frame, 478 encrypted_block_info.tracking_info)); 479 return; 480 } 481 482 case PP_DECRYPTORSTREAMTYPE_AUDIO: { 483 LinkedAudioFrames audio_frames(new AudioFramesImpl()); 484 if (cdm_) { 485 status = cdm_->DecryptAndDecodeSamples(input_buffer, 486 audio_frames.get()); 487 } 488 CallOnMain(callback_factory_.NewCallback( 489 &CdmAdapter::DeliverSamples, 490 status, 491 audio_frames, 492 encrypted_block_info.tracking_info)); 493 return; 494 } 495 496 default: 497 PP_NOTREACHED(); 498 return; 499 } 500} 501 502cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) { 503 return allocator_.Allocate(capacity); 504} 505 506void CdmAdapter::SetTimer(int64_t delay_ms, void* context) { 507 // NOTE: doesn't really need to run on the main thread; could just as well run 508 // on a helper thread if |cdm_| were thread-friendly and care was taken. We 509 // only use CallOnMainThread() here to get delayed-execution behavior. 510 pp::Module::Get()->core()->CallOnMainThread( 511 delay_ms, 512 callback_factory_.NewCallback(&CdmAdapter::TimerExpired, context), 513 PP_OK); 514} 515 516void CdmAdapter::TimerExpired(int32_t result, void* context) { 517 PP_DCHECK(result == PP_OK); 518 cdm_->TimerExpired(context); 519} 520 521double CdmAdapter::GetCurrentWallTimeInSeconds() { 522 return pp::Module::Get()->core()->GetTime(); 523} 524 525void CdmAdapter::SendKeyMessage( 526 const char* session_id, uint32_t session_id_length, 527 const char* message, uint32_t message_length, 528 const char* default_url, uint32_t default_url_length) { 529 PP_DCHECK(!key_system_.empty()); 530 PostOnMain(callback_factory_.NewCallback( 531 &CdmAdapter::KeyMessage, 532 SessionInfo(key_system_, 533 std::string(session_id, session_id_length)), 534 std::vector<uint8>(message, message + message_length), 535 std::string(default_url, default_url_length))); 536} 537 538void CdmAdapter::SendKeyError(const char* session_id, 539 uint32_t session_id_length, 540 cdm::MediaKeyError error_code, 541 uint32_t system_code) { 542 SendKeyErrorInternal(key_system_, 543 std::string(session_id, session_id_length), 544 error_code, 545 system_code); 546} 547 548void CdmAdapter::GetPrivateData(int32_t* instance, 549 GetPrivateInterface* get_interface) { 550 *instance = pp_instance(); 551 *get_interface = pp::Module::Get()->get_browser_interface(); 552} 553 554void CdmAdapter::SendUnknownKeyError(const std::string& key_system, 555 const std::string& session_id) { 556 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0); 557} 558 559void CdmAdapter::SendKeyAdded(const std::string& key_system, 560 const std::string& session_id) { 561 PostOnMain(callback_factory_.NewCallback( 562 &CdmAdapter::KeyAdded, 563 SessionInfo(key_system_, session_id))); 564} 565 566void CdmAdapter::SendKeyErrorInternal(const std::string& key_system, 567 const std::string& session_id, 568 cdm::MediaKeyError error_code, 569 uint32_t system_code) { 570 PostOnMain(callback_factory_.NewCallback(&CdmAdapter::KeyError, 571 SessionInfo(key_system_, session_id), 572 error_code, 573 system_code)); 574} 575 576void CdmAdapter::KeyAdded(int32_t result, const SessionInfo& session_info) { 577 PP_DCHECK(result == PP_OK); 578 PP_DCHECK(!session_info.key_system.empty()); 579 pp::ContentDecryptor_Private::KeyAdded(session_info.key_system, 580 session_info.session_id); 581} 582 583void CdmAdapter::KeyMessage(int32_t result, 584 const SessionInfo& session_info, 585 const std::vector<uint8>& message, 586 const std::string& default_url) { 587 PP_DCHECK(result == PP_OK); 588 PP_DCHECK(!session_info.key_system.empty()); 589 590 pp::VarArrayBuffer message_array_buffer(message.size()); 591 if (message.size() > 0) { 592 memcpy(message_array_buffer.Map(), message.data(), message.size()); 593 } 594 595 pp::ContentDecryptor_Private::KeyMessage( 596 session_info.key_system, session_info.session_id, 597 message_array_buffer, default_url); 598} 599 600void CdmAdapter::KeyError(int32_t result, 601 const SessionInfo& session_info, 602 cdm::MediaKeyError error_code, 603 uint32_t system_code) { 604 PP_DCHECK(result == PP_OK); 605 pp::ContentDecryptor_Private::KeyError( 606 session_info.key_system, session_info.session_id, 607 error_code, system_code); 608} 609 610void CdmAdapter::DeliverBlock(int32_t result, 611 const cdm::Status& status, 612 const LinkedDecryptedBlock& decrypted_block, 613 const PP_DecryptTrackingInfo& tracking_info) { 614 PP_DCHECK(result == PP_OK); 615 PP_DecryptedBlockInfo decrypted_block_info; 616 decrypted_block_info.tracking_info = tracking_info; 617 decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp(); 618 decrypted_block_info.tracking_info.buffer_id = 0; 619 decrypted_block_info.data_size = 0; 620 decrypted_block_info.result = CdmStatusToPpDecryptResult(status); 621 622 pp::Buffer_Dev buffer; 623 624 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) { 625 PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer()); 626 if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) { 627 PP_NOTREACHED(); 628 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR; 629 } else { 630 PpbBuffer* ppb_buffer = 631 static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer()); 632 buffer = ppb_buffer->buffer_dev(); 633 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id(); 634 decrypted_block_info.data_size = ppb_buffer->Size(); 635 } 636 } 637 638 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info); 639} 640 641void CdmAdapter::DecoderInitializeDone(int32_t result, 642 PP_DecryptorStreamType decoder_type, 643 uint32_t request_id, 644 bool success) { 645 PP_DCHECK(result == PP_OK); 646 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type, 647 request_id, 648 success); 649} 650 651void CdmAdapter::DecoderDeinitializeDone(int32_t result, 652 PP_DecryptorStreamType decoder_type, 653 uint32_t request_id) { 654 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type, 655 request_id); 656} 657 658void CdmAdapter::DecoderResetDone(int32_t result, 659 PP_DecryptorStreamType decoder_type, 660 uint32_t request_id) { 661 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id); 662} 663 664void CdmAdapter::DeliverFrame( 665 int32_t result, 666 const cdm::Status& status, 667 const LinkedVideoFrame& video_frame, 668 const PP_DecryptTrackingInfo& tracking_info) { 669 PP_DCHECK(result == PP_OK); 670 PP_DecryptedFrameInfo decrypted_frame_info; 671 decrypted_frame_info.tracking_info.request_id = tracking_info.request_id; 672 decrypted_frame_info.tracking_info.buffer_id = 0; 673 decrypted_frame_info.result = CdmStatusToPpDecryptResult(status); 674 675 pp::Buffer_Dev buffer; 676 677 if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) { 678 if (!IsValidVideoFrame(video_frame)) { 679 PP_NOTREACHED(); 680 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR; 681 } else { 682 PpbBuffer* ppb_buffer = 683 static_cast<PpbBuffer*>(video_frame->FrameBuffer()); 684 685 buffer = ppb_buffer->buffer_dev(); 686 687 decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp(); 688 decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id(); 689 decrypted_frame_info.format = 690 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format()); 691 decrypted_frame_info.width = video_frame->Size().width; 692 decrypted_frame_info.height = video_frame->Size().height; 693 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] = 694 video_frame->PlaneOffset(cdm::VideoFrame::kYPlane); 695 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] = 696 video_frame->PlaneOffset(cdm::VideoFrame::kUPlane); 697 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] = 698 video_frame->PlaneOffset(cdm::VideoFrame::kVPlane); 699 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] = 700 video_frame->Stride(cdm::VideoFrame::kYPlane); 701 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] = 702 video_frame->Stride(cdm::VideoFrame::kUPlane); 703 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] = 704 video_frame->Stride(cdm::VideoFrame::kVPlane); 705 } 706 } 707 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info); 708} 709 710void CdmAdapter::DeliverSamples(int32_t result, 711 const cdm::Status& status, 712 const LinkedAudioFrames& audio_frames, 713 const PP_DecryptTrackingInfo& tracking_info) { 714 PP_DCHECK(result == PP_OK); 715 716 PP_DecryptedSampleInfo decrypted_sample_info; 717 decrypted_sample_info.tracking_info = tracking_info; 718 decrypted_sample_info.tracking_info.timestamp = 0; 719 decrypted_sample_info.tracking_info.buffer_id = 0; 720 decrypted_sample_info.data_size = 0; 721 decrypted_sample_info.result = CdmStatusToPpDecryptResult(status); 722 723 pp::Buffer_Dev buffer; 724 725 if (decrypted_sample_info.result == PP_DECRYPTRESULT_SUCCESS) { 726 PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer()); 727 if (!audio_frames.get() || !audio_frames->FrameBuffer()) { 728 PP_NOTREACHED(); 729 decrypted_sample_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR; 730 } else { 731 PpbBuffer* ppb_buffer = 732 static_cast<PpbBuffer*>(audio_frames->FrameBuffer()); 733 buffer = ppb_buffer->buffer_dev(); 734 decrypted_sample_info.tracking_info.buffer_id = ppb_buffer->buffer_id(); 735 decrypted_sample_info.data_size = ppb_buffer->Size(); 736 decrypted_sample_info.format = 737 CdmAudioFormatToPpDecryptedSampleFormat(audio_frames->Format()); 738 } 739 } 740 741 pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_sample_info); 742} 743 744bool CdmAdapter::IsValidVideoFrame(const LinkedVideoFrame& video_frame) { 745 if (!video_frame.get() || 746 !video_frame->FrameBuffer() || 747 (video_frame->Format() != cdm::kI420 && 748 video_frame->Format() != cdm::kYv12)) { 749 return false; 750 } 751 752 PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer()); 753 754 for (uint32_t i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) { 755 int plane_height = (i == cdm::VideoFrame::kYPlane) ? 756 video_frame->Size().height : (video_frame->Size().height + 1) / 2; 757 cdm::VideoFrame::VideoPlane plane = 758 static_cast<cdm::VideoFrame::VideoPlane>(i); 759 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) + 760 plane_height * video_frame->Stride(plane)) { 761 return false; 762 } 763 } 764 765 return true; 766} 767 768void CdmAdapter::SendPlatformChallenge( 769 const char* service_id, uint32_t service_id_length, 770 const char* challenge, uint32_t challenge_length) { 771#if defined(OS_CHROMEOS) 772 PP_DCHECK(!challenge_in_progress_); 773 774 // Ensure member variables set by the callback are in a clean state. 775 signed_data_output_ = pp::Var(); 776 signed_data_signature_output_ = pp::Var(); 777 platform_key_certificate_output_ = pp::Var(); 778 779 pp::VarArrayBuffer challenge_var(challenge_length); 780 uint8_t* var_data = static_cast<uint8_t*>(challenge_var.Map()); 781 memcpy(var_data, challenge, challenge_length); 782 783 std::string service_id_str(service_id, service_id_length); 784 int32_t result = platform_verification_.ChallengePlatform( 785 pp::Var(service_id_str), challenge_var, &signed_data_output_, 786 &signed_data_signature_output_, &platform_key_certificate_output_, 787 callback_factory_.NewCallback(&CdmAdapter::SendPlatformChallengeDone)); 788 challenge_var.Unmap(); 789 if (result == PP_OK_COMPLETIONPENDING) { 790 challenge_in_progress_ = true; 791 return; 792 } 793 794 // Fall through on error and issue an empty OnPlatformChallengeResponse(). 795 PP_DCHECK(result != PP_OK); 796#endif 797 798 cdm::PlatformChallengeResponse response = {}; 799 cdm_->OnPlatformChallengeResponse(response); 800} 801 802void CdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) { 803#if defined(OS_CHROMEOS) 804 output_protection_.EnableProtection( 805 desired_protection_mask, callback_factory_.NewCallback( 806 &CdmAdapter::EnableProtectionDone)); 807 808 // Errors are ignored since clients must call QueryOutputProtectionStatus() to 809 // inspect the protection status on a regular basis. 810 // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here... 811#endif 812} 813 814void CdmAdapter::QueryOutputProtectionStatus() { 815#if defined(OS_CHROMEOS) 816 PP_DCHECK(!query_output_protection_in_progress_); 817 818 output_link_mask_ = output_protection_mask_ = 0; 819 const int32_t result = output_protection_.QueryStatus( 820 &output_link_mask_, 821 &output_protection_mask_, 822 callback_factory_.NewCallback( 823 &CdmAdapter::QueryOutputProtectionStatusDone)); 824 if (result == PP_OK_COMPLETIONPENDING) { 825 query_output_protection_in_progress_ = true; 826 return; 827 } 828 829 // Fall through on error and issue an empty OnQueryOutputProtectionStatus(). 830 PP_DCHECK(result != PP_OK); 831#endif 832 833 cdm_->OnQueryOutputProtectionStatus(0, 0); 834} 835 836void CdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type, 837 cdm::Status decoder_status) { 838 switch (stream_type) { 839 case cdm::kStreamTypeAudio: 840 PP_DCHECK(deferred_initialize_audio_decoder_); 841 CallOnMain( 842 callback_factory_.NewCallback(&CdmAdapter::DecoderInitializeDone, 843 PP_DECRYPTORSTREAMTYPE_AUDIO, 844 deferred_audio_decoder_config_id_, 845 decoder_status == cdm::kSuccess)); 846 deferred_initialize_audio_decoder_ = false; 847 deferred_audio_decoder_config_id_ = 0; 848 break; 849 case cdm::kStreamTypeVideo: 850 PP_DCHECK(deferred_initialize_video_decoder_); 851 CallOnMain( 852 callback_factory_.NewCallback(&CdmAdapter::DecoderInitializeDone, 853 PP_DECRYPTORSTREAMTYPE_VIDEO, 854 deferred_video_decoder_config_id_, 855 decoder_status == cdm::kSuccess)); 856 deferred_initialize_video_decoder_ = false; 857 deferred_video_decoder_config_id_ = 0; 858 break; 859 } 860} 861 862#if defined(OS_CHROMEOS) 863void CdmAdapter::SendPlatformChallengeDone(int32_t result) { 864 challenge_in_progress_ = false; 865 866 if (result != PP_OK) { 867 cdm::PlatformChallengeResponse response = {}; 868 cdm_->OnPlatformChallengeResponse(response); 869 return; 870 } 871 872 pp::VarArrayBuffer signed_data_var(signed_data_output_); 873 pp::VarArrayBuffer signed_data_signature_var(signed_data_signature_output_); 874 std::string platform_key_certificate_string = 875 platform_key_certificate_output_.AsString(); 876 877 cdm::PlatformChallengeResponse response = { 878 static_cast<uint8_t*>(signed_data_var.Map()), 879 signed_data_var.ByteLength(), 880 881 static_cast<uint8_t*>(signed_data_signature_var.Map()), 882 signed_data_signature_var.ByteLength(), 883 884 reinterpret_cast<const uint8_t*>(platform_key_certificate_string.c_str()), 885 static_cast<uint32_t>(platform_key_certificate_string.length()) 886 }; 887 cdm_->OnPlatformChallengeResponse(response); 888 889 signed_data_var.Unmap(); 890 signed_data_signature_var.Unmap(); 891} 892 893void CdmAdapter::EnableProtectionDone(int32_t result) { 894 // Does nothing since clients must call QueryOutputProtectionStatus() to 895 // inspect the protection status on a regular basis. 896 // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here... 897} 898 899void CdmAdapter::QueryOutputProtectionStatusDone(int32_t result) { 900 PP_DCHECK(query_output_protection_in_progress_); 901 query_output_protection_in_progress_ = false; 902 903 // Return a protection status of none on error. 904 if (result != PP_OK) 905 output_link_mask_ = output_protection_mask_ = 0; 906 907 cdm_->OnQueryOutputProtectionStatus(output_link_mask_, 908 output_protection_mask_); 909} 910#endif 911 912void* GetCdmHost(int host_interface_version, void* user_data) { 913 if (!host_interface_version || !user_data) 914 return NULL; 915 916 COMPILE_ASSERT(cdm::ContentDecryptionModule::Host::kVersion == 917 cdm::ContentDecryptionModule_2::Host::kVersion, 918 update_code_below); 919 920 // Ensure IsSupportedCdmHostVersion matches implementation of this function. 921 // Always update this DCHECK when updating this function. 922 // If this check fails, update this function and DCHECK or update 923 // IsSupportedCdmHostVersion. 924 PP_DCHECK( 925 // Future version is not supported. 926 !IsSupportedCdmHostVersion( 927 cdm::ContentDecryptionModule::Host::kVersion + 1) && 928 // Current version is supported. 929 IsSupportedCdmHostVersion(cdm::ContentDecryptionModule::Host::kVersion) && 930 // Include all previous supported versions here. 931 IsSupportedCdmHostVersion(cdm::Host_1::kVersion) && 932 // One older than the oldest supported version is not supported. 933 !IsSupportedCdmHostVersion(cdm::Host_1::kVersion - 1)); 934 PP_DCHECK(IsSupportedCdmHostVersion(host_interface_version)); 935 936 CdmAdapter* cdm_adapter = static_cast<CdmAdapter*>(user_data); 937 switch (host_interface_version) { 938 // The latest CDM host version. 939 case cdm::ContentDecryptionModule::Host::kVersion: 940 return static_cast<cdm::ContentDecryptionModule::Host*>(cdm_adapter); 941 // Older supported version(s) of the CDM host. 942 case cdm::Host_1::kVersion: 943 return static_cast<cdm::Host_1*>(cdm_adapter); 944 default: 945 PP_NOTREACHED(); 946 return NULL; 947 } 948} 949 950// This object is the global object representing this plugin library as long 951// as it is loaded. 952class CdmAdapterModule : public pp::Module { 953 public: 954 CdmAdapterModule() : pp::Module() { 955 // This function blocks the renderer thread (PluginInstance::Initialize()). 956 // Move this call to other places if this may be a concern in the future. 957 INITIALIZE_CDM_MODULE(); 958 } 959 virtual ~CdmAdapterModule() { 960 DeinitializeCdmModule(); 961 } 962 963 virtual pp::Instance* CreateInstance(PP_Instance instance) { 964 return new CdmAdapter(instance, this); 965 } 966}; 967 968} // namespace media 969 970namespace pp { 971 972// Factory function for your specialization of the Module object. 973Module* CreateModule() { 974 return new media::CdmAdapterModule(); 975} 976 977} // namespace pp 978