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

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: Further reduce reliance on |ended_|. 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 ||
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 play_state_(PlayState::GONE),
157 idle_suspend_(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),
DaleCurtis 2016/03/26 01:12:55 Is this sufficient? What happens when a seek takes
sandersd (OOO until July 31) 2016/03/28 21:31:58 Currently the logic is that a suspend while seekin
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 idle_suspend_ = 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 idle_suspend_ = 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 UpdatePlayState();
958 } 944 }
959 945
960 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { 946 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
961 DVLOG(1) << __FUNCTION__; 947 DVLOG(1) << __FUNCTION__;
962 DCHECK(main_task_runner_->BelongsToCurrentThread()); 948 DCHECK(main_task_runner_->BelongsToCurrentThread());
963 DCHECK_NE(error, PIPELINE_OK); 949 DCHECK_NE(error, PIPELINE_OK);
964 950
965 if (suppress_destruction_errors_) 951 if (suppress_destruction_errors_)
966 return; 952 return;
967 953
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) 954 #if defined(OS_ANDROID)
974 // For 10% of pipeline decode failures log the playback URL. The URL is set 955 // For 10% of pipeline decode failures log the playback URL. The URL is set
975 // as the crash-key 'subresource_url' during DoLoad(). 956 // as the crash-key 'subresource_url' during DoLoad().
976 // 957 //
977 // TODO(dalecurtis): This is temporary to track down higher than average 958 // TODO(dalecurtis): This is temporary to track down higher than average
978 // decode failure rates for video-only content. See http://crbug.com/595076. 959 // decode failure rates for video-only content. See http://crbug.com/595076.
979 if (base::RandDouble() <= 0.1 && error == PIPELINE_ERROR_DECODE) 960 if (base::RandDouble() <= 0.1 && error == PIPELINE_ERROR_DECODE)
980 base::debug::DumpWithoutCrashing(); 961 base::debug::DumpWithoutCrashing();
981 #endif 962 #endif
982 963
983 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 964 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
984 965
985 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) { 966 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
986 // Any error that occurs before reaching ReadyStateHaveMetadata should 967 // Any error that occurs before reaching ReadyStateHaveMetadata should
987 // be considered a format error. 968 // be considered a format error.
988 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); 969 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
989 return; 970 } else {
971 SetNetworkState(PipelineErrorToNetworkState(error));
990 } 972 }
991 973
992 SetNetworkState(PipelineErrorToNetworkState(error)); 974 UpdatePlayState();
993 } 975 }
994 976
995 void WebMediaPlayerImpl::OnPipelineMetadata( 977 void WebMediaPlayerImpl::OnPipelineMetadata(
996 PipelineMetadata metadata) { 978 PipelineMetadata metadata) {
997 DVLOG(1) << __FUNCTION__; 979 DVLOG(1) << __FUNCTION__;
998 980
999 pipeline_metadata_ = metadata; 981 pipeline_metadata_ = metadata;
1000 982
1001 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation, 983 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
1002 VIDEO_ROTATION_MAX + 1); 984 VIDEO_ROTATION_MAX + 1);
1003 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 985 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
1004 986
1005 if (hasVideo()) { 987 if (hasVideo()) {
1006 DCHECK(!video_weblayer_); 988 DCHECK(!video_weblayer_);
1007 scoped_refptr<cc::VideoLayer> layer = 989 scoped_refptr<cc::VideoLayer> layer =
1008 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation); 990 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
1009 991
1010 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 || 992 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
1011 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) { 993 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
1012 gfx::Size size = pipeline_metadata_.natural_size; 994 gfx::Size size = pipeline_metadata_.natural_size;
1013 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width()); 995 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
1014 } 996 }
1015 997
1016 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer)); 998 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
1017 video_weblayer_->layer()->SetContentsOpaque(opaque_); 999 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1018 video_weblayer_->SetContentsOpaqueIsFixed(true); 1000 video_weblayer_->SetContentsOpaqueIsFixed(true);
1019 client_->setWebLayer(video_weblayer_.get()); 1001 client_->setWebLayer(video_weblayer_.get());
1020 } 1002 }
1021 1003
1022 // Tell the delegate we can now be safely suspended due to inactivity if a 1004 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 } 1005 }
1031 1006
1032 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 1007 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
1033 BufferingState buffering_state) { 1008 BufferingState buffering_state) {
1034 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 1009 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
1035 1010
1036 // Ignore buffering state changes until we've completed all outstanding 1011 // Ignore buffering state changes until we've completed all outstanding
1037 // operations. 1012 // operations.
1038 if (!pipeline_controller_.IsStable()) 1013 if (!pipeline_controller_.IsStable())
1039 return; 1014 return;
1040 1015
1041 // TODO(scherkus): Handle other buffering states when Pipeline starts using 1016 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1042 // them and translate them ready state changes http://crbug.com/144683 1017 // them and translate them ready state changes http://crbug.com/144683
1043 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH); 1018 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
1044 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 1019 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1045 1020
1046 // Let the DataSource know we have enough data. It may use this information to 1021 // Let the DataSource know we have enough data. It may use this information to
1047 // release unused network connections. 1022 // release unused network connections.
1048 if (data_source_) 1023 if (data_source_)
1049 data_source_->OnBufferingHaveEnough(false); 1024 data_source_->OnBufferingHaveEnough(false);
1050 1025
1051 // Blink expects a timeChanged() in response to a seek(). 1026 // Blink expects a timeChanged() in response to a seek().
1052 if (should_notify_time_changed_) 1027 if (should_notify_time_changed_)
1053 client_->timeChanged(); 1028 client_->timeChanged();
1054 1029
1055 // Once we have enough, start reporting the total memory usage. We'll also 1030 // Once we have enough, start reporting the total memory usage. We'll also
1056 // report once playback starts. 1031 // report once playback starts.
1057 ReportMemoryUsage(); 1032 ReportMemoryUsage();
1033
1034 UpdatePlayState();
1058 } 1035 }
1059 1036
1060 void WebMediaPlayerImpl::OnDemuxerOpened() { 1037 void WebMediaPlayerImpl::OnDemuxerOpened() {
1061 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1038 DCHECK(main_task_runner_->BelongsToCurrentThread());
1062 client_->mediaSourceOpened( 1039 client_->mediaSourceOpened(
1063 new WebMediaSourceImpl(chunk_demuxer_, media_log_)); 1040 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
1064 } 1041 }
1065 1042
1066 void WebMediaPlayerImpl::OnAddTextTrack( 1043 void WebMediaPlayerImpl::OnAddTextTrack(
1067 const TextTrackConfig& config, 1044 const TextTrackConfig& config,
(...skipping 13 matching lines...) Expand all
1081 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id)); 1058 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
1082 1059
1083 scoped_ptr<TextTrack> text_track(new TextTrackImpl( 1060 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
1084 main_task_runner_, client_, std::move(web_inband_text_track))); 1061 main_task_runner_, client_, std::move(web_inband_text_track)));
1085 1062
1086 done_cb.Run(std::move(text_track)); 1063 done_cb.Run(std::move(text_track));
1087 } 1064 }
1088 1065
1089 void WebMediaPlayerImpl::OnHidden() { 1066 void WebMediaPlayerImpl::OnHidden() {
1090 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1067 DCHECK(main_task_runner_->BelongsToCurrentThread());
1091 if (!IsSuspendUponHiddenEnabled()) 1068 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;
DaleCurtis 2016/03/26 01:12:55 You dropped this bit. I think it's still necessary
sandersd (OOO until July 31) 2016/03/28 21:31:58 We need to eventually suspend, and as soon as we d
1119 if (delegate_)
1120 delegate_->PlayerGone(delegate_id_);
1121 } 1069 }
1122 1070
1123 void WebMediaPlayerImpl::OnShown() { 1071 void WebMediaPlayerImpl::OnShown() {
1124 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1072 DCHECK(main_task_runner_->BelongsToCurrentThread());
1125 if (!IsSuspendUponHiddenEnabled()) 1073 must_suspend_ = false;
1126 return; 1074 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 } 1075 }
1144 1076
1145 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { 1077 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
1146 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1078 DCHECK(main_task_runner_->BelongsToCurrentThread());
1147 1079 if (must_suspend) {
1148 #if defined(OS_ANDROID) // WMPI_CAST 1080 must_suspend_ = true;
1149 // If we're remote, the pipeline should already be suspended. 1081 } else {
1150 if (isRemote()) 1082 idle_suspend_ = true;
1151 return; 1083 }
1152 #endif 1084 UpdatePlayState();
1153
1154 #if defined(OS_MACOSX)
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 } 1085 }
1172 1086
1173 void WebMediaPlayerImpl::OnPlay() { 1087 void WebMediaPlayerImpl::OnPlay() {
1174 play(); 1088 play();
1175 client_->playbackStateChanged(); 1089 client_->playbackStateChanged();
1176 } 1090 }
1177 1091
1178 void WebMediaPlayerImpl::OnPause() { 1092 void WebMediaPlayerImpl::OnPause() {
1179 pause(); 1093 pause();
1180 client_->playbackStateChanged(); 1094 client_->playbackStateChanged();
1181 } 1095 }
1182 1096
1183 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) { 1097 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1184 volume_multiplier_ = multiplier; 1098 volume_multiplier_ = multiplier;
1185 setVolume(volume_); 1099 setVolume(volume_);
1186 } 1100 }
1187 1101
1188 void WebMediaPlayerImpl::ScheduleRestart() { 1102 void WebMediaPlayerImpl::ScheduleRestart() {
1189 if (!pipeline_controller_.IsSuspended()) { 1103 // TODO(watk): All restart logic should be moved into PipelineController.
1104 if (pipeline_.IsRunning() && !pipeline_controller_.IsSuspended()) {
1190 pending_suspend_resume_cycle_ = true; 1105 pending_suspend_resume_cycle_ = true;
1191 pipeline_controller_.Suspend(); 1106 UpdatePlayState();
1192 } 1107 }
1193 } 1108 }
1194 1109
1195 #if defined(OS_ANDROID) // WMPI_CAST 1110 #if defined(OS_ANDROID) // WMPI_CAST
1196 bool WebMediaPlayerImpl::isRemote() const { 1111 bool WebMediaPlayerImpl::isRemote() const {
1197 return cast_impl_.isRemote(); 1112 return cast_impl_.isRemote();
1198 } 1113 }
1199 1114
1200 void WebMediaPlayerImpl::SetMediaPlayerManager( 1115 void WebMediaPlayerImpl::SetMediaPlayerManager(
1201 RendererMediaPlayerManagerInterface* media_player_manager) { 1116 RendererMediaPlayerManagerInterface* media_player_manager) {
(...skipping 11 matching lines...) Expand all
1213 void WebMediaPlayerImpl::OnRemotePlaybackEnded() { 1128 void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1214 DVLOG(1) << __FUNCTION__; 1129 DVLOG(1) << __FUNCTION__;
1215 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1130 DCHECK(main_task_runner_->BelongsToCurrentThread());
1216 1131
1217 ended_ = true; 1132 ended_ = true;
1218 client_->timeChanged(); 1133 client_->timeChanged();
1219 } 1134 }
1220 1135
1221 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { 1136 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
1222 DoSeek(base::TimeDelta::FromSecondsD(t), false); 1137 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1223 if (delegate_ && !delegate_->IsHidden())
1224 pipeline_controller_.Resume();
1225 1138
1226 // We already told the delegate we're paused when remoting started. 1139 // We already told the delegate we're paused when remoting started.
1227 client_->playbackStateChanged(); 1140 client_->playbackStateChanged();
1228 client_->disconnectedFromRemoteDevice(); 1141 client_->disconnectedFromRemoteDevice();
1142
1143 UpdatePlayState();
1229 } 1144 }
1230 1145
1231 void WebMediaPlayerImpl::SuspendForRemote() { 1146 void WebMediaPlayerImpl::SuspendForRemote() {
1232 if (!pipeline_controller_.IsSuspended()) { 1147 if (pipeline_controller_.IsSuspended()) {
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(); 1148 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1238 if (frame) { 1149 if (frame)
1239 compositor_->PaintFrameUsingOldRenderingPath(frame); 1150 compositor_->PaintFrameUsingOldRenderingPath(frame);
1240 }
1241 } 1151 }
1152
1153 UpdatePlayState();
1242 } 1154 }
1243 1155
1244 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { 1156 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1245 if (!video_weblayer_) 1157 if (!video_weblayer_)
1246 return pipeline_metadata_.natural_size; 1158 return pipeline_metadata_.natural_size;
1247 1159
1248 return video_weblayer_->bounds(); 1160 return video_weblayer_->bounds();
1249 } 1161 }
1250 1162
1251 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) { 1163 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1252 cast_impl_.SetDeviceScaleFactor(scale_factor); 1164 cast_impl_.SetDeviceScaleFactor(scale_factor);
1253 } 1165 }
1254 #endif // defined(OS_ANDROID) // WMPI_CAST 1166 #endif // defined(OS_ANDROID) // WMPI_CAST
1255 1167
1256 void WebMediaPlayerImpl::DataSourceInitialized(bool success) { 1168 void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
1257 DVLOG(1) << __FUNCTION__; 1169 DVLOG(1) << __FUNCTION__;
1258 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1170 DCHECK(main_task_runner_->BelongsToCurrentThread());
1259 1171
1260 if (!success) { 1172 if (!success) {
1261 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); 1173 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
1174
1175 // Not really necessary, since the pipeline was never started, but it at
1176 // least this makes sure that the error handling code is in sync.
1177 UpdatePlayState();
1178
1262 return; 1179 return;
1263 } 1180 }
1264 1181
1265 StartPipeline(); 1182 StartPipeline();
1266 } 1183 }
1267 1184
1268 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { 1185 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
1269 DVLOG(1) << __FUNCTION__; 1186 DVLOG(1) << __FUNCTION__;
1270 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) 1187 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1271 SetNetworkState(WebMediaPlayer::NetworkStateIdle); 1188 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) { 1296 void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
1380 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; 1297 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
1381 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1298 DCHECK(main_task_runner_->BelongsToCurrentThread());
1382 1299
1383 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ && 1300 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1384 data_source_->assume_fully_buffered() && 1301 data_source_->assume_fully_buffered() &&
1385 network_state_ == WebMediaPlayer::NetworkStateLoading) 1302 network_state_ == WebMediaPlayer::NetworkStateLoading)
1386 SetNetworkState(WebMediaPlayer::NetworkStateLoaded); 1303 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1387 1304
1388 ready_state_ = state; 1305 ready_state_ = state;
1306 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
1307
1389 // Always notify to ensure client has the latest value. 1308 // Always notify to ensure client has the latest value.
1390 client_->readyStateChanged(); 1309 client_->readyStateChanged();
1391 } 1310 }
1392 1311
1393 blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() { 1312 blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() {
1394 return audio_source_provider_.get(); 1313 return audio_source_provider_.get();
1395 } 1314 }
1396 1315
1397 double WebMediaPlayerImpl::GetPipelineDuration() const { 1316 double WebMediaPlayerImpl::GetPipelineDuration() const {
1398 base::TimeDelta duration = pipeline_.GetMediaDuration(); 1317 base::TimeDelta duration = pipeline_.GetMediaDuration();
1399 1318
1400 // Return positive infinity if the resource is unbounded. 1319 // Return positive infinity if the resource is unbounded.
1401 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom- media-duration 1320 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom- media-duration
1402 if (duration == kInfiniteDuration()) 1321 if (duration == kInfiniteDuration())
1403 return std::numeric_limits<double>::infinity(); 1322 return std::numeric_limits<double>::infinity();
1404 1323
1405 return duration.InSecondsF(); 1324 return duration.InSecondsF();
1406 } 1325 }
1407 1326
1408 void WebMediaPlayerImpl::OnDurationChanged() { 1327 void WebMediaPlayerImpl::OnDurationChanged() {
1328 // TODO(sandersd): Do we need to re-init the media session?
DaleCurtis 2016/03/26 01:12:55 Probably a good idea. It will really only matter i
sandersd (OOO until July 31) 2016/03/28 21:31:58 Acknowledged.
1409 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) 1329 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1410 return; 1330 return;
1411 1331
1412 client_->durationChanged(); 1332 client_->durationChanged();
1413 } 1333 }
1414 1334
1415 void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) { 1335 void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
1416 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1336 DCHECK(main_task_runner_->BelongsToCurrentThread());
1417 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 1337 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1418 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged"); 1338 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 base::WaitableEvent event(false, false); 1381 base::WaitableEvent event(false, false);
1462 compositor_task_runner_->PostTask(FROM_HERE, 1382 compositor_task_runner_->PostTask(FROM_HERE,
1463 base::Bind(&GetCurrentFrameAndSignal, 1383 base::Bind(&GetCurrentFrameAndSignal,
1464 base::Unretained(compositor_), 1384 base::Unretained(compositor_),
1465 &video_frame, 1385 &video_frame,
1466 &event)); 1386 &event));
1467 event.Wait(); 1387 event.Wait();
1468 return video_frame; 1388 return video_frame;
1469 } 1389 }
1470 1390
1471 void WebMediaPlayerImpl::NotifyPlaybackStarted() { 1391 void WebMediaPlayerImpl::UpdatePlayState() {
1392 // This includes both data source (pre-pipeline startup) and pipeline errors.
1393 bool has_error = IsNetworkStateError(network_state_);
1394
1472 #if defined(OS_ANDROID) // WMPI_CAST 1395 #if defined(OS_ANDROID) // WMPI_CAST
1473 // We do not tell our delegates about remote playback, because that would 1396 bool casting = isRemote();
DaleCurtis 2016/03/26 01:12:55 Maybe just is_remote ?
sandersd (OOO until July 31) 2016/03/28 21:31:58 Done.
1474 // keep the device awake, which is not what we want. 1397 #else
1475 if (isRemote()) 1398 bool casting = false;
1476 return;
1477 #endif 1399 #endif
1478 1400
1479 // NotifyPlaybackStarted() may be called by interactions while suspended, 1401 // After HaveMetadata, we know which tracks are present and the duration.
1480 // (play/pause in particular). Those actions won't have any effect until the 1402 bool have_metadata = (ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata);
DaleCurtis 2016/03/26 01:12:55 nit: no unnecessary parens. ditto for below.
sandersd (OOO until July 31) 2016/03/28 21:31:58 Done.
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;
1487 1403
1404 // After HaveFutureData, Blink will call play() if the state is not paused.
1405 bool have_future_data =
1406 (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData);
1407
1408 // Background suspend is not enabled for audio-only players.
1409 bool backgrounded =
1410 IsSuspendUponHiddenEnabled() && delegate_ && delegate_->IsHidden();
1411 bool background_suspended = backgrounded && have_metadata && hasVideo();
1412
1413 // Idle suspend is enabled once there is future data. We don't want to idle
1414 // suspend before that because play() may never be triggered to leave the idle
1415 // state.
1416 //
1417 // TODO(sandersd): Make the delegate suspend idle players immediately when
1418 // hidden.
1419 // TODO(sandersd): If Blink told us the paused state sooner, we could
1420 // idle suspend sooner.
1421 bool idle_suspended = idle_suspend_ && have_future_data;
1422
1423 // Combined suspend state.
1424 //
1425 // |pending_suspend_resume_cycle_| is skipped here, mostly to keep it as
1426 // separate as possible.
1427 bool suspended =
1428 casting || must_suspend_ || idle_suspended || background_suspended;
1429
1430 // We do not treat |playback_rate_| == 0 as paused. We could, but this
1431 // interpretation keeps everything in sync with the media session. (It doesn't
1432 // make sense to pause the media session because there is no way for the play
1433 // button to resume playback.) Similarly, we don't consider |ended_|, since
1434 // Blink will immediately either pause or seek.
1435 //
1436 // |is_playing| decides whether the memory usage reporting timer is enabled.
1437 //
1438 // |has_session| is used to decide when to create a media session. It is
1439 // similer, but excludes idle suspension, because in the audio-only case we
watk 2016/03/29 00:47:53 similar
sandersd (OOO until July 31) 2016/03/30 23:46:00 Acknowledged.
1440 // expect that the notification controls to remain. We also require:
watk 2016/03/29 00:47:53 s/that the/the
sandersd (OOO until July 31) 2016/03/30 23:46:00 Done.
1441 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1442 // - |have_future_data|, since we need to know whether we are paused to
1443 // correctly configure the session.
1444 // These conditions are common with |is_playing|, but would need to be made
1445 // explicit if the definition of |is_playing| changes.
1446 //
1447 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1448 // the media session sooner.
1449 bool can_play = !has_error && !casting && have_future_data;
1450 bool is_playing = can_play && !suspended && !paused_;
1451 bool has_session = can_play && !must_suspend_ && !background_suspended;
1452
1453 // If there is a delegate, let it know what to do with the media session (and
1454 // implicitly the idle timer as well).
1488 if (delegate_) { 1455 if (delegate_) {
1489 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false, 1456 if (!has_session) {
1490 pipeline_.GetMediaDuration()); 1457 UpdatePlayState_SetPlayState(PlayState::GONE);
1458 } else if (paused_) {
1459 UpdatePlayState_SetPlayState(ended_ ? PlayState::ENDED
1460 : PlayState::PAUSED);
1461 } else {
1462 UpdatePlayState_SetPlayState(PlayState::PLAYING);
1463 }
1491 } 1464 }
1492 if (!memory_usage_reporting_timer_.IsRunning()) { 1465
1466 // Make sure that suspend state is in sync, unless there was an error (in that
1467 // case we don't want to change the state).
1468 //
1469 // Suspend() and Resume() are idempotent, so we don't need to worry about
1470 // calling them multiple times.
1471 if (!has_error) {
1472 if (suspended || pending_suspend_resume_cycle_) {
1473 pipeline_controller_.Suspend();
1474 } else {
1475 pipeline_controller_.Resume();
1476 }
1477 }
1478
1479 // Make sure that the memory usage reporting timer is running whenever we are
1480 // playing. It's not critical if some cases where memory usage can change are
1481 // missed, since media memory changes are usually gradual.
1482 if (is_playing && !memory_usage_reporting_timer_.IsRunning()) {
1493 memory_usage_reporting_timer_.Start(FROM_HERE, 1483 memory_usage_reporting_timer_.Start(FROM_HERE,
1494 base::TimeDelta::FromSeconds(2), this, 1484 base::TimeDelta::FromSeconds(2), this,
1495 &WebMediaPlayerImpl::ReportMemoryUsage); 1485 &WebMediaPlayerImpl::ReportMemoryUsage);
1486 } else if (memory_usage_reporting_timer_.IsRunning()) {
watk 2016/03/29 00:47:53 Should this be: else if (!is_playing && memory_usa
sandersd (OOO until July 31) 2016/03/30 23:46:00 Acknowledged.
1487 memory_usage_reporting_timer_.Stop();
1488 ReportMemoryUsage();
1496 } 1489 }
1497 } 1490 }
1498 1491
1499 void WebMediaPlayerImpl::NotifyPlaybackPaused() { 1492 void WebMediaPlayerImpl::UpdatePlayState_SetPlayState(PlayState new_state) {
1500 #if defined(OS_ANDROID) // WMPI_CAST 1493 DCHECK(delegate_);
1501 if (isRemote())
1502 return;
1503 #endif
1504 1494
1505 // Same as above, NotifyPlaybackPaused() may be called by interactions while 1495 if (play_state_ == new_state)
1506 // suspended, but those actions won't have any effect until the pipeline is
1507 // resumed.
1508 if (pipeline_controller_.IsSuspended())
1509 return; 1496 return;
1510 1497
1511 if (delegate_) 1498 play_state_ = new_state;
1512 delegate_->DidPause(delegate_id_, ended_); 1499
1513 memory_usage_reporting_timer_.Stop(); 1500 switch (new_state) {
1514 ReportMemoryUsage(); 1501 case PlayState::GONE:
1502 delegate_->PlayerGone(delegate_id_);
1503 break;
1504 case PlayState::PLAYING:
1505 // TODO(sandersd): Do we need to call this again on duration change?
1506 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1507 pipeline_.GetMediaDuration());
1508 break;
1509 case PlayState::PAUSED:
1510 delegate_->DidPause(delegate_id_, false);
1511 break;
1512 case PlayState::ENDED:
1513 delegate_->DidPause(delegate_id_, true);
1514 break;
1515 }
1515 } 1516 }
1516 1517
1517 void WebMediaPlayerImpl::ReportMemoryUsage() { 1518 void WebMediaPlayerImpl::ReportMemoryUsage() {
1518 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1519 DCHECK(main_task_runner_->BelongsToCurrentThread());
1519 1520
1520 // About base::Unretained() usage below: We destroy |demuxer_| on the main 1521 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1521 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 1522 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1522 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task 1523 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1523 // posted here must finish earlier. 1524 // posted here must finish earlier.
1524 1525
(...skipping 22 matching lines...) Expand all
1547 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage 1548 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1548 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1549 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1549 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1550 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1550 << ", Demuxer: " << demuxer_memory_usage; 1551 << ", Demuxer: " << demuxer_memory_usage;
1551 1552
1552 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1553 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1553 last_reported_memory_usage_ = current_memory_usage; 1554 last_reported_memory_usage_ = current_memory_usage;
1554 adjust_allocated_memory_cb_.Run(delta); 1555 adjust_allocated_memory_cb_.Run(delta);
1555 } 1556 }
1556 1557
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 1558 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698