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

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

Powered by Google App Engine
This is Rietveld 408576698