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

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: Add thread checker. Created 4 years, 9 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 network_state_(WebMediaPlayer::NetworkStateEmpty), 137 network_state_(WebMediaPlayer::NetworkStateEmpty),
137 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 138 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
138 preload_(BufferedDataSource::AUTO), 139 preload_(BufferedDataSource::AUTO),
139 buffering_strategy_( 140 buffering_strategy_(
140 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL), 141 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
141 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 142 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
142 media_task_runner_(params.media_task_runner()), 143 media_task_runner_(params.media_task_runner()),
143 worker_task_runner_(params.worker_task_runner()), 144 worker_task_runner_(params.worker_task_runner()),
144 media_log_(params.media_log()), 145 media_log_(params.media_log()),
145 pipeline_(media_task_runner_, media_log_.get()), 146 pipeline_(media_task_runner_, media_log_.get()),
147 pipeline_controller_(
148 &pipeline_,
149 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
150 base::Unretained(this)),
151 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
152 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
153 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
154 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())),
146 load_type_(LoadTypeURL), 155 load_type_(LoadTypeURL),
147 opaque_(false), 156 opaque_(false),
148 playback_rate_(0.0), 157 playback_rate_(0.0),
149 paused_(true), 158 paused_(true),
150 seeking_(false), 159 seeking_(false),
151 pending_suspend_(false),
152 pending_time_change_(false),
153 pending_resume_(false),
154 suspending_(false),
155 suspended_(false),
156 resuming_(false),
157 pending_suspend_resume_cycle_(false), 160 pending_suspend_resume_cycle_(false),
158 ended_(false), 161 ended_(false),
159 pending_seek_(false),
160 should_notify_time_changed_(false),
161 fullscreen_(false), 162 fullscreen_(false),
162 decoder_requires_restart_for_fullscreen_(false), 163 decoder_requires_restart_for_fullscreen_(false),
163 client_(client), 164 client_(client),
164 encrypted_client_(encrypted_client), 165 encrypted_client_(encrypted_client),
165 delegate_(delegate), 166 delegate_(delegate),
166 delegate_id_(0), 167 delegate_id_(0),
167 defer_load_cb_(params.defer_load_cb()), 168 defer_load_cb_(params.defer_load_cb()),
168 context_3d_cb_(params.context_3d_cb()), 169 context_3d_cb_(params.context_3d_cb()),
169 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()), 170 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
170 last_reported_memory_usage_(0), 171 last_reported_memory_usage_(0),
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 if (delegate_) { 222 if (delegate_) {
222 delegate_->PlayerGone(delegate_id_); 223 delegate_->PlayerGone(delegate_id_);
223 delegate_->RemoveObserver(delegate_id_); 224 delegate_->RemoveObserver(delegate_id_);
224 } 225 }
225 226
226 // Abort any pending IO so stopping the pipeline doesn't get blocked. 227 // Abort any pending IO so stopping the pipeline doesn't get blocked.
227 if (data_source_) 228 if (data_source_)
228 data_source_->Abort(); 229 data_source_->Abort();
229 if (chunk_demuxer_) { 230 if (chunk_demuxer_) {
230 chunk_demuxer_->Shutdown(); 231 chunk_demuxer_->Shutdown();
231 chunk_demuxer_ = NULL; 232 chunk_demuxer_ = nullptr;
232 } 233 }
233 234
234 renderer_factory_.reset(); 235 renderer_factory_.reset();
235 236
236 // Make sure to kill the pipeline so there's no more media threads running. 237 // Make sure to kill the pipeline so there's no more media threads running.
237 // Note: stopping the pipeline might block for a long time. 238 // Note: stopping the pipeline might block for a long time.
238 base::WaitableEvent waiter(false, false); 239 base::WaitableEvent waiter(false, false);
239 pipeline_.Stop( 240 pipeline_.Stop(
240 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter))); 241 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
241 waiter.Wait(); 242 waiter.Wait();
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 DCHECK(main_task_runner_->BelongsToCurrentThread()); 334 DCHECK(main_task_runner_->BelongsToCurrentThread());
334 335
335 #if defined(OS_ANDROID) // WMPI_CAST 336 #if defined(OS_ANDROID) // WMPI_CAST
336 if (isRemote()) { 337 if (isRemote()) {
337 cast_impl_.play(); 338 cast_impl_.play();
338 return; 339 return;
339 } 340 }
340 #endif 341 #endif
341 342
342 paused_ = false; 343 paused_ = false;
344 pipeline_.SetPlaybackRate(playback_rate_);
343 345
344 pipeline_.SetPlaybackRate(playback_rate_);
345 if (data_source_) 346 if (data_source_)
346 data_source_->MediaIsPlaying(); 347 data_source_->MediaIsPlaying();
347 348
348 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 349 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
349 350
350 if (playback_rate_ > 0) 351 if (playback_rate_ > 0)
351 NotifyPlaybackStarted(); 352 NotifyPlaybackStarted();
352 } 353 }
353 354
354 void WebMediaPlayerImpl::pause() { 355 void WebMediaPlayerImpl::pause() {
355 DVLOG(1) << __FUNCTION__; 356 DVLOG(1) << __FUNCTION__;
356 DCHECK(main_task_runner_->BelongsToCurrentThread()); 357 DCHECK(main_task_runner_->BelongsToCurrentThread());
357 358
358 const bool was_already_paused = paused_ || playback_rate_ == 0; 359 const bool was_already_paused = paused_ || playback_rate_ == 0;
359 paused_ = true; 360 paused_ = true;
360 361
361 #if defined(OS_ANDROID) // WMPI_CAST 362 #if defined(OS_ANDROID) // WMPI_CAST
362 if (isRemote()) { 363 if (isRemote()) {
363 cast_impl_.pause(); 364 cast_impl_.pause();
364 return; 365 return;
365 } 366 }
366 #endif 367 #endif
367 368
368 pipeline_.SetPlaybackRate(0.0); 369 pipeline_.SetPlaybackRate(0.0);
369 UpdatePausedTime(); 370
371 // pause() may be called after playback has ended and the HTMLMediaElement
372 // requires that currentTime() == duration() after ending. We want to ensure
373 // |paused_time_| matches currentTime() in this case or a future seek() may
374 // incorrectly discard what it thinks is a seek to the existing time.
375 paused_time_ =
376 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
370 377
371 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); 378 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
372 379
373 if (!was_already_paused) 380 if (!was_already_paused)
374 NotifyPlaybackPaused(); 381 NotifyPlaybackPaused();
375 } 382 }
376 383
377 bool WebMediaPlayerImpl::supportsSave() const { 384 bool WebMediaPlayerImpl::supportsSave() const {
378 DCHECK(main_task_runner_->BelongsToCurrentThread()); 385 DCHECK(main_task_runner_->BelongsToCurrentThread());
379 return supports_save_; 386 return supports_save_;
380 } 387 }
381 388
382 void WebMediaPlayerImpl::seek(double seconds) { 389 void WebMediaPlayerImpl::seek(double seconds) {
383 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; 390 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
384 DCHECK(main_task_runner_->BelongsToCurrentThread()); 391 DCHECK(main_task_runner_->BelongsToCurrentThread());
392 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
393 }
394
395 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
396 DCHECK(main_task_runner_->BelongsToCurrentThread());
385 397
386 ended_ = false; 398 ended_ = false;
387 399
388 base::TimeDelta new_seek_time = base::TimeDelta::FromSecondsD(seconds);
389
390 #if defined(OS_ANDROID) // WMPI_CAST 400 #if defined(OS_ANDROID) // WMPI_CAST
391 if (isRemote()) { 401 if (isRemote()) {
392 cast_impl_.seek(new_seek_time); 402 cast_impl_.seek(time);
393 return; 403 return;
394 } 404 }
395 #endif 405 #endif
396 406
397 ReadyState old_state = ready_state_; 407 ReadyState old_state = ready_state_;
398 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) 408 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
399 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 409 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
400 410
401 if (seeking_ || suspended_) { 411 // When paused, we know exactly what the current time is and can elide seeks
402 // Once resuming, it's too late to change the resume time and so the 412 // to it. However, there are two cases that are not elided:
403 // implementation is a little different. 413 // 1) When the pipeline state is not stable.
404 bool is_suspended = suspended_ && !resuming_; 414 // In this case we just let |pipeline_controller_| decide what to do, as
405 415 // it has complete information.
406 // If we are currently seeking or resuming to |new_seek_time|, skip the 416 // 2) For MSE.
407 // seek (except for MSE, which always seeks). 417 // Because the buffers may have changed between seeks, MSE seeks are
408 if (!is_suspended && new_seek_time == seek_time_) { 418 // never elided.
409 if (chunk_demuxer_) { 419 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
410 // Don't suppress any redundant in-progress MSE seek. There could have 420 !chunk_demuxer_) {
411 // been changes to the underlying buffers after seeking the demuxer and 421 // If the ready state was high enough before, we can indicate that the seek
412 // before receiving OnPipelineSeeked() for the currently in-progress 422 // completed just by restoring it. Otherwise we will just wait for the real
413 // seek. 423 // ready state change to eventually happen.
414 MEDIA_LOG(DEBUG, media_log_) 424 if (old_state == ReadyStateHaveEnoughData) {
415 << "Detected MediaSource seek to same time as in-progress seek to "
416 << seek_time_ << ".";
417 } else {
418 // Suppress all redundant seeks if unrestricted by media source demuxer
419 // API.
420 pending_seek_ = false;
421 pending_seek_time_ = base::TimeDelta();
422 return;
423 }
424 }
425
426 // If |chunk_demuxer_| is already seeking, cancel that seek and schedule the
427 // new one.
428 if (!is_suspended && chunk_demuxer_)
429 chunk_demuxer_->CancelPendingSeek(new_seek_time);
430
431 // Schedule a seek once the current suspend or seek finishes.
432 pending_seek_ = true;
433 pending_seek_time_ = new_seek_time;
434
435 // In the case of seeking while suspended, the seek is considered to have
436 // started immediately (but won't complete until the pipeline is resumed).
437 if (is_suspended) {
438 seeking_ = true;
439 seek_time_ = new_seek_time;
440 }
441
442 return;
443 }
444
445 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
446
447 // Update our paused time.
448 // For non-MSE playbacks, in paused state ignore the seek operations to
449 // current time if the loading is completed and generate
450 // OnPipelineBufferingStateChanged event to eventually fire seeking and seeked
451 // events. We don't short-circuit MSE seeks in this logic because the
452 // underlying buffers around the seek time might have changed (or even been
453 // removed) since previous seek/preroll/pause action, and the pipeline might
454 // need to flush so the new buffers are decoded and rendered instead of the
455 // old ones.
456 if (paused_) {
457 if (paused_time_ != new_seek_time || chunk_demuxer_) {
458 paused_time_ = new_seek_time;
459 } else if (old_state == ReadyStateHaveEnoughData) {
460 main_task_runner_->PostTask( 425 main_task_runner_->PostTask(
461 FROM_HERE, 426 FROM_HERE,
462 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, 427 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
463 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 428 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
464 return;
465 } 429 }
430 return;
466 } 431 }
467 432
468 seeking_ = true; 433 seeking_ = true;
469 seek_time_ = new_seek_time; 434 seek_time_ = time;
470 435 if (paused_)
471 if (chunk_demuxer_) 436 paused_time_ = time;
472 chunk_demuxer_->StartWaitingForSeek(seek_time_); 437 pipeline_controller_.Seek(time, time_updated);
473
474 pipeline_.Seek(seek_time_, BIND_TO_RENDER_LOOP1(
475 &WebMediaPlayerImpl::OnPipelineSeeked, true));
476 } 438 }
477 439
478 void WebMediaPlayerImpl::setRate(double rate) { 440 void WebMediaPlayerImpl::setRate(double rate) {
479 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 441 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
480 DCHECK(main_task_runner_->BelongsToCurrentThread()); 442 DCHECK(main_task_runner_->BelongsToCurrentThread());
481 443
482 // TODO(kylep): Remove when support for negatives is added. Also, modify the 444 // TODO(kylep): Remove when support for negatives is added. Also, modify the
483 // following checks so rewind uses reasonable values also. 445 // following checks so rewind uses reasonable values also.
484 if (rate < 0.0) 446 if (rate < 0.0)
485 return; 447 return;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 576
615 double WebMediaPlayerImpl::currentTime() const { 577 double WebMediaPlayerImpl::currentTime() const {
616 DCHECK(main_task_runner_->BelongsToCurrentThread()); 578 DCHECK(main_task_runner_->BelongsToCurrentThread());
617 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 579 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
618 580
619 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, 581 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
620 // see http://crbug.com/409280 582 // see http://crbug.com/409280
621 if (ended_) 583 if (ended_)
622 return duration(); 584 return duration();
623 585
624 // We know the current seek time better than pipeline: pipeline may processing 586 if (seeking())
625 // an earlier seek before a pending seek has been started, or it might not yet 587 return seek_time_.InSecondsF();
626 // have the current seek time returnable via GetMediaTime().
627 if (seeking()) {
628 return pending_seek_ ? pending_seek_time_.InSecondsF()
629 : seek_time_.InSecondsF();
630 }
631 588
632 #if defined(OS_ANDROID) // WMPI_CAST 589 #if defined(OS_ANDROID) // WMPI_CAST
633 if (isRemote()) { 590 if (isRemote())
634 return cast_impl_.currentTime(); 591 return cast_impl_.currentTime();
635 }
636 #endif 592 #endif
637 593
638 if (paused_) { 594 if (paused_)
639 return paused_time_.InSecondsF(); 595 return paused_time_.InSecondsF();
640 }
641 596
642 return pipeline_.GetMediaTime().InSecondsF(); 597 return pipeline_.GetMediaTime().InSecondsF();
643 } 598 }
644 599
645 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { 600 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
646 DCHECK(main_task_runner_->BelongsToCurrentThread()); 601 DCHECK(main_task_runner_->BelongsToCurrentThread());
647 return network_state_; 602 return network_state_;
648 } 603 }
649 604
650 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { 605 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 is_cdm_attached_ = true; 825 is_cdm_attached_ = true;
871 return; 826 return;
872 } 827 }
873 828
874 set_cdm_result_->completeWithError( 829 set_cdm_result_->completeWithError(
875 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0, 830 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
876 "Unable to set MediaKeys object"); 831 "Unable to set MediaKeys object");
877 set_cdm_result_.reset(); 832 set_cdm_result_.reset();
878 } 833 }
879 834
880 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, 835 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
881 PipelineStatus status) {
882 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
883 DCHECK(main_task_runner_->BelongsToCurrentThread());
884
885 if (status != PIPELINE_OK) {
886 OnPipelineError(status);
887 return;
888 }
889
890 // If we we're resuming into the playing state, notify the delegate.
891 if (resuming_ && playback_rate_ > 0 && !paused_)
892 NotifyPlaybackStarted();
893
894 // Whether or not the seek was caused by a resume, we're not suspended now.
895 resuming_ = false;
896 suspended_ = false;
897
898 // If there is a pending suspend, the seek does not complete until after the
899 // next resume.
900 if (pending_suspend_) {
901 pending_suspend_ = false;
902 pending_time_change_ = time_changed;
903 Suspend();
904 return;
905 }
906
907 // Clear seek state. Note that if the seek was caused by a resume, then
908 // |seek_time_| is always set but |seeking_| is only set if there was a
909 // pending seek at the time.
910 seeking_ = false; 836 seeking_ = false;
911 seek_time_ = base::TimeDelta(); 837 seek_time_ = base::TimeDelta();
912
913 if (pending_seek_) {
914 double pending_seek_seconds = pending_seek_time_.InSecondsF();
915 pending_seek_ = false;
916 pending_seek_time_ = base::TimeDelta();
917 seek(pending_seek_seconds);
918 return;
919 }
920
921 // Update our paused time.
922 if (paused_) 838 if (paused_)
923 UpdatePausedTime(); 839 paused_time_ = pipeline_.GetMediaTime();
924 840 if (time_updated)
925 should_notify_time_changed_ = time_changed; 841 should_notify_time_changed_ = true;
926 } 842 }
927 843
928 void WebMediaPlayerImpl::OnPipelineSuspended(PipelineStatus status) { 844 void WebMediaPlayerImpl::OnPipelineSuspended() {
929 DVLOG(1) << __FUNCTION__ << "(" << status << ")";
930 DCHECK(main_task_runner_->BelongsToCurrentThread());
931
932 if (status != PIPELINE_OK) {
933 OnPipelineError(status);
934 return;
935 }
936
937 suspending_ = false;
938 if (delegate_)
939 delegate_->PlayerGone(delegate_id_);
940
941 #if defined(OS_ANDROID) 845 #if defined(OS_ANDROID)
942 if (isRemote()) { 846 if (isRemote()) {
943 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 847 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
944 if (frame) { 848 if (frame) {
945 compositor_->PaintFrameUsingOldRenderingPath(frame); 849 compositor_->PaintFrameUsingOldRenderingPath(frame);
946 } 850 }
947 } 851 }
948 #endif 852 #endif
949 853
950 if (pending_resume_ || pending_suspend_resume_cycle_) { 854 if (delegate_)
951 pending_resume_ = false; 855 delegate_->PlayerGone(delegate_id_);
856
857 if (pending_suspend_resume_cycle_) {
952 pending_suspend_resume_cycle_ = false; 858 pending_suspend_resume_cycle_ = false;
953 Resume(); 859 pipeline_controller_.Resume();
954 return; 860 return;
955 } 861 }
956 } 862 }
957 863
864 void WebMediaPlayerImpl::OnPipelineResumed() {
865 if (playback_rate_ > 0 && !paused_)
866 NotifyPlaybackStarted();
867 }
868
958 void WebMediaPlayerImpl::OnPipelineEnded() { 869 void WebMediaPlayerImpl::OnPipelineEnded() {
959 DVLOG(1) << __FUNCTION__; 870 DVLOG(1) << __FUNCTION__;
960 DCHECK(main_task_runner_->BelongsToCurrentThread()); 871 DCHECK(main_task_runner_->BelongsToCurrentThread());
961 872
962 // Ignore state changes until we've completed all outstanding seeks. 873 // Ignore state changes until we've completed all outstanding operations.
963 if (seeking_ || pending_seek_) 874 if (!pipeline_controller_.IsStable())
964 return; 875 return;
965 876
966 ended_ = true; 877 ended_ = true;
967 client_->timeChanged(); 878 client_->timeChanged();
968 } 879 }
969 880
970 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { 881 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
971 DVLOG(1) << __FUNCTION__; 882 DVLOG(1) << __FUNCTION__;
972 DCHECK(main_task_runner_->BelongsToCurrentThread()); 883 DCHECK(main_task_runner_->BelongsToCurrentThread());
973 DCHECK_NE(error, PIPELINE_OK); 884 DCHECK_NE(error, PIPELINE_OK);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 // playback. 924 // playback.
1014 if (delegate_ && delegate_->IsHidden()) 925 if (delegate_ && delegate_->IsHidden())
1015 OnHidden(false); 926 OnHidden(false);
1016 } 927 }
1017 } 928 }
1018 929
1019 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 930 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
1020 BufferingState buffering_state) { 931 BufferingState buffering_state) {
1021 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 932 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
1022 933
1023 // Ignore buffering state changes until we've completed all outstanding seeks. 934 // Ignore buffering state changes until we've completed all outstanding
1024 if (seeking_ || pending_seek_) 935 // operations.
936 if (!pipeline_controller_.IsStable())
1025 return; 937 return;
1026 938
1027 // TODO(scherkus): Handle other buffering states when Pipeline starts using 939 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1028 // them and translate them ready state changes http://crbug.com/144683 940 // them and translate them ready state changes http://crbug.com/144683
1029 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH); 941 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
1030 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 942 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1031 943
1032 // Let the DataSource know we have enough data. It may use this information to 944 // Let the DataSource know we have enough data. It may use this information to
1033 // release unused network connections. 945 // release unused network connections.
1034 if (data_source_) 946 if (data_source_)
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 return; 1000 return;
1089 } 1001 }
1090 1002
1091 #if defined(OS_ANDROID) 1003 #if defined(OS_ANDROID)
1092 // If we're remote, the pipeline should already be suspended. 1004 // If we're remote, the pipeline should already be suspended.
1093 if (isRemote()) 1005 if (isRemote())
1094 return; 1006 return;
1095 #endif 1007 #endif
1096 1008
1097 if (must_suspend || paused_ || hasVideo()) 1009 if (must_suspend || paused_ || hasVideo())
1098 ScheduleSuspend(); 1010 pipeline_controller_.Suspend();
1099 }
1100
1101 void WebMediaPlayerImpl::ScheduleSuspend() {
1102 if (!pipeline_.IsRunning())
1103 return;
1104
1105 if (resuming_ || seeking_) {
1106 pending_suspend_ = true;
1107 return;
1108 }
1109
1110 if (pending_resume_) {
1111 pending_resume_ = false;
1112 return;
1113 }
1114
1115 Suspend();
1116 }
1117
1118 void WebMediaPlayerImpl::Suspend() {
1119 DCHECK(main_task_runner_->BelongsToCurrentThread());
1120
1121 // Since Pipeline::IsRunning() may be set on the media thread there are cases
1122 // where two suspends might be issued concurrently.
1123 if (suspended_)
1124 return;
1125
1126 suspended_ = true;
1127 suspending_ = true;
1128 pipeline_.Suspend(
1129 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSuspended));
1130 } 1011 }
1131 1012
1132 void WebMediaPlayerImpl::OnShown() { 1013 void WebMediaPlayerImpl::OnShown() {
1133 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1014 DCHECK(main_task_runner_->BelongsToCurrentThread());
1134 1015
1135 #if !defined(OS_ANDROID) 1016 #if !defined(OS_ANDROID)
1136 // Suspend/Resume is enabled by default on Android. 1017 // Suspend/Resume is enabled by default on Android.
1137 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 1018 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1138 switches::kEnableMediaSuspend)) { 1019 switches::kEnableMediaSuspend)) {
1139 return; 1020 return;
1140 } 1021 }
1141 #endif // !defined(OS_ANDROID) 1022 #endif // !defined(OS_ANDROID)
1142 1023
1143 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 1024 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1144 switches::kDisableMediaSuspend)) { 1025 switches::kDisableMediaSuspend)) {
1145 return; 1026 return;
1146 } 1027 }
1147 1028
1148 #if defined(OS_ANDROID) 1029 #if defined(OS_ANDROID)
1149 // If we're remote, the pipeline should stay suspended. 1030 // If we're remote, the pipeline should stay suspended.
1150 if (isRemote()) 1031 if (isRemote())
1151 return; 1032 return;
1152 #endif 1033 #endif
1153 1034
1154 ScheduleResume(); 1035 pipeline_controller_.Resume();
1155 }
1156
1157 void WebMediaPlayerImpl::ScheduleResume() {
1158 if (!pipeline_.IsRunning())
1159 return;
1160
1161 if (suspending_) {
1162 pending_resume_ = true;
1163 return;
1164 }
1165
1166 if (pending_suspend_) {
1167 pending_suspend_ = false;
1168 return;
1169 }
1170
1171 // Might already be resuming iff we came back from remote playback recently.
1172 if (suspended_ && !resuming_)
1173 Resume();
1174 } 1036 }
1175 1037
1176 void WebMediaPlayerImpl::OnPlay() { 1038 void WebMediaPlayerImpl::OnPlay() {
1177 play(); 1039 play();
1178 client_->playbackStateChanged(); 1040 client_->playbackStateChanged();
1179 } 1041 }
1180 1042
1181 void WebMediaPlayerImpl::OnPause() { 1043 void WebMediaPlayerImpl::OnPause() {
1182 pause(); 1044 pause();
1183 client_->playbackStateChanged(); 1045 client_->playbackStateChanged();
1184 } 1046 }
1185 1047
1186 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) { 1048 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1187 volume_multiplier_ = multiplier; 1049 volume_multiplier_ = multiplier;
1188 setVolume(volume_); 1050 setVolume(volume_);
1189 } 1051 }
1190 1052
1191 void WebMediaPlayerImpl::Resume() {
1192 DCHECK(main_task_runner_->BelongsToCurrentThread());
1193 CHECK(suspended_);
1194 CHECK(!resuming_);
1195
1196 // If there was a time change pending when we suspended (which can happen when
1197 // we suspend immediately after a seek), surface it after resuming.
1198 bool time_changed = pending_time_change_;
1199 pending_time_change_ = false;
1200
1201 if (seeking_ || pending_seek_) {
1202 if (pending_seek_) {
1203 seek_time_ = pending_seek_time_;
1204 pending_seek_ = false;
1205 pending_seek_time_ = base::TimeDelta();
1206 }
1207 time_changed = true;
1208 } else {
1209 // It is safe to call GetCurrentFrameTimestamp() because VFC is stopped
1210 // during Suspend(). It won't be started again until after Resume() is
1211 // called. Use the pipeline time if there's no video.
1212 if (!data_source_ || !data_source_->IsStreaming()) {
1213 seek_time_ = hasVideo() ? compositor_->GetCurrentFrameTimestamp()
1214 : pipeline_.GetMediaTime();
1215 } else {
1216 // Resume from zero if a resource does not support range requests; this
1217 // avoids a painful "read-the-whole-file" seek penalty.
1218 seek_time_ = base::TimeDelta();
1219 }
1220 }
1221
1222 if (chunk_demuxer_)
1223 chunk_demuxer_->StartWaitingForSeek(seek_time_);
1224
1225 resuming_ = true;
1226 pipeline_.Resume(CreateRenderer(), seek_time_,
1227 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked,
1228 time_changed));
1229 }
1230
1231 void WebMediaPlayerImpl::ScheduleRestart() { 1053 void WebMediaPlayerImpl::ScheduleRestart() {
1232 // If we're suspended but not resuming there is no need to restart because 1054 if (!pipeline_controller_.IsSuspended()) {
1233 // there is no renderer to kill.
1234 if (!suspended_ || resuming_) {
1235 pending_suspend_resume_cycle_ = true; 1055 pending_suspend_resume_cycle_ = true;
1236 ScheduleSuspend(); 1056 pipeline_controller_.Suspend();
1237 } 1057 }
1238 } 1058 }
1239 1059
1240 #if defined(OS_ANDROID) // WMPI_CAST 1060 #if defined(OS_ANDROID) // WMPI_CAST
1241
1242 bool WebMediaPlayerImpl::isRemote() const { 1061 bool WebMediaPlayerImpl::isRemote() const {
1243 return cast_impl_.isRemote(); 1062 return cast_impl_.isRemote();
1244 } 1063 }
1245 1064
1246 void WebMediaPlayerImpl::SetMediaPlayerManager( 1065 void WebMediaPlayerImpl::SetMediaPlayerManager(
1247 RendererMediaPlayerManagerInterface* media_player_manager) { 1066 RendererMediaPlayerManagerInterface* media_player_manager) {
1248 cast_impl_.SetMediaPlayerManager(media_player_manager); 1067 cast_impl_.SetMediaPlayerManager(media_player_manager);
1249 } 1068 }
1250 1069
1251 void WebMediaPlayerImpl::requestRemotePlayback() { 1070 void WebMediaPlayerImpl::requestRemotePlayback() {
1252 cast_impl_.requestRemotePlayback(); 1071 cast_impl_.requestRemotePlayback();
1253 } 1072 }
1254 1073
1255 void WebMediaPlayerImpl::requestRemotePlaybackControl() { 1074 void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1256 cast_impl_.requestRemotePlaybackControl(); 1075 cast_impl_.requestRemotePlaybackControl();
1257 } 1076 }
1258 1077
1259 void WebMediaPlayerImpl::OnRemotePlaybackEnded() { 1078 void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1260 DVLOG(1) << __FUNCTION__; 1079 DVLOG(1) << __FUNCTION__;
1261 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1080 DCHECK(main_task_runner_->BelongsToCurrentThread());
1262 1081
1263 ended_ = true; 1082 ended_ = true;
1264 client_->timeChanged(); 1083 client_->timeChanged();
1265 } 1084 }
1266 1085
1267 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { 1086 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
1268 paused_time_ = base::TimeDelta::FromSecondsD(t); 1087 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1269 pending_seek_ = true; 1088 if (delegate_ && !delegate_->IsHidden())
1270 pending_seek_time_ = paused_time_; 1089 pipeline_controller_.Resume();
1271 1090
1272 ScheduleResume();
1273
1274 if (paused_time_ == pipeline_.GetMediaDuration()) {
1275 ended_ = true;
1276 }
1277 // We already told the delegate we're paused when remoting started. 1091 // We already told the delegate we're paused when remoting started.
1278 client_->playbackStateChanged(); 1092 client_->playbackStateChanged();
1279 client_->disconnectedFromRemoteDevice(); 1093 client_->disconnectedFromRemoteDevice();
1280 } 1094 }
1281 1095
1282 void WebMediaPlayerImpl::SuspendForRemote() { 1096 void WebMediaPlayerImpl::SuspendForRemote() {
1283 if (suspended_ && !suspending_) { 1097 if (!pipeline_controller_.IsSuspended()) {
1098 pipeline_controller_.Suspend();
1099 } else {
1100 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1101 // when already suspended, we wouldn't need this case.
1284 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 1102 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1285 if (frame) { 1103 if (frame) {
1286 compositor_->PaintFrameUsingOldRenderingPath(frame); 1104 compositor_->PaintFrameUsingOldRenderingPath(frame);
1287 } 1105 }
1288 } 1106 }
1289 ScheduleSuspend();
1290 } 1107 }
1291 1108
1292 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { 1109 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1293 if (!video_weblayer_) 1110 if (!video_weblayer_)
1294 return pipeline_metadata_.natural_size; 1111 return pipeline_metadata_.natural_size;
1295 1112
1296 return video_weblayer_->bounds(); 1113 return video_weblayer_->bounds();
1297 } 1114 }
1298 1115
1299 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) { 1116 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1390 chunk_demuxer_ = new ChunkDemuxer( 1207 chunk_demuxer_ = new ChunkDemuxer(
1391 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), 1208 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
1392 encrypted_media_init_data_cb, media_log_, true); 1209 encrypted_media_init_data_cb, media_log_, true);
1393 demuxer_.reset(chunk_demuxer_); 1210 demuxer_.reset(chunk_demuxer_);
1394 } 1211 }
1395 1212
1396 // ... and we're ready to go! 1213 // ... and we're ready to go!
1397 seeking_ = true; 1214 seeking_ = true;
1398 1215
1399 // TODO(sandersd): On Android, defer Start() if the tab is not visible. 1216 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
1400 pipeline_.Start( 1217 bool is_streaming = (data_source_ && data_source_->IsStreaming());
1401 demuxer_.get(), CreateRenderer(), 1218 pipeline_controller_.Start(
1219 chunk_demuxer_, demuxer_.get(), is_streaming,
1402 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), 1220 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1403 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1404 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
1405 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), 1221 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
1406 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), 1222 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
1407 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), 1223 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
1408 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack), 1224 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1409 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey)); 1225 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
1410 } 1226 }
1411 1227
1412 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { 1228 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
1413 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; 1229 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
1414 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1230 DCHECK(main_task_runner_->BelongsToCurrentThread());
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 base::WaitableEvent event(false, false); 1318 base::WaitableEvent event(false, false);
1503 compositor_task_runner_->PostTask(FROM_HERE, 1319 compositor_task_runner_->PostTask(FROM_HERE,
1504 base::Bind(&GetCurrentFrameAndSignal, 1320 base::Bind(&GetCurrentFrameAndSignal,
1505 base::Unretained(compositor_), 1321 base::Unretained(compositor_),
1506 &video_frame, 1322 &video_frame,
1507 &event)); 1323 &event));
1508 event.Wait(); 1324 event.Wait();
1509 return video_frame; 1325 return video_frame;
1510 } 1326 }
1511 1327
1512 void WebMediaPlayerImpl::UpdatePausedTime() {
1513 DCHECK(main_task_runner_->BelongsToCurrentThread());
1514
1515 // pause() may be called after playback has ended and the HTMLMediaElement
1516 // requires that currentTime() == duration() after ending. We want to ensure
1517 // |paused_time_| matches currentTime() in this case or a future seek() may
1518 // incorrectly discard what it thinks is a seek to the existing time.
1519 paused_time_ =
1520 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
1521 }
1522
1523 void WebMediaPlayerImpl::NotifyPlaybackStarted() { 1328 void WebMediaPlayerImpl::NotifyPlaybackStarted() {
1524 #if defined(OS_ANDROID) // WMPI_CAST 1329 #if defined(OS_ANDROID) // WMPI_CAST
1525 // We do not tell our delegates about remote playback, becuase that would 1330 // We do not tell our delegates about remote playback, becuase that would
1526 // keep the device awake, which is not what we want. 1331 // keep the device awake, which is not what we want.
1527 if (isRemote()) 1332 if (isRemote())
1528 return; 1333 return;
1529 #endif 1334 #endif
1335
1336 // NotifyPlaybackStarted() may be called by interactions while suspended,
1337 // (play/pause in particular). Those actions won't have any effect until the
1338 // pipeline is resumed.
1339 // TODO(dalecurtis): Should these be dropped at the call sites instead?
1340 // Alternatively, rename this method to include Maybe or Changed, and handle
1341 // multiple calls safely.
1342 if (pipeline_controller_.IsSuspended())
1343 return;
1344
1530 if (delegate_) { 1345 if (delegate_) {
1531 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false, 1346 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1532 pipeline_.GetMediaDuration()); 1347 pipeline_.GetMediaDuration());
1533 } 1348 }
1534 if (!memory_usage_reporting_timer_.IsRunning()) { 1349 if (!memory_usage_reporting_timer_.IsRunning()) {
1535 memory_usage_reporting_timer_.Start(FROM_HERE, 1350 memory_usage_reporting_timer_.Start(FROM_HERE,
1536 base::TimeDelta::FromSeconds(2), this, 1351 base::TimeDelta::FromSeconds(2), this,
1537 &WebMediaPlayerImpl::ReportMemoryUsage); 1352 &WebMediaPlayerImpl::ReportMemoryUsage);
1538 } 1353 }
1539 } 1354 }
1540 1355
1541 void WebMediaPlayerImpl::NotifyPlaybackPaused() { 1356 void WebMediaPlayerImpl::NotifyPlaybackPaused() {
1542 #if defined(OS_ANDROID) // WMPI_CAST 1357 #if defined(OS_ANDROID) // WMPI_CAST
1543 if (isRemote()) 1358 if (isRemote())
1544 return; 1359 return;
1545 #endif 1360 #endif
1546 if (delegate_) 1361 if (delegate_)
DaleCurtis 2016/02/26 22:34:34 You need to block these too on issupended.
sandersd (OOO until July 31) 2016/02/26 23:25:07 Done.
1547 delegate_->DidPause(delegate_id_, ended_); 1362 delegate_->DidPause(delegate_id_, ended_);
1548 memory_usage_reporting_timer_.Stop(); 1363 memory_usage_reporting_timer_.Stop();
1549 ReportMemoryUsage(); 1364 ReportMemoryUsage();
1550 } 1365 }
1551 1366
1552 void WebMediaPlayerImpl::ReportMemoryUsage() { 1367 void WebMediaPlayerImpl::ReportMemoryUsage() {
1553 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1368 DCHECK(main_task_runner_->BelongsToCurrentThread());
1554 1369
1555 // About base::Unretained() usage below: We destroy |demuxer_| on the main 1370 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1556 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 1371 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
(...skipping 23 matching lines...) Expand all
1580 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1395 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1581 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1396 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1582 << ", Demuxer: " << demuxer_memory_usage; 1397 << ", Demuxer: " << demuxer_memory_usage;
1583 1398
1584 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1399 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1585 last_reported_memory_usage_ = current_memory_usage; 1400 last_reported_memory_usage_ = current_memory_usage;
1586 adjust_allocated_memory_cb_.Run(delta); 1401 adjust_allocated_memory_cb_.Run(delta);
1587 } 1402 }
1588 1403
1589 } // namespace media 1404 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698