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 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 // TODO(dalecurtis): Technically this allows seeking on media which return an | 747 // TODO(dalecurtis): Technically this allows seeking on media which return an |
748 // infinite duration so long as DataSource::IsStreaming() is false. While not | 748 // infinite duration so long as DataSource::IsStreaming() is false. While not |
749 // expected, disabling this breaks semi-live players, http://crbug.com/427412. | 749 // expected, disabling this breaks semi-live players, http://crbug.com/427412. |
750 const blink::WebTimeRange seekable_range( | 750 const blink::WebTimeRange seekable_range( |
751 0.0, allow_seek_to_zero ? 0.0 : seekable_end); | 751 0.0, allow_seek_to_zero ? 0.0 : seekable_end); |
752 return blink::WebTimeRanges(&seekable_range, 1); | 752 return blink::WebTimeRanges(&seekable_range, 1); |
753 } | 753 } |
754 | 754 |
755 bool WebMediaPlayerImpl::didLoadingProgress() { | 755 bool WebMediaPlayerImpl::didLoadingProgress() { |
756 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 756 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
757 bool pipeline_progress = pipeline_.DidLoadingProgress(); | 757 |
758 bool data_progress = buffered_data_source_host_.DidLoadingProgress(); | 758 // Note: Separate variables used to ensure both methods are called every time. |
759 return pipeline_progress || data_progress; | 759 const bool pipeline_progress = pipeline_.DidLoadingProgress(); |
| 760 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); |
| 761 const bool did_loading_progress = pipeline_progress || data_progress; |
| 762 |
| 763 // If we've idle suspended before reaching kHaveFutureData and loading has |
| 764 // progressed we need to spin up the renderer and figure out if we have enough |
| 765 // data yet; |client_| may be waiting on this signal to trigger playback. The |
| 766 // idle timeout is long enough that this is a low-cost operation. |
| 767 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData && |
| 768 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) { |
| 769 is_idle_ = false; |
| 770 UpdatePlayState(); |
| 771 } |
| 772 |
| 773 return did_loading_progress; |
760 } | 774 } |
761 | 775 |
762 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, | 776 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, |
763 const blink::WebRect& rect, | 777 const blink::WebRect& rect, |
764 unsigned char alpha, | 778 unsigned char alpha, |
765 SkXfermode::Mode mode) { | 779 SkXfermode::Mode mode) { |
766 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 780 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
767 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); | 781 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); |
768 | 782 |
769 if (is_cdm_attached_) | 783 if (is_cdm_attached_) |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 | 1247 |
1234 must_suspend_ = false; | 1248 must_suspend_ = false; |
1235 background_pause_timer_.Stop(); | 1249 background_pause_timer_.Stop(); |
1236 | 1250 |
1237 UpdatePlayState(); | 1251 UpdatePlayState(); |
1238 } | 1252 } |
1239 | 1253 |
1240 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { | 1254 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { |
1241 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1255 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
1242 | 1256 |
1243 if (must_suspend) { | 1257 if (must_suspend) |
1244 must_suspend_ = true; | 1258 must_suspend_ = true; |
1245 } else { | 1259 else |
1246 // TODO(sandersd): Remove this when idleness is separate from play state. | |
1247 if (delegate_state_ == DelegateState::PAUSED_BUT_NOT_IDLE) | |
1248 return; | |
1249 is_idle_ = true; | 1260 is_idle_ = true; |
1250 } | |
1251 | 1261 |
1252 UpdatePlayState(); | 1262 UpdatePlayState(); |
1253 } | 1263 } |
1254 | 1264 |
1255 void WebMediaPlayerImpl::OnPlay() { | 1265 void WebMediaPlayerImpl::OnPlay() { |
1256 play(); | 1266 play(); |
1257 client_->playbackStateChanged(); | 1267 client_->playbackStateChanged(); |
1258 } | 1268 } |
1259 | 1269 |
1260 void WebMediaPlayerImpl::OnPause() { | 1270 void WebMediaPlayerImpl::OnPause() { |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 bool is_backgrounded = | 1570 bool is_backgrounded = |
1561 IsBackgroundedSuspendEnabled() && delegate_ && delegate_->IsHidden(); | 1571 IsBackgroundedSuspendEnabled() && delegate_ && delegate_->IsHidden(); |
1562 PlayState state = UpdatePlayState_ComputePlayState(is_remote, is_suspended, | 1572 PlayState state = UpdatePlayState_ComputePlayState(is_remote, is_suspended, |
1563 is_backgrounded); | 1573 is_backgrounded); |
1564 SetDelegateState(state.delegate_state); | 1574 SetDelegateState(state.delegate_state); |
1565 SetMemoryReportingState(state.is_memory_reporting_enabled); | 1575 SetMemoryReportingState(state.is_memory_reporting_enabled); |
1566 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); | 1576 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); |
1567 } | 1577 } |
1568 | 1578 |
1569 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { | 1579 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { |
1570 if (!delegate_ || delegate_state_ == new_state) | 1580 if (!delegate_) |
| 1581 return; |
| 1582 |
| 1583 // Dedupe state changes in the general case, but make an exception for gone |
| 1584 // since the delegate will use that information to decide when the idle timer |
| 1585 // should be fired. |
| 1586 if (delegate_state_ == new_state && new_state != DelegateState::GONE) |
1571 return; | 1587 return; |
1572 | 1588 |
1573 delegate_state_ = new_state; | 1589 delegate_state_ = new_state; |
1574 | 1590 |
1575 switch (delegate_state_) { | 1591 switch (delegate_state_) { |
1576 case DelegateState::GONE: | 1592 case DelegateState::GONE: |
1577 delegate_->PlayerGone(delegate_id_); | 1593 delegate_->PlayerGone(delegate_id_); |
1578 break; | 1594 break; |
1579 case DelegateState::PLAYING: | 1595 case DelegateState::PLAYING: |
1580 delegate_->DidPlay( | 1596 delegate_->DidPlay( |
1581 delegate_id_, hasVideo(), hasAudio(), false, | 1597 delegate_id_, hasVideo(), hasAudio(), false, |
1582 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); | 1598 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); |
1583 break; | 1599 break; |
1584 case DelegateState::PAUSED: | 1600 case DelegateState::PAUSED: |
1585 delegate_->DidPause(delegate_id_, false); | 1601 delegate_->DidPause(delegate_id_, false); |
1586 break; | 1602 break; |
1587 case DelegateState::PAUSED_BUT_NOT_IDLE: | |
1588 // It doesn't really matter what happens when we enter this state, only | |
1589 // that we reset the idle timer when leaving it. | |
1590 // | |
1591 // TODO(sandersd): Ideally the delegate would consider idleness and play | |
1592 // state as orthogonal properties so that we could avoid this. | |
1593 delegate_->DidPause(delegate_id_, false); | |
1594 break; | |
1595 case DelegateState::ENDED: | 1603 case DelegateState::ENDED: |
1596 delegate_->DidPause(delegate_id_, true); | 1604 delegate_->DidPause(delegate_id_, true); |
1597 break; | 1605 break; |
1598 } | 1606 } |
1599 } | 1607 } |
1600 | 1608 |
1601 void WebMediaPlayerImpl::SetMemoryReportingState( | 1609 void WebMediaPlayerImpl::SetMemoryReportingState( |
1602 bool is_memory_reporting_enabled) { | 1610 bool is_memory_reporting_enabled) { |
1603 if (memory_usage_reporting_timer_.IsRunning() == | 1611 if (memory_usage_reporting_timer_.IsRunning() == |
1604 is_memory_reporting_enabled) { | 1612 is_memory_reporting_enabled) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 // though in the case of audio-only the session should be kept. | 1679 // though in the case of audio-only the session should be kept. |
1672 // Videos are not suspended if the user resumed the playback via the remote | 1680 // Videos are not suspended if the user resumed the playback via the remote |
1673 // controls earlier and it's still playing. | 1681 // controls earlier and it's still playing. |
1674 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); | 1682 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); |
1675 bool can_play_backgrounded = is_backgrounded_video && !is_remote && | 1683 bool can_play_backgrounded = is_backgrounded_video && !is_remote && |
1676 hasAudio() && IsResumeBackgroundVideosEnabled(); | 1684 hasAudio() && IsResumeBackgroundVideosEnabled(); |
1677 bool is_background_playing = | 1685 bool is_background_playing = |
1678 delegate_ && delegate_->IsPlayingBackgroundVideo(); | 1686 delegate_ && delegate_->IsPlayingBackgroundVideo(); |
1679 bool background_suspended = is_backgrounded_video && | 1687 bool background_suspended = is_backgrounded_video && |
1680 !(can_play_backgrounded && is_background_playing); | 1688 !(can_play_backgrounded && is_background_playing); |
| 1689 bool background_pause_suspended = is_backgrounded && paused_; |
1681 | 1690 |
1682 // The |paused_| state is not reliable until we |have_future_data|. | |
1683 bool background_pause_suspended = | |
1684 is_backgrounded && have_future_data && paused_; | |
1685 | |
1686 // Idle suspend is enabled once there is future data. We don't want to idle | |
1687 // suspend before that because play() may never be triggered to leave the idle | |
1688 // state. There could be other theoretical problems if the page is waiting for | |
1689 // other events before actually calling play(), but at least we don't break | |
1690 // Blink. | |
1691 // | |
1692 // TODO(sandersd): Make the delegate suspend idle players immediately when | 1691 // TODO(sandersd): Make the delegate suspend idle players immediately when |
1693 // hidden. | 1692 // hidden. |
1694 // TODO(sandersd): If Blink told us the paused state sooner, we could | 1693 bool idle_suspended = is_idle_ && paused_ && !seeking_ && !overlay_enabled_; |
1695 // idle suspend sooner. | 1694 |
1696 bool idle_suspended = is_idle_ && have_future_data; | 1695 // If we're already suspended, see if we can wait for user interaction. Prior |
| 1696 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_| |
| 1697 // will be cleared when we receive data which may take us to HaveFutureData. |
| 1698 bool can_stay_suspended = |
| 1699 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_; |
1697 | 1700 |
1698 // Combined suspend state. | 1701 // Combined suspend state. |
1699 result.is_suspended = | 1702 result.is_suspended = is_remote || must_suspend_ || idle_suspended || |
1700 is_remote || must_suspend_ || idle_suspended || background_suspended || | 1703 background_suspended || background_pause_suspended || |
1701 background_pause_suspended || | 1704 can_stay_suspended; |
1702 // If we're already suspended, see if we can wait for user interaction. | |
1703 (is_suspended && have_future_data && paused_ && !seeking_); | |
1704 | 1705 |
1705 // We do not treat |playback_rate_| == 0 as paused. For the media session, | 1706 // We do not treat |playback_rate_| == 0 as paused. For the media session, |
1706 // being paused implies displaying a play button, which is incorrect in this | 1707 // being paused implies displaying a play button, which is incorrect in this |
1707 // case. For memory usage reporting, we just use the same definition (but we | 1708 // case. For memory usage reporting, we just use the same definition (but we |
1708 // don't have to). | 1709 // don't have to). |
1709 // | 1710 // |
1710 // Similarly, we don't consider |ended_| to be paused. Blink will immediately | 1711 // Similarly, we don't consider |ended_| to be paused. Blink will immediately |
1711 // call pause() or seek(), so |ended_| should not affect the computation. | 1712 // call pause() or seek(), so |ended_| should not affect the computation. |
1712 // Despite that, |ended_| does result in a separate paused state, to simplfy | 1713 // Despite that, |ended_| does result in a separate paused state, to simplfy |
1713 // the contract for SetDelegateState(). | 1714 // the contract for SetDelegateState(). |
(...skipping 15 matching lines...) Expand all Loading... |
1729 // element point of view but paused and can be resumed from the delegate point | 1730 // element point of view but paused and can be resumed from the delegate point |
1730 // of view. Therefore it behaves like |paused_| for the delegate. | 1731 // of view. Therefore it behaves like |paused_| for the delegate. |
1731 bool has_session_suspended = can_play && !must_suspend_ && | 1732 bool has_session_suspended = can_play && !must_suspend_ && |
1732 background_suspended && can_play_backgrounded; | 1733 background_suspended && can_play_backgrounded; |
1733 | 1734 |
1734 bool has_session = has_session_playing || has_session_suspended; | 1735 bool has_session = has_session_playing || has_session_suspended; |
1735 | 1736 |
1736 if (!has_session) { | 1737 if (!has_session) { |
1737 result.delegate_state = DelegateState::GONE; | 1738 result.delegate_state = DelegateState::GONE; |
1738 } else if (paused_ || has_session_suspended) { | 1739 } else if (paused_ || has_session_suspended) { |
1739 if (seeking() || overlay_enabled_) { | 1740 result.delegate_state = |
1740 result.delegate_state = DelegateState::PAUSED_BUT_NOT_IDLE; | 1741 ended_ ? DelegateState::ENDED : DelegateState::PAUSED; |
1741 } else if (ended_) { | |
1742 result.delegate_state = DelegateState::ENDED; | |
1743 } else { | |
1744 result.delegate_state = DelegateState::PAUSED; | |
1745 } | |
1746 } else { | 1742 } else { |
1747 result.delegate_state = DelegateState::PLAYING; | 1743 result.delegate_state = DelegateState::PLAYING; |
1748 } | 1744 } |
1749 | 1745 |
1750 // It's not critical if some cases where memory usage can change are missed, | 1746 // It's not critical if some cases where memory usage can change are missed, |
1751 // since media memory changes are usually gradual. | 1747 // since media memory changes are usually gradual. |
1752 result.is_memory_reporting_enabled = | 1748 result.is_memory_reporting_enabled = |
1753 can_play && !result.is_suspended && !paused_; | 1749 can_play && !result.is_suspended && !paused_; |
1754 | 1750 |
1755 return result; | 1751 return result; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1789 << ", Video: " << stats.video_memory_usage << ", DataSource: " | 1785 << ", Video: " << stats.video_memory_usage << ", DataSource: " |
1790 << (data_source_ ? data_source_->GetMemoryUsage() : 0) | 1786 << (data_source_ ? data_source_->GetMemoryUsage() : 0) |
1791 << ", Demuxer: " << demuxer_memory_usage; | 1787 << ", Demuxer: " << demuxer_memory_usage; |
1792 | 1788 |
1793 const int64_t delta = current_memory_usage - last_reported_memory_usage_; | 1789 const int64_t delta = current_memory_usage - last_reported_memory_usage_; |
1794 last_reported_memory_usage_ = current_memory_usage; | 1790 last_reported_memory_usage_ = current_memory_usage; |
1795 adjust_allocated_memory_cb_.Run(delta); | 1791 adjust_allocated_memory_cb_.Run(delta); |
1796 } | 1792 } |
1797 | 1793 |
1798 void WebMediaPlayerImpl::ScheduleIdlePauseTimer() { | 1794 void WebMediaPlayerImpl::ScheduleIdlePauseTimer() { |
1799 // Only schedule the pause timer if we're playing and are suspended. We use | 1795 // Only schedule the pause timer if we're playing and are suspended. |
1800 // delegate state as a proxy for suspended here since the suspension may be in | 1796 if (paused_ || !pipeline_controller_.IsSuspended()) |
1801 // flight at the time of this call. | |
1802 if (paused_ || delegate_state_ != DelegateState::GONE) | |
1803 return; | 1797 return; |
1804 | 1798 |
1805 #if defined(OS_ANDROID) | 1799 #if defined(OS_ANDROID) |
1806 // Remote players will be suspended and locally paused. | 1800 // Remote players will be suspended and locally paused. |
1807 if (isRemote()) | 1801 if (isRemote()) |
1808 return; | 1802 return; |
1809 #endif | 1803 #endif |
1810 | 1804 |
1811 // Idle timeout chosen arbitrarily. | 1805 // Idle timeout chosen arbitrarily. |
1812 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), | 1806 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), |
1813 this, &WebMediaPlayerImpl::OnPause); | 1807 this, &WebMediaPlayerImpl::OnPause); |
1814 } | 1808 } |
1815 | 1809 |
1816 void WebMediaPlayerImpl::CreateWatchTimeReporter() { | 1810 void WebMediaPlayerImpl::CreateWatchTimeReporter() { |
1817 // Create the watch time reporter and synchronize its initial state. | 1811 // Create the watch time reporter and synchronize its initial state. |
1818 watch_time_reporter_.reset(new WatchTimeReporter( | 1812 watch_time_reporter_.reset(new WatchTimeReporter( |
1819 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, | 1813 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, |
1820 pipeline_metadata_.natural_size, | 1814 pipeline_metadata_.natural_size, |
1821 base::Bind(&GetCurrentTimeInternal, this))); | 1815 base::Bind(&GetCurrentTimeInternal, this))); |
1822 watch_time_reporter_->OnVolumeChange(volume_); | 1816 watch_time_reporter_->OnVolumeChange(volume_); |
1823 if (delegate_ && delegate_->IsHidden()) | 1817 if (delegate_ && delegate_->IsHidden()) |
1824 watch_time_reporter_->OnHidden(); | 1818 watch_time_reporter_->OnHidden(); |
1825 else | 1819 else |
1826 watch_time_reporter_->OnShown(); | 1820 watch_time_reporter_->OnShown(); |
1827 } | 1821 } |
1828 | 1822 |
1829 } // namespace media | 1823 } // namespace media |
OLD | NEW |