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

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: fix style checker errors 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/memory/ptr_util.h"
14 #include "base/run_loop.h"
15 #include "base/test/scoped_task_environment.h"
16 #include "media/base/bind_to_current_loop.h"
17 #include "media/capture/video/chromeos/camera_device_context.h"
18 #include "media/capture/video/chromeos/camera_hal_delegate.h"
19 #include "media/capture/video/chromeos/mock_camera_module.h"
20 #include "media/capture/video/chromeos/mock_video_capture_client.h"
21 #include "media/capture/video/chromeos/mojo/arc_camera3.mojom.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using testing::_;
26 using testing::A;
27 using testing::AtLeast;
28 using testing::Invoke;
29
30 namespace media {
31
32 namespace {
33
34 class MockCameraDevice : public arc::mojom::Camera3DeviceOps {
35 public:
36 MockCameraDevice() {}
37
38 ~MockCameraDevice() {}
39
40 void Initialize(arc::mojom::Camera3CallbackOpsPtr callback_ops,
41 InitializeCallback callback) override {
42 DoInitialize(callback_ops, callback);
43 }
44 MOCK_METHOD2(DoInitialize,
45 void(arc::mojom::Camera3CallbackOpsPtr& callback_ops,
46 InitializeCallback& callback));
47
48 void ConfigureStreams(arc::mojom::Camera3StreamConfigurationPtr config,
49 ConfigureStreamsCallback callback) override {
50 DoConfigureStreams(config, callback);
51 }
52 MOCK_METHOD2(DoConfigureStreams,
53 void(arc::mojom::Camera3StreamConfigurationPtr& config,
54 ConfigureStreamsCallback& callback));
55
56 void ConstructDefaultRequestSettings(
57 arc::mojom::Camera3RequestTemplate type,
58 ConstructDefaultRequestSettingsCallback callback) override {
59 DoConstructDefaultRequestSettings(type, callback);
60 }
61 MOCK_METHOD2(DoConstructDefaultRequestSettings,
62 void(arc::mojom::Camera3RequestTemplate type,
63 ConstructDefaultRequestSettingsCallback& callback));
64
65 void ProcessCaptureRequest(arc::mojom::Camera3CaptureRequestPtr request,
66 ProcessCaptureRequestCallback callback) override {
67 DoProcessCaptureRequest(request, callback);
68 }
69 MOCK_METHOD2(DoProcessCaptureRequest,
70 void(arc::mojom::Camera3CaptureRequestPtr& request,
71 ProcessCaptureRequestCallback& callback));
72
73 void Dump(mojo::ScopedHandle fd) override { DoDump(fd); }
74 MOCK_METHOD1(DoDump, void(mojo::ScopedHandle& fd));
75
76 void Flush(FlushCallback callback) override { DoFlush(callback); }
77 MOCK_METHOD1(DoFlush, void(FlushCallback& callback));
78
79 void RegisterBuffer(uint64_t buffer_id,
80 arc::mojom::Camera3DeviceOps::BufferType type,
81 std::vector<mojo::ScopedHandle> fds,
82 uint32_t drm_format,
83 arc::mojom::HalPixelFormat hal_pixel_format,
84 uint32_t width,
85 uint32_t height,
86 const std::vector<uint32_t>& strides,
87 const std::vector<uint32_t>& offsets,
88 RegisterBufferCallback callback) override {
89 DoRegisterBuffer(buffer_id, type, fds, drm_format, hal_pixel_format, width,
90 height, strides, offsets, callback);
91 }
92 MOCK_METHOD10(DoRegisterBuffer,
93 void(uint64_t buffer_id,
94 arc::mojom::Camera3DeviceOps::BufferType type,
95 std::vector<mojo::ScopedHandle>& fds,
96 uint32_t drm_format,
97 arc::mojom::HalPixelFormat hal_pixel_format,
98 uint32_t width,
99 uint32_t height,
100 const std::vector<uint32_t>& strides,
101 const std::vector<uint32_t>& offsets,
102 RegisterBufferCallback& callback));
103
104 void Close(CloseCallback callback) override { DoClose(callback); }
105 MOCK_METHOD1(DoClose, void(CloseCallback& callback));
106
107 private:
108 DISALLOW_COPY_AND_ASSIGN(MockCameraDevice);
109 };
110
111 const VideoCaptureDeviceDescriptor kDefaultDescriptor("Fake device", "0");
112 const VideoCaptureFormat kDefaultCaptureFormat(gfx::Size(1280, 720),
113 30.0,
114 PIXEL_FORMAT_I420);
115
116 } // namespace
117
118 class CameraDeviceDelegateTest : public ::testing::Test {
119 public:
120 CameraDeviceDelegateTest()
121 : mock_camera_device_binding_(&mock_camera_device_),
122 device_delegate_thread_("DeviceDelegateThread"),
123 hal_delegate_thread_("HalDelegateThread") {}
124
125 void SetUp() override {
126 hal_delegate_thread_.Start();
127 camera_hal_delegate_ =
128 new CameraHalDelegate(hal_delegate_thread_.task_runner());
129 camera_hal_delegate_->StartForTesting(
130 mock_camera_module_.GetInterfacePtrInfo());
131
132 ResetCaptureClient();
133 }
134
135 void TearDown() override {
136 camera_hal_delegate_->Reset();
137 hal_delegate_thread_.Stop();
138 }
139
140 void AllocateDeviceWithDescriptor(VideoCaptureDeviceDescriptor descriptor) {
141 ASSERT_FALSE(device_delegate_thread_.IsRunning());
142 ASSERT_FALSE(camera_device_delegate_);
143 device_delegate_thread_.Start();
144 camera_device_delegate_ =
145 new CameraDeviceDelegate(descriptor, camera_hal_delegate_,
146 device_delegate_thread_.task_runner());
147 }
148
149 void GetFakeCameraInfo(uint32_t camera_id,
150 arc::mojom::CameraModule::GetCameraInfoCallback& cb) {
151 arc::mojom::CameraInfoPtr camera_info = arc::mojom::CameraInfo::New();
152 arc::mojom::CameraMetadataPtr static_metadata =
153 arc::mojom::CameraMetadata::New();
154 switch (camera_id) {
155 case 0:
156 camera_info->facing = arc::mojom::CameraFacing::CAMERA_FACING_FRONT;
157 camera_info->orientation = 0;
158 camera_info->static_camera_characteristics = std::move(static_metadata);
159 break;
160 default:
161 FAIL() << "Invalid camera id";
162 }
163 std::move(cb).Run(0, std::move(camera_info));
164 }
165
166 void OpenMockCameraDevice(
167 int32_t camera_id,
168 arc::mojom::Camera3DeviceOpsRequest& device_ops_request,
169 base::OnceCallback<void(int32_t)>& callback) {
170 mock_camera_device_binding_.Bind(std::move(device_ops_request));
171 std::move(callback).Run(0);
172 }
173
174 void InitializeMockCameraDevice(
175 arc::mojom::Camera3CallbackOpsPtr& callback_ops,
176 base::OnceCallback<void(int32_t)>& callback) {
177 callback_ops_ = std::move(callback_ops);
178 std::move(callback).Run(0);
179 }
180
181 void ConfigureFakeStreams(
182 arc::mojom::Camera3StreamConfigurationPtr& config,
183 base::OnceCallback<
184 void(int32_t, arc::mojom::Camera3StreamConfigurationPtr)>& callback) {
185 ASSERT_EQ(1u, config->streams.size());
186 ASSERT_EQ(static_cast<uint32_t>(kDefaultCaptureFormat.frame_size.width()),
187 config->streams[0]->width);
188 ASSERT_EQ(static_cast<uint32_t>(kDefaultCaptureFormat.frame_size.height()),
189 config->streams[0]->height);
190 ASSERT_EQ(arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888,
191 config->streams[0]->format);
192 config->streams[0]->usage = 0;
193 config->streams[0]->max_buffers = 1;
194 std::move(callback).Run(0, std::move(config));
195 }
196
197 void ConstructFakeRequestSettings(
198 arc::mojom::Camera3RequestTemplate type,
199 base::OnceCallback<void(arc::mojom::CameraMetadataPtr)>& callback) {
200 ASSERT_EQ(arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW,
201 type);
202 arc::mojom::CameraMetadataPtr fake_settings =
203 arc::mojom::CameraMetadata::New();
204 fake_settings->entry_count = 1;
205 fake_settings->entry_capacity = 1;
206 fake_settings->entries = std::vector<arc::mojom::CameraMetadataEntryPtr>();
207 std::move(callback).Run(std::move(fake_settings));
208 }
209
210 void RegisterBuffer(uint64_t buffer_id,
211 arc::mojom::Camera3DeviceOps::BufferType type,
212 std::vector<mojo::ScopedHandle>& fds,
213 uint32_t drm_format,
214 arc::mojom::HalPixelFormat hal_pixel_format,
215 uint32_t width,
216 uint32_t height,
217 const std::vector<uint32_t>& strides,
218 const std::vector<uint32_t>& offsets,
219 base::OnceCallback<void(int32_t)>& callback) {
220 std::move(callback).Run(0);
221 }
222
223 void ProcessCaptureRequest(arc::mojom::Camera3CaptureRequestPtr& request,
224 base::OnceCallback<void(int32_t)>& callback) {
225 std::move(callback).Run(0);
226
227 arc::mojom::Camera3NotifyMsgPtr msg = arc::mojom::Camera3NotifyMsg::New();
228 msg->type = arc::mojom::Camera3MsgType::CAMERA3_MSG_SHUTTER;
229 msg->message = arc::mojom::Camera3NotifyMsgMessage::New();
230 arc::mojom::Camera3ShutterMsgPtr shutter_msg =
231 arc::mojom::Camera3ShutterMsg::New();
232 shutter_msg->timestamp = base::TimeTicks::Now().ToInternalValue();
233 msg->message->set_shutter(std::move(shutter_msg));
234 callback_ops_->Notify(std::move(msg));
235
236 arc::mojom::Camera3CaptureResultPtr result =
237 arc::mojom::Camera3CaptureResult::New();
238 result->frame_number = request->frame_number;
239 result->result = arc::mojom::CameraMetadata::New();
240 result->output_buffers = std::move(request->output_buffers);
241 result->partial_result = 1;
242 callback_ops_->ProcessCaptureResult(std::move(result));
243 }
244
245 void CloseMockCameraDevice(base::OnceCallback<void(int32_t)>& callback) {
246 if (mock_camera_device_binding_.is_bound()) {
247 mock_camera_device_binding_.Close();
248 }
249 callback_ops_.reset();
250 std::move(callback).Run(0);
251 }
252
253 void SetUpExpectationUntilInitialized() {
254 EXPECT_CALL(mock_camera_module_, DoGetCameraInfo(0, _))
255 .Times(1)
256 .WillOnce(Invoke(this, &CameraDeviceDelegateTest::GetFakeCameraInfo));
257 EXPECT_CALL(mock_camera_module_, DoOpenDevice(0, _, _))
258 .Times(1)
259 .WillOnce(
260 Invoke(this, &CameraDeviceDelegateTest::OpenMockCameraDevice));
261 EXPECT_CALL(mock_camera_device_, DoInitialize(_, _))
262 .Times(1)
263 .WillOnce(Invoke(
264 this, &CameraDeviceDelegateTest::InitializeMockCameraDevice));
265 }
266
267 void SetUpExpectationUntilStreamConfigured() {
268 SetUpExpectationUntilInitialized();
269 EXPECT_CALL(mock_camera_device_, DoConfigureStreams(_, _))
270 .Times(1)
271 .WillOnce(
272 Invoke(this, &CameraDeviceDelegateTest::ConfigureFakeStreams));
273 }
274
275 void SetUpExpectationUntilCapturing(
276 unittest_internal::MockVideoCaptureClient* mock_client) {
277 SetUpExpectationUntilStreamConfigured();
278 EXPECT_CALL(mock_camera_device_, DoConstructDefaultRequestSettings(_, _))
279 .Times(1)
280 .WillOnce(Invoke(
281 this, &CameraDeviceDelegateTest::ConstructFakeRequestSettings));
282 EXPECT_CALL(*mock_client, OnStarted()).Times(1);
283 }
284
285 void SetUpExpectationForCaptureLoop() {
286 EXPECT_CALL(mock_camera_device_,
287 DoRegisterBuffer(_, _, _, _, _, _, _, _, _, _))
288 .Times(AtLeast(1))
289 .WillOnce(Invoke(this, &CameraDeviceDelegateTest::RegisterBuffer))
290 .WillRepeatedly(
291 Invoke(this, &CameraDeviceDelegateTest::RegisterBuffer));
292 EXPECT_CALL(mock_camera_device_, DoProcessCaptureRequest(_, _))
293 .Times(AtLeast(1))
294 .WillOnce(
295 Invoke(this, &CameraDeviceDelegateTest::ProcessCaptureRequest))
296 .WillRepeatedly(
297 Invoke(this, &CameraDeviceDelegateTest::ProcessCaptureRequest));
298 }
299
300 void SetUpExpectationForClose() {
301 EXPECT_CALL(mock_camera_device_, DoClose(_))
302 .Times(1)
303 .WillOnce(
304 Invoke(this, &CameraDeviceDelegateTest::CloseMockCameraDevice));
305 }
306
307 void ResetCaptureClient() {
308 mock_client_ =
309 base::MakeUnique<unittest_internal::MockVideoCaptureClient>();
310 }
311
312 void ResetDevice() {
313 ASSERT_TRUE(device_delegate_thread_.IsRunning());
314 ASSERT_TRUE(camera_device_delegate_);
315 while (!camera_device_delegate_->HasOneRef()) {
316 base::PlatformThread::YieldCurrentThread();
317 }
318 camera_device_delegate_ = nullptr;
319 device_delegate_thread_.Stop();
320 }
321
322 void DoLoop() {
323 run_loop_.reset(new base::RunLoop());
324 run_loop_->Run();
325 }
326
327 void QuitRunLoop() {
328 VLOG(2) << "quit!";
329 if (run_loop_) {
330 run_loop_->Quit();
331 }
332 }
333
334 CameraDeviceContext::State GetState() {
335 if (camera_device_delegate_->device_context_) {
336 return camera_device_delegate_->device_context_->GetState();
337 } else {
338 // No device context means the VCD is either not started yet or already
339 // stopped.
340 return CameraDeviceContext::State::kStopped;
341 }
342 }
343
344 protected:
345 scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
346 scoped_refptr<CameraDeviceDelegate> camera_device_delegate_;
347
348 testing::StrictMock<unittest_internal::MockCameraModule> mock_camera_module_;
349
350 testing::StrictMock<MockCameraDevice> mock_camera_device_;
351 mojo::Binding<arc::mojom::Camera3DeviceOps> mock_camera_device_binding_;
352 arc::mojom::Camera3CallbackOpsPtr callback_ops_;
353
354 base::Thread device_delegate_thread_;
355
356 std::unique_ptr<VideoCaptureDevice::Client> mock_client_;
357
358 private:
359 base::test::ScopedTaskEnvironment scoped_task_environment_;
360 base::Thread hal_delegate_thread_;
361 std::unique_ptr<base::RunLoop> run_loop_;
362 DISALLOW_COPY_AND_ASSIGN(CameraDeviceDelegateTest);
363 };
364
365 // Test the complete capture flow: initialize, configure stream, capture one
366 // frame, and close the device.
367 TEST_F(CameraDeviceDelegateTest, AllocateCaptureAndStop) {
368 AllocateDeviceWithDescriptor(kDefaultDescriptor);
369
370 VideoCaptureParams params;
371 params.requested_format = kDefaultCaptureFormat;
372
373 auto* mock_client =
374 reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
375 mock_client_.get());
376 mock_client->SetFrameCb(BindToCurrentLoop(base::BindOnce(
377 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
378 mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
379 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
380 SetUpExpectationUntilCapturing(mock_client);
381 SetUpExpectationForCaptureLoop();
382
383 device_delegate_thread_.task_runner()->PostTask(
384 FROM_HERE,
385 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
386 camera_device_delegate_, params, base::Passed(&mock_client_)));
387
388 // Wait until a frame is received. MockVideoCaptureClient calls QuitRunLoop()
389 // to stop the run loop.
390 DoLoop();
391 EXPECT_EQ(CameraDeviceContext::State::kCapturing, GetState());
392
393 SetUpExpectationForClose();
394
395 device_delegate_thread_.task_runner()->PostTask(
396 FROM_HERE, base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
397 camera_device_delegate_));
398
399 // Wait until the MockVideoCaptureClient is deleted.
400 DoLoop();
401 EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState());
402
403 ResetDevice();
404 }
405
406 // Test that the camera device delegate closes properly when StopAndDeAllocate
407 // is called right after the device is initialized.
408 TEST_F(CameraDeviceDelegateTest, StopAfterInitialized) {
409 AllocateDeviceWithDescriptor(kDefaultDescriptor);
410
411 VideoCaptureParams params;
412 params.requested_format = kDefaultCaptureFormat;
413
414 auto* mock_client =
415 reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
416 mock_client_.get());
417 mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
418 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
419 SetUpExpectationUntilInitialized();
420
421 device_delegate_thread_.task_runner()->PostTask(
422 FROM_HERE,
423 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
424 camera_device_delegate_, params, base::Passed(&mock_client_)));
425
426 EXPECT_CALL(mock_camera_device_, DoConfigureStreams(_, _))
427 .Times(1)
428 .WillOnce(Invoke(
429 [this](arc::mojom::Camera3StreamConfigurationPtr& config,
430 base::OnceCallback<void(
431 int32_t, arc::mojom::Camera3StreamConfigurationPtr)>&
432 callback) {
433 EXPECT_EQ(CameraDeviceContext::State::kInitialized,
434 this->GetState());
435 this->QuitRunLoop();
436 std::move(callback).Run(
437 0, arc::mojom::Camera3StreamConfiguration::New());
438 }));
439
440 // Wait until the QuitRunLoop call in |mock_camera_device_->ConfigureStreams|.
441 DoLoop();
442
443 SetUpExpectationForClose();
444
445 device_delegate_thread_.task_runner()->PostTask(
446 FROM_HERE, base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
447 camera_device_delegate_));
448
449 // Wait until the MockVideoCaptureClient is deleted.
450 DoLoop();
451 EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState());
452
453 ResetDevice();
454 }
455
456 // Test that the camera device delegate closes properly when StopAndDeAllocate
457 // is called right after the stream is configured.
458 TEST_F(CameraDeviceDelegateTest, StopAfterStreamConfigured) {
459 AllocateDeviceWithDescriptor(kDefaultDescriptor);
460
461 VideoCaptureParams params;
462 params.requested_format = kDefaultCaptureFormat;
463
464 auto* mock_client =
465 reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
466 mock_client_.get());
467 mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
468 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
469 SetUpExpectationUntilStreamConfigured();
470
471 device_delegate_thread_.task_runner()->PostTask(
472 FROM_HERE,
473 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
474 camera_device_delegate_, params, base::Passed(&mock_client_)));
475
476 EXPECT_CALL(mock_camera_device_, DoConstructDefaultRequestSettings(_, _))
477 .Times(1)
478 .WillOnce(
479 Invoke([this](arc::mojom::Camera3RequestTemplate type,
480 base::OnceCallback<void(arc::mojom::CameraMetadataPtr)>&
481 callback) {
482 EXPECT_EQ(CameraDeviceContext::State::kStreamConfigured,
483 this->GetState());
484 this->QuitRunLoop();
485 std::move(callback).Run(arc::mojom::CameraMetadataPtr());
486 }));
487
488 // Wait until the QuitRunLoop call in |mock_camera_device_->ConfigureStreams|.
489 DoLoop();
490
491 SetUpExpectationForClose();
492
493 device_delegate_thread_.task_runner()->PostTask(
494 FROM_HERE, base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
495 camera_device_delegate_));
496
497 // Wait until the MockVideoCaptureClient is deleted.
498 DoLoop();
499 EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState());
500
501 ResetDevice();
502 }
503
504 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698