Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / base / null_video_sink_unittest.cc
blob5d6e150d3d9a4fbdade2659f7e5626cf9b531638
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/callback_helpers.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "media/base/null_video_sink.h"
10 #include "media/base/test_helpers.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using testing::_;
15 using testing::DoAll;
16 using testing::Return;
18 namespace media {
20 ACTION_P(RunClosure, closure) {
21 closure.Run();
24 class NullVideoSinkTest : public testing::Test,
25 public VideoRendererSink::RenderCallback {
26 public:
27 NullVideoSinkTest() {
28 // Never use null TimeTicks since they have special connotations.
29 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(12345));
31 ~NullVideoSinkTest() override {}
33 scoped_ptr<NullVideoSink> ConstructSink(bool clockless,
34 base::TimeDelta interval) {
35 scoped_ptr<NullVideoSink> new_sink(new NullVideoSink(
36 clockless, interval,
37 base::Bind(&NullVideoSinkTest::FrameReceived, base::Unretained(this)),
38 message_loop_.task_runner()));
39 new_sink->set_tick_clock_for_testing(&tick_clock_);
40 return new_sink;
43 scoped_refptr<VideoFrame> CreateFrame(base::TimeDelta timestamp) {
44 const gfx::Size natural_size(8, 8);
45 return VideoFrame::CreateFrame(PIXEL_FORMAT_YV12, natural_size,
46 gfx::Rect(natural_size), natural_size,
47 timestamp);
50 // VideoRendererSink::RenderCallback implementation.
51 MOCK_METHOD3(Render,
52 scoped_refptr<VideoFrame>(base::TimeTicks,
53 base::TimeTicks,
54 bool));
55 MOCK_METHOD0(OnFrameDropped, void());
57 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&));
59 protected:
60 base::MessageLoop message_loop_;
61 base::SimpleTestTickClock tick_clock_;
63 DISALLOW_COPY_AND_ASSIGN(NullVideoSinkTest);
66 TEST_F(NullVideoSinkTest, BasicFunctionality) {
67 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(25);
69 scoped_ptr<NullVideoSink> sink = ConstructSink(false, kInterval);
70 scoped_refptr<VideoFrame> test_frame = CreateFrame(base::TimeDelta());
72 // The sink shouldn't have to be started to use the paint method.
73 EXPECT_CALL(*this, FrameReceived(test_frame));
74 sink->PaintFrameUsingOldRenderingPath(test_frame);
77 SCOPED_TRACE("Waiting for sink startup.");
78 sink->Start(this);
79 const base::TimeTicks current_time = tick_clock_.NowTicks();
80 const base::TimeTicks current_interval_end = current_time + kInterval;
81 EXPECT_CALL(*this, Render(current_time, current_interval_end, false))
82 .WillOnce(Return(test_frame));
83 WaitableMessageLoopEvent event;
84 EXPECT_CALL(*this, FrameReceived(test_frame))
85 .WillOnce(RunClosure(event.GetClosure()));
86 event.RunAndWait();
89 // Verify that toggling background rendering mode issues the right bit to
90 // each Render() call.
91 sink->set_background_render(true);
93 // A second call returning the same frame should not result in a new call to
94 // FrameReceived().
96 SCOPED_TRACE("Waiting for second render call.");
97 WaitableMessageLoopEvent event;
98 EXPECT_CALL(*this, Render(_, _, true))
99 .WillOnce(Return(test_frame))
100 .WillOnce(Return(nullptr));
101 EXPECT_CALL(*this, FrameReceived(test_frame)).Times(0);
102 EXPECT_CALL(*this, FrameReceived(scoped_refptr<VideoFrame>()))
103 .WillOnce(RunClosure(event.GetClosure()));
104 event.RunAndWait();
108 SCOPED_TRACE("Waiting for stop event.");
109 WaitableMessageLoopEvent event;
110 sink->set_stop_cb(event.GetClosure());
111 sink->Stop();
112 event.RunAndWait();
116 TEST_F(NullVideoSinkTest, ClocklessFunctionality) {
117 // Construct the sink with a huge interval, it should still complete quickly.
118 const base::TimeDelta interval = base::TimeDelta::FromSeconds(10);
119 scoped_ptr<NullVideoSink> sink = ConstructSink(true, interval);
121 scoped_refptr<VideoFrame> test_frame = CreateFrame(base::TimeDelta());
122 sink->Start(this);
124 EXPECT_CALL(*this, FrameReceived(test_frame)).Times(1);
125 EXPECT_CALL(*this, FrameReceived(scoped_refptr<VideoFrame>())).Times(1);
127 const int kTestRuns = 6;
128 const base::TimeTicks now = base::TimeTicks::Now();
129 const base::TimeTicks current_time = tick_clock_.NowTicks();
131 SCOPED_TRACE("Waiting for multiple render callbacks");
132 WaitableMessageLoopEvent event;
133 for (int i = 0; i < kTestRuns; ++i) {
134 if (i < kTestRuns - 1) {
135 EXPECT_CALL(*this, Render(current_time + i * interval,
136 current_time + (i + 1) * interval, false))
137 .WillOnce(Return(test_frame));
138 } else {
139 EXPECT_CALL(*this, Render(current_time + i * interval,
140 current_time + (i + 1) * interval, false))
141 .WillOnce(DoAll(RunClosure(event.GetClosure()), Return(nullptr)));
144 event.RunAndWait();
145 ASSERT_LT(base::TimeTicks::Now() - now, kTestRuns * interval);
146 sink->Stop();
149 } // namespace media