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

Side by Side Diff: media/capture/video/chromeos/stream_buffer_manager_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/stream_buffer_manager.h"
6
7 #include "base/run_loop.h"
8 #include "base/test/scoped_task_environment.h"
9 #include "base/threading/thread.h"
10 #include "base/threading/thread_task_runner_handle.h"
11 #include "media/capture/video/chromeos/camera_device_context.h"
12 #include "media/capture/video/chromeos/camera_device_delegate.h"
13 #include "media/capture/video/chromeos/mock_video_capture_client.h"
14 #include "media/capture/video/chromeos/mojo/arc_camera3.mojom.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using testing::_;
19 using testing::A;
20 using testing::AtLeast;
21 using testing::Invoke;
22 using testing::InvokeWithoutArgs;
23
24 namespace media {
25
26 namespace {
27
28 class MockStreamCaptureInterface : public StreamCaptureInterface {
29 public:
30 void RegisterBuffer(uint64_t buffer_id,
31 arc::mojom::Camera3DeviceOps::BufferType type,
32 std::vector<mojo::ScopedHandle> fds,
33 uint32_t drm_format,
34 arc::mojom::HalPixelFormat hal_pixel_format,
35 uint32_t width,
36 uint32_t height,
37 std::vector<uint32_t> strides,
38 std::vector<uint32_t> offsets,
39 base::OnceCallback<void(int32_t)> callback) {
40 DoRegisterBuffer(buffer_id, type, fds, drm_format, hal_pixel_format, width,
41 height, strides, offsets, callback);
42 }
43 MOCK_METHOD10(DoRegisterBuffer,
44 void(uint64_t buffer_id,
45 arc::mojom::Camera3DeviceOps::BufferType type,
46 std::vector<mojo::ScopedHandle>& fds,
47 uint32_t drm_format,
48 arc::mojom::HalPixelFormat hal_pixel_format,
49 uint32_t width,
50 uint32_t height,
51 const std::vector<uint32_t>& strides,
52 const std::vector<uint32_t>& offsets,
53 base::OnceCallback<void(int32_t)>& callback));
54
55 void ProcessCaptureRequest(arc::mojom::Camera3CaptureRequestPtr request,
56 base::OnceCallback<void(int32_t)> callback) {
57 DoProcessCaptureRequest(request, callback);
58 }
59 MOCK_METHOD2(DoProcessCaptureRequest,
60 void(arc::mojom::Camera3CaptureRequestPtr& request,
61 base::OnceCallback<void(int32_t)>& callback));
62 };
63
64 const VideoCaptureFormat kDefaultCaptureFormat(gfx::Size(1280, 720),
65 30.0,
66 PIXEL_FORMAT_NV12);
67
68 } // namespace
69
70 class StreamBufferManagerTest : public ::testing::Test {
71 public:
72 void SetUp() override {
73 quit_ = false;
74 arc::mojom::Camera3CallbackOpsRequest callback_ops_request =
75 mojo::MakeRequest(&mock_callback_ops_);
76 device_context_ = base::MakeUnique<CameraDeviceContext>(
77 base::MakeUnique<unittest_internal::MockVideoCaptureClient>());
78
79 stream_buffer_manager_ = new StreamBufferManager(
80 std::move(callback_ops_request),
81 base::MakeUnique<MockStreamCaptureInterface>(), device_context_.get(),
82 base::ThreadTaskRunnerHandle::Get());
83 }
84
85 void TearDown() override {
86 while (!stream_buffer_manager_->HasOneRef()) {
87 base::PlatformThread::YieldCurrentThread();
88 }
89 stream_buffer_manager_ = nullptr;
90 }
91
92 void DoLoop() {
93 run_loop_.reset(new base::RunLoop());
94 run_loop_->Run();
95 }
96
97 void QuitCaptureLoop() {
98 quit_ = true;
99 if (run_loop_) {
100 run_loop_->Quit();
101 }
102 }
103
104 void RegisterBuffer(uint64_t buffer_id,
105 arc::mojom::Camera3DeviceOps::BufferType type,
106 std::vector<mojo::ScopedHandle>& fds,
107 uint32_t drm_format,
108 arc::mojom::HalPixelFormat hal_pixel_format,
109 uint32_t width,
110 uint32_t height,
111 const std::vector<uint32_t>& strides,
112 const std::vector<uint32_t>& offsets,
113 base::OnceCallback<void(int32_t)>& callback) {
114 if (quit_) {
115 return;
116 }
117 std::move(callback).Run(0);
118 }
119
120 void ProcessCaptureRequest(arc::mojom::Camera3CaptureRequestPtr& request,
121 base::OnceCallback<void(int32_t)>& callback) {
122 if (quit_) {
123 return;
124 }
125 std::move(callback).Run(0);
126 mock_callback_ops_->Notify(PrepareShutterNotifyMessage(
127 request->frame_number, base::TimeTicks::Now().ToInternalValue()));
128 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
129 request->frame_number, arc::mojom::CameraMetadata::New(), 1,
130 std::move(request->output_buffers)));
131 }
132
133 MockStreamCaptureInterface* GetMockCaptureInterface() {
134 EXPECT_NE(nullptr, stream_buffer_manager_.get());
135 return reinterpret_cast<MockStreamCaptureInterface*>(
136 stream_buffer_manager_->capture_interface_.get());
137 }
138
139 unittest_internal::MockVideoCaptureClient* GetMockVideoCaptureClient() {
140 EXPECT_NE(nullptr, device_context_);
141 return reinterpret_cast<unittest_internal::MockVideoCaptureClient*>(
142 device_context_->client_.get());
143 }
144
145 std::map<uint32_t, StreamBufferManager::CaptureResult>& GetPartialResults() {
146 EXPECT_NE(nullptr, stream_buffer_manager_.get());
147 return stream_buffer_manager_->partial_results_;
148 }
149
150 arc::mojom::Camera3StreamPtr PrepareCaptureStream(uint32_t max_buffers) {
151 auto stream = arc::mojom::Camera3Stream::New();
152 stream->id = 0;
153 stream->stream_type = arc::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
154 stream->width = kDefaultCaptureFormat.frame_size.width();
155 stream->height = kDefaultCaptureFormat.frame_size.height();
156 stream->format = arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888;
157 stream->usage = 0;
158 stream->max_buffers = max_buffers;
159 stream->data_space = 0;
160 stream->rotation =
161 arc::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;
162 return stream;
163 }
164
165 arc::mojom::Camera3NotifyMsgPtr PrepareErrorNotifyMessage(
166 uint32_t frame_number,
167 arc::mojom::Camera3ErrorMsgCode error_code) {
168 auto error_msg = arc::mojom::Camera3ErrorMsg::New();
169 error_msg->frame_number = frame_number;
170 // There is only the preview stream.
171 error_msg->error_stream_id = 1;
172 error_msg->error_code = error_code;
173 auto notify_msg = arc::mojom::Camera3NotifyMsg::New();
174 notify_msg->message = arc::mojom::Camera3NotifyMsgMessage::New();
175 notify_msg->type = arc::mojom::Camera3MsgType::CAMERA3_MSG_ERROR;
176 notify_msg->message->set_error(std::move(error_msg));
177 return notify_msg;
178 }
179
180 arc::mojom::Camera3NotifyMsgPtr PrepareShutterNotifyMessage(
181 uint32_t frame_number,
182 uint64_t timestamp) {
183 auto shutter_msg = arc::mojom::Camera3ShutterMsg::New();
184 shutter_msg->frame_number = frame_number;
185 shutter_msg->timestamp = timestamp;
186 auto notify_msg = arc::mojom::Camera3NotifyMsg::New();
187 notify_msg->message = arc::mojom::Camera3NotifyMsgMessage::New();
188 notify_msg->type = arc::mojom::Camera3MsgType::CAMERA3_MSG_SHUTTER;
189 notify_msg->message->set_shutter(std::move(shutter_msg));
190 return notify_msg;
191 }
192
193 arc::mojom::Camera3CaptureResultPtr PrepareCapturedResult(
194 uint32_t frame_number,
195 arc::mojom::CameraMetadataPtr result_metadata,
196 uint32_t partial_result,
197 std::vector<arc::mojom::Camera3StreamBufferPtr> output_buffers) {
198 auto result = arc::mojom::Camera3CaptureResult::New();
199 result->frame_number = frame_number;
200 result->result = std::move(result_metadata);
201 if (output_buffers.size()) {
202 result->output_buffers = std::move(output_buffers);
203 }
204 result->partial_result = partial_result;
205 return result;
206 }
207
208 protected:
209 scoped_refptr<StreamBufferManager> stream_buffer_manager_;
210 arc::mojom::Camera3CallbackOpsPtr mock_callback_ops_;
211 std::unique_ptr<CameraDeviceContext> device_context_;
212 arc::mojom::Camera3StreamPtr stream;
213
214 private:
215 std::unique_ptr<base::RunLoop> run_loop_;
216 bool quit_;
217 base::test::ScopedTaskEnvironment scoped_test_environment_;
218 };
219
220 // A basic sanity test to capture one frame with the capture loop.
221 TEST_F(StreamBufferManagerTest, SimpleCaptureTest) {
222 GetMockVideoCaptureClient()->SetFrameCb(base::BindOnce(
223 &StreamBufferManagerTest::QuitCaptureLoop, base::Unretained(this)));
224 EXPECT_CALL(*GetMockCaptureInterface(),
225 DoRegisterBuffer(0, arc::mojom::Camera3DeviceOps::BufferType::SHM,
226 _, _, _, _, _, _, _, _))
227 .Times(AtLeast(1))
228 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer));
229 EXPECT_CALL(*GetMockCaptureInterface(), DoProcessCaptureRequest(_, _))
230 .Times(1)
231 .WillOnce(Invoke(this, &StreamBufferManagerTest::ProcessCaptureRequest));
232
233 stream_buffer_manager_->SetUpStreamAndBuffers(
234 kDefaultCaptureFormat, /* partial_result_count */ 1,
235 PrepareCaptureStream(/* max_buffers */ 1));
236 stream_buffer_manager_->StartCapture(arc::mojom::CameraMetadata::New());
237
238 // Wait until a captured frame is received by MockVideoCaptureClient.
239 DoLoop();
240 }
241
242 // Test that the StreamBufferManager submits a captured result only after all
243 // partial metadata are received.
244 TEST_F(StreamBufferManagerTest, PartialResultTest) {
245 GetMockVideoCaptureClient()->SetFrameCb(base::BindOnce(
246 [](StreamBufferManagerTest* test) {
247 EXPECT_EQ(1u, test->GetPartialResults().size());
248 // Make sure all the three partial metadata are received before the
249 // captured result is submitted.
250 EXPECT_EQ(
251 3u, test->GetPartialResults()[0].partial_metadata_received.size());
252 test->QuitCaptureLoop();
253 },
254 base::Unretained(this)));
255 EXPECT_CALL(*GetMockCaptureInterface(),
256 DoRegisterBuffer(0, arc::mojom::Camera3DeviceOps::BufferType::SHM,
257 _, _, _, _, _, _, _, _))
258 .Times(AtLeast(1))
259 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer));
260 EXPECT_CALL(*GetMockCaptureInterface(), DoProcessCaptureRequest(_, _))
261 .Times(1)
262 .WillOnce(Invoke([this](arc::mojom::Camera3CaptureRequestPtr& request,
263 base::OnceCallback<void(int32_t)>& callback) {
264 std::move(callback).Run(0);
265 mock_callback_ops_->Notify(PrepareShutterNotifyMessage(
266 request->frame_number, base::TimeTicks::Now().ToInternalValue()));
267 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
268 request->frame_number, arc::mojom::CameraMetadata::New(), 1,
269 std::move(request->output_buffers)));
270
271 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
272 request->frame_number, arc::mojom::CameraMetadata::New(), 2,
273 std::vector<arc::mojom::Camera3StreamBufferPtr>()));
274
275 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
276 request->frame_number, arc::mojom::CameraMetadata::New(), 3,
277 std::vector<arc::mojom::Camera3StreamBufferPtr>()));
278 }));
279
280 stream_buffer_manager_->SetUpStreamAndBuffers(
281 kDefaultCaptureFormat, /* partial_result_count */ 3,
282 PrepareCaptureStream(/* max_buffers */ 1));
283 stream_buffer_manager_->StartCapture(arc::mojom::CameraMetadata::New());
284
285 // Wait until a captured frame is received by MockVideoCaptureClient.
286 DoLoop();
287 }
288
289 // Test that the capture loop is stopped and no frame is submitted when a device
290 // error happens.
291 TEST_F(StreamBufferManagerTest, DeviceErrorTest) {
292 GetMockVideoCaptureClient()->SetFrameCb(base::BindOnce(
293 [](StreamBufferManagerTest* test) {
294 ADD_FAILURE() << "No frame should be submitted";
295 test->QuitCaptureLoop();
296 },
297 base::Unretained(this)));
298 EXPECT_CALL(*GetMockVideoCaptureClient(), OnError(_, _))
299 .Times(1)
300 .WillOnce(
301 InvokeWithoutArgs(this, &StreamBufferManagerTest::QuitCaptureLoop));
302 EXPECT_CALL(*GetMockCaptureInterface(),
303 DoRegisterBuffer(0, arc::mojom::Camera3DeviceOps::BufferType::SHM,
304 _, _, _, _, _, _, _, _))
305 .Times(1)
306 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer));
307 EXPECT_CALL(*GetMockCaptureInterface(), DoProcessCaptureRequest(_, _))
308 .Times(1)
309 .WillOnce(Invoke([this](arc::mojom::Camera3CaptureRequestPtr& request,
310 base::OnceCallback<void(int32_t)>& callback) {
311 std::move(callback).Run(0);
312 mock_callback_ops_->Notify(PrepareErrorNotifyMessage(
313 request->frame_number,
314 arc::mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_DEVICE));
315 }));
316
317 stream_buffer_manager_->SetUpStreamAndBuffers(
318 kDefaultCaptureFormat, /* partial_result_count */ 1,
319 PrepareCaptureStream(/* max_buffers */ 1));
320 stream_buffer_manager_->StartCapture(arc::mojom::CameraMetadata::New());
321
322 // Wait until the MockVideoCaptureClient is deleted.
323 DoLoop();
324 }
325
326 // Test that upon request error the erroneous frame is dropped, and the capture
327 // loop continues.
328 TEST_F(StreamBufferManagerTest, RequestErrorTest) {
329 GetMockVideoCaptureClient()->SetFrameCb(base::BindOnce(
330 [](StreamBufferManagerTest* test) {
331 // Frame 0 should be dropped, and the frame callback should be called
332 // with frame 1.
333 EXPECT_EQ(test->GetPartialResults().end(),
334 test->GetPartialResults().find(0));
335 EXPECT_NE(test->GetPartialResults().end(),
336 test->GetPartialResults().find(1));
337 test->QuitCaptureLoop();
338 },
339 base::Unretained(this)));
340 EXPECT_CALL(*GetMockCaptureInterface(),
341 DoRegisterBuffer(0, arc::mojom::Camera3DeviceOps::BufferType::SHM,
342 _, _, _, _, _, _, _, _))
343 .Times(AtLeast(2))
344 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer))
345 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer));
346 EXPECT_CALL(*GetMockCaptureInterface(), DoProcessCaptureRequest(_, _))
347 .Times(2)
348 .WillOnce(Invoke([this](arc::mojom::Camera3CaptureRequestPtr& request,
349 base::OnceCallback<void(int32_t)>& callback) {
350 std::move(callback).Run(0);
351 mock_callback_ops_->Notify(PrepareErrorNotifyMessage(
352 request->frame_number,
353 arc::mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_REQUEST));
354 request->output_buffers[0]->status =
355 arc::mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_ERROR;
356 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
357 request->frame_number, arc::mojom::CameraMetadata::New(), 1,
358 std::move(request->output_buffers)));
359 }))
360 .WillOnce(Invoke(this, &StreamBufferManagerTest::ProcessCaptureRequest));
361
362 stream_buffer_manager_->SetUpStreamAndBuffers(
363 kDefaultCaptureFormat, /* partial_result_count */ 1,
364 PrepareCaptureStream(/* max_buffers */ 1));
365 stream_buffer_manager_->StartCapture(arc::mojom::CameraMetadata::New());
366
367 // Wait until the MockVideoCaptureClient is deleted.
368 DoLoop();
369 }
370
371 // Test that upon result error the captured buffer is submitted despite of the
372 // missing result metadata, and the capture loop continues.
373 TEST_F(StreamBufferManagerTest, ResultErrorTest) {
374 GetMockVideoCaptureClient()->SetFrameCb(base::BindOnce(
375 [](StreamBufferManagerTest* test) {
376 // Frame 0 should be submitted.
377 EXPECT_NE(test->GetPartialResults().end(),
378 test->GetPartialResults().find(0));
379 test->QuitCaptureLoop();
380 },
381 base::Unretained(this)));
382 EXPECT_CALL(*GetMockCaptureInterface(),
383 DoRegisterBuffer(0, arc::mojom::Camera3DeviceOps::BufferType::SHM,
384 _, _, _, _, _, _, _, _))
385 .Times(AtLeast(1))
386 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer));
387 EXPECT_CALL(*GetMockCaptureInterface(), DoProcessCaptureRequest(_, _))
388 .Times(1)
389 .WillOnce(Invoke([this](arc::mojom::Camera3CaptureRequestPtr& request,
390 base::OnceCallback<void(int32_t)>& callback) {
391 std::move(callback).Run(0);
392 mock_callback_ops_->Notify(PrepareShutterNotifyMessage(
393 request->frame_number, base::TimeTicks::Now().ToInternalValue()));
394 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
395 request->frame_number, arc::mojom::CameraMetadata::New(), 1,
396 std::move(request->output_buffers)));
397 // Send a result error notify without sending the second partial result.
398 // StreamBufferManager should submit the buffer when it receives the
399 // result error.
400 mock_callback_ops_->Notify(PrepareErrorNotifyMessage(
401 request->frame_number,
402 arc::mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_RESULT));
403 }))
404 .WillOnce(Invoke(this, &StreamBufferManagerTest::ProcessCaptureRequest));
405
406 stream_buffer_manager_->SetUpStreamAndBuffers(
407 kDefaultCaptureFormat, /* partial_result_count */ 2,
408 PrepareCaptureStream(/* max_buffers */ 1));
409 stream_buffer_manager_->StartCapture(arc::mojom::CameraMetadata::New());
410
411 // Wait until the MockVideoCaptureClient is deleted.
412 DoLoop();
413 }
414
415 // Test that upon buffer error the erroneous buffer is dropped, and the capture
416 // loop continues.
417 TEST_F(StreamBufferManagerTest, BufferErrorTest) {
418 GetMockVideoCaptureClient()->SetFrameCb(base::BindOnce(
419 [](StreamBufferManagerTest* test) {
420 // Frame 0 should be dropped, and the frame callback should be called
421 // with frame 1.
422 EXPECT_EQ(test->GetPartialResults().end(),
423 test->GetPartialResults().find(0));
424 EXPECT_NE(test->GetPartialResults().end(),
425 test->GetPartialResults().find(1));
426 test->QuitCaptureLoop();
427 },
428 base::Unretained(this)));
429 EXPECT_CALL(*GetMockCaptureInterface(),
430 DoRegisterBuffer(0, arc::mojom::Camera3DeviceOps::BufferType::SHM,
431 _, _, _, _, _, _, _, _))
432 .Times(AtLeast(2))
433 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer))
434 .WillOnce(Invoke(this, &StreamBufferManagerTest::RegisterBuffer));
435 EXPECT_CALL(*GetMockCaptureInterface(), DoProcessCaptureRequest(_, _))
436 .Times(2)
437 .WillOnce(Invoke([this](arc::mojom::Camera3CaptureRequestPtr& request,
438 base::OnceCallback<void(int32_t)>& callback) {
439 std::move(callback).Run(0);
440 mock_callback_ops_->Notify(PrepareShutterNotifyMessage(
441 request->frame_number, base::TimeTicks::Now().ToInternalValue()));
442 mock_callback_ops_->Notify(PrepareErrorNotifyMessage(
443 request->frame_number,
444 arc::mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_BUFFER));
445 request->output_buffers[0]->status =
446 arc::mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_ERROR;
447 mock_callback_ops_->ProcessCaptureResult(PrepareCapturedResult(
448 request->frame_number, arc::mojom::CameraMetadata::New(), 1,
449 std::move(request->output_buffers)));
450 }))
451 .WillOnce(Invoke(this, &StreamBufferManagerTest::ProcessCaptureRequest));
452
453 stream_buffer_manager_->SetUpStreamAndBuffers(
454 kDefaultCaptureFormat, /* partial_result_count */ 1,
455 PrepareCaptureStream(/* max_buffers */ 1));
456 stream_buffer_manager_->StartCapture(arc::mojom::CameraMetadata::New());
457
458 // Wait until the MockVideoCaptureClient is deleted.
459 DoLoop();
460 }
461
462 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698