Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: media/blink/webmediaplayer_impl.cc

Issue 2355143002: Merge M54: "Allow suspension prior to reaching kHaveFutureData." (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/blink/webmediaplayer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 // TODO(dalecurtis): Technically this allows seeking on media which return an 742 // TODO(dalecurtis): Technically this allows seeking on media which return an
743 // infinite duration so long as DataSource::IsStreaming() is false. While not 743 // infinite duration so long as DataSource::IsStreaming() is false. While not
744 // expected, disabling this breaks semi-live players, http://crbug.com/427412. 744 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
745 const blink::WebTimeRange seekable_range( 745 const blink::WebTimeRange seekable_range(
746 0.0, allow_seek_to_zero ? 0.0 : seekable_end); 746 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
747 return blink::WebTimeRanges(&seekable_range, 1); 747 return blink::WebTimeRanges(&seekable_range, 1);
748 } 748 }
749 749
750 bool WebMediaPlayerImpl::didLoadingProgress() { 750 bool WebMediaPlayerImpl::didLoadingProgress() {
751 DCHECK(main_task_runner_->BelongsToCurrentThread()); 751 DCHECK(main_task_runner_->BelongsToCurrentThread());
752 bool pipeline_progress = pipeline_.DidLoadingProgress(); 752
753 bool data_progress = buffered_data_source_host_.DidLoadingProgress(); 753 // Note: Separate variables used to ensure both methods are called every time.
754 return pipeline_progress || data_progress; 754 const bool pipeline_progress = pipeline_.DidLoadingProgress();
755 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
756 const bool did_loading_progress = pipeline_progress || data_progress;
757
758 // If we've idle suspended before reaching kHaveFutureData and loading has
759 // progressed we need to spin up the renderer and figure out if we have enough
760 // data yet; |client_| may be waiting on this signal to trigger playback. The
761 // idle timeout is long enough that this is a low-cost operation.
762 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData &&
763 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) {
764 is_idle_ = false;
765 UpdatePlayState();
766 }
767
768 return did_loading_progress;
755 } 769 }
756 770
757 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, 771 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
758 const blink::WebRect& rect, 772 const blink::WebRect& rect,
759 unsigned char alpha, 773 unsigned char alpha,
760 SkXfermode::Mode mode) { 774 SkXfermode::Mode mode) {
761 DCHECK(main_task_runner_->BelongsToCurrentThread()); 775 DCHECK(main_task_runner_->BelongsToCurrentThread());
762 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); 776 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
763 777
764 if (is_cdm_attached_) 778 if (is_cdm_attached_)
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 1218
1205 must_suspend_ = false; 1219 must_suspend_ = false;
1206 background_pause_timer_.Stop(); 1220 background_pause_timer_.Stop();
1207 1221
1208 UpdatePlayState(); 1222 UpdatePlayState();
1209 } 1223 }
1210 1224
1211 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { 1225 void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
1212 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1226 DCHECK(main_task_runner_->BelongsToCurrentThread());
1213 1227
1214 if (must_suspend) { 1228 if (must_suspend)
1215 must_suspend_ = true; 1229 must_suspend_ = true;
1216 } else { 1230 else
1217 // TODO(sandersd): Remove this when idleness is separate from play state.
1218 if (delegate_state_ == DelegateState::PAUSED_BUT_NOT_IDLE)
1219 return;
1220 is_idle_ = true; 1231 is_idle_ = true;
1221 }
1222 1232
1223 UpdatePlayState(); 1233 UpdatePlayState();
1224 } 1234 }
1225 1235
1226 void WebMediaPlayerImpl::OnPlay() { 1236 void WebMediaPlayerImpl::OnPlay() {
1227 play(); 1237 play();
1228 client_->playbackStateChanged(); 1238 client_->playbackStateChanged();
1229 } 1239 }
1230 1240
1231 void WebMediaPlayerImpl::OnPause() { 1241 void WebMediaPlayerImpl::OnPause() {
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 bool is_backgrounded = 1541 bool is_backgrounded =
1532 IsBackgroundedSuspendEnabled() && delegate_ && delegate_->IsHidden(); 1542 IsBackgroundedSuspendEnabled() && delegate_ && delegate_->IsHidden();
1533 PlayState state = UpdatePlayState_ComputePlayState(is_remote, is_suspended, 1543 PlayState state = UpdatePlayState_ComputePlayState(is_remote, is_suspended,
1534 is_backgrounded); 1544 is_backgrounded);
1535 SetDelegateState(state.delegate_state); 1545 SetDelegateState(state.delegate_state);
1536 SetMemoryReportingState(state.is_memory_reporting_enabled); 1546 SetMemoryReportingState(state.is_memory_reporting_enabled);
1537 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); 1547 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1538 } 1548 }
1539 1549
1540 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { 1550 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) {
1541 if (!delegate_ || delegate_state_ == new_state) 1551 if (!delegate_)
1552 return;
1553
1554 // Dedupe state changes in the general case, but make an exception for gone
1555 // since the delegate will use that information to decide when the idle timer
1556 // should be fired.
1557 if (delegate_state_ == new_state && new_state != DelegateState::GONE)
1542 return; 1558 return;
1543 1559
1544 delegate_state_ = new_state; 1560 delegate_state_ = new_state;
1545 1561
1546 switch (delegate_state_) { 1562 switch (delegate_state_) {
1547 case DelegateState::GONE: 1563 case DelegateState::GONE:
1548 delegate_->PlayerGone(delegate_id_); 1564 delegate_->PlayerGone(delegate_id_);
1549 break; 1565 break;
1550 case DelegateState::PLAYING: 1566 case DelegateState::PLAYING:
1551 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false, 1567 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1552 pipeline_.GetMediaDuration()); 1568 pipeline_.GetMediaDuration());
1553 break; 1569 break;
1554 case DelegateState::PAUSED: 1570 case DelegateState::PAUSED:
1555 delegate_->DidPause(delegate_id_, false); 1571 delegate_->DidPause(delegate_id_, false);
1556 break; 1572 break;
1557 case DelegateState::PAUSED_BUT_NOT_IDLE:
1558 // It doesn't really matter what happens when we enter this state, only
1559 // that we reset the idle timer when leaving it.
1560 //
1561 // TODO(sandersd): Ideally the delegate would consider idleness and play
1562 // state as orthogonal properties so that we could avoid this.
1563 delegate_->DidPause(delegate_id_, false);
1564 break;
1565 case DelegateState::ENDED: 1573 case DelegateState::ENDED:
1566 delegate_->DidPause(delegate_id_, true); 1574 delegate_->DidPause(delegate_id_, true);
1567 break; 1575 break;
1568 } 1576 }
1569 } 1577 }
1570 1578
1571 void WebMediaPlayerImpl::SetMemoryReportingState( 1579 void WebMediaPlayerImpl::SetMemoryReportingState(
1572 bool is_memory_reporting_enabled) { 1580 bool is_memory_reporting_enabled) {
1573 if (memory_usage_reporting_timer_.IsRunning() == 1581 if (memory_usage_reporting_timer_.IsRunning() ==
1574 is_memory_reporting_enabled) { 1582 is_memory_reporting_enabled) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 // though in the case of audio-only the session should be kept. 1649 // though in the case of audio-only the session should be kept.
1642 // Videos are not suspended if the user resumed the playback via the remote 1650 // Videos are not suspended if the user resumed the playback via the remote
1643 // controls earlier and it's still playing. 1651 // controls earlier and it's still playing.
1644 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); 1652 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo();
1645 bool can_play_backgrounded = is_backgrounded_video && !is_remote && 1653 bool can_play_backgrounded = is_backgrounded_video && !is_remote &&
1646 hasAudio() && IsResumeBackgroundVideosEnabled(); 1654 hasAudio() && IsResumeBackgroundVideosEnabled();
1647 bool is_background_playing = 1655 bool is_background_playing =
1648 delegate_ && delegate_->IsPlayingBackgroundVideo(); 1656 delegate_ && delegate_->IsPlayingBackgroundVideo();
1649 bool background_suspended = is_backgrounded_video && 1657 bool background_suspended = is_backgrounded_video &&
1650 !(can_play_backgrounded && is_background_playing); 1658 !(can_play_backgrounded && is_background_playing);
1659 bool background_pause_suspended = is_backgrounded && paused_;
1651 1660
1652 // The |paused_| state is not reliable until we |have_future_data|.
1653 bool background_pause_suspended =
1654 is_backgrounded && have_future_data && paused_;
1655
1656 // Idle suspend is enabled once there is future data. We don't want to idle
1657 // suspend before that because play() may never be triggered to leave the idle
1658 // state. There could be other theoretical problems if the page is waiting for
1659 // other events before actually calling play(), but at least we don't break
1660 // Blink.
1661 //
1662 // TODO(sandersd): Make the delegate suspend idle players immediately when 1661 // TODO(sandersd): Make the delegate suspend idle players immediately when
1663 // hidden. 1662 // hidden.
1664 // TODO(sandersd): If Blink told us the paused state sooner, we could 1663 bool idle_suspended = is_idle_ && paused_ && !seeking_ && !overlay_enabled_;
1665 // idle suspend sooner. 1664
1666 bool idle_suspended = is_idle_ && have_future_data; 1665 // If we're already suspended, see if we can wait for user interaction. Prior
1666 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_|
1667 // will be cleared when we receive data which may take us to HaveFutureData.
1668 bool can_stay_suspended =
1669 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_;
1667 1670
1668 // Combined suspend state. 1671 // Combined suspend state.
1669 result.is_suspended = 1672 result.is_suspended = is_remote || must_suspend_ || idle_suspended ||
1670 is_remote || must_suspend_ || idle_suspended || background_suspended || 1673 background_suspended || background_pause_suspended ||
1671 background_pause_suspended || 1674 can_stay_suspended;
1672 // If we're already suspended, see if we can wait for user interaction.
1673 (is_suspended && have_future_data && paused_ && !seeking_);
1674 1675
1675 // We do not treat |playback_rate_| == 0 as paused. For the media session, 1676 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1676 // being paused implies displaying a play button, which is incorrect in this 1677 // being paused implies displaying a play button, which is incorrect in this
1677 // case. For memory usage reporting, we just use the same definition (but we 1678 // case. For memory usage reporting, we just use the same definition (but we
1678 // don't have to). 1679 // don't have to).
1679 // 1680 //
1680 // Similarly, we don't consider |ended_| to be paused. Blink will immediately 1681 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1681 // call pause() or seek(), so |ended_| should not affect the computation. 1682 // call pause() or seek(), so |ended_| should not affect the computation.
1682 // Despite that, |ended_| does result in a separate paused state, to simplfy 1683 // Despite that, |ended_| does result in a separate paused state, to simplfy
1683 // the contract for SetDelegateState(). 1684 // the contract for SetDelegateState().
(...skipping 15 matching lines...) Expand all
1699 // element point of view but paused and can be resumed from the delegate point 1700 // element point of view but paused and can be resumed from the delegate point
1700 // of view. Therefore it behaves like |paused_| for the delegate. 1701 // of view. Therefore it behaves like |paused_| for the delegate.
1701 bool has_session_suspended = can_play && !must_suspend_ && 1702 bool has_session_suspended = can_play && !must_suspend_ &&
1702 background_suspended && can_play_backgrounded; 1703 background_suspended && can_play_backgrounded;
1703 1704
1704 bool has_session = has_session_playing || has_session_suspended; 1705 bool has_session = has_session_playing || has_session_suspended;
1705 1706
1706 if (!has_session) { 1707 if (!has_session) {
1707 result.delegate_state = DelegateState::GONE; 1708 result.delegate_state = DelegateState::GONE;
1708 } else if (paused_ || has_session_suspended) { 1709 } else if (paused_ || has_session_suspended) {
1709 if (seeking() || overlay_enabled_) { 1710 result.delegate_state =
1710 result.delegate_state = DelegateState::PAUSED_BUT_NOT_IDLE; 1711 ended_ ? DelegateState::ENDED : DelegateState::PAUSED;
1711 } else if (ended_) {
1712 result.delegate_state = DelegateState::ENDED;
1713 } else {
1714 result.delegate_state = DelegateState::PAUSED;
1715 }
1716 } else { 1712 } else {
1717 result.delegate_state = DelegateState::PLAYING; 1713 result.delegate_state = DelegateState::PLAYING;
1718 } 1714 }
1719 1715
1720 // It's not critical if some cases where memory usage can change are missed, 1716 // It's not critical if some cases where memory usage can change are missed,
1721 // since media memory changes are usually gradual. 1717 // since media memory changes are usually gradual.
1722 result.is_memory_reporting_enabled = 1718 result.is_memory_reporting_enabled =
1723 can_play && !result.is_suspended && !paused_; 1719 can_play && !result.is_suspended && !paused_;
1724 1720
1725 return result; 1721 return result;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1759 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1755 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1760 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1756 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1761 << ", Demuxer: " << demuxer_memory_usage; 1757 << ", Demuxer: " << demuxer_memory_usage;
1762 1758
1763 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1759 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1764 last_reported_memory_usage_ = current_memory_usage; 1760 last_reported_memory_usage_ = current_memory_usage;
1765 adjust_allocated_memory_cb_.Run(delta); 1761 adjust_allocated_memory_cb_.Run(delta);
1766 } 1762 }
1767 1763
1768 void WebMediaPlayerImpl::ScheduleIdlePauseTimer() { 1764 void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
1769 // Only schedule the pause timer if we're playing and are suspended. We use 1765 // Only schedule the pause timer if we're playing and are suspended.
1770 // delegate state as a proxy for suspended here since the suspension may be in 1766 if (paused_ || !pipeline_controller_.IsSuspended())
1771 // flight at the time of this call.
1772 if (paused_ || delegate_state_ != DelegateState::GONE)
1773 return; 1767 return;
1774 1768
1775 #if defined(OS_ANDROID) 1769 #if defined(OS_ANDROID)
1776 // Remote players will be suspended and locally paused. 1770 // Remote players will be suspended and locally paused.
1777 if (isRemote()) 1771 if (isRemote())
1778 return; 1772 return;
1779 #endif 1773 #endif
1780 1774
1781 // Idle timeout chosen arbitrarily. 1775 // Idle timeout chosen arbitrarily.
1782 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), 1776 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
1783 this, &WebMediaPlayerImpl::OnPause); 1777 this, &WebMediaPlayerImpl::OnPause);
1784 } 1778 }
1785 1779
1786 void WebMediaPlayerImpl::CreateWatchTimeReporter() { 1780 void WebMediaPlayerImpl::CreateWatchTimeReporter() {
1787 // Create the watch time reporter and synchronize its initial state. 1781 // Create the watch time reporter and synchronize its initial state.
1788 watch_time_reporter_.reset(new WatchTimeReporter( 1782 watch_time_reporter_.reset(new WatchTimeReporter(
1789 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, 1783 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_,
1790 pipeline_metadata_.natural_size, 1784 pipeline_metadata_.natural_size,
1791 base::Bind(&GetCurrentTimeInternal, this))); 1785 base::Bind(&GetCurrentTimeInternal, this)));
1792 watch_time_reporter_->OnVolumeChange(volume_); 1786 watch_time_reporter_->OnVolumeChange(volume_);
1793 if (delegate_ && delegate_->IsHidden()) 1787 if (delegate_ && delegate_->IsHidden())
1794 watch_time_reporter_->OnHidden(); 1788 watch_time_reporter_->OnHidden();
1795 else 1789 else
1796 watch_time_reporter_->OnShown(); 1790 watch_time_reporter_->OnShown();
1797 } 1791 }
1798 1792
1799 } // namespace media 1793 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/blink/webmediaplayer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698