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 |