Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_device_client_unittest.cc
blobf6e6446a3a2999b0a2a5acc6c77d37a6733cb8ba
1 // Copyright 2015 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/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
11 #include "content/browser/renderer_host/media/video_capture_controller.h"
12 #include "content/browser/renderer_host/media/video_capture_device_client.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "media/base/limits.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using ::testing::_;
19 using ::testing::Mock;
20 using ::testing::InSequence;
21 using ::testing::SaveArg;
23 namespace content {
25 namespace {
27 class MockVideoCaptureController : public VideoCaptureController {
28 public:
29 explicit MockVideoCaptureController(int max_buffers)
30 : VideoCaptureController(max_buffers) {}
31 ~MockVideoCaptureController() override {}
33 MOCK_METHOD1(MockDoIncomingCapturedVideoFrameOnIOThread,
34 void(const gfx::Size&));
35 MOCK_METHOD0(DoErrorOnIOThread, void());
36 MOCK_METHOD1(DoLogOnIOThread, void(const std::string& message));
37 MOCK_METHOD1(DoBufferDestroyedOnIOThread, void(int buffer_id_to_drop));
39 void DoIncomingCapturedVideoFrameOnIOThread(
40 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
41 const scoped_refptr<media::VideoFrame>& frame,
42 const base::TimeTicks& timestamp) override {
43 MockDoIncomingCapturedVideoFrameOnIOThread(frame->coded_size());
47 class VideoCaptureDeviceClientTest : public ::testing::Test {
48 public:
49 VideoCaptureDeviceClientTest()
50 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
51 controller_(new MockVideoCaptureController(1)),
52 device_client_(
53 controller_->NewDeviceClient(base::ThreadTaskRunnerHandle::Get())) {
55 ~VideoCaptureDeviceClientTest() override {}
57 void TearDown() override { base::RunLoop().RunUntilIdle(); }
59 protected:
60 const content::TestBrowserThreadBundle thread_bundle_;
61 const scoped_ptr<MockVideoCaptureController> controller_;
62 const scoped_ptr<media::VideoCaptureDevice::Client> device_client_;
64 private:
65 DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceClientTest);
68 } // namespace
70 // A small test for reference and to verify VideoCaptureDeviceClient is
71 // minimally functional.
72 TEST_F(VideoCaptureDeviceClientTest, Minimal) {
73 const size_t kScratchpadSizeInBytes = 400;
74 unsigned char data[kScratchpadSizeInBytes] = {};
75 const media::VideoCaptureFormat kFrameFormat(
76 gfx::Size(10, 10), 30.0f /*frame_rate*/,
77 media::PIXEL_FORMAT_I420,
78 media::PIXEL_STORAGE_CPU);
79 DCHECK(device_client_.get());
80 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
81 .Times(1);
82 device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
83 kFrameFormat, 0 /*clockwise rotation*/,
84 base::TimeTicks());
85 base::RunLoop().RunUntilIdle();
86 Mock::VerifyAndClearExpectations(controller_.get());
89 // Tests that we don't try to pass on frames with an invalid frame format.
90 TEST_F(VideoCaptureDeviceClientTest, FailsSilentlyGivenInvalidFrameFormat) {
91 const size_t kScratchpadSizeInBytes = 400;
92 unsigned char data[kScratchpadSizeInBytes] = {};
93 // kFrameFormat is invalid in a number of ways.
94 const media::VideoCaptureFormat kFrameFormat(
95 gfx::Size(media::limits::kMaxDimension + 1, media::limits::kMaxDimension),
96 media::limits::kMaxFramesPerSecond + 1,
97 media::VideoPixelFormat::PIXEL_FORMAT_I420,
98 media::VideoPixelStorage::PIXEL_STORAGE_CPU);
99 DCHECK(device_client_.get());
100 // Expect the the call to fail silently inside the VideoCaptureDeviceClient.
101 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
102 .Times(0);
103 device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
104 kFrameFormat, 0 /*clockwise rotation*/,
105 base::TimeTicks());
106 base::RunLoop().RunUntilIdle();
107 Mock::VerifyAndClearExpectations(controller_.get());
110 // Tests that we fail silently if no available buffers to use.
111 TEST_F(VideoCaptureDeviceClientTest, DropsFrameIfNoBuffer) {
112 const size_t kScratchpadSizeInBytes = 400;
113 unsigned char data[kScratchpadSizeInBytes] = {};
114 const media::VideoCaptureFormat kFrameFormat(
115 gfx::Size(10, 10), 30.0f /*frame_rate*/,
116 media::PIXEL_FORMAT_I420,
117 media::PIXEL_STORAGE_CPU);
118 // We expect the second frame to be silently dropped, so these should
119 // only be called once despite the two frames.
120 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
121 .Times(1);
122 // Pass two frames. The second will be dropped.
123 device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
124 kFrameFormat, 0 /*clockwise rotation*/,
125 base::TimeTicks());
126 device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
127 kFrameFormat, 0 /*clockwise rotation*/,
128 base::TimeTicks());
129 base::RunLoop().RunUntilIdle();
130 Mock::VerifyAndClearExpectations(controller_.get());
133 // Tests that buffer-based capture API accepts all memory-backed pixel formats.
134 TEST_F(VideoCaptureDeviceClientTest, DataCaptureInEachVideoFormatInSequence) {
135 // The usual ReserveOutputBuffer() -> OnIncomingCapturedVideoFrame() cannot
136 // be used since it does not accept all pixel formats. The memory backed
137 // buffer OnIncomingCapturedData() is used instead, with a dummy scratchpad
138 // buffer.
139 const size_t kScratchpadSizeInBytes = 400;
140 unsigned char data[kScratchpadSizeInBytes] = {};
141 const gfx::Size capture_resolution(10, 10);
142 ASSERT_GE(kScratchpadSizeInBytes, capture_resolution.GetArea() * 4u)
143 << "Scratchpad is too small to hold the largest pixel format (ARGB).";
145 for (int format = 0; format < media::PIXEL_FORMAT_MAX;
146 ++format) {
147 // Conversion from some formats are unsupported.
148 if (format == media::PIXEL_FORMAT_UNKNOWN ||
149 format == media::PIXEL_FORMAT_YV16 ||
150 format == media::PIXEL_FORMAT_YV12A ||
151 format == media::PIXEL_FORMAT_YV24 ||
152 format == media::PIXEL_FORMAT_ARGB ||
153 format == media::PIXEL_FORMAT_XRGB ||
154 format == media::PIXEL_FORMAT_MJPEG ||
155 format == media::PIXEL_FORMAT_MT21) {
156 continue;
158 #if !defined(OS_LINUX) && !defined(OS_WIN)
159 if (format == media::PIXEL_FORMAT_RGB24){
160 continue;
162 #endif
163 media::VideoCaptureParams params;
164 params.requested_format = media::VideoCaptureFormat(
165 capture_resolution, 30.0f, media::VideoPixelFormat(format));
166 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
167 .Times(1);
168 device_client_->OnIncomingCapturedData(
169 data, params.requested_format.ImageAllocationSize(),
170 params.requested_format, 0 /* clockwise_rotation */, base::TimeTicks());
171 base::RunLoop().RunUntilIdle();
172 Mock::VerifyAndClearExpectations(controller_.get());
176 // Test that we receive the expected resolution for a given captured frame
177 // resolution and rotation. Odd resolutions are also cropped.
178 TEST_F(VideoCaptureDeviceClientTest, CheckRotationsAndCrops) {
179 const struct SizeAndRotation {
180 gfx::Size input_resolution;
181 int rotation;
182 gfx::Size output_resolution;
183 } kSizeAndRotations[] = {{{6, 4}, 0, {6, 4}},
184 {{6, 4}, 90, {4, 6}},
185 {{6, 4}, 180, {6, 4}},
186 {{6, 4}, 270, {4, 6}},
187 {{7, 4}, 0, {6, 4}},
188 {{7, 4}, 90, {4, 6}},
189 {{7, 4}, 180, {6, 4}},
190 {{7, 4}, 270, {4, 6}}};
192 // The usual ReserveOutputBuffer() -> OnIncomingCapturedVideoFrame() cannot
193 // be used since it does not resolve rotations or crops. The memory backed
194 // buffer OnIncomingCapturedData() is used instead, with a dummy scratchpad
195 // buffer.
196 const size_t kScratchpadSizeInBytes = 400;
197 unsigned char data[kScratchpadSizeInBytes] = {};
199 media::VideoCaptureParams params;
200 for (const auto& size_and_rotation : kSizeAndRotations) {
201 ASSERT_GE(kScratchpadSizeInBytes,
202 size_and_rotation.input_resolution.GetArea() * 4u)
203 << "Scratchpad is too small to hold the largest pixel format (ARGB).";
204 params.requested_format =
205 media::VideoCaptureFormat(size_and_rotation.input_resolution, 30.0f,
206 media::PIXEL_FORMAT_ARGB);
207 gfx::Size coded_size;
208 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
209 .Times(1)
210 .WillOnce(SaveArg<0>(&coded_size));
211 device_client_->OnIncomingCapturedData(
212 data, params.requested_format.ImageAllocationSize(),
213 params.requested_format, size_and_rotation.rotation, base::TimeTicks());
214 base::RunLoop().RunUntilIdle();
216 EXPECT_EQ(coded_size.width(), size_and_rotation.output_resolution.width());
217 EXPECT_EQ(coded_size.height(),
218 size_and_rotation.output_resolution.height());
220 Mock::VerifyAndClearExpectations(controller_.get());
224 } // namespace content