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

Side by Side Diff: media/blink/webmediaplayer_impl.cc

Issue 1164343003: Fix WMPI::currentTime/seek race causing flaky Blink mediasource-redundant-seek.html on desktop (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 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 "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
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
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
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
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
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
OLDNEW
« media/blink/webmediaplayer_impl.h ('K') | « media/blink/webmediaplayer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698