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 <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 media_task_runner_(params.media_task_runner()), | 113 media_task_runner_(params.media_task_runner()), |
114 media_log_(params.media_log()), | 114 media_log_(params.media_log()), |
115 pipeline_(media_task_runner_, media_log_.get()), | 115 pipeline_(media_task_runner_, media_log_.get()), |
116 load_type_(LoadTypeURL), | 116 load_type_(LoadTypeURL), |
117 opaque_(false), | 117 opaque_(false), |
118 paused_(true), | 118 paused_(true), |
119 seeking_(false), | 119 seeking_(false), |
120 playback_rate_(0.0), | 120 playback_rate_(0.0), |
121 ended_(false), | 121 ended_(false), |
122 pending_seek_(false), | 122 pending_seek_(false), |
123 pending_seek_seconds_(0.0f), | |
124 should_notify_time_changed_(false), | 123 should_notify_time_changed_(false), |
125 client_(client), | 124 client_(client), |
126 delegate_(delegate), | 125 delegate_(delegate), |
127 defer_load_cb_(params.defer_load_cb()), | 126 defer_load_cb_(params.defer_load_cb()), |
128 context_3d_cb_(params.context_3d_cb()), | 127 context_3d_cb_(params.context_3d_cb()), |
129 supports_save_(true), | 128 supports_save_(true), |
130 chunk_demuxer_(NULL), | 129 chunk_demuxer_(NULL), |
131 // Threaded compositing isn't enabled universally yet. | 130 // Threaded compositing isn't enabled universally yet. |
132 compositor_task_runner_( | 131 compositor_task_runner_( |
133 params.compositor_task_runner() | 132 params.compositor_task_runner() |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 void WebMediaPlayerImpl::seek(double seconds) { | 282 void WebMediaPlayerImpl::seek(double seconds) { |
284 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; | 283 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; |
285 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 284 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
286 | 285 |
287 ended_ = false; | 286 ended_ = false; |
288 | 287 |
289 ReadyState old_state = ready_state_; | 288 ReadyState old_state = ready_state_; |
290 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) | 289 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) |
291 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); | 290 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); |
292 | 291 |
293 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds); | 292 base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds); |
294 | 293 |
295 if (seeking_) { | 294 if (seeking_) { |
295 if (new_seek_time == seek_time_) { | |
296 if (chunk_demuxer_) { | |
297 if (!pending_seek_) { | |
298 // If using media source demuxer, only suppress redundant seeks if | |
299 // there is no pending seek. This enforces that any pending seek that | |
300 // results in a demuxer seek is preceded by matching | |
301 // CancelPendingSeek() and StartWaitingForSeek() calls. | |
302 return; | |
303 } | |
304 } else { | |
305 // Suppress all redundant seeks if unrestricted by media source demuxer | |
306 // API. | |
307 pending_seek_ = false; | |
Srirama
2015/06/09 17:08:42
I think this may not be required, isn't it already
wolenetz
2015/06/09 19:44:28
Consider the following sequence of seeks without a
xhwang
2015/06/09 21:33:57
reset |pending_seek_time_| as well?
wolenetz
2015/06/09 22:09:58
Sure, done. |pending_seek_time_| has no meaning wh
| |
308 return; | |
309 } | |
310 } | |
311 | |
296 pending_seek_ = true; | 312 pending_seek_ = true; |
297 pending_seek_seconds_ = seconds; | 313 pending_seek_time_ = new_seek_time; |
298 if (chunk_demuxer_) | 314 if (chunk_demuxer_) |
299 chunk_demuxer_->CancelPendingSeek(seek_time); | 315 chunk_demuxer_->CancelPendingSeek(pending_seek_time_); |
300 return; | 316 return; |
301 } | 317 } |
302 | 318 |
303 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds)); | 319 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds)); |
304 | 320 |
305 // Update our paused time. | 321 // Update our paused time. |
306 // In paused state ignore the seek operations to current time if the loading | 322 // In paused state ignore the seek operations to current time if the loading |
307 // is completed and generate OnPipelineBufferingStateChanged event to | 323 // is completed and generate OnPipelineBufferingStateChanged event to |
308 // eventually fire seeking and seeked events | 324 // eventually fire seeking and seeked events |
309 if (paused_) { | 325 if (paused_) { |
310 if (paused_time_ != seek_time) { | 326 if (paused_time_ != new_seek_time) { |
311 paused_time_ = seek_time; | 327 paused_time_ = new_seek_time; |
312 } else if (old_state == ReadyStateHaveEnoughData) { | 328 } else if (old_state == ReadyStateHaveEnoughData) { |
313 main_task_runner_->PostTask( | 329 main_task_runner_->PostTask( |
314 FROM_HERE, | 330 FROM_HERE, |
315 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, | 331 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, |
316 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); | 332 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); |
317 return; | 333 return; |
318 } | 334 } |
319 } | 335 } |
320 | 336 |
321 seeking_ = true; | 337 seeking_ = true; |
338 seek_time_ = new_seek_time; | |
322 | 339 |
323 if (chunk_demuxer_) | 340 if (chunk_demuxer_) |
324 chunk_demuxer_->StartWaitingForSeek(seek_time); | 341 chunk_demuxer_->StartWaitingForSeek(seek_time_); |
325 | 342 |
326 // Kick off the asynchronous seek! | 343 // Kick off the asynchronous seek! |
327 pipeline_.Seek( | 344 pipeline_.Seek(seek_time_, BIND_TO_RENDER_LOOP1( |
328 seek_time, | 345 &WebMediaPlayerImpl::OnPipelineSeeked, true)); |
329 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, true)); | |
330 } | 346 } |
331 | 347 |
332 void WebMediaPlayerImpl::setRate(double rate) { | 348 void WebMediaPlayerImpl::setRate(double rate) { |
333 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; | 349 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; |
334 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 350 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
335 | 351 |
336 // TODO(kylep): Remove when support for negatives is added. Also, modify the | 352 // TODO(kylep): Remove when support for negatives is added. Also, modify the |
337 // following checks so rewind uses reasonable values also. | 353 // following checks so rewind uses reasonable values also. |
338 if (rate < 0.0) | 354 if (rate < 0.0) |
339 return; | 355 return; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 | 452 |
437 double WebMediaPlayerImpl::currentTime() const { | 453 double WebMediaPlayerImpl::currentTime() const { |
438 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 454 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
439 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); | 455 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); |
440 | 456 |
441 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, | 457 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, |
442 // see http://crbug.com/409280 | 458 // see http://crbug.com/409280 |
443 if (ended_) | 459 if (ended_) |
444 return duration(); | 460 return duration(); |
445 | 461 |
462 // We know the current seek time better than pipeline: pipeline may processing | |
463 // an earlier seek before a pending seek has been started, or it might not yet | |
464 // have the current seek time returnable via GetMediaTime(). | |
465 if (seeking()) { | |
466 return pending_seek_ ? pending_seek_time_.InSecondsF() | |
467 : seek_time_.InSecondsF(); | |
468 } | |
469 | |
446 return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF(); | 470 return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF(); |
447 } | 471 } |
448 | 472 |
449 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { | 473 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { |
450 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 474 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
451 return network_state_; | 475 return network_state_; |
452 } | 476 } |
453 | 477 |
454 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { | 478 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { |
455 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 479 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
709 "Unable to set MediaKeys object"); | 733 "Unable to set MediaKeys object"); |
710 } | 734 } |
711 | 735 |
712 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, | 736 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, |
713 PipelineStatus status) { | 737 PipelineStatus status) { |
714 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")"; | 738 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")"; |
715 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 739 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
716 seeking_ = false; | 740 seeking_ = false; |
717 if (pending_seek_) { | 741 if (pending_seek_) { |
718 pending_seek_ = false; | 742 pending_seek_ = false; |
719 seek(pending_seek_seconds_); | 743 seek(pending_seek_time_.InSecondsF()); |
720 return; | 744 return; |
721 } | 745 } |
722 | 746 |
723 if (status != PIPELINE_OK) { | 747 if (status != PIPELINE_OK) { |
724 OnPipelineError(status); | 748 OnPipelineError(status); |
725 return; | 749 return; |
726 } | 750 } |
727 | 751 |
728 // Update our paused time. | 752 // Update our paused time. |
729 if (paused_) | 753 if (paused_) |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1005 | 1029 |
1006 // pause() may be called after playback has ended and the HTMLMediaElement | 1030 // pause() may be called after playback has ended and the HTMLMediaElement |
1007 // requires that currentTime() == duration() after ending. We want to ensure | 1031 // requires that currentTime() == duration() after ending. We want to ensure |
1008 // |paused_time_| matches currentTime() in this case or a future seek() may | 1032 // |paused_time_| matches currentTime() in this case or a future seek() may |
1009 // incorrectly discard what it thinks is a seek to the existing time. | 1033 // incorrectly discard what it thinks is a seek to the existing time. |
1010 paused_time_ = | 1034 paused_time_ = |
1011 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime(); | 1035 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime(); |
1012 } | 1036 } |
1013 | 1037 |
1014 } // namespace media | 1038 } // namespace media |
OLD | NEW |