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

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

Issue 1641423002: Re-land extract state management from WebMediaPlayerImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix scoped_ptr usage. Created 4 years, 10 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 #include <string> 10 #include <string>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
14 #include "base/callback.h" 15 #include "base/callback.h"
15 #include "base/callback_helpers.h" 16 #include "base/callback_helpers.h"
16 #include "base/command_line.h" 17 #include "base/command_line.h"
17 #include "base/debug/alias.h" 18 #include "base/debug/alias.h"
18 #include "base/debug/crash_logging.h" 19 #include "base/debug/crash_logging.h"
19 #include "base/metrics/histogram.h" 20 #include "base/metrics/histogram.h"
20 #include "base/single_thread_task_runner.h" 21 #include "base/single_thread_task_runner.h"
21 #include "base/synchronization/waitable_event.h" 22 #include "base/synchronization/waitable_event.h"
22 #include "base/task_runner_util.h" 23 #include "base/task_runner_util.h"
23 #include "base/thread_task_runner_handle.h" 24 #include "base/thread_task_runner_handle.h"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 network_state_(WebMediaPlayer::NetworkStateEmpty), 138 network_state_(WebMediaPlayer::NetworkStateEmpty),
138 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 139 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
139 preload_(BufferedDataSource::AUTO), 140 preload_(BufferedDataSource::AUTO),
140 buffering_strategy_( 141 buffering_strategy_(
141 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL), 142 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
142 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 143 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
143 media_task_runner_(params.media_task_runner()), 144 media_task_runner_(params.media_task_runner()),
144 worker_task_runner_(params.worker_task_runner()), 145 worker_task_runner_(params.worker_task_runner()),
145 media_log_(params.media_log()), 146 media_log_(params.media_log()),
146 pipeline_(media_task_runner_, media_log_.get()), 147 pipeline_(media_task_runner_, media_log_.get()),
148 pipeline_controller_(&pipeline_,
149 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
150 base::Unretained(this)),
DaleCurtis 2016/02/19 23:28:30 These probably still need to be WeakPtrs unless it
sandersd (OOO until July 31) 2016/02/24 00:09:56 Done.
151 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked,
152 base::Unretained(this)),
153 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended,
154 base::Unretained(this)),
155 base::Bind(&WebMediaPlayerImpl::OnPipelineError,
156 base::Unretained(this))),
147 load_type_(LoadTypeURL), 157 load_type_(LoadTypeURL),
148 opaque_(false), 158 opaque_(false),
149 playback_rate_(0.0), 159 playback_rate_(0.0),
150 paused_(true), 160 paused_(true),
151 seeking_(false), 161 seeking_(false),
152 pending_suspend_(false),
153 pending_time_change_(false),
154 pending_resume_(false),
155 suspending_(false),
156 suspended_(false),
157 resuming_(false),
158 pending_suspend_resume_cycle_(false), 162 pending_suspend_resume_cycle_(false),
159 ended_(false), 163 ended_(false),
160 pending_seek_(false),
161 should_notify_time_changed_(false),
162 fullscreen_(false), 164 fullscreen_(false),
163 decoder_requires_restart_for_fullscreen_(false), 165 decoder_requires_restart_for_fullscreen_(false),
164 client_(client), 166 client_(client),
165 encrypted_client_(encrypted_client), 167 encrypted_client_(encrypted_client),
166 delegate_(delegate), 168 delegate_(delegate),
167 delegate_id_(0), 169 delegate_id_(0),
168 defer_load_cb_(params.defer_load_cb()), 170 defer_load_cb_(params.defer_load_cb()),
169 context_3d_cb_(params.context_3d_cb()), 171 context_3d_cb_(params.context_3d_cb()),
170 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()), 172 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
171 last_reported_memory_usage_(0), 173 last_reported_memory_usage_(0),
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 if (delegate_) { 230 if (delegate_) {
229 delegate_->PlayerGone(delegate_id_); 231 delegate_->PlayerGone(delegate_id_);
230 delegate_->RemoveObserver(delegate_id_); 232 delegate_->RemoveObserver(delegate_id_);
231 } 233 }
232 234
233 // Abort any pending IO so stopping the pipeline doesn't get blocked. 235 // Abort any pending IO so stopping the pipeline doesn't get blocked.
234 if (data_source_) 236 if (data_source_)
235 data_source_->Abort(); 237 data_source_->Abort();
236 if (chunk_demuxer_) { 238 if (chunk_demuxer_) {
237 chunk_demuxer_->Shutdown(); 239 chunk_demuxer_->Shutdown();
238 chunk_demuxer_ = NULL; 240 chunk_demuxer_ = nullptr;
239 } 241 }
240 242
241 renderer_factory_.reset(); 243 renderer_factory_.reset();
242 244
243 // Make sure to kill the pipeline so there's no more media threads running. 245 // Make sure to kill the pipeline so there's no more media threads running.
244 // Note: stopping the pipeline might block for a long time. 246 // Note: stopping the pipeline might block for a long time.
245 base::WaitableEvent waiter(false, false); 247 base::WaitableEvent waiter(false, false);
246 pipeline_.Stop( 248 pipeline_.Stop(
247 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter))); 249 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
248 waiter.Wait(); 250 waiter.Wait();
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 DCHECK(main_task_runner_->BelongsToCurrentThread()); 342 DCHECK(main_task_runner_->BelongsToCurrentThread());
341 343
342 #if defined(OS_ANDROID) // WMPI_CAST 344 #if defined(OS_ANDROID) // WMPI_CAST
343 if (isRemote()) { 345 if (isRemote()) {
344 cast_impl_.play(); 346 cast_impl_.play();
345 return; 347 return;
346 } 348 }
347 #endif 349 #endif
348 350
349 paused_ = false; 351 paused_ = false;
352 pipeline_.SetPlaybackRate(playback_rate_);
350 353
351 pipeline_.SetPlaybackRate(playback_rate_);
352 if (data_source_) 354 if (data_source_)
353 data_source_->MediaIsPlaying(); 355 data_source_->MediaIsPlaying();
354 356
355 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 357 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
356 358
357 if (playback_rate_ > 0) 359 if (playback_rate_ > 0)
358 NotifyPlaybackStarted(); 360 NotifyPlaybackStarted();
359 } 361 }
360 362
361 void WebMediaPlayerImpl::pause() { 363 void WebMediaPlayerImpl::pause() {
362 DVLOG(1) << __FUNCTION__; 364 DVLOG(1) << __FUNCTION__;
363 DCHECK(main_task_runner_->BelongsToCurrentThread()); 365 DCHECK(main_task_runner_->BelongsToCurrentThread());
364 366
365 const bool was_already_paused = paused_ || playback_rate_ == 0; 367 const bool was_already_paused = paused_ || playback_rate_ == 0;
366 paused_ = true; 368 paused_ = true;
367 369
368 #if defined(OS_ANDROID) // WMPI_CAST 370 #if defined(OS_ANDROID) // WMPI_CAST
369 if (isRemote()) { 371 if (isRemote()) {
370 cast_impl_.pause(); 372 cast_impl_.pause();
371 return; 373 return;
372 } 374 }
373 #endif 375 #endif
374 376
375 pipeline_.SetPlaybackRate(0.0); 377 pipeline_.SetPlaybackRate(0.0);
376 UpdatePausedTime(); 378
379 // pause() may be called after playback has ended and the HTMLMediaElement
380 // requires that currentTime() == duration() after ending. We want to ensure
381 // |paused_time_| matches currentTime() in this case or a future seek() may
382 // incorrectly discard what it thinks is a seek to the existing time.
383 paused_time_ =
384 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
377 385
378 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); 386 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
379 387
380 if (!was_already_paused) 388 if (!was_already_paused)
381 NotifyPlaybackPaused(); 389 NotifyPlaybackPaused();
382 } 390 }
383 391
384 bool WebMediaPlayerImpl::supportsSave() const { 392 bool WebMediaPlayerImpl::supportsSave() const {
385 DCHECK(main_task_runner_->BelongsToCurrentThread()); 393 DCHECK(main_task_runner_->BelongsToCurrentThread());
386 return supports_save_; 394 return supports_save_;
387 } 395 }
388 396
389 void WebMediaPlayerImpl::seek(double seconds) { 397 void WebMediaPlayerImpl::seek(double seconds) {
390 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; 398 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
391 DCHECK(main_task_runner_->BelongsToCurrentThread()); 399 DCHECK(main_task_runner_->BelongsToCurrentThread());
400 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
401 }
402
403 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
404 DCHECK(main_task_runner_->BelongsToCurrentThread());
392 405
393 ended_ = false; 406 ended_ = false;
394 407
395 base::TimeDelta new_seek_time = base::TimeDelta::FromSecondsD(seconds);
396
397 #if defined(OS_ANDROID) // WMPI_CAST 408 #if defined(OS_ANDROID) // WMPI_CAST
398 if (isRemote()) { 409 if (isRemote()) {
399 cast_impl_.seek(new_seek_time); 410 cast_impl_.seek(time);
400 return; 411 return;
401 } 412 }
402 #endif 413 #endif
403 414
404 ReadyState old_state = ready_state_; 415 ReadyState old_state = ready_state_;
405 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) 416 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
406 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 417 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
407 418
408 if (seeking_ || suspended_) { 419 // When paused, we know exactly what the current time is and can elide seeks
409 // Once resuming, it's too late to change the resume time and so the 420 // to it. However, there are two cases that are not elided:
410 // implementation is a little different. 421 // 1) When the pipeline state is not stable.
411 bool is_suspended = suspended_ && !resuming_; 422 // In this case we just let |pipeline_controller_| decide what to do, as
412 423 // it has complete information.
413 // If we are currently seeking or resuming to |new_seek_time|, skip the 424 // 2) For MSE.
414 // seek (except for MSE, which always seeks). 425 // Because the buffers may have changed between seeks, MSE seeks are
415 if (!is_suspended && new_seek_time == seek_time_) { 426 // never elided.
416 if (chunk_demuxer_) { 427 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
417 // Don't suppress any redundant in-progress MSE seek. There could have 428 !chunk_demuxer_) {
418 // been changes to the underlying buffers after seeking the demuxer and 429 // If the ready state was high enough before, we can indicate that the seek
419 // before receiving OnPipelineSeeked() for the currently in-progress 430 // completed just by restoring it. Otherwise we will just wait for the real
420 // seek. 431 // ready state change to eventually happen.
421 MEDIA_LOG(DEBUG, media_log_) 432 if (old_state == ReadyStateHaveEnoughData) {
422 << "Detected MediaSource seek to same time as in-progress seek to "
423 << seek_time_ << ".";
424 } else {
425 // Suppress all redundant seeks if unrestricted by media source demuxer
426 // API.
427 pending_seek_ = false;
428 pending_seek_time_ = base::TimeDelta();
429 return;
430 }
431 }
432
433 // If |chunk_demuxer_| is already seeking, cancel that seek and schedule the
434 // new one.
435 if (!is_suspended && chunk_demuxer_)
436 chunk_demuxer_->CancelPendingSeek(new_seek_time);
437
438 // Schedule a seek once the current suspend or seek finishes.
439 pending_seek_ = true;
440 pending_seek_time_ = new_seek_time;
441
442 // In the case of seeking while suspended, the seek is considered to have
443 // started immediately (but won't complete until the pipeline is resumed).
444 if (is_suspended) {
445 seeking_ = true;
446 seek_time_ = new_seek_time;
447 }
448
449 return;
450 }
451
452 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
453
454 // Update our paused time.
455 // For non-MSE playbacks, in paused state ignore the seek operations to
456 // current time if the loading is completed and generate
457 // OnPipelineBufferingStateChanged event to eventually fire seeking and seeked
458 // events. We don't short-circuit MSE seeks in this logic because the
459 // underlying buffers around the seek time might have changed (or even been
460 // removed) since previous seek/preroll/pause action, and the pipeline might
461 // need to flush so the new buffers are decoded and rendered instead of the
462 // old ones.
463 if (paused_) {
464 if (paused_time_ != new_seek_time || chunk_demuxer_) {
465 paused_time_ = new_seek_time;
466 } else if (old_state == ReadyStateHaveEnoughData) {
467 main_task_runner_->PostTask( 433 main_task_runner_->PostTask(
468 FROM_HERE, 434 FROM_HERE,
469 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, 435 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
470 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 436 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
471 return;
472 } 437 }
438 return;
473 } 439 }
474 440
475 seeking_ = true; 441 seeking_ = true;
476 seek_time_ = new_seek_time; 442 seek_time_ = time;
477 443 if (paused_)
478 if (chunk_demuxer_) 444 paused_time_ = time;
479 chunk_demuxer_->StartWaitingForSeek(seek_time_); 445 pipeline_controller_.Seek(time, time_updated);
480
481 pipeline_.Seek(seek_time_, BIND_TO_RENDER_LOOP1(
482 &WebMediaPlayerImpl::OnPipelineSeeked, true));
483 } 446 }
484 447
485 void WebMediaPlayerImpl::setRate(double rate) { 448 void WebMediaPlayerImpl::setRate(double rate) {
486 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 449 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
487 DCHECK(main_task_runner_->BelongsToCurrentThread()); 450 DCHECK(main_task_runner_->BelongsToCurrentThread());
488 451
489 // TODO(kylep): Remove when support for negatives is added. Also, modify the 452 // TODO(kylep): Remove when support for negatives is added. Also, modify the
490 // following checks so rewind uses reasonable values also. 453 // following checks so rewind uses reasonable values also.
491 if (rate < 0.0) 454 if (rate < 0.0)
492 return; 455 return;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 584
622 double WebMediaPlayerImpl::currentTime() const { 585 double WebMediaPlayerImpl::currentTime() const {
623 DCHECK(main_task_runner_->BelongsToCurrentThread()); 586 DCHECK(main_task_runner_->BelongsToCurrentThread());
624 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 587 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
625 588
626 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, 589 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
627 // see http://crbug.com/409280 590 // see http://crbug.com/409280
628 if (ended_) 591 if (ended_)
629 return duration(); 592 return duration();
630 593
631 // We know the current seek time better than pipeline: pipeline may processing 594 if (seeking())
632 // an earlier seek before a pending seek has been started, or it might not yet 595 return seek_time_.InSecondsF();
633 // have the current seek time returnable via GetMediaTime().
634 if (seeking()) {
635 return pending_seek_ ? pending_seek_time_.InSecondsF()
636 : seek_time_.InSecondsF();
637 }
638 596
639 #if defined(OS_ANDROID) // WMPI_CAST 597 #if defined(OS_ANDROID) // WMPI_CAST
640 if (isRemote()) { 598 if (isRemote())
641 return cast_impl_.currentTime(); 599 return cast_impl_.currentTime();
642 }
643 #endif 600 #endif
644 601
645 if (paused_) { 602 if (paused_)
646 return paused_time_.InSecondsF(); 603 return paused_time_.InSecondsF();
647 }
648 604
649 return pipeline_.GetMediaTime().InSecondsF(); 605 return pipeline_.GetMediaTime().InSecondsF();
650 } 606 }
651 607
652 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { 608 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
653 DCHECK(main_task_runner_->BelongsToCurrentThread()); 609 DCHECK(main_task_runner_->BelongsToCurrentThread());
654 return network_state_; 610 return network_state_;
655 } 611 }
656 612
657 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { 613 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 is_cdm_attached_ = true; 867 is_cdm_attached_ = true;
912 return; 868 return;
913 } 869 }
914 870
915 set_cdm_result_->completeWithError( 871 set_cdm_result_->completeWithError(
916 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0, 872 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
917 "Unable to set MediaKeys object"); 873 "Unable to set MediaKeys object");
918 set_cdm_result_.reset(); 874 set_cdm_result_.reset();
919 } 875 }
920 876
921 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, 877 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
922 PipelineStatus status) {
923 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
924 DCHECK(main_task_runner_->BelongsToCurrentThread());
925
926 if (status != PIPELINE_OK) {
927 OnPipelineError(status);
928 return;
929 }
930
931 // If we we're resuming into the playing state, notify the delegate.
932 if (resuming_ && playback_rate_ > 0 && !paused_)
933 NotifyPlaybackStarted();
934
935 // Whether or not the seek was caused by a resume, we're not suspended now.
936 resuming_ = false;
937 suspended_ = false;
938
939 // If there is a pending suspend, the seek does not complete until after the
940 // next resume.
941 if (pending_suspend_) {
942 pending_suspend_ = false;
943 pending_time_change_ = time_changed;
944 Suspend();
945 return;
946 }
947
948 // Clear seek state. Note that if the seek was caused by a resume, then
949 // |seek_time_| is always set but |seeking_| is only set if there was a
950 // pending seek at the time.
951 seeking_ = false; 878 seeking_ = false;
952 seek_time_ = base::TimeDelta(); 879 seek_time_ = base::TimeDelta();
953
954 if (pending_seek_) {
955 double pending_seek_seconds = pending_seek_time_.InSecondsF();
956 pending_seek_ = false;
957 pending_seek_time_ = base::TimeDelta();
958 seek(pending_seek_seconds);
959 return;
960 }
961
962 // Update our paused time.
963 if (paused_) 880 if (paused_)
964 UpdatePausedTime(); 881 paused_time_ = pipeline_.GetMediaTime();
965 882 if (time_updated)
966 should_notify_time_changed_ = time_changed; 883 should_notify_time_changed_ = true;
967 } 884 }
968 885
969 void WebMediaPlayerImpl::OnPipelineSuspended(PipelineStatus status) { 886 void WebMediaPlayerImpl::OnPipelineSuspended() {
970 DVLOG(1) << __FUNCTION__ << "(" << status << ")";
971 DCHECK(main_task_runner_->BelongsToCurrentThread());
972
973 if (status != PIPELINE_OK) {
974 OnPipelineError(status);
975 return;
976 }
977
978 suspending_ = false;
979 if (delegate_)
980 delegate_->PlayerGone(delegate_id_);
981
982 #if defined(OS_ANDROID) 887 #if defined(OS_ANDROID)
983 if (isRemote()) { 888 if (isRemote()) {
984 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 889 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
985 if (frame) { 890 if (frame) {
986 compositor_->PaintFrameUsingOldRenderingPath(frame); 891 compositor_->PaintFrameUsingOldRenderingPath(frame);
987 } 892 }
988 } 893 }
989 #endif 894 #endif
990 895
991 if (pending_resume_ || pending_suspend_resume_cycle_) { 896 if (pending_suspend_resume_cycle_) {
992 pending_resume_ = false;
993 pending_suspend_resume_cycle_ = false; 897 pending_suspend_resume_cycle_ = false;
994 Resume(); 898 pipeline_controller_.Resume();
995 return; 899 return;
996 } 900 }
997 } 901 }
998 902
999 void WebMediaPlayerImpl::OnPipelineEnded() { 903 void WebMediaPlayerImpl::OnPipelineEnded() {
1000 DVLOG(1) << __FUNCTION__; 904 DVLOG(1) << __FUNCTION__;
1001 DCHECK(main_task_runner_->BelongsToCurrentThread()); 905 DCHECK(main_task_runner_->BelongsToCurrentThread());
1002 906
1003 // Ignore state changes until we've completed all outstanding seeks. 907 // Ignore state changes until we've completed all outstanding operations.
1004 if (seeking_ || pending_seek_) 908 if (!pipeline_controller_.IsStable())
1005 return; 909 return;
1006 910
1007 ended_ = true; 911 ended_ = true;
1008 client_->timeChanged(); 912 client_->timeChanged();
1009 } 913 }
1010 914
1011 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { 915 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
1012 DVLOG(1) << __FUNCTION__; 916 DVLOG(1) << __FUNCTION__;
1013 DCHECK(main_task_runner_->BelongsToCurrentThread()); 917 DCHECK(main_task_runner_->BelongsToCurrentThread());
1014 DCHECK_NE(error, PIPELINE_OK); 918 DCHECK_NE(error, PIPELINE_OK);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 // playback. 958 // playback.
1055 if (delegate_ && delegate_->IsHidden()) 959 if (delegate_ && delegate_->IsHidden())
1056 OnHidden(false); 960 OnHidden(false);
1057 } 961 }
1058 } 962 }
1059 963
1060 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 964 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
1061 BufferingState buffering_state) { 965 BufferingState buffering_state) {
1062 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 966 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
1063 967
1064 // Ignore buffering state changes until we've completed all outstanding seeks. 968 // Ignore buffering state changes until we've completed all outstanding
1065 if (seeking_ || pending_seek_) 969 // operations.
970 if (!pipeline_controller_.IsStable())
1066 return; 971 return;
1067 972
1068 // TODO(scherkus): Handle other buffering states when Pipeline starts using 973 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1069 // them and translate them ready state changes http://crbug.com/144683 974 // them and translate them ready state changes http://crbug.com/144683
1070 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH); 975 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
1071 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 976 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1072 977
1073 // Let the DataSource know we have enough data. It may use this information to 978 // Let the DataSource know we have enough data. It may use this information to
1074 // release unused network connections. 979 // release unused network connections.
1075 if (data_source_) 980 if (data_source_)
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 return; 1034 return;
1130 } 1035 }
1131 1036
1132 #if defined(OS_ANDROID) 1037 #if defined(OS_ANDROID)
1133 // If we're remote, the pipeline should already be suspended. 1038 // If we're remote, the pipeline should already be suspended.
1134 if (isRemote()) 1039 if (isRemote())
1135 return; 1040 return;
1136 #endif 1041 #endif
1137 1042
1138 if (must_suspend || hasVideo()) 1043 if (must_suspend || hasVideo())
1139 ScheduleSuspend(); 1044 pipeline_controller_.Suspend();
1140 }
1141
1142 void WebMediaPlayerImpl::ScheduleSuspend() {
1143 if (!pipeline_.IsRunning())
1144 return;
1145
1146 if (resuming_ || seeking_) {
1147 pending_suspend_ = true;
1148 return;
1149 }
1150
1151 if (pending_resume_) {
1152 pending_resume_ = false;
1153 return;
1154 }
1155
1156 Suspend();
1157 }
1158
1159 void WebMediaPlayerImpl::Suspend() {
1160 DCHECK(main_task_runner_->BelongsToCurrentThread());
1161
1162 // Since Pipeline::IsRunning() may be set on the media thread there are cases
1163 // where two suspends might be issued concurrently.
1164 if (suspended_)
1165 return;
1166
1167 suspended_ = true;
1168 suspending_ = true;
1169 pipeline_.Suspend(
1170 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSuspended));
1171 } 1045 }
1172 1046
1173 void WebMediaPlayerImpl::OnShown() { 1047 void WebMediaPlayerImpl::OnShown() {
1174 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1048 DCHECK(main_task_runner_->BelongsToCurrentThread());
1175 1049
1176 #if !defined(OS_ANDROID) 1050 #if !defined(OS_ANDROID)
1177 // Suspend/Resume is enabled by default on Android. 1051 // Suspend/Resume is enabled by default on Android.
1178 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 1052 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1179 switches::kEnableMediaSuspend)) { 1053 switches::kEnableMediaSuspend)) {
1180 return; 1054 return;
1181 } 1055 }
1182 #endif // !defined(OS_ANDROID) 1056 #endif // !defined(OS_ANDROID)
1183 1057
1184 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 1058 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1185 switches::kDisableMediaSuspend)) { 1059 switches::kDisableMediaSuspend)) {
1186 return; 1060 return;
1187 } 1061 }
1188 1062
1189 #if defined(OS_ANDROID) 1063 #if defined(OS_ANDROID)
1190 // If we're remote, the pipeline should stay suspended. 1064 // If we're remote, the pipeline should stay suspended.
1191 if (isRemote()) 1065 if (isRemote())
1192 return; 1066 return;
1193 #endif 1067 #endif
1194 1068
1195 ScheduleResume(); 1069 pipeline_controller_.Resume();
1196 }
1197
1198 void WebMediaPlayerImpl::ScheduleResume() {
1199 if (!pipeline_.IsRunning())
1200 return;
1201
1202 if (suspending_) {
1203 pending_resume_ = true;
1204 return;
1205 }
1206
1207 if (pending_suspend_) {
1208 pending_suspend_ = false;
1209 return;
1210 }
1211
1212 // Might already be resuming iff we came back from remote playback recently.
1213 if (suspended_ && !resuming_)
1214 Resume();
1215 } 1070 }
1216 1071
1217 void WebMediaPlayerImpl::OnPlay() { 1072 void WebMediaPlayerImpl::OnPlay() {
1218 play(); 1073 play();
1219 client_->playbackStateChanged(); 1074 client_->playbackStateChanged();
1220 } 1075 }
1221 1076
1222 void WebMediaPlayerImpl::OnPause() { 1077 void WebMediaPlayerImpl::OnPause() {
1223 pause(); 1078 pause();
1224 client_->playbackStateChanged(); 1079 client_->playbackStateChanged();
1225 } 1080 }
1226 1081
1227 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) { 1082 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1228 volume_multiplier_ = multiplier; 1083 volume_multiplier_ = multiplier;
1229 setVolume(volume_); 1084 setVolume(volume_);
1230 } 1085 }
1231 1086
1232 void WebMediaPlayerImpl::Resume() {
1233 DCHECK(main_task_runner_->BelongsToCurrentThread());
1234 CHECK(suspended_);
1235 CHECK(!resuming_);
1236
1237 // If there was a time change pending when we suspended (which can happen when
1238 // we suspend immediately after a seek), surface it after resuming.
1239 bool time_changed = pending_time_change_;
1240 pending_time_change_ = false;
1241
1242 if (seeking_ || pending_seek_) {
1243 if (pending_seek_) {
1244 seek_time_ = pending_seek_time_;
1245 pending_seek_ = false;
1246 pending_seek_time_ = base::TimeDelta();
1247 }
1248 time_changed = true;
1249 } else {
1250 // It is safe to call GetCurrentFrameTimestamp() because VFC is stopped
1251 // during Suspend(). It won't be started again until after Resume() is
1252 // called. Use the pipeline time if there's no video.
1253 seek_time_ = hasVideo() ? compositor_->GetCurrentFrameTimestamp()
1254 : pipeline_.GetMediaTime();
1255 }
1256
1257 if (chunk_demuxer_)
1258 chunk_demuxer_->StartWaitingForSeek(seek_time_);
1259
1260 resuming_ = true;
1261 pipeline_.Resume(CreateRenderer(), seek_time_,
1262 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked,
1263 time_changed));
1264 }
1265
1266 void WebMediaPlayerImpl::ScheduleRestart() { 1087 void WebMediaPlayerImpl::ScheduleRestart() {
1267 // If we're suspended but not resuming there is no need to restart because 1088 if (!pipeline_controller_.IsSuspended()) {
1268 // there is no renderer to kill.
1269 if (!suspended_ || resuming_) {
1270 pending_suspend_resume_cycle_ = true; 1089 pending_suspend_resume_cycle_ = true;
1271 ScheduleSuspend(); 1090 pipeline_controller_.Suspend();
1272 } 1091 }
1273 } 1092 }
1274 1093
1275 #if defined(OS_ANDROID) // WMPI_CAST 1094 #if defined(OS_ANDROID) // WMPI_CAST
1276
1277 bool WebMediaPlayerImpl::isRemote() const { 1095 bool WebMediaPlayerImpl::isRemote() const {
1278 return cast_impl_.isRemote(); 1096 return cast_impl_.isRemote();
1279 } 1097 }
1280 1098
1281 void WebMediaPlayerImpl::SetMediaPlayerManager( 1099 void WebMediaPlayerImpl::SetMediaPlayerManager(
1282 RendererMediaPlayerManagerInterface* media_player_manager) { 1100 RendererMediaPlayerManagerInterface* media_player_manager) {
1283 cast_impl_.SetMediaPlayerManager(media_player_manager); 1101 cast_impl_.SetMediaPlayerManager(media_player_manager);
1284 } 1102 }
1285 1103
1286 void WebMediaPlayerImpl::requestRemotePlayback() { 1104 void WebMediaPlayerImpl::requestRemotePlayback() {
1287 cast_impl_.requestRemotePlayback(); 1105 cast_impl_.requestRemotePlayback();
1288 } 1106 }
1289 1107
1290 void WebMediaPlayerImpl::requestRemotePlaybackControl() { 1108 void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1291 cast_impl_.requestRemotePlaybackControl(); 1109 cast_impl_.requestRemotePlaybackControl();
1292 } 1110 }
1293 1111
1294 void WebMediaPlayerImpl::OnRemotePlaybackEnded() { 1112 void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1295 DVLOG(1) << __FUNCTION__; 1113 DVLOG(1) << __FUNCTION__;
1296 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1114 DCHECK(main_task_runner_->BelongsToCurrentThread());
1297 1115
1298 ended_ = true; 1116 ended_ = true;
1299 client_->timeChanged(); 1117 client_->timeChanged();
1300 } 1118 }
1301 1119
1302 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { 1120 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
1303 paused_time_ = base::TimeDelta::FromSecondsD(t); 1121 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1304 pending_seek_ = true; 1122 if (delegate_ && !delegate_->IsHidden())
1305 pending_seek_time_ = paused_time_; 1123 pipeline_controller_.Resume();
1306 1124
1307 ScheduleResume();
1308
1309 if (paused_time_ == pipeline_.GetMediaDuration()) {
1310 ended_ = true;
1311 }
1312 // We already told the delegate we're paused when remoting started. 1125 // We already told the delegate we're paused when remoting started.
1313 client_->playbackStateChanged(); 1126 client_->playbackStateChanged();
1314 client_->disconnectedFromRemoteDevice(); 1127 client_->disconnectedFromRemoteDevice();
1315 } 1128 }
1316 1129
1317 void WebMediaPlayerImpl::SuspendForRemote() { 1130 void WebMediaPlayerImpl::SuspendForRemote() {
1318 if (suspended_ && !suspending_) { 1131 if (!pipeline_controller_.IsSuspended()) {
1132 pipeline_controller_.Suspend();
1133 } else {
1134 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1135 // when already suspended, we wouldn't need this case.
1319 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 1136 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1320 if (frame) { 1137 if (frame) {
1321 compositor_->PaintFrameUsingOldRenderingPath(frame); 1138 compositor_->PaintFrameUsingOldRenderingPath(frame);
1322 } 1139 }
1323 } 1140 }
1324 ScheduleSuspend();
1325 } 1141 }
1326 1142
1327 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { 1143 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1328 if (!video_weblayer_) 1144 if (!video_weblayer_)
1329 return pipeline_metadata_.natural_size; 1145 return pipeline_metadata_.natural_size;
1330 1146
1331 return video_weblayer_->bounds(); 1147 return video_weblayer_->bounds();
1332 } 1148 }
1333 1149
1334 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) { 1150 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 chunk_demuxer_ = new ChunkDemuxer( 1241 chunk_demuxer_ = new ChunkDemuxer(
1426 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), 1242 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
1427 encrypted_media_init_data_cb, media_log_, true); 1243 encrypted_media_init_data_cb, media_log_, true);
1428 demuxer_.reset(chunk_demuxer_); 1244 demuxer_.reset(chunk_demuxer_);
1429 } 1245 }
1430 1246
1431 // ... and we're ready to go! 1247 // ... and we're ready to go!
1432 seeking_ = true; 1248 seeking_ = true;
1433 1249
1434 // TODO(sandersd): On Android, defer Start() if the tab is not visible. 1250 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
1435 pipeline_.Start( 1251 pipeline_controller_.Start(
1436 demuxer_.get(), CreateRenderer(), 1252 chunk_demuxer_, demuxer_.get(),
1437 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), 1253 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1438 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1439 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
1440 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), 1254 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
1441 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), 1255 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
1442 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), 1256 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
1443 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack), 1257 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1444 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey)); 1258 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
1445 } 1259 }
1446 1260
1447 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { 1261 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
1448 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; 1262 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
1449 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1263 DCHECK(main_task_runner_->BelongsToCurrentThread());
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 base::WaitableEvent event(false, false); 1351 base::WaitableEvent event(false, false);
1538 compositor_task_runner_->PostTask(FROM_HERE, 1352 compositor_task_runner_->PostTask(FROM_HERE,
1539 base::Bind(&GetCurrentFrameAndSignal, 1353 base::Bind(&GetCurrentFrameAndSignal,
1540 base::Unretained(compositor_), 1354 base::Unretained(compositor_),
1541 &video_frame, 1355 &video_frame,
1542 &event)); 1356 &event));
1543 event.Wait(); 1357 event.Wait();
1544 return video_frame; 1358 return video_frame;
1545 } 1359 }
1546 1360
1547 void WebMediaPlayerImpl::UpdatePausedTime() {
1548 DCHECK(main_task_runner_->BelongsToCurrentThread());
1549
1550 // pause() may be called after playback has ended and the HTMLMediaElement
1551 // requires that currentTime() == duration() after ending. We want to ensure
1552 // |paused_time_| matches currentTime() in this case or a future seek() may
1553 // incorrectly discard what it thinks is a seek to the existing time.
1554 paused_time_ =
1555 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
1556 }
1557
1558 void WebMediaPlayerImpl::NotifyPlaybackStarted() { 1361 void WebMediaPlayerImpl::NotifyPlaybackStarted() {
1559 #if defined(OS_ANDROID) // WMPI_CAST 1362 #if defined(OS_ANDROID) // WMPI_CAST
1560 // We do not tell our delegates about remote playback, becuase that would 1363 // We do not tell our delegates about remote playback, becuase that would
1561 // keep the device awake, which is not what we want. 1364 // keep the device awake, which is not what we want.
1562 if (isRemote()) 1365 if (isRemote())
1563 return; 1366 return;
1564 #endif 1367 #endif
1565 if (delegate_) { 1368 if (delegate_) {
1566 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false, 1369 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1567 pipeline_.GetMediaDuration()); 1370 pipeline_.GetMediaDuration());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1418 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1616 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1419 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1617 << ", Demuxer: " << demuxer_memory_usage; 1420 << ", Demuxer: " << demuxer_memory_usage;
1618 1421
1619 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1422 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1620 last_reported_memory_usage_ = current_memory_usage; 1423 last_reported_memory_usage_ = current_memory_usage;
1621 adjust_allocated_memory_cb_.Run(delta); 1424 adjust_allocated_memory_cb_.Run(delta);
1622 } 1425 }
1623 1426
1624 } // namespace media 1427 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698