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

Side by Side Diff: media/capture/video/chromeos/camera_device_delegate.cc

Issue 2837273004: media: add video capture device for ARC++ camera HAL v3 (Closed)
Patch Set: fix style checker errors 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 "base/memory/ptr_util.h"
8 #include "media/base/bind_to_current_loop.h"
9 #include "media/capture/video/chromeos/camera_device_context.h"
10 #include "media/capture/video/chromeos/camera_hal_delegate.h"
11 #include "media/capture/video/chromeos/camera_metadata_utils.h"
12 #include "media/capture/video/chromeos/pixel_format_utils.h"
13 #include "media/capture/video/chromeos/stream_buffer_manager.h"
14 #include "mojo/edk/embedder/embedder.h"
15 #include "mojo/edk/embedder/scoped_platform_handle.h"
16
17 namespace media {
18
19 StreamCaptureInterface::Plane::Plane() {}
20
21 StreamCaptureInterface::Plane::~Plane() {}
22
23 class CameraDeviceDelegate::StreamCaptureInterfaceImpl final
24 : public StreamCaptureInterface {
25 public:
26 StreamCaptureInterfaceImpl(
27 scoped_refptr<CameraDeviceDelegate> camera_device_delegate)
28 : camera_device_delegate_(std::move(camera_device_delegate)) {}
29
30 void RegisterBuffer(uint64_t buffer_id,
31 arc::mojom::Camera3DeviceOps::BufferType type,
32 uint32_t drm_format,
33 arc::mojom::HalPixelFormat hal_pixel_format,
34 uint32_t width,
35 uint32_t height,
36 std::vector<StreamCaptureInterface::Plane> planes,
37 base::OnceCallback<void(int32_t)> callback) final {
38 camera_device_delegate_->RegisterBuffer(
39 buffer_id, type, drm_format, hal_pixel_format, width, height,
40 std::move(planes), std::move(callback));
41 }
42
43 void ProcessCaptureRequest(arc::mojom::Camera3CaptureRequestPtr request,
44 base::OnceCallback<void(int32_t)> callback) final {
45 camera_device_delegate_->ProcessCaptureRequest(std::move(request),
46 std::move(callback));
47 }
48
49 private:
50 const scoped_refptr<CameraDeviceDelegate> camera_device_delegate_;
51 };
52
53 CameraDeviceDelegate::CameraDeviceDelegate(
54 VideoCaptureDeviceDescriptor device_descriptor,
55 scoped_refptr<CameraHalDelegate> camera_hal_delegate,
56 scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
57 : device_descriptor_(device_descriptor),
58 camera_id_(std::stoi(device_descriptor.device_id)),
59 camera_hal_delegate_(std::move(camera_hal_delegate)),
60 ipc_task_runner_(std::move(ipc_task_runner)) {}
61
62 void CameraDeviceDelegate::AllocateAndStart(
63 const VideoCaptureParams& params,
64 std::unique_ptr<VideoCaptureDevice::Client> client) {
65 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
66
67 chrome_capture_params_ = params;
68 device_context_.reset(new CameraDeviceContext(std::move(client)));
69 device_context_->SetState(CameraDeviceContext::State::kStarting);
70
71 // We need to get the static camera metadata of the camera device first.
72 camera_hal_delegate_->GetCameraInfo(
73 camera_id_, BindToCurrentLoop(base::Bind(
74 &CameraDeviceDelegate::OnGotCameraInfo, this)));
75 }
76
77 void CameraDeviceDelegate::StopAndDeAllocate() {
78 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
79 // StopAndDeAllocate may be called at any state except
80 // CameraDeviceContext::State::kStopping.
81 DCHECK_NE(device_context_->GetState(), CameraDeviceContext::State::kStopping);
82
83 if (device_context_->GetState() == CameraDeviceContext::State::kStopped) {
84 // In case of Mojo connection error the device may be stopped before
85 // StopAndDeAllocate is called.
86 return;
87 }
88
89 device_context_->SetState(CameraDeviceContext::State::kStopping);
90 if (!device_ops_.is_bound()) {
91 // The device delegate is in the process of opening the camera device.
92 return;
93 }
94 stream_buffer_manager_->StopCapture();
95 device_ops_->Close(base::Bind(&CameraDeviceDelegate::OnClosed, this));
96 }
97
98 void CameraDeviceDelegate::TakePhoto(
99 VideoCaptureDevice::TakePhotoCallback callback) {
100 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
101 // TODO(jcliang): Implement TakePhoto.
102 NOTIMPLEMENTED() << "TakePhoto is not implemented";
103 }
104
105 void CameraDeviceDelegate::GetPhotoState(
106 VideoCaptureDevice::GetPhotoStateCallback callback) {
107 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
108 // TODO(jcliang): Implement GetPhotoState.
109 NOTIMPLEMENTED() << "GetPhotoState is not implemented";
110 }
111
112 void CameraDeviceDelegate::SetPhotoOptions(
113 mojom::PhotoSettingsPtr settings,
114 VideoCaptureDevice::SetPhotoOptionsCallback callback) {
115 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
116 // TODO(jcliang): Implement SetPhotoOptions.
117 NOTIMPLEMENTED() << "SetPhotoOptions is not implemented";
118 }
119
120 void CameraDeviceDelegate::SetRotation(int rotation) {
121 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
122 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
123 device_context_->SetRotation(rotation);
124 }
125
126 CameraDeviceDelegate::~CameraDeviceDelegate() {}
127
128 void CameraDeviceDelegate::OnMojoConnectionError() {
129 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
130
131 if (device_context_->GetState() == CameraDeviceContext::State::kStopping) {
132 // When in stopping state the camera HAL adapter may terminate the Mojo
133 // channel before we do, in which case the OnClosed callback will not be
134 // called.
135 OnClosed(0);
136 } else {
137 // The Mojo channel terminated unexpectedly.
138 stream_buffer_manager_->StopCapture();
139 device_context_->SetState(CameraDeviceContext::State::kStopped);
140 device_context_->SetErrorState(FROM_HERE, "Mojo connection error");
141 ResetMojoInterface();
142 // We cannnot reset |device_context_| here because
143 // |device_context_->SetErrorState| above will call StopAndDeAllocate later
144 // to handle the class destruction.
145 }
146 }
147
148 void CameraDeviceDelegate::OnClosed(int32_t result) {
149 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
150 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStopping);
151
152 device_context_->SetState(CameraDeviceContext::State::kStopped);
153 if (result) {
154 device_context_->LogToClient(std::string("Failed to close device: ") +
155 std::string(strerror(result)));
156 }
157 ResetMojoInterface();
158 device_context_.reset();
159 }
160
161 void CameraDeviceDelegate::ResetMojoInterface() {
162 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
163
164 device_ops_.reset();
165 stream_buffer_manager_.reset();
166 }
167
168 void CameraDeviceDelegate::OnGotCameraInfo(
169 int32_t result,
170 arc::mojom::CameraInfoPtr camera_info) {
171 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
172
173 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
174 DCHECK_EQ(device_context_->GetState(),
175 CameraDeviceContext::State::kStopping);
176 OnClosed(0);
177 return;
178 }
179
180 if (result) {
181 device_context_->SetErrorState(FROM_HERE, "Failed to get camera info");
182 return;
183 }
184 static_metadata_ = std::move(camera_info->static_camera_characteristics);
185 // |device_ops_| is bound after the MakeRequest call.
186 arc::mojom::Camera3DeviceOpsRequest device_ops_request =
187 mojo::MakeRequest(&device_ops_);
188 device_ops_.set_connection_error_handler(
189 base::Bind(&CameraDeviceDelegate::OnMojoConnectionError, this));
190 camera_hal_delegate_->OpenDevice(
191 camera_id_, std::move(device_ops_request),
192 BindToCurrentLoop(
193 base::Bind(&CameraDeviceDelegate::OnOpenedDevice, this)));
194 }
195
196 void CameraDeviceDelegate::OnOpenedDevice(int32_t result) {
197 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
198
199 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
200 DCHECK_EQ(device_context_->GetState(),
201 CameraDeviceContext::State::kStopping);
202 OnClosed(0);
203 return;
204 }
205
206 if (result) {
207 device_context_->SetErrorState(FROM_HERE, "Failed to open camera device");
208 return;
209 }
210 Initialize();
211 }
212
213 void CameraDeviceDelegate::Initialize() {
214 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
215 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStarting);
216
217 arc::mojom::Camera3CallbackOpsPtr callback_ops_ptr;
218 arc::mojom::Camera3CallbackOpsRequest callback_ops_request =
219 mojo::MakeRequest(&callback_ops_ptr);
220 stream_buffer_manager_ = base::MakeUnique<StreamBufferManager>(
221 std::move(callback_ops_request),
222 base::MakeUnique<StreamCaptureInterfaceImpl>(this), device_context_.get(),
223 ipc_task_runner_);
224 device_ops_->Initialize(
225 std::move(callback_ops_ptr),
226 base::Bind(&CameraDeviceDelegate::OnInitialized, this));
227 }
228
229 void CameraDeviceDelegate::OnInitialized(int32_t result) {
230 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
231
232 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
233 DCHECK_EQ(device_context_->GetState(),
234 CameraDeviceContext::State::kStopping);
235 return;
236 }
237 if (result) {
238 device_context_->SetErrorState(
239 FROM_HERE, std::string("Failed to initialize camera device") +
240 std::string(strerror(result)));
241 return;
242 }
243 device_context_->SetState(CameraDeviceContext::State::kInitialized);
244 ConfigureStreams();
245 }
246
247 void CameraDeviceDelegate::ConfigureStreams() {
248 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
249 DCHECK_EQ(device_context_->GetState(),
250 CameraDeviceContext::State::kInitialized);
251
252 // Set up context for preview stream.
253 arc::mojom::Camera3StreamPtr preview_stream =
254 arc::mojom::Camera3Stream::New();
255 preview_stream->id = static_cast<uint64_t>(
256 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
257 preview_stream->stream_type =
258 arc::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
259 preview_stream->width =
260 chrome_capture_params_.requested_format.frame_size.width();
261 preview_stream->height =
262 chrome_capture_params_.requested_format.frame_size.height();
263 preview_stream->format =
264 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888;
265 preview_stream->data_space = 0;
266 preview_stream->rotation =
267 arc::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;
268
269 arc::mojom::Camera3StreamConfigurationPtr stream_config =
270 arc::mojom::Camera3StreamConfiguration::New();
271 stream_config->streams.push_back(std::move(preview_stream));
272 stream_config->operation_mode = arc::mojom::Camera3StreamConfigurationMode::
273 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
274 device_ops_->ConfigureStreams(
275 std::move(stream_config),
276 base::Bind(&CameraDeviceDelegate::OnConfiguredStreams, this));
277 }
278
279 void CameraDeviceDelegate::OnConfiguredStreams(
280 int32_t result,
281 arc::mojom::Camera3StreamConfigurationPtr updated_config) {
282 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
283
284 if (device_context_->GetState() != CameraDeviceContext::State::kInitialized) {
285 DCHECK_EQ(device_context_->GetState(),
286 CameraDeviceContext::State::kStopping);
287 return;
288 }
289 if (result) {
290 device_context_->SetErrorState(
291 FROM_HERE, std::string("Failed to configure streams: ") +
292 std::string(strerror(result)));
293 return;
294 }
295 if (!updated_config || updated_config->streams.size() != 1) {
296 device_context_->SetErrorState(
297 FROM_HERE, std::string("Wrong number of streams configured: ") +
298 std::to_string(updated_config->streams.size()));
299 return;
300 }
301
302 VideoCaptureFormat capture_format = chrome_capture_params_.requested_format;
303 // TODO(jcliang): Determine the best format from metadata.
304 capture_format.pixel_format = PIXEL_FORMAT_NV12;
305
306 // The partial result count metadata is optional; defaults to 1 in case it
307 // is not set in the static metadata.
308 uint32_t partial_result_count = 1;
309 const arc::mojom::CameraMetadataEntryPtr* partial_count = GetMetadataEntry(
310 static_metadata_,
311 arc::mojom::CameraMetadataTag::ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
312 if (partial_count) {
313 partial_result_count =
314 *reinterpret_cast<int32_t*>((*partial_count)->data.data());
315 }
316 stream_buffer_manager_->SetUpStreamAndBuffers(
317 capture_format, partial_result_count,
318 std::move(updated_config->streams[0]));
319
320 device_context_->SetState(CameraDeviceContext::State::kStreamConfigured);
321 ConstructDefaultRequestSettings();
322 }
323
324 void CameraDeviceDelegate::ConstructDefaultRequestSettings() {
325 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
326 DCHECK_EQ(device_context_->GetState(),
327 CameraDeviceContext::State::kStreamConfigured);
328
329 device_ops_->ConstructDefaultRequestSettings(
330 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW,
331 base::Bind(&CameraDeviceDelegate::OnConstructedDefaultRequestSettings,
332 this));
333 }
334
335 void CameraDeviceDelegate::OnConstructedDefaultRequestSettings(
336 arc::mojom::CameraMetadataPtr settings) {
337 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
338
339 if (device_context_->GetState() !=
340 CameraDeviceContext::State::kStreamConfigured) {
341 DCHECK_EQ(device_context_->GetState(),
342 CameraDeviceContext::State::kStopping);
343 return;
344 }
345 if (!settings) {
346 device_context_->SetErrorState(FROM_HERE,
347 "Failed to get default request settings");
348 return;
349 }
350 device_context_->SetState(CameraDeviceContext::State::kCapturing);
351 stream_buffer_manager_->StartCapture(std::move(settings));
352 }
353
354 void CameraDeviceDelegate::RegisterBuffer(
355 uint64_t buffer_id,
356 arc::mojom::Camera3DeviceOps::BufferType type,
357 uint32_t drm_format,
358 arc::mojom::HalPixelFormat hal_pixel_format,
359 uint32_t width,
360 uint32_t height,
361 std::vector<StreamCaptureInterface::Plane> planes,
362 base::OnceCallback<void(int32_t)> callback) {
363 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
364
365 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
366 DCHECK_EQ(device_context_->GetState(),
367 CameraDeviceContext::State::kStopping);
368 return;
369 }
370 size_t num_planes = planes.size();
371 std::vector<mojo::ScopedHandle> fds(num_planes);
372 std::vector<uint32_t> strides(num_planes);
373 std::vector<uint32_t> offsets(num_planes);
374 for (size_t i = 0; i < num_planes; ++i) {
375 fds[i] = std::move(planes[i].fd);
376 strides[i] = planes[i].stride;
377 offsets[i] = planes[i].offset;
378 }
379 device_ops_->RegisterBuffer(
380 buffer_id, type, std::move(fds), drm_format, hal_pixel_format, width,
381 height, std::move(strides), std::move(offsets), std::move(callback));
382 }
383
384 void CameraDeviceDelegate::ProcessCaptureRequest(
385 arc::mojom::Camera3CaptureRequestPtr request,
386 base::OnceCallback<void(int32_t)> callback) {
387 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
388
389 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
390 DCHECK_EQ(device_context_->GetState(),
391 CameraDeviceContext::State::kStopping);
392 return;
393 }
394 device_ops_->ProcessCaptureRequest(std::move(request), std::move(callback));
395 }
396
397 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698