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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h" | 56 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h" |
57 #include "third_party/WebKit/public/platform/WebMediaSource.h" | 57 #include "third_party/WebKit/public/platform/WebMediaSource.h" |
58 #include "third_party/WebKit/public/platform/WebRect.h" | 58 #include "third_party/WebKit/public/platform/WebRect.h" |
59 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" | 59 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" |
60 #include "third_party/WebKit/public/platform/WebSize.h" | 60 #include "third_party/WebKit/public/platform/WebSize.h" |
61 #include "third_party/WebKit/public/platform/WebString.h" | 61 #include "third_party/WebKit/public/platform/WebString.h" |
62 #include "third_party/WebKit/public/platform/WebURL.h" | 62 #include "third_party/WebKit/public/platform/WebURL.h" |
63 #include "third_party/WebKit/public/web/WebDocument.h" | 63 #include "third_party/WebKit/public/web/WebDocument.h" |
64 #include "third_party/WebKit/public/web/WebFrame.h" | 64 #include "third_party/WebKit/public/web/WebFrame.h" |
65 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 65 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 66 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
66 #include "third_party/WebKit/public/web/WebView.h" | 67 #include "third_party/WebKit/public/web/WebView.h" |
67 | 68 |
68 #if defined(OS_ANDROID) | 69 #if defined(OS_ANDROID) |
69 #include "media/base/android/media_codec_util.h" | 70 #include "media/base/android/media_codec_util.h" |
70 #endif | 71 #endif |
71 | 72 |
72 using blink::WebCanvas; | 73 using blink::WebCanvas; |
73 using blink::WebMediaPlayer; | 74 using blink::WebMediaPlayer; |
74 using blink::WebRect; | 75 using blink::WebRect; |
75 using blink::WebSize; | 76 using blink::WebSize; |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 | 411 |
411 #if defined(OS_ANDROID) // WMPI_CAST | 412 #if defined(OS_ANDROID) // WMPI_CAST |
412 cast_impl_.Initialize(url, frame_, delegate_id_); | 413 cast_impl_.Initialize(url, frame_, delegate_id_); |
413 #endif | 414 #endif |
414 } | 415 } |
415 | 416 |
416 void WebMediaPlayerImpl::play() { | 417 void WebMediaPlayerImpl::play() { |
417 DVLOG(1) << __func__; | 418 DVLOG(1) << __func__; |
418 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 419 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
419 | 420 |
| 421 // User initiated play unlocks background video playback. |
| 422 if (blink::WebUserGestureIndicator::isProcessingUserGesture()) |
| 423 video_locked_when_paused_when_hidden_ = false; |
| 424 |
420 #if defined(OS_ANDROID) // WMPI_CAST | 425 #if defined(OS_ANDROID) // WMPI_CAST |
421 if (isRemote()) { | 426 if (isRemote()) { |
422 cast_impl_.play(); | 427 cast_impl_.play(); |
423 return; | 428 return; |
424 } | 429 } |
425 #endif | 430 #endif |
426 // TODO(sandersd): Do we want to reset the idle timer here? | 431 // TODO(sandersd): Do we want to reset the idle timer here? |
427 delegate_->SetIdle(delegate_id_, false); | 432 delegate_->SetIdle(delegate_id_, false); |
428 paused_ = false; | 433 paused_ = false; |
429 pipeline_.SetPlaybackRate(playback_rate_); | 434 pipeline_.SetPlaybackRate(playback_rate_); |
(...skipping 16 matching lines...) Expand all Loading... |
446 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 451 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
447 | 452 |
448 // We update the paused state even when casting, since we expect pause() to be | 453 // We update the paused state even when casting, since we expect pause() to be |
449 // called when casting begins, and when we exit casting we should end up in a | 454 // called when casting begins, and when we exit casting we should end up in a |
450 // paused state. | 455 // paused state. |
451 paused_ = true; | 456 paused_ = true; |
452 | 457 |
453 // No longer paused because it was hidden. | 458 // No longer paused because it was hidden. |
454 paused_when_hidden_ = false; | 459 paused_when_hidden_ = false; |
455 | 460 |
| 461 // User initiated pause locks background videos. |
| 462 if (blink::WebUserGestureIndicator::isProcessingUserGesture()) |
| 463 video_locked_when_paused_when_hidden_ = true; |
| 464 |
456 #if defined(OS_ANDROID) // WMPI_CAST | 465 #if defined(OS_ANDROID) // WMPI_CAST |
457 if (isRemote()) { | 466 if (isRemote()) { |
458 cast_impl_.pause(); | 467 cast_impl_.pause(); |
459 return; | 468 return; |
460 } | 469 } |
461 #endif | 470 #endif |
462 | 471 |
463 pipeline_.SetPlaybackRate(0.0); | 472 pipeline_.SetPlaybackRate(0.0); |
464 | 473 |
465 // pause() may be called after playback has ended and the HTMLMediaElement | 474 // pause() may be called after playback has ended and the HTMLMediaElement |
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1420 video_weblayer_->layer()->SetContentsOpaque(opaque_); | 1429 video_weblayer_->layer()->SetContentsOpaque(opaque_); |
1421 } | 1430 } |
1422 | 1431 |
1423 void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() { | 1432 void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() { |
1424 UpdateBackgroundVideoOptimizationState(); | 1433 UpdateBackgroundVideoOptimizationState(); |
1425 } | 1434 } |
1426 | 1435 |
1427 void WebMediaPlayerImpl::OnFrameHidden() { | 1436 void WebMediaPlayerImpl::OnFrameHidden() { |
1428 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1437 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1429 | 1438 |
| 1439 // Backgrounding a video requires a user gesture to resume playback. |
| 1440 if (IsHidden()) |
| 1441 video_locked_when_paused_when_hidden_ = true; |
| 1442 |
1430 if (watch_time_reporter_) | 1443 if (watch_time_reporter_) |
1431 watch_time_reporter_->OnHidden(); | 1444 watch_time_reporter_->OnHidden(); |
1432 | 1445 |
1433 // OnFrameHidden() can be called when frame is closed, then IsHidden() will | 1446 UpdateBackgroundVideoOptimizationState(); |
1434 // return false, so check explicitly. | |
1435 if (IsHidden()) { | |
1436 if (ShouldPauseVideoWhenHidden()) { | |
1437 PauseVideoIfNeeded(); | |
1438 return; | |
1439 } else { | |
1440 DisableVideoTrackIfNeeded(); | |
1441 } | |
1442 } | |
1443 | |
1444 UpdatePlayState(); | 1447 UpdatePlayState(); |
1445 | 1448 |
1446 // Schedule suspended playing media to be paused if the user doesn't come back | 1449 // Schedule suspended playing media to be paused if the user doesn't come back |
1447 // to it within some timeout period to avoid any autoplay surprises. | 1450 // to it within some timeout period to avoid any autoplay surprises. |
1448 ScheduleIdlePauseTimer(); | 1451 ScheduleIdlePauseTimer(); |
1449 } | 1452 } |
1450 | 1453 |
1451 void WebMediaPlayerImpl::OnFrameClosed() { | 1454 void WebMediaPlayerImpl::OnFrameClosed() { |
1452 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1455 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1453 UpdatePlayState(); | 1456 UpdatePlayState(); |
1454 } | 1457 } |
1455 | 1458 |
1456 void WebMediaPlayerImpl::OnFrameShown() { | 1459 void WebMediaPlayerImpl::OnFrameShown() { |
1457 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1460 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1458 background_pause_timer_.Stop(); | 1461 background_pause_timer_.Stop(); |
1459 | 1462 |
| 1463 // Foreground videos don't require user gesture to continue playback. |
| 1464 video_locked_when_paused_when_hidden_ = false; |
| 1465 |
1460 if (watch_time_reporter_) | 1466 if (watch_time_reporter_) |
1461 watch_time_reporter_->OnShown(); | 1467 watch_time_reporter_->OnShown(); |
1462 | 1468 |
1463 // Only track the time to the first frame if playing or about to play because | 1469 // Only track the time to the first frame if playing or about to play because |
1464 // of being shown and only for videos we would optimize background playback | 1470 // of being shown and only for videos we would optimize background playback |
1465 // for. | 1471 // for. |
1466 if ((!paused_ && IsBackgroundOptimizationCandidate()) || | 1472 if ((!paused_ && IsBackgroundOptimizationCandidate()) || |
1467 paused_when_hidden_) { | 1473 paused_when_hidden_) { |
1468 VideoFrameCompositor::OnNewProcessedFrameCB new_processed_frame_cb = | 1474 VideoFrameCompositor::OnNewProcessedFrameCB new_processed_frame_cb = |
1469 BindToCurrentLoop(base::Bind( | 1475 BindToCurrentLoop(base::Bind( |
1470 &WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame, | 1476 &WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame, |
1471 AsWeakPtr(), base::TimeTicks::Now())); | 1477 AsWeakPtr(), base::TimeTicks::Now())); |
1472 compositor_task_runner_->PostTask( | 1478 compositor_task_runner_->PostTask( |
1473 FROM_HERE, | 1479 FROM_HERE, |
1474 base::Bind(&VideoFrameCompositor::SetOnNewProcessedFrameCallback, | 1480 base::Bind(&VideoFrameCompositor::SetOnNewProcessedFrameCallback, |
1475 base::Unretained(compositor_), new_processed_frame_cb)); | 1481 base::Unretained(compositor_), new_processed_frame_cb)); |
1476 } | 1482 } |
1477 | 1483 |
| 1484 EnableVideoTrackIfNeeded(); |
| 1485 |
1478 if (paused_when_hidden_) { | 1486 if (paused_when_hidden_) { |
1479 paused_when_hidden_ = false; | 1487 paused_when_hidden_ = false; |
1480 OnPlay(); // Calls UpdatePlayState() so return afterwards. | 1488 OnPlay(); // Calls UpdatePlayState() so return afterwards. |
1481 return; | 1489 return; |
1482 } | 1490 } |
1483 | 1491 |
1484 EnableVideoTrackIfNeeded(); | |
1485 | |
1486 UpdatePlayState(); | 1492 UpdatePlayState(); |
1487 } | 1493 } |
1488 | 1494 |
1489 void WebMediaPlayerImpl::OnIdleTimeout() { | 1495 void WebMediaPlayerImpl::OnIdleTimeout() { |
1490 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1496 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1491 | 1497 |
1492 // If we are attempting preroll, clear the stale flag. | 1498 // If we are attempting preroll, clear the stale flag. |
1493 if (IsPrerollAttemptNeeded()) { | 1499 if (IsPrerollAttemptNeeded()) { |
1494 delegate_->ClearStaleFlag(delegate_id_); | 1500 delegate_->ClearStaleFlag(delegate_id_); |
1495 return; | 1501 return; |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1940 bool is_backgrounded) { | 1946 bool is_backgrounded) { |
1941 PlayState result; | 1947 PlayState result; |
1942 | 1948 |
1943 bool must_suspend = delegate_->IsFrameClosed(); | 1949 bool must_suspend = delegate_->IsFrameClosed(); |
1944 bool is_stale = delegate_->IsStale(delegate_id_); | 1950 bool is_stale = delegate_->IsStale(delegate_id_); |
1945 | 1951 |
1946 // This includes both data source (before pipeline startup) and pipeline | 1952 // This includes both data source (before pipeline startup) and pipeline |
1947 // errors. | 1953 // errors. |
1948 bool has_error = IsNetworkStateError(network_state_); | 1954 bool has_error = IsNetworkStateError(network_state_); |
1949 | 1955 |
1950 // After HaveMetadata, we know which tracks are present and the duration. | |
1951 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata; | |
1952 | |
1953 // After HaveFutureData, Blink will call play() if the state is not paused; | 1956 // After HaveFutureData, Blink will call play() if the state is not paused; |
1954 // prior to this point |paused_| is not accurate. | 1957 // prior to this point |paused_| is not accurate. |
1955 bool have_future_data = | 1958 bool have_future_data = |
1956 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; | 1959 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; |
1957 | 1960 |
1958 // Background suspend is not enabled for audio-only players unless paused, | 1961 // Background suspend is only enabled for paused players. |
1959 // though in the case of audio-only the session should be kept. | 1962 // In the case of players with audio the session should be kept. |
1960 // Videos are not suspended if the user resumed the playback via the remote | 1963 bool background_suspended = |
1961 // controls earlier and it's still playing. | |
1962 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); | |
1963 bool can_play_backgrounded = is_backgrounded_video && !is_remote && | |
1964 hasAudio() && IsResumeBackgroundVideosEnabled(); | |
1965 bool is_background_playing = delegate_->IsBackgroundVideoPlaybackUnlocked(); | |
1966 bool background_suspended = can_auto_suspend && is_backgrounded_video && | |
1967 !(can_play_backgrounded && is_background_playing); | |
1968 bool background_pause_suspended = | |
1969 can_auto_suspend && is_backgrounded && paused_ && have_future_data; | 1964 can_auto_suspend && is_backgrounded && paused_ && have_future_data; |
1970 | 1965 |
1971 // Idle suspension is allowed prior to have future data since there exist | 1966 // Idle suspension is allowed prior to have future data since there exist |
1972 // mechanisms to exit the idle state when the player is capable of reaching | 1967 // mechanisms to exit the idle state when the player is capable of reaching |
1973 // the have future data state; see didLoadingProgress(). | 1968 // the have future data state; see didLoadingProgress(). |
1974 // | 1969 // |
1975 // TODO(sandersd): Make the delegate suspend idle players immediately when | 1970 // TODO(sandersd): Make the delegate suspend idle players immediately when |
1976 // hidden. | 1971 // hidden. |
1977 bool idle_suspended = | 1972 bool idle_suspended = |
1978 can_auto_suspend && is_stale && paused_ && !seeking_ && !overlay_enabled_; | 1973 can_auto_suspend && is_stale && paused_ && !seeking_ && !overlay_enabled_; |
1979 | 1974 |
1980 // If we're already suspended, see if we can wait for user interaction. Prior | 1975 // If we're already suspended, see if we can wait for user interaction. Prior |
1981 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale| | 1976 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale| |
1982 // will be cleared when we receive data which may take us to HaveFutureData. | 1977 // will be cleared when we receive data which may take us to HaveFutureData. |
1983 bool can_stay_suspended = | 1978 bool can_stay_suspended = |
1984 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_; | 1979 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_; |
1985 | 1980 |
1986 // Combined suspend state. | 1981 // Combined suspend state. |
1987 result.is_suspended = is_remote || must_suspend || idle_suspended || | 1982 result.is_suspended = is_remote || must_suspend || idle_suspended || |
1988 background_suspended || background_pause_suspended || | 1983 background_suspended || can_stay_suspended; |
1989 can_stay_suspended; | |
1990 | 1984 |
1991 // We do not treat |playback_rate_| == 0 as paused. For the media session, | 1985 // We do not treat |playback_rate_| == 0 as paused. For the media session, |
1992 // being paused implies displaying a play button, which is incorrect in this | 1986 // being paused implies displaying a play button, which is incorrect in this |
1993 // case. For memory usage reporting, we just use the same definition (but we | 1987 // case. For memory usage reporting, we just use the same definition (but we |
1994 // don't have to). | 1988 // don't have to). |
1995 // | 1989 // |
1996 // Similarly, we don't consider |ended_| to be paused. Blink will immediately | 1990 // Similarly, we don't consider |ended_| to be paused. Blink will immediately |
1997 // call pause() or seek(), so |ended_| should not affect the computation. | 1991 // call pause() or seek(), so |ended_| should not affect the computation. |
1998 // Despite that, |ended_| does result in a separate paused state, to simplfy | 1992 // Despite that, |ended_| does result in a separate paused state, to simplfy |
1999 // the contract for SetDelegateState(). | 1993 // the contract for SetDelegateState(). |
2000 // | 1994 // |
2001 // |has_session| is used to decide when to create a media session. Idle | 1995 // |has_remote_controls| indicates if the player can be controlled outside the |
| 1996 // page (e.g. via the notification controls or by audio focus events). Idle |
2002 // suspension does not destroy the media session, because we expect that the | 1997 // suspension does not destroy the media session, because we expect that the |
2003 // notification controls (and audio focus) remain. We also require: | 1998 // notification controls (and audio focus) remain. The following must be true |
2004 // - |have_metadata|, since the tracks and duration are passed to DidPlay(). | 1999 // for the player to have remote controls: |
2005 // - |have_future_data|, since we need to know whether we are paused to | 2000 // - |have_future_data|, since we need to know whether we are paused to |
2006 // correctly configure the session. | 2001 // correctly configure the session and also because the tracks and |
| 2002 // duration are passed to DidPlay() |
| 2003 // - |is_remote| is false as remote players have their own controls |
| 2004 // - |has_error| is false player should have no errors |
| 2005 // - hasAudio() (requires |have_future_data|) |
2007 // | 2006 // |
2008 // TODO(sandersd): If Blink told us the paused state sooner, we could create | 2007 // TODO(sandersd): If Blink told us the paused state sooner, we could detect |
2009 // the media session sooner. | 2008 // if the remote controls are available sooner. |
| 2009 |
| 2010 // Background videos with audio don't have remote controls if background |
| 2011 // suspend is enabled and resuming background videos is not (original Android |
| 2012 // behavior). |
| 2013 bool backgrounded_video_has_no_remote_controls = |
| 2014 IsBackgroundedSuspendEnabled() && !IsResumeBackgroundVideosEnabled() && |
| 2015 is_backgrounded && hasVideo(); |
2010 bool can_play = !has_error && !is_remote && have_future_data; | 2016 bool can_play = !has_error && !is_remote && have_future_data; |
2011 bool has_session_playing = can_play && !must_suspend && !background_suspended; | 2017 bool has_remote_controls = can_play && !must_suspend && hasAudio() && |
| 2018 !backgrounded_video_has_no_remote_controls; |
2012 | 2019 |
2013 // |has_session_suspended| means the player is suspended from the media | 2020 if (!has_remote_controls) { |
2014 // element point of view but paused and can be resumed from the delegate point | |
2015 // of view. Therefore it behaves like |paused_| for the delegate. | |
2016 bool has_session_suspended = can_play && !must_suspend && | |
2017 background_suspended && can_play_backgrounded; | |
2018 | |
2019 bool has_session = has_session_playing || has_session_suspended; | |
2020 | |
2021 if (!has_session) { | |
2022 result.delegate_state = DelegateState::GONE; | 2021 result.delegate_state = DelegateState::GONE; |
2023 result.is_idle = delegate_->IsIdle(delegate_id_); | 2022 result.is_idle = delegate_->IsIdle(delegate_id_); |
2024 } else if (paused_ || has_session_suspended) { | 2023 } else if (paused_) { |
2025 // TODO(sandersd): Is it possible to have a suspended session, be ended, | 2024 // TODO(sandersd): Is it possible to have a suspended session, be ended, |
2026 // and not be paused? If so we should be in a PLAYING state. | 2025 // and not be paused? If so we should be in a PLAYING state. |
2027 result.delegate_state = | 2026 result.delegate_state = |
2028 ended_ ? DelegateState::GONE : DelegateState::PAUSED; | 2027 ended_ ? DelegateState::GONE : DelegateState::PAUSED; |
2029 result.is_idle = !seeking_; | 2028 result.is_idle = !seeking_; |
2030 } else { | 2029 } else { |
2031 result.delegate_state = DelegateState::PLAYING; | 2030 result.delegate_state = DelegateState::PLAYING; |
2032 result.is_idle = false; | 2031 result.is_idle = false; |
2033 } | 2032 } |
2034 | 2033 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2092 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource", | 2091 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource", |
2093 data_source_memory_usage / 1024); | 2092 data_source_memory_usage / 1024); |
2094 } | 2093 } |
2095 if (demuxer_) { | 2094 if (demuxer_) { |
2096 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Demuxer", | 2095 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Demuxer", |
2097 demuxer_memory_usage / 1024); | 2096 demuxer_memory_usage / 1024); |
2098 } | 2097 } |
2099 } | 2098 } |
2100 | 2099 |
2101 void WebMediaPlayerImpl::ScheduleIdlePauseTimer() { | 2100 void WebMediaPlayerImpl::ScheduleIdlePauseTimer() { |
2102 // Only schedule the pause timer if we're playing and are suspended. | 2101 // Only schedule the pause timer if we're not paused or paused but going to |
2103 if (paused_ || !pipeline_controller_.IsSuspended()) | 2102 // resume when foregrounded, and are suspended. |
| 2103 if ((paused_ && !paused_when_hidden_) || !pipeline_controller_.IsSuspended()) |
2104 return; | 2104 return; |
2105 | 2105 |
2106 #if defined(OS_ANDROID) | 2106 #if defined(OS_ANDROID) |
2107 // Remote players will be suspended and locally paused. | 2107 // Remote players will be suspended and locally paused. |
2108 if (isRemote()) | 2108 if (isRemote()) |
2109 return; | 2109 return; |
2110 #endif | 2110 #endif |
2111 | 2111 |
2112 // Idle timeout chosen arbitrarily. | 2112 // Idle timeout chosen arbitrarily. |
2113 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), | 2113 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), |
(...skipping 27 matching lines...) Expand all Loading... |
2141 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0; | 2141 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0; |
2142 } | 2142 } |
2143 | 2143 |
2144 void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) { | 2144 void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) { |
2145 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 2145 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
2146 | 2146 |
2147 client_->activateViewportIntersectionMonitoring(activate); | 2147 client_->activateViewportIntersectionMonitoring(activate); |
2148 } | 2148 } |
2149 | 2149 |
2150 bool WebMediaPlayerImpl::ShouldPauseVideoWhenHidden() const { | 2150 bool WebMediaPlayerImpl::ShouldPauseVideoWhenHidden() const { |
2151 #if !defined(OS_ANDROID) | 2151 // If suspending background video, pause any video that's not remoted or |
2152 // On desktop, this behavior is behind the feature flag. | 2152 // not unlocked to play in the background. |
2153 if (!IsBackgroundVideoTrackOptimizationEnabled()) | 2153 if (IsBackgroundedSuspendEnabled()) { |
2154 return false; | 2154 if (!hasVideo()) |
| 2155 return false; |
| 2156 |
| 2157 #if defined(OS_ANDROID) |
| 2158 if (isRemote()) |
| 2159 return false; |
2155 #endif | 2160 #endif |
2156 | 2161 |
2157 // Pause video-only players that match the criteria for being optimized. | 2162 return !hasAudio() || |
2158 return !hasAudio() && IsBackgroundOptimizationCandidate(); | 2163 (IsResumeBackgroundVideosEnabled() && |
| 2164 video_locked_when_paused_when_hidden_); |
| 2165 } |
| 2166 |
| 2167 // Otherwise only pause if the optimization is on and it's a video-only |
| 2168 // optimization candidate. |
| 2169 return IsBackgroundVideoTrackOptimizationEnabled() && !hasAudio() && |
| 2170 IsBackgroundOptimizationCandidate(); |
2159 } | 2171 } |
2160 | 2172 |
2161 bool WebMediaPlayerImpl::ShouldDisableVideoWhenHidden() const { | 2173 bool WebMediaPlayerImpl::ShouldDisableVideoWhenHidden() const { |
2162 // This optimization is behind the flag on all platforms. | 2174 // This optimization is behind the flag on all platforms. |
2163 if (!IsBackgroundVideoTrackOptimizationEnabled()) | 2175 if (!IsBackgroundVideoTrackOptimizationEnabled()) |
2164 return false; | 2176 return false; |
2165 | 2177 |
2166 // Disable video track only for players with audio that match the criteria for | 2178 // Disable video track only for players with audio that match the criteria for |
2167 // being optimized. | 2179 // being optimized. |
2168 return hasAudio() && IsBackgroundOptimizationCandidate(); | 2180 return hasAudio() && IsBackgroundOptimizationCandidate(); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2279 base::TimeDelta time_to_first_frame = new_frame_time - foreground_time; | 2291 base::TimeDelta time_to_first_frame = new_frame_time - foreground_time; |
2280 if (hasAudio()) { | 2292 if (hasAudio()) { |
2281 UMA_HISTOGRAM_TIMES( | 2293 UMA_HISTOGRAM_TIMES( |
2282 "Media.Video.TimeFromForegroundToFirstFrame.DisableTrack", | 2294 "Media.Video.TimeFromForegroundToFirstFrame.DisableTrack", |
2283 time_to_first_frame); | 2295 time_to_first_frame); |
2284 } else { | 2296 } else { |
2285 UMA_HISTOGRAM_TIMES("Media.Video.TimeFromForegroundToFirstFrame.Paused", | 2297 UMA_HISTOGRAM_TIMES("Media.Video.TimeFromForegroundToFirstFrame.Paused", |
2286 time_to_first_frame); | 2298 time_to_first_frame); |
2287 } | 2299 } |
2288 } | 2300 } |
2289 | |
2290 void WebMediaPlayerImpl::SwitchRenderer(bool disable_pipeline_auto_suspend) { | 2301 void WebMediaPlayerImpl::SwitchRenderer(bool disable_pipeline_auto_suspend) { |
2291 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 2302 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
2292 disable_pipeline_auto_suspend_ = disable_pipeline_auto_suspend; | 2303 disable_pipeline_auto_suspend_ = disable_pipeline_auto_suspend; |
2293 ScheduleRestart(); | 2304 ScheduleRestart(); |
2294 } | 2305 } |
2295 | 2306 |
2296 void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) { | 2307 void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) { |
2297 DCHECK(data_source_ || chunk_demuxer_); | 2308 DCHECK(data_source_ || chunk_demuxer_); |
2298 if (data_source_) | 2309 if (data_source_) |
2299 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", duration); | 2310 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", duration); |
2300 else | 2311 else |
2301 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration); | 2312 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration); |
2302 } | 2313 } |
2303 | 2314 |
2304 } // namespace media | 2315 } // namespace media |
OLD | NEW |