| 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" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 16 #include "media/base/audio_decoder_config.h" | 16 #include "media/base/audio_decoder_config.h" |
| 17 #include "media/base/cdm_initialized_promise.h" | 17 #include "media/base/cdm_initialized_promise.h" |
| 18 #include "media/base/cdm_key_information.h" | 18 #include "media/base/cdm_key_information.h" |
| 19 #include "media/base/channel_layout.h" | 19 #include "media/base/channel_layout.h" |
| 20 #include "media/base/decoder_buffer.h" | 20 #include "media/base/decoder_buffer.h" |
| 21 #include "media/base/decrypt_config.h" | 21 #include "media/base/decrypt_config.h" |
| 22 #include "media/base/limits.h" | 22 #include "media/base/limits.h" |
| 23 #include "media/base/sample_format.h" | 23 #include "media/base/sample_format.h" |
| 24 #include "media/base/video_codecs.h" | 24 #include "media/base/video_codecs.h" |
| 25 #include "media/base/video_decoder_config.h" | 25 #include "media/base/video_decoder_config.h" |
| 26 #include "media/base/video_frame.h" | 26 #include "media/base/video_frame.h" |
| 27 #include "media/base/video_types.h" | 27 #include "media/base/video_types.h" |
| 28 #include "media/cdm/cdm_buffer_impl.h" | 28 #include "media/cdm/cdm_buffer.h" |
| 29 #include "media/cdm/cdm_buffer_allocator.h" |
| 29 #include "media/cdm/cdm_helpers.h" | 30 #include "media/cdm/cdm_helpers.h" |
| 31 #include "media/cdm/cdm_video_frame.h" |
| 30 #include "media/cdm/cdm_wrapper.h" | 32 #include "media/cdm/cdm_wrapper.h" |
| 31 #include "ui/gfx/geometry/rect.h" | 33 #include "ui/gfx/geometry/rect.h" |
| 32 | 34 |
| 33 namespace media { | 35 namespace media { |
| 34 | 36 |
| 35 namespace { | 37 namespace { |
| 36 | 38 |
| 37 cdm::SessionType ToCdmSessionType(MediaKeys::SessionType session_type) { | 39 cdm::SessionType ToCdmSessionType(MediaKeys::SessionType session_type) { |
| 38 switch (session_type) { | 40 switch (session_type) { |
| 39 case MediaKeys::TEMPORARY_SESSION: | 41 case MediaKeys::TEMPORARY_SESSION: |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 320 } |
| 319 } | 321 } |
| 320 | 322 |
| 321 } // namespace | 323 } // namespace |
| 322 | 324 |
| 323 // static | 325 // static |
| 324 void CdmAdapter::Create( | 326 void CdmAdapter::Create( |
| 325 const std::string& key_system, | 327 const std::string& key_system, |
| 326 const base::FilePath& cdm_path, | 328 const base::FilePath& cdm_path, |
| 327 const CdmConfig& cdm_config, | 329 const CdmConfig& cdm_config, |
| 330 scoped_ptr<CdmBufferAllocator> allocator, |
| 328 const SessionMessageCB& session_message_cb, | 331 const SessionMessageCB& session_message_cb, |
| 329 const SessionClosedCB& session_closed_cb, | 332 const SessionClosedCB& session_closed_cb, |
| 330 const LegacySessionErrorCB& legacy_session_error_cb, | 333 const LegacySessionErrorCB& legacy_session_error_cb, |
| 331 const SessionKeysChangeCB& session_keys_change_cb, | 334 const SessionKeysChangeCB& session_keys_change_cb, |
| 332 const SessionExpirationUpdateCB& session_expiration_update_cb, | 335 const SessionExpirationUpdateCB& session_expiration_update_cb, |
| 333 const CdmCreatedCB& cdm_created_cb) { | 336 const CdmCreatedCB& cdm_created_cb) { |
| 334 DCHECK(!key_system.empty()); | 337 DCHECK(!key_system.empty()); |
| 335 DCHECK(!session_message_cb.is_null()); | 338 DCHECK(!session_message_cb.is_null()); |
| 336 DCHECK(!session_closed_cb.is_null()); | 339 DCHECK(!session_closed_cb.is_null()); |
| 337 DCHECK(!legacy_session_error_cb.is_null()); | 340 DCHECK(!legacy_session_error_cb.is_null()); |
| 338 DCHECK(!session_keys_change_cb.is_null()); | 341 DCHECK(!session_keys_change_cb.is_null()); |
| 339 DCHECK(!session_expiration_update_cb.is_null()); | 342 DCHECK(!session_expiration_update_cb.is_null()); |
| 340 | 343 |
| 341 scoped_refptr<CdmAdapter> cdm = | 344 scoped_refptr<CdmAdapter> cdm = new CdmAdapter( |
| 342 new CdmAdapter(key_system, cdm_config, session_message_cb, | 345 key_system, cdm_config, std::move(allocator), session_message_cb, |
| 343 session_closed_cb, legacy_session_error_cb, | 346 session_closed_cb, legacy_session_error_cb, session_keys_change_cb, |
| 344 session_keys_change_cb, session_expiration_update_cb); | 347 session_expiration_update_cb); |
| 345 | 348 |
| 346 // |cdm| ownership passed to the promise. | 349 // |cdm| ownership passed to the promise. |
| 347 scoped_ptr<CdmInitializedPromise> cdm_created_promise( | 350 scoped_ptr<CdmInitializedPromise> cdm_created_promise( |
| 348 new CdmInitializedPromise(cdm_created_cb, cdm)); | 351 new CdmInitializedPromise(cdm_created_cb, cdm)); |
| 349 | 352 |
| 350 cdm->Initialize(cdm_path, std::move(cdm_created_promise)); | 353 cdm->Initialize(cdm_path, std::move(cdm_created_promise)); |
| 351 } | 354 } |
| 352 | 355 |
| 353 CdmAdapter::CdmAdapter( | 356 CdmAdapter::CdmAdapter( |
| 354 const std::string& key_system, | 357 const std::string& key_system, |
| 355 const CdmConfig& cdm_config, | 358 const CdmConfig& cdm_config, |
| 359 scoped_ptr<CdmBufferAllocator> allocator, |
| 356 const SessionMessageCB& session_message_cb, | 360 const SessionMessageCB& session_message_cb, |
| 357 const SessionClosedCB& session_closed_cb, | 361 const SessionClosedCB& session_closed_cb, |
| 358 const LegacySessionErrorCB& legacy_session_error_cb, | 362 const LegacySessionErrorCB& legacy_session_error_cb, |
| 359 const SessionKeysChangeCB& session_keys_change_cb, | 363 const SessionKeysChangeCB& session_keys_change_cb, |
| 360 const SessionExpirationUpdateCB& session_expiration_update_cb) | 364 const SessionExpirationUpdateCB& session_expiration_update_cb) |
| 361 : key_system_(key_system), | 365 : key_system_(key_system), |
| 362 cdm_config_(cdm_config), | 366 cdm_config_(cdm_config), |
| 363 session_message_cb_(session_message_cb), | 367 session_message_cb_(session_message_cb), |
| 364 session_closed_cb_(session_closed_cb), | 368 session_closed_cb_(session_closed_cb), |
| 365 legacy_session_error_cb_(legacy_session_error_cb), | 369 legacy_session_error_cb_(legacy_session_error_cb), |
| 366 session_keys_change_cb_(session_keys_change_cb), | 370 session_keys_change_cb_(session_keys_change_cb), |
| 367 session_expiration_update_cb_(session_expiration_update_cb), | 371 session_expiration_update_cb_(session_expiration_update_cb), |
| 368 audio_samples_per_second_(0), | 372 audio_samples_per_second_(0), |
| 369 audio_channel_layout_(CHANNEL_LAYOUT_NONE), | 373 audio_channel_layout_(CHANNEL_LAYOUT_NONE), |
| 374 allocator_(std::move(allocator)), |
| 370 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 375 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 371 weak_factory_(this) { | 376 weak_factory_(this) { |
| 372 DCHECK(!key_system_.empty()); | 377 DCHECK(!key_system_.empty()); |
| 373 DCHECK(!session_message_cb_.is_null()); | 378 DCHECK(!session_message_cb_.is_null()); |
| 374 DCHECK(!session_closed_cb_.is_null()); | 379 DCHECK(!session_closed_cb_.is_null()); |
| 375 DCHECK(!legacy_session_error_cb_.is_null()); | 380 DCHECK(!legacy_session_error_cb_.is_null()); |
| 376 DCHECK(!session_keys_change_cb_.is_null()); | 381 DCHECK(!session_keys_change_cb_.is_null()); |
| 377 DCHECK(!session_expiration_update_cb_.is_null()); | 382 DCHECK(!session_expiration_update_cb_.is_null()); |
| 383 DCHECK(allocator_); |
| 378 } | 384 } |
| 379 | 385 |
| 380 CdmAdapter::~CdmAdapter() {} | 386 CdmAdapter::~CdmAdapter() {} |
| 381 | 387 |
| 382 CdmWrapper* CdmAdapter::CreateCdmInstance(const std::string& key_system, | 388 CdmWrapper* CdmAdapter::CreateCdmInstance(const std::string& key_system, |
| 383 const base::FilePath& cdm_path) { | 389 const base::FilePath& cdm_path) { |
| 384 DCHECK(task_runner_->BelongsToCurrentThread()); | 390 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 385 | 391 |
| 386 // TODO(jrummell): We need to call INITIALIZE_CDM_MODULE() and | 392 // TODO(jrummell): We need to call INITIALIZE_CDM_MODULE() and |
| 387 // DeinitializeCdmModule(). However, that should only be done once for the | 393 // DeinitializeCdmModule(). However, that should only be done once for the |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 | 662 |
| 657 void CdmAdapter::DecryptAndDecodeVideo( | 663 void CdmAdapter::DecryptAndDecodeVideo( |
| 658 const scoped_refptr<DecoderBuffer>& encrypted, | 664 const scoped_refptr<DecoderBuffer>& encrypted, |
| 659 const VideoDecodeCB& video_decode_cb) { | 665 const VideoDecodeCB& video_decode_cb) { |
| 660 DCHECK(task_runner_->BelongsToCurrentThread()); | 666 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 661 DVLOG(3) << __FUNCTION__ | 667 DVLOG(3) << __FUNCTION__ |
| 662 << " encrypted: " << encrypted->AsHumanReadableString(); | 668 << " encrypted: " << encrypted->AsHumanReadableString(); |
| 663 | 669 |
| 664 cdm::InputBuffer input_buffer; | 670 cdm::InputBuffer input_buffer; |
| 665 std::vector<cdm::SubsampleEntry> subsamples; | 671 std::vector<cdm::SubsampleEntry> subsamples; |
| 666 scoped_ptr<VideoFrameImpl> video_frame(new VideoFrameImpl()); | 672 scoped_ptr<CdmVideoFrame> video_frame = allocator_->CreateCdmVideoFrame(); |
| 667 | 673 |
| 668 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); | 674 ToCdmInputBuffer(encrypted, &subsamples, &input_buffer); |
| 669 cdm::Status status = | 675 cdm::Status status = |
| 670 cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get()); | 676 cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get()); |
| 671 | 677 |
| 672 if (status != cdm::kSuccess) { | 678 if (status != cdm::kSuccess) { |
| 673 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; | 679 DVLOG(1) << __FUNCTION__ << " failed with cdm::Error " << status; |
| 674 video_decode_cb.Run(ToMediaDecryptorStatus(status), nullptr); | 680 video_decode_cb.Run(ToMediaDecryptorStatus(status), nullptr); |
| 675 return; | 681 return; |
| 676 } | 682 } |
| 677 | 683 |
| 678 uint8_t* frame_data = video_frame->FrameBuffer()->Data(); | 684 scoped_refptr<VideoFrame> decoded_frame = |
| 679 gfx::Size frame_size(video_frame->Size().width, video_frame->Size().height); | 685 video_frame->CreateVideoFrame(natural_size_); |
| 680 scoped_refptr<VideoFrame> decoded_frame = VideoFrame::WrapExternalYuvData( | |
| 681 PIXEL_FORMAT_YV12, frame_size, gfx::Rect(frame_size), natural_size_, | |
| 682 video_frame->Stride(VideoFrameImpl::kYPlane), | |
| 683 video_frame->Stride(VideoFrameImpl::kUPlane), | |
| 684 video_frame->Stride(VideoFrameImpl::kVPlane), | |
| 685 frame_data + video_frame->PlaneOffset(VideoFrameImpl::kYPlane), | |
| 686 frame_data + video_frame->PlaneOffset(VideoFrameImpl::kUPlane), | |
| 687 frame_data + video_frame->PlaneOffset(VideoFrameImpl::kVPlane), | |
| 688 base::TimeDelta::FromMicroseconds(video_frame->Timestamp())); | |
| 689 video_decode_cb.Run(Decryptor::kSuccess, decoded_frame); | 686 video_decode_cb.Run(Decryptor::kSuccess, decoded_frame); |
| 690 } | 687 } |
| 691 | 688 |
| 692 void CdmAdapter::ResetDecoder(StreamType stream_type) { | 689 void CdmAdapter::ResetDecoder(StreamType stream_type) { |
| 693 DCHECK(task_runner_->BelongsToCurrentThread()); | 690 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 694 cdm_->ResetDecoder(ToCdmStreamType(stream_type)); | 691 cdm_->ResetDecoder(ToCdmStreamType(stream_type)); |
| 695 } | 692 } |
| 696 | 693 |
| 697 void CdmAdapter::DeinitializeDecoder(StreamType stream_type) { | 694 void CdmAdapter::DeinitializeDecoder(StreamType stream_type) { |
| 698 DCHECK(task_runner_->BelongsToCurrentThread()); | 695 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 699 cdm_->DeinitializeDecoder(ToCdmStreamType(stream_type)); | 696 cdm_->DeinitializeDecoder(ToCdmStreamType(stream_type)); |
| 700 | 697 |
| 701 // Reset the saved values from initializing the decoder. | 698 // Reset the saved values from initializing the decoder. |
| 702 switch (stream_type) { | 699 switch (stream_type) { |
| 703 case Decryptor::kAudio: | 700 case Decryptor::kAudio: |
| 704 audio_samples_per_second_ = 0; | 701 audio_samples_per_second_ = 0; |
| 705 audio_channel_layout_ = CHANNEL_LAYOUT_NONE; | 702 audio_channel_layout_ = CHANNEL_LAYOUT_NONE; |
| 706 break; | 703 break; |
| 707 case Decryptor::kVideo: | 704 case Decryptor::kVideo: |
| 708 natural_size_ = gfx::Size(); | 705 natural_size_ = gfx::Size(); |
| 709 break; | 706 break; |
| 710 } | 707 } |
| 711 } | 708 } |
| 712 | 709 |
| 713 cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) { | 710 cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) { |
| 714 DCHECK(task_runner_->BelongsToCurrentThread()); | 711 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 715 return CdmBuffer::Create(capacity); | 712 scoped_refptr<CdmBuffer> buffer = allocator_->Allocate(capacity); |
| 713 |
| 714 // Since the CDM only expects a pointer, we create a dummy reference to |
| 715 // |buffer|. When the buffer is assigned to a helper object |
| 716 // (DecryptedBlockImpl, VideoFrameImpl, AudioFramesImpl) it will take the |
| 717 // ownership of the buffer. |
| 718 buffer->AddRef(); |
| 719 return buffer.get(); |
| 716 } | 720 } |
| 717 | 721 |
| 718 void CdmAdapter::SetTimer(int64_t delay_ms, void* context) { | 722 void CdmAdapter::SetTimer(int64_t delay_ms, void* context) { |
| 719 DCHECK(task_runner_->BelongsToCurrentThread()); | 723 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 720 task_runner_->PostDelayedTask(FROM_HERE, | 724 task_runner_->PostDelayedTask(FROM_HERE, |
| 721 base::Bind(&CdmAdapter::TimerExpired, | 725 base::Bind(&CdmAdapter::TimerExpired, |
| 722 weak_factory_.GetWeakPtr(), context), | 726 weak_factory_.GetWeakPtr(), context), |
| 723 base::TimeDelta::FromMilliseconds(delay_ms)); | 727 base::TimeDelta::FromMilliseconds(delay_ms)); |
| 724 } | 728 } |
| 725 | 729 |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 result_frames->push_back(frame); | 955 result_frames->push_back(frame); |
| 952 | 956 |
| 953 data += frame_size; | 957 data += frame_size; |
| 954 bytes_left -= frame_size; | 958 bytes_left -= frame_size; |
| 955 } while (bytes_left > 0); | 959 } while (bytes_left > 0); |
| 956 | 960 |
| 957 return true; | 961 return true; |
| 958 } | 962 } |
| 959 | 963 |
| 960 } // namespace media | 964 } // namespace media |
| OLD | NEW |