OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cdm/cdm_adapter.h" | 5 #include "media/cdm/cdm_adapter.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 } | 326 } |
327 } | 327 } |
328 | 328 |
329 } // namespace | 329 } // namespace |
330 | 330 |
331 // static | 331 // static |
332 void CdmAdapter::Create( | 332 void CdmAdapter::Create( |
333 const std::string& key_system, | 333 const std::string& key_system, |
334 const base::FilePath& cdm_path, | 334 const base::FilePath& cdm_path, |
335 const CdmConfig& cdm_config, | 335 const CdmConfig& cdm_config, |
336 scoped_ptr<CdmAllocator> allocator, | 336 std::unique_ptr<CdmAllocator> allocator, |
337 const CreateCdmFileIOCB& create_cdm_file_io_cb, | 337 const CreateCdmFileIOCB& create_cdm_file_io_cb, |
338 const SessionMessageCB& session_message_cb, | 338 const SessionMessageCB& session_message_cb, |
339 const SessionClosedCB& session_closed_cb, | 339 const SessionClosedCB& session_closed_cb, |
340 const LegacySessionErrorCB& legacy_session_error_cb, | 340 const LegacySessionErrorCB& legacy_session_error_cb, |
341 const SessionKeysChangeCB& session_keys_change_cb, | 341 const SessionKeysChangeCB& session_keys_change_cb, |
342 const SessionExpirationUpdateCB& session_expiration_update_cb, | 342 const SessionExpirationUpdateCB& session_expiration_update_cb, |
343 const CdmCreatedCB& cdm_created_cb) { | 343 const CdmCreatedCB& cdm_created_cb) { |
344 DCHECK(!key_system.empty()); | 344 DCHECK(!key_system.empty()); |
345 DCHECK(!session_message_cb.is_null()); | 345 DCHECK(!session_message_cb.is_null()); |
346 DCHECK(!session_closed_cb.is_null()); | 346 DCHECK(!session_closed_cb.is_null()); |
347 DCHECK(!legacy_session_error_cb.is_null()); | 347 DCHECK(!legacy_session_error_cb.is_null()); |
348 DCHECK(!session_keys_change_cb.is_null()); | 348 DCHECK(!session_keys_change_cb.is_null()); |
349 DCHECK(!session_expiration_update_cb.is_null()); | 349 DCHECK(!session_expiration_update_cb.is_null()); |
350 | 350 |
351 scoped_refptr<CdmAdapter> cdm = new CdmAdapter( | 351 scoped_refptr<CdmAdapter> cdm = new CdmAdapter( |
352 key_system, cdm_config, std::move(allocator), create_cdm_file_io_cb, | 352 key_system, cdm_config, std::move(allocator), create_cdm_file_io_cb, |
353 session_message_cb, session_closed_cb, legacy_session_error_cb, | 353 session_message_cb, session_closed_cb, legacy_session_error_cb, |
354 session_keys_change_cb, session_expiration_update_cb); | 354 session_keys_change_cb, session_expiration_update_cb); |
355 | 355 |
356 // |cdm| ownership passed to the promise. | 356 // |cdm| ownership passed to the promise. |
357 scoped_ptr<CdmInitializedPromise> cdm_created_promise( | 357 std::unique_ptr<CdmInitializedPromise> cdm_created_promise( |
358 new CdmInitializedPromise(cdm_created_cb, cdm)); | 358 new CdmInitializedPromise(cdm_created_cb, cdm)); |
359 | 359 |
360 cdm->Initialize(cdm_path, std::move(cdm_created_promise)); | 360 cdm->Initialize(cdm_path, std::move(cdm_created_promise)); |
361 } | 361 } |
362 | 362 |
363 CdmAdapter::CdmAdapter( | 363 CdmAdapter::CdmAdapter( |
364 const std::string& key_system, | 364 const std::string& key_system, |
365 const CdmConfig& cdm_config, | 365 const CdmConfig& cdm_config, |
366 scoped_ptr<CdmAllocator> allocator, | 366 std::unique_ptr<CdmAllocator> allocator, |
367 const CreateCdmFileIOCB& create_cdm_file_io_cb, | 367 const CreateCdmFileIOCB& create_cdm_file_io_cb, |
368 const SessionMessageCB& session_message_cb, | 368 const SessionMessageCB& session_message_cb, |
369 const SessionClosedCB& session_closed_cb, | 369 const SessionClosedCB& session_closed_cb, |
370 const LegacySessionErrorCB& legacy_session_error_cb, | 370 const LegacySessionErrorCB& legacy_session_error_cb, |
371 const SessionKeysChangeCB& session_keys_change_cb, | 371 const SessionKeysChangeCB& session_keys_change_cb, |
372 const SessionExpirationUpdateCB& session_expiration_update_cb) | 372 const SessionExpirationUpdateCB& session_expiration_update_cb) |
373 : key_system_(key_system), | 373 : key_system_(key_system), |
374 cdm_config_(cdm_config), | 374 cdm_config_(cdm_config), |
375 session_message_cb_(session_message_cb), | 375 session_message_cb_(session_message_cb), |
376 session_closed_cb_(session_closed_cb), | 376 session_closed_cb_(session_closed_cb), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 | 418 |
419 CdmWrapper* cdm = CdmWrapper::Create(create_cdm_func, key_system.data(), | 419 CdmWrapper* cdm = CdmWrapper::Create(create_cdm_func, key_system.data(), |
420 key_system.size(), GetCdmHost, this); | 420 key_system.size(), GetCdmHost, this); |
421 | 421 |
422 DVLOG(1) << "CDM instance for " + key_system + (cdm ? "" : " could not be") + | 422 DVLOG(1) << "CDM instance for " + key_system + (cdm ? "" : " could not be") + |
423 " created."; | 423 " created."; |
424 return cdm; | 424 return cdm; |
425 } | 425 } |
426 | 426 |
427 void CdmAdapter::Initialize(const base::FilePath& cdm_path, | 427 void CdmAdapter::Initialize(const base::FilePath& cdm_path, |
428 scoped_ptr<media::SimpleCdmPromise> promise) { | 428 std::unique_ptr<media::SimpleCdmPromise> promise) { |
429 cdm_.reset(CreateCdmInstance(key_system_, cdm_path)); | 429 cdm_.reset(CreateCdmInstance(key_system_, cdm_path)); |
430 if (!cdm_) { | 430 if (!cdm_) { |
431 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, | 431 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
432 "Unable to create CDM."); | 432 "Unable to create CDM."); |
433 return; | 433 return; |
434 } | 434 } |
435 | 435 |
436 cdm_->Initialize(cdm_config_.allow_distinctive_identifier, | 436 cdm_->Initialize(cdm_config_.allow_distinctive_identifier, |
437 cdm_config_.allow_persistent_state); | 437 cdm_config_.allow_persistent_state); |
438 promise->resolve(); | 438 promise->resolve(); |
439 } | 439 } |
440 | 440 |
441 void CdmAdapter::SetServerCertificate(const std::vector<uint8_t>& certificate, | 441 void CdmAdapter::SetServerCertificate( |
442 scoped_ptr<SimpleCdmPromise> promise) { | 442 const std::vector<uint8_t>& certificate, |
| 443 std::unique_ptr<SimpleCdmPromise> promise) { |
443 DCHECK(task_runner_->BelongsToCurrentThread()); | 444 DCHECK(task_runner_->BelongsToCurrentThread()); |
444 | 445 |
445 if (certificate.size() < limits::kMinCertificateLength || | 446 if (certificate.size() < limits::kMinCertificateLength || |
446 certificate.size() > limits::kMaxCertificateLength) { | 447 certificate.size() > limits::kMaxCertificateLength) { |
447 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, | 448 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
448 "Incorrect certificate."); | 449 "Incorrect certificate."); |
449 return; | 450 return; |
450 } | 451 } |
451 | 452 |
452 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); | 453 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
453 cdm_->SetServerCertificate(promise_id, certificate.data(), | 454 cdm_->SetServerCertificate(promise_id, certificate.data(), |
454 certificate.size()); | 455 certificate.size()); |
455 } | 456 } |
456 | 457 |
457 void CdmAdapter::CreateSessionAndGenerateRequest( | 458 void CdmAdapter::CreateSessionAndGenerateRequest( |
458 SessionType session_type, | 459 SessionType session_type, |
459 EmeInitDataType init_data_type, | 460 EmeInitDataType init_data_type, |
460 const std::vector<uint8_t>& init_data, | 461 const std::vector<uint8_t>& init_data, |
461 scoped_ptr<NewSessionCdmPromise> promise) { | 462 std::unique_ptr<NewSessionCdmPromise> promise) { |
462 DCHECK(task_runner_->BelongsToCurrentThread()); | 463 DCHECK(task_runner_->BelongsToCurrentThread()); |
463 | 464 |
464 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); | 465 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
465 cdm_->CreateSessionAndGenerateRequest( | 466 cdm_->CreateSessionAndGenerateRequest( |
466 promise_id, ToCdmSessionType(session_type), | 467 promise_id, ToCdmSessionType(session_type), |
467 ToCdmInitDataType(init_data_type), init_data.data(), init_data.size()); | 468 ToCdmInitDataType(init_data_type), init_data.data(), init_data.size()); |
468 } | 469 } |
469 | 470 |
470 void CdmAdapter::LoadSession(SessionType session_type, | 471 void CdmAdapter::LoadSession(SessionType session_type, |
471 const std::string& session_id, | 472 const std::string& session_id, |
472 scoped_ptr<NewSessionCdmPromise> promise) { | 473 std::unique_ptr<NewSessionCdmPromise> promise) { |
473 DCHECK(task_runner_->BelongsToCurrentThread()); | 474 DCHECK(task_runner_->BelongsToCurrentThread()); |
474 | 475 |
475 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); | 476 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
476 cdm_->LoadSession(promise_id, ToCdmSessionType(session_type), | 477 cdm_->LoadSession(promise_id, ToCdmSessionType(session_type), |
477 session_id.data(), session_id.size()); | 478 session_id.data(), session_id.size()); |
478 } | 479 } |
479 | 480 |
480 void CdmAdapter::UpdateSession(const std::string& session_id, | 481 void CdmAdapter::UpdateSession(const std::string& session_id, |
481 const std::vector<uint8_t>& response, | 482 const std::vector<uint8_t>& response, |
482 scoped_ptr<SimpleCdmPromise> promise) { | 483 std::unique_ptr<SimpleCdmPromise> promise) { |
483 DCHECK(task_runner_->BelongsToCurrentThread()); | 484 DCHECK(task_runner_->BelongsToCurrentThread()); |
484 DCHECK(!session_id.empty()); | 485 DCHECK(!session_id.empty()); |
485 DCHECK(!response.empty()); | 486 DCHECK(!response.empty()); |
486 | 487 |
487 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); | 488 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
488 cdm_->UpdateSession(promise_id, session_id.data(), session_id.size(), | 489 cdm_->UpdateSession(promise_id, session_id.data(), session_id.size(), |
489 response.data(), response.size()); | 490 response.data(), response.size()); |
490 } | 491 } |
491 | 492 |
492 void CdmAdapter::CloseSession(const std::string& session_id, | 493 void CdmAdapter::CloseSession(const std::string& session_id, |
493 scoped_ptr<SimpleCdmPromise> promise) { | 494 std::unique_ptr<SimpleCdmPromise> promise) { |
494 DCHECK(task_runner_->BelongsToCurrentThread()); | 495 DCHECK(task_runner_->BelongsToCurrentThread()); |
495 DCHECK(!session_id.empty()); | 496 DCHECK(!session_id.empty()); |
496 | 497 |
497 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); | 498 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
498 cdm_->CloseSession(promise_id, session_id.data(), session_id.size()); | 499 cdm_->CloseSession(promise_id, session_id.data(), session_id.size()); |
499 } | 500 } |
500 | 501 |
501 void CdmAdapter::RemoveSession(const std::string& session_id, | 502 void CdmAdapter::RemoveSession(const std::string& session_id, |
502 scoped_ptr<SimpleCdmPromise> promise) { | 503 std::unique_ptr<SimpleCdmPromise> promise) { |
503 DCHECK(task_runner_->BelongsToCurrentThread()); | 504 DCHECK(task_runner_->BelongsToCurrentThread()); |
504 DCHECK(!session_id.empty()); | 505 DCHECK(!session_id.empty()); |
505 | 506 |
506 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); | 507 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
507 cdm_->RemoveSession(promise_id, session_id.data(), session_id.size()); | 508 cdm_->RemoveSession(promise_id, session_id.data(), session_id.size()); |
508 } | 509 } |
509 | 510 |
510 CdmContext* CdmAdapter::GetCdmContext() { | 511 CdmContext* CdmAdapter::GetCdmContext() { |
511 DCHECK(task_runner_->BelongsToCurrentThread()); | 512 DCHECK(task_runner_->BelongsToCurrentThread()); |
512 return this; | 513 return this; |
(...skipping 24 matching lines...) Expand all Loading... |
537 NOTREACHED() << "Unexpected StreamType " << stream_type; | 538 NOTREACHED() << "Unexpected StreamType " << stream_type; |
538 } | 539 } |
539 | 540 |
540 void CdmAdapter::Decrypt(StreamType stream_type, | 541 void CdmAdapter::Decrypt(StreamType stream_type, |
541 const scoped_refptr<DecoderBuffer>& encrypted, | 542 const scoped_refptr<DecoderBuffer>& encrypted, |
542 const DecryptCB& decrypt_cb) { | 543 const DecryptCB& decrypt_cb) { |
543 DCHECK(task_runner_->BelongsToCurrentThread()); | 544 DCHECK(task_runner_->BelongsToCurrentThread()); |
544 | 545 |
545 cdm::InputBuffer input_buffer; | 546 cdm::InputBuffer input_buffer; |
546 std::vector<cdm::SubsampleEntry> subsamples; | 547 std::vector<cdm::SubsampleEntry> subsamples; |
547 scoped_ptr<DecryptedBlockImpl> decrypted_block(new DecryptedBlockImpl()); | 548 std::unique_ptr<DecryptedBlockImpl> decrypted_block(new DecryptedBlockImpl()); |
548 | 549 |
549 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); | 550 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); |
550 cdm::Status status = cdm_->Decrypt(input_buffer, decrypted_block.get()); | 551 cdm::Status status = cdm_->Decrypt(input_buffer, decrypted_block.get()); |
551 | 552 |
552 if (status != cdm::kSuccess) { | 553 if (status != cdm::kSuccess) { |
553 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; | 554 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; |
554 decrypt_cb.Run(ToMediaDecryptorStatus(status), nullptr); | 555 decrypt_cb.Run(ToMediaDecryptorStatus(status), nullptr); |
555 return; | 556 return; |
556 } | 557 } |
557 | 558 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 init_cb.Run(true); | 638 init_cb.Run(true); |
638 } | 639 } |
639 | 640 |
640 void CdmAdapter::DecryptAndDecodeAudio( | 641 void CdmAdapter::DecryptAndDecodeAudio( |
641 const scoped_refptr<DecoderBuffer>& encrypted, | 642 const scoped_refptr<DecoderBuffer>& encrypted, |
642 const AudioDecodeCB& audio_decode_cb) { | 643 const AudioDecodeCB& audio_decode_cb) { |
643 DCHECK(task_runner_->BelongsToCurrentThread()); | 644 DCHECK(task_runner_->BelongsToCurrentThread()); |
644 | 645 |
645 cdm::InputBuffer input_buffer; | 646 cdm::InputBuffer input_buffer; |
646 std::vector<cdm::SubsampleEntry> subsamples; | 647 std::vector<cdm::SubsampleEntry> subsamples; |
647 scoped_ptr<AudioFramesImpl> audio_frames(new AudioFramesImpl()); | 648 std::unique_ptr<AudioFramesImpl> audio_frames(new AudioFramesImpl()); |
648 | 649 |
649 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); | 650 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); |
650 cdm::Status status = | 651 cdm::Status status = |
651 cdm_->DecryptAndDecodeSamples(input_buffer, audio_frames.get()); | 652 cdm_->DecryptAndDecodeSamples(input_buffer, audio_frames.get()); |
652 | 653 |
653 const Decryptor::AudioFrames empty_frames; | 654 const Decryptor::AudioFrames empty_frames; |
654 if (status != cdm::kSuccess) { | 655 if (status != cdm::kSuccess) { |
655 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; | 656 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; |
656 audio_decode_cb.Run(ToMediaDecryptorStatus(status), empty_frames); | 657 audio_decode_cb.Run(ToMediaDecryptorStatus(status), empty_frames); |
657 return; | 658 return; |
(...skipping 13 matching lines...) Expand all Loading... |
671 | 672 |
672 void CdmAdapter::DecryptAndDecodeVideo( | 673 void CdmAdapter::DecryptAndDecodeVideo( |
673 const scoped_refptr<DecoderBuffer>& encrypted, | 674 const scoped_refptr<DecoderBuffer>& encrypted, |
674 const VideoDecodeCB& video_decode_cb) { | 675 const VideoDecodeCB& video_decode_cb) { |
675 DCHECK(task_runner_->BelongsToCurrentThread()); | 676 DCHECK(task_runner_->BelongsToCurrentThread()); |
676 DVLOG(3) << __FUNCTION__ | 677 DVLOG(3) << __FUNCTION__ |
677 << " encrypted: " << encrypted->AsHumanReadableString(); | 678 << " encrypted: " << encrypted->AsHumanReadableString(); |
678 | 679 |
679 cdm::InputBuffer input_buffer; | 680 cdm::InputBuffer input_buffer; |
680 std::vector<cdm::SubsampleEntry> subsamples; | 681 std::vector<cdm::SubsampleEntry> subsamples; |
681 scoped_ptr<VideoFrameImpl> video_frame = allocator_->CreateCdmVideoFrame(); | 682 std::unique_ptr<VideoFrameImpl> video_frame = |
| 683 allocator_->CreateCdmVideoFrame(); |
682 | 684 |
683 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); | 685 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); |
684 cdm::Status status = | 686 cdm::Status status = |
685 cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get()); | 687 cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get()); |
686 | 688 |
687 if (status != cdm::kSuccess) { | 689 if (status != cdm::kSuccess) { |
688 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; | 690 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; |
689 video_decode_cb.Run(ToMediaDecryptorStatus(status), nullptr); | 691 video_decode_cb.Run(ToMediaDecryptorStatus(status), nullptr); |
690 return; | 692 return; |
691 } | 693 } |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 DCHECK(task_runner_->BelongsToCurrentThread()); | 901 DCHECK(task_runner_->BelongsToCurrentThread()); |
900 | 902 |
901 std::unique_ptr<CdmFileIO> file_io = create_cdm_file_io_cb_.Run(client); | 903 std::unique_ptr<CdmFileIO> file_io = create_cdm_file_io_cb_.Run(client); |
902 | 904 |
903 // The CDM owns the returned object and must call FileIO::Close() | 905 // The CDM owns the returned object and must call FileIO::Close() |
904 // to release it. | 906 // to release it. |
905 return file_io.release(); | 907 return file_io.release(); |
906 } | 908 } |
907 | 909 |
908 bool CdmAdapter::AudioFramesDataToAudioFrames( | 910 bool CdmAdapter::AudioFramesDataToAudioFrames( |
909 scoped_ptr<AudioFramesImpl> audio_frames, | 911 std::unique_ptr<AudioFramesImpl> audio_frames, |
910 Decryptor::AudioFrames* result_frames) { | 912 Decryptor::AudioFrames* result_frames) { |
911 const uint8_t* data = audio_frames->FrameBuffer()->Data(); | 913 const uint8_t* data = audio_frames->FrameBuffer()->Data(); |
912 const size_t data_size = audio_frames->FrameBuffer()->Size(); | 914 const size_t data_size = audio_frames->FrameBuffer()->Size(); |
913 size_t bytes_left = data_size; | 915 size_t bytes_left = data_size; |
914 const SampleFormat sample_format = | 916 const SampleFormat sample_format = |
915 ToMediaSampleFormat(audio_frames->Format()); | 917 ToMediaSampleFormat(audio_frames->Format()); |
916 const int audio_channel_count = | 918 const int audio_channel_count = |
917 ChannelLayoutToChannelCount(audio_channel_layout_); | 919 ChannelLayoutToChannelCount(audio_channel_layout_); |
918 const int audio_bytes_per_frame = | 920 const int audio_bytes_per_frame = |
919 SampleFormatToBytesPerChannel(sample_format) * audio_channel_count; | 921 SampleFormatToBytesPerChannel(sample_format) * audio_channel_count; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 result_frames->push_back(frame); | 960 result_frames->push_back(frame); |
959 | 961 |
960 data += frame_size; | 962 data += frame_size; |
961 bytes_left -= frame_size; | 963 bytes_left -= frame_size; |
962 } while (bytes_left > 0); | 964 } while (bytes_left > 0); |
963 | 965 |
964 return true; | 966 return true; |
965 } | 967 } |
966 | 968 |
967 } // namespace media | 969 } // namespace media |
OLD | NEW |