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/video_capture_device.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_METHOD3(Error
, void(MediaStreamType
, int,
42 MediaStreamProviderError
));
43 }; // class MockMediaStreamProviderListener
45 // Needed as an input argument to StartCaptureForClient().
46 class MockFrameObserver
: public VideoCaptureControllerEventHandler
{
48 MOCK_METHOD1(OnError
, void(const VideoCaptureControllerID
& id
));
50 virtual void OnBufferCreated(const VideoCaptureControllerID
& id
,
51 base::SharedMemoryHandle handle
,
52 int length
, int buffer_id
) OVERRIDE
{}
53 virtual void OnBufferDestroyed(const VideoCaptureControllerID
& id
,
54 int buffer_id
) OVERRIDE
{}
55 virtual void OnBufferReady(
56 const VideoCaptureControllerID
& id
,
59 const media::VideoCaptureFormat
& format
) OVERRIDE
{}
60 virtual void OnEnded(const VideoCaptureControllerID
& id
) OVERRIDE
{}
62 void OnGotControllerCallback(VideoCaptureControllerID
) {}
66 class VideoCaptureManagerTest
: public testing::Test
{
68 VideoCaptureManagerTest() : next_client_id_(1) {}
69 virtual ~VideoCaptureManagerTest() {}
72 virtual void SetUp() OVERRIDE
{
73 listener_
.reset(new MockMediaStreamProviderListener());
74 message_loop_
.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO
));
75 io_thread_
.reset(new BrowserThreadImpl(BrowserThread::IO
,
76 message_loop_
.get()));
77 vcm_
= new VideoCaptureManager();
78 vcm_
->UseFakeDevice();
79 vcm_
->Register(listener_
.get(), message_loop_
->message_loop_proxy().get());
80 frame_observer_
.reset(new MockFrameObserver());
83 virtual void TearDown() OVERRIDE
{}
85 void OnGotControllerCallback(
86 VideoCaptureControllerID id
,
87 base::Closure quit_closure
,
89 const base::WeakPtr
<VideoCaptureController
>& controller
) {
91 ASSERT_TRUE(controller
);
92 ASSERT_TRUE(0 == controllers_
.count(id
));
93 controllers_
[id
] = controller
.get();
95 ASSERT_TRUE(NULL
== controller
);
100 VideoCaptureControllerID
StartClient(int session_id
, bool expect_success
) {
101 media::VideoCaptureParams params
;
102 params
.requested_format
= media::VideoCaptureFormat(
103 gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420
);
105 VideoCaptureControllerID
client_id(next_client_id_
++);
106 base::RunLoop run_loop
;
107 vcm_
->StartCaptureForClient(
110 base::kNullProcessHandle
,
112 frame_observer_
.get(),
113 base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback
,
114 base::Unretained(this),
116 run_loop
.QuitClosure(),
122 void StopClient(VideoCaptureControllerID client_id
) {
123 ASSERT_TRUE(1 == controllers_
.count(client_id
));
124 vcm_
->StopCaptureForClient(controllers_
[client_id
], client_id
,
125 frame_observer_
.get());
126 controllers_
.erase(client_id
);
130 std::map
<VideoCaptureControllerID
, VideoCaptureController
*> controllers_
;
131 scoped_refptr
<VideoCaptureManager
> vcm_
;
132 scoped_ptr
<MockMediaStreamProviderListener
> listener_
;
133 scoped_ptr
<base::MessageLoop
> message_loop_
;
134 scoped_ptr
<BrowserThreadImpl
> io_thread_
;
135 scoped_ptr
<MockFrameObserver
> frame_observer_
;
138 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest
);
143 // Try to open, start, stop and close a device.
144 TEST_F(VideoCaptureManagerTest
, CreateAndClose
) {
145 StreamDeviceInfoArray devices
;
148 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
149 .Times(1).WillOnce(SaveArg
<1>(&devices
));
150 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(1);
151 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(1);
153 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
155 // Wait to get device callback.
156 message_loop_
->RunUntilIdle();
158 int video_session_id
= vcm_
->Open(devices
.front());
159 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
161 StopClient(client_id
);
162 vcm_
->Close(video_session_id
);
164 // Wait to check callbacks before removing the listener.
165 message_loop_
->RunUntilIdle();
169 // Open the same device twice.
170 TEST_F(VideoCaptureManagerTest
, OpenTwice
) {
171 StreamDeviceInfoArray devices
;
174 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
175 .Times(1).WillOnce(SaveArg
<1>(&devices
));
176 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
177 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
179 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
181 // Wait to get device callback.
182 message_loop_
->RunUntilIdle();
184 int video_session_id_first
= vcm_
->Open(devices
.front());
186 // This should trigger an error callback with error code
187 // 'kDeviceAlreadyInUse'.
188 int video_session_id_second
= vcm_
->Open(devices
.front());
189 EXPECT_NE(video_session_id_first
, video_session_id_second
);
191 vcm_
->Close(video_session_id_first
);
192 vcm_
->Close(video_session_id_second
);
194 // Wait to check callbacks before removing the listener.
195 message_loop_
->RunUntilIdle();
199 // Open two different devices.
200 TEST_F(VideoCaptureManagerTest
, OpenTwo
) {
201 StreamDeviceInfoArray devices
;
204 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
205 .Times(1).WillOnce(SaveArg
<1>(&devices
));
206 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
207 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(2);
209 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
211 // Wait to get device callback.
212 message_loop_
->RunUntilIdle();
214 StreamDeviceInfoArray::iterator it
= devices
.begin();
216 int video_session_id_first
= vcm_
->Open(*it
);
218 int video_session_id_second
= vcm_
->Open(*it
);
220 vcm_
->Close(video_session_id_first
);
221 vcm_
->Close(video_session_id_second
);
223 // Wait to check callbacks before removing the listener.
224 message_loop_
->RunUntilIdle();
228 // Try open a non-existing device.
229 TEST_F(VideoCaptureManagerTest
, OpenNotExisting
) {
230 StreamDeviceInfoArray devices
;
233 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
234 .Times(1).WillOnce(SaveArg
<1>(&devices
));
235 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(1);
236 EXPECT_CALL(*frame_observer_
, OnError(_
)).Times(1);
237 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(1);
239 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
241 // Wait to get device callback.
242 message_loop_
->RunUntilIdle();
244 MediaStreamType stream_type
= MEDIA_DEVICE_VIDEO_CAPTURE
;
245 std::string
device_name("device_doesnt_exist");
246 std::string
device_id("id_doesnt_exist");
247 StreamDeviceInfo
dummy_device(stream_type
, device_name
, device_id
);
249 // This should fail with an error to the controller.
250 int session_id
= vcm_
->Open(dummy_device
);
251 VideoCaptureControllerID client_id
= StartClient(session_id
, true);
252 message_loop_
->RunUntilIdle();
254 StopClient(client_id
);
255 vcm_
->Close(session_id
);
256 message_loop_
->RunUntilIdle();
261 // Start a device without calling Open, using a non-magic ID.
262 TEST_F(VideoCaptureManagerTest
, StartInvalidSession
) {
263 StartClient(22, false);
265 // Wait to check callbacks before removing the listener.
266 message_loop_
->RunUntilIdle();
270 // Open and start a device, close it before calling Stop.
271 TEST_F(VideoCaptureManagerTest
, CloseWithoutStop
) {
272 StreamDeviceInfoArray devices
;
275 EXPECT_CALL(*listener_
, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE
, _
))
276 .Times(1).WillOnce(SaveArg
<1>(&devices
));
277 EXPECT_CALL(*listener_
, Opened(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(1);
278 EXPECT_CALL(*listener_
, Closed(MEDIA_DEVICE_VIDEO_CAPTURE
, _
)).Times(1);
280 vcm_
->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE
);
282 // Wait to get device callback.
283 message_loop_
->RunUntilIdle();
285 int video_session_id
= vcm_
->Open(devices
.front());
287 VideoCaptureControllerID client_id
= StartClient(video_session_id
, true);
289 // Close will stop the running device, an assert will be triggered in
290 // VideoCaptureManager destructor otherwise.
291 vcm_
->Close(video_session_id
);
292 StopClient(client_id
);
294 // Wait to check callbacks before removing the listener
295 message_loop_
->RunUntilIdle();
299 } // namespace content