| 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> |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 | 198 |
| 199 const mojom::PhotoCapabilities* capabilities() { return capabilities_.get(); } | 199 const mojom::PhotoCapabilities* capabilities() { return capabilities_.get(); } |
| 200 | 200 |
| 201 private: | 201 private: |
| 202 friend class base::RefCountedThreadSafe<MockImageCaptureClient>; | 202 friend class base::RefCountedThreadSafe<MockImageCaptureClient>; |
| 203 virtual ~MockImageCaptureClient() {} | 203 virtual ~MockImageCaptureClient() {} |
| 204 | 204 |
| 205 mojom::PhotoCapabilitiesPtr capabilities_; | 205 mojom::PhotoCapabilitiesPtr capabilities_; |
| 206 }; | 206 }; |
| 207 | 207 |
| 208 class DeviceEnumerationListener | |
| 209 : public base::RefCounted<DeviceEnumerationListener> { | |
| 210 public: | |
| 211 MOCK_METHOD1(DoOnEnumerateDeviceDescriptors, | |
| 212 void(VideoCaptureDeviceDescriptors* device_descriptors)); | |
| 213 // GMock doesn't support move-only arguments, so we use this forward method. | |
| 214 void OnEnumerateDeviceDescriptors( | |
| 215 std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors) { | |
| 216 DoOnEnumerateDeviceDescriptors(device_descriptors.release()); | |
| 217 } | |
| 218 | |
| 219 private: | |
| 220 friend class base::RefCounted<DeviceEnumerationListener>; | |
| 221 virtual ~DeviceEnumerationListener() {} | |
| 222 }; | |
| 223 | |
| 224 } // namespace | 208 } // namespace |
| 225 | 209 |
| 226 class VideoCaptureDeviceTest : public testing::TestWithParam<gfx::Size> { | 210 class VideoCaptureDeviceTest : public testing::TestWithParam<gfx::Size> { |
| 227 protected: | 211 protected: |
| 228 typedef VideoCaptureDevice::Client Client; | 212 typedef VideoCaptureDevice::Client Client; |
| 229 | 213 |
| 230 VideoCaptureDeviceTest() | 214 VideoCaptureDeviceTest() |
| 231 : loop_(new base::MessageLoop()), | 215 : loop_(new base::MessageLoop()), |
| 216 device_descriptors_(new VideoCaptureDeviceDescriptors()), |
| 232 video_capture_client_(new MockVideoCaptureClient( | 217 video_capture_client_(new MockVideoCaptureClient( |
| 233 base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, | 218 base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, |
| 234 base::Unretained(this)))), | 219 base::Unretained(this)))), |
| 235 device_enumeration_listener_(new DeviceEnumerationListener()), | |
| 236 image_capture_client_(new MockImageCaptureClient()), | 220 image_capture_client_(new MockImageCaptureClient()), |
| 237 video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( | 221 video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( |
| 238 base::ThreadTaskRunnerHandle::Get())) {} | 222 base::ThreadTaskRunnerHandle::Get())) {} |
| 239 | 223 |
| 240 void SetUp() override { | 224 void SetUp() override { |
| 241 #if defined(OS_ANDROID) | 225 #if defined(OS_ANDROID) |
| 242 VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( | 226 VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( |
| 243 base::android::AttachCurrentThread()); | 227 base::android::AttachCurrentThread()); |
| 244 | 228 |
| 245 static_cast<VideoCaptureDeviceFactoryAndroid*>( | 229 static_cast<VideoCaptureDeviceFactoryAndroid*>( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 261 last_format_ = format; | 245 last_format_ = format; |
| 262 if (run_loop_) | 246 if (run_loop_) |
| 263 run_loop_->QuitClosure().Run(); | 247 run_loop_->QuitClosure().Run(); |
| 264 } | 248 } |
| 265 | 249 |
| 266 void WaitForCapturedFrame() { | 250 void WaitForCapturedFrame() { |
| 267 run_loop_.reset(new base::RunLoop()); | 251 run_loop_.reset(new base::RunLoop()); |
| 268 run_loop_->Run(); | 252 run_loop_->Run(); |
| 269 } | 253 } |
| 270 | 254 |
| 271 bool EnumerateAndFindUsableDevices() { | 255 bool FindUsableDevices() { |
| 272 VideoCaptureDeviceDescriptors* descriptors = nullptr; | 256 video_capture_device_factory_->GetDeviceDescriptors( |
| 273 EXPECT_CALL(*device_enumeration_listener_.get(), | 257 device_descriptors_.get()); |
| 274 DoOnEnumerateDeviceDescriptors(_)) | |
| 275 .WillOnce(SaveArg<0>(&descriptors)); | |
| 276 | |
| 277 video_capture_device_factory_->EnumerateDeviceDescriptors( | |
| 278 base::Bind(&DeviceEnumerationListener::OnEnumerateDeviceDescriptors, | |
| 279 device_enumeration_listener_)); | |
| 280 base::RunLoop().RunUntilIdle(); | |
| 281 | |
| 282 device_descriptors_.reset(descriptors); | |
| 283 if (!device_descriptors_) | |
| 284 return false; | |
| 285 | 258 |
| 286 #if defined(OS_ANDROID) | 259 #if defined(OS_ANDROID) |
| 287 // Android deprecated/legacy devices capture on a single thread, which is | 260 // Android deprecated/legacy devices capture on a single thread, which is |
| 288 // occupied by the tests, so nothing gets actually delivered. | 261 // occupied by the tests, so nothing gets actually delivered. |
| 289 // TODO(mcasas): use those devices' test mode to deliver frames in a | 262 // TODO(mcasas): use those devices' test mode to deliver frames in a |
| 290 // background thread, https://crbug.com/626857 | 263 // background thread, https://crbug.com/626857 |
| 291 for (const auto& descriptor : *descriptors) { | 264 for (const auto& descriptor : *device_descriptors_) { |
| 292 if (VideoCaptureDeviceFactoryAndroid::IsLegacyOrDeprecatedDevice( | 265 if (VideoCaptureDeviceFactoryAndroid::IsLegacyOrDeprecatedDevice( |
| 293 descriptor.device_id)) { | 266 descriptor.device_id)) { |
| 294 return false; | 267 return false; |
| 295 } | 268 } |
| 296 } | 269 } |
| 297 #endif | 270 #endif |
| 298 | 271 |
| 299 return !device_descriptors_->empty(); | 272 return !device_descriptors_->empty(); |
| 300 } | 273 } |
| 301 | 274 |
| 302 const VideoCaptureFormat& last_format() const { return last_format_; } | 275 const VideoCaptureFormat& last_format() const { return last_format_; } |
| 303 | 276 |
| 304 std::unique_ptr<VideoCaptureDeviceDescriptor> | 277 std::unique_ptr<VideoCaptureDeviceDescriptor> |
| 305 GetFirstDeviceDescriptorSupportingPixelFormat( | 278 GetFirstDeviceDescriptorSupportingPixelFormat( |
| 306 const VideoPixelFormat& pixel_format) { | 279 const VideoPixelFormat& pixel_format) { |
| 307 if (!EnumerateAndFindUsableDevices()) | 280 if (!FindUsableDevices()) |
| 308 return nullptr; | 281 return nullptr; |
| 309 | 282 |
| 310 for (const auto& descriptor : *device_descriptors_) { | 283 for (const auto& descriptor : *device_descriptors_) { |
| 311 VideoCaptureFormats supported_formats; | 284 VideoCaptureFormats supported_formats; |
| 312 video_capture_device_factory_->GetSupportedFormats(descriptor, | 285 video_capture_device_factory_->GetSupportedFormats(descriptor, |
| 313 &supported_formats); | 286 &supported_formats); |
| 314 for (const auto& formats_iterator : supported_formats) { | 287 for (const auto& formats_iterator : supported_formats) { |
| 315 if (formats_iterator.pixel_format == pixel_format) { | 288 if (formats_iterator.pixel_format == pixel_format) { |
| 316 return std::unique_ptr<VideoCaptureDeviceDescriptor>( | 289 return std::unique_ptr<VideoCaptureDeviceDescriptor>( |
| 317 new VideoCaptureDeviceDescriptor(descriptor)); | 290 new VideoCaptureDeviceDescriptor(descriptor)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 334 if (it == supported_formats.end()) { | 307 if (it == supported_formats.end()) { |
| 335 DVLOG(1) << "Size " << size.ToString() << " is not supported."; | 308 DVLOG(1) << "Size " << size.ToString() << " is not supported."; |
| 336 return false; | 309 return false; |
| 337 } | 310 } |
| 338 return true; | 311 return true; |
| 339 } | 312 } |
| 340 | 313 |
| 341 #if defined(OS_WIN) | 314 #if defined(OS_WIN) |
| 342 base::win::ScopedCOMInitializer initialize_com_; | 315 base::win::ScopedCOMInitializer initialize_com_; |
| 343 #endif | 316 #endif |
| 317 const std::unique_ptr<base::MessageLoop> loop_; |
| 344 std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors_; | 318 std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors_; |
| 345 const std::unique_ptr<base::MessageLoop> loop_; | |
| 346 std::unique_ptr<base::RunLoop> run_loop_; | 319 std::unique_ptr<base::RunLoop> run_loop_; |
| 347 std::unique_ptr<MockVideoCaptureClient> video_capture_client_; | 320 std::unique_ptr<MockVideoCaptureClient> video_capture_client_; |
| 348 const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; | |
| 349 const scoped_refptr<MockImageCaptureClient> image_capture_client_; | 321 const scoped_refptr<MockImageCaptureClient> image_capture_client_; |
| 350 VideoCaptureFormat last_format_; | 322 VideoCaptureFormat last_format_; |
| 351 const std::unique_ptr<VideoCaptureDeviceFactory> | 323 const std::unique_ptr<VideoCaptureDeviceFactory> |
| 352 video_capture_device_factory_; | 324 video_capture_device_factory_; |
| 353 }; | 325 }; |
| 354 | 326 |
| 355 // Cause hangs on Windows Debug. http://crbug.com/417824 | 327 // Cause hangs on Windows Debug. http://crbug.com/417824 |
| 356 #if defined(OS_WIN) && !defined(NDEBUG) | 328 #if defined(OS_WIN) && !defined(NDEBUG) |
| 357 #define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice | 329 #define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice |
| 358 #else | 330 #else |
| (...skipping 26 matching lines...) Expand all Loading... |
| 385 capture_params.requested_format.frame_size.SetSize(640, 480); | 357 capture_params.requested_format.frame_size.SetSize(640, 480); |
| 386 capture_params.requested_format.frame_rate = 30; | 358 capture_params.requested_format.frame_rate = 30; |
| 387 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | 359 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; |
| 388 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | 360 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); |
| 389 device->StopAndDeAllocate(); | 361 device->StopAndDeAllocate(); |
| 390 #endif | 362 #endif |
| 391 } | 363 } |
| 392 | 364 |
| 393 // Allocates the first enumerated device, and expects a frame. | 365 // Allocates the first enumerated device, and expects a frame. |
| 394 TEST_P(VideoCaptureDeviceTest, CaptureWithSize) { | 366 TEST_P(VideoCaptureDeviceTest, CaptureWithSize) { |
| 395 if (!EnumerateAndFindUsableDevices()) | 367 if (!FindUsableDevices()) |
| 396 return; | 368 return; |
| 397 | 369 |
| 398 const gfx::Size& size = GetParam(); | 370 const gfx::Size& size = GetParam(); |
| 399 if (!IsCaptureSizeSupported(device_descriptors_->front(), size)) | 371 if (!IsCaptureSizeSupported(device_descriptors_->front(), size)) |
| 400 return; | 372 return; |
| 401 const int width = size.width(); | 373 const int width = size.width(); |
| 402 const int height = size.height(); | 374 const int height = size.height(); |
| 403 | 375 |
| 404 std::unique_ptr<VideoCaptureDevice> device( | 376 std::unique_ptr<VideoCaptureDevice> device( |
| 405 video_capture_device_factory_->CreateDevice( | 377 video_capture_device_factory_->CreateDevice( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 426 | 398 |
| 427 const gfx::Size kCaptureSizes[] = {gfx::Size(640, 480), gfx::Size(1280, 720)}; | 399 const gfx::Size kCaptureSizes[] = {gfx::Size(640, 480), gfx::Size(1280, 720)}; |
| 428 | 400 |
| 429 INSTANTIATE_TEST_CASE_P(VideoCaptureDeviceTests, | 401 INSTANTIATE_TEST_CASE_P(VideoCaptureDeviceTests, |
| 430 VideoCaptureDeviceTest, | 402 VideoCaptureDeviceTest, |
| 431 testing::ValuesIn(kCaptureSizes)); | 403 testing::ValuesIn(kCaptureSizes)); |
| 432 | 404 |
| 433 // Allocates a device with an uncommon resolution and verifies frames are | 405 // Allocates a device with an uncommon resolution and verifies frames are |
| 434 // captured in a close, much more typical one. | 406 // captured in a close, much more typical one. |
| 435 TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) { | 407 TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) { |
| 436 if (!EnumerateAndFindUsableDevices()) | 408 if (!FindUsableDevices()) |
| 437 return; | 409 return; |
| 438 | 410 |
| 439 std::unique_ptr<VideoCaptureDevice> device( | 411 std::unique_ptr<VideoCaptureDevice> device( |
| 440 video_capture_device_factory_->CreateDevice( | 412 video_capture_device_factory_->CreateDevice( |
| 441 device_descriptors_->front())); | 413 device_descriptors_->front())); |
| 442 ASSERT_TRUE(device); | 414 ASSERT_TRUE(device); |
| 443 | 415 |
| 444 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); | 416 EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); |
| 445 EXPECT_CALL(*video_capture_client_, OnStarted()); | 417 EXPECT_CALL(*video_capture_client_, OnStarted()); |
| 446 | 418 |
| 447 const gfx::Size input_size(640, 480); | 419 const gfx::Size input_size(640, 480); |
| 448 VideoCaptureParams capture_params; | 420 VideoCaptureParams capture_params; |
| 449 capture_params.requested_format.frame_size.SetSize(637, 472); | 421 capture_params.requested_format.frame_size.SetSize(637, 472); |
| 450 capture_params.requested_format.frame_rate = 35; | 422 capture_params.requested_format.frame_rate = 35; |
| 451 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; | 423 capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; |
| 452 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); | 424 device->AllocateAndStart(capture_params, std::move(video_capture_client_)); |
| 453 WaitForCapturedFrame(); | 425 WaitForCapturedFrame(); |
| 454 device->StopAndDeAllocate(); | 426 device->StopAndDeAllocate(); |
| 455 EXPECT_EQ(last_format().frame_size.width(), input_size.width()); | 427 EXPECT_EQ(last_format().frame_size.width(), input_size.width()); |
| 456 EXPECT_EQ(last_format().frame_size.height(), input_size.height()); | 428 EXPECT_EQ(last_format().frame_size.height(), input_size.height()); |
| 457 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) | 429 if (last_format().pixel_format != PIXEL_FORMAT_MJPEG) |
| 458 EXPECT_EQ(input_size.GetArea(), last_format().frame_size.GetArea()); | 430 EXPECT_EQ(input_size.GetArea(), last_format().frame_size.GetArea()); |
| 459 } | 431 } |
| 460 | 432 |
| 461 // Cause hangs on Windows, Linux. Fails Android. https://crbug.com/417824 | 433 // Cause hangs on Windows, Linux. Fails Android. https://crbug.com/417824 |
| 462 TEST_F(VideoCaptureDeviceTest, DISABLED_ReAllocateCamera) { | 434 TEST_F(VideoCaptureDeviceTest, DISABLED_ReAllocateCamera) { |
| 463 if (!EnumerateAndFindUsableDevices()) | 435 if (!FindUsableDevices()) |
| 464 return; | 436 return; |
| 465 | 437 |
| 466 // First, do a number of very fast device start/stops. | 438 // First, do a number of very fast device start/stops. |
| 467 for (int i = 0; i <= 5; i++) { | 439 for (int i = 0; i <= 5; i++) { |
| 468 ResetWithNewClient(); | 440 ResetWithNewClient(); |
| 469 std::unique_ptr<VideoCaptureDevice> device( | 441 std::unique_ptr<VideoCaptureDevice> device( |
| 470 video_capture_device_factory_->CreateDevice( | 442 video_capture_device_factory_->CreateDevice( |
| 471 device_descriptors_->front())); | 443 device_descriptors_->front())); |
| 472 gfx::Size resolution; | 444 gfx::Size resolution; |
| 473 if (i % 2) | 445 if (i % 2) |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 std::unique_ptr<VideoCaptureDeviceDescriptor> device_descriptor = | 518 std::unique_ptr<VideoCaptureDeviceDescriptor> device_descriptor = |
| 547 GetFirstDeviceDescriptorSupportingPixelFormat(PIXEL_FORMAT_MAX); | 519 GetFirstDeviceDescriptorSupportingPixelFormat(PIXEL_FORMAT_MAX); |
| 548 // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here | 520 // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here |
| 549 // since we cannot forecast the hardware capabilities. | 521 // since we cannot forecast the hardware capabilities. |
| 550 ASSERT_FALSE(device_descriptor); | 522 ASSERT_FALSE(device_descriptor); |
| 551 } | 523 } |
| 552 | 524 |
| 553 // Starts the camera and verifies that a photo can be taken. The correctness of | 525 // Starts the camera and verifies that a photo can be taken. The correctness of |
| 554 // the photo is enforced by MockImageCaptureClient. | 526 // the photo is enforced by MockImageCaptureClient. |
| 555 TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) { | 527 TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) { |
| 556 if (!EnumerateAndFindUsableDevices()) | 528 if (!FindUsableDevices()) |
| 557 return; | 529 return; |
| 558 | 530 |
| 559 #if defined(OS_ANDROID) | 531 #if defined(OS_ANDROID) |
| 560 // TODO(mcasas): fails on Lollipop devices, reconnect https://crbug.com/646840 | 532 // TODO(mcasas): fails on Lollipop devices, reconnect https://crbug.com/646840 |
| 561 if (base::android::BuildInfo::GetInstance()->sdk_int() < | 533 if (base::android::BuildInfo::GetInstance()->sdk_int() < |
| 562 base::android::SDK_VERSION_MARSHMALLOW) { | 534 base::android::SDK_VERSION_MARSHMALLOW) { |
| 563 return; | 535 return; |
| 564 } | 536 } |
| 565 #endif | 537 #endif |
| 566 | 538 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 591 .WillOnce(RunClosure(quit_closure)); | 563 .WillOnce(RunClosure(quit_closure)); |
| 592 | 564 |
| 593 device->TakePhoto(std::move(scoped_callback)); | 565 device->TakePhoto(std::move(scoped_callback)); |
| 594 run_loop.Run(); | 566 run_loop.Run(); |
| 595 | 567 |
| 596 device->StopAndDeAllocate(); | 568 device->StopAndDeAllocate(); |
| 597 } | 569 } |
| 598 | 570 |
| 599 // Starts the camera and verifies that the photo capabilities can be retrieved. | 571 // Starts the camera and verifies that the photo capabilities can be retrieved. |
| 600 TEST_F(VideoCaptureDeviceTest, MAYBE_GetPhotoCapabilities) { | 572 TEST_F(VideoCaptureDeviceTest, MAYBE_GetPhotoCapabilities) { |
| 601 if (!EnumerateAndFindUsableDevices()) | 573 if (!FindUsableDevices()) |
| 602 return; | 574 return; |
| 603 | 575 |
| 604 #if defined(OS_ANDROID) | 576 #if defined(OS_ANDROID) |
| 605 // TODO(mcasas): fails on Lollipop devices, reconnect https://crbug.com/646840 | 577 // TODO(mcasas): fails on Lollipop devices, reconnect https://crbug.com/646840 |
| 606 if (base::android::BuildInfo::GetInstance()->sdk_int() < | 578 if (base::android::BuildInfo::GetInstance()->sdk_int() < |
| 607 base::android::SDK_VERSION_MARSHMALLOW) { | 579 base::android::SDK_VERSION_MARSHMALLOW) { |
| 608 return; | 580 return; |
| 609 } | 581 } |
| 610 #endif | 582 #endif |
| 611 | 583 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 638 | 610 |
| 639 device->GetPhotoCapabilities(std::move(scoped_get_callback)); | 611 device->GetPhotoCapabilities(std::move(scoped_get_callback)); |
| 640 run_loop.Run(); | 612 run_loop.Run(); |
| 641 | 613 |
| 642 ASSERT_TRUE(image_capture_client_->capabilities()); | 614 ASSERT_TRUE(image_capture_client_->capabilities()); |
| 643 | 615 |
| 644 device->StopAndDeAllocate(); | 616 device->StopAndDeAllocate(); |
| 645 } | 617 } |
| 646 | 618 |
| 647 }; // namespace media | 619 }; // namespace media |
| OLD | NEW |