Chromium Code Reviews| 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 #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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |