summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authordalecurtis <dalecurtis@chromium.org>2015-04-29 01:31:01 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-29 08:31:43 +0000
commit6523d600339aad86efcf1c238152e833c248dae5 (patch)
tree505c14a911e4afc30f2f0d5d83918f39bd0dbfae /media
parent3c2ba0ab093e303f5ae04ed8a88c94c19b9e26ff (diff)
downloadchromium_src-6523d600339aad86efcf1c238152e833c248dae5.zip
chromium_src-6523d600339aad86efcf1c238152e833c248dae5.tar.gz
chromium_src-6523d600339aad86efcf1c238152e833c248dae5.tar.bz2
Introduce NullVideoSink for test classes.
Similar to NullAudioSink, but I decided not to use FakeAudioWorker as a generic fake worker since it adds more complexity then we need for the video renderer sink interface. I also didn't want to add pause support or stop callback support to it. BUG=473424 TEST=new unittest, forthcoming pipeline changes. Review URL: https://codereview.chromium.org/1116473002 Cr-Commit-Position: refs/heads/master@{#327450}
Diffstat (limited to 'media')
-rw-r--r--media/base/BUILD.gn3
-rw-r--r--media/base/null_video_sink.cc101
-rw-r--r--media/base/null_video_sink.h93
-rw-r--r--media/base/null_video_sink_unittest.cc147
-rw-r--r--media/media.gyp3
-rw-r--r--media/renderers/video_renderer_impl_unittest.cc60
-rw-r--r--media/test/pipeline_integration_test_base.cc18
-rw-r--r--media/test/pipeline_integration_test_base.h17
8 files changed, 392 insertions, 50 deletions
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 8a50fbe..f8f3c69 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -121,6 +121,8 @@ source_set("base") {
"media_switches.h",
"multi_channel_resampler.cc",
"multi_channel_resampler.h",
+ "null_video_sink.cc",
+ "null_video_sink.h",
"pipeline.cc",
"pipeline.h",
"pipeline_status.h",
@@ -374,6 +376,7 @@ source_set("unittests") {
"gmock_callback_support_unittest.cc",
"key_systems_unittest.cc",
"multi_channel_resampler_unittest.cc",
+ "null_video_sink_unittest.cc",
"pipeline_unittest.cc",
"ranges_unittest.cc",
"run_all_unittests.cc",
diff --git a/media/base/null_video_sink.cc b/media/base/null_video_sink.cc
new file mode 100644
index 0000000..214c499
--- /dev/null
+++ b/media/base/null_video_sink.cc
@@ -0,0 +1,101 @@
+// Copyright 2015 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.
+
+#include "media/base/null_video_sink.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+
+namespace media {
+
+NullVideoSink::NullVideoSink(
+ bool clockless,
+ base::TimeDelta interval,
+ const NewFrameCB& new_frame_cb,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+ : clockless_(clockless),
+ interval_(interval),
+ new_frame_cb_(new_frame_cb),
+ task_runner_(task_runner),
+ started_(false),
+ callback_(nullptr),
+ tick_clock_(&default_tick_clock_) {
+}
+
+NullVideoSink::~NullVideoSink() {
+ DCHECK(!started_);
+}
+
+void NullVideoSink::Start(RenderCallback* callback) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(!started_);
+ callback_ = callback;
+ started_ = true;
+ last_now_ = current_render_time_ = tick_clock_->NowTicks();
+ cancelable_worker_.Reset(
+ base::Bind(&NullVideoSink::CallRender, base::Unretained(this)));
+ task_runner_->PostTask(FROM_HERE, cancelable_worker_.callback());
+}
+
+void NullVideoSink::Stop() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ cancelable_worker_.Cancel();
+ started_ = false;
+ if (!stop_cb_.is_null())
+ base::ResetAndReturn(&stop_cb_).Run();
+}
+
+void NullVideoSink::CallRender() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(started_);
+
+ const base::TimeTicks end_of_interval = current_render_time_ + interval_;
+ if (current_render_time_ > pause_end_time_) {
+ scoped_refptr<VideoFrame> new_frame =
+ callback_->Render(current_render_time_, end_of_interval);
+ const bool is_new_frame = new_frame != last_frame_;
+ last_frame_ = new_frame;
+ if (is_new_frame)
+ new_frame_cb_.Run(new_frame);
+ }
+
+ current_render_time_ += interval_;
+
+ if (clockless_) {
+ task_runner_->PostTask(FROM_HERE, cancelable_worker_.callback());
+ return;
+ }
+
+ // Recompute now to compensate for the cost of Render().
+ const base::TimeTicks now = tick_clock_->NowTicks();
+ base::TimeDelta delay = current_render_time_ - now;
+
+ // If we're behind, find the next nearest on time interval.
+ if (delay < base::TimeDelta())
+ delay += interval_ * (-delay / interval_ + 1);
+ current_render_time_ = now + delay;
+
+ // The tick clock is frozen in this case, so clamp delay to the interval time.
+ // We still want the interval passed to Render() to grow, but we also don't
+ // want the delay used here to increase slowly over time.
+ if (last_now_ == now && delay > interval_)
+ delay = interval_;
+ last_now_ = now;
+
+ task_runner_->PostDelayedTask(FROM_HERE, cancelable_worker_.callback(),
+ delay);
+}
+
+void NullVideoSink::PaintFrameUsingOldRenderingPath(
+ const scoped_refptr<VideoFrame>& frame) {
+ new_frame_cb_.Run(frame);
+}
+
+void NullVideoSink::PauseRenderCallbacks(base::TimeTicks pause_until) {
+ pause_end_time_ = pause_until;
+}
+
+} // namespace media
diff --git a/media/base/null_video_sink.h b/media/base/null_video_sink.h
new file mode 100644
index 0000000..b4c0ac7
--- /dev/null
+++ b/media/base/null_video_sink.h
@@ -0,0 +1,93 @@
+// Copyright 2015 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 MEDIA_AUDIO_NULL_VIDEO_SINK_H_
+#define MEDIA_AUDIO_NULL_VIDEO_SINK_H_
+
+#include "base/cancelable_callback.h"
+#include "base/md5.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
+#include "media/base/video_renderer_sink.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace media {
+
+class MEDIA_EXPORT NullVideoSink : NON_EXPORTED_BASE(public VideoRendererSink) {
+ public:
+ using NewFrameCB = base::Callback<void(const scoped_refptr<VideoFrame>&)>;
+
+ // Periodically calls |callback| every |interval| on |task_runner| once the
+ // sink has been started. If |clockless| is true, the RenderCallback will
+ // be called back to back by repeated post tasks. Optionally, if specified,
+ // |new_frame_cb| will be called for each new frame received.
+ NullVideoSink(bool clockless,
+ base::TimeDelta interval,
+ const NewFrameCB& new_frame_cb,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+ ~NullVideoSink() override;
+
+ // VideoRendererSink implementation.
+ void Start(RenderCallback* callback) override;
+ void Stop() override;
+ void PaintFrameUsingOldRenderingPath(
+ const scoped_refptr<VideoFrame>& frame) override;
+
+ // Allows tests to simulate suspension of Render() callbacks.
+ void PauseRenderCallbacks(base::TimeTicks pause_until);
+
+ void set_tick_clock_for_testing(base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
+ }
+
+ // Sets |stop_cb_|, which will be fired when Stop() is called.
+ void set_stop_cb(const base::Closure& stop_cb) {
+ stop_cb_ = stop_cb;
+ }
+
+ private:
+ // Task that periodically calls Render() to consume video data.
+ void CallRender();
+
+ const bool clockless_;
+ const base::TimeDelta interval_;
+ const NewFrameCB new_frame_cb_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ bool started_;
+ RenderCallback* callback_;
+
+ // Manages cancellation of periodic Render() callback task.
+ base::CancelableClosure cancelable_worker_;
+
+ // Used to determine when a new frame is received.
+ scoped_refptr<VideoFrame> last_frame_;
+
+ // Used to determine the interval given to RenderCallback::Render() as well as
+ // to maintain stable periodicity of callbacks.
+ base::TimeTicks current_render_time_;
+
+ // Used to suspend Render() callbacks to |callback_| for some time.
+ base::TimeTicks pause_end_time_;
+
+ // Allow for an injectable tick clock for testing.
+ base::DefaultTickClock default_tick_clock_;
+ base::TimeTicks last_now_;
+
+ // If specified, used instead of |default_tick_clock_|.
+ base::TickClock* tick_clock_;
+
+ // If set, called when Stop() is called.
+ base::Closure stop_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullVideoSink);
+};
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_NULL_VIDEO_SINK_H_
diff --git a/media/base/null_video_sink_unittest.cc b/media/base/null_video_sink_unittest.cc
new file mode 100644
index 0000000..f2412e5
--- /dev/null
+++ b/media/base/null_video_sink_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2015 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.
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "media/base/null_video_sink.h"
+#include "media/base/test_helpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+
+namespace media {
+
+ACTION_P(RunClosure, closure) {
+ closure.Run();
+}
+
+class NullVideoSinkTest : public testing::Test,
+ public VideoRendererSink::RenderCallback {
+ public:
+ NullVideoSinkTest() {
+ // Never use null TimeTicks since they have special connotations.
+ tick_clock_.Advance(base::TimeDelta::FromMicroseconds(12345));
+ }
+ ~NullVideoSinkTest() override {}
+
+ scoped_ptr<NullVideoSink> ConstructSink(bool clockless,
+ base::TimeDelta interval) {
+ scoped_ptr<NullVideoSink> new_sink(new NullVideoSink(
+ clockless, interval,
+ base::Bind(&NullVideoSinkTest::FrameReceived, base::Unretained(this)),
+ message_loop_.task_runner()));
+ new_sink->set_tick_clock_for_testing(&tick_clock_);
+ return new_sink;
+ }
+
+ scoped_refptr<VideoFrame> CreateFrame(base::TimeDelta timestamp) {
+ const gfx::Size natural_size(8, 8);
+ return VideoFrame::CreateFrame(VideoFrame::YV12, natural_size,
+ gfx::Rect(natural_size), natural_size,
+ timestamp);
+ }
+
+ // VideoRendererSink::RenderCallback implementation.
+ MOCK_METHOD2(Render,
+ scoped_refptr<VideoFrame>(base::TimeTicks, base::TimeTicks));
+ MOCK_METHOD0(OnFrameDropped, void());
+
+ MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&));
+
+ protected:
+ base::MessageLoop message_loop_;
+ base::SimpleTestTickClock tick_clock_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullVideoSinkTest);
+};
+
+TEST_F(NullVideoSinkTest, BasicFunctionality) {
+ const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(25);
+
+ scoped_ptr<NullVideoSink> sink = ConstructSink(false, kInterval);
+ scoped_refptr<VideoFrame> test_frame = CreateFrame(base::TimeDelta());
+
+ // The sink shouldn't have to be started to use the paint method.
+ EXPECT_CALL(*this, FrameReceived(test_frame));
+ sink->PaintFrameUsingOldRenderingPath(test_frame);
+
+ {
+ SCOPED_TRACE("Waiting for sink startup.");
+ sink->Start(this);
+ const base::TimeTicks current_time = tick_clock_.NowTicks();
+ const base::TimeTicks current_interval_end = current_time + kInterval;
+ EXPECT_CALL(*this, Render(current_time, current_interval_end))
+ .WillOnce(Return(test_frame));
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(*this, FrameReceived(test_frame))
+ .WillOnce(RunClosure(event.GetClosure()));
+ event.RunAndWait();
+ }
+
+ // A second call returning the same frame should not result in a new call to
+ // FrameReceived().
+ {
+ SCOPED_TRACE("Waiting for second render call.");
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(*this, Render(_, _))
+ .WillOnce(Return(test_frame))
+ .WillOnce(Return(nullptr));
+ EXPECT_CALL(*this, FrameReceived(test_frame)).Times(0);
+ EXPECT_CALL(*this, FrameReceived(scoped_refptr<VideoFrame>()))
+ .WillOnce(RunClosure(event.GetClosure()));
+ event.RunAndWait();
+ }
+
+ {
+ SCOPED_TRACE("Waiting for stop event.");
+ WaitableMessageLoopEvent event;
+ sink->set_stop_cb(event.GetClosure());
+ sink->Stop();
+ event.RunAndWait();
+ }
+}
+
+TEST_F(NullVideoSinkTest, ClocklessFunctionality) {
+ // Construct the sink with a huge interval, it should still complete quickly.
+ const base::TimeDelta interval = base::TimeDelta::FromSeconds(10);
+ scoped_ptr<NullVideoSink> sink = ConstructSink(true, interval);
+
+ scoped_refptr<VideoFrame> test_frame = CreateFrame(base::TimeDelta());
+ sink->Start(this);
+
+ EXPECT_CALL(*this, FrameReceived(test_frame)).Times(1);
+ EXPECT_CALL(*this, FrameReceived(scoped_refptr<VideoFrame>())).Times(1);
+
+ const int kTestRuns = 6;
+ const base::TimeTicks now = base::TimeTicks::Now();
+ const base::TimeTicks current_time = tick_clock_.NowTicks();
+
+ // Use a RunLoop instead of WaitableMessageLoopEvent() since it will only quit
+ // the loop when it's idle, instead of quitting immediately which is required
+ // when clockless playback is enabled (otherwise the loop is never idle).
+ base::RunLoop run_loop;
+ for (int i = 0; i < kTestRuns; ++i) {
+ if (i < kTestRuns - 1) {
+ EXPECT_CALL(*this, Render(current_time + i * interval,
+ current_time + (i + 1) * interval))
+ .WillOnce(Return(test_frame));
+ } else {
+ EXPECT_CALL(*this, Render(current_time + i * interval,
+ current_time + (i + 1) * interval))
+ .WillOnce(DoAll(RunClosure(run_loop.QuitClosure()), Return(nullptr)));
+ }
+ }
+
+ run_loop.Run();
+ ASSERT_LT(base::TimeTicks::Now() - now, kTestRuns * interval);
+ sink->Stop();
+}
+
+}
diff --git a/media/media.gyp b/media/media.gyp
index e4518de..327c01c 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -332,6 +332,8 @@
'base/media_win.cc',
'base/multi_channel_resampler.cc',
'base/multi_channel_resampler.h',
+ 'base/null_video_sink.cc',
+ 'base/null_video_sink.h',
'base/pipeline.cc',
'base/pipeline.h',
'base/pipeline_status.h',
@@ -1211,6 +1213,7 @@
'base/mac/video_frame_mac_unittests.cc',
'base/media_file_checker_unittest.cc',
'base/multi_channel_resampler_unittest.cc',
+ 'base/null_video_sink_unittest.cc',
'base/pipeline_unittest.cc',
'base/ranges_unittest.cc',
'base/run_all_unittests.cc',
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc
index 86f767f..9203d69 100644
--- a/media/renderers/video_renderer_impl_unittest.cc
+++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -19,6 +19,7 @@
#include "media/base/gmock_callback_support.h"
#include "media/base/limits.h"
#include "media/base/mock_filters.h"
+#include "media/base/null_video_sink.h"
#include "media/base/test_helpers.h"
#include "media/base/video_frame.h"
#include "media/renderers/video_renderer_impl.h"
@@ -53,11 +54,19 @@ class VideoRendererImplTest : public ::testing::Test {
ScopedVector<VideoDecoder> decoders;
decoders.push_back(decoder_);
- renderer_.reset(new VideoRendererImpl(message_loop_.message_loop_proxy(),
- &mock_cb_,
- decoders.Pass(), true,
- new MediaLog()));
+ // Since the Underflow test needs a render interval shorter than the frame
+ // duration, use 120Hz (which makes each interval is < 10ms; ~9.9ms).
+ null_video_sink_.reset(new NullVideoSink(
+ false, base::TimeDelta::FromSecondsD(1.0 / 120),
+ base::Bind(&MockCB::FrameReceived, base::Unretained(&mock_cb_)),
+ message_loop_.task_runner()));
+
+ renderer_.reset(new VideoRendererImpl(
+ message_loop_.message_loop_proxy(), null_video_sink_.get(),
+ decoders.Pass(), true, new MediaLog()));
+
renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
+ null_video_sink_->set_tick_clock_for_testing(tick_clock_);
// Start wallclock time at a non-zero value.
AdvanceWallclockTimeInMs(12345);
@@ -265,19 +274,16 @@ class VideoRendererImplTest : public ::testing::Test {
NiceMock<MockDemuxerStream> demuxer_stream_;
// Use StrictMock<T> to catch missing/extra callbacks.
- // TODO(dalecurtis): Mocks won't be useful for the new rendering path, we'll
- // need fake callback generators like we have for the audio path.
- // http://crbug.com/473424
- class MockCB : public VideoRendererSink {
+ class MockCB {
public:
- MOCK_METHOD1(Start, void(VideoRendererSink::RenderCallback*));
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD1(PaintFrameUsingOldRenderingPath,
- void(const scoped_refptr<VideoFrame>&));
+ MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&));
MOCK_METHOD1(BufferingStateChange, void(BufferingState));
};
StrictMock<MockCB> mock_cb_;
+ // Must be destroyed before |renderer_| since they share |tick_clock_|.
+ scoped_ptr<NullVideoSink> null_video_sink_;
+
private:
base::TimeTicks GetWallClockTime(base::TimeDelta time) {
base::AutoLock l(lock_);
@@ -355,7 +361,7 @@ TEST_F(VideoRendererImplTest, Initialize) {
TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
Initialize();
QueueFrames("0 10 20 30");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(0);
Destroy();
@@ -369,7 +375,7 @@ TEST_F(VideoRendererImplTest, DestroyWhileInitializing) {
TEST_F(VideoRendererImplTest, DestroyWhileFlushing) {
Initialize();
QueueFrames("0 10 20 30");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(0);
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING));
@@ -380,7 +386,7 @@ TEST_F(VideoRendererImplTest, DestroyWhileFlushing) {
TEST_F(VideoRendererImplTest, Play) {
Initialize();
QueueFrames("0 10 20 30");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(0);
Destroy();
@@ -399,10 +405,12 @@ TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) {
TEST_F(VideoRendererImplTest, DecodeError_Playing) {
Initialize();
QueueFrames("0 10 20 30");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(0);
+ WaitForPendingRead();
+
QueueFrames("error");
SatisfyPendingRead();
WaitForError(PIPELINE_ERROR_DECODE);
@@ -420,7 +428,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) {
Initialize();
QueueFrames("50 60 70 80 90");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(60)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(60);
Destroy();
@@ -430,7 +438,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
Initialize();
QueueFrames("50 60 70 80 90");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(50)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(59);
Destroy();
@@ -440,7 +448,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
Initialize();
QueueFrames("50 60 70 80 90");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(60)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(61);
Destroy();
@@ -452,7 +460,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
QueueFrames("0");
// Expect some amount of have enough/nothing due to only requiring one frame.
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
.Times(AnyNumber());
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
@@ -463,7 +471,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
SatisfyPendingRead();
WaitableMessageLoopEvent event;
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(10)))
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10)))
.WillOnce(RunClosure(event.GetClosure()));
AdvanceTimeInMs(10);
event.RunAndWait();
@@ -475,7 +483,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) {
Initialize();
QueueFrames("0 10 20 30");
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(0);
@@ -496,7 +504,7 @@ TEST_F(VideoRendererImplTest, Underflow) {
{
WaitableMessageLoopEvent event;
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
.WillOnce(RunClosure(event.GetClosure()));
StartPlayingFrom(0);
@@ -509,11 +517,11 @@ TEST_F(VideoRendererImplTest, Underflow) {
{
SCOPED_TRACE("Waiting for frame drops");
WaitableMessageLoopEvent event;
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(10)))
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10)))
.Times(0);
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(20)))
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20)))
.Times(0);
- EXPECT_CALL(mock_cb_, PaintFrameUsingOldRenderingPath(HasTimestamp(30)))
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30)))
.WillOnce(RunClosure(event.GetClosure()));
AdvanceTimeInMs(31);
event.RunAndWait();
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc
index c17431a..5217925 100644
--- a/media/test/pipeline_integration_test_base.cc
+++ b/media/test/pipeline_integration_test_base.cc
@@ -35,9 +35,6 @@ namespace media {
const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e";
const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,";
-MockVideoRendererSink::MockVideoRendererSink() {}
-MockVideoRendererSink::~MockVideoRendererSink() {}
-
PipelineIntegrationTestBase::PipelineIntegrationTestBase()
: hashing_enabled_(false),
clockless_playback_(false),
@@ -240,14 +237,17 @@ scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer() {
new FFmpegVideoDecoder(message_loop_.message_loop_proxy()));
#endif
- EXPECT_CALL(video_sink_, PaintFrameUsingOldRenderingPath(_))
- .WillRepeatedly(
- Invoke(this, &PipelineIntegrationTestBase::OnVideoFramePaint));
+ // Simulate a 60Hz rendering sink.
+ video_sink_.reset(new NullVideoSink(
+ clockless_playback_, base::TimeDelta::FromSecondsD(1.0 / 60),
+ base::Bind(&PipelineIntegrationTestBase::OnVideoFramePaint,
+ base::Unretained(this)),
+ message_loop_.task_runner()));
// Disable frame dropping if hashing is enabled.
- scoped_ptr<VideoRenderer> video_renderer(
- new VideoRendererImpl(message_loop_.message_loop_proxy(), &video_sink_,
- video_decoders.Pass(), false, new MediaLog()));
+ scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
+ message_loop_.message_loop_proxy(), video_sink_.get(),
+ video_decoders.Pass(), false, new MediaLog()));
if (!clockless_playback_) {
audio_sink_ = new NullAudioSink(message_loop_.message_loop_proxy());
diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h
index aa41337..efbffea 100644
--- a/media/test/pipeline_integration_test_base.h
+++ b/media/test/pipeline_integration_test_base.h
@@ -12,6 +12,7 @@
#include "media/base/audio_hardware_config.h"
#include "media/base/demuxer.h"
#include "media/base/media_keys.h"
+#include "media/base/null_video_sink.h"
#include "media/base/pipeline.h"
#include "media/base/text_track.h"
#include "media/base/text_track_config.h"
@@ -45,20 +46,6 @@ class DummyTickClock : public base::TickClock {
base::TimeTicks now_;
};
-// TODO(dalecurtis): Mocks won't be useful for the new rendering path, we'll
-// need fake callback generators like we have for the audio path.
-// http://crbug.com/473424
-class MockVideoRendererSink : public VideoRendererSink {
- public:
- MockVideoRendererSink();
- ~MockVideoRendererSink() override;
-
- MOCK_METHOD1(Start, void(VideoRendererSink::RenderCallback*));
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD1(PaintFrameUsingOldRenderingPath,
- void(const scoped_refptr<VideoFrame>&));
-};
-
// Integration tests for Pipeline. Real demuxers, real decoders, and
// base renderer implementations are used to verify pipeline functionality. The
// renderers used in these tests rely heavily on the AudioRendererBase &
@@ -119,7 +106,7 @@ class PipelineIntegrationTestBase {
scoped_ptr<Pipeline> pipeline_;
scoped_refptr<NullAudioSink> audio_sink_;
scoped_refptr<ClocklessAudioSink> clockless_audio_sink_;
- testing::NiceMock<MockVideoRendererSink> video_sink_;
+ scoped_ptr<NullVideoSink> video_sink_;
bool ended_;
PipelineStatus pipeline_status_;
Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;