Chromium Code Reviews| 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |