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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |