| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "base/test/task_environment.h" |
| #include "media/base/bind_to_current_loop.h" |
| #include "media/base/test_data_util.h" |
| #include "media/capture/video/file_video_capture_device.h" |
| #include "media/capture/video/mock_video_capture_device_client.h" |
| #include "media/video/fake_gpu_memory_buffer.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using ::testing::_; |
| using ::testing::InvokeWithoutArgs; |
| |
| namespace media { |
| |
| namespace { |
| |
| const base::TimeDelta kWaitTimeoutSecs = base::Seconds(3); |
| |
| class MockImageCaptureClient { |
| public: |
| MockImageCaptureClient() |
| : wait_get_photo_state_(base::WaitableEvent::ResetPolicy::AUTOMATIC), |
| wait_set_photo_state_(base::WaitableEvent::ResetPolicy::AUTOMATIC) {} |
| |
| // GMock doesn't support move-only arguments, so we use this forward method. |
| void DoOnGetPhotoState(mojom::PhotoStatePtr state) { |
| state_ = std::move(state); |
| wait_get_photo_state_.Signal(); |
| } |
| |
| const mojom::PhotoState* State() { |
| EXPECT_TRUE(wait_get_photo_state_.TimedWait(kWaitTimeoutSecs)); |
| return state_.get(); |
| } |
| |
| void DoOnSetPhotoOptions(bool success) { |
| EXPECT_TRUE(success); |
| wait_set_photo_state_.Signal(); |
| } |
| |
| void WaitSetPhotoOptions() { |
| EXPECT_TRUE(wait_set_photo_state_.TimedWait(kWaitTimeoutSecs)); |
| } |
| |
| // GMock doesn't support move-only arguments, so we use this forward method. |
| void DoOnPhotoTaken(mojom::BlobPtr blob) { |
| EXPECT_TRUE(blob); |
| OnCorrectPhotoTaken(); |
| } |
| MOCK_METHOD0(OnCorrectPhotoTaken, void(void)); |
| |
| private: |
| base::WaitableEvent wait_get_photo_state_; |
| mojom::PhotoStatePtr state_; |
| |
| base::WaitableEvent wait_set_photo_state_; |
| }; |
| |
| } // namespace |
| |
| class FileVideoCaptureDeviceTest : public ::testing::Test { |
| protected: |
| FileVideoCaptureDeviceTest() |
| : client_(new NiceMockVideoCaptureDeviceClient()) {} |
| |
| void SetUp() override { |
| EXPECT_CALL(*client_, OnError(_, _, _)).Times(0); |
| EXPECT_CALL(*client_, OnStarted()); |
| device_ = std::make_unique<FileVideoCaptureDevice>( |
| GetTestDataFilePath("bear.mjpeg"), |
| std::make_unique<FakeGpuMemoryBufferSupport>()); |
| device_->AllocateAndStart(VideoCaptureParams(), std::move(client_)); |
| } |
| |
| void TearDown() override { device_->StopAndDeAllocate(); } |
| |
| std::unique_ptr<MockVideoCaptureDeviceClient> CreateClient() { |
| return MockVideoCaptureDeviceClient::CreateMockClientWithBufferAllocator( |
| BindToCurrentLoop( |
| base::BindRepeating(&FileVideoCaptureDeviceTest::OnFrameCaptured, |
| base::Unretained(this)))); |
| } |
| |
| void OnFrameCaptured(const VideoCaptureFormat& format) { |
| last_format_ = format; |
| run_loop_->Quit(); |
| } |
| |
| void WaitForCapturedFrame() { |
| run_loop_ = std::make_unique<base::RunLoop>(); |
| run_loop_->Run(); |
| } |
| |
| void SetPhotoOptions(double pan, double tilt, double zoom) { |
| mojom::PhotoSettingsPtr photo_settings = mojom::PhotoSettings::New(); |
| photo_settings->has_pan = photo_settings->has_tilt = |
| photo_settings->has_zoom = true; |
| photo_settings->pan = pan; |
| photo_settings->tilt = tilt; |
| photo_settings->zoom = zoom; |
| |
| VideoCaptureDevice::SetPhotoOptionsCallback scoped_set_callback = |
| base::BindOnce(&MockImageCaptureClient::DoOnSetPhotoOptions, |
| base::Unretained(&image_capture_client_)); |
| device_->SetPhotoOptions(std::move(photo_settings), |
| std::move(scoped_set_callback)); |
| image_capture_client_.WaitSetPhotoOptions(); |
| } |
| |
| std::unique_ptr<NiceMockVideoCaptureDeviceClient> client_; |
| MockImageCaptureClient image_capture_client_; |
| std::unique_ptr<VideoCaptureDevice> device_; |
| VideoCaptureFormat last_format_; |
| base::test::TaskEnvironment task_environment_; |
| std::unique_ptr<base::RunLoop> run_loop_; |
| }; |
| |
| TEST_F(FileVideoCaptureDeviceTest, GetPhotoState) { |
| VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback = |
| base::BindOnce(&MockImageCaptureClient::DoOnGetPhotoState, |
| base::Unretained(&image_capture_client_)); |
| |
| device_->GetPhotoState(std::move(scoped_get_callback)); |
| |
| const mojom::PhotoState* state = image_capture_client_.State(); |
| EXPECT_TRUE(state); |
| |
| // From gcd of "bear.mjpeg" width=320, height=192. |
| const int kZoomMaxLevels = 64; |
| |
| const mojom::RangePtr& pan = state->pan; |
| EXPECT_TRUE(pan); |
| EXPECT_EQ(pan->current, 0); |
| EXPECT_EQ(pan->max, kZoomMaxLevels - 1); |
| EXPECT_EQ(pan->min, 0); |
| EXPECT_EQ(pan->step, 1); |
| |
| const mojom::RangePtr& tilt = state->tilt; |
| EXPECT_TRUE(tilt); |
| EXPECT_EQ(tilt->current, kZoomMaxLevels - 1); |
| EXPECT_EQ(tilt->max, kZoomMaxLevels - 1); |
| EXPECT_EQ(tilt->min, 0); |
| EXPECT_EQ(tilt->step, 1); |
| |
| const mojom::RangePtr& zoom = state->zoom; |
| EXPECT_TRUE(zoom); |
| EXPECT_EQ(zoom->current, 0); |
| EXPECT_EQ(zoom->max, kZoomMaxLevels - 1); |
| EXPECT_EQ(zoom->min, 0); |
| EXPECT_EQ(zoom->step, 1); |
| } |
| |
| TEST_F(FileVideoCaptureDeviceTest, SetPhotoOptions) { |
| SetPhotoOptions(1.0, 1.0, 1.0); |
| } |
| |
| TEST_F(FileVideoCaptureDeviceTest, TakePhoto) { |
| SetPhotoOptions(1.0, 1.0, 1.0); |
| |
| VideoCaptureDevice::TakePhotoCallback scoped_callback = |
| base::BindOnce(&MockImageCaptureClient::DoOnPhotoTaken, |
| base::Unretained(&image_capture_client_)); |
| |
| base::RunLoop run_loop; |
| base::RepeatingClosure quit_closure = |
| BindToCurrentLoop(run_loop.QuitClosure()); |
| EXPECT_CALL(image_capture_client_, OnCorrectPhotoTaken()) |
| .Times(1) |
| .WillOnce(InvokeWithoutArgs([quit_closure]() { quit_closure.Run(); })); |
| device_->TakePhoto(std::move(scoped_callback)); |
| run_loop.Run(); |
| } |
| |
| TEST_F(FileVideoCaptureDeviceTest, CaptureWithGpuMemoryBuffer) { |
| auto client = CreateClient(); |
| VideoCaptureParams params; |
| params.buffer_type = VideoCaptureBufferType::kGpuMemoryBuffer; |
| auto device = std::make_unique<FileVideoCaptureDevice>( |
| GetTestDataFilePath("bear.mjpeg"), |
| std::make_unique<FakeGpuMemoryBufferSupport>()); |
| device->AllocateAndStart(params, std::move(client)); |
| WaitForCapturedFrame(); |
| EXPECT_EQ(last_format_.pixel_format, PIXEL_FORMAT_NV12); |
| device->StopAndDeAllocate(); |
| } |
| |
| } // namespace media |