Add ICU message format support
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_device_client_unittest.cc
blobc02ede62faa12e8f50db252a8f54bc5465c59aa9
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::VideoCapturePixelFormat::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
78 media::VideoPixelStorage::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::VideoCapturePixelFormat::VIDEO_CAPTURE_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::VideoCapturePixelFormat::VIDEO_CAPTURE_PIXEL_FORMAT_I420,
117 media::VideoPixelStorage::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::VIDEO_CAPTURE_PIXEL_FORMAT_MAX;
146 ++format) {
147 // Conversion from MJPEG to I420 seems to be unsupported.
148 if (format == media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN ||
149 format == media::VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG) {
150 continue;
152 #if !defined(OS_LINUX) && !defined(OS_WIN)
153 if (format == media::VIDEO_CAPTURE_PIXEL_FORMAT_RGB24){
154 continue;
156 #endif
157 media::VideoCaptureParams params;
158 params.requested_format = media::VideoCaptureFormat(
159 capture_resolution, 30.0f, media::VideoCapturePixelFormat(format));
160 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
161 .Times(1);
162 device_client_->OnIncomingCapturedData(
163 data, params.requested_format.ImageAllocationSize(),
164 params.requested_format, 0 /* clockwise_rotation */, base::TimeTicks());
165 base::RunLoop().RunUntilIdle();
166 Mock::VerifyAndClearExpectations(controller_.get());
170 // Test that we receive the expected resolution for a given captured frame
171 // resolution and rotation. Odd resolutions are also cropped.
172 TEST_F(VideoCaptureDeviceClientTest, CheckRotationsAndCrops) {
173 const struct SizeAndRotation {
174 gfx::Size input_resolution;
175 int rotation;
176 gfx::Size output_resolution;
177 } kSizeAndRotations[] = {{{6, 4}, 0, {6, 4}},
178 {{6, 4}, 90, {4, 6}},
179 {{6, 4}, 180, {6, 4}},
180 {{6, 4}, 270, {4, 6}},
181 {{7, 4}, 0, {6, 4}},
182 {{7, 4}, 90, {4, 6}},
183 {{7, 4}, 180, {6, 4}},
184 {{7, 4}, 270, {4, 6}}};
186 // The usual ReserveOutputBuffer() -> OnIncomingCapturedVideoFrame() cannot
187 // be used since it does not resolve rotations or crops. The memory backed
188 // buffer OnIncomingCapturedData() is used instead, with a dummy scratchpad
189 // buffer.
190 const size_t kScratchpadSizeInBytes = 400;
191 unsigned char data[kScratchpadSizeInBytes] = {};
193 media::VideoCaptureParams params;
194 for (const auto& size_and_rotation : kSizeAndRotations) {
195 ASSERT_GE(kScratchpadSizeInBytes,
196 size_and_rotation.input_resolution.GetArea() * 4u)
197 << "Scratchpad is too small to hold the largest pixel format (ARGB).";
198 params.requested_format =
199 media::VideoCaptureFormat(size_and_rotation.input_resolution, 30.0f,
200 media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB);
201 gfx::Size coded_size;
202 EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
203 .Times(1)
204 .WillOnce(SaveArg<0>(&coded_size));
205 device_client_->OnIncomingCapturedData(
206 data, params.requested_format.ImageAllocationSize(),
207 params.requested_format, size_and_rotation.rotation, base::TimeTicks());
208 base::RunLoop().RunUntilIdle();
210 EXPECT_EQ(coded_size.width(), size_and_rotation.output_resolution.width());
211 EXPECT_EQ(coded_size.height(),
212 size_and_rotation.output_resolution.height());
214 Mock::VerifyAndClearExpectations(controller_.get());
218 } // namespace content