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

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

Powered by Google App Engine
This is Rietveld 408576698