Removed unused VideoCaptureCapability parameters.
[chromium-blink-merge.git] / media / video / capture / video_capture_device_unittest.cc
blobf9d0ab2cb8abe84fbf7f06419b973d628b1e6c98
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 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/run_loop.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/threading/thread.h"
14 #include "media/video/capture/fake_video_capture_device.h"
15 #include "media/video/capture/video_capture_device.h"
16 #include "media/video/capture/video_capture_types.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 #if defined(OS_WIN)
21 #include "base/win/scoped_com_initializer.h"
22 #include "media/video/capture/win/video_capture_device_mf_win.h"
23 #endif
25 #if defined(OS_ANDROID)
26 #include "base/android/jni_android.h"
27 #include "media/video/capture/android/video_capture_device_android.h"
28 #endif
30 #if defined(OS_MACOSX)
31 // Mac/QTKit will always give you the size you ask for and this case will fail.
32 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
33 // We will always get ARGB from the Mac/QTKit implementation.
34 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
35 #elif defined(OS_WIN)
36 #define MAYBE_AllocateBadSize AllocateBadSize
37 // Windows currently uses DirectShow to convert from MJPEG and a raw format is
38 // always delivered.
39 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
40 #elif defined(OS_ANDROID)
41 // TODO(wjia): enable those tests on Android.
42 // On Android, native camera (JAVA) delivers frames on UI thread which is the
43 // main thread for tests. This results in no frame received by
44 // VideoCaptureAndroid.
45 #define CaptureVGA DISABLED_CaptureVGA
46 #define Capture720p DISABLED_Capture720p
47 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
48 #define ReAllocateCamera DISABLED_ReAllocateCamera
49 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
50 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
51 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
52 #else
53 #define MAYBE_AllocateBadSize AllocateBadSize
54 #define MAYBE_CaptureMjpeg CaptureMjpeg
55 #endif
57 using ::testing::_;
58 using ::testing::AnyNumber;
59 using ::testing::Return;
60 using ::testing::AtLeast;
61 using ::testing::SaveArg;
63 namespace media {
65 class MockClient : public media::VideoCaptureDevice::Client {
66 public:
67 MOCK_METHOD1(ReserveOutputBuffer,
68 scoped_refptr<media::VideoFrame>(const gfx::Size&));
69 MOCK_METHOD0(OnErr, void());
70 MOCK_METHOD1(OnFrameInfo, void(const VideoCaptureCapability&));
71 MOCK_METHOD1(OnFrameInfoChanged, void(const VideoCaptureCapability&));
73 explicit MockClient(
74 base::Closure frame_cb)
75 : main_thread_(base::MessageLoopProxy::current()),
76 frame_cb_(frame_cb) {}
78 virtual void OnError() OVERRIDE {
79 OnErr();
82 virtual void OnIncomingCapturedFrame(
83 const uint8* data,
84 int length,
85 base::Time timestamp,
86 int rotation,
87 bool flip_vert,
88 bool flip_horiz) OVERRIDE {
89 main_thread_->PostTask(FROM_HERE, frame_cb_);
92 virtual void OnIncomingCapturedVideoFrame(
93 const scoped_refptr<media::VideoFrame>& frame,
94 base::Time timestamp) OVERRIDE {
95 main_thread_->PostTask(FROM_HERE, frame_cb_);
98 private:
99 scoped_refptr<base::MessageLoopProxy> main_thread_;
100 base::Closure frame_cb_;
103 class VideoCaptureDeviceTest : public testing::Test {
104 protected:
105 typedef media::VideoCaptureDevice::Client Client;
107 virtual void SetUp() {
108 loop_.reset(new base::MessageLoopForUI());
109 client_.reset(new MockClient(loop_->QuitClosure()));
110 #if defined(OS_ANDROID)
111 media::VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(
112 base::android::AttachCurrentThread());
113 #endif
116 void WaitForCapturedFrame() {
117 loop_->Run();
120 #if defined(OS_WIN)
121 base::win::ScopedCOMInitializer initialize_com_;
122 #endif
123 scoped_ptr<MockClient> client_;
124 VideoCaptureDevice::Names names_;
125 scoped_ptr<base::MessageLoop> loop_;
128 TEST_F(VideoCaptureDeviceTest, OpenInvalidDevice) {
129 #if defined(OS_WIN)
130 VideoCaptureDevice::Name::CaptureApiType api_type =
131 VideoCaptureDeviceMFWin::PlatformSupported()
132 ? VideoCaptureDevice::Name::MEDIA_FOUNDATION
133 : VideoCaptureDevice::Name::DIRECT_SHOW;
134 VideoCaptureDevice::Name device_name("jibberish", "jibberish", api_type);
135 #else
136 VideoCaptureDevice::Name device_name("jibberish", "jibberish");
137 #endif
138 VideoCaptureDevice* device = VideoCaptureDevice::Create(device_name);
139 EXPECT_TRUE(device == NULL);
142 TEST_F(VideoCaptureDeviceTest, CaptureVGA) {
143 VideoCaptureDevice::GetDeviceNames(&names_);
144 if (!names_.size()) {
145 DVLOG(1) << "No camera available. Exiting test.";
146 return;
149 scoped_ptr<VideoCaptureDevice> device(
150 VideoCaptureDevice::Create(names_.front()));
151 ASSERT_FALSE(device.get() == NULL);
152 DVLOG(1) << names_.front().id();
153 // Get info about the new resolution.
154 VideoCaptureCapability rx_capability;
155 EXPECT_CALL(*client_, OnFrameInfo(_))
156 .Times(1).WillOnce(SaveArg<0>(&rx_capability));
158 EXPECT_CALL(*client_, OnErr())
159 .Times(0);
161 VideoCaptureCapability capture_format(640,
162 480,
164 PIXEL_FORMAT_I420,
165 ConstantResolutionVideoCaptureDevice);
166 device->AllocateAndStart(capture_format,
167 client_.PassAs<Client>());
168 // Get captured video frames.
169 loop_->Run();
170 EXPECT_EQ(rx_capability.width, 640);
171 EXPECT_EQ(rx_capability.height, 480);
172 device->StopAndDeAllocate();
175 TEST_F(VideoCaptureDeviceTest, Capture720p) {
176 VideoCaptureDevice::GetDeviceNames(&names_);
177 if (!names_.size()) {
178 DVLOG(1) << "No camera available. Exiting test.";
179 return;
182 scoped_ptr<VideoCaptureDevice> device(
183 VideoCaptureDevice::Create(names_.front()));
184 ASSERT_FALSE(device.get() == NULL);
186 // Get info about the new resolution.
187 // We don't care about the resulting resolution or frame rate as it might
188 // be different from one machine to the next.
189 EXPECT_CALL(*client_, OnFrameInfo(_))
190 .Times(1);
192 EXPECT_CALL(*client_, OnErr())
193 .Times(0);
195 VideoCaptureCapability capture_format(1280,
196 720,
198 PIXEL_FORMAT_I420,
199 ConstantResolutionVideoCaptureDevice);
200 device->AllocateAndStart(capture_format,
201 client_.PassAs<Client>());
202 // Get captured video frames.
203 WaitForCapturedFrame();
204 device->StopAndDeAllocate();
207 TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) {
208 VideoCaptureDevice::GetDeviceNames(&names_);
209 if (!names_.size()) {
210 DVLOG(1) << "No camera available. Exiting test.";
211 return;
213 scoped_ptr<VideoCaptureDevice> device(
214 VideoCaptureDevice::Create(names_.front()));
215 ASSERT_TRUE(device.get() != NULL);
217 EXPECT_CALL(*client_, OnErr())
218 .Times(0);
220 // Get info about the new resolution.
221 VideoCaptureCapability rx_capability;
222 EXPECT_CALL(*client_, OnFrameInfo(_))
223 .Times(AtLeast(1)).WillOnce(SaveArg<0>(&rx_capability));
225 VideoCaptureCapability capture_format(637,
226 472,
228 PIXEL_FORMAT_I420,
229 ConstantResolutionVideoCaptureDevice);
230 device->AllocateAndStart(capture_format,
231 client_.PassAs<Client>());
232 device->StopAndDeAllocate();
233 EXPECT_EQ(rx_capability.width, 640);
234 EXPECT_EQ(rx_capability.height, 480);
237 TEST_F(VideoCaptureDeviceTest, ReAllocateCamera) {
238 VideoCaptureDevice::GetDeviceNames(&names_);
239 if (!names_.size()) {
240 DVLOG(1) << "No camera available. Exiting test.";
241 return;
244 // First, do a number of very fast device start/stops.
245 for (int i = 0; i <= 5; i++) {
246 scoped_ptr<MockClient> client(
247 new MockClient(base::Bind(&base::DoNothing)));
248 scoped_ptr<VideoCaptureDevice> device(
249 VideoCaptureDevice::Create(names_.front()));
250 gfx::Size resolution;
251 if (i % 2) {
252 resolution = gfx::Size(640, 480);
253 } else {
254 resolution = gfx::Size(1280, 1024);
256 VideoCaptureCapability requested_format(
257 resolution.width(),
258 resolution.height(),
260 PIXEL_FORMAT_I420,
261 ConstantResolutionVideoCaptureDevice);
263 // The device (if it is an async implementation) may or may not get as far
264 // as the OnFrameInfo() step; we're intentionally not going to wait for it
265 // to get that far.
266 EXPECT_CALL(*client, OnFrameInfo(_)).Times(testing::AtMost(1));
267 device->AllocateAndStart(requested_format,
268 client.PassAs<Client>());
269 device->StopAndDeAllocate();
272 // Finally, do a device start and wait for it to finish.
273 gfx::Size resolution;
274 VideoCaptureCapability requested_format(
275 320,
276 240,
278 PIXEL_FORMAT_I420,
279 ConstantResolutionVideoCaptureDevice);
281 base::RunLoop run_loop;
282 scoped_ptr<MockClient> client(
283 new MockClient(base::Bind(run_loop.QuitClosure())));
284 scoped_ptr<VideoCaptureDevice> device(
285 VideoCaptureDevice::Create(names_.front()));
287 // The device (if it is an async implementation) may or may not get as far
288 // as the OnFrameInfo() step; we're intentionally not going to wait for it
289 // to get that far.
290 VideoCaptureCapability final_format;
291 EXPECT_CALL(*client, OnFrameInfo(_))
292 .Times(1).WillOnce(SaveArg<0>(&final_format));
293 device->AllocateAndStart(requested_format,
294 client.PassAs<Client>());
295 run_loop.Run(); // Waits for a frame.
296 device->StopAndDeAllocate();
297 device.reset();
298 EXPECT_EQ(final_format.width, 320);
299 EXPECT_EQ(final_format.height, 240);
302 TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) {
303 VideoCaptureDevice::GetDeviceNames(&names_);
304 if (!names_.size()) {
305 DVLOG(1) << "No camera available. Exiting test.";
306 return;
308 scoped_ptr<VideoCaptureDevice> device(
309 VideoCaptureDevice::Create(names_.front()));
310 ASSERT_TRUE(device.get() != NULL);
312 EXPECT_CALL(*client_, OnErr())
313 .Times(0);
314 // Get info about the new resolution.
315 VideoCaptureCapability rx_capability;
316 EXPECT_CALL(*client_, OnFrameInfo(_))
317 .WillOnce(SaveArg<0>(&rx_capability));
319 VideoCaptureCapability capture_format(640,
320 480,
322 PIXEL_FORMAT_I420,
323 ConstantResolutionVideoCaptureDevice);
324 device->AllocateAndStart(capture_format, client_.PassAs<Client>());
325 // Get captured video frames.
326 WaitForCapturedFrame();
327 EXPECT_EQ(rx_capability.width, 640);
328 EXPECT_EQ(rx_capability.height, 480);
329 EXPECT_EQ(rx_capability.frame_rate, 30);
330 device->StopAndDeAllocate();
333 TEST_F(VideoCaptureDeviceTest, FakeCapture) {
334 VideoCaptureDevice::Names names;
336 FakeVideoCaptureDevice::GetDeviceNames(&names);
338 ASSERT_GT(static_cast<int>(names.size()), 0);
340 scoped_ptr<VideoCaptureDevice> device(
341 FakeVideoCaptureDevice::Create(names.front()));
342 ASSERT_TRUE(device.get() != NULL);
344 // Get info about the new resolution.
345 VideoCaptureCapability rx_capability;
346 EXPECT_CALL(*client_, OnFrameInfo(_))
347 .Times(1).WillOnce(SaveArg<0>(&rx_capability));
349 EXPECT_CALL(*client_, OnErr())
350 .Times(0);
352 VideoCaptureCapability capture_format(640,
353 480,
355 PIXEL_FORMAT_I420,
356 ConstantResolutionVideoCaptureDevice);
357 device->AllocateAndStart(capture_format,
358 client_.PassAs<Client>());
359 WaitForCapturedFrame();
360 EXPECT_EQ(rx_capability.width, 640);
361 EXPECT_EQ(rx_capability.height, 480);
362 EXPECT_EQ(rx_capability.frame_rate, 30);
363 device->StopAndDeAllocate();
366 // Start the camera in 720p to capture MJPEG instead of a raw format.
367 TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) {
368 VideoCaptureDevice::GetDeviceNames(&names_);
369 if (!names_.size()) {
370 DVLOG(1) << "No camera available. Exiting test.";
371 return;
373 scoped_ptr<VideoCaptureDevice> device(
374 VideoCaptureDevice::Create(names_.front()));
375 ASSERT_TRUE(device.get() != NULL);
377 EXPECT_CALL(*client_, OnErr())
378 .Times(0);
379 // Verify we get MJPEG from the device. Not all devices can capture 1280x720
380 // @ 30 fps, so we don't care about the exact resolution we get.
381 VideoCaptureCapability rx_capability;
382 EXPECT_CALL(*client_, OnFrameInfo(_))
383 .WillOnce(SaveArg<0>(&rx_capability));
385 VideoCaptureCapability capture_format(1280,
386 720,
388 PIXEL_FORMAT_MJPEG,
389 ConstantResolutionVideoCaptureDevice);
390 device->AllocateAndStart(capture_format, client_.PassAs<Client>());
391 // Get captured video frames.
392 WaitForCapturedFrame();
393 EXPECT_EQ(rx_capability.color, PIXEL_FORMAT_MJPEG);
394 device->StopAndDeAllocate();
397 TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) {
398 VideoCaptureDevice::GetDeviceNames(&names_);
399 if (!names_.size()) {
400 DVLOG(1) << "No camera available. Exiting test.";
401 return;
403 VideoCaptureCapabilities capture_formats;
404 VideoCaptureDevice::Names::iterator names_iterator;
405 for (names_iterator = names_.begin(); names_iterator != names_.end();
406 ++names_iterator) {
407 VideoCaptureDevice::GetDeviceSupportedFormats(*names_iterator,
408 &capture_formats);
409 // Nothing to test here since we cannot forecast the hardware capabilities.
413 TEST_F(VideoCaptureDeviceTest, FakeCaptureVariableResolution) {
414 VideoCaptureDevice::Names names;
416 FakeVideoCaptureDevice::GetDeviceNames(&names);
417 media::VideoCaptureCapability capture_format;
418 capture_format.width = 640;
419 capture_format.height = 480;
420 capture_format.frame_rate = 30;
421 capture_format.frame_size_type = media::VariableResolutionVideoCaptureDevice;
423 ASSERT_GT(static_cast<int>(names.size()), 0);
425 scoped_ptr<VideoCaptureDevice> device(
426 FakeVideoCaptureDevice::Create(names.front()));
427 ASSERT_TRUE(device.get() != NULL);
429 // Get info about the new resolution.
430 EXPECT_CALL(*client_, OnFrameInfo(_))
431 .Times(1);
433 EXPECT_CALL(*client_, OnErr())
434 .Times(0);
435 int action_count = 200;
436 EXPECT_CALL(*client_, OnFrameInfoChanged(_))
437 .Times(AtLeast(action_count / 30));
439 device->AllocateAndStart(capture_format, client_.PassAs<Client>());
441 // The amount of times the OnFrameInfoChanged gets called depends on how often
442 // FakeDevice is supposed to change and what is its actual frame rate.
443 // We set TimeWait to 200 action timeouts and this should be enough for at
444 // least action_count/kFakeCaptureCapabilityChangePeriod calls.
445 for (int i = 0; i < action_count; ++i) {
446 WaitForCapturedFrame();
448 device->StopAndDeAllocate();
451 TEST_F(VideoCaptureDeviceTest, FakeGetDeviceSupportedFormats) {
452 VideoCaptureDevice::Names names;
453 FakeVideoCaptureDevice::GetDeviceNames(&names);
455 VideoCaptureCapabilities capture_formats;
456 VideoCaptureDevice::Names::iterator names_iterator;
458 for (names_iterator = names.begin(); names_iterator != names.end();
459 ++names_iterator) {
460 FakeVideoCaptureDevice::GetDeviceSupportedFormats(*names_iterator,
461 &capture_formats);
462 EXPECT_GE(capture_formats.size(), 1u);
463 EXPECT_EQ(capture_formats[0].width, 640);
464 EXPECT_EQ(capture_formats[0].height, 480);
465 EXPECT_EQ(capture_formats[0].color, media::PIXEL_FORMAT_I420);
466 EXPECT_GE(capture_formats[0].frame_rate, 20);
470 }; // namespace media