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.h"
20 #include "media/video/capture/video_capture_device.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
25 using ::testing::AnyNumber;
26 using ::testing::InSequence;
27 using ::testing::Return;
28 using ::testing::SaveArg;
32 // Listener class used to track progress of VideoCaptureManager test.
33 class MockMediaStreamProviderListener : public MediaStreamProviderListener {
35 MockMediaStreamProviderListener() {}
36 ~MockMediaStreamProviderListener() {}
38 MOCK_METHOD2(Opened, void(MediaStreamType, int));
39 MOCK_METHOD2(Closed, void(MediaStreamType, int));
40 MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType,
41 const StreamDeviceInfoArray&));
42 MOCK_METHOD3(Error, void(MediaStreamType, int,
43 MediaStreamProviderError));
44 }; // class MockMediaStreamProviderListener
46 // Needed as an input argument to StartCaptureForClient().
47 class MockFrameObserver : public VideoCaptureControllerEventHandler {
49 MOCK_METHOD1(OnError, void(const VideoCaptureControllerID& id));
51 virtual void OnBufferCreated(const VideoCaptureControllerID& id,
52 base::SharedMemoryHandle handle,
53 int length, int buffer_id) OVERRIDE {}
54 virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
55 int buffer_id) OVERRIDE {}
56 virtual void OnBufferReady(
57 const VideoCaptureControllerID& id,
59 base::TimeTicks timestamp,
60 const media::VideoCaptureFormat& format) OVERRIDE {}
61 virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {}
63 void OnGotControllerCallback(VideoCaptureControllerID) {}
67 class VideoCaptureManagerTest : public testing::Test {
69 VideoCaptureManagerTest() : next_client_id_(1) {}
70 virtual ~VideoCaptureManagerTest() {}
73 virtual void SetUp() OVERRIDE {
74 listener_.reset(new MockMediaStreamProviderListener());
75 message_loop_.reset(new base::MessageLoopForIO);
76 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
77 message_loop_.get()));
78 vcm_ = new VideoCaptureManager();
79 vcm_->UseFakeDevice();
80 vcm_->Register(listener_.get(), message_loop_->message_loop_proxy().get());
81 frame_observer_.reset(new MockFrameObserver());
84 virtual 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::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());
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_;
139 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest);
144 // Try to open, start, stop and close a device.
145 TEST_F(VideoCaptureManagerTest, CreateAndClose) {
146 StreamDeviceInfoArray devices;
149 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
150 .Times(1).WillOnce(SaveArg<1>(&devices));
151 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
152 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
154 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
156 // Wait to get device callback.
157 message_loop_->RunUntilIdle();
159 int video_session_id = vcm_->Open(devices.front());
160 VideoCaptureControllerID client_id = StartClient(video_session_id, true);
162 StopClient(client_id);
163 vcm_->Close(video_session_id);
165 // Wait to check callbacks before removing the listener.
166 message_loop_->RunUntilIdle();
170 // Open the same device twice.
171 TEST_F(VideoCaptureManagerTest, OpenTwice) {
172 StreamDeviceInfoArray devices;
175 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
176 .Times(1).WillOnce(SaveArg<1>(&devices));
177 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
178 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
180 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
182 // Wait to get device callback.
183 message_loop_->RunUntilIdle();
185 int video_session_id_first = vcm_->Open(devices.front());
187 // This should trigger an error callback with error code
188 // 'kDeviceAlreadyInUse'.
189 int video_session_id_second = vcm_->Open(devices.front());
190 EXPECT_NE(video_session_id_first, video_session_id_second);
192 vcm_->Close(video_session_id_first);
193 vcm_->Close(video_session_id_second);
195 // Wait to check callbacks before removing the listener.
196 message_loop_->RunUntilIdle();
200 // Connect and disconnect devices.
201 TEST_F(VideoCaptureManagerTest, ConnectAndDisconnectDevices) {
202 StreamDeviceInfoArray devices;
203 int number_of_devices_keep =
204 media::FakeVideoCaptureDevice::NumberOfFakeDevices();
207 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
208 .Times(1).WillOnce(SaveArg<1>(&devices));
209 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
210 message_loop_->RunUntilIdle();
211 ASSERT_EQ(devices.size(), 2u);
213 // Simulate we remove 1 fake device.
214 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(1);
215 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
216 .Times(1).WillOnce(SaveArg<1>(&devices));
217 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
218 message_loop_->RunUntilIdle();
219 ASSERT_EQ(devices.size(), 1u);
221 // Simulate we add 2 fake devices.
222 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(3);
223 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
224 .Times(1).WillOnce(SaveArg<1>(&devices));
225 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
226 message_loop_->RunUntilIdle();
227 ASSERT_EQ(devices.size(), 3u);
230 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_devices_keep);
233 // Enumerate devices and open the first, then check the list of supported
234 // formats. Then start the opened device. The capability list should stay the
235 // same. Finally stop the device and check that the capabilities stay unchanged.
236 TEST_F(VideoCaptureManagerTest, ManipulateDeviceAndCheckCapabilities) {
237 StreamDeviceInfoArray devices;
239 // Before enumerating the devices, requesting formats should return false.
240 int video_session_id = 0;
241 media::VideoCaptureFormats supported_formats;
242 supported_formats.clear();
244 vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats));
247 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
248 .Times(1).WillOnce(SaveArg<1>(&devices));
249 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
250 message_loop_->RunUntilIdle();
251 ASSERT_GE(devices.size(), 2u);
253 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
254 video_session_id = vcm_->Open(devices.front());
255 message_loop_->RunUntilIdle();
257 // Right after opening the device, we should see all its formats.
258 supported_formats.clear();
260 vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats));
261 ASSERT_GT(supported_formats.size(), 1u);
262 EXPECT_GT(supported_formats[0].frame_size.width(), 1);
263 EXPECT_GT(supported_formats[0].frame_size.height(), 1);
264 EXPECT_GT(supported_formats[0].frame_rate, 1);
265 EXPECT_GT(supported_formats[1].frame_size.width(), 1);
266 EXPECT_GT(supported_formats[1].frame_size.height(), 1);
267 EXPECT_GT(supported_formats[1].frame_rate, 1);
269 VideoCaptureControllerID client_id = StartClient(video_session_id, true);
270 message_loop_->RunUntilIdle();
271 // After StartClient(), device's supported formats should stay the same.
272 supported_formats.clear();
274 vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats));
275 ASSERT_GE(supported_formats.size(), 2u);
276 EXPECT_GT(supported_formats[0].frame_size.width(), 1);
277 EXPECT_GT(supported_formats[0].frame_size.height(), 1);
278 EXPECT_GT(supported_formats[0].frame_rate, 1);
279 EXPECT_GT(supported_formats[1].frame_size.width(), 1);
280 EXPECT_GT(supported_formats[1].frame_size.height(), 1);
281 EXPECT_GT(supported_formats[1].frame_rate, 1);
283 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
284 StopClient(client_id);
285 supported_formats.clear();
287 vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats));
288 ASSERT_GE(supported_formats.size(), 2u);
289 EXPECT_GT(supported_formats[0].frame_size.width(), 1);
290 EXPECT_GT(supported_formats[0].frame_size.height(), 1);
291 EXPECT_GT(supported_formats[0].frame_rate, 1);
292 EXPECT_GT(supported_formats[1].frame_size.width(), 1);
293 EXPECT_GT(supported_formats[1].frame_size.height(), 1);
294 EXPECT_GT(supported_formats[1].frame_rate, 1);
296 vcm_->Close(video_session_id);
297 message_loop_->RunUntilIdle();
301 // Enumerate devices and open the first, then check the formats currently in
302 // use, which should be an empty vector. Then start the opened device. The
303 // format(s) in use should be just one format (the one used when configuring-
304 // starting the device). Finally stop the device and check that the formats in
305 // use is an empty vector.
306 TEST_F(VideoCaptureManagerTest, StartDeviceAndGetDeviceFormatInUse) {
307 StreamDeviceInfoArray devices;
310 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
311 .Times(1).WillOnce(SaveArg<1>(&devices));
312 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
313 message_loop_->RunUntilIdle();
314 ASSERT_GE(devices.size(), 2u);
316 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
317 int video_session_id = vcm_->Open(devices.front());
318 message_loop_->RunUntilIdle();
320 // Right after opening the device, we should see no format in use.
321 media::VideoCaptureFormats formats_in_use;
322 EXPECT_TRUE(vcm_->GetDeviceFormatsInUse(video_session_id, &formats_in_use));
323 EXPECT_TRUE(formats_in_use.empty());
325 VideoCaptureControllerID client_id = StartClient(video_session_id, true);
326 message_loop_->RunUntilIdle();
327 // After StartClient(), |formats_in_use| should contain one valid format.
328 EXPECT_TRUE(vcm_->GetDeviceFormatsInUse(video_session_id, &formats_in_use));
329 EXPECT_EQ(formats_in_use.size(), 1u);
330 if (formats_in_use.size()) {
331 media::VideoCaptureFormat& format_in_use = formats_in_use.front();
332 EXPECT_TRUE(format_in_use.IsValid());
333 EXPECT_GT(format_in_use.frame_size.width(), 1);
334 EXPECT_GT(format_in_use.frame_size.height(), 1);
335 EXPECT_GT(format_in_use.frame_rate, 1);
337 formats_in_use.clear();
339 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
340 StopClient(client_id);
341 message_loop_->RunUntilIdle();
342 // After StopClient(), the device's formats in use should be empty again.
343 EXPECT_TRUE(vcm_->GetDeviceFormatsInUse(video_session_id, &formats_in_use));
344 EXPECT_TRUE(formats_in_use.empty());
346 vcm_->Close(video_session_id);
347 message_loop_->RunUntilIdle();
351 // Open two different devices.
352 TEST_F(VideoCaptureManagerTest, OpenTwo) {
353 StreamDeviceInfoArray devices;
356 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
357 .Times(1).WillOnce(SaveArg<1>(&devices));
358 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
359 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
361 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
363 // Wait to get device callback.
364 message_loop_->RunUntilIdle();
366 StreamDeviceInfoArray::iterator it = devices.begin();
368 int video_session_id_first = vcm_->Open(*it);
370 int video_session_id_second = vcm_->Open(*it);
372 vcm_->Close(video_session_id_first);
373 vcm_->Close(video_session_id_second);
375 // Wait to check callbacks before removing the listener.
376 message_loop_->RunUntilIdle();
380 // Try open a non-existing device.
381 TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
382 StreamDeviceInfoArray devices;
385 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
386 .Times(1).WillOnce(SaveArg<1>(&devices));
387 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
388 EXPECT_CALL(*frame_observer_, OnError(_)).Times(1);
389 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
391 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
393 // Wait to get device callback.
394 message_loop_->RunUntilIdle();
396 MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
397 std::string device_name("device_doesnt_exist");
398 std::string device_id("id_doesnt_exist");
399 StreamDeviceInfo dummy_device(stream_type, device_name, device_id);
401 // This should fail with an error to the controller.
402 int session_id = vcm_->Open(dummy_device);
403 VideoCaptureControllerID client_id = StartClient(session_id, true);
404 message_loop_->RunUntilIdle();
406 StopClient(client_id);
407 vcm_->Close(session_id);
408 message_loop_->RunUntilIdle();
413 // Start a device without calling Open, using a non-magic ID.
414 TEST_F(VideoCaptureManagerTest, StartInvalidSession) {
415 StartClient(22, false);
417 // Wait to check callbacks before removing the listener.
418 message_loop_->RunUntilIdle();
422 // Open and start a device, close it before calling Stop.
423 TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
424 StreamDeviceInfoArray devices;
427 EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
428 .Times(1).WillOnce(SaveArg<1>(&devices));
429 EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
430 EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
432 vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
434 // Wait to get device callback.
435 message_loop_->RunUntilIdle();
437 int video_session_id = vcm_->Open(devices.front());
439 VideoCaptureControllerID client_id = StartClient(video_session_id, true);
441 // Close will stop the running device, an assert will be triggered in
442 // VideoCaptureManager destructor otherwise.
443 vcm_->Close(video_session_id);
444 StopClient(client_id);
446 // Wait to check callbacks before removing the listener
447 message_loop_->RunUntilIdle();
451 } // namespace content