| 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 "webkit/media/webmediaplayer_impl.h" | 5 #include "webkit/media/webmediaplayer_impl.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> |
| 9 | 10 |
| 10 #include "base/bind.h" | 11 #include "base/bind.h" |
| 11 #include "base/callback.h" | 12 #include "base/callback.h" |
| 12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 13 #include "base/message_loop_proxy.h" | 14 #include "base/message_loop_proxy.h" |
| 14 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 15 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
| 16 #include "base/synchronization/waitable_event.h" | 17 #include "base/synchronization/waitable_event.h" |
| 17 #include "media/audio/null_audio_sink.h" | 18 #include "media/audio/null_audio_sink.h" |
| 18 #include "media/base/filter_collection.h" | 19 #include "media/base/filter_collection.h" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 base::Bind(&WebMediaPlayerProxy::Repaint, proxy_), | 148 base::Bind(&WebMediaPlayerProxy::Repaint, proxy_), |
| 148 base::Bind(&WebMediaPlayerProxy::SetOpaque, proxy_.get()), | 149 base::Bind(&WebMediaPlayerProxy::SetOpaque, proxy_.get()), |
| 149 true); | 150 true); |
| 150 filter_collection_->AddVideoRenderer(video_renderer); | 151 filter_collection_->AddVideoRenderer(video_renderer); |
| 151 proxy_->set_frame_provider(video_renderer); | 152 proxy_->set_frame_provider(video_renderer); |
| 152 | 153 |
| 153 // Create default audio renderer. | 154 // Create default audio renderer. |
| 154 filter_collection_->AddAudioRenderer( | 155 filter_collection_->AddAudioRenderer( |
| 155 new media::AudioRendererImpl(new media::NullAudioSink())); | 156 new media::AudioRendererImpl(new media::NullAudioSink())); |
| 156 | 157 |
| 157 decryptor_.reset(new media::AesDecryptor()); | 158 decryptor_.reset(new media::AesDecryptor(proxy_.get())); |
| 158 } | 159 } |
| 159 | 160 |
| 160 WebMediaPlayerImpl::~WebMediaPlayerImpl() { | 161 WebMediaPlayerImpl::~WebMediaPlayerImpl() { |
| 161 DCHECK_EQ(main_loop_, MessageLoop::current()); | 162 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 162 Destroy(); | 163 Destroy(); |
| 163 media_log_->AddEvent( | 164 media_log_->AddEvent( |
| 164 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); | 165 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); |
| 165 | 166 |
| 166 if (delegate_) | 167 if (delegate_) |
| 167 delegate_->PlayerGone(this); | 168 delegate_->PlayerGone(this); |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 bool WebMediaPlayerImpl::sourceAbort(const WebKit::WebString& id) { | 684 bool WebMediaPlayerImpl::sourceAbort(const WebKit::WebString& id) { |
| 684 proxy_->DemuxerAbort(id.utf8().data()); | 685 proxy_->DemuxerAbort(id.utf8().data()); |
| 685 return true; | 686 return true; |
| 686 } | 687 } |
| 687 | 688 |
| 688 void WebMediaPlayerImpl::sourceEndOfStream( | 689 void WebMediaPlayerImpl::sourceEndOfStream( |
| 689 WebMediaPlayer::EndOfStreamStatus status) { | 690 WebMediaPlayer::EndOfStreamStatus status) { |
| 690 DCHECK_EQ(main_loop_, MessageLoop::current()); | 691 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 691 media::PipelineStatus pipeline_status = media::PIPELINE_OK; | 692 media::PipelineStatus pipeline_status = media::PIPELINE_OK; |
| 692 | 693 |
| 693 switch(status) { | 694 switch (status) { |
| 694 case WebMediaPlayer::EndOfStreamStatusNoError: | 695 case WebMediaPlayer::EndOfStreamStatusNoError: |
| 695 break; | 696 break; |
| 696 case WebMediaPlayer::EndOfStreamStatusNetworkError: | 697 case WebMediaPlayer::EndOfStreamStatusNetworkError: |
| 697 pipeline_status = media::PIPELINE_ERROR_NETWORK; | 698 pipeline_status = media::PIPELINE_ERROR_NETWORK; |
| 698 break; | 699 break; |
| 699 case WebMediaPlayer::EndOfStreamStatusDecodeError: | 700 case WebMediaPlayer::EndOfStreamStatusDecodeError: |
| 700 pipeline_status = media::PIPELINE_ERROR_DECODE; | 701 pipeline_status = media::PIPELINE_ERROR_DECODE; |
| 701 break; | 702 break; |
| 702 default: | 703 default: |
| 703 NOTIMPLEMENTED(); | 704 NOTIMPLEMENTED(); |
| 704 } | 705 } |
| 705 | 706 |
| 706 proxy_->DemuxerEndOfStream(pipeline_status); | 707 proxy_->DemuxerEndOfStream(pipeline_status); |
| 707 } | 708 } |
| 708 | 709 |
| 709 WebKit::WebMediaPlayer::MediaKeyException | 710 WebKit::WebMediaPlayer::MediaKeyException |
| 710 WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system, | 711 WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system, |
| 711 const unsigned char* init_data, | 712 const unsigned char* init_data, |
| 712 unsigned init_data_length) { | 713 unsigned init_data_length) { |
| 713 if (!IsSupportedKeySystem(key_system)) | 714 if (!IsSupportedKeySystem(key_system)) |
| 714 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 715 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 715 | 716 |
| 716 // Every request call creates a unique ID. | |
| 717 // TODO(ddorwin): Move this to the CDM implementations since the CDMs may | |
| 718 // create their own IDs and since CDMs supporting multiple renderer processes | |
| 719 // need globally unique IDs. | |
| 720 // Everything from here until the return should probably be handled by | |
| 721 // the decryptor - see http://crbug.com/123260. | |
| 722 static uint32_t next_available_session_id = 1; | |
| 723 uint32_t session_id = next_available_session_id++; | |
| 724 | |
| 725 WebString session_id_string(base::UintToString16(session_id)); | |
| 726 | |
| 727 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " | 717 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " |
| 728 << std::string(reinterpret_cast<const char*>(init_data), | 718 << std::string(reinterpret_cast<const char*>(init_data), |
| 729 static_cast<size_t>(init_data_length)) | 719 static_cast<size_t>(init_data_length)); |
| 730 << " [" << session_id_string.utf8().data() << "]"; | |
| 731 | 720 |
| 732 // TODO(ddorwin): Generate a key request in the decryptor and fire | 721 decryptor_->GenerateKeyRequest(key_system.utf8(), |
| 733 // keyMessage when it completes. | 722 init_data, init_data_length); |
| 734 // For now, just fire the event with the init_data as the request. | |
| 735 const unsigned char* message = init_data; | |
| 736 unsigned message_length = init_data_length; | |
| 737 | |
| 738 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
| 739 &WebKit::WebMediaPlayerClient::keyMessage, | |
| 740 base::Unretained(GetClient()), | |
| 741 key_system, | |
| 742 session_id_string, | |
| 743 message, | |
| 744 message_length)); | |
| 745 | |
| 746 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; | 723 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; |
| 747 } | 724 } |
| 748 | 725 |
| 749 WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey( | 726 WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey( |
| 750 const WebString& key_system, | 727 const WebString& key_system, |
| 751 const unsigned char* key, | 728 const unsigned char* key, |
| 752 unsigned key_length, | 729 unsigned key_length, |
| 753 const unsigned char* init_data, | 730 const unsigned char* init_data, |
| 754 unsigned init_data_length, | 731 unsigned init_data_length, |
| 755 const WebString& session_id) { | 732 const WebString& session_id) { |
| 756 DCHECK(key); | 733 DCHECK(key); |
| 757 DCHECK_GT(key_length, 0u); | 734 DCHECK_GT(key_length, 0u); |
| 758 | 735 |
| 759 if (!IsSupportedKeySystem(key_system)) | 736 if (!IsSupportedKeySystem(key_system)) |
| 760 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 737 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 761 | 738 |
| 762 | |
| 763 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " | 739 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " |
| 764 << std::string(reinterpret_cast<const char*>(key), | 740 << std::string(reinterpret_cast<const char*>(key), |
| 765 static_cast<size_t>(key_length)) << ", " | 741 static_cast<size_t>(key_length)) << ", " |
| 766 << std::string(reinterpret_cast<const char*>(init_data), | 742 << std::string(reinterpret_cast<const char*>(init_data), |
| 767 static_cast<size_t>(init_data_length)) | 743 static_cast<size_t>(init_data_length)) |
| 768 << " [" << session_id.utf8().data() << "]"; | 744 << " [" << session_id.utf8().data() << "]"; |
| 769 | 745 |
| 770 // TODO(ddorwin): Everything from here until the return should probably be | 746 decryptor_->AddKey(key_system.utf8(), key, key_length, |
| 771 // handled by the decryptor - see http://crbug.com/123260. | 747 init_data, init_data_length, session_id.utf8()); |
| 772 // Temporarily, fire an error for invalid key length so we can test the error | |
| 773 // event and fire the keyAdded event in all other cases. | |
| 774 const unsigned kSupportedKeyLength = 16; // 128-bit key. | |
| 775 if (key_length != kSupportedKeyLength) { | |
| 776 DLOG(ERROR) << "addKey: invalid key length: " << key_length; | |
| 777 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
| 778 &WebKit::WebMediaPlayerClient::keyError, | |
| 779 base::Unretained(GetClient()), | |
| 780 key_system, | |
| 781 session_id, | |
| 782 WebKit::WebMediaPlayerClient::MediaKeyErrorCodeUnknown, | |
| 783 0)); | |
| 784 } else { | |
| 785 // TODO(ddorwin): Fix the decryptor to accept no |init_data|. See | |
| 786 // http://crbug.com/123265. Until then, ensure a non-empty value is passed. | |
| 787 static const unsigned char kDummyInitData[1] = {0}; | |
| 788 if (!init_data) { | |
| 789 init_data = kDummyInitData; | |
| 790 init_data_length = arraysize(kDummyInitData); | |
| 791 } | |
| 792 | |
| 793 decryptor_->AddKey(init_data, init_data_length, key, key_length); | |
| 794 | |
| 795 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
| 796 &WebKit::WebMediaPlayerClient::keyAdded, | |
| 797 base::Unretained(GetClient()), | |
| 798 key_system, | |
| 799 session_id)); | |
| 800 } | |
| 801 | |
| 802 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; | 748 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; |
| 803 } | 749 } |
| 804 | 750 |
| 805 WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( | 751 WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( |
| 806 const WebString& key_system, | 752 const WebString& key_system, |
| 807 const WebString& session_id) { | 753 const WebString& session_id) { |
| 808 if (!IsSupportedKeySystem(key_system)) | 754 if (!IsSupportedKeySystem(key_system)) |
| 809 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 755 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 810 | 756 |
| 811 // TODO(ddorwin): Cancel the key request in the decryptor. | 757 decryptor_->CancelKeyRequest(key_system.utf8(), session_id.utf8()); |
| 812 | |
| 813 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; | 758 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; |
| 814 } | 759 } |
| 815 | 760 |
| 816 void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { | 761 void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { |
| 817 Destroy(); | 762 Destroy(); |
| 818 main_loop_ = NULL; | 763 main_loop_ = NULL; |
| 819 } | 764 } |
| 820 | 765 |
| 821 void WebMediaPlayerImpl::Repaint() { | 766 void WebMediaPlayerImpl::Repaint() { |
| 822 DCHECK_EQ(main_loop_, MessageLoop::current()); | 767 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 // Repaint to trigger UI update. | 864 // Repaint to trigger UI update. |
| 920 Repaint(); | 865 Repaint(); |
| 921 } | 866 } |
| 922 | 867 |
| 923 void WebMediaPlayerImpl::OnDemuxerOpened() { | 868 void WebMediaPlayerImpl::OnDemuxerOpened() { |
| 924 DCHECK_EQ(main_loop_, MessageLoop::current()); | 869 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 925 | 870 |
| 926 GetClient()->sourceOpened(); | 871 GetClient()->sourceOpened(); |
| 927 } | 872 } |
| 928 | 873 |
| 929 void WebMediaPlayerImpl::OnKeyNeeded(scoped_array<uint8> init_data, | 874 void WebMediaPlayerImpl::OnKeyAdded(const std::string& key_system, |
| 930 int init_data_size) { | 875 const std::string& session_id) { |
| 931 DCHECK_EQ(main_loop_, MessageLoop::current()); | 876 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 932 | 877 |
| 933 GetClient()->keyNeeded("", "", init_data.get(), init_data_size); | 878 GetClient()->keyAdded(WebString::fromUTF8(key_system), |
| 879 WebString::fromUTF8(session_id)); |
| 880 } |
| 881 |
| 882 void WebMediaPlayerImpl::OnNeedKey(const std::string& key_system, |
| 883 const std::string& session_id, |
| 884 scoped_array<uint8> init_data, |
| 885 int init_data_size) { |
| 886 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 887 |
| 888 GetClient()->keyNeeded(WebString::fromUTF8(key_system), |
| 889 WebString::fromUTF8(session_id), |
| 890 init_data.get(), |
| 891 init_data_size); |
| 892 } |
| 893 |
| 894 void WebMediaPlayerImpl::OnKeyError(const std::string& key_system, |
| 895 const std::string& session_id, |
| 896 media::AesDecryptor::KeyError error_code, |
| 897 int system_code) { |
| 898 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 899 |
| 900 GetClient()->keyError( |
| 901 WebString::fromUTF8(key_system), |
| 902 WebString::fromUTF8(session_id), |
| 903 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), |
| 904 system_code); |
| 905 } |
| 906 |
| 907 void WebMediaPlayerImpl::OnKeyMessage(const std::string& key_system, |
| 908 const std::string& session_id, |
| 909 scoped_array<uint8> message, |
| 910 int message_length, |
| 911 const std::string& /* default_url */) { |
| 912 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 913 |
| 914 GetClient()->keyMessage(WebString::fromUTF8(key_system), |
| 915 WebString::fromUTF8(session_id), |
| 916 message.get(), |
| 917 message_length); |
| 934 } | 918 } |
| 935 | 919 |
| 936 void WebMediaPlayerImpl::SetOpaque(bool opaque) { | 920 void WebMediaPlayerImpl::SetOpaque(bool opaque) { |
| 937 DCHECK_EQ(main_loop_, MessageLoop::current()); | 921 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 938 | 922 |
| 939 GetClient()->setOpaque(opaque); | 923 GetClient()->setOpaque(opaque); |
| 940 } | 924 } |
| 941 | 925 |
| 942 void WebMediaPlayerImpl::DataSourceInitialized( | 926 void WebMediaPlayerImpl::DataSourceInitialized( |
| 943 const GURL& gurl, | 927 const GURL& gurl, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 return audio_source_provider_; | 1021 return audio_source_provider_; |
| 1038 } | 1022 } |
| 1039 | 1023 |
| 1040 void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() { | 1024 void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() { |
| 1041 DCHECK_EQ(main_loop_, MessageLoop::current()); | 1025 DCHECK_EQ(main_loop_, MessageLoop::current()); |
| 1042 incremented_externally_allocated_memory_ = true; | 1026 incremented_externally_allocated_memory_ = true; |
| 1043 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory); | 1027 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory); |
| 1044 } | 1028 } |
| 1045 | 1029 |
| 1046 } // namespace webkit_media | 1030 } // namespace webkit_media |
| OLD | NEW |