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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 | 174 |
175 WebMediaPlayerImpl::WebMediaPlayerImpl( | 175 WebMediaPlayerImpl::WebMediaPlayerImpl( |
176 blink::WebLocalFrame* frame, | 176 blink::WebLocalFrame* frame, |
177 blink::WebMediaPlayerClient* client, | 177 blink::WebMediaPlayerClient* client, |
178 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client, | 178 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client, |
179 base::WeakPtr<WebMediaPlayerDelegate> delegate, | 179 base::WeakPtr<WebMediaPlayerDelegate> delegate, |
180 std::unique_ptr<RendererFactory> renderer_factory, | 180 std::unique_ptr<RendererFactory> renderer_factory, |
181 linked_ptr<UrlIndex> url_index, | 181 linked_ptr<UrlIndex> url_index, |
182 const WebMediaPlayerParams& params) | 182 const WebMediaPlayerParams& params) |
183 : frame_(frame), | 183 : frame_(frame), |
184 delegate_state_(DelegateState::GONE), | |
185 is_idle_(false), | |
186 must_suspend_(false), | |
187 network_state_(WebMediaPlayer::NetworkStateEmpty), | 184 network_state_(WebMediaPlayer::NetworkStateEmpty), |
188 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), | 185 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), |
189 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing), | 186 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing), |
190 preload_(MultibufferDataSource::AUTO), | 187 preload_(MultibufferDataSource::AUTO), |
191 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL), | 188 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL), |
192 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 189 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
193 media_task_runner_(params.media_task_runner()), | 190 media_task_runner_(params.media_task_runner()), |
194 worker_task_runner_(params.worker_task_runner()), | 191 worker_task_runner_(params.worker_task_runner()), |
195 media_log_(params.media_log()), | 192 media_log_(params.media_log()), |
196 pipeline_(media_task_runner_, media_log_.get()), | 193 pipeline_(media_task_runner_, media_log_.get()), |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 volume_(1.0), | 230 volume_(1.0), |
234 volume_multiplier_(1.0), | 231 volume_multiplier_(1.0), |
235 renderer_factory_(std::move(renderer_factory)), | 232 renderer_factory_(std::move(renderer_factory)), |
236 surface_manager_(params.surface_manager()), | 233 surface_manager_(params.surface_manager()), |
237 overlay_surface_id_(SurfaceManager::kNoSurfaceID), | 234 overlay_surface_id_(SurfaceManager::kNoSurfaceID), |
238 suppress_destruction_errors_(false), | 235 suppress_destruction_errors_(false), |
239 can_suspend_state_(CanSuspendState::UNKNOWN), | 236 can_suspend_state_(CanSuspendState::UNKNOWN), |
240 use_fallback_path_(false), | 237 use_fallback_path_(false), |
241 is_encrypted_(false), | 238 is_encrypted_(false), |
242 underflow_count_(0), | 239 underflow_count_(0), |
240 preroll_attempt_pending_(false), | |
243 observer_(params.media_observer()) { | 241 observer_(params.media_observer()) { |
244 DCHECK(!adjust_allocated_memory_cb_.is_null()); | 242 DCHECK(!adjust_allocated_memory_cb_.is_null()); |
245 DCHECK(renderer_factory_); | 243 DCHECK(renderer_factory_); |
246 DCHECK(client_); | 244 DCHECK(client_); |
247 | 245 |
248 tick_clock_.reset(new base::DefaultTickClock()); | 246 tick_clock_.reset(new base::DefaultTickClock()); |
249 | 247 |
250 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch( | 248 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch( |
251 switches::kForceVideoOverlays); | 249 switches::kForceVideoOverlays); |
252 | 250 |
253 disable_fullscreen_video_overlays_ = | 251 disable_fullscreen_video_overlays_ = |
254 !base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo); | 252 !base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo); |
255 | 253 |
256 if (delegate_) | 254 if (delegate_) { |
257 delegate_id_ = delegate_->AddObserver(this); | 255 delegate_id_ = delegate_->AddObserver(this); |
256 delegate_->SetIdle(delegate_id_, true); | |
257 } | |
258 | 258 |
259 media_log_->AddEvent( | 259 media_log_->AddEvent( |
260 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); | 260 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); |
261 | 261 |
262 if (params.initial_cdm()) | 262 if (params.initial_cdm()) |
263 SetCdm(params.initial_cdm()); | 263 SetCdm(params.initial_cdm()); |
264 | 264 |
265 // TODO(xhwang): When we use an external Renderer, many methods won't work, | 265 // TODO(xhwang): When we use an external Renderer, many methods won't work, |
266 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 | 266 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 |
267 | 267 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
414 void WebMediaPlayerImpl::play() { | 414 void WebMediaPlayerImpl::play() { |
415 DVLOG(1) << __func__; | 415 DVLOG(1) << __func__; |
416 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 416 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
417 | 417 |
418 #if defined(OS_ANDROID) // WMPI_CAST | 418 #if defined(OS_ANDROID) // WMPI_CAST |
419 if (isRemote()) { | 419 if (isRemote()) { |
420 cast_impl_.play(); | 420 cast_impl_.play(); |
421 return; | 421 return; |
422 } | 422 } |
423 #endif | 423 #endif |
424 // TODO(sandersd): Do we want to reset the idle timer here? | |
425 if (delegate_) | |
426 delegate_->SetIdle(delegate_id_, false); | |
424 paused_ = false; | 427 paused_ = false; |
425 is_idle_ = false; | |
426 pipeline_.SetPlaybackRate(playback_rate_); | 428 pipeline_.SetPlaybackRate(playback_rate_); |
427 background_pause_timer_.Stop(); | 429 background_pause_timer_.Stop(); |
428 | 430 |
429 if (data_source_) | 431 if (data_source_) |
430 data_source_->MediaIsPlaying(); | 432 data_source_->MediaIsPlaying(); |
431 | 433 |
432 DCHECK(watch_time_reporter_); | 434 DCHECK(watch_time_reporter_); |
433 watch_time_reporter_->OnPlaying(); | 435 watch_time_reporter_->OnPlaying(); |
434 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); | 436 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); |
435 UpdatePlayState(); | 437 UpdatePlayState(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); | 512 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); |
511 } | 513 } |
512 return; | 514 return; |
513 } | 515 } |
514 | 516 |
515 // Call this before setting |seeking_| so that the current media time can be | 517 // Call this before setting |seeking_| so that the current media time can be |
516 // recorded by the reporter. | 518 // recorded by the reporter. |
517 if (watch_time_reporter_) | 519 if (watch_time_reporter_) |
518 watch_time_reporter_->OnSeeking(); | 520 watch_time_reporter_->OnSeeking(); |
519 | 521 |
520 // TODO(sandersd): Ideally we would not clear the idle state if | 522 // TODO(sandersd): Move |seeking_| to PipelineController. |
521 // |pipeline_controller_| can elide the seek. | 523 // TODO(sandersd): Do we want to reset the idle timer here? |
522 is_idle_ = false; | 524 if (delegate_) |
525 delegate_->SetIdle(delegate_id_, false); | |
523 ended_ = false; | 526 ended_ = false; |
524 | |
525 seeking_ = true; | 527 seeking_ = true; |
526 seek_time_ = time; | 528 seek_time_ = time; |
527 if (paused_) | 529 if (paused_) |
528 paused_time_ = time; | 530 paused_time_ = time; |
529 pipeline_controller_.Seek(time, time_updated); | 531 pipeline_controller_.Seek(time, time_updated); |
530 | 532 |
531 // This needs to be called after Seek() so that if a resume is triggered, it | 533 // This needs to be called after Seek() so that if a resume is triggered, it |
532 // is to the correct time. | 534 // is to the correct time. |
533 UpdatePlayState(); | 535 UpdatePlayState(); |
534 } | 536 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 std::isfinite(seekable_end); | 783 std::isfinite(seekable_end); |
782 | 784 |
783 // TODO(dalecurtis): Technically this allows seeking on media which return an | 785 // TODO(dalecurtis): Technically this allows seeking on media which return an |
784 // infinite duration so long as DataSource::IsStreaming() is false. While not | 786 // infinite duration so long as DataSource::IsStreaming() is false. While not |
785 // expected, disabling this breaks semi-live players, http://crbug.com/427412. | 787 // expected, disabling this breaks semi-live players, http://crbug.com/427412. |
786 const blink::WebTimeRange seekable_range( | 788 const blink::WebTimeRange seekable_range( |
787 0.0, allow_seek_to_zero ? 0.0 : seekable_end); | 789 0.0, allow_seek_to_zero ? 0.0 : seekable_end); |
788 return blink::WebTimeRanges(&seekable_range, 1); | 790 return blink::WebTimeRanges(&seekable_range, 1); |
789 } | 791 } |
790 | 792 |
793 bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() { | |
794 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need | |
795 // to ensure that preroll always gets a chance to complete. | |
796 if (highest_ready_state_ >= ReadyState::ReadyStateHaveFutureData) | |
797 return false; | |
798 | |
799 if (preroll_attempt_pending_) | |
800 return true; | |
801 | |
802 // Freshly initialized; there has never been any loading progress. (Otherwise | |
803 // |preroll_attempt_pending_| would be true when the start time is null.) | |
804 if (preroll_attempt_start_time_.is_null()) | |
805 return false; | |
806 | |
807 base::TimeDelta preroll_attempt_duration = | |
808 tick_clock_->NowTicks() - preroll_attempt_start_time_; | |
809 return preroll_attempt_duration < kLoadingToIdleTimeout; | |
810 } | |
811 | |
791 bool WebMediaPlayerImpl::didLoadingProgress() { | 812 bool WebMediaPlayerImpl::didLoadingProgress() { |
792 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 813 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
793 | 814 |
794 // Note: Separate variables used to ensure both methods are called every time. | 815 // Note: Separate variables used to ensure both methods are called every time. |
795 const bool pipeline_progress = pipeline_.DidLoadingProgress(); | 816 const bool pipeline_progress = pipeline_.DidLoadingProgress(); |
796 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); | 817 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); |
797 const bool did_loading_progress = pipeline_progress || data_progress; | 818 const bool did_loading_progress = pipeline_progress || data_progress; |
798 | 819 |
799 // If we've idle suspended before reaching kHaveFutureData and loading has | 820 if (did_loading_progress && |
800 // progressed we need to spin up the renderer and figure out if we have enough | 821 highest_ready_state_ < ReadyState::ReadyStateHaveFutureData) { |
801 // data yet; |client_| may be waiting on this signal to trigger playback. The | 822 // Reset the preroll attempt clock. |
802 // idle timeout is long enough that this is a low-cost operation. | 823 preroll_attempt_pending_ = true; |
803 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData && | 824 preroll_attempt_start_time_ = base::TimeTicks(); |
804 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) { | 825 |
805 is_idle_ = false; | 826 // Clear any 'stale' flag and give the pipeline a chance to resume. If we |
827 // are already resumed, this will cause |preroll_attempt_start_time_| to be | |
828 // set. | |
829 // TODO(sandersd): Should this be on the same stack? It might be surprsing | |
tguilbert
2016/12/15 22:01:06
Typo: surprising
sandersd (OOO until July 31)
2017/01/05 23:12:21
Done.
| |
830 // that didLoadingProgress() can synchronously change state. | |
831 if (delegate_) | |
832 delegate_->ClearStaleFlag(delegate_id_); | |
806 UpdatePlayState(); | 833 UpdatePlayState(); |
807 } | 834 } |
808 | 835 |
809 if (did_loading_progress) | |
810 last_time_loading_progressed_ = tick_clock_->NowTicks(); | |
811 | |
812 return did_loading_progress; | 836 return did_loading_progress; |
813 } | 837 } |
814 | 838 |
815 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, | 839 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, |
816 const blink::WebRect& rect, | 840 const blink::WebRect& rect, |
817 SkPaint& paint) { | 841 SkPaint& paint) { |
818 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 842 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
819 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); | 843 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); |
820 | 844 |
821 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when | 845 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1194 // TODO(chcunningham): Monitor playback position vs buffered. Potentially | 1218 // TODO(chcunningham): Monitor playback position vs buffered. Potentially |
1195 // transition to HAVE_FUTURE_DATA here if not enough is buffered. | 1219 // transition to HAVE_FUTURE_DATA here if not enough is buffered. |
1196 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | 1220 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); |
1197 | 1221 |
1198 // Let the DataSource know we have enough data. It may use this information | 1222 // Let the DataSource know we have enough data. It may use this information |
1199 // to release unused network connections. | 1223 // to release unused network connections. |
1200 if (data_source_) | 1224 if (data_source_) |
1201 data_source_->OnBufferingHaveEnough(false); | 1225 data_source_->OnBufferingHaveEnough(false); |
1202 | 1226 |
1203 // Blink expects a timeChanged() in response to a seek(). | 1227 // Blink expects a timeChanged() in response to a seek(). |
1204 if (should_notify_time_changed_) | 1228 if (should_notify_time_changed_) { |
1229 should_notify_time_changed_ = false; | |
1205 client_->timeChanged(); | 1230 client_->timeChanged(); |
1231 } | |
1206 | 1232 |
1207 // Once we have enough, start reporting the total memory usage. We'll also | 1233 // Once we have enough, start reporting the total memory usage. We'll also |
1208 // report once playback starts. | 1234 // report once playback starts. |
1209 ReportMemoryUsage(); | 1235 ReportMemoryUsage(); |
1210 | 1236 |
1211 // Report the amount of time it took to leave the underflow state. Don't | 1237 // Report the amount of time it took to leave the underflow state. Don't |
1212 // bother to report this for MSE playbacks since it's out of our control. | 1238 // bother to report this for MSE playbacks since it's out of our control. |
1213 if (underflow_timer_ && data_source_) { | 1239 if (underflow_timer_ && data_source_) { |
1214 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", | 1240 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", |
1215 underflow_timer_->Elapsed()); | 1241 underflow_timer_->Elapsed()); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1311 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1337 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1312 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); | 1338 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); |
1313 | 1339 |
1314 opaque_ = opaque; | 1340 opaque_ = opaque; |
1315 // Modify content opaqueness of cc::Layer directly so that | 1341 // Modify content opaqueness of cc::Layer directly so that |
1316 // SetContentsOpaqueIsFixed is ignored. | 1342 // SetContentsOpaqueIsFixed is ignored. |
1317 if (video_weblayer_) | 1343 if (video_weblayer_) |
1318 video_weblayer_->layer()->SetContentsOpaque(opaque_); | 1344 video_weblayer_->layer()->SetContentsOpaque(opaque_); |
1319 } | 1345 } |
1320 | 1346 |
1321 void WebMediaPlayerImpl::OnHidden() { | 1347 void WebMediaPlayerImpl::OnFrameHidden() { |
1322 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1348 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1323 | 1349 |
1324 if (IsBackgroundVideoTrackOptimizationEnabled()) | 1350 if (IsBackgroundVideoTrackOptimizationEnabled()) |
1325 selectedVideoTrackChanged(nullptr); | 1351 selectedVideoTrackChanged(nullptr); |
1326 | 1352 |
1327 if (watch_time_reporter_) | 1353 if (watch_time_reporter_) |
1328 watch_time_reporter_->OnHidden(); | 1354 watch_time_reporter_->OnHidden(); |
1329 | 1355 |
1330 UpdatePlayState(); | 1356 UpdatePlayState(); |
1331 | 1357 |
1332 // Schedule suspended playing media to be paused if the user doesn't come back | 1358 // Schedule suspended playing media to be paused if the user doesn't come back |
1333 // to it within some timeout period to avoid any autoplay surprises. | 1359 // to it within some timeout period to avoid any autoplay surprises. |
1334 ScheduleIdlePauseTimer(); | 1360 ScheduleIdlePauseTimer(); |
1335 } | 1361 } |
1336 | 1362 |
1337 void WebMediaPlayerImpl::OnShown() { | 1363 void WebMediaPlayerImpl::OnFrameClosed() { |
1338 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1364 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1365 UpdatePlayState(); | |
1366 } | |
1367 | |
1368 void WebMediaPlayerImpl::OnFrameShown() { | |
1369 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
1370 background_pause_timer_.Stop(); | |
1371 | |
1339 if (watch_time_reporter_) | 1372 if (watch_time_reporter_) |
1340 watch_time_reporter_->OnShown(); | 1373 watch_time_reporter_->OnShown(); |
1341 | 1374 |
1342 if (IsBackgroundVideoTrackOptimizationEnabled() && | 1375 if (IsBackgroundVideoTrackOptimizationEnabled() && |
1343 client_->hasSelectedVideoTrack()) { | 1376 client_->hasSelectedVideoTrack()) { |
1344 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId(); | 1377 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId(); |
1345 selectedVideoTrackChanged(&trackId); | 1378 selectedVideoTrackChanged(&trackId); |
1346 } | 1379 } |
1347 | 1380 |
1348 must_suspend_ = false; | |
1349 background_pause_timer_.Stop(); | |
1350 | |
1351 UpdatePlayState(); | 1381 UpdatePlayState(); |
1352 } | 1382 } |
1353 | 1383 |
1354 bool WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { | 1384 bool WebMediaPlayerImpl::OnIdleTimeout() { |
1355 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1385 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1386 if (IsPrerollAttemptNeeded()) | |
1387 return false; | |
1356 | 1388 |
1357 if (must_suspend) { | 1389 // Post the update as a task so that: |
1358 must_suspend_ = true; | 1390 // 1) IsStale() returns true in UpdatePlayState(). |
1359 UpdatePlayState(); | 1391 // 2) We don't have to worry if we call SetIdle(false). |
1360 return true; | 1392 main_task_runner_->PostTask( |
1361 } | 1393 FROM_HERE, base::Bind(&WebMediaPlayerImpl::UpdatePlayState, AsWeakPtr())); |
1362 | 1394 |
1363 // If we're beyond HaveFutureData, we can safely suspend at any time. | 1395 return true; |
1364 if (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData) { | |
1365 is_idle_ = true; | |
1366 UpdatePlayState(); | |
1367 return true; | |
1368 } | |
1369 | |
1370 // Before HaveFutureData blink will not call play(), so we must be careful to | |
1371 // only suspend if we'll eventually receive an event that will trigger a | |
1372 // resume. If the last time loading progressed was a while ago, and we still | |
1373 // haven't reached HaveFutureData, we assume that we're waiting on more data | |
1374 // to continue pre-rolling. When that data is loaded the pipeline will be | |
1375 // resumed by didLoadingProgress(). | |
1376 if (last_time_loading_progressed_.is_null() || | |
1377 (tick_clock_->NowTicks() - last_time_loading_progressed_) > | |
1378 kLoadingToIdleTimeout) { | |
1379 is_idle_ = true; | |
1380 UpdatePlayState(); | |
1381 return true; | |
1382 } | |
1383 | |
1384 return false; | |
1385 } | 1396 } |
1386 | 1397 |
1387 void WebMediaPlayerImpl::OnPlay() { | 1398 void WebMediaPlayerImpl::OnPlay() { |
1388 play(); | 1399 play(); |
1389 client_->playbackStateChanged(); | 1400 client_->playbackStateChanged(); |
1390 } | 1401 } |
1391 | 1402 |
1392 void WebMediaPlayerImpl::OnPause() { | 1403 void WebMediaPlayerImpl::OnPause() { |
1393 pause(); | 1404 pause(); |
1394 client_->playbackStateChanged(); | 1405 client_->playbackStateChanged(); |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1717 bool is_streaming = false; | 1728 bool is_streaming = false; |
1718 #else | 1729 #else |
1719 bool is_remote = false; | 1730 bool is_remote = false; |
1720 bool is_streaming = data_source_ && data_source_->IsStreaming(); | 1731 bool is_streaming = data_source_ && data_source_->IsStreaming(); |
1721 #endif | 1732 #endif |
1722 | 1733 |
1723 bool is_suspended = pipeline_controller_.IsSuspended(); | 1734 bool is_suspended = pipeline_controller_.IsSuspended(); |
1724 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden(); | 1735 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden(); |
1725 PlayState state = UpdatePlayState_ComputePlayState( | 1736 PlayState state = UpdatePlayState_ComputePlayState( |
1726 is_remote, is_streaming, is_suspended, is_backgrounded); | 1737 is_remote, is_streaming, is_suspended, is_backgrounded); |
1727 SetDelegateState(state.delegate_state); | 1738 SetDelegateState(state.delegate_state, state.is_idle); |
1728 SetMemoryReportingState(state.is_memory_reporting_enabled); | 1739 SetMemoryReportingState(state.is_memory_reporting_enabled); |
1729 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); | 1740 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); |
1730 } | 1741 } |
1731 | 1742 |
1732 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { | 1743 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state, |
1744 bool is_idle) { | |
1733 if (!delegate_) | 1745 if (!delegate_) |
1734 return; | 1746 return; |
1735 | 1747 |
1736 if (delegate_state_ == new_state) { | 1748 switch (new_state) { |
1737 if (delegate_state_ != DelegateState::PLAYING || | |
1738 autoplay_muted_ == client_->isAutoplayingMuted()) { | |
1739 return; | |
1740 } | |
1741 } | |
1742 | |
1743 delegate_state_ = new_state; | |
1744 | |
1745 switch (delegate_state_) { | |
1746 case DelegateState::GONE: | 1749 case DelegateState::GONE: |
1747 delegate_->PlayerGone(delegate_id_); | 1750 delegate_->PlayerGone(delegate_id_); |
1748 break; | 1751 break; |
1749 case DelegateState::PLAYING: { | 1752 case DelegateState::PLAYING: { |
1750 autoplay_muted_ = client_->isAutoplayingMuted(); | 1753 bool has_audio = hasAudio() && !client_->isAutoplayingMuted(); |
1751 bool has_audio = autoplay_muted_ ? false : hasAudio(); | |
1752 delegate_->DidPlay( | 1754 delegate_->DidPlay( |
1753 delegate_id_, hasVideo(), has_audio, false, | 1755 delegate_id_, has_audio, hasVideo(), |
1754 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); | 1756 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); |
1755 break; | 1757 break; |
1756 } | 1758 } |
1757 case DelegateState::PAUSED: | 1759 case DelegateState::PAUSED: |
1758 delegate_->DidPause(delegate_id_, false); | 1760 delegate_->DidPause(delegate_id_); |
1759 break; | |
1760 case DelegateState::ENDED: | |
1761 delegate_->DidPause(delegate_id_, true); | |
1762 break; | 1761 break; |
1763 } | 1762 } |
1763 | |
1764 delegate_->SetIdle(delegate_id_, is_idle); | |
1764 } | 1765 } |
1765 | 1766 |
1766 void WebMediaPlayerImpl::SetMemoryReportingState( | 1767 void WebMediaPlayerImpl::SetMemoryReportingState( |
1767 bool is_memory_reporting_enabled) { | 1768 bool is_memory_reporting_enabled) { |
1768 if (memory_usage_reporting_timer_.IsRunning() == | 1769 if (memory_usage_reporting_timer_.IsRunning() == |
1769 is_memory_reporting_enabled) { | 1770 is_memory_reporting_enabled) { |
1770 return; | 1771 return; |
1771 } | 1772 } |
1772 | 1773 |
1773 if (is_memory_reporting_enabled) { | 1774 if (is_memory_reporting_enabled) { |
(...skipping 25 matching lines...) Expand all Loading... | |
1799 can_suspend_state_ = | 1800 can_suspend_state_ = |
1800 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME) | 1801 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME) |
1801 ? CanSuspendState::NO | 1802 ? CanSuspendState::NO |
1802 : CanSuspendState::YES; | 1803 : CanSuspendState::YES; |
1803 } | 1804 } |
1804 } | 1805 } |
1805 #else | 1806 #else |
1806 can_suspend_state_ = CanSuspendState::YES; | 1807 can_suspend_state_ = CanSuspendState::YES; |
1807 #endif | 1808 #endif |
1808 | 1809 |
1809 if (can_suspend_state_ == CanSuspendState::NO) | 1810 if (is_suspended && can_suspend_state_ != CanSuspendState::NO) { |
1810 return; | 1811 // If we were not resumed for long enough to satisfy the preroll attempt, |
1811 | 1812 // reset the clock. |
1812 if (is_suspended) { | 1813 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) { |
1814 preroll_attempt_pending_ = true; | |
1815 preroll_attempt_start_time_ = base::TimeTicks(); | |
1816 } | |
1813 pipeline_controller_.Suspend(); | 1817 pipeline_controller_.Suspend(); |
1814 } else { | 1818 } else { |
1819 // When resuming, start the preroll attempt clock. | |
1820 if (preroll_attempt_pending_) { | |
1821 preroll_attempt_pending_ = false; | |
1822 preroll_attempt_start_time_ = tick_clock_->NowTicks(); | |
1823 } | |
1815 pipeline_controller_.Resume(); | 1824 pipeline_controller_.Resume(); |
1816 } | 1825 } |
1817 } | 1826 } |
1818 | 1827 |
1819 WebMediaPlayerImpl::PlayState | 1828 WebMediaPlayerImpl::PlayState |
1820 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote, | 1829 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote, |
1821 bool is_streaming, | 1830 bool is_streaming, |
1822 bool is_suspended, | 1831 bool is_suspended, |
1823 bool is_backgrounded) { | 1832 bool is_backgrounded) { |
1824 PlayState result; | 1833 PlayState result; |
1825 | 1834 |
1835 bool must_suspend = delegate_->IsFrameClosed(); | |
1836 bool is_stale = delegate_->IsStale(delegate_id_); | |
1837 | |
1826 // This includes both data source (before pipeline startup) and pipeline | 1838 // This includes both data source (before pipeline startup) and pipeline |
1827 // errors. | 1839 // errors. |
1828 bool has_error = IsNetworkStateError(network_state_); | 1840 bool has_error = IsNetworkStateError(network_state_); |
1829 | 1841 |
1830 // After HaveMetadata, we know which tracks are present and the duration. | 1842 // After HaveMetadata, we know which tracks are present and the duration. |
1831 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata; | 1843 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata; |
1832 | 1844 |
1833 // After HaveFutureData, Blink will call play() if the state is not paused; | 1845 // After HaveFutureData, Blink will call play() if the state is not paused; |
1834 // prior to this point |paused_| is not accurate. | 1846 // prior to this point |paused_| is not accurate. |
1835 bool have_future_data = | 1847 bool have_future_data = |
1836 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; | 1848 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; |
1837 | 1849 |
1838 // Background suspend is not enabled for audio-only players unless paused, | 1850 // Background suspend is not enabled for audio-only players unless paused, |
1839 // though in the case of audio-only the session should be kept. | 1851 // though in the case of audio-only the session should be kept. |
1840 // Videos are not suspended if the user resumed the playback via the remote | 1852 // Videos are not suspended if the user resumed the playback via the remote |
1841 // controls earlier and it's still playing. | 1853 // controls earlier and it's still playing. |
1842 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); | 1854 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); |
1843 bool can_play_backgrounded = is_backgrounded_video && !is_remote && | 1855 bool can_play_backgrounded = is_backgrounded_video && !is_remote && |
1844 hasAudio() && IsResumeBackgroundVideosEnabled(); | 1856 hasAudio() && |
1845 bool is_background_playing = | 1857 IsResumeBackgroundVideosEnabled() && delegate_ && |
1846 delegate_ && delegate_->IsPlayingBackgroundVideo(); | 1858 delegate_->IsBackgroundVideoPlaybackAllowed(); |
1847 bool background_suspended = !is_streaming && is_backgrounded_video && | 1859 bool background_suspended = |
1848 !(can_play_backgrounded && is_background_playing); | 1860 !is_streaming && is_backgrounded_video && !can_play_backgrounded; |
1849 bool background_pause_suspended = | 1861 bool background_pause_suspended = |
1850 !is_streaming && is_backgrounded && paused_ && have_future_data; | 1862 !is_streaming && is_backgrounded && paused_ && have_future_data; |
1851 | 1863 |
1852 // Idle suspension is allowed prior to have future data since there exist | 1864 // Idle suspension is allowed prior to have future data since there exist |
1853 // mechanisms to exit the idle state when the player is capable of reaching | 1865 // mechanisms to exit the idle state when the player is capable of reaching |
1854 // the have future data state; see didLoadingProgress(). | 1866 // the have future data state; see didLoadingProgress(). |
1855 // | 1867 // |
1856 // TODO(sandersd): Make the delegate suspend idle players immediately when | 1868 // TODO(sandersd): Make the delegate suspend idle players immediately when |
1857 // hidden. | 1869 // hidden. |
1858 bool idle_suspended = | 1870 bool idle_suspended = |
1859 !is_streaming && is_idle_ && paused_ && !seeking_ && !overlay_enabled_; | 1871 !is_streaming && is_stale && paused_ && !seeking_ && !overlay_enabled_; |
1860 | 1872 |
1861 // If we're already suspended, see if we can wait for user interaction. Prior | 1873 // If we're already suspended, see if we can wait for user interaction. Prior |
1862 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_| | 1874 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale| |
1863 // will be cleared when we receive data which may take us to HaveFutureData. | 1875 // will be cleared when we receive data which may take us to HaveFutureData. |
1864 bool can_stay_suspended = | 1876 bool can_stay_suspended = |
1865 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_; | 1877 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_; |
1866 | 1878 |
1867 // Combined suspend state. | 1879 // Combined suspend state. |
1868 result.is_suspended = is_remote || must_suspend_ || idle_suspended || | 1880 result.is_suspended = is_remote || must_suspend || idle_suspended || |
1869 background_suspended || background_pause_suspended || | 1881 background_suspended || background_pause_suspended || |
1870 can_stay_suspended; | 1882 can_stay_suspended; |
1871 | 1883 |
1872 // We do not treat |playback_rate_| == 0 as paused. For the media session, | 1884 // We do not treat |playback_rate_| == 0 as paused. For the media session, |
1873 // being paused implies displaying a play button, which is incorrect in this | 1885 // being paused implies displaying a play button, which is incorrect in this |
1874 // case. For memory usage reporting, we just use the same definition (but we | 1886 // case. For memory usage reporting, we just use the same definition (but we |
1875 // don't have to). | 1887 // don't have to). |
1876 // | 1888 // |
1877 // Similarly, we don't consider |ended_| to be paused. Blink will immediately | 1889 // Similarly, we don't consider |ended_| to be paused. Blink will immediately |
1878 // call pause() or seek(), so |ended_| should not affect the computation. | 1890 // call pause() or seek(), so |ended_| should not affect the computation. |
1879 // Despite that, |ended_| does result in a separate paused state, to simplfy | 1891 // Despite that, |ended_| does result in a separate paused state, to simplfy |
1880 // the contract for SetDelegateState(). | 1892 // the contract for SetDelegateState(). |
1881 // | 1893 // |
1882 // |has_session| is used to decide when to create a media session. Idle | 1894 // |has_session| is used to decide when to create a media session. Idle |
1883 // suspension does not destroy the media session, because we expect that the | 1895 // suspension does not destroy the media session, because we expect that the |
1884 // notification controls (and audio focus) remain. We also require: | 1896 // notification controls (and audio focus) remain. We also require: |
1885 // - |have_metadata|, since the tracks and duration are passed to DidPlay(). | 1897 // - |have_metadata|, since the tracks and duration are passed to DidPlay(). |
1886 // - |have_future_data|, since we need to know whether we are paused to | 1898 // - |have_future_data|, since we need to know whether we are paused to |
1887 // correctly configure the session. | 1899 // correctly configure the session. |
1888 // | 1900 // |
1889 // TODO(sandersd): If Blink told us the paused state sooner, we could create | 1901 // TODO(sandersd): If Blink told us the paused state sooner, we could create |
1890 // the media session sooner. | 1902 // the media session sooner. |
1891 bool can_play = !has_error && !is_remote && have_future_data; | 1903 bool can_play = !has_error && !is_remote && have_future_data; |
1892 bool has_session_playing = | 1904 bool has_session_playing = can_play && !must_suspend && !background_suspended; |
1893 can_play && !must_suspend_ && !background_suspended; | |
1894 | 1905 |
1895 // |has_session_suspended| means the player is suspended from the media | 1906 // |has_session_suspended| means the player is suspended from the media |
1896 // element point of view but paused and can be resumed from the delegate point | 1907 // element point of view but paused and can be resumed from the delegate point |
1897 // of view. Therefore it behaves like |paused_| for the delegate. | 1908 // of view. Therefore it behaves like |paused_| for the delegate. |
1898 bool has_session_suspended = can_play && !must_suspend_ && | 1909 bool has_session_suspended = can_play && !must_suspend && |
1899 background_suspended && can_play_backgrounded; | 1910 background_suspended && can_play_backgrounded; |
whywhat
2016/12/12 18:11:23
hm, I don't think background_suspended will ever b
sandersd (OOO until July 31)
2017/01/05 23:12:21
Original computation restored.
| |
1900 | 1911 |
1901 bool has_session = has_session_playing || has_session_suspended; | 1912 bool has_session = has_session_playing || has_session_suspended; |
1902 | 1913 |
1903 if (!has_session) { | 1914 if (!has_session) { |
1904 result.delegate_state = DelegateState::GONE; | 1915 result.delegate_state = DelegateState::GONE; |
1916 result.is_idle = delegate_ && delegate_->IsIdle(delegate_id_); | |
1905 } else if (paused_ || has_session_suspended) { | 1917 } else if (paused_ || has_session_suspended) { |
1918 // TODO(sandersd): Is it possible to have a suspended session, be ended, | |
1919 // and not be paused? If so we should be in a PLAYING state. | |
1906 result.delegate_state = | 1920 result.delegate_state = |
1907 ended_ ? DelegateState::ENDED : DelegateState::PAUSED; | 1921 ended_ ? DelegateState::GONE : DelegateState::PAUSED; |
1922 result.is_idle = !seeking_; | |
1908 } else { | 1923 } else { |
1909 result.delegate_state = DelegateState::PLAYING; | 1924 result.delegate_state = DelegateState::PLAYING; |
1925 result.is_idle = false; | |
1910 } | 1926 } |
1911 | 1927 |
1912 // It's not critical if some cases where memory usage can change are missed, | 1928 // It's not critical if some cases where memory usage can change are missed, |
1913 // since media memory changes are usually gradual. | 1929 // since media memory changes are usually gradual. |
1914 result.is_memory_reporting_enabled = | 1930 result.is_memory_reporting_enabled = |
1915 can_play && !result.is_suspended && !paused_; | 1931 can_play && !result.is_suspended && (!paused_ || seeking_); |
1916 | 1932 |
1917 return result; | 1933 return result; |
1918 } | 1934 } |
1919 | 1935 |
1920 void WebMediaPlayerImpl::ReportMemoryUsage() { | 1936 void WebMediaPlayerImpl::ReportMemoryUsage() { |
1921 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1937 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1922 | 1938 |
1923 // About base::Unretained() usage below: We destroy |demuxer_| on the main | 1939 // About base::Unretained() usage below: We destroy |demuxer_| on the main |
1924 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the | 1940 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the |
1925 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task | 1941 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1973 this, &WebMediaPlayerImpl::OnPause); | 1989 this, &WebMediaPlayerImpl::OnPause); |
1974 } | 1990 } |
1975 | 1991 |
1976 void WebMediaPlayerImpl::CreateWatchTimeReporter() { | 1992 void WebMediaPlayerImpl::CreateWatchTimeReporter() { |
1977 // Create the watch time reporter and synchronize its initial state. | 1993 // Create the watch time reporter and synchronize its initial state. |
1978 watch_time_reporter_.reset(new WatchTimeReporter( | 1994 watch_time_reporter_.reset(new WatchTimeReporter( |
1979 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, | 1995 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, |
1980 pipeline_metadata_.natural_size, | 1996 pipeline_metadata_.natural_size, |
1981 base::Bind(&GetCurrentTimeInternal, this))); | 1997 base::Bind(&GetCurrentTimeInternal, this))); |
1982 watch_time_reporter_->OnVolumeChange(volume_); | 1998 watch_time_reporter_->OnVolumeChange(volume_); |
1983 if (IsHidden()) | 1999 if (delegate_ && delegate_->IsFrameHidden()) |
1984 watch_time_reporter_->OnHidden(); | 2000 watch_time_reporter_->OnHidden(); |
1985 else | 2001 else |
1986 watch_time_reporter_->OnShown(); | 2002 watch_time_reporter_->OnShown(); |
1987 } | 2003 } |
1988 | 2004 |
1989 bool WebMediaPlayerImpl::IsHidden() const { | 2005 bool WebMediaPlayerImpl::IsHidden() const { |
1990 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 2006 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1991 | 2007 |
1992 return delegate_ && delegate_->IsHidden(); | 2008 return delegate_ && delegate_->IsFrameHidden() && !delegate_->IsFrameClosed(); |
1993 } | 2009 } |
1994 | 2010 |
1995 } // namespace media | 2011 } // namespace media |
OLD | NEW |