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.
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"
16 using testing::Return
;
20 ACTION_P(RunClosure
, closure
) {
24 class NullVideoSinkTest
: public testing::Test
,
25 public VideoRendererSink::RenderCallback
{
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(
37 base::Bind(&NullVideoSinkTest::FrameReceived
, base::Unretained(this)),
38 message_loop_
.task_runner()));
39 new_sink
->set_tick_clock_for_testing(&tick_clock_
);
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
,
50 // VideoRendererSink::RenderCallback implementation.
52 scoped_refptr
<VideoFrame
>(base::TimeTicks
,
55 MOCK_METHOD0(OnFrameDropped
, void());
57 MOCK_METHOD1(FrameReceived
, void(const scoped_refptr
<VideoFrame
>&));
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.");
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()));
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
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()));
108 SCOPED_TRACE("Waiting for stop event.");
109 WaitableMessageLoopEvent event
;
110 sink
->set_stop_cb(event
.GetClosure());
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());
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
));
139 EXPECT_CALL(*this, Render(current_time
+ i
* interval
,
140 current_time
+ (i
+ 1) * interval
, false))
141 .WillOnce(DoAll(RunClosure(event
.GetClosure()), Return(nullptr)));
145 ASSERT_LT(base::TimeTicks::Now() - now
, kTestRuns
* interval
);