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/test/test_timeouts.h"
12 #include "base/time/time.h"
13 #include "base/timer/timer.h"
14 #include "media/base/audio_buffer.h"
15 #include "media/base/bind_to_loop.h"
16 #include "media/base/decoder_buffer.h"
17 #include "ui/gfx/rect.h"
20 using ::testing::StrictMock
;
24 // Utility mock for testing methods expecting Closures and PipelineStatusCBs.
25 class MockCallback
: public base::RefCountedThreadSafe
<MockCallback
> {
28 MOCK_METHOD0(Run
, void());
29 MOCK_METHOD1(RunWithStatus
, void(PipelineStatus
));
32 friend class base::RefCountedThreadSafe
<MockCallback
>;
33 virtual ~MockCallback();
36 DISALLOW_COPY_AND_ASSIGN(MockCallback
);
39 MockCallback::MockCallback() {}
40 MockCallback::~MockCallback() {}
42 base::Closure
NewExpectedClosure() {
43 StrictMock
<MockCallback
>* callback
= new StrictMock
<MockCallback
>();
44 EXPECT_CALL(*callback
, Run());
45 return base::Bind(&MockCallback::Run
, callback
);
48 PipelineStatusCB
NewExpectedStatusCB(PipelineStatus status
) {
49 StrictMock
<MockCallback
>* callback
= new StrictMock
<MockCallback
>();
50 EXPECT_CALL(*callback
, RunWithStatus(status
));
51 return base::Bind(&MockCallback::RunWithStatus
, callback
);
54 WaitableMessageLoopEvent::WaitableMessageLoopEvent()
55 : message_loop_(base::MessageLoop::current()),
57 status_(PIPELINE_OK
) {
58 DCHECK(message_loop_
);
61 WaitableMessageLoopEvent::~WaitableMessageLoopEvent() {}
63 base::Closure
WaitableMessageLoopEvent::GetClosure() {
64 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
65 return BindToLoop(message_loop_
->message_loop_proxy(), base::Bind(
66 &WaitableMessageLoopEvent::OnCallback
, base::Unretained(this),
70 PipelineStatusCB
WaitableMessageLoopEvent::GetPipelineStatusCB() {
71 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
72 return BindToLoop(message_loop_
->message_loop_proxy(), base::Bind(
73 &WaitableMessageLoopEvent::OnCallback
, base::Unretained(this)));
76 void WaitableMessageLoopEvent::RunAndWait() {
77 RunAndWaitForStatus(PIPELINE_OK
);
80 void WaitableMessageLoopEvent::RunAndWaitForStatus(PipelineStatus expected
) {
81 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
83 EXPECT_EQ(expected
, status_
);
87 base::Timer
timer(false, false);
88 timer
.Start(FROM_HERE
, TestTimeouts::action_timeout(), base::Bind(
89 &WaitableMessageLoopEvent::OnTimeout
, base::Unretained(this)));
92 EXPECT_TRUE(signaled_
);
93 EXPECT_EQ(expected
, status_
);
96 void WaitableMessageLoopEvent::OnCallback(PipelineStatus status
) {
97 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
100 message_loop_
->QuitWhenIdle();
103 void WaitableMessageLoopEvent::OnTimeout() {
104 DCHECK_EQ(message_loop_
, base::MessageLoop::current());
105 ADD_FAILURE() << "Timed out waiting for message loop to quit";
106 message_loop_
->QuitWhenIdle();
109 static VideoDecoderConfig
GetTestConfig(VideoCodec codec
,
110 gfx::Size coded_size
,
112 gfx::Rect
visible_rect(coded_size
.width(), coded_size
.height());
113 gfx::Size natural_size
= coded_size
;
115 return VideoDecoderConfig(codec
, VIDEO_CODEC_PROFILE_UNKNOWN
,
116 VideoFrame::YV12
, coded_size
, visible_rect
, natural_size
,
117 NULL
, 0, is_encrypted
);
120 static const gfx::Size
kNormalSize(320, 240);
121 static const gfx::Size
kLargeSize(640, 480);
123 VideoDecoderConfig
TestVideoConfig::Invalid() {
124 return GetTestConfig(kUnknownVideoCodec
, kNormalSize
, false);
127 VideoDecoderConfig
TestVideoConfig::Normal() {
128 return GetTestConfig(kCodecVP8
, kNormalSize
, false);
131 VideoDecoderConfig
TestVideoConfig::NormalEncrypted() {
132 return GetTestConfig(kCodecVP8
, kNormalSize
, true);
135 VideoDecoderConfig
TestVideoConfig::Large() {
136 return GetTestConfig(kCodecVP8
, kLargeSize
, false);
139 VideoDecoderConfig
TestVideoConfig::LargeEncrypted() {
140 return GetTestConfig(kCodecVP8
, kLargeSize
, true);
143 gfx::Size
TestVideoConfig::NormalCodedSize() {
147 gfx::Size
TestVideoConfig::LargeCodedSize() {
152 scoped_refptr
<AudioBuffer
> MakeInterleavedAudioBuffer(
158 base::TimeDelta start_time
,
159 base::TimeDelta duration
) {
160 DCHECK(format
== kSampleFormatU8
|| format
== kSampleFormatS16
||
161 format
== kSampleFormatS32
|| format
== kSampleFormatF32
);
163 // Create a block of memory with values:
166 // start + 2 * increment, ...
167 // Since this is interleaved data, channel 0 data will be:
169 // start + channels * increment
170 // start + 2 * channels * increment, ...
171 int buffer_size
= frames
* channels
* sizeof(T
);
172 scoped_ptr
<uint8
[]> memory(new uint8
[buffer_size
]);
173 uint8
* data
[] = { memory
.get() };
174 T
* buffer
= reinterpret_cast<T
*>(memory
.get());
175 for (int i
= 0; i
< frames
* channels
; ++i
) {
179 return AudioBuffer::CopyFrom(
180 format
, channels
, frames
, data
, start_time
, duration
);
184 scoped_refptr
<AudioBuffer
> MakePlanarAudioBuffer(
190 base::TimeDelta start_time
,
191 base::TimeDelta duration
) {
192 DCHECK(format
== kSampleFormatPlanarF32
|| format
== kSampleFormatPlanarS16
);
194 // Create multiple blocks of data, one for each channel.
195 // Values in channel 0 will be:
198 // start + 2 * increment, ...
199 // Values in channel 1 will be:
200 // start + frames * increment
201 // start + (frames + 1) * increment
202 // start + (frames + 2) * increment, ...
203 int buffer_size
= frames
* sizeof(T
);
204 scoped_ptr
<uint8
*[]> data(new uint8
*[channels
]);
205 scoped_ptr
<uint8
[]> memory(new uint8
[channels
* buffer_size
]);
206 for (int i
= 0; i
< channels
; ++i
) {
207 data
.get()[i
] = memory
.get() + i
* buffer_size
;
208 T
* buffer
= reinterpret_cast<T
*>(data
.get()[i
]);
209 for (int j
= 0; j
< frames
; ++j
) {
214 return AudioBuffer::CopyFrom(
215 format
, channels
, frames
, data
.get(), start_time
, duration
);
218 // Instantiate all the types of MakeInterleavedAudioBuffer() and
219 // MakePlanarAudioBuffer() needed.
221 #define DEFINE_INTERLEAVED_INSTANCE(type) \
222 template scoped_refptr<AudioBuffer> MakeInterleavedAudioBuffer<type>( \
223 SampleFormat format, \
228 base::TimeDelta start_time, \
229 base::TimeDelta duration)
230 DEFINE_INTERLEAVED_INSTANCE(uint8
);
231 DEFINE_INTERLEAVED_INSTANCE(int16
);
232 DEFINE_INTERLEAVED_INSTANCE(int32
);
233 DEFINE_INTERLEAVED_INSTANCE(float);
235 #define DEFINE_PLANAR_INSTANCE(type) \
236 template scoped_refptr<AudioBuffer> MakePlanarAudioBuffer<type>( \
237 SampleFormat format, \
242 base::TimeDelta start_time, \
243 base::TimeDelta duration);
244 DEFINE_PLANAR_INSTANCE(int16
);
245 DEFINE_PLANAR_INSTANCE(float);
247 static const char kFakeVideoBufferHeader
[] = "FakeVideoBufferForTest";
249 scoped_refptr
<DecoderBuffer
> CreateFakeVideoBufferForTest(
250 const VideoDecoderConfig
& config
,
251 base::TimeDelta timestamp
, base::TimeDelta duration
) {
253 pickle
.WriteString(kFakeVideoBufferHeader
);
254 pickle
.WriteInt(config
.coded_size().width());
255 pickle
.WriteInt(config
.coded_size().height());
256 pickle
.WriteInt64(timestamp
.InMilliseconds());
258 scoped_refptr
<DecoderBuffer
> buffer
= DecoderBuffer::CopyFrom(
259 static_cast<const uint8
*>(pickle
.data()),
260 static_cast<int>(pickle
.size()));
261 buffer
->set_timestamp(timestamp
);
262 buffer
->set_duration(duration
);
267 bool VerifyFakeVideoBufferForTest(
268 const scoped_refptr
<DecoderBuffer
>& buffer
,
269 const VideoDecoderConfig
& config
) {
270 // Check if the input |buffer| matches the |config|.
271 PickleIterator
pickle(Pickle(reinterpret_cast<const char*>(buffer
->data()),
272 buffer
->data_size()));
276 bool success
= pickle
.ReadString(&header
) && pickle
.ReadInt(&width
) &&
277 pickle
.ReadInt(&height
);
278 return (success
&& header
== kFakeVideoBufferHeader
&&
279 width
== config
.coded_size().width() &&
280 height
== config
.coded_size().height());