Commit 0484f40a authored by Mounir Lamouri's avatar Mounir Lamouri Committed by Commit Bot

VideoSurfaceLayer: add flag to force frame submission regardless of visibility.

Picture-in-Picture requires submission even if the video may appear as
not visible to the frame submitter. This is adding a flag that is turned
on when a video enters Picture-in-Picture.

Bug: 865940
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I98ece11c4ad91ba2c34cafad711c50068fc91384
Reviewed-on: https://chromium-review.googlesource.com/1147542
Commit-Queue: Mounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Reviewed-by: default avatarCJ DiMeglio <lethalantidote@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577781}
parent 51ca9ce3
...@@ -208,10 +208,13 @@ void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host, ...@@ -208,10 +208,13 @@ void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() && if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() &&
pip_player_->render_frame_host == render_frame_host) { pip_player_->render_frame_host == render_frame_host) {
content::PictureInPictureWindowController::GetOrCreateForWebContents( PictureInPictureWindowControllerImpl* pip_controller =
web_contents()) PictureInPictureWindowControllerImpl::FromWebContents(
->UpdatePlaybackState(false /* is not playing */, web_contents_impl());
reached_end_of_stream); if (pip_controller) {
pip_controller->UpdatePlaybackState(false /* is not playing */,
reached_end_of_stream);
}
} }
if (removed_audio || removed_video) { if (removed_audio || removed_video) {
...@@ -260,10 +263,13 @@ void MediaWebContentsObserver::OnMediaPlaying( ...@@ -260,10 +263,13 @@ void MediaWebContentsObserver::OnMediaPlaying(
if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() && if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() &&
pip_player_->render_frame_host == render_frame_host) { pip_player_->render_frame_host == render_frame_host) {
content::PictureInPictureWindowController::GetOrCreateForWebContents( PictureInPictureWindowControllerImpl* pip_controller =
web_contents()) PictureInPictureWindowControllerImpl::FromWebContents(
->UpdatePlaybackState(true /* is playing */, web_contents_impl());
false /* reached_end_of_stream */); if (pip_controller) {
pip_controller->UpdatePlaybackState(true /* is not playing */,
false /* reached_end_of_stream */);
}
} }
// Notify observers of the new player. // Notify observers of the new player.
...@@ -349,13 +355,16 @@ void MediaWebContentsObserver::OnPictureInPictureSurfaceChanged( ...@@ -349,13 +355,16 @@ void MediaWebContentsObserver::OnPictureInPictureSurfaceChanged(
DCHECK(surface_id.is_valid()); DCHECK(surface_id.is_valid());
DCHECK(pip_player_); DCHECK(pip_player_);
pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
PictureInPictureWindowControllerImpl* pip_controller = PictureInPictureWindowControllerImpl* pip_controller =
PictureInPictureWindowControllerImpl::FromWebContents( PictureInPictureWindowControllerImpl::FromWebContents(
web_contents_impl()); web_contents_impl());
DCHECK(pip_controller);
pip_player_ = MediaPlayerId(render_frame_host, delegate_id); // The PictureInPictureWindowController instance may not have been created by
pip_controller->EmbedSurface(surface_id, natural_size); // the embedder.
if (pip_controller)
pip_controller->EmbedSurface(surface_id, natural_size);
} }
void MediaWebContentsObserver::ClearWakeLocks( void MediaWebContentsObserver::ClearWakeLocks(
......
...@@ -80,9 +80,11 @@ VideoFrameCompositor::~VideoFrameCompositor() { ...@@ -80,9 +80,11 @@ VideoFrameCompositor::~VideoFrameCompositor() {
void VideoFrameCompositor::EnableSubmission( void VideoFrameCompositor::EnableSubmission(
const viz::SurfaceId& id, const viz::SurfaceId& id,
media::VideoRotation rotation, media::VideoRotation rotation,
bool force_submit,
blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) { blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
submitter_->SetRotation(rotation); submitter_->SetRotation(rotation);
submitter_->SetForceSubmit(force_submit);
submitter_->EnableSubmission(id, std::move(frame_sink_destroyed_callback)); submitter_->EnableSubmission(id, std::move(frame_sink_destroyed_callback));
client_ = submitter_.get(); client_ = submitter_.get();
} }
...@@ -316,4 +318,8 @@ void VideoFrameCompositor::UpdateRotation(media::VideoRotation rotation) { ...@@ -316,4 +318,8 @@ void VideoFrameCompositor::UpdateRotation(media::VideoRotation rotation) {
submitter_->SetRotation(rotation); submitter_->SetRotation(rotation);
} }
void VideoFrameCompositor::SetForceSubmit(bool force_submit) {
submitter_->SetForceSubmit(force_submit);
}
} // namespace media } // namespace media
...@@ -85,6 +85,7 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink, ...@@ -85,6 +85,7 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink,
virtual void EnableSubmission( virtual void EnableSubmission(
const viz::SurfaceId& id, const viz::SurfaceId& id,
media::VideoRotation rotation, media::VideoRotation rotation,
bool force_submit,
blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback); blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback);
// cc::VideoFrameProvider implementation. These methods must be called on the // cc::VideoFrameProvider implementation. These methods must be called on the
...@@ -131,6 +132,9 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink, ...@@ -131,6 +132,9 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink,
// Updates the rotation information for frames given to |submitter_|. // Updates the rotation information for frames given to |submitter_|.
void UpdateRotation(media::VideoRotation rotation); void UpdateRotation(media::VideoRotation rotation);
// Notifies the |submitter_| that the frames must be submitted.
void SetForceSubmit(bool);
void set_tick_clock_for_testing(const base::TickClock* tick_clock) { void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
tick_clock_ = tick_clock; tick_clock_ = tick_clock;
} }
......
...@@ -34,6 +34,7 @@ class MockWebVideoFrameSubmitter : public blink::WebVideoFrameSubmitter { ...@@ -34,6 +34,7 @@ class MockWebVideoFrameSubmitter : public blink::WebVideoFrameSubmitter {
MOCK_METHOD1(Initialize, void(cc::VideoFrameProvider*)); MOCK_METHOD1(Initialize, void(cc::VideoFrameProvider*));
MOCK_METHOD1(SetRotation, void(media::VideoRotation)); MOCK_METHOD1(SetRotation, void(media::VideoRotation));
MOCK_METHOD1(UpdateSubmissionState, void(bool)); MOCK_METHOD1(UpdateSubmissionState, void(bool));
MOCK_METHOD1(SetForceSubmit, void(bool));
void DidReceiveFrame() override { ++did_receive_frame_count_; } void DidReceiveFrame() override { ++did_receive_frame_count_; }
int did_receive_frame_count() { return did_receive_frame_count_; } int did_receive_frame_count() { return did_receive_frame_count_; }
...@@ -70,9 +71,11 @@ class VideoFrameCompositorTest : public VideoRendererSink::RenderCallback, ...@@ -70,9 +71,11 @@ class VideoFrameCompositorTest : public VideoRendererSink::RenderCallback,
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_CALL(*submitter_, EXPECT_CALL(*submitter_,
SetRotation(Eq(media::VideoRotation::VIDEO_ROTATION_90))); SetRotation(Eq(media::VideoRotation::VIDEO_ROTATION_90)));
EXPECT_CALL(*submitter_, SetForceSubmit(false));
EXPECT_CALL(*submitter_, EnableSubmission(Eq(viz::SurfaceId()), _)); EXPECT_CALL(*submitter_, EnableSubmission(Eq(viz::SurfaceId()), _));
compositor_->EnableSubmission(viz::SurfaceId(), compositor_->EnableSubmission(viz::SurfaceId(),
media::VideoRotation::VIDEO_ROTATION_90, media::VideoRotation::VIDEO_ROTATION_90,
false,
base::BindRepeating([] {})); base::BindRepeating([] {}));
} }
......
...@@ -413,10 +413,7 @@ void WebMediaPlayerImpl::OnSurfaceIdUpdated(viz::SurfaceId surface_id) { ...@@ -413,10 +413,7 @@ void WebMediaPlayerImpl::OnSurfaceIdUpdated(viz::SurfaceId surface_id) {
// disabled. // disabled.
// The viz::SurfaceId may be updated when the video begins playback or when // The viz::SurfaceId may be updated when the video begins playback or when
// the size of the video changes. // the size of the video changes.
if (client_ && if (client_ && IsInPictureInPicture() && !client_->IsInAutoPIP()) {
client_->DisplayType() ==
WebMediaPlayer::DisplayType::kPictureInPicture &&
!client_->IsInAutoPIP()) {
delegate_->DidPictureInPictureSurfaceChange( delegate_->DidPictureInPictureSurfaceChange(
delegate_id_, surface_id, pipeline_metadata_.natural_size); delegate_id_, surface_id, pipeline_metadata_.natural_size);
} }
...@@ -522,6 +519,15 @@ void WebMediaPlayerImpl::OnHasNativeControlsChanged(bool has_native_controls) { ...@@ -522,6 +519,15 @@ void WebMediaPlayerImpl::OnHasNativeControlsChanged(bool has_native_controls) {
void WebMediaPlayerImpl::OnDisplayTypeChanged( void WebMediaPlayerImpl::OnDisplayTypeChanged(
WebMediaPlayer::DisplayType display_type) { WebMediaPlayer::DisplayType display_type) {
if (surface_layer_for_video_enabled_) {
vfc_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&VideoFrameCompositor::SetForceSubmit,
base::Unretained(compositor_.get()),
display_type == WebMediaPlayer::DisplayType::kPictureInPicture));
}
if (!watch_time_reporter_) if (!watch_time_reporter_)
return; return;
...@@ -812,9 +818,7 @@ void WebMediaPlayerImpl::ExitPictureInPicture( ...@@ -812,9 +818,7 @@ void WebMediaPlayerImpl::ExitPictureInPicture(
void WebMediaPlayerImpl::RegisterPictureInPictureWindowResizeCallback( void WebMediaPlayerImpl::RegisterPictureInPictureWindowResizeCallback(
blink::WebMediaPlayer::PipWindowResizedCallback callback) { blink::WebMediaPlayer::PipWindowResizedCallback callback) {
DCHECK(client_->DisplayType() == DCHECK(IsInPictureInPicture() && !client_->IsInAutoPIP());
WebMediaPlayer::DisplayType::kPictureInPicture &&
!client_->IsInAutoPIP());
delegate_->RegisterPictureInPictureWindowResizeCallback(delegate_id_, delegate_->RegisterPictureInPictureWindowResizeCallback(delegate_id_,
std::move(callback)); std::move(callback));
...@@ -1649,6 +1653,7 @@ void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) { ...@@ -1649,6 +1653,7 @@ void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) {
&VideoFrameCompositor::EnableSubmission, &VideoFrameCompositor::EnableSubmission,
base::Unretained(compositor_.get()), bridge_->GetSurfaceId(), base::Unretained(compositor_.get()), bridge_->GetSurfaceId(),
pipeline_metadata_.video_decoder_config.video_rotation(), pipeline_metadata_.video_decoder_config.video_rotation(),
IsInPictureInPicture(),
BindToCurrentLoop(base::BindRepeating( BindToCurrentLoop(base::BindRepeating(
&WebMediaPlayerImpl::OnFrameSinkDestroyed, AsWeakPtr())))); &WebMediaPlayerImpl::OnFrameSinkDestroyed, AsWeakPtr()))));
bridge_->SetContentsOpaque(opaque_); bridge_->SetContentsOpaque(opaque_);
...@@ -2089,18 +2094,15 @@ void WebMediaPlayerImpl::OnBecamePersistentVideo(bool value) { ...@@ -2089,18 +2094,15 @@ void WebMediaPlayerImpl::OnBecamePersistentVideo(bool value) {
void WebMediaPlayerImpl::OnPictureInPictureModeEnded() { void WebMediaPlayerImpl::OnPictureInPictureModeEnded() {
// It is possible for this method to be called when the player is no longer in // It is possible for this method to be called when the player is no longer in
// Picture-in-Picture mode. // Picture-in-Picture mode.
if (!client_ || client_->DisplayType() != if (!client_ || !IsInPictureInPicture())
WebMediaPlayer::DisplayType::kPictureInPicture) {
return; return;
}
client_->PictureInPictureStopped(); client_->PictureInPictureStopped();
} }
void WebMediaPlayerImpl::OnPictureInPictureControlClicked( void WebMediaPlayerImpl::OnPictureInPictureControlClicked(
const std::string& control_id) { const std::string& control_id) {
if (client_ && client_->DisplayType() == if (client_ && IsInPictureInPicture()) {
WebMediaPlayer::DisplayType::kPictureInPicture) {
client_->PictureInPictureControlClicked( client_->PictureInPictureControlClicked(
blink::WebString::FromUTF8(control_id)); blink::WebString::FromUTF8(control_id));
} }
...@@ -2967,7 +2969,7 @@ bool WebMediaPlayerImpl::IsBackgroundOptimizationCandidate() const { ...@@ -2967,7 +2969,7 @@ bool WebMediaPlayerImpl::IsBackgroundOptimizationCandidate() const {
DCHECK(main_task_runner_->BelongsToCurrentThread()); DCHECK(main_task_runner_->BelongsToCurrentThread());
// Don't optimize Picture-in-Picture players. // Don't optimize Picture-in-Picture players.
if (client_->DisplayType() == WebMediaPlayer::DisplayType::kPictureInPicture) if (IsInPictureInPicture())
return false; return false;
#if defined(OS_ANDROID) // WMPI_CAST #if defined(OS_ANDROID) // WMPI_CAST
...@@ -3219,4 +3221,10 @@ void WebMediaPlayerImpl::RecordEncryptionScheme( ...@@ -3219,4 +3221,10 @@ void WebMediaPlayerImpl::RecordEncryptionScheme(
EncryptionSchemeUMA::kCount); EncryptionSchemeUMA::kCount);
} }
bool WebMediaPlayerImpl::IsInPictureInPicture() const {
DCHECK(client_);
return client_->DisplayType() ==
WebMediaPlayer::DisplayType::kPictureInPicture;
}
} // namespace media } // namespace media
...@@ -581,6 +581,11 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl ...@@ -581,6 +581,11 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
void RecordEncryptionScheme(const std::string& stream_name, void RecordEncryptionScheme(const std::string& stream_name,
const EncryptionScheme& encryption_scheme); const EncryptionScheme& encryption_scheme);
// Returns whether the player is currently displayed in Picture-in-Picture.
// It will return true even if the player is in AutoPIP mode.
// The player MUST have a `client_` when this call happen.
bool IsInPictureInPicture() const;
blink::WebLocalFrame* const frame_; blink::WebLocalFrame* const frame_;
// The playback state last reported to |delegate_|, to avoid setting duplicate // The playback state last reported to |delegate_|, to avoid setting duplicate
......
...@@ -319,9 +319,10 @@ class MockVideoFrameCompositor : public VideoFrameCompositor { ...@@ -319,9 +319,10 @@ class MockVideoFrameCompositor : public VideoFrameCompositor {
// MOCK_METHOD doesn't like OnceCallback. // MOCK_METHOD doesn't like OnceCallback.
void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb) override {} void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb) override {}
MOCK_METHOD0(GetCurrentFrameAndUpdateIfStale, scoped_refptr<VideoFrame>()); MOCK_METHOD0(GetCurrentFrameAndUpdateIfStale, scoped_refptr<VideoFrame>());
MOCK_METHOD3(EnableSubmission, MOCK_METHOD4(EnableSubmission,
void(const viz::SurfaceId&, void(const viz::SurfaceId&,
media::VideoRotation, media::VideoRotation,
bool,
blink::WebFrameSinkDestroyedCallback)); blink::WebFrameSinkDestroyedCallback));
}; };
...@@ -770,7 +771,7 @@ TEST_F(WebMediaPlayerImplTest, LoadPreloadMetadataSuspendNoVideoMemoryUsage) { ...@@ -770,7 +771,7 @@ TEST_F(WebMediaPlayerImplTest, LoadPreloadMetadataSuspendNoVideoMemoryUsage) {
EXPECT_CALL(client_, SetCcLayer(_)).Times(0); EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillOnce(ReturnRef(surface_id_)); .WillOnce(ReturnRef(surface_id_));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
} }
...@@ -1167,7 +1168,7 @@ TEST_F(WebMediaPlayerImplTest, NoStreams) { ...@@ -1167,7 +1168,7 @@ TEST_F(WebMediaPlayerImplTest, NoStreams) {
if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)) { if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)) {
EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()).Times(0); EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()).Times(0);
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()).Times(0); EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()).Times(0);
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)).Times(0); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _)).Times(0);
} }
// Nothing should happen. In particular, no assertions should fail. // Nothing should happen. In particular, no assertions should fail.
...@@ -1186,7 +1187,7 @@ TEST_F(WebMediaPlayerImplTest, NaturalSizeChange) { ...@@ -1186,7 +1187,7 @@ TEST_F(WebMediaPlayerImplTest, NaturalSizeChange) {
EXPECT_CALL(client_, SetCcLayer(_)).Times(0); EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillOnce(ReturnRef(surface_id_)); .WillOnce(ReturnRef(surface_id_));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
} else { } else {
EXPECT_CALL(client_, SetCcLayer(NotNull())); EXPECT_CALL(client_, SetCcLayer(NotNull()));
...@@ -1213,7 +1214,7 @@ TEST_F(WebMediaPlayerImplTest, NaturalSizeChange_Rotated) { ...@@ -1213,7 +1214,7 @@ TEST_F(WebMediaPlayerImplTest, NaturalSizeChange_Rotated) {
EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()); EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillOnce(ReturnRef(surface_id_)); .WillOnce(ReturnRef(surface_id_));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
} else { } else {
EXPECT_CALL(client_, SetCcLayer(NotNull())); EXPECT_CALL(client_, SetCcLayer(NotNull()));
...@@ -1241,7 +1242,7 @@ TEST_F(WebMediaPlayerImplTest, VideoLockedWhenPausedWhenHidden) { ...@@ -1241,7 +1242,7 @@ TEST_F(WebMediaPlayerImplTest, VideoLockedWhenPausedWhenHidden) {
EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()); EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillOnce(ReturnRef(surface_id_)); .WillOnce(ReturnRef(surface_id_));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
} else { } else {
EXPECT_CALL(client_, SetCcLayer(NotNull())); EXPECT_CALL(client_, SetCcLayer(NotNull()));
...@@ -1317,7 +1318,7 @@ TEST_F(WebMediaPlayerImplTest, InfiniteDuration) { ...@@ -1317,7 +1318,7 @@ TEST_F(WebMediaPlayerImplTest, InfiniteDuration) {
EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()); EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillOnce(ReturnRef(surface_id_)); .WillOnce(ReturnRef(surface_id_));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
} else { } else {
EXPECT_CALL(client_, SetCcLayer(NotNull())); EXPECT_CALL(client_, SetCcLayer(NotNull()));
...@@ -1356,7 +1357,7 @@ TEST_F(WebMediaPlayerImplTest, SetContentsLayerGetsWebLayerFromBridge) { ...@@ -1356,7 +1357,7 @@ TEST_F(WebMediaPlayerImplTest, SetContentsLayerGetsWebLayerFromBridge) {
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillOnce(ReturnRef(surface_id_)); .WillOnce(ReturnRef(surface_id_));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
// We only call the callback to create the bridge in OnMetadata, so we need // We only call the callback to create the bridge in OnMetadata, so we need
// to call it. // to call it.
...@@ -1394,7 +1395,7 @@ TEST_F(WebMediaPlayerImplTest, PictureInPictureTriggerCallback) { ...@@ -1394,7 +1395,7 @@ TEST_F(WebMediaPlayerImplTest, PictureInPictureTriggerCallback) {
EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()); EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()) EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
.WillRepeatedly(ReturnRef(surface_id_)); .WillRepeatedly(ReturnRef(surface_id_));
EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)); EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _));
EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
PipelineMetadata metadata; PipelineMetadata metadata;
......
...@@ -54,6 +54,9 @@ class BLINK_PLATFORM_EXPORT WebVideoFrameSubmitter ...@@ -54,6 +54,9 @@ class BLINK_PLATFORM_EXPORT WebVideoFrameSubmitter
// Updates whether we should submit frames or not based on whether the video // Updates whether we should submit frames or not based on whether the video
// is visible on screen. // is visible on screen.
virtual void UpdateSubmissionState(bool) = 0; virtual void UpdateSubmissionState(bool) = 0;
// Set whether frames should always be submitted regardless of visibility.
virtual void SetForceSubmit(bool) = 0;
}; };
} // namespace blink } // namespace blink
......
...@@ -62,14 +62,19 @@ void VideoFrameSubmitter::EnableSubmission( ...@@ -62,14 +62,19 @@ void VideoFrameSubmitter::EnableSubmission(
} }
void VideoFrameSubmitter::UpdateSubmissionState(bool should_submit) { void VideoFrameSubmitter::UpdateSubmissionState(bool should_submit) {
should_submit_ = should_submit; should_submit_internal_ = should_submit;
UpdateSubmissionStateInternal();
}
void VideoFrameSubmitter::SetForceSubmit(bool force_submit) {
force_submit_ = force_submit;
UpdateSubmissionStateInternal(); UpdateSubmissionStateInternal();
} }
void VideoFrameSubmitter::UpdateSubmissionStateInternal() { void VideoFrameSubmitter::UpdateSubmissionStateInternal() {
if (compositor_frame_sink_) { if (compositor_frame_sink_) {
compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && should_submit_); compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && ShouldSubmit());
if (should_submit_) if (ShouldSubmit())
SubmitSingleFrame(); SubmitSingleFrame();
else if (!frame_size_.IsEmpty()) else if (!frame_size_.IsEmpty())
SubmitEmptyFrame(); SubmitEmptyFrame();
...@@ -110,6 +115,10 @@ void VideoFrameSubmitter::SubmitSingleFrame() { ...@@ -110,6 +115,10 @@ void VideoFrameSubmitter::SubmitSingleFrame() {
} }
} }
bool VideoFrameSubmitter::ShouldSubmit() const {
return should_submit_internal_ || force_submit_;
}
void VideoFrameSubmitter::DidReceiveFrame() { void VideoFrameSubmitter::DidReceiveFrame() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK(provider_); DCHECK(provider_);
...@@ -127,7 +136,7 @@ void VideoFrameSubmitter::StartRendering() { ...@@ -127,7 +136,7 @@ void VideoFrameSubmitter::StartRendering() {
is_rendering_ = true; is_rendering_ = true;
if (compositor_frame_sink_) if (compositor_frame_sink_)
compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && should_submit_); compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && ShouldSubmit());
} }
void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) { void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) {
...@@ -193,7 +202,7 @@ void VideoFrameSubmitter::SubmitFrame( ...@@ -193,7 +202,7 @@ void VideoFrameSubmitter::SubmitFrame(
scoped_refptr<media::VideoFrame> video_frame) { scoped_refptr<media::VideoFrame> video_frame) {
TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame"); TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame");
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (!compositor_frame_sink_ || !should_submit_) if (!compositor_frame_sink_ || !ShouldSubmit())
return; return;
// TODO(mlamouri): the `frame_size_` is expected to be consistent but seems to // TODO(mlamouri): the `frame_size_` is expected to be consistent but seems to
...@@ -234,7 +243,7 @@ void VideoFrameSubmitter::SubmitFrame( ...@@ -234,7 +243,7 @@ void VideoFrameSubmitter::SubmitFrame(
void VideoFrameSubmitter::SubmitEmptyFrame() { void VideoFrameSubmitter::SubmitEmptyFrame() {
TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame"); TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame");
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK(compositor_frame_sink_ && !should_submit_); DCHECK(compositor_frame_sink_ && !ShouldSubmit());
DCHECK(!frame_size_.IsEmpty()); DCHECK(!frame_size_.IsEmpty());
viz::CompositorFrame compositor_frame; viz::CompositorFrame compositor_frame;
...@@ -321,7 +330,7 @@ void VideoFrameSubmitter::OnContextLost() { ...@@ -321,7 +330,7 @@ void VideoFrameSubmitter::OnContextLost() {
// We need to trigger another submit so that surface_id's get propagated // We need to trigger another submit so that surface_id's get propagated
// correctly. If we don't, we don't get any more signals to update the // correctly. If we don't, we don't get any more signals to update the
// submission state. // submission state.
should_submit_ = true; should_submit_internal_ = true;
} }
void VideoFrameSubmitter::DidReceiveCompositorFrameAck( void VideoFrameSubmitter::DidReceiveCompositorFrameAck(
......
...@@ -64,6 +64,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter ...@@ -64,6 +64,7 @@ class PLATFORM_EXPORT VideoFrameSubmitter
void SetRotation(media::VideoRotation) override; void SetRotation(media::VideoRotation) override;
void EnableSubmission(viz::SurfaceId, WebFrameSinkDestroyedCallback) override; void EnableSubmission(viz::SurfaceId, WebFrameSinkDestroyedCallback) override;
void UpdateSubmissionState(bool) override; void UpdateSubmissionState(bool) override;
void SetForceSubmit(bool) override;
// viz::ContextLostObserver implementation. // viz::ContextLostObserver implementation.
void OnContextLost() override; void OnContextLost() override;
...@@ -88,6 +89,8 @@ class PLATFORM_EXPORT VideoFrameSubmitter ...@@ -88,6 +89,8 @@ class PLATFORM_EXPORT VideoFrameSubmitter
FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, ContextLostDuringSubmit); FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, ContextLostDuringSubmit);
FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
ShouldSubmitPreventsSubmission); ShouldSubmitPreventsSubmission);
FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
SetForceSubmitForcesSubmission);
void StartSubmitting(); void StartSubmitting();
void UpdateSubmissionStateInternal(); void UpdateSubmissionStateInternal();
...@@ -100,6 +103,10 @@ class PLATFORM_EXPORT VideoFrameSubmitter ...@@ -100,6 +103,10 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// ending rendering. // ending rendering.
void SubmitSingleFrame(); void SubmitSingleFrame();
// Return whether the submitter should submit frames based on its current
// state.
bool ShouldSubmit() const;
cc::VideoFrameProvider* provider_ = nullptr; cc::VideoFrameProvider* provider_ = nullptr;
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_; scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
viz::mojom::blink::CompositorFrameSinkPtr compositor_frame_sink_; viz::mojom::blink::CompositorFrameSinkPtr compositor_frame_sink_;
...@@ -112,7 +119,9 @@ class PLATFORM_EXPORT VideoFrameSubmitter ...@@ -112,7 +119,9 @@ class PLATFORM_EXPORT VideoFrameSubmitter
bool is_rendering_; bool is_rendering_;
// If we are not on screen, we should not submit. // If we are not on screen, we should not submit.
bool should_submit_ = false; bool should_submit_internal_ = false;
// Whether frames should always be submitted.
bool force_submit_ = false;
media::VideoRotation rotation_; media::VideoRotation rotation_;
// Size of the video frame being submitted. It is set the first time a frame // Size of the video frame being submitted. It is set the first time a frame
......
...@@ -279,6 +279,8 @@ TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) { ...@@ -279,6 +279,8 @@ TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
submitter_->UpdateSubmissionState(false); submitter_->UpdateSubmissionState(false);
scoped_task_environment_.RunUntilIdle(); scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(submitter_->ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false)); EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
submitter_->StartRendering(); submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle(); scoped_task_environment_.RunUntilIdle();
...@@ -296,12 +298,84 @@ TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) { ...@@ -296,12 +298,84 @@ TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
submitter_->UpdateSubmissionState(true); submitter_->UpdateSubmissionState(true);
scoped_task_environment_.RunUntilIdle(); scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(submitter_->ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false)); EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1); EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
EXPECT_CALL(*provider_, GetCurrentFrame()).Times(0); EXPECT_CALL(*provider_, GetCurrentFrame()).Times(0);
submitter_->UpdateSubmissionState(false); submitter_->UpdateSubmissionState(false);
scoped_task_environment_.RunUntilIdle(); scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(submitter_->ShouldSubmit());
EXPECT_CALL(*provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*provider_, PutCurrentFrame());
submitter_->SubmitSingleFrame();
}
// Tests that when set to true SetForceSubmit forces frame submissions.
// regardless of the internal submit state.
TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
MakeSubmitter();
scoped_task_environment_.RunUntilIdle();
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
submitter_->UpdateSubmissionState(false);
scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(submitter_->ShouldSubmit());
EXPECT_CALL(*provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*provider_, PutCurrentFrame());
submitter_->SetForceSubmit(true);
EXPECT_TRUE(submitter_->ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle();
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
EXPECT_CALL(*provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
EXPECT_CALL(*provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
submitter_->UpdateSubmissionState(true);
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(submitter_->ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
EXPECT_CALL(*provider_, PutCurrentFrame());
EXPECT_CALL(*provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
submitter_->UpdateSubmissionState(false);
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(submitter_->ShouldSubmit());
EXPECT_CALL(*provider_, GetCurrentFrame()) EXPECT_CALL(*provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame( .WillOnce(Return(media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
......
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