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

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: RELAND: media: add video capture device for ARC++ camera HAL v3 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_ = base::MakeUnique<CameraDeviceDelegate>(
145 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 WaitForDeviceToClose() {
308 base::WaitableEvent device_closed(
309 base::WaitableEvent::ResetPolicy::MANUAL,
310 base::WaitableEvent::InitialState::NOT_SIGNALED);
311 device_delegate_thread_.task_runner()->PostTask(
312 FROM_HERE, base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
313 camera_device_delegate_->GetWeakPtr(),
314 base::Bind(
315 [](base::WaitableEvent* device_closed) {
316 device_closed->Signal();
317 },
318 base::Unretained(&device_closed))));
319 base::TimeDelta kWaitTimeoutSecs = base::TimeDelta::FromSeconds(3);
320 EXPECT_TRUE(device_closed.TimedWait(kWaitTimeoutSecs));
321 EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState());
322 }
323
324 void ResetCaptureClient() {
325 mock_client_ =
326 base::MakeUnique<unittest_internal::MockVideoCaptureClient>();
327 }
328
329 void ResetDevice() {
330 ASSERT_TRUE(device_delegate_thread_.IsRunning());
331 ASSERT_TRUE(camera_device_delegate_);
332 device_delegate_thread_.Stop();
333 camera_device_delegate_.reset();
334 }
335
336 void DoLoop() {
337 run_loop_.reset(new base::RunLoop());
338 run_loop_->Run();
339 }
340
341 void QuitRunLoop() {
342 VLOG(2) << "quit!";
343 if (run_loop_) {
344 run_loop_->Quit();
345 }
346 }
347
348 CameraDeviceContext::State GetState() {
349 if (camera_device_delegate_->device_context_) {
350 return camera_device_delegate_->device_context_->GetState();
351 } else {
352 // No device context means the VCD is either not started yet or already
353 // stopped.
354 return CameraDeviceContext::State::kStopped;
355 }
356 }
357
358 protected:
359 scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
360 std::unique_ptr<CameraDeviceDelegate> camera_device_delegate_;
361
362 testing::StrictMock<unittest_internal::MockCameraModule> mock_camera_module_;
363
364 testing::StrictMock<MockCameraDevice> mock_camera_device_;
365 mojo::Binding<arc::mojom::Camera3DeviceOps> mock_camera_device_binding_;
366 arc::mojom::Camera3CallbackOpsPtr callback_ops_;
367
368 base::Thread device_delegate_thread_;
369
370 std::unique_ptr<VideoCaptureDevice::Client> mock_client_;
371
372 private:
373 base::test::ScopedTaskEnvironment scoped_task_environment_;
374 base::Thread hal_delegate_thread_;
375 std::unique_ptr<base::RunLoop> run_loop_;
376 DISALLOW_COPY_AND_ASSIGN(CameraDeviceDelegateTest);
377 };
378
379 // Test the complete capture flow: initialize, configure stream, capture one
380 // frame, and close the device.
381 TEST_F(CameraDeviceDelegateTest, AllocateCaptureAndStop) {
382 AllocateDeviceWithDescriptor(kDefaultDescriptor);
383
384 VideoCaptureParams params;
385 params.requested_format = kDefaultCaptureFormat;
386
387 auto* mock_client =
388 reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
389 mock_client_.get());
390 mock_client->SetFrameCb(BindToCurrentLoop(base::BindOnce(
391 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
392 mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
393 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
394 SetUpExpectationUntilCapturing(mock_client);
395 SetUpExpectationForCaptureLoop();
396
397 device_delegate_thread_.task_runner()->PostTask(
398 FROM_HERE, base::Bind(&CameraDeviceDelegate::AllocateAndStart,
399 camera_device_delegate_->GetWeakPtr(), params,
400 base::Passed(&mock_client_)));
401
402 // Wait until a frame is received. MockVideoCaptureClient calls QuitRunLoop()
403 // to stop the run loop.
404 DoLoop();
405 EXPECT_EQ(CameraDeviceContext::State::kCapturing, GetState());
406
407 SetUpExpectationForClose();
408
409 WaitForDeviceToClose();
410
411 ResetDevice();
412 }
413
414 // Test that the camera device delegate closes properly when StopAndDeAllocate
415 // is called right after the device is initialized.
416 TEST_F(CameraDeviceDelegateTest, StopAfterInitialized) {
417 AllocateDeviceWithDescriptor(kDefaultDescriptor);
418
419 VideoCaptureParams params;
420 params.requested_format = kDefaultCaptureFormat;
421
422 auto* mock_client =
423 reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
424 mock_client_.get());
425 mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
426 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
427 SetUpExpectationUntilInitialized();
428
429 device_delegate_thread_.task_runner()->PostTask(
430 FROM_HERE, base::Bind(&CameraDeviceDelegate::AllocateAndStart,
431 camera_device_delegate_->GetWeakPtr(), params,
432 base::Passed(&mock_client_)));
433
434 EXPECT_CALL(mock_camera_device_, DoConfigureStreams(_, _))
435 .Times(1)
436 .WillOnce(Invoke(
437 [this](arc::mojom::Camera3StreamConfigurationPtr& config,
438 base::OnceCallback<void(
439 int32_t, arc::mojom::Camera3StreamConfigurationPtr)>&
440 callback) {
441 EXPECT_EQ(CameraDeviceContext::State::kInitialized,
442 this->GetState());
443 this->QuitRunLoop();
444 std::move(callback).Run(
445 0, arc::mojom::Camera3StreamConfiguration::New());
446 }));
447
448 // Wait until the QuitRunLoop call in |mock_camera_device_->ConfigureStreams|.
449 DoLoop();
450
451 SetUpExpectationForClose();
452
453 WaitForDeviceToClose();
454
455 ResetDevice();
456 }
457
458 // Test that the camera device delegate closes properly when StopAndDeAllocate
459 // is called right after the stream is configured.
460 TEST_F(CameraDeviceDelegateTest, StopAfterStreamConfigured) {
461 AllocateDeviceWithDescriptor(kDefaultDescriptor);
462
463 VideoCaptureParams params;
464 params.requested_format = kDefaultCaptureFormat;
465
466 auto* mock_client =
467 reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
468 mock_client_.get());
469 mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
470 &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
471 SetUpExpectationUntilStreamConfigured();
472
473 device_delegate_thread_.task_runner()->PostTask(
474 FROM_HERE, base::Bind(&CameraDeviceDelegate::AllocateAndStart,
475 camera_device_delegate_->GetWeakPtr(), params,
476 base::Passed(&mock_client_)));
477
478 EXPECT_CALL(mock_camera_device_, DoConstructDefaultRequestSettings(_, _))
479 .Times(1)
480 .WillOnce(
481 Invoke([this](arc::mojom::Camera3RequestTemplate type,
482 base::OnceCallback<void(arc::mojom::CameraMetadataPtr)>&
483 callback) {
484 EXPECT_EQ(CameraDeviceContext::State::kStreamConfigured,
485 this->GetState());
486 this->QuitRunLoop();
487 std::move(callback).Run(arc::mojom::CameraMetadataPtr());
488 }));
489
490 // Wait until the QuitRunLoop call in |mock_camera_device_->ConfigureStreams|.
491 DoLoop();
492
493 SetUpExpectationForClose();
494
495 WaitForDeviceToClose();
496
497 ResetDevice();
498 }
499
500 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/video/chromeos/camera_device_delegate.cc ('k') | media/capture/video/chromeos/camera_hal_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698