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 |