| 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 "media/blink/webmediaplayer_impl.h" | 5 #include "media/blink/webmediaplayer_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 ended_(false), | 127 ended_(false), |
| 128 pending_seek_(false), | 128 pending_seek_(false), |
| 129 pending_seek_seconds_(0.0f), | 129 pending_seek_seconds_(0.0f), |
| 130 should_notify_time_changed_(false), | 130 should_notify_time_changed_(false), |
| 131 client_(client), | 131 client_(client), |
| 132 delegate_(delegate), | 132 delegate_(delegate), |
| 133 defer_load_cb_(params.defer_load_cb()), | 133 defer_load_cb_(params.defer_load_cb()), |
| 134 context_3d_cb_(params.context_3d_cb()), | 134 context_3d_cb_(params.context_3d_cb()), |
| 135 supports_save_(true), | 135 supports_save_(true), |
| 136 chunk_demuxer_(NULL), | 136 chunk_demuxer_(NULL), |
| 137 compositor_task_runner_(params.compositor_task_runner()), | 137 // Threaded compositing isn't enabled universally yet. |
| 138 compositor_task_runner_( |
| 139 params.compositor_task_runner() |
| 140 ? params.compositor_task_runner() |
| 141 : base::MessageLoop::current()->task_runner()), |
| 138 compositor_(new VideoFrameCompositor( | 142 compositor_(new VideoFrameCompositor( |
| 143 compositor_task_runner_, |
| 139 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), | 144 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), |
| 140 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), | 145 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), |
| 141 encrypted_media_support_( | 146 encrypted_media_support_( |
| 142 cdm_factory.Pass(), | 147 cdm_factory.Pass(), |
| 143 client, | 148 client, |
| 144 params.media_permission(), | 149 params.media_permission(), |
| 145 base::Bind(&WebMediaPlayerImpl::SetCdm, AsWeakPtr())), | 150 base::Bind(&WebMediaPlayerImpl::SetCdm, AsWeakPtr())), |
| 146 renderer_factory_(renderer_factory.Pass()) { | 151 renderer_factory_(renderer_factory.Pass()) { |
| 147 // Threaded compositing isn't enabled universally yet. | |
| 148 if (!compositor_task_runner_.get()) | |
| 149 compositor_task_runner_ = base::MessageLoopProxy::current(); | |
| 150 | |
| 151 media_log_->AddEvent( | 152 media_log_->AddEvent( |
| 152 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); | 153 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); |
| 153 | 154 |
| 154 if (params.initial_cdm()) { | 155 if (params.initial_cdm()) { |
| 155 SetCdm( | 156 SetCdm( |
| 156 ToWebContentDecryptionModuleImpl(params.initial_cdm())->GetCdmContext(), | 157 ToWebContentDecryptionModuleImpl(params.initial_cdm())->GetCdmContext(), |
| 157 base::Bind(&IgnoreCdmAttached)); | 158 base::Bind(&IgnoreCdmAttached)); |
| 158 } | 159 } |
| 159 | 160 |
| 160 // TODO(xhwang): When we use an external Renderer, many methods won't work, | 161 // TODO(xhwang): When we use an external Renderer, many methods won't work, |
| 161 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 | 162 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 |
| 162 | 163 |
| 163 // Use the null sink if no sink was provided. | 164 // Use the null sink if no sink was provided. |
| 164 audio_source_provider_ = new WebAudioSourceProviderImpl( | 165 audio_source_provider_ = new WebAudioSourceProviderImpl( |
| 165 params.audio_renderer_sink().get() | 166 params.audio_renderer_sink().get() |
| 166 ? params.audio_renderer_sink() | 167 ? params.audio_renderer_sink() |
| 167 : new NullAudioSink(media_task_runner_)); | 168 : new NullAudioSink(media_task_runner_)); |
| 168 } | 169 } |
| 169 | 170 |
| 170 WebMediaPlayerImpl::~WebMediaPlayerImpl() { | 171 WebMediaPlayerImpl::~WebMediaPlayerImpl() { |
| 171 client_->setWebLayer(NULL); | 172 client_->setWebLayer(NULL); |
| 172 | 173 |
| 173 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 174 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 174 media_log_->AddEvent( | 175 media_log_->AddEvent( |
| 175 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); | 176 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); |
| 176 | 177 |
| 177 if (delegate_) | 178 if (delegate_) |
| 178 delegate_->PlayerGone(this); | 179 delegate_->PlayerGone(this); |
| 180 compositor_->StopRendering(); |
| 179 | 181 |
| 180 // Abort any pending IO so stopping the pipeline doesn't get blocked. | 182 // Abort any pending IO so stopping the pipeline doesn't get blocked. |
| 181 if (data_source_) | 183 if (data_source_) |
| 182 data_source_->Abort(); | 184 data_source_->Abort(); |
| 183 if (chunk_demuxer_) { | 185 if (chunk_demuxer_) { |
| 184 chunk_demuxer_->Shutdown(); | 186 chunk_demuxer_->Shutdown(); |
| 185 chunk_demuxer_ = NULL; | 187 chunk_demuxer_ = NULL; |
| 186 } | 188 } |
| 187 | 189 |
| 188 renderer_factory_.reset(); | 190 renderer_factory_.reset(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 DVLOG(1) << __FUNCTION__; | 253 DVLOG(1) << __FUNCTION__; |
| 252 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 254 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 253 | 255 |
| 254 paused_ = false; | 256 paused_ = false; |
| 255 pipeline_.SetPlaybackRate(playback_rate_); | 257 pipeline_.SetPlaybackRate(playback_rate_); |
| 256 if (data_source_) | 258 if (data_source_) |
| 257 data_source_->MediaIsPlaying(); | 259 data_source_->MediaIsPlaying(); |
| 258 | 260 |
| 259 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); | 261 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); |
| 260 | 262 |
| 261 if (delegate_ && playback_rate_ > 0) | 263 if (playback_rate_ > 0) { |
| 262 delegate_->DidPlay(this); | 264 compositor_->StartRendering(); |
| 265 if (delegate_) |
| 266 delegate_->DidPlay(this); |
| 267 } |
| 263 } | 268 } |
| 264 | 269 |
| 265 void WebMediaPlayerImpl::pause() { | 270 void WebMediaPlayerImpl::pause() { |
| 266 DVLOG(1) << __FUNCTION__; | 271 DVLOG(1) << __FUNCTION__; |
| 267 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 272 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 268 | 273 |
| 269 const bool was_already_paused = paused_ || playback_rate_ == 0; | 274 const bool was_already_paused = paused_ || playback_rate_ == 0; |
| 270 paused_ = true; | 275 paused_ = true; |
| 271 pipeline_.SetPlaybackRate(0.0f); | 276 pipeline_.SetPlaybackRate(0.0f); |
| 272 if (data_source_) | 277 if (data_source_) |
| 273 data_source_->MediaIsPaused(); | 278 data_source_->MediaIsPaused(); |
| 274 UpdatePausedTime(); | 279 UpdatePausedTime(); |
| 275 | 280 |
| 276 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); | 281 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); |
| 277 | 282 |
| 278 if (!was_already_paused && delegate_) | 283 if (!was_already_paused) { |
| 279 delegate_->DidPause(this); | 284 compositor_->StopRendering(); |
| 285 if (delegate_) |
| 286 delegate_->DidPause(this); |
| 287 } |
| 280 } | 288 } |
| 281 | 289 |
| 282 bool WebMediaPlayerImpl::supportsSave() const { | 290 bool WebMediaPlayerImpl::supportsSave() const { |
| 283 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 291 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 284 return supports_save_; | 292 return supports_save_; |
| 285 } | 293 } |
| 286 | 294 |
| 287 void WebMediaPlayerImpl::seek(double seconds) { | 295 void WebMediaPlayerImpl::seek(double seconds) { |
| 288 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; | 296 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; |
| 289 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 297 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 // following checks so rewind uses reasonable values also. | 349 // following checks so rewind uses reasonable values also. |
| 342 if (rate < 0.0) | 350 if (rate < 0.0) |
| 343 return; | 351 return; |
| 344 | 352 |
| 345 // Limit rates to reasonable values by clamping. | 353 // Limit rates to reasonable values by clamping. |
| 346 if (rate != 0.0) { | 354 if (rate != 0.0) { |
| 347 if (rate < kMinRate) | 355 if (rate < kMinRate) |
| 348 rate = kMinRate; | 356 rate = kMinRate; |
| 349 else if (rate > kMaxRate) | 357 else if (rate > kMaxRate) |
| 350 rate = kMaxRate; | 358 rate = kMaxRate; |
| 351 if (playback_rate_ == 0 && !paused_ && delegate_) | 359 if (playback_rate_ == 0 && !paused_) { |
| 352 delegate_->DidPlay(this); | 360 compositor_->StartRendering(); |
| 353 } else if (playback_rate_ != 0 && !paused_ && delegate_) { | 361 if (delegate_) |
| 354 delegate_->DidPause(this); | 362 delegate_->DidPlay(this); |
| 363 } |
| 364 } else if (playback_rate_ != 0 && !paused_) { |
| 365 compositor_->StopRendering(); |
| 366 if (delegate_) |
| 367 delegate_->DidPause(this); |
| 355 } | 368 } |
| 356 | 369 |
| 357 playback_rate_ = rate; | 370 playback_rate_ = rate; |
| 358 if (!paused_) { | 371 if (!paused_) { |
| 359 pipeline_.SetPlaybackRate(rate); | 372 pipeline_.SetPlaybackRate(rate); |
| 360 if (data_source_) | 373 if (data_source_) |
| 361 data_source_->MediaPlaybackRateChanged(rate); | 374 data_source_->MediaPlaybackRateChanged(rate); |
| 362 } | 375 } |
| 363 } | 376 } |
| 364 | 377 |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), | 910 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), |
| 898 encrypted_media_init_data_cb, mse_log_cb, media_log_, true); | 911 encrypted_media_init_data_cb, mse_log_cb, media_log_, true); |
| 899 demuxer_.reset(chunk_demuxer_); | 912 demuxer_.reset(chunk_demuxer_); |
| 900 } | 913 } |
| 901 | 914 |
| 902 // ... and we're ready to go! | 915 // ... and we're ready to go! |
| 903 seeking_ = true; | 916 seeking_ = true; |
| 904 | 917 |
| 905 pipeline_.Start( | 918 pipeline_.Start( |
| 906 demuxer_.get(), | 919 demuxer_.get(), |
| 907 renderer_factory_->CreateRenderer(media_task_runner_, | 920 renderer_factory_->CreateRenderer( |
| 908 audio_source_provider_.get()), | 921 media_task_runner_, audio_source_provider_.get(), compositor_), |
| 909 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), | 922 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), |
| 910 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError), | 923 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError), |
| 911 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false), | 924 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false), |
| 912 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), | 925 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), |
| 913 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), | 926 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), |
| 914 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)), | |
| 915 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), | 927 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), |
| 916 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack), | 928 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack), |
| 917 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey)); | 929 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey)); |
| 918 } | 930 } |
| 919 | 931 |
| 920 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { | 932 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { |
| 921 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; | 933 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; |
| 922 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 934 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 923 network_state_ = state; | 935 network_state_ = state; |
| 924 // Always notify to ensure client has the latest value. | 936 // Always notify to ensure client has the latest value. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 | 987 |
| 976 void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) { | 988 void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) { |
| 977 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 989 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 978 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); | 990 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); |
| 979 | 991 |
| 980 opaque_ = opaque; | 992 opaque_ = opaque; |
| 981 if (video_weblayer_) | 993 if (video_weblayer_) |
| 982 video_weblayer_->setOpaque(opaque_); | 994 video_weblayer_->setOpaque(opaque_); |
| 983 } | 995 } |
| 984 | 996 |
| 985 void WebMediaPlayerImpl::FrameReady( | |
| 986 const scoped_refptr<VideoFrame>& frame) { | |
| 987 compositor_task_runner_->PostTask( | |
| 988 FROM_HERE, | |
| 989 base::Bind(&VideoFrameCompositor::UpdateCurrentFrame, | |
| 990 base::Unretained(compositor_), | |
| 991 frame)); | |
| 992 } | |
| 993 | |
| 994 static void GetCurrentFrameAndSignal( | |
| 995 VideoFrameCompositor* compositor, | |
| 996 scoped_refptr<VideoFrame>* video_frame_out, | |
| 997 base::WaitableEvent* event) { | |
| 998 TRACE_EVENT0("media", "GetCurrentFrameAndSignal"); | |
| 999 *video_frame_out = compositor->GetCurrentFrame(); | |
| 1000 event->Signal(); | |
| 1001 } | |
| 1002 | |
| 1003 scoped_refptr<VideoFrame> | 997 scoped_refptr<VideoFrame> |
| 1004 WebMediaPlayerImpl::GetCurrentFrameFromCompositor() { | 998 WebMediaPlayerImpl::GetCurrentFrameFromCompositor() { |
| 1005 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor"); | 999 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor"); |
| 1006 if (compositor_task_runner_->BelongsToCurrentThread()) | 1000 // Since the compositor is driving frame collection, this should be at most |
| 1007 return compositor_->GetCurrentFrame(); | 1001 // one frame off; which is as good as we can get without a push based model. |
| 1008 | 1002 return compositor_->GetCurrentFrame(); |
| 1009 // Use a posted task and waitable event instead of a lock otherwise | |
| 1010 // WebGL/Canvas can see different content than what the compositor is seeing. | |
| 1011 scoped_refptr<VideoFrame> video_frame; | |
| 1012 base::WaitableEvent event(false, false); | |
| 1013 compositor_task_runner_->PostTask(FROM_HERE, | |
| 1014 base::Bind(&GetCurrentFrameAndSignal, | |
| 1015 base::Unretained(compositor_), | |
| 1016 &video_frame, | |
| 1017 &event)); | |
| 1018 event.Wait(); | |
| 1019 return video_frame; | |
| 1020 } | 1003 } |
| 1021 | 1004 |
| 1022 void WebMediaPlayerImpl::UpdatePausedTime() { | 1005 void WebMediaPlayerImpl::UpdatePausedTime() { |
| 1023 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1006 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 1024 | 1007 |
| 1025 // pause() may be called after playback has ended and the HTMLMediaElement | 1008 // pause() may be called after playback has ended and the HTMLMediaElement |
| 1026 // requires that currentTime() == duration() after ending. We want to ensure | 1009 // requires that currentTime() == duration() after ending. We want to ensure |
| 1027 // |paused_time_| matches currentTime() in this case or a future seek() may | 1010 // |paused_time_| matches currentTime() in this case or a future seek() may |
| 1028 // incorrectly discard what it thinks is a seek to the existing time. | 1011 // incorrectly discard what it thinks is a seek to the existing time. |
| 1029 paused_time_ = | 1012 paused_time_ = |
| 1030 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime(); | 1013 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime(); |
| 1031 } | 1014 } |
| 1032 | 1015 |
| 1033 } // namespace media | 1016 } // namespace media |
| OLD | NEW |