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

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: Fixup API comments. 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
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/blink/webmediaplayer_impl.h" 5 #include "media/blink/webmediaplayer_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <string> 10 #include <string>
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 const url::Origin& security_origin, 98 const url::Origin& security_origin,
99 const SwitchOutputDeviceCB& callback) { 99 const SwitchOutputDeviceCB& callback) {
100 if (sink->GetOutputDevice()) { 100 if (sink->GetOutputDevice()) {
101 sink->GetOutputDevice()->SwitchOutputDevice(device_id, security_origin, 101 sink->GetOutputDevice()->SwitchOutputDevice(device_id, security_origin,
102 callback); 102 callback);
103 } else { 103 } else {
104 callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); 104 callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
105 } 105 }
106 } 106 }
107 107
108 bool IsSuspendUponHiddenEnabled() {
109 #if !defined(OS_ANDROID)
110 // Suspend/Resume is only enabled by default on Android.
111 return base::CommandLine::ForCurrentProcess()->HasSwitch(
112 switches::kEnableMediaSuspend);
113 #else
114 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
115 switches::kDisableMediaSuspend);
116 #endif
117 }
118
108 } // namespace 119 } // namespace
109 120
110 class BufferedDataSourceHostImpl; 121 class BufferedDataSourceHostImpl;
111 122
112 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified, 123 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
113 UrlData::CORS_UNSPECIFIED); 124 UrlData::CORS_UNSPECIFIED);
114 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS); 125 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
115 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials, 126 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
116 UrlData::CORS_USE_CREDENTIALS); 127 UrlData::CORS_USE_CREDENTIALS);
117 128
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 DVLOG(1) << __FUNCTION__; 343 DVLOG(1) << __FUNCTION__;
333 DCHECK(main_task_runner_->BelongsToCurrentThread()); 344 DCHECK(main_task_runner_->BelongsToCurrentThread());
334 345
335 #if defined(OS_ANDROID) // WMPI_CAST 346 #if defined(OS_ANDROID) // WMPI_CAST
336 if (isRemote()) { 347 if (isRemote()) {
337 cast_impl_.play(); 348 cast_impl_.play();
338 return; 349 return;
339 } 350 }
340 #endif 351 #endif
341 352
353 const bool was_paused = paused_;
342 paused_ = false; 354 paused_ = false;
343 pipeline_.SetPlaybackRate(playback_rate_); 355 pipeline_.SetPlaybackRate(playback_rate_);
344 356
345 if (data_source_) 357 if (data_source_)
346 data_source_->MediaIsPlaying(); 358 data_source_->MediaIsPlaying();
347 359
348 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 360 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
349 361
350 if (playback_rate_ > 0) { 362 if (playback_rate_ > 0 && was_paused) {
351 NotifyPlaybackStarted(); 363 NotifyPlaybackStarted();
352 364
353 // Resume the player if playback was initiated in the foreground. Resume() 365 // Resume the player if allowed. We always call Resume() in case there is a
354 // will do nothing if the pipeline is not suspended state, but will clear 366 // pending suspend that should be aborted. If the pipeline is not suspended,
355 // some internal pending state, so it should always be called. 367 // Resume() will have no effect.
356 if (delegate_ && !delegate_->IsHidden()) 368 if (IsAutomaticResumeAllowed())
357 pipeline_controller_.Resume(); 369 pipeline_controller_.Resume();
358 } 370 }
359 } 371 }
360 372
361 void WebMediaPlayerImpl::pause() { 373 void WebMediaPlayerImpl::pause() {
362 DVLOG(1) << __FUNCTION__; 374 DVLOG(1) << __FUNCTION__;
363 DCHECK(main_task_runner_->BelongsToCurrentThread()); 375 DCHECK(main_task_runner_->BelongsToCurrentThread());
364 376
365 const bool was_already_paused = paused_ || playback_rate_ == 0; 377 const bool was_already_paused = paused_ || playback_rate_ == 0;
366 paused_ = true; 378 paused_ = true;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 } 447 }
436 return; 448 return;
437 } 449 }
438 450
439 seeking_ = true; 451 seeking_ = true;
440 seek_time_ = time; 452 seek_time_ = time;
441 if (paused_) 453 if (paused_)
442 paused_time_ = time; 454 paused_time_ = time;
443 pipeline_controller_.Seek(time, time_updated); 455 pipeline_controller_.Seek(time, time_updated);
444 456
445 // Resume the pipeline if the seek is initiated in the foreground so that 457 // Resume the pipeline if allowed so that the correct frame is displayed. We
446 // the correct frame is displayed. If the pipeline is not suspended, Resume() 458 // always call Resume() in case there is a pending suspend that should be
447 // will do nothing but clear some pending state. 459 // aborted. If the pipeline is not suspended, Resume() will have no effect.
448 if (delegate_ && !delegate_->IsHidden()) 460 if (IsAutomaticResumeAllowed())
449 pipeline_controller_.Resume(); 461 pipeline_controller_.Resume();
450 } 462 }
451 463
452 void WebMediaPlayerImpl::setRate(double rate) { 464 void WebMediaPlayerImpl::setRate(double rate) {
453 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 465 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
454 DCHECK(main_task_runner_->BelongsToCurrentThread()); 466 DCHECK(main_task_runner_->BelongsToCurrentThread());
455 467
456 // TODO(kylep): Remove when support for negatives is added. Also, modify the 468 // TODO(kylep): Remove when support for negatives is added. Also, modify the
457 // following checks so rewind uses reasonable values also. 469 // following checks so rewind uses reasonable values also.
458 if (rate < 0.0) 470 if (rate < 0.0)
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 void WebMediaPlayerImpl::OnPipelineSuspended() { 863 void WebMediaPlayerImpl::OnPipelineSuspended() {
852 #if defined(OS_ANDROID) 864 #if defined(OS_ANDROID)
853 if (isRemote()) { 865 if (isRemote()) {
854 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 866 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
855 if (frame) { 867 if (frame) {
856 compositor_->PaintFrameUsingOldRenderingPath(frame); 868 compositor_->PaintFrameUsingOldRenderingPath(frame);
857 } 869 }
858 } 870 }
859 #endif 871 #endif
860 872
861 if (delegate_)
862 delegate_->PlayerGone(delegate_id_);
863 memory_usage_reporting_timer_.Stop(); 873 memory_usage_reporting_timer_.Stop();
864 ReportMemoryUsage(); 874 ReportMemoryUsage();
865 875
866 if (pending_suspend_resume_cycle_) { 876 if (pending_suspend_resume_cycle_) {
867 pending_suspend_resume_cycle_ = false; 877 pending_suspend_resume_cycle_ = false;
868 pipeline_controller_.Resume(); 878 pipeline_controller_.Resume();
869 return; 879 return;
870 } 880 }
871 } 881 }
872 882
873 void WebMediaPlayerImpl::OnPipelineResumed() { 883 void WebMediaPlayerImpl::OnPipelineResumed() {
874 if (playback_rate_ > 0 && !paused_) 884 if (playback_rate_ > 0 && !paused_) {
875 NotifyPlaybackStarted(); 885 NotifyPlaybackStarted();
886 } else if (!playback_rate_ || paused_ || ended_) {
887 // Resend our paused notification so the pipeline is considered for idle
888 // resource reclamation; duplicate pause notifications are ignored.
889 NotifyPlaybackPaused();
890 }
876 } 891 }
877 892
878 void WebMediaPlayerImpl::OnPipelineEnded() { 893 void WebMediaPlayerImpl::OnPipelineEnded() {
879 DVLOG(1) << __FUNCTION__; 894 DVLOG(1) << __FUNCTION__;
880 DCHECK(main_task_runner_->BelongsToCurrentThread()); 895 DCHECK(main_task_runner_->BelongsToCurrentThread());
881 896
882 // Ignore state changes until we've completed all outstanding operations. 897 // Ignore state changes until we've completed all outstanding operations.
883 if (!pipeline_controller_.IsStable()) 898 if (!pipeline_controller_.IsStable())
884 return; 899 return;
885 900
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 } 944 }
930 945
931 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer)); 946 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
932 video_weblayer_->layer()->SetContentsOpaque(opaque_); 947 video_weblayer_->layer()->SetContentsOpaque(opaque_);
933 video_weblayer_->SetContentsOpaqueIsFixed(true); 948 video_weblayer_->SetContentsOpaqueIsFixed(true);
934 client_->setWebLayer(video_weblayer_.get()); 949 client_->setWebLayer(video_weblayer_.get());
935 950
936 // If there is video and the frame is hidden, then it may be time to suspend 951 // If there is video and the frame is hidden, then it may be time to suspend
937 // playback. 952 // playback.
938 if (delegate_ && delegate_->IsHidden()) 953 if (delegate_ && delegate_->IsHidden())
939 OnHidden(false); 954 OnHidden();
940 } 955 }
941 } 956 }
942 957
943 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 958 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
944 BufferingState buffering_state) { 959 BufferingState buffering_state) {
945 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 960 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
946 961
947 // Ignore buffering state changes until we've completed all outstanding 962 // Ignore buffering state changes until we've completed all outstanding
948 // operations. 963 // operations.
949 if (!pipeline_controller_.IsStable()) 964 if (!pipeline_controller_.IsStable())
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 1005
991 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track( 1006 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
992 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id)); 1007 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
993 1008
994 scoped_ptr<TextTrack> text_track(new TextTrackImpl( 1009 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
995 main_task_runner_, client_, std::move(web_inband_text_track))); 1010 main_task_runner_, client_, std::move(web_inband_text_track)));
996 1011
997 done_cb.Run(std::move(text_track)); 1012 done_cb.Run(std::move(text_track));
998 } 1013 }
999 1014
1000 void WebMediaPlayerImpl::OnHidden(bool must_suspend) { 1015 void WebMediaPlayerImpl::OnHidden() {
1001 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1016 DCHECK(main_task_runner_->BelongsToCurrentThread());
1017 if (!IsSuspendUponHiddenEnabled())
1018 return;
1002 1019
1003 #if !defined(OS_ANDROID) 1020 #if defined(OS_ANDROID) // WMPI_CAST
1004 // Suspend/Resume is enabled by default on Android.
1005 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1006 switches::kEnableMediaSuspend)) {
1007 return;
1008 }
1009 #endif // !defined(OS_ANDROID)
1010
1011 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1012 switches::kDisableMediaSuspend)) {
1013 return;
1014 }
1015
1016 #if defined(OS_ANDROID)
1017 // If we're remote, the pipeline should already be suspended. 1021 // If we're remote, the pipeline should already be suspended.
1018 if (isRemote()) 1022 if (isRemote())
1019 return; 1023 return;
1020 #endif 1024 #endif
1021 1025
1022 if (must_suspend || (paused_ && ended_) || hasVideo()) 1026 // Don't suspend players which only have audio and have not completed
1023 pipeline_controller_.Suspend(); 1027 // playback. The user can still control these players via the MediaSession UI.
1028 // If the player has never started playback, OnSuspendRequested() will handle
1029 // release of any idle resources.
1030 if (!hasVideo() && !paused_ && !ended_)
1031 return;
1032
1033 pipeline_controller_.Suspend();
1034 if (delegate_)
1035 delegate_->PlayerGone(delegate_id_);
1024 } 1036 }
1025 1037
1026 void WebMediaPlayerImpl::OnShown() { 1038 void WebMediaPlayerImpl::OnShown() {
1027 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1039 DCHECK(main_task_runner_->BelongsToCurrentThread());
1040 if (!IsSuspendUponHiddenEnabled())
1041 return;
1028 1042
1029 #if !defined(OS_ANDROID) 1043 #if defined(OS_ANDROID) // WMPI_CAST
1030 // Suspend/Resume is enabled by default on Android.
1031 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1032 switches::kEnableMediaSuspend)) {
1033 return;
1034 }
1035 #endif // !defined(OS_ANDROID)
1036
1037 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1038 switches::kDisableMediaSuspend)) {
1039 return;
1040 }
1041
1042 #if defined(OS_ANDROID)
1043 // If we're remote, the pipeline should stay suspended. 1044 // If we're remote, the pipeline should stay suspended.
1044 if (isRemote()) 1045 if (isRemote())
1045 return; 1046 return;
1046 #endif 1047 #endif
1047 1048
1048 if (!ended_ && !paused_) 1049 if (!ended_ && !paused_)
1049 pipeline_controller_.Resume(); 1050 pipeline_controller_.Resume();
1050 } 1051 }
1051 1052
1053 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
1054 DCHECK(main_task_runner_->BelongsToCurrentThread());
1055
1056 #if defined(OS_ANDROID) // WMPI_CAST
1057 // If we're remote, the pipeline should already be suspended.
1058 if (isRemote())
1059 return;
1060 #endif
1061
1062 // Suspend should never be requested unless required or we're already in an
1063 // idle state (paused or ended).
1064 DCHECK(must_suspend || paused_ || ended_);
1065
1066 // Always suspend, but only notify the delegate if we must; this allows any
1067 // exposed UI for player controls to continue to function even though the
1068 // player has now been suspended.
1069 pipeline_controller_.Suspend();
1070 if (must_suspend && delegate_)
1071 delegate_->PlayerGone(delegate_id_);
1072 }
1073
1052 void WebMediaPlayerImpl::OnPlay() { 1074 void WebMediaPlayerImpl::OnPlay() {
1053 play(); 1075 play();
1054 client_->playbackStateChanged(); 1076 client_->playbackStateChanged();
1055 } 1077 }
1056 1078
1057 void WebMediaPlayerImpl::OnPause() { 1079 void WebMediaPlayerImpl::OnPause() {
1058 pause(); 1080 pause();
1059 client_->playbackStateChanged(); 1081 client_->playbackStateChanged();
1060 } 1082 }
1061 1083
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage 1449 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1428 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1450 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1429 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1451 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1430 << ", Demuxer: " << demuxer_memory_usage; 1452 << ", Demuxer: " << demuxer_memory_usage;
1431 1453
1432 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1454 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1433 last_reported_memory_usage_ = current_memory_usage; 1455 last_reported_memory_usage_ = current_memory_usage;
1434 adjust_allocated_memory_cb_.Run(delta); 1456 adjust_allocated_memory_cb_.Run(delta);
1435 } 1457 }
1436 1458
1459 bool WebMediaPlayerImpl::IsAutomaticResumeAllowed() {
1460 #if defined(OS_ANDROID)
1461 return !hasVideo() || (delegate_ && !delegate_->IsHidden());
1462 #else
1463 // On non-Android platforms Resume() is always allowed.
1464 return true;
1465 #endif
1466 }
1467
1437 } // namespace media 1468 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698