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

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: 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());
scherkus (not reviewing) 2014/09/05 20:12:57 is this needed? the docs and code make it look lik
qinmin 2014/09/05 21:32:19 It will return 0 only if interpolator_.StartInterp
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 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 743
740 if (need_to_signal_duration_changed) 744 if (need_to_signal_duration_changed)
741 client_->durationChanged(); 745 client_->durationChanged();
742 } 746 }
743 747
744 void WebMediaPlayerAndroid::OnPlaybackComplete() { 748 void WebMediaPlayerAndroid::OnPlaybackComplete() {
745 // When playback is about to finish, android media player often stops 749 // 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 750 // 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 751 // know that the playback has finished. To solve this, we set the
748 // current time to media duration when OnPlaybackComplete() get called. 752 // current time to media duration when OnPlaybackComplete() get called.
749 OnTimeUpdate(duration_); 753 interpolator_.SetBounds(duration_, duration_);
754 interpolator_.StopInterpolating();
750 client_->timeChanged(); 755 client_->timeChanged();
751 756
752 // if the loop attribute is set, timeChanged() will update the current time 757 // 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 758 // to 0. It will perform a seek to 0. As the requests to the renderer
754 // process are sequential, the OnSeekComplete() will only occur 759 // process are sequential, the OnSeekComplete() will only occur
755 // once OnPlaybackComplete() is done. As the playback can only be executed 760 // once OnPlaybackComplete() is done. As the playback can only be executed
756 // upon completion of OnSeekComplete(), the request needs to be saved. 761 // upon completion of OnSeekComplete(), the request needs to be saved.
757 is_playing_ = false; 762 is_playing_ = false;
758 if (seeking_ && seek_time_ == base::TimeDelta()) 763 if (seeking_ && seek_time_ == base::TimeDelta())
759 pending_playback_ = true; 764 pending_playback_ = true;
(...skipping 11 matching lines...) Expand all
771 776
772 void WebMediaPlayerAndroid::OnSeekComplete( 777 void WebMediaPlayerAndroid::OnSeekComplete(
773 const base::TimeDelta& current_time) { 778 const base::TimeDelta& current_time) {
774 DCHECK(main_thread_checker_.CalledOnValidThread()); 779 DCHECK(main_thread_checker_.CalledOnValidThread());
775 seeking_ = false; 780 seeking_ = false;
776 if (pending_seek_) { 781 if (pending_seek_) {
777 pending_seek_ = false; 782 pending_seek_ = false;
778 seek(pending_seek_time_.InSecondsF()); 783 seek(pending_seek_time_.InSecondsF());
779 return; 784 return;
780 } 785 }
781 786 interpolator_.SetBounds(current_time, current_time);
782 OnTimeUpdate(current_time);
783 787
784 UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 788 UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
785 789
786 client_->timeChanged(); 790 client_->timeChanged();
787 791
788 if (pending_playback_) { 792 if (pending_playback_) {
789 play(); 793 play();
790 pending_playback_ = false; 794 pending_playback_ = false;
791 } 795 }
792 } 796 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0))); 860 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0)));
857 client_->setWebLayer(video_weblayer_.get()); 861 client_->setWebLayer(video_weblayer_.get());
858 } 862 }
859 863
860 // TODO(qinmin): This is a hack. We need the media element to stop showing the 864 // 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 865 // poster image by forcing it to call setDisplayMode(video). Should move the
862 // logic into HTMLMediaElement.cpp. 866 // logic into HTMLMediaElement.cpp.
863 client_->timeChanged(); 867 client_->timeChanged();
864 } 868 }
865 869
866 void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) { 870 void WebMediaPlayerAndroid::OnTimeUpdate(base::TimeDelta current_timestamp,
871 base::TimeTicks current_time_ticks) {
867 DCHECK(main_thread_checker_.CalledOnValidThread()); 872 DCHECK(main_thread_checker_.CalledOnValidThread());
868 current_time_ = current_time.InSecondsF(); 873 // Compensate the current_timestamp with the IPC latency.
869 if (is_local_resource_ && current_time_ <= duration()) 874 base::TimeDelta lower_bound =
870 buffered_[0].end = current_time_; 875 base::TimeTicks::Now() - current_time_ticks + current_timestamp;
876 base::TimeDelta upper_bound = lower_bound;
877 // We should get another time update in about |kTimeUpdateInterval|
878 // milliseconds.
879 if (is_playing_) {
880 upper_bound += base::TimeDelta::FromMilliseconds(
881 media::kTimeUpdateInterval);
882 }
883 // if the lower_bound is smaller than the current time, just use the current
884 // time so that the timer is always progressing.
885 lower_bound =
886 std::min(lower_bound, base::TimeDelta::FromSecondsD(currentTime()));
887 interpolator_.SetBounds(lower_bound, upper_bound);
888 if (is_local_resource_ && current_timestamp <= duration_)
889 buffered_[0].end = current_timestamp.InSecondsF();
scherkus (not reviewing) 2014/09/05 20:12:57 it looks like this code was added in https://coder
qinmin 2014/09/05 21:32:19 Moved this to OnMediaMetadataChanged(), feels wier
871 } 890 }
872 891
873 void WebMediaPlayerAndroid::OnConnectedToRemoteDevice( 892 void WebMediaPlayerAndroid::OnConnectedToRemoteDevice(
874 const std::string& remote_playback_message) { 893 const std::string& remote_playback_message) {
875 DCHECK(main_thread_checker_.CalledOnValidThread()); 894 DCHECK(main_thread_checker_.CalledOnValidThread());
876 DCHECK(!media_source_delegate_); 895 DCHECK(!media_source_delegate_);
877 DrawRemotePlaybackText(remote_playback_message); 896 DrawRemotePlaybackText(remote_playback_message);
878 is_remote_ = true; 897 is_remote_ = true;
879 SetNeedsEstablishPeer(false); 898 SetNeedsEstablishPeer(false);
880 } 899 }
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { 1297 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) {
1279 needs_establish_peer_ = needs_establish_peer; 1298 needs_establish_peer_ = needs_establish_peer;
1280 } 1299 }
1281 1300
1282 void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) { 1301 void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) {
1283 player_manager_->SetPoster(player_id_, poster); 1302 player_manager_->SetPoster(player_id_, poster);
1284 } 1303 }
1285 1304
1286 void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) { 1305 void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
1287 is_playing_ = is_playing; 1306 is_playing_ = is_playing;
1288 if (!delegate_) 1307 if (!delegate_)
scherkus (not reviewing) 2014/09/05 20:12:57 when do we not have a delegate? if we don't have
qinmin 2014/09/05 21:32:19 If there is no delegate, then the WMPA instance is
1289 return; 1308 return;
1290 if (is_playing) 1309 if (is_playing) {
1291 delegate_->DidPlay(this); 1310 delegate_->DidPlay(this);
1292 else 1311 interpolator_.StartInterpolating();
1312 } else {
1293 delegate_->DidPause(this); 1313 delegate_->DidPause(this);
1314 interpolator_.StopInterpolating();
1315 }
1294 } 1316 }
1295 1317
1296 #if defined(VIDEO_HOLE) 1318 #if defined(VIDEO_HOLE)
1297 bool WebMediaPlayerAndroid::UpdateBoundaryRectangle() { 1319 bool WebMediaPlayerAndroid::UpdateBoundaryRectangle() {
1298 if (!video_weblayer_) 1320 if (!video_weblayer_)
1299 return false; 1321 return false;
1300 1322
1301 // Compute the geometry of video frame layer. 1323 // Compute the geometry of video frame layer.
1302 cc::Layer* layer = video_weblayer_->layer(); 1324 cc::Layer* layer = video_weblayer_->layer();
1303 gfx::RectF rect(layer->bounds()); 1325 gfx::RectF rect(layer->bounds());
(...skipping 460 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

Powered by Google App Engine
This is Rietveld 408576698