Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: media/capture/video/chromeos/camera_device_delegate_unittest.cc

Issue 2837273004: media: add video capture device for ARC++ camera HAL v3 (Closed)
Patch Set: address chfremer's comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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/chromeos/camera_device_delegate.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <utility>
12
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "media/capture/video/chromeos/camera_hal_delegate_unittest.h"
16 #include "media/capture/video/chromeos/mojo/arc_camera3.mojom.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 using testing::_;
21 using testing::A;
22 using testing::Invoke;
23
24 namespace media {
25
26 namespace {
27
28 void DumpError(const tracked_objects::Location& location,
29 const std::string& message) {
30 DPLOG(ERROR) << location.ToString() << " " << message;
31 }
32
33 class MockVideoCaptureClient : public VideoCaptureDevice::Client {
34 public:
35 MOCK_METHOD0(DoReserveOutputBuffer, void(void));
36 MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
37 MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
38 MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void));
39 MOCK_METHOD2(OnError,
40 void(const tracked_objects::Location& from_here,
41 const std::string& reason));
42 MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void));
43 MOCK_METHOD0(OnStarted, void(void));
44
45 explicit MockVideoCaptureClient(
46 base::Callback<void(const VideoCaptureFormat&)> frame_cb)
47 : main_thread_(base::ThreadTaskRunnerHandle::Get()), frame_cb_(frame_cb) {
48 ON_CALL(*this, OnError(_, _)).WillByDefault(Invoke(DumpError));
49 }
50
51 void OnIncomingCapturedData(const uint8_t* data,
52 int length,
53 const VideoCaptureFormat& format,
54 int rotation,
55 base::TimeTicks reference_time,
56 base::TimeDelta timestamp,
57 int frame_feedback_id) override {
58 ASSERT_GT(length, 0);
59 ASSERT_TRUE(data);
60 main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format));
61 }
62
63 // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
64 Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
65 media::VideoPixelFormat format,
66 media::VideoPixelStorage storage,
67 int frame_feedback_id) override {
68 DoReserveOutputBuffer();
69 NOTREACHED() << "This should never be called";
70 return Buffer();
71 }
72 void OnIncomingCapturedBuffer(Buffer buffer,
73 const VideoCaptureFormat& format,
74 base::TimeTicks reference_time,
75 base::TimeDelta timestamp) override {
76 DoOnIncomingCapturedBuffer();
77 }
78 void OnIncomingCapturedBufferExt(
79 Buffer buffer,
80 const VideoCaptureFormat& format,
81 base::TimeTicks reference_time,
82 base::TimeDelta timestamp,
83 gfx::Rect visible_rect,
84 const VideoFrameMetadata& additional_metadata) override {
85 DoOnIncomingCapturedVideoFrame();
86 }
87 Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
88 media::VideoPixelFormat format,
89 media::VideoPixelStorage storage,
90 int frame_feedback_id) {
91 DoResurrectLastOutputBuffer();
92 NOTREACHED() << "This should never be called";
93 return Buffer();
94 }
95
96 private:
97 scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
98 base::Callback<void(const VideoCaptureFormat&)> frame_cb_;
99 };
100
101 class MockCameraDevice : public arc::mojom::Camera3DeviceOps {
102 public:
103 MockCameraDevice() : mock_device_thread_("MockDeviceThread"), binding_(this) {
104 mock_device_thread_.Start();
105 }
106
107 ~MockCameraDevice() {
108 mock_device_thread_.task_runner()->PostTask(
109 FROM_HERE, base::Bind(&MockCameraDevice::CloseBindingOnThread,
110 base::Unretained(this)));
111 mock_device_thread_.Stop();
112 }
113
114 void Initialize(arc::mojom::Camera3CallbackOpsPtr callback_ops,
115 InitializeCallback callback) override {
116 DoInitialize(callback_ops, callback);
117 callback_ops_ = std::move(callback_ops);
118 std::move(callback).Run(0);
119 }
120 MOCK_METHOD2(DoInitialize,
121 void(arc::mojom::Camera3CallbackOpsPtr& callback_ops,
122 InitializeCallback& callback));
123
124 void ConfigureStreams(arc::mojom::Camera3StreamConfigurationPtr config,
125 ConfigureStreamsCallback callback) override {
126 DoConfigureStreams(config, callback);
127 }
128 MOCK_METHOD2(DoConfigureStreams,
129 void(arc::mojom::Camera3StreamConfigurationPtr& config,
130 ConfigureStreamsCallback& callback));
131
132 void ConstructDefaultRequestSettings(
133 arc::mojom::Camera3RequestTemplate type,
134 ConstructDefaultRequestSettingsCallback callback) override {
135 DoConstructDefaultRequestSettings(type, callback);
136 }
137 MOCK_METHOD2(DoConstructDefaultRequestSettings,
138 void(arc::mojom::Camera3RequestTemplate type,
139 ConstructDefaultRequestSettingsCallback& callback));
140
141 void ProcessCaptureRequest(arc::mojom::Camera3CaptureRequestPtr request,
142 ProcessCaptureRequestCallback callback) override {
143 DoProcessCaptureRequest(request, callback);
144 }
145 MOCK_METHOD2(DoProcessCaptureRequest,
146 void(arc::mojom::Camera3CaptureRequestPtr& request,
147 ProcessCaptureRequestCallback& callback));
148
149 void Dump(mojo::ScopedHandle fd) override { DoDump(fd); }
150 MOCK_METHOD1(DoDump, void(mojo::ScopedHandle& fd));
151
152 void Flush(FlushCallback callback) override { DoFlush(callback); }
153 MOCK_METHOD1(DoFlush, void(FlushCallback& callback));
154
155 void RegisterBuffer(uint64_t buffer_id,
156 arc::mojom::Camera3DeviceOps::BufferType type,
157 std::vector<mojo::ScopedHandle> fds,
158 uint32_t drm_format,
159 arc::mojom::HalPixelFormat hal_pixel_format,
160 uint32_t width,
161 uint32_t height,
162 const std::vector<uint32_t>& strides,
163 const std::vector<uint32_t>& offsets,
164 RegisterBufferCallback callback) override {
165 DoRegisterBuffer(buffer_id, type, fds, drm_format, hal_pixel_format, width,
166 height, strides, offsets, callback);
167 }
168 MOCK_METHOD10(DoRegisterBuffer,
169 void(uint64_t buffer_id,
170 arc::mojom::Camera3DeviceOps::BufferType type,
171 std::vector<mojo::ScopedHandle>& fds,
172 uint32_t drm_format,
173 arc::mojom::HalPixelFormat hal_pixel_format,
174 uint32_t width,
175 uint32_t height,
176 const std::vector<uint32_t>& strides,
177 const std::vector<uint32_t>& offsets,
178 RegisterBufferCallback& callback));
179
180 void Close(CloseCallback callback) override { DoClose(callback); }
181 MOCK_METHOD1(DoClose, void(CloseCallback& callback));
182
183 arc::mojom::Camera3DeviceOpsPtrInfo GetInterfacePtrInfo() {
chfremer 2017/06/01 00:16:27 This is the pattern as in MockCameraModule, which
jcliang 2017/06/01 17:11:17 This I can fix in this CL since the follow-up CL d
184 base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
185 base::WaitableEvent::InitialState::NOT_SIGNALED);
186 arc::mojom::Camera3DeviceOpsPtrInfo ptr_info;
187 mock_device_thread_.task_runner()->PostTask(
188 FROM_HERE,
189 base::Bind(&MockCameraDevice::BindOnThread, base::Unretained(this),
190 base::Unretained(&done), base::Unretained(&ptr_info)));
191 done.Wait();
192 return ptr_info;
193 }
194
195 private:
196 void CloseBindingOnThread() {
197 if (binding_.is_bound()) {
198 binding_.Close();
199 }
200 }
201
202 void BindOnThread(base::WaitableEvent* done,
203 arc::mojom::Camera3DeviceOpsPtrInfo* ptr_info) {
204 *ptr_info = binding_.CreateInterfacePtrAndBind().PassInterface();
205 done->Signal();
206 }
207
208 base::Thread mock_device_thread_;
209 mojo::Binding<arc::mojom::Camera3DeviceOps> binding_;
210 arc::mojom::Camera3CallbackOpsPtr callback_ops_;
211
212 DISALLOW_COPY_AND_ASSIGN(MockCameraDevice);
213 };
214
215 } // namespace
216
217 class CameraDeviceDelegateTest : public ::testing::Test {
218 public:
219 CameraDeviceDelegateTest()
220 : device_delegate_thread_("DeviceDelegateThread"),
221 message_loop_(new base::MessageLoop),
chfremer 2017/06/01 00:16:27 Please use ScopedTaskEnvironment instead
jcliang 2017/06/01 17:11:17 Done.
222 hal_delegate_thread_("HalDelegateThread") {}
223
224 void SetUp() override {
225 hal_delegate_thread_.Start();
226 camera_hal_delegate_ =
227 new CameraHalDelegate(hal_delegate_thread_.task_runner());
228 camera_hal_delegate_->StartForTesting(
229 mock_camera_module_.GetInterfacePtrInfo());
230 }
231
232 void TearDown() override {
233 while (!camera_hal_delegate_->HasOneRef()) {
234 base::PlatformThread::YieldCurrentThread();
235 }
236 camera_hal_delegate_ = nullptr;
237 hal_delegate_thread_.Stop();
238 }
239
240 void AllocateDeviceWithDescriptor(VideoCaptureDeviceDescriptor descriptor) {
241 ASSERT_FALSE(device_delegate_thread_.IsRunning());
242 ASSERT_FALSE(camera_device_delegate_);
243 device_delegate_thread_.Start();
244 camera_device_delegate_ =
245 new CameraDeviceDelegate(descriptor, camera_hal_delegate_,
246 device_delegate_thread_.task_runner());
247 }
248
249 void ResetDevice() {
250 ASSERT_TRUE(device_delegate_thread_.IsRunning());
251 ASSERT_TRUE(camera_device_delegate_);
252 while (!camera_device_delegate_->HasOneRef()) {
253 base::PlatformThread::YieldCurrentThread();
254 }
255 camera_device_delegate_ = nullptr;
256 device_delegate_thread_.Stop();
257 }
258
259 void Wait() {
chfremer 2017/06/01 00:16:27 needed?
jcliang 2017/06/01 17:11:17 This is needed after I extend the test.
260 run_loop_.reset(new base::RunLoop());
261 run_loop_->Run();
262 }
263
264 protected:
265 scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
266 scoped_refptr<CameraDeviceDelegate> camera_device_delegate_;
267 testing::StrictMock<unittest_internal::MockCameraModule> mock_camera_module_;
268 testing::StrictMock<MockCameraDevice> mock_camera_device_;
269 base::Thread device_delegate_thread_;
270
271 private:
272 std::unique_ptr<base::MessageLoop> message_loop_;
273 base::Thread hal_delegate_thread_;
274 std::unique_ptr<base::RunLoop> run_loop_;
275 DISALLOW_COPY_AND_ASSIGN(CameraDeviceDelegateTest);
276 };
277
278 TEST_F(CameraDeviceDelegateTest, AllocateAndStop) {
chfremer 2017/06/01 00:16:27 Please add more test cases to get coverage for the
jcliang 2017/06/01 17:11:17 I've extended the test case to allocate a capture
279 VideoCaptureDeviceDescriptor descriptor("Fake device", "0");
280 AllocateDeviceWithDescriptor(descriptor);
281
282 auto get_camera_info_cb =
283 [](uint32_t camera_id,
284 arc::mojom::CameraModule::GetCameraInfoCallback& cb) {
285 arc::mojom::CameraInfoPtr camera_info = arc::mojom::CameraInfo::New();
286 arc::mojom::CameraMetadataPtr static_metadata =
287 arc::mojom::CameraMetadata::New();
288 switch (camera_id) {
289 case 0:
290 camera_info->facing = arc::mojom::CameraFacing::CAMERA_FACING_BACK;
291 camera_info->orientation = 0;
292 camera_info->static_camera_characteristics =
293 std::move(static_metadata);
294 break;
295 default:
296 FAIL() << "Invalid camera id";
297 }
298 std::move(cb).Run(0, std::move(camera_info));
299 };
300
301 VideoCaptureParams params;
302 params.requested_format =
303 VideoCaptureFormat(gfx::Size(1280, 720), 30.0, PIXEL_FORMAT_I420);
304
305 base::Callback<void(const VideoCaptureFormat&)> frame_cb =
306 base::BindRepeating([](const VideoCaptureFormat& format) {});
307
308 std::unique_ptr<VideoCaptureDevice::Client> mock_client(
309 new MockVideoCaptureClient(frame_cb));
310
311 EXPECT_CALL(mock_camera_module_, DoGetCameraInfo(0, _))
312 .Times(1)
313 .WillOnce(Invoke(get_camera_info_cb));
314
315 device_delegate_thread_.task_runner()->PostTask(
316 FROM_HERE,
317 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
318 camera_device_delegate_, params, base::Passed(&mock_client)));
319
320 device_delegate_thread_.task_runner()->PostTask(
321 FROM_HERE, base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
322 camera_device_delegate_));
323
324 ResetDevice();
325 }
326
327 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698