| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/renderer/media/android/webmediaplayer_android.h" | 5 #include "content/renderer/media/android/webmediaplayer_android.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "content/renderer/media/android/renderer_demuxer_android.h" | 24 #include "content/renderer/media/android/renderer_demuxer_android.h" |
| 25 #include "content/renderer/media/android/renderer_media_player_manager.h" | 25 #include "content/renderer/media/android/renderer_media_player_manager.h" |
| 26 #include "content/renderer/media/crypto/key_systems.h" | 26 #include "content/renderer/media/crypto/key_systems.h" |
| 27 #include "content/renderer/media/crypto/renderer_cdm_manager.h" | 27 #include "content/renderer/media/crypto/renderer_cdm_manager.h" |
| 28 #include "content/renderer/media/webcontentdecryptionmodule_impl.h" | 28 #include "content/renderer/media/webcontentdecryptionmodule_impl.h" |
| 29 #include "content/renderer/render_frame_impl.h" | 29 #include "content/renderer/render_frame_impl.h" |
| 30 #include "content/renderer/render_thread_impl.h" | 30 #include "content/renderer/render_thread_impl.h" |
| 31 #include "gpu/GLES2/gl2extchromium.h" | 31 #include "gpu/GLES2/gl2extchromium.h" |
| 32 #include "gpu/command_buffer/client/gles2_interface.h" | 32 #include "gpu/command_buffer/client/gles2_interface.h" |
| 33 #include "gpu/command_buffer/common/mailbox_holder.h" | 33 #include "gpu/command_buffer/common/mailbox_holder.h" |
| 34 #include "media/base/android/media_common_android.h" |
| 34 #include "media/base/android/media_player_android.h" | 35 #include "media/base/android/media_player_android.h" |
| 35 #include "media/base/bind_to_current_loop.h" | 36 #include "media/base/bind_to_current_loop.h" |
| 36 // TODO(xhwang): Remove when we remove prefixed EME implementation. | 37 // TODO(xhwang): Remove when we remove prefixed EME implementation. |
| 37 #include "media/base/media_keys.h" | 38 #include "media/base/media_keys.h" |
| 38 #include "media/base/media_log.h" | 39 #include "media/base/media_log.h" |
| 39 #include "media/base/media_switches.h" | 40 #include "media/base/media_switches.h" |
| 40 #include "media/base/video_frame.h" | 41 #include "media/base/video_frame.h" |
| 41 #include "media/blink/webmediaplayer_delegate.h" | 42 #include "media/blink/webmediaplayer_delegate.h" |
| 42 #include "media/blink/webmediaplayer_util.h" | 43 #include "media/blink/webmediaplayer_util.h" |
| 43 #include "net/base/mime_util.h" | 44 #include "net/base/mime_util.h" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 is_playing_(false), | 137 is_playing_(false), |
| 137 needs_establish_peer_(true), | 138 needs_establish_peer_(true), |
| 138 stream_texture_proxy_initialized_(false), | 139 stream_texture_proxy_initialized_(false), |
| 139 has_size_info_(false), | 140 has_size_info_(false), |
| 140 stream_texture_factory_(factory), | 141 stream_texture_factory_(factory), |
| 141 needs_external_surface_(false), | 142 needs_external_surface_(false), |
| 142 has_valid_metadata_(false), | 143 has_valid_metadata_(false), |
| 143 video_frame_provider_client_(NULL), | 144 video_frame_provider_client_(NULL), |
| 144 pending_playback_(false), | 145 pending_playback_(false), |
| 145 player_type_(MEDIA_PLAYER_TYPE_URL), | 146 player_type_(MEDIA_PLAYER_TYPE_URL), |
| 146 current_time_(0), | |
| 147 is_remote_(false), | 147 is_remote_(false), |
| 148 media_log_(media_log), | 148 media_log_(media_log), |
| 149 web_cdm_(NULL), | 149 web_cdm_(NULL), |
| 150 allow_stored_credentials_(false), | 150 allow_stored_credentials_(false), |
| 151 is_local_resource_(false), | 151 is_local_resource_(false), |
| 152 interpolator_(&default_tick_clock_), |
| 152 weak_factory_(this) { | 153 weak_factory_(this) { |
| 153 DCHECK(player_manager_); | 154 DCHECK(player_manager_); |
| 154 DCHECK(cdm_manager_); | 155 DCHECK(cdm_manager_); |
| 155 | 156 |
| 156 DCHECK(main_thread_checker_.CalledOnValidThread()); | 157 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 157 | 158 |
| 158 player_id_ = player_manager_->RegisterMediaPlayer(this); | 159 player_id_ = player_manager_->RegisterMediaPlayer(this); |
| 159 | 160 |
| 160 #if defined(VIDEO_HOLE) | 161 #if defined(VIDEO_HOLE) |
| 161 force_use_overlay_embedded_video_ = CommandLine::ForCurrentProcess()-> | 162 force_use_overlay_embedded_video_ = CommandLine::ForCurrentProcess()-> |
| 162 HasSwitch(switches::kForceUseOverlayEmbeddedVideo); | 163 HasSwitch(switches::kForceUseOverlayEmbeddedVideo); |
| 163 if (force_use_overlay_embedded_video_ || | 164 if (force_use_overlay_embedded_video_ || |
| 164 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { | 165 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { |
| 165 // Defer stream texture creation until we are sure it's necessary. | 166 // Defer stream texture creation until we are sure it's necessary. |
| 166 needs_establish_peer_ = false; | 167 needs_establish_peer_ = false; |
| 167 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); | 168 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); |
| 168 } | 169 } |
| 169 #endif // defined(VIDEO_HOLE) | 170 #endif // defined(VIDEO_HOLE) |
| 170 TryCreateStreamTextureProxyIfNeeded(); | 171 TryCreateStreamTextureProxyIfNeeded(); |
| 172 interpolator_.SetUpperBound(base::TimeDelta()); |
| 171 } | 173 } |
| 172 | 174 |
| 173 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { | 175 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { |
| 174 DCHECK(main_thread_checker_.CalledOnValidThread()); | 176 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 175 SetVideoFrameProviderClient(NULL); | 177 SetVideoFrameProviderClient(NULL); |
| 176 client_->setWebLayer(NULL); | 178 client_->setWebLayer(NULL); |
| 177 | 179 |
| 178 if (player_manager_) { | 180 if (player_manager_) { |
| 179 player_manager_->DestroyPlayer(player_id_); | 181 player_manager_->DestroyPlayer(player_id_); |
| 180 player_manager_->UnregisterMediaPlayer(player_id_); | 182 player_manager_->UnregisterMediaPlayer(player_id_); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 | 460 |
| 459 double WebMediaPlayerAndroid::currentTime() const { | 461 double WebMediaPlayerAndroid::currentTime() const { |
| 460 DCHECK(main_thread_checker_.CalledOnValidThread()); | 462 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 461 // If the player is processing a seek, return the seek time. | 463 // If the player is processing a seek, return the seek time. |
| 462 // Blink may still query us if updatePlaybackState() occurs while seeking. | 464 // Blink may still query us if updatePlaybackState() occurs while seeking. |
| 463 if (seeking()) { | 465 if (seeking()) { |
| 464 return pending_seek_ ? | 466 return pending_seek_ ? |
| 465 pending_seek_time_.InSecondsF() : seek_time_.InSecondsF(); | 467 pending_seek_time_.InSecondsF() : seek_time_.InSecondsF(); |
| 466 } | 468 } |
| 467 | 469 |
| 468 return current_time_; | 470 return std::min( |
| 471 (const_cast<media::TimeDeltaInterpolator*>( |
| 472 &interpolator_))->GetInterpolatedTime(), duration_).InSecondsF(); |
| 469 } | 473 } |
| 470 | 474 |
| 471 WebSize WebMediaPlayerAndroid::naturalSize() const { | 475 WebSize WebMediaPlayerAndroid::naturalSize() const { |
| 472 return natural_size_; | 476 return natural_size_; |
| 473 } | 477 } |
| 474 | 478 |
| 475 WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const { | 479 WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const { |
| 476 return network_state_; | 480 return network_state_; |
| 477 } | 481 } |
| 478 | 482 |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 DCHECK(main_thread_checker_.CalledOnValidThread()); | 715 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 712 bool need_to_signal_duration_changed = false; | 716 bool need_to_signal_duration_changed = false; |
| 713 | 717 |
| 714 if (is_local_resource_) | 718 if (is_local_resource_) |
| 715 UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded); | 719 UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded); |
| 716 | 720 |
| 717 // Update duration, if necessary, prior to ready state updates that may | 721 // Update duration, if necessary, prior to ready state updates that may |
| 718 // cause duration() query. | 722 // cause duration() query. |
| 719 if (!ignore_metadata_duration_change_ && duration_ != duration) { | 723 if (!ignore_metadata_duration_change_ && duration_ != duration) { |
| 720 duration_ = duration; | 724 duration_ = duration; |
| 721 | 725 if (is_local_resource_) |
| 726 buffered_[0].end = duration_.InSecondsF(); |
| 722 // Client readyState transition from HAVE_NOTHING to HAVE_METADATA | 727 // Client readyState transition from HAVE_NOTHING to HAVE_METADATA |
| 723 // already triggers a durationchanged event. If this is a different | 728 // already triggers a durationchanged event. If this is a different |
| 724 // transition, remember to signal durationchanged. | 729 // transition, remember to signal durationchanged. |
| 725 // Do not ever signal durationchanged on metadata change in MSE case | 730 // Do not ever signal durationchanged on metadata change in MSE case |
| 726 // because OnDurationChanged() handles this. | 731 // because OnDurationChanged() handles this. |
| 727 if (ready_state_ > WebMediaPlayer::ReadyStateHaveNothing && | 732 if (ready_state_ > WebMediaPlayer::ReadyStateHaveNothing && |
| 728 player_type_ != MEDIA_PLAYER_TYPE_MEDIA_SOURCE) { | 733 player_type_ != MEDIA_PLAYER_TYPE_MEDIA_SOURCE) { |
| 729 need_to_signal_duration_changed = true; | 734 need_to_signal_duration_changed = true; |
| 730 } | 735 } |
| 731 } | 736 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 744 | 749 |
| 745 if (need_to_signal_duration_changed) | 750 if (need_to_signal_duration_changed) |
| 746 client_->durationChanged(); | 751 client_->durationChanged(); |
| 747 } | 752 } |
| 748 | 753 |
| 749 void WebMediaPlayerAndroid::OnPlaybackComplete() { | 754 void WebMediaPlayerAndroid::OnPlaybackComplete() { |
| 750 // When playback is about to finish, android media player often stops | 755 // When playback is about to finish, android media player often stops |
| 751 // at a time which is smaller than the duration. This makes webkit never | 756 // at a time which is smaller than the duration. This makes webkit never |
| 752 // know that the playback has finished. To solve this, we set the | 757 // know that the playback has finished. To solve this, we set the |
| 753 // current time to media duration when OnPlaybackComplete() get called. | 758 // current time to media duration when OnPlaybackComplete() get called. |
| 754 OnTimeUpdate(duration_); | 759 interpolator_.SetBounds(duration_, duration_); |
| 755 client_->timeChanged(); | 760 client_->timeChanged(); |
| 756 | 761 |
| 757 // if the loop attribute is set, timeChanged() will update the current time | 762 // if the loop attribute is set, timeChanged() will update the current time |
| 758 // to 0. It will perform a seek to 0. As the requests to the renderer | 763 // to 0. It will perform a seek to 0. As the requests to the renderer |
| 759 // process are sequential, the OnSeekComplete() will only occur | 764 // process are sequential, the OnSeekComplete() will only occur |
| 760 // once OnPlaybackComplete() is done. As the playback can only be executed | 765 // once OnPlaybackComplete() is done. As the playback can only be executed |
| 761 // upon completion of OnSeekComplete(), the request needs to be saved. | 766 // upon completion of OnSeekComplete(), the request needs to be saved. |
| 762 is_playing_ = false; | 767 is_playing_ = false; |
| 763 if (seeking_ && seek_time_ == base::TimeDelta()) | 768 if (seeking_ && seek_time_ == base::TimeDelta()) |
| 764 pending_playback_ = true; | 769 pending_playback_ = true; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 776 | 781 |
| 777 void WebMediaPlayerAndroid::OnSeekComplete( | 782 void WebMediaPlayerAndroid::OnSeekComplete( |
| 778 const base::TimeDelta& current_time) { | 783 const base::TimeDelta& current_time) { |
| 779 DCHECK(main_thread_checker_.CalledOnValidThread()); | 784 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 780 seeking_ = false; | 785 seeking_ = false; |
| 781 if (pending_seek_) { | 786 if (pending_seek_) { |
| 782 pending_seek_ = false; | 787 pending_seek_ = false; |
| 783 seek(pending_seek_time_.InSecondsF()); | 788 seek(pending_seek_time_.InSecondsF()); |
| 784 return; | 789 return; |
| 785 } | 790 } |
| 786 | 791 interpolator_.SetBounds(current_time, current_time); |
| 787 OnTimeUpdate(current_time); | |
| 788 | 792 |
| 789 UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | 793 UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); |
| 790 | 794 |
| 791 client_->timeChanged(); | 795 client_->timeChanged(); |
| 792 | 796 |
| 793 if (pending_playback_) { | 797 if (pending_playback_) { |
| 794 play(); | 798 play(); |
| 795 pending_playback_ = false; | 799 pending_playback_ = false; |
| 796 } | 800 } |
| 797 } | 801 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0))); | 865 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0))); |
| 862 client_->setWebLayer(video_weblayer_.get()); | 866 client_->setWebLayer(video_weblayer_.get()); |
| 863 } | 867 } |
| 864 | 868 |
| 865 // TODO(qinmin): This is a hack. We need the media element to stop showing the | 869 // TODO(qinmin): This is a hack. We need the media element to stop showing the |
| 866 // poster image by forcing it to call setDisplayMode(video). Should move the | 870 // poster image by forcing it to call setDisplayMode(video). Should move the |
| 867 // logic into HTMLMediaElement.cpp. | 871 // logic into HTMLMediaElement.cpp. |
| 868 client_->timeChanged(); | 872 client_->timeChanged(); |
| 869 } | 873 } |
| 870 | 874 |
| 871 void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) { | 875 void WebMediaPlayerAndroid::OnTimeUpdate(base::TimeDelta current_timestamp, |
| 876 base::TimeTicks current_time_ticks) { |
| 872 DCHECK(main_thread_checker_.CalledOnValidThread()); | 877 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 873 current_time_ = current_time.InSecondsF(); | 878 // Compensate the current_timestamp with the IPC latency. |
| 874 if (is_local_resource_ && current_time_ <= duration()) | 879 base::TimeDelta lower_bound = |
| 875 buffered_[0].end = current_time_; | 880 base::TimeTicks::Now() - current_time_ticks + current_timestamp; |
| 881 base::TimeDelta upper_bound = lower_bound; |
| 882 // We should get another time update in about |kTimeUpdateInterval| |
| 883 // milliseconds. |
| 884 if (is_playing_) { |
| 885 upper_bound += base::TimeDelta::FromMilliseconds( |
| 886 media::kTimeUpdateInterval); |
| 887 } |
| 888 // if the lower_bound is smaller than the current time, just use the current |
| 889 // time so that the timer is always progressing. |
| 890 lower_bound = |
| 891 std::min(lower_bound, base::TimeDelta::FromSecondsD(currentTime())); |
| 892 interpolator_.SetBounds(lower_bound, upper_bound); |
| 876 } | 893 } |
| 877 | 894 |
| 878 void WebMediaPlayerAndroid::OnConnectedToRemoteDevice( | 895 void WebMediaPlayerAndroid::OnConnectedToRemoteDevice( |
| 879 const std::string& remote_playback_message) { | 896 const std::string& remote_playback_message) { |
| 880 DCHECK(main_thread_checker_.CalledOnValidThread()); | 897 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 881 DCHECK(!media_source_delegate_); | 898 DCHECK(!media_source_delegate_); |
| 882 DrawRemotePlaybackText(remote_playback_message); | 899 DrawRemotePlaybackText(remote_playback_message); |
| 883 is_remote_ = true; | 900 is_remote_ = true; |
| 884 SetNeedsEstablishPeer(false); | 901 SetNeedsEstablishPeer(false); |
| 885 } | 902 } |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) { | 1304 void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) { |
| 1288 player_manager_->SetPoster(player_id_, poster); | 1305 player_manager_->SetPoster(player_id_, poster); |
| 1289 } | 1306 } |
| 1290 | 1307 |
| 1291 void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) { | 1308 void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) { |
| 1292 const bool was_playing = is_playing_; | 1309 const bool was_playing = is_playing_; |
| 1293 is_playing_ = is_playing; | 1310 is_playing_ = is_playing; |
| 1294 if (!delegate_ || was_playing == is_playing_) | 1311 if (!delegate_ || was_playing == is_playing_) |
| 1295 return; | 1312 return; |
| 1296 if (is_playing) | 1313 if (is_playing) |
| 1314 interpolator_.StartInterpolating(); |
| 1315 else |
| 1316 interpolator_.StopInterpolating(); |
| 1317 if (is_playing) |
| 1297 delegate_->DidPlay(this); | 1318 delegate_->DidPlay(this); |
| 1298 else | 1319 else |
| 1299 delegate_->DidPause(this); | 1320 delegate_->DidPause(this); |
| 1300 } | 1321 } |
| 1301 | 1322 |
| 1302 #if defined(VIDEO_HOLE) | 1323 #if defined(VIDEO_HOLE) |
| 1303 bool WebMediaPlayerAndroid::UpdateBoundaryRectangle() { | 1324 bool WebMediaPlayerAndroid::UpdateBoundaryRectangle() { |
| 1304 if (!video_weblayer_) | 1325 if (!video_weblayer_) |
| 1305 return false; | 1326 return false; |
| 1306 | 1327 |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 | 1791 |
| 1771 bool WebMediaPlayerAndroid::IsHLSStream() const { | 1792 bool WebMediaPlayerAndroid::IsHLSStream() const { |
| 1772 std::string mime; | 1793 std::string mime; |
| 1773 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_; | 1794 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_; |
| 1774 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime)) | 1795 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime)) |
| 1775 return false; | 1796 return false; |
| 1776 return !mime.compare("application/x-mpegurl"); | 1797 return !mime.compare("application/x-mpegurl"); |
| 1777 } | 1798 } |
| 1778 | 1799 |
| 1779 } // namespace content | 1800 } // namespace content |
| OLD | NEW |