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

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

Issue 1830913005: Convert WMPI state management to level-triggered. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use EXPECT_TRUE/EXPECT_FALSE. Created 4 years, 8 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
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/blink/webmediaplayer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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>
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 const double kMinRate = 0.0625; 94 const double kMinRate = 0.0625;
95 const double kMaxRate = 16.0; 95 const double kMaxRate = 16.0;
96 96
97 void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink, 97 void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
98 const std::string& device_id, 98 const std::string& device_id,
99 const url::Origin& security_origin, 99 const url::Origin& security_origin,
100 const OutputDeviceStatusCB& callback) { 100 const OutputDeviceStatusCB& callback) {
101 sink->SwitchOutputDevice(device_id, security_origin, callback); 101 sink->SwitchOutputDevice(device_id, security_origin, callback);
102 } 102 }
103 103
104 bool IsSuspendUponHiddenEnabled() { 104 bool IsBackgroundedSuspendEnabled() {
105 #if !defined(OS_ANDROID) 105 #if !defined(OS_ANDROID)
106 // Suspend/Resume is only enabled by default on Android. 106 // Suspend/Resume is only enabled by default on Android.
107 return base::CommandLine::ForCurrentProcess()->HasSwitch( 107 return base::CommandLine::ForCurrentProcess()->HasSwitch(
108 switches::kEnableMediaSuspend); 108 switches::kEnableMediaSuspend);
109 #else 109 #else
110 return !base::CommandLine::ForCurrentProcess()->HasSwitch( 110 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
111 switches::kDisableMediaSuspend); 111 switches::kDisableMediaSuspend);
112 #endif 112 #endif
113 } 113 }
114 114
115 bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) {
116 bool result = state == blink::WebMediaPlayer::NetworkStateFormatError ||
117 state == blink::WebMediaPlayer::NetworkStateNetworkError ||
118 state == blink::WebMediaPlayer::NetworkStateDecodeError;
119 DCHECK_EQ(state > blink::WebMediaPlayer::NetworkStateLoaded, result);
120 return result;
121 }
122
115 } // namespace 123 } // namespace
116 124
117 class BufferedDataSourceHostImpl; 125 class BufferedDataSourceHostImpl;
118 126
119 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified, 127 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
120 UrlData::CORS_UNSPECIFIED); 128 UrlData::CORS_UNSPECIFIED);
121 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS); 129 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
122 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials, 130 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
123 UrlData::CORS_USE_CREDENTIALS); 131 UrlData::CORS_USE_CREDENTIALS);
124 132
125 #define BIND_TO_RENDER_LOOP(function) \ 133 #define BIND_TO_RENDER_LOOP(function) \
126 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \ 134 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
127 BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) 135 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
128 136
129 #define BIND_TO_RENDER_LOOP1(function, arg1) \ 137 #define BIND_TO_RENDER_LOOP1(function, arg1) \
130 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \ 138 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
131 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1))) 139 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
132 140
133 WebMediaPlayerImpl::WebMediaPlayerImpl( 141 WebMediaPlayerImpl::WebMediaPlayerImpl(
134 blink::WebLocalFrame* frame, 142 blink::WebLocalFrame* frame,
135 blink::WebMediaPlayerClient* client, 143 blink::WebMediaPlayerClient* client,
136 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client, 144 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
137 base::WeakPtr<WebMediaPlayerDelegate> delegate, 145 base::WeakPtr<WebMediaPlayerDelegate> delegate,
138 scoped_ptr<RendererFactory> renderer_factory, 146 scoped_ptr<RendererFactory> renderer_factory,
139 linked_ptr<UrlIndex> url_index, 147 linked_ptr<UrlIndex> url_index,
140 const WebMediaPlayerParams& params) 148 const WebMediaPlayerParams& params)
141 : frame_(frame), 149 : frame_(frame),
150 delegate_state_(DelegateState::GONE),
151 is_idle_(false),
152 must_suspend_(false),
142 network_state_(WebMediaPlayer::NetworkStateEmpty), 153 network_state_(WebMediaPlayer::NetworkStateEmpty),
143 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 154 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
155 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
144 preload_(BufferedDataSource::AUTO), 156 preload_(BufferedDataSource::AUTO),
145 buffering_strategy_( 157 buffering_strategy_(
146 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL), 158 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
147 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 159 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
148 media_task_runner_(params.media_task_runner()), 160 media_task_runner_(params.media_task_runner()),
149 worker_task_runner_(params.worker_task_runner()), 161 worker_task_runner_(params.worker_task_runner()),
150 media_log_(params.media_log()), 162 media_log_(params.media_log()),
151 pipeline_(media_task_runner_, media_log_.get()), 163 pipeline_(media_task_runner_, media_log_.get()),
152 pipeline_controller_( 164 pipeline_controller_(
153 &pipeline_, 165 &pipeline_,
154 base::Bind(&WebMediaPlayerImpl::CreateRenderer, 166 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
155 base::Unretained(this)), 167 base::Unretained(this)),
156 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()), 168 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
157 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()), 169 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
158 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
159 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())), 170 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())),
160 load_type_(LoadTypeURL), 171 load_type_(LoadTypeURL),
161 opaque_(false), 172 opaque_(false),
162 playback_rate_(0.0), 173 playback_rate_(0.0),
163 paused_(true), 174 paused_(true),
164 seeking_(false), 175 seeking_(false),
165 pending_suspend_resume_cycle_(false), 176 pending_suspend_resume_cycle_(false),
166 ended_(false), 177 ended_(false),
167 should_notify_time_changed_(false), 178 should_notify_time_changed_(false),
168 fullscreen_(false), 179 fullscreen_(false),
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 DVLOG(1) << __FUNCTION__; 350 DVLOG(1) << __FUNCTION__;
340 DCHECK(main_task_runner_->BelongsToCurrentThread()); 351 DCHECK(main_task_runner_->BelongsToCurrentThread());
341 352
342 #if defined(OS_ANDROID) // WMPI_CAST 353 #if defined(OS_ANDROID) // WMPI_CAST
343 if (isRemote()) { 354 if (isRemote()) {
344 cast_impl_.play(); 355 cast_impl_.play();
345 return; 356 return;
346 } 357 }
347 #endif 358 #endif
348 359
349 const bool was_paused = paused_;
350 paused_ = false; 360 paused_ = false;
361 is_idle_ = false;
351 pipeline_.SetPlaybackRate(playback_rate_); 362 pipeline_.SetPlaybackRate(playback_rate_);
352 363
353 if (data_source_) 364 if (data_source_)
354 data_source_->MediaIsPlaying(); 365 data_source_->MediaIsPlaying();
355 366
356 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 367 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
357 368 UpdatePlayState();
358 if (playback_rate_ > 0 && was_paused) {
359 NotifyPlaybackStarted();
360
361 // Resume the player if allowed. We always call Resume() in case there is a
362 // pending suspend that should be aborted. If the pipeline is not suspended,
363 // Resume() will have no effect.
364 if (IsAutomaticResumeAllowed())
365 pipeline_controller_.Resume();
366 }
367 } 369 }
368 370
369 void WebMediaPlayerImpl::pause() { 371 void WebMediaPlayerImpl::pause() {
370 DVLOG(1) << __FUNCTION__; 372 DVLOG(1) << __FUNCTION__;
371 DCHECK(main_task_runner_->BelongsToCurrentThread()); 373 DCHECK(main_task_runner_->BelongsToCurrentThread());
372 374
373 const bool was_already_paused = paused_ || playback_rate_ == 0; 375 // We update the paused state even when casting, since we expect pause() to be
376 // called when casting begins, and when we exit casting we should end up in a
377 // paused state.
374 paused_ = true; 378 paused_ = true;
375 379
376 #if defined(OS_ANDROID) // WMPI_CAST 380 #if defined(OS_ANDROID) // WMPI_CAST
377 if (isRemote()) { 381 if (isRemote()) {
378 cast_impl_.pause(); 382 cast_impl_.pause();
379 return; 383 return;
380 } 384 }
381 #endif 385 #endif
382 386
383 pipeline_.SetPlaybackRate(0.0); 387 pipeline_.SetPlaybackRate(0.0);
384 388
385 // pause() may be called after playback has ended and the HTMLMediaElement 389 // pause() may be called after playback has ended and the HTMLMediaElement
386 // requires that currentTime() == duration() after ending. We want to ensure 390 // requires that currentTime() == duration() after ending. We want to ensure
387 // |paused_time_| matches currentTime() in this case or a future seek() may 391 // |paused_time_| matches currentTime() in this case or a future seek() may
388 // incorrectly discard what it thinks is a seek to the existing time. 392 // incorrectly discard what it thinks is a seek to the existing time.
389 paused_time_ = 393 paused_time_ =
390 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime(); 394 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
391 395
392 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); 396 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
393 397 UpdatePlayState();
394 if (!was_already_paused)
395 NotifyPlaybackPaused();
396 } 398 }
397 399
398 bool WebMediaPlayerImpl::supportsSave() const { 400 bool WebMediaPlayerImpl::supportsSave() const {
399 DCHECK(main_task_runner_->BelongsToCurrentThread()); 401 DCHECK(main_task_runner_->BelongsToCurrentThread());
400 return supports_save_; 402 return supports_save_;
401 } 403 }
402 404
403 void WebMediaPlayerImpl::seek(double seconds) { 405 void WebMediaPlayerImpl::seek(double seconds) {
404 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; 406 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
405 DCHECK(main_task_runner_->BelongsToCurrentThread()); 407 DCHECK(main_task_runner_->BelongsToCurrentThread());
406 DoSeek(base::TimeDelta::FromSecondsD(seconds), true); 408 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
407 } 409 }
408 410
409 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) { 411 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
410 DCHECK(main_task_runner_->BelongsToCurrentThread()); 412 DCHECK(main_task_runner_->BelongsToCurrentThread());
411 413
412 ended_ = false;
413
414 #if defined(OS_ANDROID) // WMPI_CAST 414 #if defined(OS_ANDROID) // WMPI_CAST
415 if (isRemote()) { 415 if (isRemote()) {
416 cast_impl_.seek(time); 416 cast_impl_.seek(time);
417 return; 417 return;
418 } 418 }
419 #endif 419 #endif
420 420
421 ReadyState old_state = ready_state_; 421 ReadyState old_state = ready_state_;
422 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) 422 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
423 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 423 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
(...skipping 13 matching lines...) Expand all
437 // ready state change to eventually happen. 437 // ready state change to eventually happen.
438 if (old_state == ReadyStateHaveEnoughData) { 438 if (old_state == ReadyStateHaveEnoughData) {
439 main_task_runner_->PostTask( 439 main_task_runner_->PostTask(
440 FROM_HERE, 440 FROM_HERE,
441 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, 441 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
442 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 442 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
443 } 443 }
444 return; 444 return;
445 } 445 }
446 446
447 // TODO(sandersd): Ideally we would not clear the idle state if
448 // |pipeline_controller_| can elide the seek.
449 is_idle_ = false;
450 ended_ = false;
451
447 seeking_ = true; 452 seeking_ = true;
448 seek_time_ = time; 453 seek_time_ = time;
449 if (paused_) 454 if (paused_)
450 paused_time_ = time; 455 paused_time_ = time;
451 pipeline_controller_.Seek(time, time_updated); 456 pipeline_controller_.Seek(time, time_updated);
452 457
453 // Resume the pipeline if allowed so that the correct frame is displayed. We 458 // This needs to be called after Seek() so that if a resume is triggered, it
454 // always call Resume() in case there is a pending suspend that should be 459 // is to the correct time.
455 // aborted. If the pipeline is not suspended, Resume() will have no effect. 460 UpdatePlayState();
456 if (IsAutomaticResumeAllowed())
457 pipeline_controller_.Resume();
458 } 461 }
459 462
460 void WebMediaPlayerImpl::setRate(double rate) { 463 void WebMediaPlayerImpl::setRate(double rate) {
461 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 464 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
462 DCHECK(main_task_runner_->BelongsToCurrentThread()); 465 DCHECK(main_task_runner_->BelongsToCurrentThread());
463 466
464 // TODO(kylep): Remove when support for negatives is added. Also, modify the 467 // TODO(kylep): Remove when support for negatives is added. Also, modify the
465 // following checks so rewind uses reasonable values also. 468 // following checks so rewind uses reasonable values also.
466 if (rate < 0.0) 469 if (rate < 0.0)
467 return; 470 return;
468 471
469 // Limit rates to reasonable values by clamping. 472 // Limit rates to reasonable values by clamping.
470 if (rate != 0.0) { 473 if (rate != 0.0) {
471 if (rate < kMinRate) 474 if (rate < kMinRate)
472 rate = kMinRate; 475 rate = kMinRate;
473 else if (rate > kMaxRate) 476 else if (rate > kMaxRate)
474 rate = kMaxRate; 477 rate = kMaxRate;
475 if (playback_rate_ == 0 && !paused_)
476 NotifyPlaybackStarted();
477 } else if (playback_rate_ != 0 && !paused_) {
478 NotifyPlaybackPaused();
479 } 478 }
480 479
481 playback_rate_ = rate; 480 playback_rate_ = rate;
482 if (!paused_) { 481 if (!paused_) {
483 pipeline_.SetPlaybackRate(rate); 482 pipeline_.SetPlaybackRate(rate);
484 if (data_source_) 483 if (data_source_)
485 data_source_->MediaPlaybackRateChanged(rate); 484 data_source_->MediaPlaybackRateChanged(rate);
486 } 485 }
487 } 486 }
488 487
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 return blink::WebSize(pipeline_metadata_.natural_size); 565 return blink::WebSize(pipeline_metadata_.natural_size);
567 } 566 }
568 567
569 bool WebMediaPlayerImpl::paused() const { 568 bool WebMediaPlayerImpl::paused() const {
570 DCHECK(main_task_runner_->BelongsToCurrentThread()); 569 DCHECK(main_task_runner_->BelongsToCurrentThread());
571 570
572 #if defined(OS_ANDROID) // WMPI_CAST 571 #if defined(OS_ANDROID) // WMPI_CAST
573 if (isRemote()) 572 if (isRemote())
574 return cast_impl_.paused(); 573 return cast_impl_.paused();
575 #endif 574 #endif
575
576 return pipeline_.GetPlaybackRate() == 0.0f; 576 return pipeline_.GetPlaybackRate() == 0.0f;
577 } 577 }
578 578
579 bool WebMediaPlayerImpl::seeking() const { 579 bool WebMediaPlayerImpl::seeking() const {
580 DCHECK(main_task_runner_->BelongsToCurrentThread()); 580 DCHECK(main_task_runner_->BelongsToCurrentThread());
581 581
582 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) 582 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
583 return false; 583 return false;
584 584
585 return seeking_; 585 return seeking_;
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 paused_time_ = pipeline_.GetMediaTime(); 889 paused_time_ = pipeline_.GetMediaTime();
890 #endif 890 #endif
891 } 891 }
892 if (time_updated) 892 if (time_updated)
893 should_notify_time_changed_ = true; 893 should_notify_time_changed_ = true;
894 } 894 }
895 895
896 void WebMediaPlayerImpl::OnPipelineSuspended() { 896 void WebMediaPlayerImpl::OnPipelineSuspended() {
897 #if defined(OS_ANDROID) 897 #if defined(OS_ANDROID)
898 if (isRemote()) { 898 if (isRemote()) {
899 if (delegate_)
900 delegate_->PlayerGone(delegate_id_);
901 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 899 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
902 if (frame) { 900 if (frame)
903 compositor_->PaintFrameUsingOldRenderingPath(frame); 901 compositor_->PaintFrameUsingOldRenderingPath(frame);
904 }
905 } 902 }
906 #endif 903 #endif
907 904
908 memory_usage_reporting_timer_.Stop();
909 ReportMemoryUsage();
910
911 // If we're not in an aggressive buffering state, tell the data source we have 905 // If we're not in an aggressive buffering state, tell the data source we have
912 // enough data so that it may release the connection. 906 // enough data so that it may release the connection.
913 if (buffering_strategy_ != 907 if (buffering_strategy_ !=
914 BufferedDataSource::BUFFERING_STRATEGY_AGGRESSIVE) { 908 BufferedDataSource::BUFFERING_STRATEGY_AGGRESSIVE) {
915 if (data_source_) 909 if (data_source_)
916 data_source_->OnBufferingHaveEnough(true); 910 data_source_->OnBufferingHaveEnough(true);
917 } 911 }
918 912
913 ReportMemoryUsage();
914
919 if (pending_suspend_resume_cycle_) { 915 if (pending_suspend_resume_cycle_) {
920 pending_suspend_resume_cycle_ = false; 916 pending_suspend_resume_cycle_ = false;
921 pipeline_controller_.Resume(); 917 UpdatePlayState();
922 return;
923 } 918 }
924 } 919 }
925 920
926 void WebMediaPlayerImpl::OnPipelineResumed() {
927 if (playback_rate_ > 0 && !paused_) {
928 NotifyPlaybackStarted();
929 } else if (!playback_rate_ || paused_ || ended_) {
930 // Resend our paused notification so the pipeline is considered for idle
931 // resource reclamation; duplicate pause notifications are ignored.
932 NotifyPlaybackPaused();
933 }
934 }
935
936 void WebMediaPlayerImpl::OnPipelineEnded() { 921 void WebMediaPlayerImpl::OnPipelineEnded() {
937 DVLOG(1) << __FUNCTION__; 922 DVLOG(1) << __FUNCTION__;
938 DCHECK(main_task_runner_->BelongsToCurrentThread()); 923 DCHECK(main_task_runner_->BelongsToCurrentThread());
939 924
940 // Ignore state changes until we've completed all outstanding operations. 925 // Ignore state changes until we've completed all outstanding operations.
941 if (!pipeline_controller_.IsStable()) 926 if (!pipeline_controller_.IsStable())
942 return; 927 return;
943 928
944 ended_ = true; 929 ended_ = true;
945 client_->timeChanged(); 930 client_->timeChanged();
931
932 // We don't actually want this to run until |client_| calls seek() or pause(),
933 // but that should have already happened in timeChanged() and so this is
934 // expected to be a no-op.
935 UpdatePlayState();
946 } 936 }
947 937
948 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { 938 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
949 DVLOG(1) << __FUNCTION__; 939 DVLOG(1) << __FUNCTION__;
950 DCHECK(main_task_runner_->BelongsToCurrentThread()); 940 DCHECK(main_task_runner_->BelongsToCurrentThread());
951 DCHECK_NE(error, PIPELINE_OK); 941 DCHECK_NE(error, PIPELINE_OK);
952 942
953 if (suppress_destruction_errors_) 943 if (suppress_destruction_errors_)
954 return; 944 return;
955 945
956 // Release the delegate for player errors; this drops the media session and
957 // avoids idle suspension from ticking.
958 if (delegate_)
959 delegate_->PlayerGone(delegate_id_);
960
961 #if defined(OS_ANDROID) 946 #if defined(OS_ANDROID)
962 // For 10% of pipeline decode failures log the playback URL. The URL is set 947 // For 10% of pipeline decode failures log the playback URL. The URL is set
963 // as the crash-key 'subresource_url' during DoLoad(). 948 // as the crash-key 'subresource_url' during DoLoad().
964 // 949 //
965 // TODO(dalecurtis): This is temporary to track down higher than average 950 // TODO(dalecurtis): This is temporary to track down higher than average
966 // decode failure rates for video-only content. See http://crbug.com/595076. 951 // decode failure rates for video-only content. See http://crbug.com/595076.
967 if (base::RandDouble() <= 0.1 && error == PIPELINE_ERROR_DECODE) 952 if (base::RandDouble() <= 0.1 && error == PIPELINE_ERROR_DECODE)
968 base::debug::DumpWithoutCrashing(); 953 base::debug::DumpWithoutCrashing();
969 #endif 954 #endif
970 955
971 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 956 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
972 957
973 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) { 958 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
974 // Any error that occurs before reaching ReadyStateHaveMetadata should 959 // Any error that occurs before reaching ReadyStateHaveMetadata should
975 // be considered a format error. 960 // be considered a format error.
976 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); 961 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
977 return; 962 } else {
963 SetNetworkState(PipelineErrorToNetworkState(error));
978 } 964 }
979 965
980 SetNetworkState(PipelineErrorToNetworkState(error)); 966 UpdatePlayState();
981 } 967 }
982 968
983 void WebMediaPlayerImpl::OnPipelineMetadata( 969 void WebMediaPlayerImpl::OnPipelineMetadata(
984 PipelineMetadata metadata) { 970 PipelineMetadata metadata) {
985 DVLOG(1) << __FUNCTION__; 971 DVLOG(1) << __FUNCTION__;
986 972
987 pipeline_metadata_ = metadata; 973 pipeline_metadata_ = metadata;
988 974
989 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation, 975 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
990 VIDEO_ROTATION_MAX + 1); 976 VIDEO_ROTATION_MAX + 1);
991 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 977 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
992 978
993 if (hasVideo()) { 979 if (hasVideo()) {
994 DCHECK(!video_weblayer_); 980 DCHECK(!video_weblayer_);
995 scoped_refptr<cc::VideoLayer> layer = 981 scoped_refptr<cc::VideoLayer> layer =
996 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation); 982 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
997 983
998 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 || 984 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
999 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) { 985 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
1000 gfx::Size size = pipeline_metadata_.natural_size; 986 gfx::Size size = pipeline_metadata_.natural_size;
1001 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width()); 987 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
1002 } 988 }
1003 989
1004 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer)); 990 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
1005 video_weblayer_->layer()->SetContentsOpaque(opaque_); 991 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1006 video_weblayer_->SetContentsOpaqueIsFixed(true); 992 video_weblayer_->SetContentsOpaqueIsFixed(true);
1007 client_->setWebLayer(video_weblayer_.get()); 993 client_->setWebLayer(video_weblayer_.get());
1008 } 994 }
1009 995
1010 // Tell the delegate we can now be safely suspended due to inactivity if a 996 UpdatePlayState();
1011 // subsequent play event does not occur.
1012 if (paused_)
1013 NotifyPlaybackPaused();
1014
1015 // If the frame is hidden, it may be time to suspend playback.
1016 if (delegate_ && delegate_->IsHidden())
1017 OnHidden();
1018 } 997 }
1019 998
1020 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 999 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
1021 BufferingState buffering_state) { 1000 BufferingState buffering_state) {
1022 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 1001 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
1023 1002
1024 // Ignore buffering state changes until we've completed all outstanding 1003 // Ignore buffering state changes until we've completed all outstanding
1025 // operations. 1004 // operations.
1026 if (!pipeline_controller_.IsStable()) 1005 if (!pipeline_controller_.IsStable())
1027 return; 1006 return;
1028 1007
1029 // TODO(scherkus): Handle other buffering states when Pipeline starts using 1008 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1030 // them and translate them ready state changes http://crbug.com/144683 1009 // them and translate them ready state changes http://crbug.com/144683
1031 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH); 1010 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
1032 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 1011 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1033 1012
1034 // Let the DataSource know we have enough data. It may use this information to 1013 // Let the DataSource know we have enough data. It may use this information to
1035 // release unused network connections. 1014 // release unused network connections.
1036 if (data_source_) 1015 if (data_source_)
1037 data_source_->OnBufferingHaveEnough(false); 1016 data_source_->OnBufferingHaveEnough(false);
1038 1017
1039 // Blink expects a timeChanged() in response to a seek(). 1018 // Blink expects a timeChanged() in response to a seek().
1040 if (should_notify_time_changed_) 1019 if (should_notify_time_changed_)
1041 client_->timeChanged(); 1020 client_->timeChanged();
1042 1021
1043 // Once we have enough, start reporting the total memory usage. We'll also 1022 // Once we have enough, start reporting the total memory usage. We'll also
1044 // report once playback starts. 1023 // report once playback starts.
1045 ReportMemoryUsage(); 1024 ReportMemoryUsage();
1025
1026 UpdatePlayState();
1046 } 1027 }
1047 1028
1048 void WebMediaPlayerImpl::OnDemuxerOpened() { 1029 void WebMediaPlayerImpl::OnDemuxerOpened() {
1049 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1030 DCHECK(main_task_runner_->BelongsToCurrentThread());
1050 client_->mediaSourceOpened( 1031 client_->mediaSourceOpened(
1051 new WebMediaSourceImpl(chunk_demuxer_, media_log_)); 1032 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
1052 } 1033 }
1053 1034
1054 void WebMediaPlayerImpl::OnAddTextTrack( 1035 void WebMediaPlayerImpl::OnAddTextTrack(
1055 const TextTrackConfig& config, 1036 const TextTrackConfig& config,
(...skipping 13 matching lines...) Expand all
1069 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id)); 1050 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
1070 1051
1071 scoped_ptr<media::TextTrack> text_track(new TextTrackImpl( 1052 scoped_ptr<media::TextTrack> text_track(new TextTrackImpl(
1072 main_task_runner_, client_, std::move(web_inband_text_track))); 1053 main_task_runner_, client_, std::move(web_inband_text_track)));
1073 1054
1074 done_cb.Run(std::move(text_track)); 1055 done_cb.Run(std::move(text_track));
1075 } 1056 }
1076 1057
1077 void WebMediaPlayerImpl::OnHidden() { 1058 void WebMediaPlayerImpl::OnHidden() {
1078 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1059 DCHECK(main_task_runner_->BelongsToCurrentThread());
1079 if (!IsSuspendUponHiddenEnabled()) 1060 UpdatePlayState();
1080 return;
1081
1082 #if defined(OS_ANDROID) // WMPI_CAST
1083 // If we're remote, the pipeline should already be suspended.
1084 if (isRemote())
1085 return;
1086 #endif
1087
1088 // Don't suspend before metadata is available, as we don't know if there is a
1089 // video track yet.
1090 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
1091 return;
1092
1093 // Don't suspend players which only have audio and have not completed
1094 // playback. The user can still control these players via the MediaSession UI.
1095 // If the player has never started playback, OnSuspendRequested() will handle
1096 // release of any idle resources.
1097 if (!hasVideo() && !paused_ && !ended_)
1098 return;
1099
1100 // Always reset the buffering strategy to normal when suspending for hidden to
1101 // prevent an idle network connection from lingering.
1102 setBufferingStrategy(WebMediaPlayer::BufferingStrategy::Normal);
1103 pipeline_controller_.Suspend();
1104 // If we're in the middle of a suspend/resume cycle we no longer want to
1105 // resume when the suspend completes.
1106 pending_suspend_resume_cycle_ = false;
1107 if (delegate_)
1108 delegate_->PlayerGone(delegate_id_);
1109 } 1061 }
1110 1062
1111 void WebMediaPlayerImpl::OnShown() { 1063 void WebMediaPlayerImpl::OnShown() {
1112 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1064 DCHECK(main_task_runner_->BelongsToCurrentThread());
1113 if (!IsSuspendUponHiddenEnabled()) 1065 must_suspend_ = false;
1114 return; 1066 UpdatePlayState();
1115
1116 #if defined(OS_ANDROID) // WMPI_CAST
1117 // If we're remote, the pipeline should stay suspended.
1118 if (isRemote())
1119 return;
1120 #endif
1121
1122 // If we do not yet have metadata, the only way we could have been suspended
1123 // is by a OnSuspendRequested() with |must_suspend| set. In that case we need
1124 // to resume, otherwise playback will be broken.
1125 //
1126 // Otherwise, resume if we should be playing.
1127 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata ||
1128 (!ended_ && !paused_)) {
1129 pipeline_controller_.Resume();
1130 }
1131 } 1067 }
1132 1068
1133 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { 1069 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
1134 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1070 DCHECK(main_task_runner_->BelongsToCurrentThread());
1135 1071
1136 #if defined(OS_ANDROID) // WMPI_CAST
1137 // If we're remote, the pipeline should already be suspended.
1138 if (isRemote())
1139 return;
1140 #endif
1141
1142 #if defined(OS_MACOSX) 1072 #if defined(OS_MACOSX)
1143 // TODO(sandersd): Idle suspend is disabled on OSX since hardware decoded 1073 // TODO(sandersd): Idle suspend is disabled on OSX since hardware decoded
1144 // frames are owned by the video decoder in the GPU process. A mechanism for 1074 // frames are owned by the video decoder in the GPU process. A mechanism for
1145 // detaching ownership from the decoder is needed. http://crbug.com/595716. 1075 // detaching ownership from the decoder is needed. http://crbug.com/595716.
1146 return; 1076 return;
1147 #else 1077 #endif
1148 // Suspend should never be requested unless required or we're already in an
1149 // idle state (paused or ended).
1150 DCHECK(must_suspend || paused_ || ended_);
1151 1078
1152 // Always suspend, but only notify the delegate if we must; this allows any 1079 if (must_suspend) {
1153 // exposed UI for player controls to continue to function even though the 1080 must_suspend_ = true;
1154 // player has now been suspended. 1081 } else {
1155 pipeline_controller_.Suspend(); 1082 is_idle_ = true;
1156 if (must_suspend && delegate_) 1083 }
1157 delegate_->PlayerGone(delegate_id_); 1084
1158 #endif 1085 UpdatePlayState();
1159 } 1086 }
1160 1087
1161 void WebMediaPlayerImpl::OnPlay() { 1088 void WebMediaPlayerImpl::OnPlay() {
1162 play(); 1089 play();
1163 client_->playbackStateChanged(); 1090 client_->playbackStateChanged();
1164 } 1091 }
1165 1092
1166 void WebMediaPlayerImpl::OnPause() { 1093 void WebMediaPlayerImpl::OnPause() {
1167 pause(); 1094 pause();
1168 client_->playbackStateChanged(); 1095 client_->playbackStateChanged();
1169 } 1096 }
1170 1097
1171 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) { 1098 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1172 volume_multiplier_ = multiplier; 1099 volume_multiplier_ = multiplier;
1173 setVolume(volume_); 1100 setVolume(volume_);
1174 } 1101 }
1175 1102
1176 void WebMediaPlayerImpl::ScheduleRestart() { 1103 void WebMediaPlayerImpl::ScheduleRestart() {
1177 if (!pipeline_controller_.IsSuspended()) { 1104 // TODO(watk): All restart logic should be moved into PipelineController.
1105 if (pipeline_.IsRunning() && !pipeline_controller_.IsPipelineSuspended()) {
1178 pending_suspend_resume_cycle_ = true; 1106 pending_suspend_resume_cycle_ = true;
1179 pipeline_controller_.Suspend(); 1107 UpdatePlayState();
1180 } 1108 }
1181 } 1109 }
1182 1110
1183 #if defined(OS_ANDROID) // WMPI_CAST 1111 #if defined(OS_ANDROID) // WMPI_CAST
1184 bool WebMediaPlayerImpl::isRemote() const { 1112 bool WebMediaPlayerImpl::isRemote() const {
1185 return cast_impl_.isRemote(); 1113 return cast_impl_.isRemote();
1186 } 1114 }
1187 1115
1188 void WebMediaPlayerImpl::SetMediaPlayerManager( 1116 void WebMediaPlayerImpl::SetMediaPlayerManager(
1189 RendererMediaPlayerManagerInterface* media_player_manager) { 1117 RendererMediaPlayerManagerInterface* media_player_manager) {
(...skipping 11 matching lines...) Expand all
1201 void WebMediaPlayerImpl::OnRemotePlaybackEnded() { 1129 void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1202 DVLOG(1) << __FUNCTION__; 1130 DVLOG(1) << __FUNCTION__;
1203 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1131 DCHECK(main_task_runner_->BelongsToCurrentThread());
1204 1132
1205 ended_ = true; 1133 ended_ = true;
1206 client_->timeChanged(); 1134 client_->timeChanged();
1207 } 1135 }
1208 1136
1209 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { 1137 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
1210 DoSeek(base::TimeDelta::FromSecondsD(t), false); 1138 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1211 if (delegate_ && !delegate_->IsHidden())
1212 pipeline_controller_.Resume();
1213 1139
1214 // We already told the delegate we're paused when remoting started. 1140 // We already told the delegate we're paused when remoting started.
1215 client_->playbackStateChanged(); 1141 client_->playbackStateChanged();
1216 client_->disconnectedFromRemoteDevice(); 1142 client_->disconnectedFromRemoteDevice();
1143
1144 UpdatePlayState();
1217 } 1145 }
1218 1146
1219 void WebMediaPlayerImpl::SuspendForRemote() { 1147 void WebMediaPlayerImpl::SuspendForRemote() {
1220 if (!pipeline_controller_.IsSuspended()) { 1148 if (pipeline_controller_.IsPipelineSuspended()) {
1221 pipeline_controller_.Suspend();
1222 } else {
1223 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1224 // when already suspended, we wouldn't need this case.
1225 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 1149 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1226 if (frame) { 1150 if (frame)
1227 compositor_->PaintFrameUsingOldRenderingPath(frame); 1151 compositor_->PaintFrameUsingOldRenderingPath(frame);
1228 }
1229 } 1152 }
1153
1154 UpdatePlayState();
1230 } 1155 }
1231 1156
1232 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { 1157 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1233 if (!video_weblayer_) 1158 if (!video_weblayer_)
1234 return pipeline_metadata_.natural_size; 1159 return pipeline_metadata_.natural_size;
1235 1160
1236 return video_weblayer_->bounds(); 1161 return video_weblayer_->bounds();
1237 } 1162 }
1238 1163
1239 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) { 1164 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1240 cast_impl_.SetDeviceScaleFactor(scale_factor); 1165 cast_impl_.SetDeviceScaleFactor(scale_factor);
1241 } 1166 }
1242 #endif // defined(OS_ANDROID) // WMPI_CAST 1167 #endif // defined(OS_ANDROID) // WMPI_CAST
1243 1168
1244 void WebMediaPlayerImpl::DataSourceInitialized(bool success) { 1169 void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
1245 DVLOG(1) << __FUNCTION__; 1170 DVLOG(1) << __FUNCTION__;
1246 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1171 DCHECK(main_task_runner_->BelongsToCurrentThread());
1247 1172
1248 if (!success) { 1173 if (!success) {
1249 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); 1174 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
1175
1176 // Not really necessary, since the pipeline was never started, but it at
1177 // least this makes sure that the error handling code is in sync.
1178 UpdatePlayState();
1179
1250 return; 1180 return;
1251 } 1181 }
1252 1182
1253 StartPipeline(); 1183 StartPipeline();
1254 } 1184 }
1255 1185
1256 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { 1186 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
1257 DVLOG(1) << __FUNCTION__; 1187 DVLOG(1) << __FUNCTION__;
1258 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) 1188 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1259 SetNetworkState(WebMediaPlayer::NetworkStateIdle); 1189 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) { 1297 void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
1368 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; 1298 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
1369 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1299 DCHECK(main_task_runner_->BelongsToCurrentThread());
1370 1300
1371 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ && 1301 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1372 data_source_->assume_fully_buffered() && 1302 data_source_->assume_fully_buffered() &&
1373 network_state_ == WebMediaPlayer::NetworkStateLoading) 1303 network_state_ == WebMediaPlayer::NetworkStateLoading)
1374 SetNetworkState(WebMediaPlayer::NetworkStateLoaded); 1304 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1375 1305
1376 ready_state_ = state; 1306 ready_state_ = state;
1307 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
1308
1377 // Always notify to ensure client has the latest value. 1309 // Always notify to ensure client has the latest value.
1378 client_->readyStateChanged(); 1310 client_->readyStateChanged();
1379 } 1311 }
1380 1312
1381 blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() { 1313 blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() {
1382 return audio_source_provider_.get(); 1314 return audio_source_provider_.get();
1383 } 1315 }
1384 1316
1385 double WebMediaPlayerImpl::GetPipelineDuration() const { 1317 double WebMediaPlayerImpl::GetPipelineDuration() const {
1386 base::TimeDelta duration = pipeline_.GetMediaDuration(); 1318 base::TimeDelta duration = pipeline_.GetMediaDuration();
1387 1319
1388 // Return positive infinity if the resource is unbounded. 1320 // Return positive infinity if the resource is unbounded.
1389 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom- media-duration 1321 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom- media-duration
1390 if (duration == kInfiniteDuration()) 1322 if (duration == kInfiniteDuration())
1391 return std::numeric_limits<double>::infinity(); 1323 return std::numeric_limits<double>::infinity();
1392 1324
1393 return duration.InSecondsF(); 1325 return duration.InSecondsF();
1394 } 1326 }
1395 1327
1396 void WebMediaPlayerImpl::OnDurationChanged() { 1328 void WebMediaPlayerImpl::OnDurationChanged() {
1329 // TODO(sandersd): We should call delegate_->DidPlay() with the new duration,
1330 // especially if it changed from <5s to >5s.
1397 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) 1331 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1398 return; 1332 return;
1399 1333
1400 client_->durationChanged(); 1334 client_->durationChanged();
1401 } 1335 }
1402 1336
1403 void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) { 1337 void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
1404 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1338 DCHECK(main_task_runner_->BelongsToCurrentThread());
1405 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 1339 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1406 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged"); 1340 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 base::WaitableEvent event(false, false); 1383 base::WaitableEvent event(false, false);
1450 compositor_task_runner_->PostTask(FROM_HERE, 1384 compositor_task_runner_->PostTask(FROM_HERE,
1451 base::Bind(&GetCurrentFrameAndSignal, 1385 base::Bind(&GetCurrentFrameAndSignal,
1452 base::Unretained(compositor_), 1386 base::Unretained(compositor_),
1453 &video_frame, 1387 &video_frame,
1454 &event)); 1388 &event));
1455 event.Wait(); 1389 event.Wait();
1456 return video_frame; 1390 return video_frame;
1457 } 1391 }
1458 1392
1459 void WebMediaPlayerImpl::NotifyPlaybackStarted() { 1393 void WebMediaPlayerImpl::UpdatePlayState() {
1460 #if defined(OS_ANDROID) // WMPI_CAST 1394 #if defined(OS_ANDROID) // WMPI_CAST
1461 // We do not tell our delegates about remote playback, because that would 1395 bool is_remote = isRemote();
1462 // keep the device awake, which is not what we want. 1396 #else
1463 if (isRemote()) 1397 bool is_remote = false;
1464 return;
1465 #endif 1398 #endif
1399 bool is_backgrounded =
1400 IsBackgroundedSuspendEnabled() && delegate_ && delegate_->IsHidden();
1401 PlayState state =
1402 UpdatePlayState_ComputePlayState(is_remote, is_backgrounded);
1403 SetDelegateState(state.delegate_state);
1404 SetMemoryReportingState(state.is_memory_reporting_enabled);
1405 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1406 }
1466 1407
1467 // NotifyPlaybackStarted() may be called by interactions while suspended, 1408 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) {
1468 // (play/pause in particular). Those actions won't have any effect until the 1409 if (!delegate_ || delegate_state_ == new_state)
1469 // pipeline is resumed.
1470 // TODO(dalecurtis): Should these be dropped at the call sites instead?
1471 // Alternatively, rename this method to include Maybe or Changed, and handle
1472 // multiple calls safely.
1473 if (pipeline_controller_.IsSuspended())
1474 return; 1410 return;
1475 1411
1476 if (delegate_) { 1412 delegate_state_ = new_state;
1477 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false, 1413
1478 pipeline_.GetMediaDuration()); 1414 switch (delegate_state_) {
1415 case DelegateState::GONE:
1416 delegate_->PlayerGone(delegate_id_);
1417 break;
1418 case DelegateState::PLAYING:
1419 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1420 pipeline_.GetMediaDuration());
1421 break;
1422 case DelegateState::PAUSED:
1423 delegate_->DidPause(delegate_id_, false);
1424 break;
1425 case DelegateState::ENDED:
1426 delegate_->DidPause(delegate_id_, true);
1427 break;
1479 } 1428 }
1480 if (!memory_usage_reporting_timer_.IsRunning()) { 1429 }
1430
1431 void WebMediaPlayerImpl::SetMemoryReportingState(
1432 bool is_memory_reporting_enabled) {
1433 if (memory_usage_reporting_timer_.IsRunning() ==
1434 is_memory_reporting_enabled) {
1435 return;
1436 }
1437
1438 if (is_memory_reporting_enabled) {
1481 memory_usage_reporting_timer_.Start(FROM_HERE, 1439 memory_usage_reporting_timer_.Start(FROM_HERE,
1482 base::TimeDelta::FromSeconds(2), this, 1440 base::TimeDelta::FromSeconds(2), this,
1483 &WebMediaPlayerImpl::ReportMemoryUsage); 1441 &WebMediaPlayerImpl::ReportMemoryUsage);
1442 } else {
1443 memory_usage_reporting_timer_.Stop();
1444 ReportMemoryUsage();
1484 } 1445 }
1485 } 1446 }
1486 1447
1487 void WebMediaPlayerImpl::NotifyPlaybackPaused() { 1448 void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
1488 #if defined(OS_ANDROID) // WMPI_CAST 1449 // Do not change the state after an error has occurred.
1489 if (isRemote()) 1450 // TODO(sandersd): Update PipelineController to remove the need for this.
1490 return; 1451 if (IsNetworkStateError(network_state_))
1491 #endif
1492
1493 // Same as above, NotifyPlaybackPaused() may be called by interactions while
1494 // suspended, but those actions won't have any effect until the pipeline is
1495 // resumed.
1496 if (pipeline_controller_.IsSuspended())
1497 return; 1452 return;
1498 1453
1499 if (delegate_) 1454 if (is_suspended) {
1500 delegate_->DidPause(delegate_id_, ended_); 1455 pipeline_controller_.Suspend();
1501 memory_usage_reporting_timer_.Stop(); 1456 } else {
1502 ReportMemoryUsage(); 1457 pipeline_controller_.Resume();
1458 }
1459 }
1460
1461 WebMediaPlayerImpl::PlayState
1462 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
1463 bool is_backgrounded) {
1464 PlayState result;
1465
1466 // This includes both data source (before pipeline startup) and pipeline
1467 // errors.
1468 bool has_error = IsNetworkStateError(network_state_);
1469
1470 // After HaveMetadata, we know which tracks are present and the duration.
1471 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata;
1472
1473 // After HaveFutureData, Blink will call play() if the state is not paused.
1474 bool have_future_data =
1475 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData;
1476
1477 // Background suspend is not enabled for audio-only players.
1478 bool background_suspended = is_backgrounded && have_metadata && hasVideo();
1479
1480 // Idle suspend is enabled once there is future data. We don't want to idle
1481 // suspend before that because play() may never be triggered to leave the idle
1482 // state. There could be other theoretical problems if the page is waiting for
1483 // other events before actually calling play(), but at least we don't break
1484 // Blink.
1485 //
1486 // TODO(sandersd): Make the delegate suspend idle players immediately when
1487 // hidden.
1488 // TODO(sandersd): If Blink told us the paused state sooner, we could
1489 // idle suspend sooner.
1490 bool idle_suspended = is_idle_ && have_future_data;
1491
1492 // Combined suspend state.
1493 result.is_suspended =
1494 is_remote || must_suspend_ || idle_suspended || background_suspended;
1495
1496 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1497 // being paused implies displaying a play button, which is incorrect in this
1498 // case. For memory usage reporting, we just use the same definition (but we
1499 // don't have to).
1500 //
1501 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1502 // call pause() or seek(), so |ended_| should not affect the computation.
1503 // Despite that, |ended_| does result in a separate paused state, to simplfy
1504 // the contract for SetDelegateState().
1505 //
1506 // |has_session| is used to decide when to create a media session. Idle
1507 // suspension does not destroy the media session, because we expect that the
1508 // notification controls (and audio focus) remain. We also require:
1509 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1510 // - |have_future_data|, since we need to know whether we are paused to
1511 // correctly configure the session.
1512 //
1513 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1514 // the media session sooner.
1515 bool can_play = !has_error && !is_remote && have_future_data;
1516 bool has_session = can_play && !must_suspend_ && !background_suspended;
1517
1518 if (!has_session) {
1519 result.delegate_state = DelegateState::GONE;
1520 } else if (paused_) {
1521 // TODO(sandersd): There should be a paused+seeking state, during which
1522 // the idle timer is disabled. Without that, idle suspending before or
1523 // during seeking will have bad results.
1524 result.delegate_state =
1525 ended_ ? DelegateState::ENDED : DelegateState::PAUSED;
1526 } else {
1527 result.delegate_state = DelegateState::PLAYING;
1528 }
1529
1530 // It's not critical if some cases where memory usage can change are missed,
1531 // since media memory changes are usually gradual.
1532 result.is_memory_reporting_enabled =
1533 can_play && !result.is_suspended && !paused_;
1534
1535 return result;
1503 } 1536 }
1504 1537
1505 void WebMediaPlayerImpl::ReportMemoryUsage() { 1538 void WebMediaPlayerImpl::ReportMemoryUsage() {
1506 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1539 DCHECK(main_task_runner_->BelongsToCurrentThread());
1507 1540
1508 // About base::Unretained() usage below: We destroy |demuxer_| on the main 1541 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1509 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 1542 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1510 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task 1543 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1511 // posted here must finish earlier. 1544 // posted here must finish earlier.
1512 1545
(...skipping 22 matching lines...) Expand all
1535 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage 1568 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1536 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1569 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1537 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1570 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1538 << ", Demuxer: " << demuxer_memory_usage; 1571 << ", Demuxer: " << demuxer_memory_usage;
1539 1572
1540 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1573 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1541 last_reported_memory_usage_ = current_memory_usage; 1574 last_reported_memory_usage_ = current_memory_usage;
1542 adjust_allocated_memory_cb_.Run(delta); 1575 adjust_allocated_memory_cb_.Run(delta);
1543 } 1576 }
1544 1577
1545 bool WebMediaPlayerImpl::IsAutomaticResumeAllowed() {
1546 #if defined(OS_ANDROID)
1547 return !hasVideo() || (delegate_ && !delegate_->IsHidden());
1548 #else
1549 // On non-Android platforms Resume() is always allowed.
1550 return true;
1551 #endif
1552 }
1553
1554 } // namespace media 1578 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/blink/webmediaplayer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698