summaryrefslogtreecommitdiffstats
path: root/webkit/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-13 22:16:17 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-13 22:16:17 +0000
commitd4833b74f7042a84c85ffc73b9fdf26f515d9ab8 (patch)
treeec5ed59bff3827a8dfcbf6d2e88b838ad30bce77 /webkit/media
parent3e2694fa1dc6404cc1739bccf865fc71393f0c03 (diff)
downloadchromium_src-d4833b74f7042a84c85ffc73b9fdf26f515d9ab8.zip
chromium_src-d4833b74f7042a84c85ffc73b9fdf26f515d9ab8.tar.gz
chromium_src-d4833b74f7042a84c85ffc73b9fdf26f515d9ab8.tar.bz2
Refactor webkit_media::VideoRendererImpl into standalone class.
As a follow up to r115583 VideoRendererImpl no longer extends VideoRendererBase and instead is a standalone class whose sole purpose is to paint VideoFrames to SkCanvases. BUG=28208 Review URL: http://codereview.chromium.org/9024019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117711 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/media')
-rw-r--r--webkit/media/video_renderer_impl.cc33
-rw-r--r--webkit/media/video_renderer_impl.h48
-rw-r--r--webkit/media/video_renderer_impl_unittest.cc355
-rw-r--r--webkit/media/webmediaplayer_delegate.h2
-rw-r--r--webkit/media/webmediaplayer_impl.cc10
-rw-r--r--webkit/media/webmediaplayer_impl.h6
-rw-r--r--webkit/media/webmediaplayer_proxy.cc26
-rw-r--r--webkit/media/webmediaplayer_proxy.h15
8 files changed, 213 insertions, 282 deletions
diff --git a/webkit/media/video_renderer_impl.cc b/webkit/media/video_renderer_impl.cc
index 87f4955..4663acc 100644
--- a/webkit/media/video_renderer_impl.cc
+++ b/webkit/media/video_renderer_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -229,20 +229,15 @@ static void ConvertVideoFrameToBitmap(
bitmap->unlockPixels();
}
-VideoRendererImpl::VideoRendererImpl(
- const base::Closure& paint_cb,
- const SetOpaqueCB& set_opaque_cb)
- : media::VideoRendererBase(paint_cb, set_opaque_cb),
- bitmap_timestamp_(media::kNoTimestamp) {
+VideoRendererImpl::VideoRendererImpl()
+ : last_frame_timestamp_(media::kNoTimestamp) {
}
VideoRendererImpl::~VideoRendererImpl() {}
-// This method is always called on the renderer's thread.
-void VideoRendererImpl::Paint(SkCanvas* canvas, const gfx::Rect& dest_rect) {
- scoped_refptr<media::VideoFrame> video_frame;
- GetCurrentFrame(&video_frame);
-
+void VideoRendererImpl::Paint(media::VideoFrame* video_frame,
+ SkCanvas* canvas,
+ const gfx::Rect& dest_rect) {
// Paint black rectangle if there isn't a frame available.
if (!video_frame) {
SkPaint paint;
@@ -253,26 +248,24 @@ void VideoRendererImpl::Paint(SkCanvas* canvas, const gfx::Rect& dest_rect) {
static_cast<float>(dest_rect.right()),
static_cast<float>(dest_rect.bottom()),
paint);
- PutCurrentFrame(video_frame);
return;
}
// Scale and convert to RGB in one step if we can.
if (CanFastPaint(canvas, dest_rect)) {
FastPaint(video_frame, canvas, dest_rect);
- PutCurrentFrame(video_frame);
return;
}
- // Check if we should convert and update |bitmap_|.
- if (video_frame->GetTimestamp() != bitmap_timestamp_) {
- ConvertVideoFrameToBitmap(video_frame, &bitmap_);
- bitmap_timestamp_ = video_frame->GetTimestamp();
+ // Check if we should convert and update |last_frame_|.
+ if (last_frame_.isNull() ||
+ video_frame->GetTimestamp() != last_frame_timestamp_) {
+ ConvertVideoFrameToBitmap(video_frame, &last_frame_);
+ last_frame_timestamp_ = video_frame->GetTimestamp();
}
- // Do a slower paint using |bitmap_|.
- SlowPaint(bitmap_, canvas, dest_rect);
- PutCurrentFrame(video_frame);
+ // Do a slower paint using |last_frame_|.
+ SlowPaint(last_frame_, canvas, dest_rect);
}
} // namespace webkit_media
diff --git a/webkit/media/video_renderer_impl.h b/webkit/media/video_renderer_impl.h
index 64b4c01..6ab73b6 100644
--- a/webkit/media/video_renderer_impl.h
+++ b/webkit/media/video_renderer_impl.h
@@ -1,46 +1,42 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WEBKIT_MEDIA_VIDEO_RENDERER_IMPL_H_
#define WEBKIT_MEDIA_VIDEO_RENDERER_IMPL_H_
-#include "base/callback.h"
-#include "media/base/filters.h"
-#include "media/filters/video_renderer_base.h"
+#include "base/time.h"
#include "ui/gfx/rect.h"
#include "third_party/skia/include/core/SkBitmap.h"
class SkCanvas;
+namespace media {
+class VideoFrame;
+}
+
namespace webkit_media {
-// The video renderer implementation used by the media pipeline. It runs
-// primarily on the video renderer thread with the render thread used for
-// painting.
-//
-// TODO(scherkus): don't extend VideoRendererBase and instead bind Paint()
-// and pass to VideoRendererBase as a callback. This will be easier to do
-// when http://crbug.com/108435 is fixed.
-class VideoRendererImpl : public media::VideoRendererBase {
+// Handles rendering of VideoFrames to SkCanvases, doing any necessary YUV
+// conversion and caching of resulting RGB bitmaps.
+class VideoRendererImpl {
public:
- // |paint_cb| is executed whenever a new frame is available for painting.
- // |set_opaque_cb| is used to imform the player whether the video is opaque.
- VideoRendererImpl(
- const base::Closure& paint_cb,
- const SetOpaqueCB& set_opaque_cb);
- virtual ~VideoRendererImpl();
-
- // Paint the current front frame on the |canvas| stretching it to fit the
- // |dest_rect|.
+ VideoRendererImpl();
+ ~VideoRendererImpl();
+
+ // Paints |video_frame| on |canvas|, scaling the result to fit dimensions
+ // specified by |dest_rect|.
//
- // Method called on the render thread.
- void Paint(SkCanvas* canvas, const gfx::Rect& dest_rect);
+ // Black will be painted on |canvas| if |video_frame| is null.
+ void Paint(media::VideoFrame* video_frame,
+ SkCanvas* canvas,
+ const gfx::Rect& dest_rect);
private:
- // An RGB bitmap and corresponding timestamp of converted video frame data.
- SkBitmap bitmap_;
- base::TimeDelta bitmap_timestamp_;
+ // An RGB bitmap and corresponding timestamp of the previously converted
+ // video frame data.
+ SkBitmap last_frame_;
+ base::TimeDelta last_frame_timestamp_;
DISALLOW_COPY_AND_ASSIGN(VideoRendererImpl);
};
diff --git a/webkit/media/video_renderer_impl_unittest.cc b/webkit/media/video_renderer_impl_unittest.cc
index 9f58372..0bd95a7 100644
--- a/webkit/media/video_renderer_impl_unittest.cc
+++ b/webkit/media/video_renderer_impl_unittest.cc
@@ -2,262 +2,199 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/bind.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/test_timeouts.h"
-#include "media/base/limits.h"
-#include "media/base/mock_filters.h"
-#include "media/base/mock_filter_host.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "webkit/media/video_renderer_impl.h"
-using media::PipelineStatistics;
-using media::PipelineStatus;
-using media::VideoDecoder;
using media::VideoFrame;
-using testing::_;
-using testing::NiceMock;
-using testing::Return;
-using testing::ReturnRef;
-
namespace webkit_media {
-static const int64 kFrameDurationMs = 10;
static const int kWidth = 320;
static const int kHeight = 240;
-static const gfx::Size kNaturalSize(kWidth, kHeight);
+static const gfx::Rect kNaturalRect(0, 0, kWidth, kHeight);
+
+// Helper for filling a |canvas| with a solid |color|.
+void FillCanvas(SkCanvas* canvas, SkColor color) {
+ const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true);
+ bitmap.lockPixels();
+ bitmap.eraseColor(color);
+ bitmap.unlockPixels();
+}
+
+// Helper for returning the color of a solid |canvas|.
+SkColor GetColor(SkCanvas* canvas) {
+ const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
+ bitmap.lockPixels();
+ SkColor c = bitmap.getColor(0, 0);
+ bitmap.unlockPixels();
+ return c;
+}
class VideoRendererImplTest : public testing::Test {
public:
- VideoRendererImplTest()
- : timeout_(base::TimeDelta::FromMilliseconds(
- TestTimeouts::action_timeout_ms())),
- cv_(&lock_),
- prerolled_(false) {
- // Bind callbacks with various values for TestPainting() tests.
- natural_frame_cb_ = base::Bind(
- &VideoRendererImplTest::DeliverFrame, base::Unretained(this),
- kWidth, kHeight);
- larger_frame_cb_ = base::Bind(
- &VideoRendererImplTest::DeliverFrame, base::Unretained(this),
- kWidth * 2, kHeight * 2);
- smaller_frame_cb_ = base::Bind(
- &VideoRendererImplTest::DeliverFrame, base::Unretained(this),
- kWidth / 2, kHeight / 2);
- fast_paint_cb_ = base::Bind(
- &VideoRendererImplTest::Paint, base::Unretained(this), true);
- slow_paint_cb_ = base::Bind(
- &VideoRendererImplTest::Paint, base::Unretained(this), false);
-
- // Forward all time requests to lock-protected getter.
- ON_CALL(host_, GetTime())
- .WillByDefault(Invoke(this, &VideoRendererImplTest::GetTime));
- ON_CALL(host_, GetDuration())
- .WillByDefault(Return(base::TimeDelta::FromSeconds(10)));
-
- decoder_ = new media::MockVideoDecoder();
- EXPECT_CALL(*decoder_, natural_size())
- .WillOnce(ReturnRef(kNaturalSize));
-
- // Initialize the renderer.
- base::WaitableEvent event(false, false);
- renderer_ = new VideoRendererImpl(
- base::Bind(
- &VideoRendererImplTest::OnPaint, base::Unretained(this)),
- base::Bind(
- &VideoRendererImplTest::SetOpaque, base::Unretained(this)));
- renderer_->set_host(&host_);
- renderer_->SetPlaybackRate(1.0f);
- renderer_->Initialize(
- decoder_,
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)),
- base::Bind(&VideoRendererImplTest::OnStatistics,
- base::Unretained(this)));
- CHECK(event.TimedWait(timeout_)) << "Timed out waiting to initialize.";
- }
+ enum Color {
+ kRed,
+ kBlue,
+ };
- virtual ~VideoRendererImplTest() {
- // Stop the renderer.
- base::WaitableEvent event(false, false);
- renderer_->Stop(
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
- CHECK(event.TimedWait(timeout_)) << "Timed out waiting to stop.";
- }
+ VideoRendererImplTest();
+ virtual ~VideoRendererImplTest();
- typedef base::Callback<void(int64)> DeliverCB;
- void TestPainting(const DeliverCB& deliver_first_frame,
- const DeliverCB& deliver_remaining_frames,
- const base::Closure& paint) {
- StartPrerolling();
- for (int i = 0; i < media::limits::kMaxVideoFrames; ++i) {
- WaitForRead();
- if (i == 0)
- deliver_first_frame.Run(i * kFrameDurationMs);
- else
- deliver_remaining_frames.Run(i * kFrameDurationMs);
- }
-
- // Wait for prerolling to complete and paint first frame.
- WaitForPrerolled();
- paint.Run();
-
- // Advance to remaining frames and paint again.
- Play();
- for (int i = 1; i < media::limits::kMaxVideoFrames; ++i) {
- SetTime(i * kFrameDurationMs);
- paint.Run();
- }
- WaitForRead();
- paint.Run();
- }
+ // Paints to |canvas| using |renderer_| without any frame data.
+ void PaintWithoutFrame(SkCanvas* canvas);
- const DeliverCB& natural_frame_cb() { return natural_frame_cb_; }
- const DeliverCB& larger_frame_cb() { return larger_frame_cb_; }
- const DeliverCB& smaller_frame_cb() { return smaller_frame_cb_; }
- const base::Closure& fast_paint_cb() { return fast_paint_cb_; }
- const base::Closure& slow_paint_cb() { return slow_paint_cb_; }
+ // Paints the |video_frame| to the |canvas| using |renderer_|, setting the
+ // color of |video_frame| to |color| first.
+ void Paint(VideoFrame* video_frame, SkCanvas* canvas, Color color);
- private:
- void OnPaint() {}
- void SetOpaque(bool) {}
- void OnStatistics(const PipelineStatistics&) {}
-
- void StartPrerolling() {
- EXPECT_CALL(*decoder_, Read(_))
- .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FrameRequested));
-
- renderer_->Seek(base::TimeDelta::FromMilliseconds(0),
- base::Bind(&VideoRendererImplTest::PrerollDone,
- base::Unretained(this),
- media::PIPELINE_OK));
- }
+ // Getters for various frame sizes.
+ VideoFrame* natural_frame() { return natural_frame_; }
+ VideoFrame* larger_frame() { return larger_frame_; }
+ VideoFrame* smaller_frame() { return smaller_frame_; }
- void Play() {
- base::WaitableEvent event(false, false);
- renderer_->Play(
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
- CHECK(event.TimedWait(timeout_)) << "Timed out waiting to play.";
- }
+ // Getters for canvases that trigger the various painting paths.
+ SkCanvas* fast_path_canvas() { return &fast_path_canvas_; }
+ SkCanvas* slow_path_canvas() { return &slow_path_canvas_; }
- void SetTime(int64 timestamp) {
- base::AutoLock l(lock_);
- time_ = base::TimeDelta::FromMilliseconds(timestamp);
- }
+ private:
+ VideoRendererImpl renderer_;
- base::TimeDelta GetTime() {
- base::AutoLock l(lock_);
- return time_;
- }
+ scoped_refptr<VideoFrame> natural_frame_;
+ scoped_refptr<VideoFrame> larger_frame_;
+ scoped_refptr<VideoFrame> smaller_frame_;
- void WaitForRead() {
- base::AutoLock l(lock_);
- if (!read_cb_.is_null())
- return;
- cv_.TimedWait(timeout_);
- CHECK(!read_cb_.is_null()) << "Timed out waiting for read.";
- }
+ SkDevice fast_path_device_;
+ SkCanvas fast_path_canvas_;
+ SkDevice slow_path_device_;
+ SkCanvas slow_path_canvas_;
- void WaitForPrerolled() {
- base::AutoLock l(lock_);
- if (prerolled_)
- return;
- cv_.TimedWait(timeout_);
- CHECK(prerolled_) << "Timed out waiting for prerolled.";
- }
+ DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
+};
- void FrameRequested(const VideoDecoder::ReadCB& callback) {
- base::AutoLock l(lock_);
- CHECK(read_cb_.is_null());
- read_cb_ = callback;
- cv_.Signal();
- }
+VideoRendererImplTest::VideoRendererImplTest()
+ : natural_frame_(VideoFrame::CreateBlackFrame(kWidth, kHeight)),
+ larger_frame_(VideoFrame::CreateBlackFrame(kWidth * 2, kHeight * 2)),
+ smaller_frame_(VideoFrame::CreateBlackFrame(kWidth / 2, kHeight / 2)),
+ fast_path_device_(SkBitmap::kARGB_8888_Config, kWidth, kHeight, true),
+ fast_path_canvas_(&fast_path_device_),
+ slow_path_device_(SkBitmap::kARGB_8888_Config, kWidth, kHeight, false),
+ slow_path_canvas_(&slow_path_device_) {
+ // Give each frame a unique timestamp.
+ natural_frame_->SetTimestamp(base::TimeDelta::FromMilliseconds(1));
+ larger_frame_->SetTimestamp(base::TimeDelta::FromMilliseconds(2));
+ smaller_frame_->SetTimestamp(base::TimeDelta::FromMilliseconds(3));
+}
- void PrerollDone(media::PipelineStatus expected_status,
- PipelineStatus status) {
- base::AutoLock l(lock_);
- EXPECT_EQ(status, expected_status);
- prerolled_ = true;
- cv_.Signal();
- }
+VideoRendererImplTest::~VideoRendererImplTest() {}
- // Allocates a frame of |width| and |height| dimensions with |timestamp|
- // and delivers it to the renderer by running |read_cb_|.
- void DeliverFrame(int width, int height, int64 timestamp) {
- scoped_refptr<VideoFrame> video_frame =
- VideoFrame::CreateBlackFrame(width, height);
- video_frame->SetTimestamp(base::TimeDelta::FromMilliseconds(timestamp));
- video_frame->SetDuration(
- base::TimeDelta::FromMilliseconds(kFrameDurationMs));
-
- VideoDecoder::ReadCB read_cb;
- {
- base::AutoLock l(lock_);
- CHECK(!read_cb_.is_null());
- std::swap(read_cb_, read_cb);
- }
-
- read_cb.Run(video_frame);
- }
+void VideoRendererImplTest::PaintWithoutFrame(SkCanvas* canvas) {
+ renderer_.Paint(NULL, canvas, kNaturalRect);
+}
- // Triggers the fast painting path when |opaque| is true and the slow
- // painting path when |opaque| is false.
- void Paint(bool opaque) {
- SkDevice device(SkBitmap::kARGB_8888_Config, kWidth, kHeight, opaque);
- SkCanvas canvas(&device);
- gfx::Rect rect(0, 0, kWidth, kHeight);
- renderer_->Paint(&canvas, rect);
+void VideoRendererImplTest::Paint(VideoFrame* video_frame,
+ SkCanvas* canvas,
+ Color color) {
+ switch (color) {
+ case kRed:
+ media::FillYUV(video_frame, 76, 84, 255);
+ break;
+ case kBlue:
+ media::FillYUV(video_frame, 29, 255, 107);
+ break;
}
+ renderer_.Paint(video_frame, canvas, kNaturalRect);
+}
- NiceMock<media::MockFilterHost> host_;
- scoped_refptr<VideoRendererImpl> renderer_;
- scoped_refptr<media::MockVideoDecoder> decoder_;
-
- base::TimeDelta timeout_;
-
- base::Lock lock_;
- base::ConditionVariable cv_;
-
- // Protected by |lock_|.
- base::TimeDelta time_;
- VideoDecoder::ReadCB read_cb_;
- bool prerolled_;
-
- // Prebound closures for use with TestPainting().
- DeliverCB natural_frame_cb_;
- DeliverCB larger_frame_cb_;
- DeliverCB smaller_frame_cb_;
- base::Closure slow_paint_cb_;
- base::Closure fast_paint_cb_;
+TEST_F(VideoRendererImplTest, FastPaint_NoFrame) {
+ // Test that black gets painted over canvas.
+ FillCanvas(fast_path_canvas(), SK_ColorRED);
+ PaintWithoutFrame(fast_path_canvas());
+ EXPECT_EQ(SK_ColorBLACK, GetColor(fast_path_canvas()));
+}
- DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
-};
+TEST_F(VideoRendererImplTest, SlowPaint_NoFrame) {
+ // Test that black gets painted over canvas.
+ FillCanvas(slow_path_canvas(), SK_ColorRED);
+ PaintWithoutFrame(slow_path_canvas());
+ EXPECT_EQ(SK_ColorBLACK, GetColor(slow_path_canvas()));
+}
TEST_F(VideoRendererImplTest, FastPaint_Natural) {
- TestPainting(natural_frame_cb(), natural_frame_cb(), fast_paint_cb());
+ Paint(natural_frame(), fast_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(fast_path_canvas()));
}
TEST_F(VideoRendererImplTest, SlowPaint_Natural) {
- TestPainting(natural_frame_cb(), natural_frame_cb(), slow_paint_cb());
+ Paint(natural_frame(), slow_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
}
TEST_F(VideoRendererImplTest, FastPaint_Larger) {
- TestPainting(natural_frame_cb(), larger_frame_cb(), fast_paint_cb());
+ Paint(natural_frame(), fast_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(fast_path_canvas()));
+
+ Paint(larger_frame(), fast_path_canvas(), kBlue);
+ EXPECT_EQ(SK_ColorBLUE, GetColor(fast_path_canvas()));
}
TEST_F(VideoRendererImplTest, SlowPaint_Larger) {
- TestPainting(natural_frame_cb(), larger_frame_cb(), slow_paint_cb());
+ Paint(natural_frame(), slow_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
+
+ Paint(larger_frame(), slow_path_canvas(), kBlue);
+ EXPECT_EQ(SK_ColorBLUE, GetColor(slow_path_canvas()));
}
TEST_F(VideoRendererImplTest, FastPaint_Smaller) {
- TestPainting(natural_frame_cb(), smaller_frame_cb(), fast_paint_cb());
+ Paint(natural_frame(), fast_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(fast_path_canvas()));
+
+ Paint(smaller_frame(), fast_path_canvas(), kBlue);
+ EXPECT_EQ(SK_ColorBLUE, GetColor(fast_path_canvas()));
}
TEST_F(VideoRendererImplTest, SlowPaint_Smaller) {
- TestPainting(natural_frame_cb(), smaller_frame_cb(), slow_paint_cb());
+ Paint(natural_frame(), slow_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
+
+ Paint(smaller_frame(), slow_path_canvas(), kBlue);
+ EXPECT_EQ(SK_ColorBLUE, GetColor(slow_path_canvas()));
+}
+
+TEST_F(VideoRendererImplTest, FastPaint_NoTimestamp) {
+ VideoFrame* video_frame = natural_frame();
+ video_frame->SetTimestamp(media::kNoTimestamp);
+ Paint(video_frame, fast_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(fast_path_canvas()));
+}
+
+TEST_F(VideoRendererImplTest, SlowPaint_NoTimestamp) {
+ VideoFrame* video_frame = natural_frame();
+ video_frame->SetTimestamp(media::kNoTimestamp);
+ Paint(video_frame, slow_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
+}
+
+TEST_F(VideoRendererImplTest, FastPaint_SameVideoFrame) {
+ Paint(natural_frame(), fast_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(fast_path_canvas()));
+
+ // Fast paints always get painted to the canvas.
+ Paint(natural_frame(), fast_path_canvas(), kBlue);
+ EXPECT_EQ(SK_ColorBLUE, GetColor(fast_path_canvas()));
+}
+
+TEST_F(VideoRendererImplTest, SlowPaint_SameVideoFrame) {
+ Paint(natural_frame(), slow_path_canvas(), kRed);
+ EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
+
+ // Slow paints can get cached, expect the old color value.
+ Paint(natural_frame(), slow_path_canvas(), kBlue);
+ EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
}
} // namespace webkit_media
diff --git a/webkit/media/webmediaplayer_delegate.h b/webkit/media/webmediaplayer_delegate.h
index 7fa3409..14edcaa 100644
--- a/webkit/media/webmediaplayer_delegate.h
+++ b/webkit/media/webmediaplayer_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc
index d441e61..4c6c92c 100644
--- a/webkit/media/webmediaplayer_impl.cc
+++ b/webkit/media/webmediaplayer_impl.cc
@@ -24,6 +24,7 @@
#include "media/filters/ffmpeg_demuxer_factory.h"
#include "media/filters/ffmpeg_video_decoder.h"
#include "media/filters/null_audio_renderer.h"
+#include "media/filters/video_renderer_base.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
@@ -33,7 +34,6 @@
#include "webkit/media/buffered_data_source.h"
#include "webkit/media/media_stream_client.h"
#include "webkit/media/simple_data_source.h"
-#include "webkit/media/video_renderer_impl.h"
#include "webkit/media/webmediaplayer_delegate.h"
#include "webkit/media/webmediaplayer_proxy.h"
#include "webkit/media/webvideoframe_impl.h"
@@ -158,12 +158,12 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
main_loop_->AddDestructionObserver(this);
// Create default video renderer.
- scoped_refptr<VideoRendererImpl> video_renderer =
- new VideoRendererImpl(
- base::Bind(&WebMediaPlayerProxy::Repaint, proxy_.get()),
+ scoped_refptr<media::VideoRendererBase> video_renderer =
+ new media::VideoRendererBase(
+ base::Bind(&WebMediaPlayerProxy::Repaint, proxy_),
base::Bind(&WebMediaPlayerProxy::SetOpaque, proxy_.get()));
filter_collection_->AddVideoRenderer(video_renderer);
- proxy_->SetVideoRenderer(video_renderer);
+ proxy_->set_frame_provider(video_renderer);
// A simple data source that keeps all data in memory.
scoped_ptr<media::DataSourceFactory> simple_data_source_factory(
diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h
index 661d7d5..301a4f9 100644
--- a/webkit/media/webmediaplayer_impl.h
+++ b/webkit/media/webmediaplayer_impl.h
@@ -14,7 +14,7 @@
// media::PipelineImpl
// The media playback pipeline.
//
-// VideoRendererImpl
+// VideoRendererBase
// Video renderer object.
//
// WebKit::WebMediaPlayerClient
@@ -29,12 +29,12 @@
// WebMediaPlayerImpl ---> PipelineImpl
// | ^ |
// | | v r
-// | | VideoRendererImpl
+// | | VideoRendererBase
// | | | ^ r
// | r | v r |
// '---> WebMediaPlayerProxy --'
//
-// Notice that WebMediaPlayerProxy and VideoRendererImpl are referencing each
+// Notice that WebMediaPlayerProxy and VideoRendererBase are referencing each
// other. This interdependency has to be treated carefully.
//
// Other issues:
diff --git a/webkit/media/webmediaplayer_proxy.cc b/webkit/media/webmediaplayer_proxy.cc
index f517ad1..2271878 100644
--- a/webkit/media/webmediaplayer_proxy.cc
+++ b/webkit/media/webmediaplayer_proxy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,7 +9,7 @@
#include "base/message_loop.h"
#include "media/base/pipeline_status.h"
#include "media/filters/chunk_demuxer.h"
-#include "webkit/media/video_renderer_impl.h"
+#include "media/filters/video_renderer_base.h"
#include "webkit/media/webmediaplayer_impl.h"
using media::NetworkEvent;
@@ -50,19 +50,17 @@ void WebMediaPlayerProxy::SetOpaque(bool opaque) {
&WebMediaPlayerProxy::SetOpaqueTask, this, opaque));
}
-void WebMediaPlayerProxy::SetVideoRenderer(
- const scoped_refptr<VideoRendererImpl>& video_renderer) {
- video_renderer_ = video_renderer;
-}
-
WebDataSourceBuildObserverHack WebMediaPlayerProxy::GetBuildObserver() {
return base::Bind(&WebMediaPlayerProxy::AddDataSource, this);
}
void WebMediaPlayerProxy::Paint(SkCanvas* canvas, const gfx::Rect& dest_rect) {
DCHECK(MessageLoop::current() == render_loop_);
- if (video_renderer_) {
- video_renderer_->Paint(canvas, dest_rect);
+ if (frame_provider_) {
+ scoped_refptr<media::VideoFrame> video_frame;
+ frame_provider_->GetCurrentFrame(&video_frame);
+ video_renderer_.Paint(video_frame, canvas, dest_rect);
+ frame_provider_->PutCurrentFrame(video_frame);
}
}
@@ -94,7 +92,7 @@ void WebMediaPlayerProxy::AbortDataSources() {
void WebMediaPlayerProxy::Detach() {
DCHECK(MessageLoop::current() == render_loop_);
webmediaplayer_ = NULL;
- video_renderer_ = NULL;
+ frame_provider_ = NULL;
{
base::AutoLock auto_lock(data_sources_lock_);
@@ -184,14 +182,14 @@ void WebMediaPlayerProxy::SetOpaqueTask(bool opaque) {
void WebMediaPlayerProxy::GetCurrentFrame(
scoped_refptr<media::VideoFrame>* frame_out) {
- if (video_renderer_)
- video_renderer_->GetCurrentFrame(frame_out);
+ if (frame_provider_)
+ frame_provider_->GetCurrentFrame(frame_out);
}
void WebMediaPlayerProxy::PutCurrentFrame(
scoped_refptr<media::VideoFrame> frame) {
- if (video_renderer_)
- video_renderer_->PutCurrentFrame(frame);
+ if (frame_provider_)
+ frame_provider_->PutCurrentFrame(frame);
}
void WebMediaPlayerProxy::DemuxerOpened(media::ChunkDemuxer* demuxer) {
diff --git a/webkit/media/webmediaplayer_proxy.h b/webkit/media/webmediaplayer_proxy.h
index 00209ca..e0bb200 100644
--- a/webkit/media/webmediaplayer_proxy.h
+++ b/webkit/media/webmediaplayer_proxy.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -11,6 +11,7 @@
#include "base/synchronization/lock.h"
#include "media/base/pipeline.h"
#include "media/filters/chunk_demuxer_client.h"
+#include "webkit/media/video_renderer_impl.h"
#include "webkit/media/web_data_source.h"
class MessageLoop;
@@ -22,12 +23,12 @@ class Rect;
namespace media {
class VideoFrame;
+class VideoRendererBase;
}
namespace webkit_media {
class WebMediaPlayerImpl;
-class VideoRendererImpl;
// Acts as a thread proxy between the various threads used for multimedia and
// the render thread that WebMediaPlayerImpl is running on.
@@ -38,10 +39,15 @@ class WebMediaPlayerProxy
WebMediaPlayerProxy(MessageLoop* render_loop,
WebMediaPlayerImpl* webmediaplayer);
+ // TODO(scherkus): remove this once VideoRendererBase::PaintCB passes
+ // ownership of the VideoFrame http://crbug.com/108435
+ void set_frame_provider(media::VideoRendererBase* frame_provider) {
+ frame_provider_ = frame_provider;
+ }
+
// Methods for Filter -> WebMediaPlayerImpl communication.
void Repaint();
void SetOpaque(bool opaque);
- void SetVideoRenderer(const scoped_refptr<VideoRendererImpl>& video_renderer);
WebDataSourceBuildObserverHack GetBuildObserver();
// Methods for WebMediaPlayerImpl -> Filter communication.
@@ -112,7 +118,8 @@ class WebMediaPlayerProxy
typedef std::list<scoped_refptr<WebDataSource> > DataSourceList;
DataSourceList data_sources_;
- scoped_refptr<VideoRendererImpl> video_renderer_;
+ scoped_refptr<media::VideoRendererBase> frame_provider_;
+ VideoRendererImpl video_renderer_;
base::Lock lock_;
int outstanding_repaints_;