Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: content/renderer/media/android/webmediaplayer_android.cc

Issue 545993002: Provide fine grained media playback time thru interpolation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressing comments Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 15 matching lines...) Expand all
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/media/webmediaplayer_delegate.h" 29 #include "content/renderer/media/webmediaplayer_delegate.h"
30 #include "content/renderer/media/webmediaplayer_util.h" 30 #include "content/renderer/media/webmediaplayer_util.h"
31 #include "content/renderer/render_frame_impl.h" 31 #include "content/renderer/render_frame_impl.h"
32 #include "content/renderer/render_thread_impl.h" 32 #include "content/renderer/render_thread_impl.h"
33 #include "gpu/GLES2/gl2extchromium.h" 33 #include "gpu/GLES2/gl2extchromium.h"
34 #include "gpu/command_buffer/client/gles2_interface.h" 34 #include "gpu/command_buffer/client/gles2_interface.h"
35 #include "gpu/command_buffer/common/mailbox_holder.h" 35 #include "gpu/command_buffer/common/mailbox_holder.h"
36 #include "media/base/android/media_common_android.h"
36 #include "media/base/android/media_player_android.h" 37 #include "media/base/android/media_player_android.h"
37 #include "media/base/bind_to_current_loop.h" 38 #include "media/base/bind_to_current_loop.h"
38 // TODO(xhwang): Remove when we remove prefixed EME implementation. 39 // TODO(xhwang): Remove when we remove prefixed EME implementation.
39 #include "media/base/media_keys.h" 40 #include "media/base/media_keys.h"
40 #include "media/base/media_log.h" 41 #include "media/base/media_log.h"
41 #include "media/base/media_switches.h" 42 #include "media/base/media_switches.h"
42 #include "media/base/video_frame.h" 43 #include "media/base/video_frame.h"
43 #include "net/base/mime_util.h" 44 #include "net/base/mime_util.h"
44 #include "third_party/WebKit/public/platform/Platform.h" 45 #include "third_party/WebKit/public/platform/Platform.h"
45 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" 46 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 stream_id_(0), 136 stream_id_(0),
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 video_frame_provider_client_(NULL), 143 video_frame_provider_client_(NULL),
143 pending_playback_(false), 144 pending_playback_(false),
144 player_type_(MEDIA_PLAYER_TYPE_URL), 145 player_type_(MEDIA_PLAYER_TYPE_URL),
145 current_time_(0),
146 is_remote_(false), 146 is_remote_(false),
147 media_log_(media_log), 147 media_log_(media_log),
148 web_cdm_(NULL), 148 web_cdm_(NULL),
149 allow_stored_credentials_(false), 149 allow_stored_credentials_(false),
150 is_local_resource_(false), 150 is_local_resource_(false),
151 interpolator_(&default_tick_clock_),
151 weak_factory_(this) { 152 weak_factory_(this) {
152 DCHECK(player_manager_); 153 DCHECK(player_manager_);
153 DCHECK(cdm_manager_); 154 DCHECK(cdm_manager_);
154 155
155 DCHECK(main_thread_checker_.CalledOnValidThread()); 156 DCHECK(main_thread_checker_.CalledOnValidThread());
156 157
157 player_id_ = player_manager_->RegisterMediaPlayer(this); 158 player_id_ = player_manager_->RegisterMediaPlayer(this);
158 159
159 #if defined(VIDEO_HOLE) 160 #if defined(VIDEO_HOLE)
160 force_use_overlay_embedded_video_ = CommandLine::ForCurrentProcess()-> 161 force_use_overlay_embedded_video_ = CommandLine::ForCurrentProcess()->
161 HasSwitch(switches::kForceUseOverlayEmbeddedVideo); 162 HasSwitch(switches::kForceUseOverlayEmbeddedVideo);
162 if (force_use_overlay_embedded_video_ || 163 if (force_use_overlay_embedded_video_ ||
163 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { 164 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) {
164 // Defer stream texture creation until we are sure it's necessary. 165 // Defer stream texture creation until we are sure it's necessary.
165 needs_establish_peer_ = false; 166 needs_establish_peer_ = false;
166 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); 167 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1));
167 } 168 }
168 #endif // defined(VIDEO_HOLE) 169 #endif // defined(VIDEO_HOLE)
169 TryCreateStreamTextureProxyIfNeeded(); 170 TryCreateStreamTextureProxyIfNeeded();
171 interpolator_.SetUpperBound(base::TimeDelta());
170 } 172 }
171 173
172 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { 174 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
173 DCHECK(main_thread_checker_.CalledOnValidThread()); 175 DCHECK(main_thread_checker_.CalledOnValidThread());
174 SetVideoFrameProviderClient(NULL); 176 SetVideoFrameProviderClient(NULL);
175 client_->setWebLayer(NULL); 177 client_->setWebLayer(NULL);
176 178
177 if (player_manager_) { 179 if (player_manager_) {
178 player_manager_->DestroyPlayer(player_id_); 180 player_manager_->DestroyPlayer(player_id_);
179 player_manager_->UnregisterMediaPlayer(player_id_); 181 player_manager_->UnregisterMediaPlayer(player_id_);
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 458
457 double WebMediaPlayerAndroid::currentTime() const { 459 double WebMediaPlayerAndroid::currentTime() const {
458 DCHECK(main_thread_checker_.CalledOnValidThread()); 460 DCHECK(main_thread_checker_.CalledOnValidThread());
459 // If the player is processing a seek, return the seek time. 461 // If the player is processing a seek, return the seek time.
460 // Blink may still query us if updatePlaybackState() occurs while seeking. 462 // Blink may still query us if updatePlaybackState() occurs while seeking.
461 if (seeking()) { 463 if (seeking()) {
462 return pending_seek_ ? 464 return pending_seek_ ?
463 pending_seek_time_.InSecondsF() : seek_time_.InSecondsF(); 465 pending_seek_time_.InSecondsF() : seek_time_.InSecondsF();
464 } 466 }
465 467
466 return current_time_; 468 return std::min(
469 (const_cast<media::TimeDeltaInterpolator*>(
470 &interpolator_))->GetInterpolatedTime(), duration_).InSecondsF();
467 } 471 }
468 472
469 WebSize WebMediaPlayerAndroid::naturalSize() const { 473 WebSize WebMediaPlayerAndroid::naturalSize() const {
470 return natural_size_; 474 return natural_size_;
471 } 475 }
472 476
473 WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const { 477 WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const {
474 return network_state_; 478 return network_state_;
475 } 479 }
476 480
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 DCHECK(main_thread_checker_.CalledOnValidThread()); 712 DCHECK(main_thread_checker_.CalledOnValidThread());
709 bool need_to_signal_duration_changed = false; 713 bool need_to_signal_duration_changed = false;
710 714
711 if (is_local_resource_) 715 if (is_local_resource_)
712 UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded); 716 UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded);
713 717
714 // Update duration, if necessary, prior to ready state updates that may 718 // Update duration, if necessary, prior to ready state updates that may
715 // cause duration() query. 719 // cause duration() query.
716 if (!ignore_metadata_duration_change_ && duration_ != duration) { 720 if (!ignore_metadata_duration_change_ && duration_ != duration) {
717 duration_ = duration; 721 duration_ = duration;
718 722 if (is_local_resource_)
723 buffered_[0].end = duration_.InSecondsF();
719 // Client readyState transition from HAVE_NOTHING to HAVE_METADATA 724 // Client readyState transition from HAVE_NOTHING to HAVE_METADATA
720 // already triggers a durationchanged event. If this is a different 725 // already triggers a durationchanged event. If this is a different
721 // transition, remember to signal durationchanged. 726 // transition, remember to signal durationchanged.
722 // Do not ever signal durationchanged on metadata change in MSE case 727 // Do not ever signal durationchanged on metadata change in MSE case
723 // because OnDurationChanged() handles this. 728 // because OnDurationChanged() handles this.
724 if (ready_state_ > WebMediaPlayer::ReadyStateHaveNothing && 729 if (ready_state_ > WebMediaPlayer::ReadyStateHaveNothing &&
725 player_type_ != MEDIA_PLAYER_TYPE_MEDIA_SOURCE) { 730 player_type_ != MEDIA_PLAYER_TYPE_MEDIA_SOURCE) {
726 need_to_signal_duration_changed = true; 731 need_to_signal_duration_changed = true;
727 } 732 }
728 } 733 }
(...skipping 10 matching lines...) Expand all
739 744
740 if (need_to_signal_duration_changed) 745 if (need_to_signal_duration_changed)
741 client_->durationChanged(); 746 client_->durationChanged();
742 } 747 }
743 748
744 void WebMediaPlayerAndroid::OnPlaybackComplete() { 749 void WebMediaPlayerAndroid::OnPlaybackComplete() {
745 // When playback is about to finish, android media player often stops 750 // When playback is about to finish, android media player often stops
746 // at a time which is smaller than the duration. This makes webkit never 751 // at a time which is smaller than the duration. This makes webkit never
747 // know that the playback has finished. To solve this, we set the 752 // know that the playback has finished. To solve this, we set the
748 // current time to media duration when OnPlaybackComplete() get called. 753 // current time to media duration when OnPlaybackComplete() get called.
749 OnTimeUpdate(duration_); 754 interpolator_.SetBounds(duration_, duration_);
755 interpolator_.StopInterpolating();
750 client_->timeChanged(); 756 client_->timeChanged();
751 757
752 // if the loop attribute is set, timeChanged() will update the current time 758 // if the loop attribute is set, timeChanged() will update the current time
753 // to 0. It will perform a seek to 0. As the requests to the renderer 759 // to 0. It will perform a seek to 0. As the requests to the renderer
754 // process are sequential, the OnSeekComplete() will only occur 760 // process are sequential, the OnSeekComplete() will only occur
755 // once OnPlaybackComplete() is done. As the playback can only be executed 761 // once OnPlaybackComplete() is done. As the playback can only be executed
756 // upon completion of OnSeekComplete(), the request needs to be saved. 762 // upon completion of OnSeekComplete(), the request needs to be saved.
757 is_playing_ = false; 763 is_playing_ = false;
scherkus (not reviewing) 2014/09/05 23:17:45 relating to UpdatePlayingState() code I previously
qinmin 2014/09/05 23:45:09 Interesting catch here. Actually calling client_->
758 if (seeking_ && seek_time_ == base::TimeDelta()) 764 if (seeking_ && seek_time_ == base::TimeDelta())
759 pending_playback_ = true; 765 pending_playback_ = true;
760 } 766 }
761 767
762 void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) { 768 void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
763 buffered_[0].end = duration() * percentage / 100; 769 buffered_[0].end = duration() * percentage / 100;
764 did_loading_progress_ = true; 770 did_loading_progress_ = true;
765 } 771 }
766 772
767 void WebMediaPlayerAndroid::OnSeekRequest(const base::TimeDelta& time_to_seek) { 773 void WebMediaPlayerAndroid::OnSeekRequest(const base::TimeDelta& time_to_seek) {
768 DCHECK(main_thread_checker_.CalledOnValidThread()); 774 DCHECK(main_thread_checker_.CalledOnValidThread());
769 client_->requestSeek(time_to_seek.InSecondsF()); 775 client_->requestSeek(time_to_seek.InSecondsF());
770 } 776 }
771 777
772 void WebMediaPlayerAndroid::OnSeekComplete( 778 void WebMediaPlayerAndroid::OnSeekComplete(
773 const base::TimeDelta& current_time) { 779 const base::TimeDelta& current_time) {
774 DCHECK(main_thread_checker_.CalledOnValidThread()); 780 DCHECK(main_thread_checker_.CalledOnValidThread());
775 seeking_ = false; 781 seeking_ = false;
776 if (pending_seek_) { 782 if (pending_seek_) {
777 pending_seek_ = false; 783 pending_seek_ = false;
778 seek(pending_seek_time_.InSecondsF()); 784 seek(pending_seek_time_.InSecondsF());
779 return; 785 return;
780 } 786 }
781 787 interpolator_.SetBounds(current_time, current_time);
782 OnTimeUpdate(current_time);
783 788
784 UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 789 UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
785 790
786 client_->timeChanged(); 791 client_->timeChanged();
787 792
788 if (pending_playback_) { 793 if (pending_playback_) {
789 play(); 794 play();
790 pending_playback_ = false; 795 pending_playback_ = false;
791 } 796 }
792 } 797 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0))); 861 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0)));
857 client_->setWebLayer(video_weblayer_.get()); 862 client_->setWebLayer(video_weblayer_.get());
858 } 863 }
859 864
860 // TODO(qinmin): This is a hack. We need the media element to stop showing the 865 // TODO(qinmin): This is a hack. We need the media element to stop showing the
861 // poster image by forcing it to call setDisplayMode(video). Should move the 866 // poster image by forcing it to call setDisplayMode(video). Should move the
862 // logic into HTMLMediaElement.cpp. 867 // logic into HTMLMediaElement.cpp.
863 client_->timeChanged(); 868 client_->timeChanged();
864 } 869 }
865 870
866 void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) { 871 void WebMediaPlayerAndroid::OnTimeUpdate(base::TimeDelta current_timestamp,
872 base::TimeTicks current_time_ticks) {
867 DCHECK(main_thread_checker_.CalledOnValidThread()); 873 DCHECK(main_thread_checker_.CalledOnValidThread());
868 current_time_ = current_time.InSecondsF(); 874 // Compensate the current_timestamp with the IPC latency.
869 if (is_local_resource_ && current_time_ <= duration()) 875 base::TimeDelta lower_bound =
870 buffered_[0].end = current_time_; 876 base::TimeTicks::Now() - current_time_ticks + current_timestamp;
877 base::TimeDelta upper_bound = lower_bound;
878 // We should get another time update in about |kTimeUpdateInterval|
879 // milliseconds.
880 if (is_playing_) {
881 upper_bound += base::TimeDelta::FromMilliseconds(
882 media::kTimeUpdateInterval);
883 }
884 // if the lower_bound is smaller than the current time, just use the current
885 // time so that the timer is always progressing.
886 lower_bound =
887 std::min(lower_bound, base::TimeDelta::FromSecondsD(currentTime()));
888 interpolator_.SetBounds(lower_bound, upper_bound);
871 } 889 }
872 890
873 void WebMediaPlayerAndroid::OnConnectedToRemoteDevice( 891 void WebMediaPlayerAndroid::OnConnectedToRemoteDevice(
874 const std::string& remote_playback_message) { 892 const std::string& remote_playback_message) {
875 DCHECK(main_thread_checker_.CalledOnValidThread()); 893 DCHECK(main_thread_checker_.CalledOnValidThread());
876 DCHECK(!media_source_delegate_); 894 DCHECK(!media_source_delegate_);
877 DrawRemotePlaybackText(remote_playback_message); 895 DrawRemotePlaybackText(remote_playback_message);
878 is_remote_ = true; 896 is_remote_ = true;
879 SetNeedsEstablishPeer(false); 897 SetNeedsEstablishPeer(false);
880 } 898 }
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { 1296 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) {
1279 needs_establish_peer_ = needs_establish_peer; 1297 needs_establish_peer_ = needs_establish_peer;
1280 } 1298 }
1281 1299
1282 void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) { 1300 void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) {
1283 player_manager_->SetPoster(player_id_, poster); 1301 player_manager_->SetPoster(player_id_, poster);
1284 } 1302 }
1285 1303
1286 void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) { 1304 void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
1287 is_playing_ = is_playing; 1305 is_playing_ = is_playing;
1306 if (is_playing)
1307 interpolator_.StartInterpolating();
1308 else
1309 interpolator_.StopInterpolating();
1288 if (!delegate_) 1310 if (!delegate_)
1289 return; 1311 return;
1290 if (is_playing) 1312 if (is_playing)
1291 delegate_->DidPlay(this); 1313 delegate_->DidPlay(this);
1292 else 1314 else
1293 delegate_->DidPause(this); 1315 delegate_->DidPause(this);
1294 } 1316 }
1295 1317
1296 #if defined(VIDEO_HOLE) 1318 #if defined(VIDEO_HOLE)
1297 bool WebMediaPlayerAndroid::UpdateBoundaryRectangle() { 1319 bool WebMediaPlayerAndroid::UpdateBoundaryRectangle() {
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
1764 1786
1765 bool WebMediaPlayerAndroid::IsHLSStream() const { 1787 bool WebMediaPlayerAndroid::IsHLSStream() const {
1766 std::string mime; 1788 std::string mime;
1767 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_; 1789 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_;
1768 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime)) 1790 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime))
1769 return false; 1791 return false;
1770 return !mime.compare("application/x-mpegurl"); 1792 return !mime.compare("application/x-mpegurl");
1771 } 1793 }
1772 1794
1773 } // namespace content 1795 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/android/webmediaplayer_android.h ('k') | media/base/android/media_common_android.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698