Commit e90fe319 authored by Thomas Guilbert's avatar Thomas Guilbert Committed by Commit Bot

Add WMPI::RequestAnimationFrame()

This CL adds the plumbing necessary in WMPI to initiate and complete
a requestAnimationFrame call.

For the moment, WebMediaPlayerClient doesn't do anything with the
frame returned, but this will be updated in upcoming CLs.

Bug:1012063

Change-Id: I99c951bf0d6317bb81986166e57ec250d47dc1cb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1900350
Commit-Queue: Thomas Guilbert <tguilbert@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarRick Byers <rbyers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713634}
parent cd7f4f87
...@@ -105,7 +105,7 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink, ...@@ -105,7 +105,7 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink,
// it was updated. In certain applications, one might need to periodically // it was updated. In certain applications, one might need to periodically
// call UpdateCurrentFrameIfStale on |task_runner_| to drive the updates. // call UpdateCurrentFrameIfStale on |task_runner_| to drive the updates.
// Can be called from any thread. // Can be called from any thread.
scoped_refptr<VideoFrame> GetCurrentFrameOnAnyThread(); virtual scoped_refptr<VideoFrame> GetCurrentFrameOnAnyThread();
// VideoRendererSink implementation. These methods must be called from the // VideoRendererSink implementation. These methods must be called from the
// same thread (typically the media thread). // same thread (typically the media thread).
...@@ -132,7 +132,7 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink, ...@@ -132,7 +132,7 @@ class MEDIA_BLINK_EXPORT VideoFrameCompositor : public VideoRendererSink,
// Must be called on the compositor thread. // Must be called on the compositor thread.
virtual void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb); virtual void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb);
void SetOnFramePresentedCallback(OnNewFramePresentedCB present_cb); virtual void SetOnFramePresentedCallback(OnNewFramePresentedCB present_cb);
// Updates the rotation information for frames given to |submitter_|. // Updates the rotation information for frames given to |submitter_|.
void UpdateRotation(VideoRotation rotation); void UpdateRotation(VideoRotation rotation);
......
...@@ -2782,6 +2782,9 @@ scoped_refptr<VideoFrame> WebMediaPlayerImpl::GetCurrentFrameFromCompositor() ...@@ -2782,6 +2782,9 @@ scoped_refptr<VideoFrame> WebMediaPlayerImpl::GetCurrentFrameFromCompositor()
DCHECK(main_task_runner_->BelongsToCurrentThread()); DCHECK(main_task_runner_->BelongsToCurrentThread());
TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor"); TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
if (current_frame_override_)
return current_frame_override_;
// Can be null. // Can be null.
scoped_refptr<VideoFrame> video_frame = scoped_refptr<VideoFrame> video_frame =
compositor_->GetCurrentFrameOnAnyThread(); compositor_->GetCurrentFrameOnAnyThread();
...@@ -3286,6 +3289,28 @@ base::Optional<viz::SurfaceId> WebMediaPlayerImpl::GetSurfaceId() { ...@@ -3286,6 +3289,28 @@ base::Optional<viz::SurfaceId> WebMediaPlayerImpl::GetSurfaceId() {
return bridge_->GetSurfaceId(); return bridge_->GetSurfaceId();
} }
void WebMediaPlayerImpl::RequestAnimationFrame() {
vfc_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VideoFrameCompositor::SetOnFramePresentedCallback,
base::Unretained(compositor_.get()),
BindToCurrentLoop(base::BindOnce(
&WebMediaPlayerImpl::OnNewFramePresentedCallback,
weak_factory_.GetWeakPtr()))));
}
void WebMediaPlayerImpl::OnNewFramePresentedCallback(
scoped_refptr<VideoFrame> presented_frame,
base::TimeTicks presentation_time,
base::TimeTicks expected_presentation_time,
uint32_t presentation_counter) {
current_frame_override_ = std::move(presented_frame);
client_->OnRequestAnimationFrame(
presentation_time, expected_presentation_time, presentation_counter,
*current_frame_override_);
current_frame_override_.reset();
}
base::WeakPtr<blink::WebMediaPlayer> WebMediaPlayerImpl::AsWeakPtr() { base::WeakPtr<blink::WebMediaPlayer> WebMediaPlayerImpl::AsWeakPtr() {
return weak_this_; return weak_this_;
} }
...@@ -3637,4 +3662,9 @@ GURL WebMediaPlayerImpl::GetSrcAfterRedirects() { ...@@ -3637,4 +3662,9 @@ GURL WebMediaPlayerImpl::GetSrcAfterRedirects() {
return mb_data_source_ ? mb_data_source_->GetUrlAfterRedirects() : GURL(); return mb_data_source_ ? mb_data_source_->GetUrlAfterRedirects() : GURL();
} }
void WebMediaPlayerImpl::SetCurrentFrameOverrideForTesting(
scoped_refptr<VideoFrame> current_frame_override) {
current_frame_override_ = current_frame_override;
}
} // namespace media } // namespace media
...@@ -281,6 +281,7 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl ...@@ -281,6 +281,7 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
int GetDelegateId() override; int GetDelegateId() override;
base::Optional<viz::SurfaceId> GetSurfaceId() override; base::Optional<viz::SurfaceId> GetSurfaceId() override;
GURL GetSrcAfterRedirects() override; GURL GetSrcAfterRedirects() override;
void RequestAnimationFrame() override;
base::WeakPtr<blink::WebMediaPlayer> AsWeakPtr() override; base::WeakPtr<blink::WebMediaPlayer> AsWeakPtr() override;
...@@ -607,11 +608,21 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl ...@@ -607,11 +608,21 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
// Switch to SurfaceLayer, either initially or from VideoLayer. // Switch to SurfaceLayer, either initially or from VideoLayer.
void ActivateSurfaceLayerForVideo(); void ActivateSurfaceLayerForVideo();
// Called by |compositor_| upon presenting a frame, after
// RequestAnimationFrame() is called.
void OnNewFramePresentedCallback(scoped_refptr<VideoFrame> presented_frame,
base::TimeTicks presentation_time,
base::TimeTicks expected_presentation_time,
uint32_t presentation_counter);
// Notifies |mb_data_source_| of playback and rate changes which may increase // Notifies |mb_data_source_| of playback and rate changes which may increase
// the amount of data the DataSource buffers. Does nothing prior to reaching // the amount of data the DataSource buffers. Does nothing prior to reaching
// kReadyStateHaveEnoughData for the first time. // kReadyStateHaveEnoughData for the first time.
void MaybeUpdateBufferSizesForPlayback(); void MaybeUpdateBufferSizesForPlayback();
void SetCurrentFrameOverrideForTesting(
scoped_refptr<VideoFrame> current_frame_override);
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
...@@ -994,6 +1005,10 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl ...@@ -994,6 +1005,10 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
// Whether background video optimization is supported on current platform. // Whether background video optimization is supported on current platform.
bool is_background_video_track_optimization_supported_ = true; bool is_background_video_track_optimization_supported_ = true;
// Valid while an active OnNewFramePresentedCallback() is in progress.
// Overrides the VideoFrame returned by GetCurrentFrameFromCompositor().
scoped_refptr<VideoFrame> current_frame_override_;
base::CancelableOnceClosure have_enough_after_lazy_load_cb_; base::CancelableOnceClosure have_enough_after_lazy_load_cb_;
// State for simplified watch time reporting. // State for simplified watch time reporting.
......
...@@ -152,6 +152,11 @@ class MockWebMediaPlayerClient : public blink::WebMediaPlayerClient { ...@@ -152,6 +152,11 @@ class MockWebMediaPlayerClient : public blink::WebMediaPlayerClient {
MOCK_METHOD0(RequestPause, void()); MOCK_METHOD0(RequestPause, void());
MOCK_METHOD1(RequestMuted, void(bool)); MOCK_METHOD1(RequestMuted, void(bool));
MOCK_METHOD0(GetFeatures, Features(void)); MOCK_METHOD0(GetFeatures, Features(void));
MOCK_METHOD4(OnRequestAnimationFrame,
void(base::TimeTicks,
base::TimeTicks,
uint32_t,
const media::VideoFrame&));
void set_was_always_muted(bool value) { was_always_muted_ = value; } void set_was_always_muted(bool value) { was_always_muted_ = value; }
...@@ -290,9 +295,9 @@ class MockVideoFrameCompositor : public VideoFrameCompositor { ...@@ -290,9 +295,9 @@ class MockVideoFrameCompositor : public VideoFrameCompositor {
~MockVideoFrameCompositor() override = default; ~MockVideoFrameCompositor() override = default;
// MOCK_METHOD doesn't like OnceCallback. // MOCK_METHOD doesn't like OnceCallback.
void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb) override {} MOCK_METHOD1(SetOnFramePresentedCallback, void(OnNewFramePresentedCB));
MOCK_METHOD1(SetIsPageVisible, void(bool)); MOCK_METHOD1(SetIsPageVisible, void(bool));
MOCK_METHOD0(GetCurrentFrameAndUpdateIfStale, scoped_refptr<VideoFrame>()); MOCK_METHOD0(GetCurrentFrameOnAnyThread, scoped_refptr<VideoFrame>());
MOCK_METHOD4( MOCK_METHOD4(
EnableSubmission, EnableSubmission,
void(const viz::SurfaceId&, base::TimeTicks, media::VideoRotation, bool)); void(const viz::SurfaceId&, base::TimeTicks, media::VideoRotation, bool));
...@@ -617,6 +622,27 @@ class WebMediaPlayerImplTest : public testing::Test { ...@@ -617,6 +622,27 @@ class WebMediaPlayerImplTest : public testing::Test {
return wmpi_->mb_data_source_->media_has_played(); return wmpi_->mb_data_source_->media_has_played();
} }
scoped_refptr<VideoFrame> CreateFrame() {
gfx::Size size(8, 8);
return VideoFrame::CreateFrame(PIXEL_FORMAT_I420, size, gfx::Rect(size),
size, base::TimeDelta());
}
void RequestAnimationFrame() { wmpi_->RequestAnimationFrame(); }
void OnNewFramePresentedCallback() {
wmpi_->OnNewFramePresentedCallback(CreateFrame(), base::TimeTicks::Now(),
base::TimeTicks::Now(), 1);
}
scoped_refptr<VideoFrame> GetCurrentFrameFromCompositor() {
return wmpi_->GetCurrentFrameFromCompositor();
}
void SetCurrentFrameOverrideForTesting(scoped_refptr<VideoFrame> frame) {
wmpi_->SetCurrentFrameOverrideForTesting(frame);
}
enum class LoadType { kFullyBuffered, kStreaming }; enum class LoadType { kFullyBuffered, kStreaming };
void Load(std::string data_file, void Load(std::string data_file,
LoadType load_type = LoadType::kFullyBuffered) { LoadType load_type = LoadType::kFullyBuffered) {
...@@ -1105,6 +1131,40 @@ TEST_F(WebMediaPlayerImplTest, DidLoadingProgressTriggersResume) { ...@@ -1105,6 +1131,40 @@ TEST_F(WebMediaPlayerImplTest, DidLoadingProgressTriggersResume) {
EXPECT_FALSE(IsSuspended()); EXPECT_FALSE(IsSuspended());
} }
TEST_F(WebMediaPlayerImplTest, RequestAnimationFrame) {
InitializeWebMediaPlayerImpl();
EXPECT_CALL(*compositor_, SetOnFramePresentedCallback(_));
RequestAnimationFrame();
}
TEST_F(WebMediaPlayerImplTest, OnNewFramePresentedCallback) {
InitializeWebMediaPlayerImpl();
EXPECT_CALL(client_, OnRequestAnimationFrame(_, _, _, _));
OnNewFramePresentedCallback();
}
TEST_F(WebMediaPlayerImplTest, GetCurrentFrameFromCompositorOverride) {
scoped_refptr<VideoFrame> compositor_frame = CreateFrame();
scoped_refptr<VideoFrame> override_frame = CreateFrame();
InitializeWebMediaPlayerImpl();
EXPECT_CALL(*compositor_, GetCurrentFrameOnAnyThread())
.WillRepeatedly(Return(compositor_frame));
EXPECT_EQ(compositor_frame, GetCurrentFrameFromCompositor());
SetCurrentFrameOverrideForTesting(override_frame);
EXPECT_EQ(override_frame, GetCurrentFrameFromCompositor());
// After returning from OnNewFramePresentedCallback(), the overriding frame
// should be cleared.
OnNewFramePresentedCallback();
EXPECT_EQ(compositor_frame, GetCurrentFrameFromCompositor());
}
TEST_F(WebMediaPlayerImplTest, ComputePlayState_Constructed) { TEST_F(WebMediaPlayerImplTest, ComputePlayState_Constructed) {
InitializeWebMediaPlayerImpl(); InitializeWebMediaPlayerImpl();
WebMediaPlayerImpl::PlayState state = ComputePlayState(); WebMediaPlayerImpl::PlayState state = ComputePlayState();
......
...@@ -26,6 +26,7 @@ include_rules = [ ...@@ -26,6 +26,7 @@ include_rules = [
"+media/base/audio_capturer_source.h", "+media/base/audio_capturer_source.h",
"+media/base/audio_renderer_sink.h", "+media/base/audio_renderer_sink.h",
"+media/base/eme_constants.h", "+media/base/eme_constants.h",
"+media/base/video_frame.h",
"+media/base/video_transformation.h", "+media/base/video_transformation.h",
"+mojo/public", "+mojo/public",
"+net/cert", "+net/cert",
......
...@@ -430,6 +430,12 @@ class WebMediaPlayer { ...@@ -430,6 +430,12 @@ class WebMediaPlayer {
// empty GURL, which will be interpreted as "use the original URL". // empty GURL, which will be interpreted as "use the original URL".
virtual GURL GetSrcAfterRedirects() { return GURL(); } virtual GURL GetSrcAfterRedirects() { return GURL(); }
// Register a request to be notified the next time a video frame is presented
// to the compositor. The video frame and its metadata will be surfaced via
// WebMediaPlayerClient::OnRequestAnimationFrame().
// TODO(https://crbug.com/1022186): Add pointer to spec.
virtual void RequestAnimationFrame() {}
virtual base::WeakPtr<WebMediaPlayer> AsWeakPtr() = 0; virtual base::WeakPtr<WebMediaPlayer> AsWeakPtr() = 0;
}; };
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MEDIA_PLAYER_CLIENT_H_ #ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MEDIA_PLAYER_CLIENT_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MEDIA_PLAYER_CLIENT_H_ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MEDIA_PLAYER_CLIENT_H_
#include "base/time/time.h"
#include "media/base/video_frame.h"
#include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_media_player.h" #include "third_party/blink/public/platform/web_media_player.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
...@@ -177,6 +179,15 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient { ...@@ -177,6 +179,15 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
// - Natural Size. // - Natural Size.
virtual void OnPictureInPictureStateChange() = 0; virtual void OnPictureInPictureStateChange() = 0;
// Called when a video frame has been presented to the compositor, after a
// request was initiated via WebMediaPlayer::RequestAnimationFrame().
// TODO(https://crbug.com/1022186): Add pointer to spec.
virtual void OnRequestAnimationFrame(
base::TimeTicks presentation_time,
base::TimeTicks expected_presentation_time,
uint32_t presented_frames_counter,
const media::VideoFrame& presented_frame) {}
struct Features { struct Features {
WebString id; WebString id;
WebString width; WebString width;
......
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