| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |