| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "media/capture/video/video_capture_device.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <memory> | |
| 11 #include <utility> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/bind_helpers.h" | |
| 15 #include "base/memory/ref_counted.h" | |
| 16 #include "base/run_loop.h" | |
| 17 #include "base/single_thread_task_runner.h" | |
| 18 #include "base/test/test_timeouts.h" | |
| 19 #include "base/threading/thread.h" | |
| 20 #include "base/threading/thread_task_runner_handle.h" | |
| 21 #include "build/build_config.h" | |
| 22 #include "media/base/bind_to_current_loop.h" | |
| 23 #include "media/base/video_capture_types.h" | |
| 24 #include "media/capture/video/video_capture_device_factory.h" | |
| 25 #include "testing/gmock/include/gmock/gmock.h" | |
| 26 #include "testing/gtest/include/gtest/gtest.h" | |
| 27 | |
| 28 #if defined(OS_WIN) | |
| 29 #include "base/win/scoped_com_initializer.h" | |
| 30 #include "base/win/windows_version.h" // For fine-grained suppression. | |
| 31 #include "media/capture/video/win/video_capture_device_factory_win.h" | |
| 32 #endif | |
| 33 | |
| 34 #if defined(OS_MACOSX) | |
| 35 #include "media/base/mac/avfoundation_glue.h" | |
| 36 #include "media/capture/video/mac/video_capture_device_factory_mac.h" | |
| 37 #endif | |
| 38 | |
| 39 #if defined(OS_ANDROID) | |
| 40 #include "base/android/jni_android.h" | |
| 41 #include "media/capture/video/android/video_capture_device_android.h" | |
| 42 #endif | |
| 43 | |
| 44 #if defined(OS_MACOSX) | |
| 45 // Mac will always give you the size you ask for and this case will fail. | |
| 46 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize | |
| 47 // We will always get YUYV from the Mac AVFoundation implementations. | |
| 48 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg | |
| 49 #define MAYBE_TakePhoto TakePhoto | |
| 50 #elif defined(OS_WIN) | |
| 51 #define MAYBE_AllocateBadSize AllocateBadSize | |
| 52 #define MAYBE_CaptureMjpeg CaptureMjpeg | |
| 53 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
| 54 #elif defined(OS_ANDROID) | |
| 55 // TODO(wjia): enable those tests on Android. | |
| 56 // On Android, native camera (JAVA) delivers frames on UI thread which is the | |
| 57 // main thread for tests. This results in no frame received by | |
| 58 // VideoCaptureAndroid. | |
| 59 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize | |
| 60 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning | |
| 61 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning | |
| 62 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg | |
| 63 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
| 64 #elif defined(OS_LINUX) | |
| 65 // AllocateBadSize will hang when a real camera is attached and if more than one | |
| 66 // test is trying to use the camera (even across processes). Do NOT renable | |
| 67 // this test without fixing the many bugs associated with it: | |
| 68 // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824 | |
| 69 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize | |
| 70 #define MAYBE_CaptureMjpeg CaptureMjpeg | |
| 71 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
| 72 #else | |
| 73 #define MAYBE_AllocateBadSize AllocateBadSize | |
| 74 #define MAYBE_CaptureMjpeg CaptureMjpeg | |
| 75 #define MAYBE_TakePhoto DISABLED_TakePhoto | |
| 76 #endif | |
| 77 | |
| 78 using ::testing::_; | |
| 79 using ::testing::SaveArg; | |
| 80 | |
| 81 namespace media { | |
| 82 namespace { | |
| 83 | |
| 84 class MockVideoCaptureClient : public VideoCaptureDevice::Client { | |
| 85 public: | |
| 86 MOCK_METHOD0(DoReserveOutputBuffer, void(void)); | |
| 87 MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void)); | |
| 88 MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void)); | |
| 89 MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void)); | |
| 90 MOCK_METHOD2(OnError, | |
| 91 void(const tracked_objects::Location& from_here, | |
| 92 const std::string& reason)); | |
| 93 MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void)); | |
| 94 | |
| 95 explicit MockVideoCaptureClient( | |
| 96 base::Callback<void(const VideoCaptureFormat&)> frame_cb) | |
| 97 : main_thread_(base::ThreadTaskRunnerHandle::Get()), | |
| 98 frame_cb_(frame_cb) {} | |
| 99 | |
| 100 void OnIncomingCapturedData(const uint8_t* data, | |
| 101 int length, | |
| 102 const VideoCaptureFormat& format, | |
| 103 int rotation, | |
| 104 base::TimeTicks reference_time, | |
| 105 base::TimeDelta timestamp) override { | |
| 106 ASSERT_GT(length, 0); | |
| 107 ASSERT_TRUE(data != NULL); | |
| 108 main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format)); | |
| 109 } | |
| 110 | |
| 111 // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>. | |
| 112 std::unique_ptr<Buffer> ReserveOutputBuffer( | |
| 113 const gfx::Size& dimensions, | |
| 114 media::VideoPixelFormat format, | |
| 115 media::VideoPixelStorage storage) override { | |
| 116 DoReserveOutputBuffer(); | |
| 117 NOTREACHED() << "This should never be called"; | |
| 118 return std::unique_ptr<Buffer>(); | |
| 119 } | |
| 120 void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer, | |
| 121 const VideoCaptureFormat& frame_format, | |
| 122 base::TimeTicks reference_time, | |
| 123 base::TimeDelta timestamp) override { | |
| 124 DoOnIncomingCapturedBuffer(); | |
| 125 } | |
| 126 void OnIncomingCapturedVideoFrame( | |
| 127 std::unique_ptr<Buffer> buffer, | |
| 128 const scoped_refptr<VideoFrame>& frame) override { | |
| 129 DoOnIncomingCapturedVideoFrame(); | |
| 130 } | |
| 131 std::unique_ptr<Buffer> ResurrectLastOutputBuffer( | |
| 132 const gfx::Size& dimensions, | |
| 133 media::VideoPixelFormat format, | |
| 134 media::VideoPixelStorage storage) { | |
| 135 DoResurrectLastOutputBuffer(); | |
| 136 NOTREACHED() << "This should never be called"; | |
| 137 return std::unique_ptr<Buffer>(); | |
| 138 } | |
| 139 | |
| 140 private: | |
| 141 scoped_refptr<base::SingleThreadTaskRunner> main_thread_; | |
| 142 base::Callback<void(const VideoCaptureFormat&)> frame_cb_; | |
| 143 }; | |
| 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); | |
| 151 // Check some bytes that univocally identify |data| as a JPEG File. | |
| 152 // https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_st
ructure | |
| 153 EXPECT_EQ(0xFF, data[0]); // First SOI byte | |
| 154 EXPECT_EQ(0xD8, data[1]); // Second SOI byte | |
| 155 EXPECT_EQ(0xFF, data[2]); // First JFIF-APP0 byte | |
| 156 EXPECT_EQ(0xE0, data[3]); // Second JFIF-APP0 byte | |
| 157 OnCorrectPhotoTaken(); | |
| 158 } | |
| 159 MOCK_METHOD0(OnCorrectPhotoTaken, void(void)); | |
| 160 MOCK_METHOD1( | |
| 161 OnTakePhotoFailure, | |
| 162 void(const base::Callback<void(mojo::String, mojo::Array<uint8_t>)>&)); | |
| 163 | |
| 164 private: | |
| 165 friend class base::RefCounted<MockImageCaptureClient>; | |
| 166 virtual ~MockImageCaptureClient() {} | |
| 167 }; | |
| 168 | |
| 169 class DeviceEnumerationListener | |
| 170 : public base::RefCounted<DeviceEnumerationListener> { | |
| 171 public: | |
| 172 MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr, | |
| 173 void(VideoCaptureDevice::Names* names)); | |
| 174 // GMock doesn't support move-only arguments, so we use this forward method. | |
| 175 void OnEnumeratedDevicesCallback( | |
| 176 std::unique_ptr<VideoCaptureDevice::Names> names) { | |
| 177 OnEnumeratedDevicesCallbackPtr(names.release()); | |
| 178 } | |
| 179 | |
| 180 private: | |
| 181 friend class base::RefCounted<DeviceEnumerationListener>; | |
| 182 virtual ~DeviceEnumerationListener() {} | |
| 183 }; | |
| 184 | |
| 185 } // namespace | |
| 186 | |
| 187 class VideoCaptureDeviceTest : public testing::TestWithParam<gfx::Size> { | |
| 188 protected: | |
| 189 typedef VideoCaptureDevice::Client Client; | |
| 190 | |
| 191 VideoCaptureDeviceTest() | |
| 192 : loop_(new base::MessageLoop()), | |
| 193 video_capture_client_(new MockVideoCaptureClient( | |
| 194 base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, | |
| 195 base::Unretained(this)))), | |
| 196 device_enumeration_listener_(new DeviceEnumerationListener()), | |
| 197 image_capture_client_(new MockImageCaptureClient()), | |
| 198 video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( | |
| 199 base::ThreadTaskRunnerHandle::Get())) {} | |
| 200 | |
| 201 void SetUp() override { | |
| 202 #if defined(OS_ANDROID) | |
| 203 VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( | |
| 204 base::android::AttachCurrentThread()); | |
| 205 #endif | |
| 206 #if defined(OS_MACOSX) | |
| 207 AVFoundationGlue::InitializeAVFoundation(); | |
| 208 #endif | |
| 209 EXPECT_CALL(*video_capture_client_, DoReserveOutputBuffer()).Times(0); | |
| 210 EXPECT_CALL(*video_capture_client_, DoOnIncomingCapturedBuffer()).Times(0); | |
| 211 EXPECT_CALL(*video_capture_client_, DoOnIncomingCapturedVideoFrame()) | |
| 212 .Times(0); | |
| 213 } | |
| 214 | |
| 215 void ResetWithNewClient() { | |
| 216 video_capture_client_.reset(new MockVideoCaptureClient(base::Bind( | |
| 217 &VideoCaptureDeviceTest::OnFrameCaptured, base::Unretained(this)))); | |
| 218 } | |
| 219 | |
| 220 void OnFrameCaptured(const VideoCaptureFormat& format) { | |
| 221 last_format_ = format; | |
| 222 run_loop_->QuitClosure().Run(); | |
| 223 } | |
| 224 | |
| 225 void WaitForCapturedFrame() { | |
| 226 run_loop_.reset(new base::RunLoop()); | |
| 227 run_loop_->Run(); | |
| 228 } | |
| 229 | |
| 230 std::unique_ptr<VideoCaptureDevice::Names> EnumerateDevices() { | |
| 231 VideoCaptureDevice::Names* names; | |
| 232 EXPECT_CALL(*device_enumeration_listener_.get(), | |
| 233 OnEnumeratedDevicesCallbackPtr(_)).WillOnce(SaveArg<0>(&names)); | |
| 234 | |
| 235 video_capture_device_factory_->EnumerateDeviceNames( | |
| 236 base::Bind(&DeviceEnumerationListener::OnEnumeratedDevicesCallback, | |
| 237 device_enumeration_listener_)); | |
| 238 base::RunLoop().RunUntilIdle(); | |
| 239 return std::unique_ptr<VideoCaptureDevice::Names>(names); | |
| 240 } | |
| 241 | |
| 242 const VideoCaptureFormat& last_format() const { return last_format_; } | |
| 243 | |
| 244 std::unique_ptr<VideoCaptureDevice::Name> | |
| 245 GetFirstDeviceNameSupportingPixelFormat( | |
| 246 const VideoPixelFormat& pixel_format) { | |
| 247 names_ = EnumerateDevices(); | |
| 248 if (names_->empty()) { | |
| 249 DVLOG(1) << "No camera available."; | |
| 250 return std::unique_ptr<VideoCaptureDevice::Name>(); | |
| 251 } | |
| 252 for (const auto& names_iterator : *names_) { | |
| 253 VideoCaptureFormats supported_formats; | |
| 254 video_capture_device_factory_->GetDeviceSupportedFormats( | |
| 255 names_iterator, &supported_formats); | |
| 256 for (const auto& formats_iterator : supported_formats) { | |
| 257 if (formats_iterator.pixel_format == pixel_format) { | |
| 258 return std::unique_ptr<VideoCaptureDevice::Name>( | |
| 259 new VideoCaptureDevice::Name(names_iterator)); | |
| 260 } | |
| 261 } | |
| 262 } | |
| 263 DVLOG_IF(1, pixel_format != PIXEL_FORMAT_MAX) | |
| 264 << "No camera can capture the" | |
| 265 << " format: " << VideoPixelFormatToString(pixel_format); | |
| 266 return std::unique_ptr<VideoCaptureDevice::Name>(); | |
| 267 } | |
| 268 | |
| 269 bool IsCaptureSizeSupported(const VideoCaptureDevice::Name& device, | |
| 270 const gfx::Size& size) { | |
| 271 VideoCaptureFormats supported_formats; | |
| 272 video_capture_device_factory_->GetDeviceSupportedFormats( | |
| 273 device, &supported_formats); | |
| 274 const auto it = std::find_if( | |
| 275 supported_formats.begin(), supported_formats.end(), | |
| 276 [&size](VideoCaptureFormat const& f) { return f.frame_size == size; }); | |
| 277 if (it == supported_formats.end()) { | |
| 278 DVLOG(1) << "Size " << size.ToString() << " is not supported."; | |
| 279 return false; | |
| 280 } | |
| 281 return true; | |
| 282 } | |
| 283 | |
| 284 #if defined(OS_WIN) | |
| 285 base::win::ScopedCOMInitializer initialize_com_; | |
| 286 #endif | |
| 287 std::unique_ptr<VideoCaptureDevice::Names> names_; | |
| 288 const std::unique_ptr<base::MessageLoop> loop_; | |
| 289 std::unique_ptr<base::RunLoop> run_loop_; | |
| 290 std::unique_ptr<MockVideoCaptureClient> video_capture_client_; | |
| 291 const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; | |
| 292 const scoped_refptr<MockImageCaptureClient> image_capture_client_; | |
| 293 VideoCaptureFormat last_format_; | |
| 294 const std::unique_ptr<VideoCaptureDeviceFactory> | |
| 295 video_capture_device_factory_; | |
| 296 }; | |
| 297 | |
| 298 // Cause hangs on Windows Debug. http://crbug.com/417824 | |
| 299 #if defined(OS_WIN) && !defined(NDEBUG) | |
| 300 #define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice | |
| 301 #else | |
| 302 #define MAYBE_OpenInvalidDevice OpenInvalidDevice | |
| 303 #endif | |
| 304 | |
| 305 TEST_F(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) { | |
| 306 #if defined(OS_WIN) | |
| 307 VideoCaptureDevice::Name::CaptureApiType api_type = | |
| 308 VideoCaptureDeviceFactoryWin::PlatformSupportsMediaFoundation() | |
| 309 ? VideoCaptureDevice::Name::MEDIA_FOUNDATION | |
| 310 : VideoCaptureDevice::Name::DIRECT_SHOW; | |
| 311 VideoCaptureDevice::Name device_name("jibberish", "jibberish", api_type); | |
| 312 #elif defined(OS_MACOSX) | |
| 313 VideoCaptureDevice::Name device_name("jibberish", "jibberish", | |
| 314 VideoCaptureDevice::Name::AVFOUNDATION); | |
| 315 #else | |
| 316 VideoCaptureDevice::Name device_name("jibberish", "jibberish"); | |
| 317 #endif | |
| 318 std::unique_ptr<VideoCaptureDevice> device = | |
| 319 video_capture_device_factory_->Create(device_name); | |
| 320 | |
| 321 #if !defined(OS_MACOSX) | |
| 322 EXPECT_TRUE(device == NULL); | |
| 323 #else | |
| 324 // The presence of the actual device is only checked on AllocateAndStart() | |
| 325 // and not on creation. | |
| 326 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(1); | |
| 327 | |
| 328 VideoCaptureParams capture_params; | |
| 329 capture_params.requested_format.frame_size.SetSize(640, 480); | |
| 330 capture_params.requested_format.frame_rate = 30; | |
| 331 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 332 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 333 device->StopAndDeAllocate(); | |
| 334 #endif | |
| 335 } | |
| 336 | |
| 337 TEST_P(VideoCaptureDeviceTest, CaptureWithSize) { | |
| 338 names_ = EnumerateDevices(); | |
| 339 if (names_->empty()) { | |
| 340 VLOG(1) << "No camera available. Exiting test."; | |
| 341 return; | |
| 342 } | |
| 343 | |
| 344 const gfx::Size& size = GetParam(); | |
| 345 if (!IsCaptureSizeSupported(names_->front(), size)) | |
| 346 return; | |
| 347 const int width = size.width(); | |
| 348 const int height = size.height(); | |
| 349 | |
| 350 std::unique_ptr<VideoCaptureDevice> device( | |
| 351 video_capture_device_factory_->Create(names_->front())); | |
| 352 ASSERT_TRUE(device); | |
| 353 DVLOG(1) << names_->front().id(); | |
| 354 | |
| 355 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | |
| 356 | |
| 357 VideoCaptureParams capture_params; | |
| 358 capture_params.requested_format.frame_size.SetSize(width, height); | |
| 359 capture_params.requested_format.frame_rate = 30.0f; | |
| 360 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 361 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 362 // Get captured video frames. | |
| 363 WaitForCapturedFrame(); | |
| 364 EXPECT_EQ(last_format().frame_size.width(), width); | |
| 365 EXPECT_EQ(last_format().frame_size.height(), height); | |
| 366 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) | |
| 367 EXPECT_EQ(size.GetArea(), last_format().frame_size.GetArea()); | |
| 368 device->StopAndDeAllocate(); | |
| 369 } | |
| 370 | |
| 371 #if !defined(OS_ANDROID) | |
| 372 const gfx::Size kCaptureSizes[] = {gfx::Size(640, 480), gfx::Size(1280, 720)}; | |
| 373 | |
| 374 INSTANTIATE_TEST_CASE_P(VideoCaptureDeviceTests, | |
| 375 VideoCaptureDeviceTest, | |
| 376 testing::ValuesIn(kCaptureSizes)); | |
| 377 #endif | |
| 378 | |
| 379 TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) { | |
| 380 names_ = EnumerateDevices(); | |
| 381 if (names_->empty()) { | |
| 382 VLOG(1) << "No camera available. Exiting test."; | |
| 383 return; | |
| 384 } | |
| 385 std::unique_ptr<VideoCaptureDevice> device( | |
| 386 video_capture_device_factory_->Create(names_->front())); | |
| 387 ASSERT_TRUE(device); | |
| 388 | |
| 389 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | |
| 390 | |
| 391 const gfx::Size input_size(640, 480); | |
| 392 VideoCaptureParams capture_params; | |
| 393 capture_params.requested_format.frame_size.SetSize(637, 472); | |
| 394 capture_params.requested_format.frame_rate = 35; | |
| 395 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 396 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 397 WaitForCapturedFrame(); | |
| 398 device->StopAndDeAllocate(); | |
| 399 EXPECT_EQ(last_format().frame_size.width(), input_size.width()); | |
| 400 EXPECT_EQ(last_format().frame_size.height(), input_size.height()); | |
| 401 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) | |
| 402 EXPECT_EQ(input_size.GetArea(), last_format().frame_size.GetArea()); | |
| 403 } | |
| 404 | |
| 405 // Cause hangs on Windows, Linux. Fails Android. http://crbug.com/417824 | |
| 406 TEST_F(VideoCaptureDeviceTest, DISABLED_ReAllocateCamera) { | |
| 407 names_ = EnumerateDevices(); | |
| 408 if (names_->empty()) { | |
| 409 VLOG(1) << "No camera available. Exiting test."; | |
| 410 return; | |
| 411 } | |
| 412 | |
| 413 // First, do a number of very fast device start/stops. | |
| 414 for (int i = 0; i <= 5; i++) { | |
| 415 ResetWithNewClient(); | |
| 416 std::unique_ptr<VideoCaptureDevice> device( | |
| 417 video_capture_device_factory_->Create(names_->front())); | |
| 418 gfx::Size resolution; | |
| 419 if (i % 2) { | |
| 420 resolution = gfx::Size(640, 480); | |
| 421 } else { | |
| 422 resolution = gfx::Size(1280, 1024); | |
| 423 } | |
| 424 VideoCaptureParams capture_params; | |
| 425 capture_params.requested_format.frame_size = resolution; | |
| 426 capture_params.requested_format.frame_rate = 30; | |
| 427 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 428 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 429 device->StopAndDeAllocate(); | |
| 430 } | |
| 431 | |
| 432 // Finally, do a device start and wait for it to finish. | |
| 433 VideoCaptureParams capture_params; | |
| 434 capture_params.requested_format.frame_size.SetSize(320, 240); | |
| 435 capture_params.requested_format.frame_rate = 30; | |
| 436 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 437 | |
| 438 ResetWithNewClient(); | |
| 439 std::unique_ptr<VideoCaptureDevice> device( | |
| 440 video_capture_device_factory_->Create(names_->front())); | |
| 441 | |
| 442 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 443 WaitForCapturedFrame(); | |
| 444 device->StopAndDeAllocate(); | |
| 445 device.reset(); | |
| 446 EXPECT_EQ(last_format().frame_size.width(), 320); | |
| 447 EXPECT_EQ(last_format().frame_size.height(), 240); | |
| 448 } | |
| 449 | |
| 450 TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) { | |
| 451 names_ = EnumerateDevices(); | |
| 452 if (names_->empty()) { | |
| 453 VLOG(1) << "No camera available. Exiting test."; | |
| 454 return; | |
| 455 } | |
| 456 std::unique_ptr<VideoCaptureDevice> device( | |
| 457 video_capture_device_factory_->Create(names_->front())); | |
| 458 ASSERT_TRUE(device); | |
| 459 | |
| 460 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | |
| 461 | |
| 462 VideoCaptureParams capture_params; | |
| 463 capture_params.requested_format.frame_size.SetSize(640, 480); | |
| 464 capture_params.requested_format.frame_rate = 30; | |
| 465 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 466 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 467 // Get captured video frames. | |
| 468 WaitForCapturedFrame(); | |
| 469 EXPECT_EQ(last_format().frame_size.width(), 640); | |
| 470 EXPECT_EQ(last_format().frame_size.height(), 480); | |
| 471 EXPECT_EQ(last_format().frame_rate, 30); | |
| 472 device->StopAndDeAllocate(); | |
| 473 } | |
| 474 | |
| 475 // Start the camera in 720p to capture MJPEG instead of a raw format. | |
| 476 TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) { | |
| 477 std::unique_ptr<VideoCaptureDevice::Name> name = | |
| 478 GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MJPEG); | |
| 479 if (!name) { | |
| 480 VLOG(1) << "No camera supports MJPEG format. Exiting test."; | |
| 481 return; | |
| 482 } | |
| 483 #if defined(OS_WIN) | |
| 484 base::win::Version version = base::win::GetVersion(); | |
| 485 VLOG(1) << "Windows version: " << (int)version; | |
| 486 if (version >= base::win::VERSION_WIN10) { | |
| 487 VLOG(1) << "Skipped on Win10: http://crbug.com/570604."; | |
| 488 return; | |
| 489 } | |
| 490 #endif | |
| 491 std::unique_ptr<VideoCaptureDevice> device( | |
| 492 video_capture_device_factory_->Create(*name)); | |
| 493 ASSERT_TRUE(device); | |
| 494 | |
| 495 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | |
| 496 | |
| 497 VideoCaptureParams capture_params; | |
| 498 capture_params.requested_format.frame_size.SetSize(1280, 720); | |
| 499 capture_params.requested_format.frame_rate = 30; | |
| 500 capture_params.requested_format.pixel_format = PIXEL_FORMAT_MJPEG; | |
| 501 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 502 // Get captured video frames. | |
| 503 WaitForCapturedFrame(); | |
| 504 // Verify we get MJPEG from the device. Not all devices can capture 1280x720 | |
| 505 // @ 30 fps, so we don't care about the exact resolution we get. | |
| 506 EXPECT_EQ(last_format().pixel_format, PIXEL_FORMAT_MJPEG); | |
| 507 EXPECT_GE(static_cast<size_t>(1280 * 720), | |
| 508 last_format().ImageAllocationSize()); | |
| 509 device->StopAndDeAllocate(); | |
| 510 } | |
| 511 | |
| 512 TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) { | |
| 513 // Use PIXEL_FORMAT_MAX to iterate all device names for testing | |
| 514 // GetDeviceSupportedFormats(). | |
| 515 std::unique_ptr<VideoCaptureDevice::Name> name = | |
| 516 GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX); | |
| 517 // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here | |
| 518 // since we cannot forecast the hardware capabilities. | |
| 519 ASSERT_FALSE(name); | |
| 520 } | |
| 521 | |
| 522 // Start the camera and take a photo. | |
| 523 TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) { | |
| 524 names_ = EnumerateDevices(); | |
| 525 if (names_->empty()) { | |
| 526 VLOG(1) << "No camera available. Exiting test."; | |
| 527 return; | |
| 528 } | |
| 529 std::unique_ptr<VideoCaptureDevice> device( | |
| 530 video_capture_device_factory_->Create(names_->front())); | |
| 531 ASSERT_TRUE(device); | |
| 532 | |
| 533 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | |
| 534 | |
| 535 VideoCaptureParams capture_params; | |
| 536 capture_params.requested_format.frame_size.SetSize(640, 480); | |
| 537 capture_params.requested_format.frame_rate = 30; | |
| 538 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | |
| 539 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | |
| 540 WaitForCapturedFrame(); | |
| 541 | |
| 542 VideoCaptureDevice::TakePhotoCallback scoped_callback( | |
| 543 base::Bind(&MockImageCaptureClient::DoOnPhotoTaken, | |
| 544 image_capture_client_), | |
| 545 media::BindToCurrentLoop(base::Bind( | |
| 546 &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_))); | |
| 547 | |
| 548 EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1); | |
| 549 device->TakePhoto(std::move(scoped_callback)); | |
| 550 WaitForCapturedFrame(); | |
| 551 | |
| 552 device->StopAndDeAllocate(); | |
| 553 } | |
| 554 | |
| 555 }; // namespace media | |
| OLD | NEW |