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

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

Powered by Google App Engine
This is Rietveld 408576698