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 // Unit test for VideoCaptureManager.
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "content/browser/browser_thread_impl.h"
15 #include "content/browser/renderer_host/media/media_stream_provider.h"
16 #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
17 #include "content/browser/renderer_host/media/video_capture_manager.h"
18 #include "content/common/media/media_stream_options.h"
19 #include "media/video/capture/fake_video_capture_device_factory.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
24 using ::testing::AnyNumber
;
25 using ::testing::InSequence
;
26 using ::testing::Return
;
27 using ::testing::SaveArg
;
31 // Listener class used to track progress of VideoCaptureManager test.
32 class MockMediaStreamProviderListener
: public MediaStreamProviderListener
{
34 MockMediaStreamProviderListener() {}
35 ~MockMediaStreamProviderListener() {}
37 MOCK_METHOD2(Opened
, void(MediaStreamType
, int));
38 MOCK_METHOD2(Closed
, void(MediaStreamType
, int));
39 MOCK_METHOD2(DevicesEnumerated
, void(MediaStreamType
,
40 const StreamDeviceInfoArray
&));
41 MOCK_METHOD2(Aborted
, void(MediaStreamType
, int));
42 }; // class MockMediaStreamProviderListener
44 // Needed as an input argument to StartCaptureForClient().
45 class MockFrameObserver
: public VideoCaptureControllerEventHandler
{
47 MOCK_METHOD1(OnError
, void(const VideoCaptureControllerID
& id
));
49 virtual void OnBufferCreated(const VideoCaptureControllerID
& id
,
50 base::SharedMemoryHandle handle
,
51 int length
, int buffer_id
) OVERRIDE
{}
52 virtual void OnBufferDestroyed(const VideoCaptureControllerID
& id
,
53 int buffer_id
) OVERRIDE
{}
54 virtual void OnBufferReady(const VideoCaptureControllerID
& id
,
56 const media::VideoCaptureFormat
& format
,
57 base::TimeTicks timestamp
) OVERRIDE
{}
58 virtual void OnMailboxBufferReady(const VideoCaptureControllerID
& id
,
60 const gpu::MailboxHolder
& mailbox_holder
,
61 const media::VideoCaptureFormat
& format
,
62 base::TimeTicks timestamp
) OVERRIDE
{}
63 virtual void OnEnded(const VideoCaptureControllerID
& id
) OVERRIDE
{}
65 void OnGotControllerCallback(VideoCaptureControllerID
) {}
69 class VideoCaptureManagerTest
: public testing::Test
{
71 VideoCaptureManagerTest() : next_client_id_(1) {}
72 virtual ~VideoCaptureManagerTest() {}
75 virtual void SetUp() OVERRIDE
{
76 listener_
.reset(new MockMediaStreamProviderListener());
77 message_loop_
.reset(new base::MessageLoopForIO
);
78 io_thread_
.reset(new BrowserThreadImpl(BrowserThread::IO
,
79 message_loop_
.get()));
80 vcm_
= new VideoCaptureManager(scoped_ptr
<media::VideoCaptureDeviceFactory
>(
81 new media::FakeVideoCaptureDeviceFactory()));
82 video_capture_device_factory_
=
83 static_cast<media::FakeVideoCaptureDeviceFactory
*>(
84 vcm_
->video_capture_device_factory());
85 const int32 kNumberOfFakeDevices
= 2;
86 video_capture_device_factory_
->set_number_of_devices(kNumberOfFakeDevices
);
87 vcm_
->Register(listener_
.get(), message_loop_
->message_loop_proxy().get());
88 frame_observer_
.reset(new MockFrameObserver());
91 virtual void TearDown() OVERRIDE
{}
93 void OnGotControllerCallback(
94 VideoCaptureControllerID id
,
95 base::Closure quit_closure
,
97 const base::WeakPtr
<VideoCaptureController
>& controller
) {
99 ASSERT_TRUE(controller
);
100 ASSERT_TRUE(0 == controllers_
.count(id
));
101 controllers_
[id
] = controller
.get();
103 ASSERT_TRUE(NULL
== controller
);
108 VideoCaptureControllerID
StartClient(int session_id
, bool expect_success
) {
109 media::VideoCaptureParams params
;
110 params
.requested_format
= media::VideoCaptureFormat(
111 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420
);
113 VideoCaptureControllerID
client_id(next_client_id_
++);
114 base::RunLoop run_loop
;
115 vcm_
->StartCaptureForClient(
118 base::kNullProcessHandle
,
120 frame_observer_
.get(),
121 base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback
,
122 base::Unretained(this),
124 run_loop
.QuitClosure(),
130 void StopClient(VideoCaptureControllerID client_id
) {
131 ASSERT_TRUE(1 == controllers_
.count(client_id
));
132 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
133 frame_observer_
.get(), false);
134 controllers_
.erase(client_id
);
138 std::map
<VideoCaptureControllerID
, VideoCaptureController
*> controllers_
;
139 scoped_refptr
<VideoCaptureManager
> vcm_
;
140 scoped_ptr
<MockMediaStreamProviderListener
> listener_
;
141 scoped_ptr
<base::MessageLoop
> message_loop_
;
142 scoped_ptr
<BrowserThreadImpl
> io_thread_
;
143 scoped_ptr
<MockFrameObserver
> frame_observer_
;
144 media::FakeVideoCaptureDeviceFactory
* video_capture_device_factory_
;
147 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest
);
152 // Try to open, start, stop and close a device.
153 TEST_F(VideoCaptureManagerTest
, CreateAndClose
) {
154 StreamDeviceInfoArray devices
;
157 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
158 .WillOnce(SaveArg
<1>(&devices
));
159 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
160 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
162 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
164 // Wait to get device callback.
165 message_loop_
->RunUntilIdle();
167 int video_session_id
= vcm_
->Open(devices
.front());
168 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
170 StopClient(client_id
);
171 vcm_
->Close(video_session_id
);
173 // Wait to check callbacks before removing the listener.
174 message_loop_
->RunUntilIdle();
178 // Try to open, start, and abort a device.
179 TEST_F(VideoCaptureManagerTest
, CreateAndAbort
) {
180 StreamDeviceInfoArray devices
;
183 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
184 .WillOnce(SaveArg
<1>(&devices
));
185 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
186 EXPECT_CALL(*listener_
, Aborted(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
188 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
190 // Wait to get device callback.
191 message_loop_
->RunUntilIdle();
193 int video_session_id
= vcm_
->Open(devices
.front());
194 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
196 // Wait for device opened.
197 message_loop_
->RunUntilIdle();
199 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
200 frame_observer_
.get(), true);
202 // Wait to check callbacks before removing the listener.
203 message_loop_
->RunUntilIdle();
207 // Open the same device twice.
208 TEST_F(VideoCaptureManagerTest
, OpenTwice
) {
209 StreamDeviceInfoArray devices
;
212 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
213 .WillOnce(SaveArg
<1>(&devices
));
214 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
215 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
217 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
219 // Wait to get device callback.
220 message_loop_
->RunUntilIdle();
222 int video_session_id_first
= vcm_
->Open(devices
.front());
224 // This should trigger an error callback with error code
225 // 'kDeviceAlreadyInUse'.
226 int video_session_id_second
= vcm_
->Open(devices
.front());
227 EXPECT_NE(video_session_id_first
, video_session_id_second
);
229 vcm_
->Close(video_session_id_first
);
230 vcm_
->Close(video_session_id_second
);
232 // Wait to check callbacks before removing the listener.
233 message_loop_
->RunUntilIdle();
237 // Connect and disconnect devices.
238 TEST_F(VideoCaptureManagerTest
, ConnectAndDisconnectDevices
) {
239 StreamDeviceInfoArray devices
;
240 int number_of_devices_keep
=
241 video_capture_device_factory_
->number_of_devices();
244 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
245 .WillOnce(SaveArg
<1>(&devices
));
246 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
247 message_loop_
->RunUntilIdle();
248 ASSERT_EQ(devices
.size(), 2u);
250 // Simulate we remove 1 fake device.
251 video_capture_device_factory_
->set_number_of_devices(1);
252 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
253 .WillOnce(SaveArg
<1>(&devices
));
254 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
255 message_loop_
->RunUntilIdle();
256 ASSERT_EQ(devices
.size(), 1u);
258 // Simulate we add 2 fake devices.
259 video_capture_device_factory_
->set_number_of_devices(3);
260 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
261 .WillOnce(SaveArg
<1>(&devices
));
262 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
263 message_loop_
->RunUntilIdle();
264 ASSERT_EQ(devices
.size(), 3u);
267 video_capture_device_factory_
->set_number_of_devices(number_of_devices_keep
);
270 // Enumerate devices and open the first, then check the list of supported
271 // formats. Then start the opened device. The capability list should stay the
272 // same. Finally stop the device and check that the capabilities stay unchanged.
273 TEST_F(VideoCaptureManagerTest
, ManipulateDeviceAndCheckCapabilities
) {
274 StreamDeviceInfoArray devices
;
276 // Before enumerating the devices, requesting formats should return false.
277 int video_session_id
= 0;
278 media::VideoCaptureFormats supported_formats
;
279 supported_formats
.clear();
281 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
284 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
285 .WillOnce(SaveArg
<1>(&devices
));
286 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
287 message_loop_
->RunUntilIdle();
288 ASSERT_GE(devices
.size(), 2u);
290 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
291 video_session_id
= vcm_
->Open(devices
.front());
292 message_loop_
->RunUntilIdle();
294 // Right after opening the device, we should see all its formats.
295 supported_formats
.clear();
297 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
298 ASSERT_GT(supported_formats
.size(), 1u);
299 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
300 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
301 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
302 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
303 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
304 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
306 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
307 message_loop_
->RunUntilIdle();
308 // After StartClient(), device's supported formats should stay the same.
309 supported_formats
.clear();
311 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
312 ASSERT_GE(supported_formats
.size(), 2u);
313 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
314 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
315 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
316 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
317 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
318 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
320 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
321 StopClient(client_id
);
322 supported_formats
.clear();
324 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
325 ASSERT_GE(supported_formats
.size(), 2u);
326 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
327 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
328 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
329 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
330 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
331 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
333 vcm_
->Close(video_session_id
);
334 message_loop_
->RunUntilIdle();
338 // Enumerate devices and open the first, then check the formats currently in
339 // use, which should be an empty vector. Then start the opened device. The
340 // format(s) in use should be just one format (the one used when configuring-
341 // starting the device). Finally stop the device and check that the formats in
342 // use is an empty vector.
343 TEST_F(VideoCaptureManagerTest
, StartDeviceAndGetDeviceFormatInUse
) {
344 StreamDeviceInfoArray devices
;
347 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
348 .WillOnce(SaveArg
<1>(&devices
));
349 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
350 message_loop_
->RunUntilIdle();
351 ASSERT_GE(devices
.size(), 2u);
353 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
354 int video_session_id
= vcm_
->Open(devices
.front());
355 message_loop_
->RunUntilIdle();
357 // Right after opening the device, we should see no format in use.
358 media::VideoCaptureFormats formats_in_use
;
359 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
360 EXPECT_TRUE(formats_in_use
.empty());
362 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
363 message_loop_
->RunUntilIdle();
364 // After StartClient(), |formats_in_use| should contain one valid format.
365 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
366 EXPECT_EQ(formats_in_use
.size(), 1u);
367 if (formats_in_use
.size()) {
368 media::VideoCaptureFormat
& format_in_use
= formats_in_use
.front();
369 EXPECT_TRUE(format_in_use
.IsValid());
370 EXPECT_GT(format_in_use
.frame_size
.width(), 1);
371 EXPECT_GT(format_in_use
.frame_size
.height(), 1);
372 EXPECT_GT(format_in_use
.frame_rate
, 1);
374 formats_in_use
.clear();
376 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
377 StopClient(client_id
);
378 message_loop_
->RunUntilIdle();
379 // After StopClient(), the device's formats in use should be empty again.
380 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
381 EXPECT_TRUE(formats_in_use
.empty());
383 vcm_
->Close(video_session_id
);
384 message_loop_
->RunUntilIdle();
388 // Open two different devices.
389 TEST_F(VideoCaptureManagerTest
, OpenTwo
) {
390 StreamDeviceInfoArray devices
;
393 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
394 .WillOnce(SaveArg
<1>(&devices
));
395 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
396 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
398 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
400 // Wait to get device callback.
401 message_loop_
->RunUntilIdle();
403 StreamDeviceInfoArray::iterator it
= devices
.begin();
405 int video_session_id_first
= vcm_
->Open(*it
);
407 int video_session_id_second
= vcm_
->Open(*it
);
409 vcm_
->Close(video_session_id_first
);
410 vcm_
->Close(video_session_id_second
);
412 // Wait to check callbacks before removing the listener.
413 message_loop_
->RunUntilIdle();
417 // Try open a non-existing device.
418 TEST_F(VideoCaptureManagerTest
, OpenNotExisting
) {
419 StreamDeviceInfoArray devices
;
422 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
423 .WillOnce(SaveArg
<1>(&devices
));
424 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
425 EXPECT_CALL(*frame_observer_
, OnError(_
));
426 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
428 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
430 // Wait to get device callback.
431 message_loop_
->RunUntilIdle();
433 MediaStreamType stream_type
= MEDIA_DEVICE_VIDEO_CAPTURE
;
434 std::string
device_name("device_doesnt_exist");
435 std::string
device_id("id_doesnt_exist");
436 StreamDeviceInfo
dummy_device(stream_type
, device_name
, device_id
);
438 // This should fail with an error to the controller.
439 int session_id
= vcm_
->Open(dummy_device
);
440 VideoCaptureControllerID client_id
= StartClient(session_id
, true);
441 message_loop_
->RunUntilIdle();
443 StopClient(client_id
);
444 vcm_
->Close(session_id
);
445 message_loop_
->RunUntilIdle();
450 // Start a device without calling Open, using a non-magic ID.
451 TEST_F(VideoCaptureManagerTest
, StartInvalidSession
) {
452 StartClient(22, false);
454 // Wait to check callbacks before removing the listener.
455 message_loop_
->RunUntilIdle();
459 // Open and start a device, close it before calling Stop.
460 TEST_F(VideoCaptureManagerTest
, CloseWithoutStop
) {
461 StreamDeviceInfoArray devices
;
464 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
465 .WillOnce(SaveArg
<1>(&devices
));
466 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
467 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
469 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
471 // Wait to get device callback.
472 message_loop_
->RunUntilIdle();
474 int video_session_id
= vcm_
->Open(devices
.front());
476 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
478 // Close will stop the running device, an assert will be triggered in
479 // VideoCaptureManager destructor otherwise.
480 vcm_
->Close(video_session_id
);
481 StopClient(client_id
);
483 // Wait to check callbacks before removing the listener
484 message_loop_
->RunUntilIdle();
488 // TODO(mcasas): Add a test to check consolidation of the supported formats
489 // provided by the device when http://crbug.com/323913 is closed.
491 } // namespace content