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

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

Issue 1766783003: Expand suspension of idle media players to all platforms. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@notify_pause
Patch Set: Cleanup. 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 const url::Origin& security_origin, 99 const url::Origin& security_origin,
100 const SwitchOutputDeviceCB& callback) { 100 const SwitchOutputDeviceCB& callback) {
101 if (sink->GetOutputDevice()) { 101 if (sink->GetOutputDevice()) {
102 sink->GetOutputDevice()->SwitchOutputDevice(device_id, security_origin, 102 sink->GetOutputDevice()->SwitchOutputDevice(device_id, security_origin,
103 callback); 103 callback);
104 } else { 104 } else {
105 callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); 105 callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
106 } 106 }
107 } 107 }
108 108
109 bool IsBackgroundSuspendResumeEnabled() {
110 #if !defined(OS_ANDROID)
111 // Suspend/Resume is only enabled by default on Android.
112 return base::CommandLine::ForCurrentProcess()->HasSwitch(
113 switches::kEnableMediaSuspend);
114 #else
115 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
116 switches::kDisableMediaSuspend);
117 #endif
118 }
119
109 } // namespace 120 } // namespace
110 121
111 class BufferedDataSourceHostImpl; 122 class BufferedDataSourceHostImpl;
112 123
113 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified, 124 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
114 UrlData::CORS_UNSPECIFIED); 125 UrlData::CORS_UNSPECIFIED);
115 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS); 126 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
116 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials, 127 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
117 UrlData::CORS_USE_CREDENTIALS); 128 UrlData::CORS_USE_CREDENTIALS);
118 129
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 compositor_task_runner_, 192 compositor_task_runner_,
182 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), 193 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
183 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), 194 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
184 is_cdm_attached_(false), 195 is_cdm_attached_(false),
185 #if defined(OS_ANDROID) // WMPI_CAST 196 #if defined(OS_ANDROID) // WMPI_CAST
186 cast_impl_(this, client_, params.context_3d_cb()), 197 cast_impl_(this, client_, params.context_3d_cb()),
187 #endif 198 #endif
188 volume_(1.0), 199 volume_(1.0),
189 volume_multiplier_(1.0), 200 volume_multiplier_(1.0),
190 renderer_factory_(std::move(renderer_factory)), 201 renderer_factory_(std::move(renderer_factory)),
202 background_playback_state_(
203 BackgroundPlaybackState::PLAY_FORBIDDEN_NEVER_CALLED_IN_FOREGROUND),
191 surface_manager_(params.surface_manager()), 204 surface_manager_(params.surface_manager()),
192 suppress_destruction_errors_(false) { 205 suppress_destruction_errors_(false) {
193 DCHECK(!adjust_allocated_memory_cb_.is_null()); 206 DCHECK(!adjust_allocated_memory_cb_.is_null());
194 DCHECK(renderer_factory_); 207 DCHECK(renderer_factory_);
195 208
196 if (delegate_) 209 if (delegate_)
197 delegate_id_ = delegate_->AddObserver(this); 210 delegate_id_ = delegate_->AddObserver(this);
198 211
199 media_log_->AddEvent( 212 media_log_->AddEvent(
200 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); 213 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 DVLOG(1) << __FUNCTION__; 346 DVLOG(1) << __FUNCTION__;
334 DCHECK(main_task_runner_->BelongsToCurrentThread()); 347 DCHECK(main_task_runner_->BelongsToCurrentThread());
335 348
336 #if defined(OS_ANDROID) // WMPI_CAST 349 #if defined(OS_ANDROID) // WMPI_CAST
337 if (isRemote()) { 350 if (isRemote()) {
338 cast_impl_.play(); 351 cast_impl_.play();
339 return; 352 return;
340 } 353 }
341 #endif 354 #endif
342 355
356 const bool was_paused = paused_;
343 paused_ = false; 357 paused_ = false;
344 pipeline_.SetPlaybackRate(playback_rate_); 358 pipeline_.SetPlaybackRate(playback_rate_);
345 359
346 if (data_source_) 360 if (data_source_)
347 data_source_->MediaIsPlaying(); 361 data_source_->MediaIsPlaying();
348 362
349 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 363 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
350 364
351 if (playback_rate_ > 0) { 365 if (background_playback_state_ ==
366 BackgroundPlaybackState::PLAY_FORBIDDEN_NEVER_CALLED_IN_FOREGROUND &&
sandersd (OOO until July 31) 2016/03/07 23:27:51 The existence of this check isn't immediately nece
DaleCurtis 2016/03/09 02:56:14 Removed.
367 delegate_ && !delegate_->IsHidden()) {
368 background_playback_state_ =
369 hasVideo() ? BackgroundPlaybackState::PLAY_FORBIDDEN_WHEN_SUSPENDED
370 : BackgroundPlaybackState::PLAY_ALLOWED_WHEN_SUSPENDED;
mlamouri (slow - plz ping) 2016/03/05 22:37:36 Should this include IsBackgroundSuspendResumeEnabl
DaleCurtis 2016/03/09 02:56:13 No, as indicated below. I've also renamed it to Is
371 }
372
373 if (playback_rate_ > 0 && was_paused) {
352 NotifyPlaybackStarted(); 374 NotifyPlaybackStarted();
sandersd (OOO until July 31) 2016/03/07 23:27:51 Add a comment here that this method won't do anyth
353 375 if (IsResumeAllowed())
354 // Resume the player if playback was initiated in the foreground. Resume()
355 // will do nothing if the pipeline is not suspended state, but will clear
356 // some internal pending state, so it should always be called.
357 if (delegate_ && !delegate_->IsHidden())
358 pipeline_controller_.Resume(); 376 pipeline_controller_.Resume();
359 } 377 }
360 } 378 }
361 379
362 void WebMediaPlayerImpl::pause() { 380 void WebMediaPlayerImpl::pause() {
363 DVLOG(1) << __FUNCTION__; 381 DVLOG(1) << __FUNCTION__;
364 DCHECK(main_task_runner_->BelongsToCurrentThread()); 382 DCHECK(main_task_runner_->BelongsToCurrentThread());
365 383
366 const bool was_already_paused = paused_ || playback_rate_ == 0; 384 const bool was_already_paused = paused_ || playback_rate_ == 0;
367 paused_ = true; 385 paused_ = true;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 } 454 }
437 return; 455 return;
438 } 456 }
439 457
440 seeking_ = true; 458 seeking_ = true;
441 seek_time_ = time; 459 seek_time_ = time;
442 if (paused_) 460 if (paused_)
443 paused_time_ = time; 461 paused_time_ = time;
444 pipeline_controller_.Seek(time, time_updated); 462 pipeline_controller_.Seek(time, time_updated);
445 463
446 // Resume the pipeline if the seek is initiated in the foreground so that 464 if (IsResumeAllowed())
447 // the correct frame is displayed. If the pipeline is not suspended, Resume()
448 // will do nothing but clear some pending state.
449 if (delegate_ && !delegate_->IsHidden())
450 pipeline_controller_.Resume(); 465 pipeline_controller_.Resume();
451 } 466 }
452 467
453 void WebMediaPlayerImpl::setRate(double rate) { 468 void WebMediaPlayerImpl::setRate(double rate) {
454 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 469 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
455 DCHECK(main_task_runner_->BelongsToCurrentThread()); 470 DCHECK(main_task_runner_->BelongsToCurrentThread());
456 471
457 // TODO(kylep): Remove when support for negatives is added. Also, modify the 472 // TODO(kylep): Remove when support for negatives is added. Also, modify the
458 // following checks so rewind uses reasonable values also. 473 // following checks so rewind uses reasonable values also.
459 if (rate < 0.0) 474 if (rate < 0.0)
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 void WebMediaPlayerImpl::OnPipelineSuspended() { 865 void WebMediaPlayerImpl::OnPipelineSuspended() {
851 #if defined(OS_ANDROID) 866 #if defined(OS_ANDROID)
852 if (isRemote()) { 867 if (isRemote()) {
853 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 868 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
854 if (frame) { 869 if (frame) {
855 compositor_->PaintFrameUsingOldRenderingPath(frame); 870 compositor_->PaintFrameUsingOldRenderingPath(frame);
856 } 871 }
857 } 872 }
858 #endif 873 #endif
859 874
860 if (delegate_)
861 delegate_->PlayerGone(delegate_id_);
862 memory_usage_reporting_timer_.Stop(); 875 memory_usage_reporting_timer_.Stop();
863 ReportMemoryUsage(); 876 ReportMemoryUsage();
864 877
865 if (pending_suspend_resume_cycle_) { 878 if (pending_suspend_resume_cycle_) {
866 pending_suspend_resume_cycle_ = false; 879 pending_suspend_resume_cycle_ = false;
867 pipeline_controller_.Resume(); 880 pipeline_controller_.Resume();
868 return; 881 return;
869 } 882 }
870 } 883 }
871 884
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 } 941 }
929 942
930 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer)); 943 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
931 video_weblayer_->layer()->SetContentsOpaque(opaque_); 944 video_weblayer_->layer()->SetContentsOpaque(opaque_);
932 video_weblayer_->SetContentsOpaqueIsFixed(true); 945 video_weblayer_->SetContentsOpaqueIsFixed(true);
933 client_->setWebLayer(video_weblayer_.get()); 946 client_->setWebLayer(video_weblayer_.get());
934 947
935 // If there is video and the frame is hidden, then it may be time to suspend 948 // If there is video and the frame is hidden, then it may be time to suspend
936 // playback. 949 // playback.
937 if (delegate_ && delegate_->IsHidden()) 950 if (delegate_ && delegate_->IsHidden())
938 OnHidden(false); 951 OnHidden();
939 } 952 }
940 } 953 }
941 954
942 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 955 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
943 BufferingState buffering_state) { 956 BufferingState buffering_state) {
944 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 957 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
945 958
946 // Ignore buffering state changes until we've completed all outstanding 959 // Ignore buffering state changes until we've completed all outstanding
947 // operations. 960 // operations.
948 if (!pipeline_controller_.IsStable()) 961 if (!pipeline_controller_.IsStable())
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 1002
990 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track( 1003 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
991 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id)); 1004 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
992 1005
993 scoped_ptr<TextTrack> text_track(new TextTrackImpl( 1006 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
994 main_task_runner_, client_, std::move(web_inband_text_track))); 1007 main_task_runner_, client_, std::move(web_inband_text_track)));
995 1008
996 done_cb.Run(std::move(text_track)); 1009 done_cb.Run(std::move(text_track));
997 } 1010 }
998 1011
999 void WebMediaPlayerImpl::OnHidden(bool must_suspend) { 1012 void WebMediaPlayerImpl::OnHidden() {
1000 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1013 DCHECK(main_task_runner_->BelongsToCurrentThread());
1014 if (!IsBackgroundSuspendResumeEnabled())
1015 return;
1001 1016
1002 #if !defined(OS_ANDROID) 1017 #if defined(OS_ANDROID) // WMPI_CAST
1003 // Suspend/Resume is enabled by default on Android.
1004 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1005 switches::kEnableMediaSuspend)) {
1006 return;
1007 }
1008 #endif // !defined(OS_ANDROID)
1009
1010 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1011 switches::kDisableMediaSuspend)) {
1012 return;
1013 }
1014
1015 #if defined(OS_ANDROID)
1016 // If we're remote, the pipeline should already be suspended. 1018 // If we're remote, the pipeline should already be suspended.
1017 if (isRemote()) 1019 if (isRemote())
1018 return; 1020 return;
1019 #endif 1021 #endif
1020 1022
1021 if (must_suspend || (paused_ && ended_) || hasVideo()) 1023 // Don't suspend players which started playback in the foreground, only have
1022 pipeline_controller_.Suspend(); 1024 // audio, and have not completed playback. The user can still control these
1025 // players via the MediaSession UI.
1026 if (background_playback_state_ >
1027 BackgroundPlaybackState::PLAY_FORBIDDEN_NEVER_CALLED_IN_FOREGROUND &&
1028 !hasVideo() && !ended_) {
1029 return;
1030 }
1031
1032 pipeline_controller_.Suspend();
1033 if (delegate_)
1034 delegate_->PlayerGone(delegate_id_);
1023 } 1035 }
1024 1036
1025 void WebMediaPlayerImpl::OnShown() { 1037 void WebMediaPlayerImpl::OnShown() {
1026 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1038 DCHECK(main_task_runner_->BelongsToCurrentThread());
1039 if (!IsBackgroundSuspendResumeEnabled())
1040 return;
1027 1041
1028 #if !defined(OS_ANDROID) 1042 #if defined(OS_ANDROID) // WMPI_CAST
1029 // Suspend/Resume is enabled by default on Android.
1030 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1031 switches::kEnableMediaSuspend)) {
1032 return;
1033 }
1034 #endif // !defined(OS_ANDROID)
1035
1036 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1037 switches::kDisableMediaSuspend)) {
1038 return;
1039 }
1040
1041 #if defined(OS_ANDROID)
1042 // If we're remote, the pipeline should stay suspended. 1043 // If we're remote, the pipeline should stay suspended.
1043 if (isRemote()) 1044 if (isRemote())
1044 return; 1045 return;
1045 #endif 1046 #endif
1046 1047
1047 if (!ended_ && !paused_) 1048 if (!ended_ && !paused_)
1048 pipeline_controller_.Resume(); 1049 pipeline_controller_.Resume();
1049 } 1050 }
1050 1051
1052 void WebMediaPlayerImpl::OnSuspend(bool must_suspend) {
1053 DCHECK(main_task_runner_->BelongsToCurrentThread());
1054
1055 #if defined(OS_ANDROID) // WMPI_CAST
1056 // If we're remote, the pipeline should already be suspended.
1057 if (isRemote())
1058 return;
1059 #endif
1060
1061 // Suspend should never be sent unless always required or we're already in a
1062 // paused or ended state.
1063 DCHECK(must_suspend || paused_ || ended_);
1064
1065 NotifyPlaybackPaused();
1066
1067 // Always suspend, but only notify the delegate if we must; this allows any
1068 // exposed UI for player controls to continue to function even though the
1069 // player has now been suspended.
1070 pipeline_controller_.Suspend();
1071 if (must_suspend && delegate_)
1072 delegate_->PlayerGone(delegate_id_);
1073 }
1074
1051 void WebMediaPlayerImpl::OnPlay() { 1075 void WebMediaPlayerImpl::OnPlay() {
1052 play(); 1076 play();
1053 client_->playbackStateChanged(); 1077 client_->playbackStateChanged();
1054 } 1078 }
1055 1079
1056 void WebMediaPlayerImpl::OnPause() { 1080 void WebMediaPlayerImpl::OnPause() {
1057 pause(); 1081 pause();
1058 client_->playbackStateChanged(); 1082 client_->playbackStateChanged();
1059 } 1083 }
1060 1084
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage 1441 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1418 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1442 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1419 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1443 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1420 << ", Demuxer: " << demuxer_memory_usage; 1444 << ", Demuxer: " << demuxer_memory_usage;
1421 1445
1422 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1446 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1423 last_reported_memory_usage_ = current_memory_usage; 1447 last_reported_memory_usage_ = current_memory_usage;
1424 adjust_allocated_memory_cb_.Run(delta); 1448 adjust_allocated_memory_cb_.Run(delta);
1425 } 1449 }
1426 1450
1451 bool WebMediaPlayerImpl::IsResumeAllowed() {
1452 #if defined(OS_ANDROID)
1453 return background_playback_state_ ==
1454 BackgroundPlaybackState::PLAY_ALLOWED_WHEN_SUSPENDED ||
1455 (delegate_ && !delegate_->IsHidden());
mlamouri (slow - plz ping) 2016/03/05 22:37:36 Should this include IsBackgroundSuspendResumeEnabl
DaleCurtis 2016/03/07 19:08:06 No, I tried to make it clear that IsBackgroundSusp
1456 #else
1457 // On non-Android platforms Resume() is always allowed.
1458 return true;
1459 #endif
1460 }
1461
1427 } // namespace media 1462 } // namespace media
OLDNEW
« media/blink/webmediaplayer_impl.h ('K') | « media/blink/webmediaplayer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698