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(VideoCaptureControllerID id
));
49 void OnBufferCreated(VideoCaptureControllerID id
,
50 base::SharedMemoryHandle handle
,
51 int length
, int buffer_id
) override
{}
52 void OnBufferDestroyed(VideoCaptureControllerID id
, int buffer_id
) override
{}
54 VideoCaptureControllerID id
,
56 const gfx::Size
& coded_size
,
57 const gfx::Rect
& visible_rect
,
58 const base::TimeTicks
& timestamp
,
59 scoped_ptr
<base::DictionaryValue
> metadata
) override
{}
60 void OnMailboxBufferReady(
61 VideoCaptureControllerID id
,
63 const gpu::MailboxHolder
& mailbox_holder
,
64 const gfx::Size
& packed_frame_size
,
65 const base::TimeTicks
& timestamp
,
66 scoped_ptr
<base::DictionaryValue
> metadata
) override
{}
67 void OnEnded(VideoCaptureControllerID id
) override
{}
69 void OnGotControllerCallback(VideoCaptureControllerID
) {}
73 class VideoCaptureManagerTest
: public testing::Test
{
75 VideoCaptureManagerTest() : next_client_id_(1) {}
76 ~VideoCaptureManagerTest() override
{}
79 void SetUp() override
{
80 listener_
.reset(new MockMediaStreamProviderListener());
81 message_loop_
.reset(new base::MessageLoopForIO
);
82 io_thread_
.reset(new BrowserThreadImpl(BrowserThread::IO
,
83 message_loop_
.get()));
84 vcm_
= new VideoCaptureManager(scoped_ptr
<media::VideoCaptureDeviceFactory
>(
85 new media::FakeVideoCaptureDeviceFactory()));
86 video_capture_device_factory_
=
87 static_cast<media::FakeVideoCaptureDeviceFactory
*>(
88 vcm_
->video_capture_device_factory());
89 const int32 kNumberOfFakeDevices
= 2;
90 video_capture_device_factory_
->set_number_of_devices(kNumberOfFakeDevices
);
91 vcm_
->Register(listener_
.get(), message_loop_
->message_loop_proxy().get());
92 frame_observer_
.reset(new MockFrameObserver());
95 void TearDown() override
{}
97 void OnGotControllerCallback(
98 VideoCaptureControllerID id
,
99 base::Closure quit_closure
,
101 const base::WeakPtr
<VideoCaptureController
>& controller
) {
102 if (expect_success
) {
103 ASSERT_TRUE(controller
);
104 ASSERT_TRUE(0 == controllers_
.count(id
));
105 controllers_
[id
] = controller
.get();
107 ASSERT_TRUE(NULL
== controller
);
112 VideoCaptureControllerID
StartClient(int session_id
, bool expect_success
) {
113 media::VideoCaptureParams params
;
114 params
.requested_format
= media::VideoCaptureFormat(
115 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420
);
117 VideoCaptureControllerID
client_id(next_client_id_
++);
118 base::RunLoop run_loop
;
119 vcm_
->StartCaptureForClient(
122 base::kNullProcessHandle
,
124 frame_observer_
.get(),
125 base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback
,
126 base::Unretained(this),
128 run_loop
.QuitClosure(),
134 void StopClient(VideoCaptureControllerID client_id
) {
135 ASSERT_TRUE(1 == controllers_
.count(client_id
));
136 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
137 frame_observer_
.get(), false);
138 controllers_
.erase(client_id
);
142 std::map
<VideoCaptureControllerID
, VideoCaptureController
*> controllers_
;
143 scoped_refptr
<VideoCaptureManager
> vcm_
;
144 scoped_ptr
<MockMediaStreamProviderListener
> listener_
;
145 scoped_ptr
<base::MessageLoop
> message_loop_
;
146 scoped_ptr
<BrowserThreadImpl
> io_thread_
;
147 scoped_ptr
<MockFrameObserver
> frame_observer_
;
148 media::FakeVideoCaptureDeviceFactory
* video_capture_device_factory_
;
151 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest
);
156 // Try to open, start, stop and close a device.
157 TEST_F(VideoCaptureManagerTest
, CreateAndClose
) {
158 StreamDeviceInfoArray devices
;
161 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
162 .WillOnce(SaveArg
<1>(&devices
));
163 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
164 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
166 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
168 // Wait to get device callback.
169 message_loop_
->RunUntilIdle();
171 int video_session_id
= vcm_
->Open(devices
.front());
172 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
174 StopClient(client_id
);
175 vcm_
->Close(video_session_id
);
177 // Wait to check callbacks before removing the listener.
178 message_loop_
->RunUntilIdle();
182 TEST_F(VideoCaptureManagerTest
, CreateAndCloseMultipleTimes
) {
183 StreamDeviceInfoArray devices
;
186 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
187 .WillOnce(SaveArg
<1>(&devices
));
189 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
191 // Wait to get device callback.
192 message_loop_
->RunUntilIdle();
194 for (int i
= 1 ; i
< 3 ; ++i
) {
195 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, i
));
196 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, i
));
197 int video_session_id
= vcm_
->Open(devices
.front());
198 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
200 StopClient(client_id
);
201 vcm_
->Close(video_session_id
);
204 // Wait to check callbacks before removing the listener.
205 message_loop_
->RunUntilIdle();
209 // Try to open, start, and abort a device.
210 TEST_F(VideoCaptureManagerTest
, CreateAndAbort
) {
211 StreamDeviceInfoArray devices
;
214 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
215 .WillOnce(SaveArg
<1>(&devices
));
216 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
217 EXPECT_CALL(*listener_
, Aborted(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
219 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
221 // Wait to get device callback.
222 message_loop_
->RunUntilIdle();
224 int video_session_id
= vcm_
->Open(devices
.front());
225 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
227 // Wait for device opened.
228 message_loop_
->RunUntilIdle();
230 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
231 frame_observer_
.get(), true);
233 // Wait to check callbacks before removing the listener.
234 message_loop_
->RunUntilIdle();
238 // Open the same device twice.
239 TEST_F(VideoCaptureManagerTest
, OpenTwice
) {
240 StreamDeviceInfoArray devices
;
243 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
244 .WillOnce(SaveArg
<1>(&devices
));
245 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
246 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
248 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
250 // Wait to get device callback.
251 message_loop_
->RunUntilIdle();
253 int video_session_id_first
= vcm_
->Open(devices
.front());
255 // This should trigger an error callback with error code
256 // 'kDeviceAlreadyInUse'.
257 int video_session_id_second
= vcm_
->Open(devices
.front());
258 EXPECT_NE(video_session_id_first
, video_session_id_second
);
260 vcm_
->Close(video_session_id_first
);
261 vcm_
->Close(video_session_id_second
);
263 // Wait to check callbacks before removing the listener.
264 message_loop_
->RunUntilIdle();
268 // Connect and disconnect devices.
269 TEST_F(VideoCaptureManagerTest
, ConnectAndDisconnectDevices
) {
270 StreamDeviceInfoArray devices
;
271 int number_of_devices_keep
=
272 video_capture_device_factory_
->number_of_devices();
275 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
276 .WillOnce(SaveArg
<1>(&devices
));
277 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
278 message_loop_
->RunUntilIdle();
279 ASSERT_EQ(devices
.size(), 2u);
281 // Simulate we remove 1 fake device.
282 video_capture_device_factory_
->set_number_of_devices(1);
283 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
284 .WillOnce(SaveArg
<1>(&devices
));
285 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
286 message_loop_
->RunUntilIdle();
287 ASSERT_EQ(devices
.size(), 1u);
289 // Simulate we add 2 fake devices.
290 video_capture_device_factory_
->set_number_of_devices(3);
291 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
292 .WillOnce(SaveArg
<1>(&devices
));
293 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
294 message_loop_
->RunUntilIdle();
295 ASSERT_EQ(devices
.size(), 3u);
298 video_capture_device_factory_
->set_number_of_devices(number_of_devices_keep
);
301 // Enumerate devices and open the first, then check the list of supported
302 // formats. Then start the opened device. The capability list should stay the
303 // same. Finally stop the device and check that the capabilities stay unchanged.
304 TEST_F(VideoCaptureManagerTest
, ManipulateDeviceAndCheckCapabilities
) {
305 StreamDeviceInfoArray devices
;
307 // Before enumerating the devices, requesting formats should return false.
308 int video_session_id
= 0;
309 media::VideoCaptureFormats supported_formats
;
310 supported_formats
.clear();
312 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
315 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
316 .WillOnce(SaveArg
<1>(&devices
));
317 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
318 message_loop_
->RunUntilIdle();
319 ASSERT_GE(devices
.size(), 2u);
321 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
322 video_session_id
= vcm_
->Open(devices
.front());
323 message_loop_
->RunUntilIdle();
325 // Right after opening the device, we should see all its formats.
326 supported_formats
.clear();
328 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
329 ASSERT_GT(supported_formats
.size(), 1u);
330 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
331 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
332 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
333 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
334 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
335 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
337 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
338 message_loop_
->RunUntilIdle();
339 // After StartClient(), device's supported formats should stay the same.
340 supported_formats
.clear();
342 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
343 ASSERT_GE(supported_formats
.size(), 2u);
344 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
345 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
346 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
347 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
348 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
349 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
351 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
352 StopClient(client_id
);
353 supported_formats
.clear();
355 vcm_
->GetDeviceSupportedFormats(video_session_id
, &supported_formats
));
356 ASSERT_GE(supported_formats
.size(), 2u);
357 EXPECT_GT(supported_formats
[0].frame_size
.width(), 1);
358 EXPECT_GT(supported_formats
[0].frame_size
.height(), 1);
359 EXPECT_GT(supported_formats
[0].frame_rate
, 1);
360 EXPECT_GT(supported_formats
[1].frame_size
.width(), 1);
361 EXPECT_GT(supported_formats
[1].frame_size
.height(), 1);
362 EXPECT_GT(supported_formats
[1].frame_rate
, 1);
364 vcm_
->Close(video_session_id
);
365 message_loop_
->RunUntilIdle();
369 // Enumerate devices and open the first, then check the formats currently in
370 // use, which should be an empty vector. Then start the opened device. The
371 // format(s) in use should be just one format (the one used when configuring-
372 // starting the device). Finally stop the device and check that the formats in
373 // use is an empty vector.
374 TEST_F(VideoCaptureManagerTest
, StartDeviceAndGetDeviceFormatInUse
) {
375 StreamDeviceInfoArray devices
;
378 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
379 .WillOnce(SaveArg
<1>(&devices
));
380 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
381 message_loop_
->RunUntilIdle();
382 ASSERT_GE(devices
.size(), 2u);
384 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
385 int video_session_id
= vcm_
->Open(devices
.front());
386 message_loop_
->RunUntilIdle();
388 // Right after opening the device, we should see no format in use.
389 media::VideoCaptureFormats formats_in_use
;
390 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
391 EXPECT_TRUE(formats_in_use
.empty());
393 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
394 message_loop_
->RunUntilIdle();
395 // After StartClient(), |formats_in_use| should contain one valid format.
396 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
397 EXPECT_EQ(formats_in_use
.size(), 1u);
398 if (formats_in_use
.size()) {
399 media::VideoCaptureFormat
& format_in_use
= formats_in_use
.front();
400 EXPECT_TRUE(format_in_use
.IsValid());
401 EXPECT_GT(format_in_use
.frame_size
.width(), 1);
402 EXPECT_GT(format_in_use
.frame_size
.height(), 1);
403 EXPECT_GT(format_in_use
.frame_rate
, 1);
405 formats_in_use
.clear();
407 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
408 StopClient(client_id
);
409 message_loop_
->RunUntilIdle();
410 // After StopClient(), the device's formats in use should be empty again.
411 EXPECT_TRUE(vcm_
->GetDeviceFormatsInUse(video_session_id
, &formats_in_use
));
412 EXPECT_TRUE(formats_in_use
.empty());
414 vcm_
->Close(video_session_id
);
415 message_loop_
->RunUntilIdle();
419 // Open two different devices.
420 TEST_F(VideoCaptureManagerTest
, OpenTwo
) {
421 StreamDeviceInfoArray devices
;
424 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
425 .WillOnce(SaveArg
<1>(&devices
));
426 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
427 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
429 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
431 // Wait to get device callback.
432 message_loop_
->RunUntilIdle();
434 StreamDeviceInfoArray::iterator it
= devices
.begin();
436 int video_session_id_first
= vcm_
->Open(*it
);
438 int video_session_id_second
= vcm_
->Open(*it
);
440 vcm_
->Close(video_session_id_first
);
441 vcm_
->Close(video_session_id_second
);
443 // Wait to check callbacks before removing the listener.
444 message_loop_
->RunUntilIdle();
448 // Try open a non-existing device.
449 TEST_F(VideoCaptureManagerTest
, OpenNotExisting
) {
450 StreamDeviceInfoArray devices
;
453 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
454 .WillOnce(SaveArg
<1>(&devices
));
455 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
456 EXPECT_CALL(*frame_observer_
, OnError(_
));
457 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
459 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
461 // Wait to get device callback.
462 message_loop_
->RunUntilIdle();
464 MediaStreamType stream_type
= MEDIA_DEVICE_VIDEO_CAPTURE
;
465 std::string
device_name("device_doesnt_exist");
466 std::string
device_id("id_doesnt_exist");
467 StreamDeviceInfo
dummy_device(stream_type
, device_name
, device_id
);
469 // This should fail with an error to the controller.
470 int session_id
= vcm_
->Open(dummy_device
);
471 VideoCaptureControllerID client_id
= StartClient(session_id
, true);
472 message_loop_
->RunUntilIdle();
474 StopClient(client_id
);
475 vcm_
->Close(session_id
);
476 message_loop_
->RunUntilIdle();
481 // Start a device without calling Open, using a non-magic ID.
482 TEST_F(VideoCaptureManagerTest
, StartInvalidSession
) {
483 StartClient(22, false);
485 // Wait to check callbacks before removing the listener.
486 message_loop_
->RunUntilIdle();
490 // Open and start a device, close it before calling Stop.
491 TEST_F(VideoCaptureManagerTest
, CloseWithoutStop
) {
492 StreamDeviceInfoArray devices
;
495 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
496 .WillOnce(SaveArg
<1>(&devices
));
497 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
498 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
));
500 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
502 // Wait to get device callback.
503 message_loop_
->RunUntilIdle();
505 int video_session_id
= vcm_
->Open(devices
.front());
507 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
509 // Close will stop the running device, an assert will be triggered in
510 // VideoCaptureManager destructor otherwise.
511 vcm_
->Close(video_session_id
);
512 StopClient(client_id
);
514 // Wait to check callbacks before removing the listener
515 message_loop_
->RunUntilIdle();
519 // TODO(mcasas): Add a test to check consolidation of the supported formats
520 // provided by the device when http://crbug.com/323913 is closed.
522 } // namespace content