1 // Copyright (c) 2012 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 "media/base/test_helpers.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/pickle.h"
11 #include "base/run_loop.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/time/time.h"
14 #include "base/timer/timer.h"
15 #include "media/base/audio_buffer.h"
16 #include "media/base/bind_to_current_loop.h"
17 #include "media/base/decoder_buffer.h"
18 #include "ui/gfx/geometry/rect.h"
21 using ::testing::StrictMock
;
25 // Utility mock for testing methods expecting Closures and PipelineStatusCBs.
26 class MockCallback
: public base::RefCountedThreadSafe
<MockCallback
> {
29 MOCK_METHOD0(Run
, void());
30 MOCK_METHOD1(RunWithBool
, void(bool));
31 MOCK_METHOD1(RunWithStatus
, void(PipelineStatus
));
34 friend class base::RefCountedThreadSafe
<MockCallback
>;
35 virtual ~MockCallback();
38 DISALLOW_COPY_AND_ASSIGN(MockCallback
);
41 MockCallback::MockCallback() {}
42 MockCallback::~MockCallback() {}
44 base::Closure
NewExpectedClosure() {
45 StrictMock
<MockCallback
>* callback
= new StrictMock
<MockCallback
>();
46 EXPECT_CALL(*callback
, Run());
47 return base::Bind(&MockCallback::Run
, callback
);
50 base::Callback
<void(bool)> NewExpectedBoolCB(bool success
) {
51 StrictMock
<MockCallback
>* callback
= new StrictMock
<MockCallback
>();
52 EXPECT_CALL(*callback
, RunWithBool(success
));
53 return base::Bind(&MockCallback::RunWithBool
, callback
);
56 PipelineStatusCB
NewExpectedStatusCB(PipelineStatus status
) {
57 StrictMock
<MockCallback
>* callback
= new StrictMock
<MockCallback
>();
58 EXPECT_CALL(*callback
, RunWithStatus(status
));
59 return base::Bind(&MockCallback::RunWithStatus
, callback
);
62 WaitableMessageLoopEvent::WaitableMessageLoopEvent()
63 : message_loop_(base::MessageLoop::current()),
65 status_(PIPELINE_OK
) {
66 DCHECK(message_loop_
);
69 WaitableMessageLoopEvent::~WaitableMessageLoopEvent() {}
71 base::Closure
WaitableMessageLoopEvent::GetClosure() {
72 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
73 return BindToCurrentLoop(base::Bind(
74 &WaitableMessageLoopEvent::OnCallback
, base::Unretained(this),
78 PipelineStatusCB
WaitableMessageLoopEvent::GetPipelineStatusCB() {
79 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
80 return BindToCurrentLoop(base::Bind(
81 &WaitableMessageLoopEvent::OnCallback
, base::Unretained(this)));
84 void WaitableMessageLoopEvent::RunAndWait() {
85 RunAndWaitForStatus(PIPELINE_OK
);
88 void WaitableMessageLoopEvent::RunAndWaitForStatus(PipelineStatus expected
) {
89 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
91 EXPECT_EQ(expected
, status_
);
95 run_loop_
.reset(new base::RunLoop());
96 base::Timer
timer(false, false);
97 timer
.Start(FROM_HERE
, TestTimeouts::action_timeout(), base::Bind(
98 &WaitableMessageLoopEvent::OnTimeout
, base::Unretained(this)));
101 EXPECT_TRUE(signaled_
);
102 EXPECT_EQ(expected
, status_
);
106 void WaitableMessageLoopEvent::OnCallback(PipelineStatus status
) {
107 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
111 // |run_loop_| may be null if the callback fires before RunAndWaitForStatus().
116 void WaitableMessageLoopEvent::OnTimeout() {
117 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
118 ADD_FAILURE() << "Timed out waiting for message loop to quit";
122 static VideoDecoderConfig
GetTestConfig(VideoCodec codec
,
123 gfx::Size coded_size
,
125 gfx::Rect
visible_rect(coded_size
.width(), coded_size
.height());
126 gfx::Size natural_size
= coded_size
;
128 return VideoDecoderConfig(codec
, VIDEO_CODEC_PROFILE_UNKNOWN
,
130 VideoFrame::COLOR_SPACE_UNSPECIFIED
, coded_size
,
131 visible_rect
, natural_size
, NULL
, 0, is_encrypted
);
134 static const gfx::Size
kNormalSize(320, 240);
135 static const gfx::Size
kLargeSize(640, 480);
137 VideoDecoderConfig
TestVideoConfig::Invalid() {
138 return GetTestConfig(kUnknownVideoCodec
, kNormalSize
, false);
141 VideoDecoderConfig
TestVideoConfig::Normal() {
142 return GetTestConfig(kCodecVP8
, kNormalSize
, false);
145 VideoDecoderConfig
TestVideoConfig::NormalEncrypted() {
146 return GetTestConfig(kCodecVP8
, kNormalSize
, true);
149 VideoDecoderConfig
TestVideoConfig::Large() {
150 return GetTestConfig(kCodecVP8
, kLargeSize
, false);
153 VideoDecoderConfig
TestVideoConfig::LargeEncrypted() {
154 return GetTestConfig(kCodecVP8
, kLargeSize
, true);
157 gfx::Size
TestVideoConfig::NormalCodedSize() {
161 gfx::Size
TestVideoConfig::LargeCodedSize() {
166 scoped_refptr
<AudioBuffer
> MakeAudioBuffer(SampleFormat format
,
167 ChannelLayout channel_layout
,
168 size_t channel_count
,
173 base::TimeDelta timestamp
) {
174 const size_t channels
= ChannelLayoutToChannelCount(channel_layout
);
175 scoped_refptr
<AudioBuffer
> output
=
176 AudioBuffer::CreateBuffer(format
,
178 static_cast<int>(channel_count
),
180 static_cast<int>(frames
));
181 output
->set_timestamp(timestamp
);
183 const bool is_planar
=
184 format
== kSampleFormatPlanarS16
|| format
== kSampleFormatPlanarF32
;
186 // Values in channel 0 will be:
189 // start + 2 * increment, ...
190 // While, values in channel 1 will be:
191 // start + frames * increment
192 // start + (frames + 1) * increment
193 // start + (frames + 2) * increment, ...
194 for (size_t ch
= 0; ch
< channels
; ++ch
) {
196 reinterpret_cast<T
*>(output
->channel_data()[is_planar
? ch
: 0]);
197 const T v
= static_cast<T
>(start
+ ch
* frames
* increment
);
198 for (size_t i
= 0; i
< frames
; ++i
) {
199 buffer
[is_planar
? i
: ch
+ i
* channels
] =
200 static_cast<T
>(v
+ i
* increment
);
206 // Instantiate all the types of MakeAudioBuffer() and
207 // MakeAudioBuffer() needed.
208 #define DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(type) \
209 template scoped_refptr<AudioBuffer> MakeAudioBuffer<type>( \
210 SampleFormat format, \
211 ChannelLayout channel_layout, \
212 size_t channel_count, \
217 base::TimeDelta start_time)
218 DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(uint8
);
219 DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int16
);
220 DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int32
);
221 DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(float);
223 static const char kFakeVideoBufferHeader
[] = "FakeVideoBufferForTest";
225 scoped_refptr
<DecoderBuffer
> CreateFakeVideoBufferForTest(
226 const VideoDecoderConfig
& config
,
227 base::TimeDelta timestamp
, base::TimeDelta duration
) {
229 pickle
.WriteString(kFakeVideoBufferHeader
);
230 pickle
.WriteInt(config
.coded_size().width());
231 pickle
.WriteInt(config
.coded_size().height());
232 pickle
.WriteInt64(timestamp
.InMilliseconds());
234 scoped_refptr
<DecoderBuffer
> buffer
= DecoderBuffer::CopyFrom(
235 static_cast<const uint8
*>(pickle
.data()),
236 static_cast<int>(pickle
.size()));
237 buffer
->set_timestamp(timestamp
);
238 buffer
->set_duration(duration
);
239 buffer
->set_is_key_frame(true);
244 bool VerifyFakeVideoBufferForTest(
245 const scoped_refptr
<DecoderBuffer
>& buffer
,
246 const VideoDecoderConfig
& config
) {
247 // Check if the input |buffer| matches the |config|.
248 base::PickleIterator
pickle(base::Pickle(
249 reinterpret_cast<const char*>(buffer
->data()), buffer
->data_size()));
253 bool success
= pickle
.ReadString(&header
) && pickle
.ReadInt(&width
) &&
254 pickle
.ReadInt(&height
);
255 return (success
&& header
== kFakeVideoBufferHeader
&&
256 width
== config
.coded_size().width() &&
257 height
== config
.coded_size().height());
260 CallbackPairChecker::CallbackPairChecker() : expecting_b_(false) {
263 CallbackPairChecker::~CallbackPairChecker() {
264 EXPECT_FALSE(expecting_b_
);
267 void CallbackPairChecker::RecordACalled() {
268 EXPECT_FALSE(expecting_b_
);
272 void CallbackPairChecker::RecordBCalled() {
273 EXPECT_TRUE(expecting_b_
);
274 expecting_b_
= false;
277 void AddLogEntryForTest(MediaLog::MediaLogLevel level
,
278 const std::string
& message
) {
279 DVLOG(1) << "Media log (" << MediaLog::MediaLogLevelToString(level
)