| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <cstring> | 5 #include <cstring> |
| 6 #include <string> | 6 #include <string> |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 } | 434 } |
| 435 | 435 |
| 436 void VideoFrameImpl::set_timestamp(int64_t timestamp) { | 436 void VideoFrameImpl::set_timestamp(int64_t timestamp) { |
| 437 timestamp_ = timestamp; | 437 timestamp_ = timestamp; |
| 438 } | 438 } |
| 439 | 439 |
| 440 int64_t VideoFrameImpl::timestamp() const { | 440 int64_t VideoFrameImpl::timestamp() const { |
| 441 return timestamp_; | 441 return timestamp_; |
| 442 } | 442 } |
| 443 | 443 |
| 444 class AudioFramesImpl : public cdm::AudioFrames { |
| 445 public: |
| 446 AudioFramesImpl() : buffer_(NULL) {} |
| 447 virtual ~AudioFramesImpl() { |
| 448 if (buffer_) |
| 449 buffer_->Destroy(); |
| 450 } |
| 451 |
| 452 // AudioFrames implementation. |
| 453 virtual void set_buffer(cdm::Buffer* buffer) OVERRIDE { |
| 454 buffer_ = static_cast<PpbBuffer*>(buffer); |
| 455 } |
| 456 virtual cdm::Buffer* buffer() OVERRIDE { |
| 457 return buffer_; |
| 458 } |
| 459 |
| 460 private: |
| 461 PpbBuffer* buffer_; |
| 462 |
| 463 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl); |
| 464 }; |
| 465 |
| 444 // A wrapper class for abstracting away PPAPI interaction and threading for a | 466 // A wrapper class for abstracting away PPAPI interaction and threading for a |
| 445 // Content Decryption Module (CDM). | 467 // Content Decryption Module (CDM). |
| 446 class CdmWrapper : public pp::Instance, | 468 class CdmWrapper : public pp::Instance, |
| 447 public pp::ContentDecryptor_Private, | 469 public pp::ContentDecryptor_Private, |
| 448 public cdm::CdmHost { | 470 public cdm::CdmHost { |
| 449 public: | 471 public: |
| 450 CdmWrapper(PP_Instance instance, pp::Module* module); | 472 CdmWrapper(PP_Instance instance, pp::Module* module); |
| 451 virtual ~CdmWrapper(); | 473 virtual ~CdmWrapper(); |
| 452 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { | 474 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
| 453 return true; | 475 return true; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 481 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE; | 503 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE; |
| 482 | 504 |
| 483 // CdmHost methods. | 505 // CdmHost methods. |
| 484 virtual void SetTimer(int64 delay_ms) OVERRIDE; | 506 virtual void SetTimer(int64 delay_ms) OVERRIDE; |
| 485 virtual double GetCurrentWallTimeMs() OVERRIDE; | 507 virtual double GetCurrentWallTimeMs() OVERRIDE; |
| 486 | 508 |
| 487 private: | 509 private: |
| 488 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock; | 510 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock; |
| 489 typedef linked_ptr<KeyMessageImpl> LinkedKeyMessage; | 511 typedef linked_ptr<KeyMessageImpl> LinkedKeyMessage; |
| 490 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame; | 512 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame; |
| 513 typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames; |
| 491 | 514 |
| 492 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to | 515 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to |
| 493 // <code>callback_factory_</code> to ensure that calls into | 516 // <code>callback_factory_</code> to ensure that calls into |
| 494 // <code>PPP_ContentDecryptor_Private</code> are asynchronous. | 517 // <code>PPP_ContentDecryptor_Private</code> are asynchronous. |
| 495 void KeyAdded(int32_t result, const std::string& session_id); | 518 void KeyAdded(int32_t result, const std::string& session_id); |
| 496 void KeyMessage(int32_t result, const LinkedKeyMessage& message); | 519 void KeyMessage(int32_t result, const LinkedKeyMessage& message); |
| 497 void KeyError(int32_t result, const std::string& session_id); | 520 void KeyError(int32_t result, const std::string& session_id); |
| 498 void DeliverBlock(int32_t result, | 521 void DeliverBlock(int32_t result, |
| 499 const cdm::Status& status, | 522 const cdm::Status& status, |
| 500 const LinkedDecryptedBlock& decrypted_block, | 523 const LinkedDecryptedBlock& decrypted_block, |
| 501 const PP_DecryptTrackingInfo& tracking_info); | 524 const PP_DecryptTrackingInfo& tracking_info); |
| 502 void DecoderInitializeDone(int32_t result, | 525 void DecoderInitializeDone(int32_t result, |
| 503 PP_DecryptorStreamType decoder_type, | 526 PP_DecryptorStreamType decoder_type, |
| 504 uint32_t request_id, | 527 uint32_t request_id, |
| 505 bool success); | 528 bool success); |
| 506 void DecoderDeinitializeDone(int32_t result, | 529 void DecoderDeinitializeDone(int32_t result, |
| 507 PP_DecryptorStreamType decoder_type, | 530 PP_DecryptorStreamType decoder_type, |
| 508 uint32_t request_id); | 531 uint32_t request_id); |
| 509 void DecoderResetDone(int32_t result, | 532 void DecoderResetDone(int32_t result, |
| 510 PP_DecryptorStreamType decoder_type, | 533 PP_DecryptorStreamType decoder_type, |
| 511 uint32_t request_id); | 534 uint32_t request_id); |
| 512 void DeliverFrame(int32_t result, | 535 void DeliverFrame(int32_t result, |
| 513 const cdm::Status& status, | 536 const cdm::Status& status, |
| 514 const LinkedVideoFrame& video_frame, | 537 const LinkedVideoFrame& video_frame, |
| 515 const PP_DecryptTrackingInfo& tracking_info); | 538 const PP_DecryptTrackingInfo& tracking_info); |
| 539 void DeliverSamples(int32_t result, |
| 540 const cdm::Status& status, |
| 541 const LinkedAudioFrames& audio_frames, |
| 542 const PP_DecryptTrackingInfo& tracking_info); |
| 516 | 543 |
| 517 // Helper for SetTimer(). | 544 // Helper for SetTimer(). |
| 518 void TimerExpired(int32 result); | 545 void TimerExpired(int32 result); |
| 519 | 546 |
| 520 PpbBufferAllocator allocator_; | 547 PpbBufferAllocator allocator_; |
| 521 pp::CompletionCallbackFactory<CdmWrapper> callback_factory_; | 548 pp::CompletionCallbackFactory<CdmWrapper> callback_factory_; |
| 522 cdm::ContentDecryptionModule* cdm_; | 549 cdm::ContentDecryptionModule* cdm_; |
| 523 std::string key_system_; | 550 std::string key_system_; |
| 524 }; | 551 }; |
| 525 | 552 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type)); | 734 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type)); |
| 708 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone, | 735 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone, |
| 709 decoder_type, | 736 decoder_type, |
| 710 request_id)); | 737 request_id)); |
| 711 } | 738 } |
| 712 | 739 |
| 713 void CdmWrapper::DecryptAndDecode( | 740 void CdmWrapper::DecryptAndDecode( |
| 714 PP_DecryptorStreamType decoder_type, | 741 PP_DecryptorStreamType decoder_type, |
| 715 pp::Buffer_Dev encrypted_buffer, | 742 pp::Buffer_Dev encrypted_buffer, |
| 716 const PP_EncryptedBlockInfo& encrypted_block_info) { | 743 const PP_EncryptedBlockInfo& encrypted_block_info) { |
| 717 // TODO(tomfinegan): Remove this check when audio decoding is added. | |
| 718 PP_DCHECK(decoder_type == PP_DECRYPTORSTREAMTYPE_VIDEO); | |
| 719 PP_DCHECK(cdm_); | 744 PP_DCHECK(cdm_); |
| 720 | 745 |
| 721 cdm::InputBuffer input_buffer; | 746 cdm::InputBuffer input_buffer; |
| 722 std::vector<cdm::SubsampleEntry> subsamples; | 747 std::vector<cdm::SubsampleEntry> subsamples; |
| 723 if (!encrypted_buffer.is_null()) { | 748 if (!encrypted_buffer.is_null()) { |
| 724 ConfigureInputBuffer(encrypted_buffer, | 749 ConfigureInputBuffer(encrypted_buffer, |
| 725 encrypted_block_info, | 750 encrypted_block_info, |
| 726 &subsamples, | 751 &subsamples, |
| 727 &input_buffer); | 752 &input_buffer); |
| 728 } | 753 } |
| 729 | 754 |
| 730 LinkedVideoFrame video_frame(new VideoFrameImpl()); | 755 cdm::Status status = cdm::kDecodeError; |
| 731 cdm::Status status = cdm_->DecryptAndDecodeFrame(input_buffer, | 756 switch (decoder_type) { |
| 732 video_frame.get()); | 757 case PP_DECRYPTORSTREAMTYPE_VIDEO: { |
| 733 CallOnMain(callback_factory_.NewCallback( | 758 LinkedVideoFrame video_frame(new VideoFrameImpl()); |
| 734 &CdmWrapper::DeliverFrame, | 759 status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get()); |
| 735 status, | 760 CallOnMain(callback_factory_.NewCallback( |
| 736 video_frame, | 761 &CdmWrapper::DeliverFrame, |
| 737 encrypted_block_info.tracking_info)); | 762 status, |
| 763 video_frame, |
| 764 encrypted_block_info.tracking_info)); |
| 765 return; |
| 766 } |
| 767 |
| 768 case PP_DECRYPTORSTREAMTYPE_AUDIO: { |
| 769 LinkedAudioFrames audio_frames(new AudioFramesImpl()); |
| 770 status = cdm_->DecryptAndDecodeSamples(input_buffer, audio_frames.get()); |
| 771 CallOnMain(callback_factory_.NewCallback( |
| 772 &CdmWrapper::DeliverSamples, |
| 773 status, |
| 774 audio_frames, |
| 775 encrypted_block_info.tracking_info)); |
| 776 return; |
| 777 } |
| 778 |
| 779 default: |
| 780 PP_NOTREACHED(); |
| 781 return; |
| 782 } |
| 738 } | 783 } |
| 739 | 784 |
| 740 void CdmWrapper::SetTimer(int64 delay_ms) { | 785 void CdmWrapper::SetTimer(int64 delay_ms) { |
| 741 // NOTE: doesn't really need to run on the main thread; could just as well run | 786 // NOTE: doesn't really need to run on the main thread; could just as well run |
| 742 // on a helper thread if |cdm_| were thread-friendly and care was taken. We | 787 // on a helper thread if |cdm_| were thread-friendly and care was taken. We |
| 743 // only use CallOnMainThread() here to get delayed-execution behavior. | 788 // only use CallOnMainThread() here to get delayed-execution behavior. |
| 744 pp::Module::Get()->core()->CallOnMainThread( | 789 pp::Module::Get()->core()->CallOnMainThread( |
| 745 delay_ms, | 790 delay_ms, |
| 746 callback_factory_.NewCallback(&CdmWrapper::TimerExpired), | 791 callback_factory_.NewCallback(&CdmWrapper::TimerExpired), |
| 747 PP_OK); | 792 PP_OK); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 PP_DecryptedBlockInfo decrypted_block_info; | 846 PP_DecryptedBlockInfo decrypted_block_info; |
| 802 decrypted_block_info.tracking_info = tracking_info; | 847 decrypted_block_info.tracking_info = tracking_info; |
| 803 decrypted_block_info.tracking_info.timestamp = decrypted_block->timestamp(); | 848 decrypted_block_info.tracking_info.timestamp = decrypted_block->timestamp(); |
| 804 decrypted_block_info.result = CdmStatusToPpDecryptResult(status); | 849 decrypted_block_info.result = CdmStatusToPpDecryptResult(status); |
| 805 | 850 |
| 806 pp::Buffer_Dev buffer; | 851 pp::Buffer_Dev buffer; |
| 807 | 852 |
| 808 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) { | 853 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) { |
| 809 PP_DCHECK(decrypted_block.get() && decrypted_block->buffer()); | 854 PP_DCHECK(decrypted_block.get() && decrypted_block->buffer()); |
| 810 if (!decrypted_block.get() || !decrypted_block->buffer()) { | 855 if (!decrypted_block.get() || !decrypted_block->buffer()) { |
| 856 PP_NOTREACHED(); |
| 811 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR; | 857 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR; |
| 812 } else { | 858 } else { |
| 813 buffer = static_cast<PpbBuffer*>(decrypted_block->buffer())->buffer_dev(); | 859 buffer = static_cast<PpbBuffer*>(decrypted_block->buffer())->buffer_dev(); |
| 814 } | 860 } |
| 815 } | 861 } |
| 816 | 862 |
| 817 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info); | 863 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info); |
| 818 } | 864 } |
| 819 | 865 |
| 820 void CdmWrapper::DecoderInitializeDone(int32_t result, | 866 void CdmWrapper::DecoderInitializeDone(int32_t result, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 PP_DCHECK(video_frame->format() == cdm::kI420 || | 903 PP_DCHECK(video_frame->format() == cdm::kI420 || |
| 858 video_frame->format() == cdm::kYv12); | 904 video_frame->format() == cdm::kYv12); |
| 859 | 905 |
| 860 decrypted_frame_info.format = | 906 decrypted_frame_info.format = |
| 861 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->format()); | 907 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->format()); |
| 862 | 908 |
| 863 if (!video_frame.get() || | 909 if (!video_frame.get() || |
| 864 !video_frame->frame_buffer() || | 910 !video_frame->frame_buffer() || |
| 865 (decrypted_frame_info.format != PP_DECRYPTEDFRAMEFORMAT_YV12 && | 911 (decrypted_frame_info.format != PP_DECRYPTEDFRAMEFORMAT_YV12 && |
| 866 decrypted_frame_info.format != PP_DECRYPTEDFRAMEFORMAT_I420)) { | 912 decrypted_frame_info.format != PP_DECRYPTEDFRAMEFORMAT_I420)) { |
| 913 PP_NOTREACHED(); |
| 867 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR; | 914 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR; |
| 868 } else { | 915 } else { |
| 869 buffer = static_cast<PpbBuffer*>( | 916 buffer = static_cast<PpbBuffer*>( |
| 870 video_frame->frame_buffer())->buffer_dev(); | 917 video_frame->frame_buffer())->buffer_dev(); |
| 871 decrypted_frame_info.width = video_frame->size().width; | 918 decrypted_frame_info.width = video_frame->size().width; |
| 872 decrypted_frame_info.height = video_frame->size().height; | 919 decrypted_frame_info.height = video_frame->size().height; |
| 873 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] = | 920 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] = |
| 874 video_frame->plane_offset(cdm::VideoFrame::kYPlane); | 921 video_frame->plane_offset(cdm::VideoFrame::kYPlane); |
| 875 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] = | 922 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] = |
| 876 video_frame->plane_offset(cdm::VideoFrame::kUPlane); | 923 video_frame->plane_offset(cdm::VideoFrame::kUPlane); |
| 877 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] = | 924 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] = |
| 878 video_frame->plane_offset(cdm::VideoFrame::kVPlane); | 925 video_frame->plane_offset(cdm::VideoFrame::kVPlane); |
| 879 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] = | 926 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] = |
| 880 video_frame->stride(cdm::VideoFrame::kYPlane); | 927 video_frame->stride(cdm::VideoFrame::kYPlane); |
| 881 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] = | 928 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] = |
| 882 video_frame->stride(cdm::VideoFrame::kUPlane); | 929 video_frame->stride(cdm::VideoFrame::kUPlane); |
| 883 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] = | 930 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] = |
| 884 video_frame->stride(cdm::VideoFrame::kVPlane); | 931 video_frame->stride(cdm::VideoFrame::kVPlane); |
| 885 } | 932 } |
| 886 } | 933 } |
| 887 | 934 |
| 888 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info); | 935 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info); |
| 889 } | 936 } |
| 890 | 937 |
| 938 void CdmWrapper::DeliverSamples(int32_t result, |
| 939 const cdm::Status& status, |
| 940 const LinkedAudioFrames& audio_frames, |
| 941 const PP_DecryptTrackingInfo& tracking_info) { |
| 942 PP_DCHECK(result == PP_OK); |
| 943 // TODO(tomfinegan): Add PP_DecryptedSamplesInfo (or better name) for |
| 944 // cdm::AudioFrames. |
| 945 PP_DecryptedBlockInfo decrypted_block_info; |
| 946 decrypted_block_info.tracking_info = tracking_info; |
| 947 // TODO(tomfinegan): Remove this after PP_DecryptedSamplesInfo is added. |
| 948 decrypted_block_info.tracking_info.timestamp = 0; |
| 949 decrypted_block_info.result = CdmStatusToPpDecryptResult(status); |
| 950 |
| 951 pp::Buffer_Dev buffer; |
| 952 |
| 953 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) { |
| 954 PP_DCHECK(audio_frames.get() && audio_frames->buffer()); |
| 955 if (!audio_frames.get() || !audio_frames->buffer()) { |
| 956 PP_NOTREACHED(); |
| 957 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR; |
| 958 } else { |
| 959 buffer = static_cast<PpbBuffer*>(audio_frames->buffer())->buffer_dev(); |
| 960 } |
| 961 } |
| 962 |
| 963 pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_block_info); |
| 964 } |
| 891 | 965 |
| 892 // This object is the global object representing this plugin library as long | 966 // This object is the global object representing this plugin library as long |
| 893 // as it is loaded. | 967 // as it is loaded. |
| 894 class CdmWrapperModule : public pp::Module { | 968 class CdmWrapperModule : public pp::Module { |
| 895 public: | 969 public: |
| 896 CdmWrapperModule() : pp::Module() {} | 970 CdmWrapperModule() : pp::Module() {} |
| 897 virtual ~CdmWrapperModule() {} | 971 virtual ~CdmWrapperModule() {} |
| 898 | 972 |
| 899 virtual pp::Instance* CreateInstance(PP_Instance instance) { | 973 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
| 900 return new CdmWrapper(instance, this); | 974 return new CdmWrapper(instance, this); |
| 901 } | 975 } |
| 902 }; | 976 }; |
| 903 | 977 |
| 904 } // namespace webkit_media | 978 } // namespace webkit_media |
| 905 | 979 |
| 906 namespace pp { | 980 namespace pp { |
| 907 | 981 |
| 908 // Factory function for your specialization of the Module object. | 982 // Factory function for your specialization of the Module object. |
| 909 Module* CreateModule() { | 983 Module* CreateModule() { |
| 910 return new webkit_media::CdmWrapperModule(); | 984 return new webkit_media::CdmWrapperModule(); |
| 911 } | 985 } |
| 912 | 986 |
| 913 } // namespace pp | 987 } // namespace pp |
| OLD | NEW |