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

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

Powered by Google App Engine
This is Rietveld 408576698