Commit af29d418 authored by xjz's avatar xjz Committed by Commit bot

Detect change on video/viewport intersection when rendered remotely.

Peoriodically (every 1s) check whether video/viewport intersection is
changed when video is rendered remotely.

BUG=643964

Review-Url: https://codereview.chromium.org/2556333002
Cr-Commit-Position: refs/heads/master@{#438980}
parent 17c7368d
......@@ -2866,6 +2866,9 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
remoting_controller_ptr->SetSwitchRendererCallback(base::Bind(
&media::WebMediaPlayerImpl::ScheduleRestart, media_player->AsWeakPtr()));
remoting_controller_ptr->SetRemoteSinkAvailableChangedCallback(base::Bind(
&media::WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring,
media_player->AsWeakPtr()));
#endif
return media_player;
}
......
......@@ -2004,4 +2004,10 @@ bool WebMediaPlayerImpl::IsHidden() const {
return delegate_ && delegate_->IsHidden();
}
void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
client_->activateViewportIntersectionMonitoring(activate);
}
} // namespace media
......@@ -220,6 +220,10 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
// then seek to resume playback at the current position.
void ScheduleRestart();
// Called when requests to activate monitoring changes on viewport
// intersection.
void ActivateViewportIntersectionMonitoring(bool activate);
// Distinct states that |delegate_| can be in.
// TODO(sandersd): This should move into WebMediaPlayerDelegate.
// (Public for testing.)
......
......@@ -43,9 +43,29 @@ void RemotingRendererController::OnSessionStateChanged() {
DCHECK(thread_checker_.CalledOnValidThread());
VLOG(1) << "OnSessionStateChanged: " << remoting_source_->state();
if (!sink_available_changed_cb_.is_null())
sink_available_changed_cb_.Run(IsRemoteSinkAvailable());
UpdateAndMaybeSwitch();
}
bool RemotingRendererController::IsRemoteSinkAvailable() {
DCHECK(thread_checker_.CalledOnValidThread());
switch (remoting_source_->state()) {
case SESSION_CAN_START:
case SESSION_STARTING:
case SESSION_STARTED:
return true;
case SESSION_UNAVAILABLE:
case SESSION_STOPPING:
case SESSION_PERMANENTLY_STOPPED:
return false;
}
return false; // To suppress compile warning.
}
void RemotingRendererController::OnEnteredFullscreen() {
DCHECK(thread_checker_.CalledOnValidThread());
......@@ -96,6 +116,15 @@ void RemotingRendererController::SetSwitchRendererCallback(
UpdateAndMaybeSwitch();
}
void RemotingRendererController::SetRemoteSinkAvailableChangedCallback(
const base::Callback<void(bool)>& cb) {
DCHECK(thread_checker_.CalledOnValidThread());
sink_available_changed_cb_ = cb;
if (!sink_available_changed_cb_.is_null())
sink_available_changed_cb_.Run(IsRemoteSinkAvailable());
}
base::WeakPtr<remoting::RpcBroker> RemotingRendererController::GetRpcBroker()
const {
DCHECK(thread_checker_.CalledOnValidThread());
......
......@@ -41,6 +41,8 @@ class RemotingRendererController final : public RemotingSourceImpl::Client,
void OnRemotePlaybackDisabled(bool disabled) override;
void SetSwitchRendererCallback(const base::Closure& cb);
void SetRemoteSinkAvailableChangedCallback(
const base::Callback<void(bool)>& cb);
base::WeakPtr<RemotingRendererController> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
......@@ -84,6 +86,7 @@ class RemotingRendererController final : public RemotingSourceImpl::Client,
bool IsVideoCodecSupported();
bool IsAudioCodecSupported();
bool IsRemoteSinkAvailable();
// Helper to decide whether to enter or leave Remoting mode.
bool ShouldBeRemoting();
......@@ -120,6 +123,9 @@ class RemotingRendererController final : public RemotingSourceImpl::Client,
// The callback to switch the media renderer.
base::Closure switch_renderer_cb_;
// Called when remoting sink availability is changed.
base::Callback<void(bool)> sink_available_changed_cb_;
// This is initially the RemotingSourceImpl passed to the ctor, and might be
// replaced with a different instance later if OnSetCdm() is called.
scoped_refptr<RemotingSourceImpl> remoting_source_;
......
......@@ -128,6 +128,7 @@ namespace {
constexpr float kMostlyFillViewportThreshold = 0.85f;
constexpr double kMostlyFillViewportBecomeStableSeconds = 5;
constexpr double kCheckViewportIntersectionIntervalSeconds = 1;
enum MediaControlsShow {
MediaControlsShowAttribute = 0,
......@@ -370,6 +371,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName,
m_viewportFillDebouncerTimer(
this,
&HTMLMediaElement::viewportFillDebouncerTimerFired),
m_checkViewportIntersectionTimer(
this,
&HTMLMediaElement::checkViewportIntersectionTimerFired),
m_playedTimeRanges(),
m_asyncEventQueue(GenericEventQueue::create(this)),
m_playbackRate(1.0f),
......@@ -2462,8 +2466,6 @@ void HTMLMediaElement::startPlaybackProgressTimer() {
}
void HTMLMediaElement::playbackProgressTimerFired(TimerBase*) {
checkViewportIntersectionChanged();
if (!std::isnan(m_fragmentEndTime) && currentTime() >= m_fragmentEndTime &&
getDirectionOfPlayback() == Forward) {
m_fragmentEndTime = std::numeric_limits<double>::quiet_NaN();
......@@ -3302,6 +3304,7 @@ void HTMLMediaElement::updatePlayState() {
void HTMLMediaElement::stopPeriodicTimers() {
m_progressEventTimer.stop();
m_playbackProgressTimer.stop();
m_checkViewportIntersectionTimer.stop();
}
void HTMLMediaElement::
......@@ -4062,9 +4065,16 @@ DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) {
visitor->trace(m_client);
}
void HTMLMediaElement::checkViewportIntersectionChanged() {
// TODO(xjz): Early return if we not in tab mirroring.
void HTMLMediaElement::activateViewportIntersectionMonitoring(bool activate) {
if (activate && !m_checkViewportIntersectionTimer.isActive()) {
m_checkViewportIntersectionTimer.startRepeating(
kCheckViewportIntersectionIntervalSeconds, BLINK_FROM_HERE);
} else if (!activate) {
m_checkViewportIntersectionTimer.stop();
}
}
void HTMLMediaElement::checkViewportIntersectionTimerFired(TimerBase*) {
bool shouldReportRootBounds = true;
IntersectionGeometry geometry(nullptr, *this, Vector<Length>(),
shouldReportRootBounds);
......
......@@ -399,10 +399,12 @@ class CORE_EXPORT HTMLMediaElement
WebMediaPlayer::TrackId getSelectedVideoTrackId() final;
bool isAutoplayingMuted() final;
void requestReload(const WebURL&) final;
void activateViewportIntersectionMonitoring(bool) final;
void loadTimerFired(TimerBase*);
void progressEventTimerFired(TimerBase*);
void playbackProgressTimerFired(TimerBase*);
void checkViewportIntersectionTimerFired(TimerBase*);
void startPlaybackProgressTimer();
void startProgressEventTimer();
void stopPeriodicTimers();
......@@ -549,7 +551,6 @@ class CORE_EXPORT HTMLMediaElement
void onVisibilityChangedForAutoplay(bool isVisible);
void checkViewportIntersectionChanged();
void viewportFillDebouncerTimerFired(TimerBase*);
UnthrottledThreadTimer<HTMLMediaElement> m_loadTimer;
......@@ -557,6 +558,7 @@ class CORE_EXPORT HTMLMediaElement
UnthrottledThreadTimer<HTMLMediaElement> m_playbackProgressTimer;
UnthrottledThreadTimer<HTMLMediaElement> m_audioTracksTimer;
UnthrottledThreadTimer<HTMLMediaElement> m_viewportFillDebouncerTimer;
UnthrottledThreadTimer<HTMLMediaElement> m_checkViewportIntersectionTimer;
Member<TimeRanges> m_playedTimeRanges;
Member<GenericEventQueue> m_asyncEventQueue;
......
......@@ -26,7 +26,10 @@ class MediaElementFillingViewportTest : public SimTest {
}
void checkViewportIntersectionChanged(HTMLMediaElement* element) {
element->checkViewportIntersectionChanged();
element->activateViewportIntersectionMonitoring(true);
EXPECT_TRUE(element->m_checkViewportIntersectionTimer.isActive());
// TODO(xjz): Mock the time and wait for 1s instead.
element->checkViewportIntersectionTimerFired(nullptr);
}
std::unique_ptr<SimRequest> createMainResource() {
......
......@@ -262,7 +262,9 @@ class WebMediaPlayer {
virtual void exitedFullscreen() {}
// Inform WebMediaPlayer when the element starts/stops being the dominant
// visible content.
// visible content. This will only be called after the monitoring of the
// intersection with viewport is activated by calling
// WebMediaPlayerClient::activateViewportIntersectionMonitoring().
virtual void becameDominantVisibleContent(bool isDominant) {}
virtual void enabledAudioTracksChanged(
......
......@@ -95,6 +95,11 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
virtual void cancelledRemotePlaybackRequest() = 0;
virtual void remotePlaybackStarted() = 0;
// After the monitoring is activated, the client will inform WebMediaPlayer
// when the element becomes/stops being the dominant visible content by
// calling WebMediaPlayer::becameDominantVisibleContent(bool).
virtual void activateViewportIntersectionMonitoring(bool) {}
// Returns whether the media element is in an autoplay muted state.
virtual bool isAutoplayingMuted() = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment