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

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

Powered by Google App Engine
This is Rietveld 408576698