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

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

Powered by Google App Engine
This is Rietveld 408576698