| 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 <map> | 6 #include <map> |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 size_(0) {} | 248 size_(0) {} |
| 249 virtual ~PpbBuffer() {} | 249 virtual ~PpbBuffer() {} |
| 250 | 250 |
| 251 pp::Buffer_Dev buffer_; | 251 pp::Buffer_Dev buffer_; |
| 252 uint32_t buffer_id_; | 252 uint32_t buffer_id_; |
| 253 int32_t size_; | 253 int32_t size_; |
| 254 | 254 |
| 255 DISALLOW_COPY_AND_ASSIGN(PpbBuffer); | 255 DISALLOW_COPY_AND_ASSIGN(PpbBuffer); |
| 256 }; | 256 }; |
| 257 | 257 |
| 258 class PpbBufferAllocator : public cdm::Allocator { | 258 class PpbBufferAllocator { |
| 259 public: | 259 public: |
| 260 explicit PpbBufferAllocator(pp::Instance* instance) | 260 explicit PpbBufferAllocator(pp::Instance* instance) |
| 261 : instance_(instance), | 261 : instance_(instance), |
| 262 next_buffer_id_(1) {} | 262 next_buffer_id_(1) {} |
| 263 virtual ~PpbBufferAllocator() {} | 263 ~PpbBufferAllocator() {} |
| 264 | 264 |
| 265 // cdm::Allocator implementation. | 265 cdm::Buffer* Allocate(int32_t capacity); |
| 266 virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE; | |
| 267 | 266 |
| 268 // Releases the buffer with |buffer_id|. A buffer can be recycled after | 267 // Releases the buffer with |buffer_id|. A buffer can be recycled after |
| 269 // it is released. | 268 // it is released. |
| 270 void Release(uint32_t buffer_id); | 269 void Release(uint32_t buffer_id); |
| 271 | 270 |
| 272 private: | 271 private: |
| 273 typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap; | 272 typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap; |
| 274 typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> > | 273 typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> > |
| 275 FreeBufferMap; | 274 FreeBufferMap; |
| 276 | 275 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 virtual cdm::Buffer* FrameBuffer() OVERRIDE { | 466 virtual cdm::Buffer* FrameBuffer() OVERRIDE { |
| 468 return buffer_; | 467 return buffer_; |
| 469 } | 468 } |
| 470 | 469 |
| 471 private: | 470 private: |
| 472 PpbBuffer* buffer_; | 471 PpbBuffer* buffer_; |
| 473 | 472 |
| 474 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl); | 473 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl); |
| 475 }; | 474 }; |
| 476 | 475 |
| 476 // GetCdmHostFunc implementation. |
| 477 void* GetCdmHost(int host_interface_version, void* user_data); |
| 478 |
| 477 // A wrapper class for abstracting away PPAPI interaction and threading for a | 479 // A wrapper class for abstracting away PPAPI interaction and threading for a |
| 478 // Content Decryption Module (CDM). | 480 // Content Decryption Module (CDM). |
| 479 class CdmWrapper : public pp::Instance, | 481 class CdmWrapper : public pp::Instance, |
| 480 public pp::ContentDecryptor_Private, | 482 public pp::ContentDecryptor_Private, |
| 481 public cdm::Host { | 483 public cdm::Host { |
| 482 public: | 484 public: |
| 483 CdmWrapper(PP_Instance instance, pp::Module* module); | 485 CdmWrapper(PP_Instance instance, pp::Module* module); |
| 484 virtual ~CdmWrapper(); | 486 virtual ~CdmWrapper(); |
| 485 | 487 |
| 486 // pp::Instance implementation. | 488 // pp::Instance implementation. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 510 virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type, | 512 virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type, |
| 511 uint32_t request_id) OVERRIDE; | 513 uint32_t request_id) OVERRIDE; |
| 512 virtual void ResetDecoder(PP_DecryptorStreamType decoder_type, | 514 virtual void ResetDecoder(PP_DecryptorStreamType decoder_type, |
| 513 uint32_t request_id) OVERRIDE; | 515 uint32_t request_id) OVERRIDE; |
| 514 virtual void DecryptAndDecode( | 516 virtual void DecryptAndDecode( |
| 515 PP_DecryptorStreamType decoder_type, | 517 PP_DecryptorStreamType decoder_type, |
| 516 pp::Buffer_Dev encrypted_buffer, | 518 pp::Buffer_Dev encrypted_buffer, |
| 517 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE; | 519 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE; |
| 518 | 520 |
| 519 // cdm::Host implementation. | 521 // cdm::Host implementation. |
| 522 virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE; |
| 520 virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE; | 523 virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE; |
| 521 virtual double GetCurrentWallTimeInSeconds() OVERRIDE; | 524 virtual double GetCurrentWallTimeInSeconds() OVERRIDE; |
| 522 virtual void SendKeyMessage( | 525 virtual void SendKeyMessage( |
| 523 const char* session_id, int32_t session_id_length, | 526 const char* session_id, int32_t session_id_length, |
| 524 const char* message, int32_t message_length, | 527 const char* message, int32_t message_length, |
| 525 const char* default_url, int32_t default_url_length) OVERRIDE; | 528 const char* default_url, int32_t default_url_length) OVERRIDE; |
| 526 virtual void SendKeyError(const char* session_id, | 529 virtual void SendKeyError(const char* session_id, |
| 527 int32_t session_id_length, | 530 int32_t session_id_length, |
| 528 cdm::MediaKeyError error_code, | 531 cdm::MediaKeyError error_code, |
| 529 uint32_t system_code) OVERRIDE; | 532 uint32_t system_code) OVERRIDE; |
| 533 virtual void GetPrivateData(int32_t* instance, |
| 534 GetPrivateInterface* get_interface) OVERRIDE; |
| 530 | 535 |
| 531 private: | 536 private: |
| 532 struct SessionInfo { | 537 struct SessionInfo { |
| 533 SessionInfo(const std::string& key_system_in, | 538 SessionInfo(const std::string& key_system_in, |
| 534 const std::string& session_id_in) | 539 const std::string& session_id_in) |
| 535 : key_system(key_system_in), | 540 : key_system(key_system_in), |
| 536 session_id(session_id_in) {} | 541 session_id(session_id_in) {} |
| 537 const std::string key_system; | 542 const std::string key_system; |
| 538 const std::string session_id; | 543 const std::string session_id; |
| 539 }; | 544 }; |
| 540 | 545 |
| 541 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock; | 546 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock; |
| 542 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame; | 547 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame; |
| 543 typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames; | 548 typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames; |
| 544 | 549 |
| 550 bool CreateCdmInstance(const std::string& key_system); |
| 551 |
| 545 void SendUnknownKeyError(const std::string& key_system, | 552 void SendUnknownKeyError(const std::string& key_system, |
| 546 const std::string& session_id); | 553 const std::string& session_id); |
| 547 | 554 |
| 548 void SendKeyAdded(const std::string& key_system, | 555 void SendKeyAdded(const std::string& key_system, |
| 549 const std::string& session_id); | 556 const std::string& session_id); |
| 550 | 557 |
| 551 void SendKeyErrorInternal(const std::string& key_system, | 558 void SendKeyErrorInternal(const std::string& key_system, |
| 552 const std::string& session_id, | 559 const std::string& session_id, |
| 553 cdm::MediaKeyError error_code, | 560 cdm::MediaKeyError error_code, |
| 554 uint32_t system_code); | 561 uint32_t system_code); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module) | 611 CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module) |
| 605 : pp::Instance(instance), | 612 : pp::Instance(instance), |
| 606 pp::ContentDecryptor_Private(this), | 613 pp::ContentDecryptor_Private(this), |
| 607 allocator_(this), | 614 allocator_(this), |
| 608 cdm_(NULL) { | 615 cdm_(NULL) { |
| 609 callback_factory_.Initialize(this); | 616 callback_factory_.Initialize(this); |
| 610 } | 617 } |
| 611 | 618 |
| 612 CdmWrapper::~CdmWrapper() { | 619 CdmWrapper::~CdmWrapper() { |
| 613 if (cdm_) | 620 if (cdm_) |
| 614 DestroyCdmInstance(cdm_); | 621 cdm_->Destroy(); |
| 622 } |
| 623 |
| 624 bool CdmWrapper::CreateCdmInstance(const std::string& key_system) { |
| 625 PP_DCHECK(!cdm_); |
| 626 cdm_ = reinterpret_cast<cdm::ContentDecryptionModule*>( |
| 627 ::CreateCdmInstance(cdm::kCdmInterfaceVersion, |
| 628 key_system.data(), key_system.size(), |
| 629 GetCdmHost, this)); |
| 630 |
| 631 return (cdm_ != NULL); |
| 615 } | 632 } |
| 616 | 633 |
| 617 void CdmWrapper::GenerateKeyRequest(const std::string& key_system, | 634 void CdmWrapper::GenerateKeyRequest(const std::string& key_system, |
| 618 const std::string& type, | 635 const std::string& type, |
| 619 pp::VarArrayBuffer init_data) { | 636 pp::VarArrayBuffer init_data) { |
| 620 PP_DCHECK(!key_system.empty()); | 637 PP_DCHECK(!key_system.empty()); |
| 621 PP_DCHECK(key_system_.empty() || key_system_ == key_system); | 638 PP_DCHECK(key_system_.empty() || key_system_ == key_system); |
| 622 | 639 |
| 623 if (!cdm_) { | 640 if (!cdm_) { |
| 624 cdm_ = CreateCdmInstance(key_system.data(), key_system.size(), | 641 if (!CreateCdmInstance(key_system)) { |
| 625 &allocator_, this); | |
| 626 PP_DCHECK(cdm_); | |
| 627 if (!cdm_) { | |
| 628 SendUnknownKeyError(key_system, ""); | 642 SendUnknownKeyError(key_system, ""); |
| 629 return; | 643 return; |
| 630 } | 644 } |
| 631 } | 645 } |
| 646 PP_DCHECK(cdm_); |
| 632 | 647 |
| 633 // Must be set here in case the CDM synchronously calls a cdm::Host method. | 648 // Must be set here in case the CDM synchronously calls a cdm::Host method. |
| 634 // Clear below on error. | 649 // Clear below on error. |
| 635 // TODO(ddorwin): Remove this when key_system is added to cdm::Host methods. | 650 // TODO(ddorwin): Set/clear key_system_ & cdm_ at same time; clear both on |
| 651 // error below. |
| 636 key_system_ = key_system; | 652 key_system_ = key_system; |
| 637 cdm::Status status = cdm_->GenerateKeyRequest( | 653 cdm::Status status = cdm_->GenerateKeyRequest( |
| 638 type.data(), type.size(), | 654 type.data(), type.size(), |
| 639 static_cast<const uint8_t*>(init_data.Map()), | 655 static_cast<const uint8_t*>(init_data.Map()), |
| 640 init_data.ByteLength()); | 656 init_data.ByteLength()); |
| 641 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); | 657 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); |
| 642 if (status != cdm::kSuccess) { | 658 if (status != cdm::kSuccess) { |
| 643 key_system_.clear(); // See comment above. | 659 key_system_.clear(); // See comment above. |
| 644 return; | 660 return; |
| 645 } | 661 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 encrypted_block_info.tracking_info)); | 868 encrypted_block_info.tracking_info)); |
| 853 return; | 869 return; |
| 854 } | 870 } |
| 855 | 871 |
| 856 default: | 872 default: |
| 857 PP_NOTREACHED(); | 873 PP_NOTREACHED(); |
| 858 return; | 874 return; |
| 859 } | 875 } |
| 860 } | 876 } |
| 861 | 877 |
| 878 cdm::Buffer* CdmWrapper::Allocate(int32_t capacity) { |
| 879 return allocator_.Allocate(capacity); |
| 880 } |
| 881 |
| 862 void CdmWrapper::SetTimer(int64_t delay_ms, void* context) { | 882 void CdmWrapper::SetTimer(int64_t delay_ms, void* context) { |
| 863 // NOTE: doesn't really need to run on the main thread; could just as well run | 883 // NOTE: doesn't really need to run on the main thread; could just as well run |
| 864 // on a helper thread if |cdm_| were thread-friendly and care was taken. We | 884 // on a helper thread if |cdm_| were thread-friendly and care was taken. We |
| 865 // only use CallOnMainThread() here to get delayed-execution behavior. | 885 // only use CallOnMainThread() here to get delayed-execution behavior. |
| 866 pp::Module::Get()->core()->CallOnMainThread( | 886 pp::Module::Get()->core()->CallOnMainThread( |
| 867 delay_ms, | 887 delay_ms, |
| 868 callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context), | 888 callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context), |
| 869 PP_OK); | 889 PP_OK); |
| 870 } | 890 } |
| 871 | 891 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 894 void CdmWrapper::SendKeyError(const char* session_id, | 914 void CdmWrapper::SendKeyError(const char* session_id, |
| 895 int32_t session_id_length, | 915 int32_t session_id_length, |
| 896 cdm::MediaKeyError error_code, | 916 cdm::MediaKeyError error_code, |
| 897 uint32_t system_code) { | 917 uint32_t system_code) { |
| 898 SendKeyErrorInternal(key_system_, | 918 SendKeyErrorInternal(key_system_, |
| 899 std::string(session_id, session_id_length), | 919 std::string(session_id, session_id_length), |
| 900 error_code, | 920 error_code, |
| 901 system_code); | 921 system_code); |
| 902 } | 922 } |
| 903 | 923 |
| 924 void CdmWrapper::GetPrivateData(int32_t* instance, |
| 925 cdm::Host::GetPrivateInterface* get_interface) { |
| 926 *instance = pp_instance(); |
| 927 *get_interface = pp::Module::Get()->get_browser_interface(); |
| 928 } |
| 929 |
| 904 void CdmWrapper::SendUnknownKeyError(const std::string& key_system, | 930 void CdmWrapper::SendUnknownKeyError(const std::string& key_system, |
| 905 const std::string& session_id) { | 931 const std::string& session_id) { |
| 906 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0); | 932 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0); |
| 907 } | 933 } |
| 908 | 934 |
| 909 | |
| 910 void CdmWrapper::SendKeyAdded(const std::string& key_system, | 935 void CdmWrapper::SendKeyAdded(const std::string& key_system, |
| 911 const std::string& session_id) { | 936 const std::string& session_id) { |
| 912 PostOnMain(callback_factory_.NewCallback( | 937 PostOnMain(callback_factory_.NewCallback( |
| 913 &CdmWrapper::KeyAdded, | 938 &CdmWrapper::KeyAdded, |
| 914 SessionInfo(key_system_, session_id))); | 939 SessionInfo(key_system_, session_id))); |
| 915 } | 940 } |
| 916 | 941 |
| 917 void CdmWrapper::SendKeyErrorInternal(const std::string& key_system, | 942 void CdmWrapper::SendKeyErrorInternal(const std::string& key_system, |
| 918 const std::string& session_id, | 943 const std::string& session_id, |
| 919 cdm::MediaKeyError error_code, | 944 cdm::MediaKeyError error_code, |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1109 static_cast<cdm::VideoFrame::VideoPlane>(i); | 1134 static_cast<cdm::VideoFrame::VideoPlane>(i); |
| 1110 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) + | 1135 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) + |
| 1111 plane_height * video_frame->Stride(plane)) { | 1136 plane_height * video_frame->Stride(plane)) { |
| 1112 return false; | 1137 return false; |
| 1113 } | 1138 } |
| 1114 } | 1139 } |
| 1115 | 1140 |
| 1116 return true; | 1141 return true; |
| 1117 } | 1142 } |
| 1118 | 1143 |
| 1144 void* GetCdmHost(int host_interface_version, void* user_data) { |
| 1145 if (!host_interface_version || !user_data) |
| 1146 return NULL; |
| 1147 |
| 1148 if (host_interface_version != cdm::kHostInterfaceVersion) |
| 1149 return NULL; |
| 1150 |
| 1151 CdmWrapper* cdm_wrapper = reinterpret_cast<CdmWrapper*>(user_data); |
| 1152 return static_cast<cdm::Host*>(cdm_wrapper); |
| 1153 } |
| 1154 |
| 1119 // This object is the global object representing this plugin library as long | 1155 // This object is the global object representing this plugin library as long |
| 1120 // as it is loaded. | 1156 // as it is loaded. |
| 1121 class CdmWrapperModule : public pp::Module { | 1157 class CdmWrapperModule : public pp::Module { |
| 1122 public: | 1158 public: |
| 1123 CdmWrapperModule() : pp::Module() { | 1159 CdmWrapperModule() : pp::Module() { |
| 1124 // This function blocks the renderer thread (PluginInstance::Initialize()). | 1160 // This function blocks the renderer thread (PluginInstance::Initialize()). |
| 1125 // Move this call to other places if this may be a concern in the future. | 1161 // Move this call to other places if this may be a concern in the future. |
| 1126 INITIALIZE_CDM_MODULE(); | 1162 INITIALIZE_CDM_MODULE(); |
| 1127 } | 1163 } |
| 1128 virtual ~CdmWrapperModule() { | 1164 virtual ~CdmWrapperModule() { |
| 1129 DeinitializeCdmModule(); | 1165 DeinitializeCdmModule(); |
| 1130 } | 1166 } |
| 1131 | 1167 |
| 1132 virtual pp::Instance* CreateInstance(PP_Instance instance) { | 1168 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
| 1133 return new CdmWrapper(instance, this); | 1169 return new CdmWrapper(instance, this); |
| 1134 } | 1170 } |
| 1135 }; | 1171 }; |
| 1136 | 1172 |
| 1137 } // namespace webkit_media | 1173 } // namespace webkit_media |
| 1138 | 1174 |
| 1139 namespace pp { | 1175 namespace pp { |
| 1140 | 1176 |
| 1141 // Factory function for your specialization of the Module object. | 1177 // Factory function for your specialization of the Module object. |
| 1142 Module* CreateModule() { | 1178 Module* CreateModule() { |
| 1143 return new webkit_media::CdmWrapperModule(); | 1179 return new webkit_media::CdmWrapperModule(); |
| 1144 } | 1180 } |
| 1145 | 1181 |
| 1146 } // namespace pp | 1182 } // namespace pp |
| OLD | NEW |