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 |