Commit 40899527 authored by qiangchen's avatar qiangchen Committed by Commit bot

Bug Fix: Resize Event Trigger

WebMediaPlayerMS triggers Resize event when the new sized frame
enters the player. However, one would need to wait some time
(~30 ms) for that frame to be displayed. Thus at the instant when
resize is triggered, javascript is still seeing the old size.

In this CL, we move the trigger to when |current_frame_| is updated.

BUG=604795

Review URL: https://codereview.chromium.org/1895233003

Cr-Commit-Position: refs/heads/master@{#388635}
parent d1f4ffde
...@@ -496,15 +496,7 @@ void WebMediaPlayerMS::OnFrameAvailable( ...@@ -496,15 +496,7 @@ void WebMediaPlayerMS::OnFrameAvailable(
} }
} }
// As EnqueueFrame can potentially change |current_frame_|, we need to do
// the size change check before it. Otherwise, we are running the risk of not
// detecting a size change event.
const bool size_changed =
compositor_->GetCurrentSize() != frame->natural_size();
compositor_->EnqueueFrame(frame); compositor_->EnqueueFrame(frame);
if (size_changed)
get_client()->sizeChanged();
} }
void WebMediaPlayerMS::RepaintInternal() { void WebMediaPlayerMS::RepaintInternal() {
...@@ -542,4 +534,8 @@ void WebMediaPlayerMS::ResetCanvasCache() { ...@@ -542,4 +534,8 @@ void WebMediaPlayerMS::ResetCanvasCache() {
video_renderer_.ResetCache(); video_renderer_.ResetCache();
} }
void WebMediaPlayerMS::TriggerResize() {
get_client()->sizeChanged();
}
} // namespace content } // namespace content
...@@ -110,6 +110,9 @@ class CONTENT_EXPORT WebMediaPlayerMS ...@@ -110,6 +110,9 @@ class CONTENT_EXPORT WebMediaPlayerMS
media::SkCanvasVideoRenderer* GetSkCanvasVideoRenderer(); media::SkCanvasVideoRenderer* GetSkCanvasVideoRenderer();
void ResetCanvasCache(); void ResetCanvasCache();
// Methods to trigger resize event.
void TriggerResize();
// True if the loaded media has a playable video/audio track. // True if the loaded media has a playable video/audio track.
bool hasVideo() const override; bool hasVideo() const override;
bool hasAudio() const override; bool hasAudio() const override;
......
...@@ -395,10 +395,19 @@ void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, ...@@ -395,10 +395,19 @@ void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min,
void WebMediaPlayerMSCompositor::SetCurrentFrame( void WebMediaPlayerMSCompositor::SetCurrentFrame(
const scoped_refptr<media::VideoFrame>& frame) { const scoped_refptr<media::VideoFrame>& frame) {
current_frame_lock_.AssertAcquired(); current_frame_lock_.AssertAcquired();
if (!current_frame_used_by_compositor_) if (!current_frame_used_by_compositor_)
++dropped_frame_count_; ++dropped_frame_count_;
current_frame_used_by_compositor_ = false; current_frame_used_by_compositor_ = false;
const bool size_changed =
!current_frame_ ||
current_frame_->natural_size() != frame->natural_size();
current_frame_ = frame; current_frame_ = frame;
if (size_changed) {
main_message_loop_->PostTask(
FROM_HERE, base::Bind(&WebMediaPlayerMS::TriggerResize, player_));
}
main_message_loop_->PostTask( main_message_loop_->PostTask(
FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_)); FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_));
} }
......
...@@ -26,6 +26,8 @@ enum class FrameType { ...@@ -26,6 +26,8 @@ enum class FrameType {
using TestFrame = std::pair<FrameType, scoped_refptr<media::VideoFrame>>; using TestFrame = std::pair<FrameType, scoped_refptr<media::VideoFrame>>;
static const int kOddSizeOffset = 3; static const int kOddSizeOffset = 3;
static const int kStandardWidth = 320;
static const int kStandardHeight = 240;
class FakeWebMediaPlayerDelegate class FakeWebMediaPlayerDelegate
: public media::WebMediaPlayerDelegate, : public media::WebMediaPlayerDelegate,
...@@ -133,7 +135,8 @@ class MockVideoFrameProvider : public VideoFrameProvider { ...@@ -133,7 +135,8 @@ class MockVideoFrameProvider : public VideoFrameProvider {
// Methods for test use // Methods for test use
void QueueFrames(const std::vector<int>& timestamps_or_frame_type, void QueueFrames(const std::vector<int>& timestamps_or_frame_type,
bool opaque_frame = true, bool opaque_frame = true,
bool odd_size_frame = false); bool odd_size_frame = false,
int double_size_index = -1);
bool Started() { return started_; } bool Started() { return started_; }
bool Paused() { return paused_; } bool Paused() { return paused_; }
...@@ -191,8 +194,14 @@ void MockVideoFrameProvider::AddFrame( ...@@ -191,8 +194,14 @@ void MockVideoFrameProvider::AddFrame(
void MockVideoFrameProvider::QueueFrames( void MockVideoFrameProvider::QueueFrames(
const std::vector<int>& timestamp_or_frame_type, const std::vector<int>& timestamp_or_frame_type,
bool opaque_frame, bool opaque_frame,
bool odd_size_frame) { bool odd_size_frame,
for (const int token : timestamp_or_frame_type) { int double_size_index) {
gfx::Size standard_size = gfx::Size(kStandardWidth, kStandardHeight);
for (size_t i = 0; i < timestamp_or_frame_type.size(); i++) {
const int token = timestamp_or_frame_type[i];
if (static_cast<int>(i) == double_size_index) {
standard_size = gfx::Size(kStandardWidth * 2, kStandardHeight * 2);
}
if (token < static_cast<int>(FrameType::MIN_TYPE)) { if (token < static_cast<int>(FrameType::MIN_TYPE)) {
CHECK(false) << "Unrecognized frame type: " << token; CHECK(false) << "Unrecognized frame type: " << token;
return; return;
...@@ -204,14 +213,16 @@ void MockVideoFrameProvider::QueueFrames( ...@@ -204,14 +213,16 @@ void MockVideoFrameProvider::QueueFrames(
} }
if (token >= 0) { if (token >= 0) {
gfx::Size natural_size = media::TestVideoConfig::NormalCodedSize(); gfx::Size frame_size;
if (odd_size_frame) { if (odd_size_frame) {
natural_size.SetSize(natural_size.width() - kOddSizeOffset, frame_size.SetSize(standard_size.width() - kOddSizeOffset,
natural_size.height() - kOddSizeOffset); standard_size.height() - kOddSizeOffset);
} else {
frame_size.SetSize(standard_size.width(), standard_size.height());
} }
auto frame = media::VideoFrame::CreateZeroInitializedFrame( auto frame = media::VideoFrame::CreateZeroInitializedFrame(
opaque_frame ? media::PIXEL_FORMAT_YV12 : media::PIXEL_FORMAT_YV12A, opaque_frame ? media::PIXEL_FORMAT_YV12 : media::PIXEL_FORMAT_YV12A,
natural_size, gfx::Rect(natural_size), natural_size, frame_size, gfx::Rect(frame_size), frame_size,
base::TimeDelta::FromMilliseconds(token)); base::TimeDelta::FromMilliseconds(token));
frame->metadata()->SetTimeTicks( frame->metadata()->SetTimeTicks(
...@@ -372,7 +383,7 @@ class WebMediaPlayerMSTest ...@@ -372,7 +383,7 @@ class WebMediaPlayerMSTest
void timeChanged() override {} void timeChanged() override {}
void repaint() override {} void repaint() override {}
void durationChanged() override {} void durationChanged() override {}
void sizeChanged() override {} void sizeChanged() override;
void playbackStateChanged() override {} void playbackStateChanged() override {}
void setWebLayer(blink::WebLayer* layer) override; void setWebLayer(blink::WebLayer* layer) override;
blink::WebMediaPlayer::TrackId addAudioTrack(const blink::WebString& id, blink::WebMediaPlayer::TrackId addAudioTrack(const blink::WebString& id,
...@@ -419,6 +430,7 @@ class WebMediaPlayerMSTest ...@@ -419,6 +430,7 @@ class WebMediaPlayerMSTest
MOCK_METHOD1(DoNetworkStateChanged, MOCK_METHOD1(DoNetworkStateChanged,
void(blink::WebMediaPlayer::NetworkState)); void(blink::WebMediaPlayer::NetworkState));
MOCK_METHOD1(DoReadyStateChanged, void(blink::WebMediaPlayer::ReadyState)); MOCK_METHOD1(DoReadyStateChanged, void(blink::WebMediaPlayer::ReadyState));
MOCK_METHOD1(CheckSizeChanged, void(gfx::Size));
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
MockRenderFactory* render_factory_; MockRenderFactory* render_factory_;
...@@ -528,6 +540,11 @@ void WebMediaPlayerMSTest::RenderFrame() { ...@@ -528,6 +540,11 @@ void WebMediaPlayerMSTest::RenderFrame() {
base::TimeDelta::FromSecondsD(1.0 / 60.0)); base::TimeDelta::FromSecondsD(1.0 / 60.0));
} }
void WebMediaPlayerMSTest::sizeChanged() {
gfx::Size frame_size = compositor_->GetCurrentSize();
CheckSizeChanged(frame_size);
}
TEST_F(WebMediaPlayerMSTest, Playing_Normal) { TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
// This test sends a bunch of normal frames with increasing timestamps // This test sends a bunch of normal frames with increasing timestamps
// and verifies that they are produced by WebMediaPlayerMS in appropriate // and verifies that they are produced by WebMediaPlayerMS in appropriate
...@@ -546,6 +563,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_Normal) { ...@@ -546,6 +563,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
blink::WebMediaPlayer::ReadyStateHaveMetadata)); blink::WebMediaPlayer::ReadyStateHaveMetadata));
EXPECT_CALL(*this, DoReadyStateChanged( EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::ReadyStateHaveEnoughData)); blink::WebMediaPlayer::ReadyStateHaveEnoughData));
EXPECT_CALL(*this,
CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight)));
message_loop_controller_.RunAndWaitForStatus( message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK); media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this); testing::Mock::VerifyAndClearExpectations(this);
...@@ -574,6 +593,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) { ...@@ -574,6 +593,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
blink::WebMediaPlayer::ReadyStateHaveEnoughData)); blink::WebMediaPlayer::ReadyStateHaveEnoughData));
EXPECT_CALL(*this, DoNetworkStateChanged( EXPECT_CALL(*this, DoNetworkStateChanged(
blink::WebMediaPlayer::NetworkStateFormatError)); blink::WebMediaPlayer::NetworkStateFormatError));
EXPECT_CALL(*this,
CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight)));
message_loop_controller_.RunAndWaitForStatus( message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_ERROR_NETWORK); media::PipelineStatus::PIPELINE_ERROR_NETWORK);
testing::Mock::VerifyAndClearExpectations(this); testing::Mock::VerifyAndClearExpectations(this);
...@@ -602,6 +623,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) { ...@@ -602,6 +623,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
blink::WebMediaPlayer::ReadyStateHaveMetadata)); blink::WebMediaPlayer::ReadyStateHaveMetadata));
EXPECT_CALL(*this, DoReadyStateChanged( EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::ReadyStateHaveEnoughData)); blink::WebMediaPlayer::ReadyStateHaveEnoughData));
gfx::Size frame_size =
gfx::Size(kStandardWidth - (odd_size_frame ? kOddSizeOffset : 0),
kStandardHeight - (odd_size_frame ? kOddSizeOffset : 0));
EXPECT_CALL(*this, CheckSizeChanged(frame_size));
message_loop_controller_.RunAndWaitForStatus( message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK); media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this); testing::Mock::VerifyAndClearExpectations(this);
...@@ -639,6 +664,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) { ...@@ -639,6 +664,10 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
blink::WebMediaPlayer::ReadyStateHaveMetadata)); blink::WebMediaPlayer::ReadyStateHaveMetadata));
EXPECT_CALL(*this, DoReadyStateChanged( EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::ReadyStateHaveEnoughData)); blink::WebMediaPlayer::ReadyStateHaveEnoughData));
gfx::Size frame_size =
gfx::Size(kStandardWidth - (odd_size_frame ? kOddSizeOffset : 0),
kStandardHeight - (odd_size_frame ? kOddSizeOffset : 0));
EXPECT_CALL(*this, CheckSizeChanged(frame_size));
message_loop_controller_.RunAndWaitForStatus( message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK); media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this); testing::Mock::VerifyAndClearExpectations(this);
...@@ -694,7 +723,8 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) { ...@@ -694,7 +723,8 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
blink::WebMediaPlayer::ReadyStateHaveMetadata)); blink::WebMediaPlayer::ReadyStateHaveMetadata));
EXPECT_CALL(*this, DoReadyStateChanged( EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::ReadyStateHaveEnoughData)); blink::WebMediaPlayer::ReadyStateHaveEnoughData));
gfx::Size frame_size = gfx::Size(kStandardWidth, kStandardHeight);
EXPECT_CALL(*this, CheckSizeChanged(frame_size));
message_loop_controller_.RunAndWaitForStatus( message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK); media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this); testing::Mock::VerifyAndClearExpectations(this);
...@@ -720,6 +750,35 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) { ...@@ -720,6 +750,35 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
EXPECT_CALL(*this, DoStopRendering()); EXPECT_CALL(*this, DoStopRendering());
} }
TEST_F(WebMediaPlayerMSTest, FrameSizeChange) {
// During this test, the frame size of the input changes.
// We need to make sure, when sizeChanged() gets called, new size should be
// returned by GetCurrentSize().
MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true);
int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
333, 366, 400, 433, 466, 500, 533, 566, 600};
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps, false, false, 7);
EXPECT_CALL(*this, DoSetWebLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::ReadyStateHaveMetadata));
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::ReadyStateHaveEnoughData));
EXPECT_CALL(*this,
CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight)));
EXPECT_CALL(*this, CheckSizeChanged(
gfx::Size(kStandardWidth * 2, kStandardHeight * 2)));
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this);
EXPECT_CALL(*this, DoSetWebLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
TEST_F(WebMediaPlayerMSTest, HiddenPlayerTests) { TEST_F(WebMediaPlayerMSTest, HiddenPlayerTests) {
LoadAndGetFrameProvider(true); LoadAndGetFrameProvider(true);
......
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