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/run_loop.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/renderer_host/media/media_stream_provider.h"
15 #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
16 #include "content/browser/renderer_host/media/video_capture_manager.h"
17 #include "content/common/media/media_stream_options.h"
18 #include "media/capture/video/fake_video_capture_device_factory.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::AnyNumber
;
24 using ::testing::InSequence
;
25 using ::testing::Return
;
26 using ::testing::SaveArg
;
30 // Listener class used to track progress of VideoCaptureManager test.
31 class MockMediaStreamProviderListener
: public MediaStreamProviderListener
{
33 MockMediaStreamProviderListener() {}
34 ~MockMediaStreamProviderListener() {}
36 MOCK_METHOD2(Opened
, void(MediaStreamType
, int));
37 MOCK_METHOD2(Closed
, void(MediaStreamType
, int));
38 MOCK_METHOD2(DevicesEnumerated
, void(MediaStreamType
,
39 const StreamDeviceInfoArray
&));
40 MOCK_METHOD2(Aborted
, void(MediaStreamType
, int));
41 }; // class MockMediaStreamProviderListener
43 // Needed as an input argument to StartCaptureForClient().
44 class MockFrameObserver
: public VideoCaptureControllerEventHandler
{
46 MOCK_METHOD1(OnError
, void(VideoCaptureControllerID id
));
48 void OnBufferCreated(VideoCaptureControllerID id
,
49 base::SharedMemoryHandle handle
,
50 int length
, int buffer_id
) override
{}
51 void OnBufferDestroyed(VideoCaptureControllerID id
, int buffer_id
) override
{}
52 void OnBufferReady(VideoCaptureControllerID id
,
54 const scoped_refptr
<media::VideoFrame
>& frame
,
55 const base::TimeTicks
& timestamp
) override
{}
56 void OnEnded(VideoCaptureControllerID id
) override
{}
58 void OnGotControllerCallback(VideoCaptureControllerID
) {}
62 class VideoCaptureManagerTest
: public testing::Test
{
64 VideoCaptureManagerTest() : next_client_id_(1) {}
65 ~VideoCaptureManagerTest() override
{}
68 void SetUp() override
{
69 listener_
.reset(new MockMediaStreamProviderListener());
70 message_loop_
.reset(new base::MessageLoopForIO
);
71 io_thread_
.reset(new BrowserThreadImpl(BrowserThread::IO
,
72 message_loop_
.get()));
73 vcm_
= new VideoCaptureManager(scoped_ptr
<media::VideoCaptureDeviceFactory
>(
74 new media::FakeVideoCaptureDeviceFactory()));
75 video_capture_device_factory_
=
76 static_cast<media::FakeVideoCaptureDeviceFactory
*>(
77 vcm_
->video_capture_device_factory());
78 const int32 kNumberOfFakeDevices
= 2;
79 video_capture_device_factory_
->set_number_of_devices(kNumberOfFakeDevices
);
80 vcm_
->Register(listener_
.get(), message_loop_
->task_runner().get());
81 frame_observer_
.reset(new MockFrameObserver());
84 void TearDown() override
{}
86 void OnGotControllerCallback(
87 VideoCaptureControllerID id
,
88 base::Closure quit_closure
,
90 const base::WeakPtr
<VideoCaptureController
>& controller
) {
92 ASSERT_TRUE(controller
);
93 ASSERT_TRUE(0 == controllers_
.count(id
));
94 controllers_
[id
] = controller
.get();
96 ASSERT_TRUE(NULL
== controller
);
101 VideoCaptureControllerID
StartClient(int session_id
, bool expect_success
) {
102 media::VideoCaptureParams params
;
103 params
.requested_format
= media::VideoCaptureFormat(
104 gfx::Size(320, 240), 30, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420
);
106 VideoCaptureControllerID
client_id(next_client_id_
++);
107 base::RunLoop run_loop
;
108 vcm_
->StartCaptureForClient(
111 base::kNullProcessHandle
,
113 frame_observer_
.get(),
114 base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback
,
115 base::Unretained(this),
117 run_loop
.QuitClosure(),
123 void StopClient(VideoCaptureControllerID client_id
) {
124 ASSERT_TRUE(1 == controllers_
.count(client_id
));
125 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
126 frame_observer_
.get(), false);
127 controllers_
.erase(client_id
);
131 std::map
<VideoCaptureControllerID
, VideoCaptureController
*> controllers_
;
132 scoped_refptr
<VideoCaptureManager
> vcm_
;
133 scoped_ptr
<MockMediaStreamProviderListener
> listener_
;
134 scoped_ptr
<base::MessageLoop
> message_loop_
;
135 scoped_ptr
<BrowserThreadImpl
> io_thread_
;
136 scoped_ptr
<MockFrameObserver
> frame_observer_
;
137 media::FakeVideoCaptureDeviceFactory
* video_capture_device_factory_
;
140 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest
);
145 // Try to open, start, stop and close a device.
146 TEST_F(VideoCaptureManagerTest
, CreateAndClose
) {
147 StreamDeviceInfoArray devices
;
150 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
151 .WillOnce(SaveArg
<1>(&devices
));
152 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
153 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
155 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
157 // Wait to get device callback.
158 message_loop_
->RunUntilIdle();
160 int video_session_id
= vcm_
->Open(devices
.front());
161 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
163 StopClient(client_id
);
164 vcm_
->Close(video_session_id
);
166 // Wait to check callbacks before removing the listener.
167 message_loop_
->RunUntilIdle();
171 TEST_F(VideoCaptureManagerTest
, CreateAndCloseMultipleTimes
) {
172 StreamDeviceInfoArray devices
;
175 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
176 .WillOnce(SaveArg
<1>(&devices
));
178 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
180 // Wait to get device callback.
181 message_loop_
->RunUntilIdle();
183 for (int i
= 1 ; i
< 3 ; ++i
) {
184 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, i
));
185 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, i
));
186 int video_session_id
= vcm_
->Open(devices
.front());
187 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
189 StopClient(client_id
);
190 vcm_
->Close(video_session_id
);
193 // Wait to check callbacks before removing the listener.
194 message_loop_
->RunUntilIdle();
198 // Try to open, start, and abort a device.
199 TEST_F(VideoCaptureManagerTest
, CreateAndAbort
) {
200 StreamDeviceInfoArray devices
;
203 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
204 .WillOnce(SaveArg
<1>(&devices
));
205 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
206 EXPECT_CALL(*listener_
, Aborted(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
208 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
210 // Wait to get device callback.
211 message_loop_
->RunUntilIdle();
213 int video_session_id
= vcm_
->Open(devices
.front());
214 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
216 // Wait for device opened.
217 message_loop_
->RunUntilIdle();
219 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
220 frame_observer_
.get(), true);
222 // Wait to check callbacks before removing the listener.
223 message_loop_
->RunUntilIdle();
227 // Open the same device twice.
228 TEST_F(VideoCaptureManagerTest
, OpenTwice
) {
229 StreamDeviceInfoArray devices
;
232 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
233 .WillOnce(SaveArg
<1>(&devices
));
234 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
235 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
237 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
239 // Wait to get device callback.
240 message_loop_
->RunUntilIdle();
242 int video_session_id_first
= vcm_
->Open(devices
.front());
244 // This should trigger an error callback with error code
245 // 'kDeviceAlreadyInUse'.
246 int video_session_id_second
= vcm_
->Open(devices
.front());
247 EXPECT_NE(video_session_id_first
, video_session_id_second
);
249 vcm_
->Close(video_session_id_first
);
250 vcm_
->Close(video_session_id_second
);
252 // Wait to check callbacks before removing the listener.
253 message_loop_
->RunUntilIdle();
257 // Connect and disconnect devices.
258 TEST_F(VideoCaptureManagerTest
, ConnectAndDisconnectDevices
) {
259 StreamDeviceInfoArray devices
;
260 int number_of_devices_keep
=
261 video_capture_device_factory_
->number_of_devices();
264 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
265 .WillOnce(SaveArg
<1>(&devices
));
266 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
267 message_loop_
->RunUntilIdle();
268 ASSERT_EQ(devices
.size(), 2u);
270 // Simulate we remove 1 fake device.
271 video_capture_device_factory_
->set_number_of_devices(1);
272 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
273 .WillOnce(SaveArg
<1>(&devices
));
274 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
275 message_loop_
->RunUntilIdle();
276 ASSERT_EQ(devices
.size(), 1u);
278 // Simulate we add 2 fake devices.
279 video_capture_device_factory_
->set_number_of_devices(3);
280 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
281 .WillOnce(SaveArg
<1>(&devices
));
282 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
283 message_loop_
->RunUntilIdle();
284 ASSERT_EQ(devices
.size(), 3u);
287 video_capture_device_factory_
->set_number_of_devices(number_of_devices_keep
);
290 // Enumerate devices and open the first, then check the list of supported
291 // formats. Then start the opened device. The capability list should stay the
292 // same. Finally stop the device and check that the capabilities stay unchanged.
293 TEST_F(VideoCaptureManagerTest
, ManipulateDeviceAndCheckCapabilities
) {
294 StreamDeviceInfoArray devices
;
296 // Before enumerating the devices, requesting formats should return false.
297 int video_session_id
= 0;
298 media::VideoCaptureFormats supported_formats
;
299 supported_formats
.clear();
301 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
304 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
305 .WillOnce(SaveArg
<1>(&devices
));
306 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
307 message_loop_
->RunUntilIdle();
308 ASSERT_GE(devices
.size(), 2u);
310 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
311 video_session_id
= vcm_
->Open(devices
.front());
312 message_loop_
->RunUntilIdle();
314 // Right after opening the device, we should see all its formats.
315 supported_formats
.clear();
317 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
318 ASSERT_GT(supported_formats
.size(), 1u);
319 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
320 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
321 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
322 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
323 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
324 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
326 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
327 message_loop_
->RunUntilIdle();
328 // After StartClient(), device's supported formats should stay the same.
329 supported_formats
.clear();
331 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
332 ASSERT_GE(supported_formats
.size(), 2u);
333 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
334 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
335 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
336 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
337 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
338 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
340 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
341 StopClient(client_id
);
342 supported_formats
.clear();
344 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
345 ASSERT_GE(supported_formats
.size(), 2u);
346 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
347 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
348 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
349 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
350 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
351 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
353 vcm_
->Close(video_session_id
);
354 message_loop_
->RunUntilIdle();
358 // Enumerate devices and open the first, then check the formats currently in
359 // use, which should be an empty vector. Then start the opened device. The
360 // format(s) in use should be just one format (the one used when configuring-
361 // starting the device). Finally stop the device and check that the formats in
362 // use is an empty vector.
363 TEST_F(VideoCaptureManagerTest
, StartDeviceAndGetDeviceFormatInUse
) {
364 StreamDeviceInfoArray devices
;
367 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
368 .WillOnce(SaveArg
<1>(&devices
));
369 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
370 message_loop_
->RunUntilIdle();
371 ASSERT_GE(devices
.size(), 2u);
373 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
374 int video_session_id
= vcm_
->Open(devices
.front());
375 message_loop_
->RunUntilIdle();
377 // Right after opening the device, we should see no format in use.
378 media::VideoCaptureFormats formats_in_use
;
379 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
380 EXPECT_TRUE(formats_in_use
.empty());
382 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
383 message_loop_
->RunUntilIdle();
384 // After StartClient(), |formats_in_use| should contain one valid format.
385 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
386 EXPECT_EQ(formats_in_use
.size(), 1u);
387 if (formats_in_use
.size()) {
388 media::VideoCaptureFormat
& format_in_use
= formats_in_use
.front();
389 EXPECT_TRUE(format_in_use
.IsValid());
390 EXPECT_GT(format_in_use
.frame_size
.width(), 1);
391 EXPECT_GT(format_in_use
.frame_size
.height(), 1);
392 EXPECT_GT(format_in_use
.frame_rate
, 1);
394 formats_in_use
.clear();
396 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
397 StopClient(client_id
);
398 message_loop_
->RunUntilIdle();
399 // After StopClient(), the device's formats in use should be empty again.
400 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
401 EXPECT_TRUE(formats_in_use
.empty());
403 vcm_
->Close(video_session_id
);
404 message_loop_
->RunUntilIdle();
408 // Open two different devices.
409 TEST_F(VideoCaptureManagerTest
, OpenTwo
) {
410 StreamDeviceInfoArray devices
;
413 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
414 .WillOnce(SaveArg
<1>(&devices
));
415 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
416 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
418 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
420 // Wait to get device callback.
421 message_loop_
->RunUntilIdle();
423 StreamDeviceInfoArray::iterator it
= devices
.begin();
425 int video_session_id_first
= vcm_
->Open(*it
);
427 int video_session_id_second
= vcm_
->Open(*it
);
429 vcm_
->Close(video_session_id_first
);
430 vcm_
->Close(video_session_id_second
);
432 // Wait to check callbacks before removing the listener.
433 message_loop_
->RunUntilIdle();
437 // Try open a non-existing device.
438 TEST_F(VideoCaptureManagerTest
, OpenNotExisting
) {
439 StreamDeviceInfoArray devices
;
442 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
443 .WillOnce(SaveArg
<1>(&devices
));
444 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
445 EXPECT_CALL(*frame_observer_
, OnError(_
));
446 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
448 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
450 // Wait to get device callback.
451 message_loop_
->RunUntilIdle();
453 MediaStreamType stream_type
= MEDIA_DEVICE_VIDEO_CAPTURE
;
454 std::string
device_name("device_doesnt_exist");
455 std::string
device_id("id_doesnt_exist");
456 StreamDeviceInfo
dummy_device(stream_type
, device_name
, device_id
);
458 // This should fail with an error to the controller.
459 int session_id
= vcm_
->Open(dummy_device
);
460 VideoCaptureControllerID client_id
= StartClient(session_id
, true);
461 message_loop_
->RunUntilIdle();
463 StopClient(client_id
);
464 vcm_
->Close(session_id
);
465 message_loop_
->RunUntilIdle();
470 // Start a device without calling Open, using a non-magic ID.
471 TEST_F(VideoCaptureManagerTest
, StartInvalidSession
) {
472 StartClient(22, false);
474 // Wait to check callbacks before removing the listener.
475 message_loop_
->RunUntilIdle();
479 // Open and start a device, close it before calling Stop.
480 TEST_F(VideoCaptureManagerTest
, CloseWithoutStop
) {
481 StreamDeviceInfoArray devices
;
484 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
485 .WillOnce(SaveArg
<1>(&devices
));
486 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
487 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
489 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
491 // Wait to get device callback.
492 message_loop_
->RunUntilIdle();
494 int video_session_id
= vcm_
->Open(devices
.front());
496 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
498 // Close will stop the running device, an assert will be triggered in
499 // VideoCaptureManager destructor otherwise.
500 vcm_
->Close(video_session_id
);
501 StopClient(client_id
);
503 // Wait to check callbacks before removing the listener
504 message_loop_
->RunUntilIdle();
508 // TODO(mcasas): Add a test to check consolidation of the supported formats
509 // provided by the device when http://crbug.com/323913 is closed.
511 } // namespace content