Disable Enhanced Bookmark for ICS devices
[chromium-blink-merge.git] / media / video / capture / video_capture_device_unittest.cc
blob0c66c344fea14cea9b81874692fd079a88356c18
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/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/run_loop.h"
11 #include "base/test/test_timeouts.h"
12 #include "base/threading/thread.h"
13 #include "media/base/video_capture_types.h"
14 #include "media/video/capture/video_capture_device.h"
15 #include "media/video/capture/video_capture_device_factory.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 #if defined(OS_WIN)
20 #include "base/win/scoped_com_initializer.h"
21 #include "media/video/capture/win/video_capture_device_factory_win.h"
22 #endif
24 #if defined(OS_MACOSX)
25 #include "media/video/capture/mac/video_capture_device_factory_mac.h"
26 #endif
28 #if defined(OS_ANDROID)
29 #include "base/android/jni_android.h"
30 #include "media/video/capture/android/video_capture_device_android.h"
31 #endif
33 #if defined(OS_MACOSX)
34 // Mac/QTKit will always give you the size you ask for and this case will fail.
35 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
36 // We will always get YUYV from the Mac QTKit/AVFoundation implementations.
37 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
38 #elif defined(OS_WIN)
39 #define MAYBE_AllocateBadSize AllocateBadSize
40 #define MAYBE_CaptureMjpeg CaptureMjpeg
41 #elif defined(OS_ANDROID)
42 // TODO(wjia): enable those tests on Android.
43 // On Android, native camera (JAVA) delivers frames on UI thread which is the
44 // main thread for tests. This results in no frame received by
45 // VideoCaptureAndroid.
46 #define CaptureVGA DISABLED_CaptureVGA
47 #define Capture720p DISABLED_Capture720p
48 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
49 #define ReAllocateCamera DISABLED_ReAllocateCamera
50 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
51 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
52 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
53 #else
54 #define MAYBE_AllocateBadSize AllocateBadSize
55 #define MAYBE_CaptureMjpeg CaptureMjpeg
56 #endif
58 using ::testing::_;
59 using ::testing::SaveArg;
61 namespace media {
63 namespace {
65 class MockClient : public VideoCaptureDevice::Client {
66 public:
67 MOCK_METHOD2(ReserveOutputBuffer,
68 scoped_refptr<Buffer>(VideoFrame::Format format,
69 const gfx::Size& dimensions));
70 MOCK_METHOD3(OnIncomingCapturedVideoFrame,
71 void(const scoped_refptr<Buffer>& buffer,
72 const scoped_refptr<VideoFrame>& frame,
73 const base::TimeTicks& timestamp));
74 MOCK_METHOD1(OnError, void(const std::string& reason));
76 explicit MockClient(base::Callback<void(const VideoCaptureFormat&)> frame_cb)
77 : main_thread_(base::MessageLoopProxy::current()), frame_cb_(frame_cb) {}
79 void OnIncomingCapturedData(const uint8* data,
80 int length,
81 const VideoCaptureFormat& format,
82 int rotation,
83 const base::TimeTicks& timestamp) override {
84 ASSERT_GT(length, 0);
85 ASSERT_TRUE(data != NULL);
86 main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format));
89 private:
90 scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
91 base::Callback<void(const VideoCaptureFormat&)> frame_cb_;
94 class DeviceEnumerationListener :
95 public base::RefCounted<DeviceEnumerationListener> {
96 public:
97 MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr,
98 void(VideoCaptureDevice::Names* names));
99 // GMock doesn't support move-only arguments, so we use this forward method.
100 void OnEnumeratedDevicesCallback(
101 scoped_ptr<VideoCaptureDevice::Names> names) {
102 OnEnumeratedDevicesCallbackPtr(names.release());
104 private:
105 friend class base::RefCounted<DeviceEnumerationListener>;
106 virtual ~DeviceEnumerationListener() {}
109 } // namespace
111 class VideoCaptureDeviceTest : public testing::Test {
112 protected:
113 typedef VideoCaptureDevice::Client Client;
115 VideoCaptureDeviceTest()
116 : loop_(new base::MessageLoop()),
117 client_(
118 new MockClient(base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured,
119 base::Unretained(this)))),
120 video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory(
121 base::MessageLoopProxy::current())) {
122 device_enumeration_listener_ = new DeviceEnumerationListener();
125 void SetUp() override {
126 #if defined(OS_ANDROID)
127 VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(
128 base::android::AttachCurrentThread());
129 #endif
130 EXPECT_CALL(*client_, ReserveOutputBuffer(_,_)).Times(0);
131 EXPECT_CALL(*client_, OnIncomingCapturedVideoFrame(_,_,_)).Times(0);
134 void ResetWithNewClient() {
135 client_.reset(new MockClient(base::Bind(
136 &VideoCaptureDeviceTest::OnFrameCaptured, base::Unretained(this))));
139 void OnFrameCaptured(const VideoCaptureFormat& format) {
140 last_format_ = format;
141 run_loop_->QuitClosure().Run();
144 void WaitForCapturedFrame() {
145 run_loop_.reset(new base::RunLoop());
146 run_loop_->Run();
149 scoped_ptr<VideoCaptureDevice::Names> EnumerateDevices() {
150 VideoCaptureDevice::Names* names;
151 EXPECT_CALL(*device_enumeration_listener_.get(),
152 OnEnumeratedDevicesCallbackPtr(_)).WillOnce(SaveArg<0>(&names));
154 video_capture_device_factory_->EnumerateDeviceNames(
155 base::Bind(&DeviceEnumerationListener::OnEnumeratedDevicesCallback,
156 device_enumeration_listener_));
157 base::MessageLoop::current()->RunUntilIdle();
158 return scoped_ptr<VideoCaptureDevice::Names>(names);
161 const VideoCaptureFormat& last_format() const { return last_format_; }
163 scoped_ptr<VideoCaptureDevice::Name> GetFirstDeviceNameSupportingPixelFormat(
164 const VideoPixelFormat& pixel_format) {
165 names_ = EnumerateDevices();
166 if (names_->empty()) {
167 DVLOG(1) << "No camera available.";
168 return scoped_ptr<VideoCaptureDevice::Name>();
170 for (const auto& names_iterator : *names_) {
171 VideoCaptureFormats supported_formats;
172 video_capture_device_factory_->GetDeviceSupportedFormats(
173 names_iterator,
174 &supported_formats);
175 for (const auto& formats_iterator : supported_formats) {
176 if (formats_iterator.pixel_format == pixel_format) {
177 return scoped_ptr<VideoCaptureDevice::Name>(
178 new VideoCaptureDevice::Name(names_iterator));
182 DVLOG(1) << "No camera can capture the format: " << pixel_format;
183 return scoped_ptr<VideoCaptureDevice::Name>();
186 #if defined(OS_WIN)
187 base::win::ScopedCOMInitializer initialize_com_;
188 #endif
189 scoped_ptr<VideoCaptureDevice::Names> names_;
190 scoped_ptr<base::MessageLoop> loop_;
191 scoped_ptr<base::RunLoop> run_loop_;
192 scoped_ptr<MockClient> client_;
193 scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_;
194 VideoCaptureFormat last_format_;
195 scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
198 // Cause hangs on Windows Debug. http://crbug.com/417824
199 #if defined(OS_WIN) && !defined(NDEBUG)
200 #define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice
201 #else
202 #define MAYBE_OpenInvalidDevice OpenInvalidDevice
203 #endif
205 TEST_F(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) {
206 #if defined(OS_WIN)
207 VideoCaptureDevice::Name::CaptureApiType api_type =
208 VideoCaptureDeviceFactoryWin::PlatformSupportsMediaFoundation()
209 ? VideoCaptureDevice::Name::MEDIA_FOUNDATION
210 : VideoCaptureDevice::Name::DIRECT_SHOW;
211 VideoCaptureDevice::Name device_name("jibberish", "jibberish", api_type);
212 #elif defined(OS_MACOSX)
213 VideoCaptureDevice::Name device_name("jibberish", "jibberish",
214 VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation()
215 ? VideoCaptureDevice::Name::AVFOUNDATION
216 : VideoCaptureDevice::Name::QTKIT);
217 #else
218 VideoCaptureDevice::Name device_name("jibberish", "jibberish");
219 #endif
220 scoped_ptr<VideoCaptureDevice> device =
221 video_capture_device_factory_->Create(device_name);
222 #if !defined(OS_MACOSX)
223 EXPECT_TRUE(device == NULL);
224 #else
225 if (VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation()) {
226 EXPECT_TRUE(device == NULL);
227 } else {
228 // The presence of the actual device is only checked on AllocateAndStart()
229 // and not on creation for QTKit API in Mac OS X platform.
230 EXPECT_CALL(*client_, OnError(_)).Times(1);
232 VideoCaptureParams capture_params;
233 capture_params.requested_format.frame_size.SetSize(640, 480);
234 capture_params.requested_format.frame_rate = 30;
235 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
236 device->AllocateAndStart(capture_params, client_.Pass());
237 device->StopAndDeAllocate();
239 #endif
242 TEST_F(VideoCaptureDeviceTest, CaptureVGA) {
243 names_ = EnumerateDevices();
244 if (names_->empty()) {
245 DVLOG(1) << "No camera available. Exiting test.";
246 return;
249 scoped_ptr<VideoCaptureDevice> device(
250 video_capture_device_factory_->Create(names_->front()));
251 ASSERT_TRUE(device);
252 DVLOG(1) << names_->front().id();
254 EXPECT_CALL(*client_, OnError(_)).Times(0);
256 VideoCaptureParams capture_params;
257 capture_params.requested_format.frame_size.SetSize(640, 480);
258 capture_params.requested_format.frame_rate = 30;
259 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
260 device->AllocateAndStart(capture_params, client_.Pass());
261 // Get captured video frames.
262 WaitForCapturedFrame();
263 EXPECT_EQ(last_format().frame_size.width(), 640);
264 EXPECT_EQ(last_format().frame_size.height(), 480);
265 EXPECT_EQ(static_cast<size_t>(640 * 480 * 3 / 2),
266 last_format().ImageAllocationSize());
267 device->StopAndDeAllocate();
270 TEST_F(VideoCaptureDeviceTest, Capture720p) {
271 names_ = EnumerateDevices();
272 if (names_->empty()) {
273 DVLOG(1) << "No camera available. Exiting test.";
274 return;
277 scoped_ptr<VideoCaptureDevice> device(
278 video_capture_device_factory_->Create(names_->front()));
279 ASSERT_TRUE(device);
281 EXPECT_CALL(*client_, OnError(_)).Times(0);
283 VideoCaptureParams capture_params;
284 capture_params.requested_format.frame_size.SetSize(1280, 720);
285 capture_params.requested_format.frame_rate = 30;
286 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
287 device->AllocateAndStart(capture_params, client_.Pass());
288 // Get captured video frames.
289 WaitForCapturedFrame();
290 EXPECT_EQ(last_format().frame_size.width(), 1280);
291 EXPECT_EQ(last_format().frame_size.height(), 720);
292 EXPECT_EQ(static_cast<size_t>(1280 * 720 * 3 / 2),
293 last_format().ImageAllocationSize());
294 device->StopAndDeAllocate();
297 TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) {
298 names_ = EnumerateDevices();
299 if (names_->empty()) {
300 DVLOG(1) << "No camera available. Exiting test.";
301 return;
303 scoped_ptr<VideoCaptureDevice> device(
304 video_capture_device_factory_->Create(names_->front()));
305 ASSERT_TRUE(device);
307 EXPECT_CALL(*client_, OnError(_)).Times(0);
309 VideoCaptureParams capture_params;
310 capture_params.requested_format.frame_size.SetSize(637, 472);
311 capture_params.requested_format.frame_rate = 35;
312 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
313 device->AllocateAndStart(capture_params, client_.Pass());
314 WaitForCapturedFrame();
315 device->StopAndDeAllocate();
316 EXPECT_EQ(last_format().frame_size.width(), 640);
317 EXPECT_EQ(last_format().frame_size.height(), 480);
318 EXPECT_EQ(static_cast<size_t>(640 * 480 * 3 / 2),
319 last_format().ImageAllocationSize());
322 // Cause hangs on Windows Debug. http://crbug.com/417824
323 #if defined(OS_WIN) && !defined(NDEBUG)
324 #define MAYBE_ReAllocateCamera DISABLED_ReAllocateCamera
325 #else
326 #define MAYBE_ReAllocateCamera ReAllocateCamera
327 #endif
329 TEST_F(VideoCaptureDeviceTest, MAYBE_ReAllocateCamera) {
330 names_ = EnumerateDevices();
331 if (names_->empty()) {
332 DVLOG(1) << "No camera available. Exiting test.";
333 return;
336 // First, do a number of very fast device start/stops.
337 for (int i = 0; i <= 5; i++) {
338 ResetWithNewClient();
339 scoped_ptr<VideoCaptureDevice> device(
340 video_capture_device_factory_->Create(names_->front()));
341 gfx::Size resolution;
342 if (i % 2) {
343 resolution = gfx::Size(640, 480);
344 } else {
345 resolution = gfx::Size(1280, 1024);
347 VideoCaptureParams capture_params;
348 capture_params.requested_format.frame_size = resolution;
349 capture_params.requested_format.frame_rate = 30;
350 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
351 device->AllocateAndStart(capture_params, client_.Pass());
352 device->StopAndDeAllocate();
355 // Finally, do a device start and wait for it to finish.
356 VideoCaptureParams capture_params;
357 capture_params.requested_format.frame_size.SetSize(320, 240);
358 capture_params.requested_format.frame_rate = 30;
359 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
361 ResetWithNewClient();
362 scoped_ptr<VideoCaptureDevice> device(
363 video_capture_device_factory_->Create(names_->front()));
365 device->AllocateAndStart(capture_params, client_.Pass());
366 WaitForCapturedFrame();
367 device->StopAndDeAllocate();
368 device.reset();
369 EXPECT_EQ(last_format().frame_size.width(), 320);
370 EXPECT_EQ(last_format().frame_size.height(), 240);
373 TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) {
374 names_ = EnumerateDevices();
375 if (names_->empty()) {
376 DVLOG(1) << "No camera available. Exiting test.";
377 return;
379 scoped_ptr<VideoCaptureDevice> device(
380 video_capture_device_factory_->Create(names_->front()));
381 ASSERT_TRUE(device);
383 EXPECT_CALL(*client_, OnError(_)).Times(0);
385 VideoCaptureParams capture_params;
386 capture_params.requested_format.frame_size.SetSize(640, 480);
387 capture_params.requested_format.frame_rate = 30;
388 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
389 device->AllocateAndStart(capture_params, client_.Pass());
390 // Get captured video frames.
391 WaitForCapturedFrame();
392 EXPECT_EQ(last_format().frame_size.width(), 640);
393 EXPECT_EQ(last_format().frame_size.height(), 480);
394 EXPECT_EQ(last_format().frame_rate, 30);
395 device->StopAndDeAllocate();
398 // Start the camera in 720p to capture MJPEG instead of a raw format.
399 TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) {
400 scoped_ptr<VideoCaptureDevice::Name> name =
401 GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MJPEG);
402 if (!name) {
403 DVLOG(1) << "No camera supports MJPEG format. Exiting test.";
404 return;
406 scoped_ptr<VideoCaptureDevice> device(
407 video_capture_device_factory_->Create(*name));
408 ASSERT_TRUE(device);
410 EXPECT_CALL(*client_, OnError(_)).Times(0);
412 VideoCaptureParams capture_params;
413 capture_params.requested_format.frame_size.SetSize(1280, 720);
414 capture_params.requested_format.frame_rate = 30;
415 capture_params.requested_format.pixel_format = PIXEL_FORMAT_MJPEG;
416 device->AllocateAndStart(capture_params, client_.Pass());
417 // Get captured video frames.
418 WaitForCapturedFrame();
419 // Verify we get MJPEG from the device. Not all devices can capture 1280x720
420 // @ 30 fps, so we don't care about the exact resolution we get.
421 EXPECT_EQ(last_format().pixel_format, PIXEL_FORMAT_MJPEG);
422 EXPECT_GE(static_cast<size_t>(1280 * 720),
423 last_format().ImageAllocationSize());
424 device->StopAndDeAllocate();
427 TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) {
428 // Use PIXEL_FORMAT_MAX to iterate all device names for testing
429 // GetDeviceSupportedFormats().
430 scoped_ptr<VideoCaptureDevice::Name> name =
431 GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX);
432 // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here
433 // since we cannot forecast the hardware capabilities.
434 ASSERT_FALSE(name);
437 }; // namespace media