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 "base/memory/shared_memory.h"
6 #include "base/message_loop/message_loop.h"
7 #include "content/child/child_process.h"
8 #include "content/common/media/video_capture_messages.h"
9 #include "content/renderer/media/video_capture_impl.h"
10 #include "media/base/bind_to_current_loop.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 using ::testing::AtLeast
;
16 using ::testing::InvokeWithoutArgs
;
17 using ::testing::Return
;
18 using ::testing::SaveArg
;
22 // TODO(ajose): http://crbug.com/522145 Improve and expand these tests.
23 // In particular, exercise VideoCaptureHostMsg_BufferReady.
24 class MockVideoCaptureMessageFilter
: public VideoCaptureMessageFilter
{
26 MockVideoCaptureMessageFilter() : VideoCaptureMessageFilter() {}
28 // Filter implementation.
29 MOCK_METHOD1(Send
, bool(IPC::Message
* message
));
32 virtual ~MockVideoCaptureMessageFilter() {}
35 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureMessageFilter
);
38 struct BufferReceivedTestArg
{
39 BufferReceivedTestArg(media::VideoPixelFormat pixel_format
,
40 const std::vector
<gpu::MailboxHolder
>& mailbox_holders
)
41 : pixel_format(pixel_format
), mailbox_holders(mailbox_holders
) {}
43 BufferReceivedTestArg(media::VideoPixelFormat pixel_format
)
44 : pixel_format(pixel_format
) {}
46 media::VideoPixelFormat pixel_format
;
47 std::vector
<gpu::MailboxHolder
> mailbox_holders
;
50 static const BufferReceivedTestArg kBufferFormats
[] = {
51 BufferReceivedTestArg(media::PIXEL_FORMAT_I420
),
52 BufferReceivedTestArg(
53 media::PIXEL_FORMAT_ARGB
,
54 std::vector
<gpu::MailboxHolder
>(
55 1, gpu::MailboxHolder(gpu::Mailbox::Generate(), 0, 0)))};
57 class VideoCaptureImplTest
:
58 public ::testing::TestWithParam
<BufferReceivedTestArg
> {
60 class MockVideoCaptureImpl
: public VideoCaptureImpl
{
62 MockVideoCaptureImpl(const media::VideoCaptureSessionId id
,
63 VideoCaptureMessageFilter
* filter
)
64 : VideoCaptureImpl(id
, filter
), received_buffer_count_(0) {
66 ~MockVideoCaptureImpl() override
{}
68 // Override Send() to mimic device to send events.
69 void Send(IPC::Message
* message
) override
{
72 // In this method, messages are sent to the according handlers as if
75 IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureImpl
, *message
)
76 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start
, DeviceStartCapture
)
77 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause
, DevicePauseCapture
)
78 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop
, DeviceStopCapture
)
79 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady
,
80 DeviceReceiveEmptyBuffer
)
81 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats
,
82 DeviceGetSupportedFormats
)
83 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse
,
84 DeviceGetFormatsInUse
)
85 IPC_MESSAGE_UNHANDLED(handled
= false)
91 void DeviceStartCapture(int device_id
,
92 media::VideoCaptureSessionId session_id
,
93 const media::VideoCaptureParams
& params
) {
94 // Do not call OnStateChanged(VIDEO_CAPTURE_STATE_STARTED) here, as this
95 // does not accurately reflect the behavior of the VideoCaptureHost.
98 void DevicePauseCapture(int device_id
) {}
100 void DeviceStopCapture(int device_id
) {
101 OnStateChanged(VIDEO_CAPTURE_STATE_STOPPED
);
104 void DeviceReceiveEmptyBuffer(int device_id
,
107 double consumer_resource_utilization
) {
108 received_buffer_count_
++;
111 void DeviceGetSupportedFormats(int device_id
,
112 media::VideoCaptureSessionId session_id
) {
113 // When the mock message filter receives a request for the device
114 // supported formats, replies immediately with an empty format list.
115 OnDeviceSupportedFormatsEnumerated(media::VideoCaptureFormats());
118 void DeviceGetFormatsInUse(int device_id
,
119 media::VideoCaptureSessionId session_id
) {
120 OnDeviceFormatsInUseReceived(media::VideoCaptureFormats());
123 void ReceiveStateChangeMessage(VideoCaptureState state
) {
124 OnStateChanged(state
);
127 int received_buffer_count() const { return received_buffer_count_
; }
130 int received_buffer_count_
;
133 VideoCaptureImplTest() {
134 params_small_
.requested_format
= media::VideoCaptureFormat(
135 gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420
);
137 params_large_
.requested_format
= media::VideoCaptureFormat(
138 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420
);
140 child_process_
.reset(new ChildProcess());
142 message_filter_
= new MockVideoCaptureMessageFilter
;
145 video_capture_impl_
.reset(new MockVideoCaptureImpl(
146 session_id_
, message_filter_
.get()));
148 video_capture_impl_
->device_id_
= 2;
151 virtual ~VideoCaptureImplTest() {
155 MOCK_METHOD2(OnFrameReady
,
156 void(const scoped_refptr
<media::VideoFrame
>&, base::TimeTicks
));
157 MOCK_METHOD1(OnStateUpdate
, void(VideoCaptureState
));
158 MOCK_METHOD1(OnDeviceFormatsInUse
,
159 void(const media::VideoCaptureFormats
&));
160 MOCK_METHOD1(OnDeviceSupportedFormats
,
161 void(const media::VideoCaptureFormats
&));
164 video_capture_impl_
->Init();
167 void StartCapture(const media::VideoCaptureParams
& params
) {
168 video_capture_impl_
->StartCapture(
169 params
, base::Bind(&VideoCaptureImplTest::OnStateUpdate
,
170 base::Unretained(this)),
171 base::Bind(&VideoCaptureImplTest::OnFrameReady
,
172 base::Unretained(this)));
175 void StopCapture() { video_capture_impl_
->StopCapture(); }
177 void NewBuffer(int buffer_id
, const base::SharedMemory
& shm
) {
178 video_capture_impl_
->OnBufferCreated(
179 base::SharedMemory::DuplicateHandle(shm
.handle()),
180 shm
.mapped_size(), buffer_id
);
183 void BufferReceived(int buffer_id
, const gfx::Size
& size
,
184 media::VideoPixelFormat pixel_format
,
185 const std::vector
<gpu::MailboxHolder
>& mailbox_holders
) {
186 video_capture_impl_
->OnBufferReceived(
187 buffer_id
, base::TimeTicks::Now(), base::DictionaryValue(),
188 pixel_format
, media::VideoFrame::STORAGE_SHMEM
, size
,
189 gfx::Rect(size
), mailbox_holders
);
192 void BufferDestroyed(int buffer_id
) {
193 video_capture_impl_
->OnBufferDestroyed(buffer_id
);
197 video_capture_impl_
->DeInit();
200 void GetDeviceSupportedFormats() {
201 const base::Callback
<void(const media::VideoCaptureFormats
&)>
202 callback
= base::Bind(
203 &VideoCaptureImplTest::OnDeviceSupportedFormats
,
204 base::Unretained(this));
205 video_capture_impl_
->GetDeviceSupportedFormats(callback
);
208 void GetDeviceFormatsInUse() {
209 const base::Callback
<void(const media::VideoCaptureFormats
&)>
210 callback
= base::Bind(
211 &VideoCaptureImplTest::OnDeviceFormatsInUse
,
212 base::Unretained(this));
213 video_capture_impl_
->GetDeviceFormatsInUse(callback
);
216 base::MessageLoop message_loop_
;
217 scoped_ptr
<ChildProcess
> child_process_
;
218 scoped_refptr
<MockVideoCaptureMessageFilter
> message_filter_
;
219 media::VideoCaptureSessionId session_id_
;
220 scoped_ptr
<MockVideoCaptureImpl
> video_capture_impl_
;
221 media::VideoCaptureParams params_small_
;
222 media::VideoCaptureParams params_large_
;
225 DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest
);
228 // Execute SetCapture() and StopCapture() for one client.
229 TEST_F(VideoCaptureImplTest
, Simple
) {
230 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED
));
231 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED
));
234 StartCapture(params_small_
);
239 // Check that a request to GetDeviceSupportedFormats() ends up eventually in the
240 // provided callback.
241 TEST_F(VideoCaptureImplTest
, GetDeviceFormats
) {
242 EXPECT_CALL(*this, OnDeviceSupportedFormats(_
));
245 GetDeviceSupportedFormats();
249 // Check that two requests to GetDeviceSupportedFormats() end up eventually
250 // calling the provided callbacks.
251 TEST_F(VideoCaptureImplTest
, TwoClientsGetDeviceFormats
) {
252 EXPECT_CALL(*this, OnDeviceSupportedFormats(_
)).Times(2);
255 GetDeviceSupportedFormats();
256 GetDeviceSupportedFormats();
260 // Check that a request to GetDeviceFormatsInUse() ends up eventually in the
261 // provided callback.
262 TEST_F(VideoCaptureImplTest
, GetDeviceFormatsInUse
) {
263 EXPECT_CALL(*this, OnDeviceFormatsInUse(_
));
266 GetDeviceFormatsInUse();
270 TEST_P(VideoCaptureImplTest
, BufferReceivedWithFormat
) {
271 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED
)).Times(1);
272 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED
)).Times(1);
273 EXPECT_CALL(*this, OnFrameReady(_
, _
)).Times(1);
275 const BufferReceivedTestArg
& buffer_arg
= GetParam();
276 const gfx::Size
size(1280, 720);
278 // Create a fake shared memory for buffer.
279 base::SharedMemory shm
;
280 const size_t frame_size
= media::VideoFrame::AllocationSize(
281 buffer_arg
.pixel_format
, size
);
282 ASSERT_TRUE(shm
.CreateAndMapAnonymous(frame_size
));
284 media::VideoCaptureParams params
;
285 params
.requested_format
= media::VideoCaptureFormat(
286 size
, 30, buffer_arg
.pixel_format
);
289 StartCapture(params
);
291 BufferReceived(0, size
, buffer_arg
.pixel_format
, buffer_arg
.mailbox_holders
);
297 INSTANTIATE_TEST_CASE_P(I420AndARGB
,
298 VideoCaptureImplTest
,
299 testing::ValuesIn(kBufferFormats
));
301 TEST_F(VideoCaptureImplTest
, BufferReceivedAfterStop
) {
302 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED
)).Times(1);
303 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED
)).Times(1);
304 EXPECT_CALL(*this, OnFrameReady(_
, _
)).Times(0);
306 // Create a fake shared memory for buffer.
307 base::SharedMemory shm
;
308 const size_t i420_frame_size
= media::VideoFrame::AllocationSize(
309 media::PIXEL_FORMAT_I420
, params_large_
.requested_format
.frame_size
);
310 ASSERT_TRUE(shm
.CreateAndMapAnonymous(i420_frame_size
));
313 StartCapture(params_large_
);
316 BufferReceived(0, params_large_
.requested_format
.frame_size
,
317 media::PIXEL_FORMAT_I420
, std::vector
<gpu::MailboxHolder
>());
321 EXPECT_EQ(this->video_capture_impl_
->received_buffer_count(), 1);
324 TEST_F(VideoCaptureImplTest
, EndedBeforeStop
) {
325 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED
));
326 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED
));
329 StartCapture(params_small_
);
331 // Receive state change message from browser.
332 video_capture_impl_
->ReceiveStateChangeMessage(VIDEO_CAPTURE_STATE_ENDED
);
338 TEST_F(VideoCaptureImplTest
, ErrorBeforeStop
) {
339 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED
));
340 EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_ERROR
));
343 StartCapture(params_small_
);
345 // Receive state change message from browser.
346 video_capture_impl_
->ReceiveStateChangeMessage(VIDEO_CAPTURE_STATE_ERROR
);
352 } // namespace content