OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/capture/video/video_capture_device.h" | 5 #include "media/capture/video/video_capture_device.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
18 #include "base/test/test_timeouts.h" | 18 #include "base/test/test_timeouts.h" |
19 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
20 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
21 #include "build/build_config.h" | 21 #include "build/build_config.h" |
22 #include "media/base/bind_to_current_loop.h" | |
22 #include "media/base/video_capture_types.h" | 23 #include "media/base/video_capture_types.h" |
23 #include "media/capture/video/video_capture_device_factory.h" | 24 #include "media/capture/video/video_capture_device_factory.h" |
24 #include "testing/gmock/include/gmock/gmock.h" | 25 #include "testing/gmock/include/gmock/gmock.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
26 | 27 |
27 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
28 #include "base/win/scoped_com_initializer.h" | 29 #include "base/win/scoped_com_initializer.h" |
29 #include "base/win/windows_version.h" // For fine-grained suppression. | 30 #include "base/win/windows_version.h" // For fine-grained suppression. |
30 #include "media/capture/video/win/video_capture_device_factory_win.h" | 31 #include "media/capture/video/win/video_capture_device_factory_win.h" |
31 #endif | 32 #endif |
32 | 33 |
33 #if defined(OS_MACOSX) | 34 #if defined(OS_MACOSX) |
34 #include "media/base/mac/avfoundation_glue.h" | 35 #include "media/base/mac/avfoundation_glue.h" |
35 #include "media/capture/video/mac/video_capture_device_factory_mac.h" | 36 #include "media/capture/video/mac/video_capture_device_factory_mac.h" |
36 #endif | 37 #endif |
37 | 38 |
38 #if defined(OS_ANDROID) | 39 #if defined(OS_ANDROID) |
39 #include "base/android/jni_android.h" | 40 #include "base/android/jni_android.h" |
40 #include "media/capture/video/android/video_capture_device_android.h" | 41 #include "media/capture/video/android/video_capture_device_android.h" |
41 #endif | 42 #endif |
42 | 43 |
43 #if defined(OS_MACOSX) | 44 #if defined(OS_MACOSX) |
44 // Mac will always give you the size you ask for and this case will fail. | 45 // Mac will always give you the size you ask for and this case will fail. |
45 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize | 46 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize |
46 // We will always get YUYV from the Mac AVFoundation implementations. | 47 // We will always get YUYV from the Mac AVFoundation implementations. |
47 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg | 48 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg |
49 #define MAYBE_TakePhoto TakePhoto | |
48 #elif defined(OS_WIN) | 50 #elif defined(OS_WIN) |
49 #define MAYBE_AllocateBadSize AllocateBadSize | 51 #define MAYBE_AllocateBadSize AllocateBadSize |
50 #define MAYBE_CaptureMjpeg CaptureMjpeg | 52 #define MAYBE_CaptureMjpeg CaptureMjpeg |
53 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
51 #elif defined(OS_ANDROID) | 54 #elif defined(OS_ANDROID) |
52 // TODO(wjia): enable those tests on Android. | 55 // TODO(wjia): enable those tests on Android. |
53 // On Android, native camera (JAVA) delivers frames on UI thread which is the | 56 // On Android, native camera (JAVA) delivers frames on UI thread which is the |
54 // main thread for tests. This results in no frame received by | 57 // main thread for tests. This results in no frame received by |
55 // VideoCaptureAndroid. | 58 // VideoCaptureAndroid. |
56 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize | 59 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize |
57 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning | 60 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning |
58 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning | 61 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning |
59 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg | 62 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg |
63 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
60 #elif defined(OS_LINUX) | 64 #elif defined(OS_LINUX) |
61 // AllocateBadSize will hang when a real camera is attached and if more than one | 65 // AllocateBadSize will hang when a real camera is attached and if more than one |
62 // test is trying to use the camera (even across processes). Do NOT renable | 66 // test is trying to use the camera (even across processes). Do NOT renable |
63 // this test without fixing the many bugs associated with it: | 67 // this test without fixing the many bugs associated with it: |
64 // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824 | 68 // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824 |
65 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize | 69 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize |
66 #define MAYBE_CaptureMjpeg CaptureMjpeg | 70 #define MAYBE_CaptureMjpeg CaptureMjpeg |
71 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
67 #else | 72 #else |
68 #define MAYBE_AllocateBadSize AllocateBadSize | 73 #define MAYBE_AllocateBadSize AllocateBadSize |
69 #define MAYBE_CaptureMjpeg CaptureMjpeg | 74 #define MAYBE_CaptureMjpeg CaptureMjpeg |
75 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
70 #endif | 76 #endif |
71 | 77 |
72 using ::testing::_; | 78 using ::testing::_; |
73 using ::testing::SaveArg; | 79 using ::testing::SaveArg; |
74 | 80 |
75 namespace media { | 81 namespace media { |
76 namespace { | 82 namespace { |
77 | 83 |
78 class MockVideoCaptureClient : public VideoCaptureDevice::Client { | 84 class MockVideoCaptureClient : public VideoCaptureDevice::Client { |
79 public: | 85 public: |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 DoResurrectLastOutputBuffer(); | 135 DoResurrectLastOutputBuffer(); |
130 NOTREACHED() << "This should never be called"; | 136 NOTREACHED() << "This should never be called"; |
131 return std::unique_ptr<Buffer>(); | 137 return std::unique_ptr<Buffer>(); |
132 } | 138 } |
133 | 139 |
134 private: | 140 private: |
135 scoped_refptr<base::SingleThreadTaskRunner> main_thread_; | 141 scoped_refptr<base::SingleThreadTaskRunner> main_thread_; |
136 base::Callback<void(const VideoCaptureFormat&)> frame_cb_; | 142 base::Callback<void(const VideoCaptureFormat&)> frame_cb_; |
137 }; | 143 }; |
138 | 144 |
145 class MockImageCaptureClient : public base::RefCounted<MockImageCaptureClient> { | |
146 public: | |
147 // GMock doesn't support move-only arguments, so we use this forward method. | |
148 void DoOnPhotoTaken(mojo::String mime_type, mojo::Array<uint8_t> data) { | |
149 EXPECT_STREQ("image/jpeg", mime_type.storage().c_str()); | |
150 ASSERT_GT(data.size(), 4u); | |
emircan
2016/07/11 21:23:08
Why is this checking for >=4?
mcasas
2016/07/11 23:29:59
Ooops, unfinished, done.
(nit: it's _GT, not _GE)
| |
151 OnCorrectPhotoTaken(); | |
152 } | |
153 MOCK_METHOD0(OnCorrectPhotoTaken, void(void)); | |
154 MOCK_METHOD1( | |
155 OnTakePhotoFailure, | |
156 void(const base::Callback<void(mojo::String, mojo::Array<uint8_t>)>&)); | |
157 | |
158 private: | |
159 friend class base::RefCounted<MockImageCaptureClient>; | |
160 virtual ~MockImageCaptureClient() {} | |
161 }; | |
162 | |
139 class DeviceEnumerationListener | 163 class DeviceEnumerationListener |
140 : public base::RefCounted<DeviceEnumerationListener> { | 164 : public base::RefCounted<DeviceEnumerationListener> { |
141 public: | 165 public: |
142 MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr, | 166 MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr, |
143 void(VideoCaptureDevice::Names* names)); | 167 void(VideoCaptureDevice::Names* names)); |
144 // GMock doesn't support move-only arguments, so we use this forward method. | 168 // GMock doesn't support move-only arguments, so we use this forward method. |
145 void OnEnumeratedDevicesCallback( | 169 void OnEnumeratedDevicesCallback( |
146 std::unique_ptr<VideoCaptureDevice::Names> names) { | 170 std::unique_ptr<VideoCaptureDevice::Names> names) { |
147 OnEnumeratedDevicesCallbackPtr(names.release()); | 171 OnEnumeratedDevicesCallbackPtr(names.release()); |
148 } | 172 } |
149 | 173 |
150 private: | 174 private: |
151 friend class base::RefCounted<DeviceEnumerationListener>; | 175 friend class base::RefCounted<DeviceEnumerationListener>; |
152 virtual ~DeviceEnumerationListener() {} | 176 virtual ~DeviceEnumerationListener() {} |
153 }; | 177 }; |
154 | 178 |
155 } // namespace | 179 } // namespace |
156 | 180 |
157 class VideoCaptureDeviceTest : public testing::TestWithParam<gfx::Size> { | 181 class VideoCaptureDeviceTest : public testing::TestWithParam<gfx::Size> { |
158 protected: | 182 protected: |
159 typedef VideoCaptureDevice::Client Client; | 183 typedef VideoCaptureDevice::Client Client; |
160 | 184 |
161 VideoCaptureDeviceTest() | 185 VideoCaptureDeviceTest() |
162 : loop_(new base::MessageLoop()), | 186 : loop_(new base::MessageLoop()), |
163 video_capture_client_(new MockVideoCaptureClient( | 187 video_capture_client_(new MockVideoCaptureClient( |
164 base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, | 188 base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, |
165 base::Unretained(this)))), | 189 base::Unretained(this)))), |
190 device_enumeration_listener_(new DeviceEnumerationListener()), | |
191 image_capture_client_(new MockImageCaptureClient()), | |
166 video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( | 192 video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( |
167 base::ThreadTaskRunnerHandle::Get())) { | 193 base::ThreadTaskRunnerHandle::Get())) {} |
168 device_enumeration_listener_ = new DeviceEnumerationListener(); | |
169 } | |
170 | 194 |
171 void SetUp() override { | 195 void SetUp() override { |
172 #if defined(OS_ANDROID) | 196 #if defined(OS_ANDROID) |
173 VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( | 197 VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( |
174 base::android::AttachCurrentThread()); | 198 base::android::AttachCurrentThread()); |
175 #endif | 199 #endif |
176 #if defined(OS_MACOSX) | 200 #if defined(OS_MACOSX) |
177 AVFoundationGlue::InitializeAVFoundation(); | 201 AVFoundationGlue::InitializeAVFoundation(); |
178 #endif | 202 #endif |
179 EXPECT_CALL(*video_capture_client_, DoReserveOutputBuffer()).Times(0); | 203 EXPECT_CALL(*video_capture_client_, DoReserveOutputBuffer()).Times(0); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 DVLOG(1) << "Size " << size.ToString() << " is not supported."; | 272 DVLOG(1) << "Size " << size.ToString() << " is not supported."; |
249 return false; | 273 return false; |
250 } | 274 } |
251 return true; | 275 return true; |
252 } | 276 } |
253 | 277 |
254 #if defined(OS_WIN) | 278 #if defined(OS_WIN) |
255 base::win::ScopedCOMInitializer initialize_com_; | 279 base::win::ScopedCOMInitializer initialize_com_; |
256 #endif | 280 #endif |
257 std::unique_ptr<VideoCaptureDevice::Names> names_; | 281 std::unique_ptr<VideoCaptureDevice::Names> names_; |
258 std::unique_ptr<base::MessageLoop> loop_; | 282 const std::unique_ptr<base::MessageLoop> loop_; |
259 std::unique_ptr<base::RunLoop> run_loop_; | 283 std::unique_ptr<base::RunLoop> run_loop_; |
260 std::unique_ptr<MockVideoCaptureClient> video_capture_client_; | 284 std::unique_ptr<MockVideoCaptureClient> video_capture_client_; |
261 scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; | 285 const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; |
286 const scoped_refptr<MockImageCaptureClient> image_capture_client_; | |
262 VideoCaptureFormat last_format_; | 287 VideoCaptureFormat last_format_; |
263 std::unique_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_; | 288 const std::unique_ptr<VideoCaptureDeviceFactory> |
289 video_capture_device_factory_; | |
264 }; | 290 }; |
265 | 291 |
266 // Cause hangs on Windows Debug. http://crbug.com/417824 | 292 // Cause hangs on Windows Debug. http://crbug.com/417824 |
267 #if defined(OS_WIN) && !defined(NDEBUG) | 293 #if defined(OS_WIN) && !defined(NDEBUG) |
268 #define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice | 294 #define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice |
269 #else | 295 #else |
270 #define MAYBE_OpenInvalidDevice OpenInvalidDevice | 296 #define MAYBE_OpenInvalidDevice OpenInvalidDevice |
271 #endif | 297 #endif |
272 | 298 |
273 TEST_F(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) { | 299 TEST_F(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 std::unique_ptr<VideoCaptureDevice> device( | 344 std::unique_ptr<VideoCaptureDevice> device( |
319 video_capture_device_factory_->Create(names_->front())); | 345 video_capture_device_factory_->Create(names_->front())); |
320 ASSERT_TRUE(device); | 346 ASSERT_TRUE(device); |
321 DVLOG(1) << names_->front().id(); | 347 DVLOG(1) << names_->front().id(); |
322 | 348 |
323 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | 349 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); |
324 | 350 |
325 VideoCaptureParams capture_params; | 351 VideoCaptureParams capture_params; |
326 capture_params.requested_format.frame_size.SetSize(width, height); | 352 capture_params.requested_format.frame_size.SetSize(width, height); |
327 capture_params.requested_format.frame_rate = 30.0f; | 353 capture_params.requested_format.frame_rate = 30.0f; |
328 capture_params.requested_format.pixel_format = | 354 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; |
329 PIXEL_FORMAT_I420; | |
330 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | 355 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); |
331 // Get captured video frames. | 356 // Get captured video frames. |
332 WaitForCapturedFrame(); | 357 WaitForCapturedFrame(); |
333 EXPECT_EQ(last_format().frame_size.width(), width); | 358 EXPECT_EQ(last_format().frame_size.width(), width); |
334 EXPECT_EQ(last_format().frame_size.height(), height); | 359 EXPECT_EQ(last_format().frame_size.height(), height); |
335 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) | 360 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) |
336 EXPECT_EQ(size.GetArea(), last_format().frame_size.GetArea()); | 361 EXPECT_EQ(size.GetArea(), last_format().frame_size.GetArea()); |
337 device->StopAndDeAllocate(); | 362 device->StopAndDeAllocate(); |
338 } | 363 } |
339 | 364 |
(...skipping 14 matching lines...) Expand all Loading... | |
354 std::unique_ptr<VideoCaptureDevice> device( | 379 std::unique_ptr<VideoCaptureDevice> device( |
355 video_capture_device_factory_->Create(names_->front())); | 380 video_capture_device_factory_->Create(names_->front())); |
356 ASSERT_TRUE(device); | 381 ASSERT_TRUE(device); |
357 | 382 |
358 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | 383 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); |
359 | 384 |
360 const gfx::Size input_size(640, 480); | 385 const gfx::Size input_size(640, 480); |
361 VideoCaptureParams capture_params; | 386 VideoCaptureParams capture_params; |
362 capture_params.requested_format.frame_size.SetSize(637, 472); | 387 capture_params.requested_format.frame_size.SetSize(637, 472); |
363 capture_params.requested_format.frame_rate = 35; | 388 capture_params.requested_format.frame_rate = 35; |
364 capture_params.requested_format.pixel_format = | 389 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; |
365 PIXEL_FORMAT_I420; | |
366 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | 390 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); |
367 WaitForCapturedFrame(); | 391 WaitForCapturedFrame(); |
368 device->StopAndDeAllocate(); | 392 device->StopAndDeAllocate(); |
369 EXPECT_EQ(last_format().frame_size.width(), input_size.width()); | 393 EXPECT_EQ(last_format().frame_size.width(), input_size.width()); |
370 EXPECT_EQ(last_format().frame_size.height(), input_size.height()); | 394 EXPECT_EQ(last_format().frame_size.height(), input_size.height()); |
371 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) | 395 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) |
372 EXPECT_EQ(input_size.GetArea(), last_format().frame_size.GetArea()); | 396 EXPECT_EQ(input_size.GetArea(), last_format().frame_size.GetArea()); |
373 } | 397 } |
374 | 398 |
375 // Cause hangs on Windows, Linux. Fails Android. http://crbug.com/417824 | 399 // Cause hangs on Windows, Linux. Fails Android. http://crbug.com/417824 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
477 EXPECT_GE(static_cast<size_t>(1280 * 720), | 501 EXPECT_GE(static_cast<size_t>(1280 * 720), |
478 last_format().ImageAllocationSize()); | 502 last_format().ImageAllocationSize()); |
479 device->StopAndDeAllocate(); | 503 device->StopAndDeAllocate(); |
480 } | 504 } |
481 | 505 |
482 TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) { | 506 TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) { |
483 // Use PIXEL_FORMAT_MAX to iterate all device names for testing | 507 // Use PIXEL_FORMAT_MAX to iterate all device names for testing |
484 // GetDeviceSupportedFormats(). | 508 // GetDeviceSupportedFormats(). |
485 std::unique_ptr<VideoCaptureDevice::Name> name = | 509 std::unique_ptr<VideoCaptureDevice::Name> name = |
486 GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX); | 510 GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX); |
487 // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else | 511 // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here |
488 // to test here | |
489 // since we cannot forecast the hardware capabilities. | 512 // since we cannot forecast the hardware capabilities. |
490 ASSERT_FALSE(name); | 513 ASSERT_FALSE(name); |
491 } | 514 } |
492 | 515 |
516 // Start the camera and take a photo. | |
517 TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) { | |
518 DVLOG(1) << __FUNCTION__; | |
Robert Sesek
2016/07/11 15:20:44
Remove.
mcasas
2016/07/11 23:30:00
Done.
| |
519 names_ = EnumerateDevices(); | |
520 if (names_->empty()) { | |
521 VLOG(1) << "No camera available. Exiting test."; | |
522 return; | |
523 } | |
524 std::unique_ptr<VideoCaptureDevice> device( | |
525 video_capture_device_factory_->Create(names_->front())); | |
526 ASSERT_TRUE(device); | |
527 | |
528 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | |
529 | |
530 VideoCaptureParams capture_params; | |
531 capture_params.requested_format.frame_size.SetSize(640, 480); | |
532 capture_params.requested_format.frame_rate = 30; | |
533 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
534 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
535 WaitForCapturedFrame(); | |
536 | |
537 VideoCaptureDevice::TakePhotoCallback scoped_callback( | |
538 base::Bind(&MockImageCaptureClient::DoOnPhotoTaken, | |
539 image_capture_client_), | |
540 media::BindToCurrentLoop(base::Bind( | |
541 &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_))); | |
542 | |
543 EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1); | |
544 device->TakePhoto(std::move(scoped_callback)); | |
545 WaitForCapturedFrame(); | |
546 | |
547 device->StopAndDeAllocate(); | |
548 } | |
549 | |
493 }; // namespace media | 550 }; // namespace media |
OLD | NEW |