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

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: 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/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"
Pawel Osciak 2017/06/13 08:40:15 How/where is this used?
jcliang 2017/06/14 04:46:05 This is moved to stream_buffer_manager.h. I should
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)) {}
Pawel Osciak 2017/06/13 08:40:15 Is std::move needed, here and in other similar loc
jcliang 2017/06/14 04:46:05 I think without std::move it invokes the copy cons
Pawel Osciak 2017/06/14 09:07:42 Acknowledged.
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.
Pawel Osciak 2017/06/13 08:40:16 s/deivce/device/
jcliang 2017/06/14 04:46:05 Done.
70 camera_hal_delegate_->GetCameraInfo(
71 camera_id_, BindToCurrentLoop(base::Bind(
72 &CameraDeviceDelegate::OnGotCameraInfo, this)));
Pawel Osciak 2017/06/13 08:40:15 I'm wondering, do we in general need to explicitly
jcliang 2017/06/14 04:46:05 We can't use weak ptr of CameraDeviceDelegate in c
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.
Pawel Osciak 2017/06/13 08:40:15 Perhaps NOTIMPLEMENTED() << "...", here and in oth
jcliang 2017/06/14 04:46:05 Done.
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 will not be
129 // called.
130 OnClosed(0);
131 } else {
132 // The Mojo channel terminated unexpectedly.
133 stream_buffer_manager_->StopCapture();
134 device_context_->SetState(CameraDeviceContext::State::kStopped);
135 device_context_->SetErrorState(FROM_HERE, "Mojo connection error");
136 ResetMojoInterface();
137 // We cannnot reset |device_context_| here because
138 // |device_context_->SetErrorState| above will call StopAndDeAllocate later
139 // to handle the class destruction.
140 }
141 }
142
143 void CameraDeviceDelegate::OnClosed(int32_t result) {
144 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
145 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStopping);
146
147 device_context_->SetState(CameraDeviceContext::State::kStopped);
148 if (result) {
149 device_context_->LogToClient(std::string("Failed to close device: ") +
150 std::string(strerror(result)));
151 }
152 ResetMojoInterface();
153 device_context_.reset();
154 }
155
156 void CameraDeviceDelegate::ResetMojoInterface() {
157 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
158
159 device_ops_.reset();
160 stream_buffer_manager_ = nullptr;
161 }
162
163 void CameraDeviceDelegate::OnGotCameraInfo(
164 int32_t result,
165 arc::mojom::CameraInfoPtr camera_info) {
166 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
167
168 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
169 DCHECK_EQ(device_context_->GetState(),
170 CameraDeviceContext::State::kStopping);
171 OnClosed(0);
172 return;
173 }
174
175 if (result) {
176 device_context_->SetErrorState(FROM_HERE, "Failed to get camera info");
177 return;
178 }
179 static_metadata_ = std::move(camera_info->static_camera_characteristics);
180 // |device_ops_| is bound after the MakeRequest call.
181 arc::mojom::Camera3DeviceOpsRequest device_ops_request =
182 mojo::MakeRequest(&device_ops_);
183 device_ops_.set_connection_error_handler(
184 base::Bind(&CameraDeviceDelegate::OnMojoConnectionError, this));
185 camera_hal_delegate_->OpenDevice(
186 camera_id_, std::move(device_ops_request),
187 BindToCurrentLoop(
188 base::Bind(&CameraDeviceDelegate::OnOpenedDevice, this)));
189 }
190
191 void CameraDeviceDelegate::OnOpenedDevice(int32_t result) {
192 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
193
194 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
195 DCHECK_EQ(device_context_->GetState(),
196 CameraDeviceContext::State::kStopping);
197 OnClosed(0);
198 return;
199 }
200
201 if (result) {
202 device_context_->SetErrorState(FROM_HERE, "Failed to open camera device");
203 return;
204 }
205 Initialize();
206 }
207
208 void CameraDeviceDelegate::Initialize() {
209 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
210 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStarting);
211
212 arc::mojom::Camera3CallbackOpsPtr callback_ops_ptr;
213 arc::mojom::Camera3CallbackOpsRequest callback_ops_request =
214 mojo::MakeRequest(&callback_ops_ptr);
215 stream_buffer_manager_ =
216 new StreamBufferManager(std::move(callback_ops_request),
217 std::unique_ptr<StreamCaptureInterface>(
218 new StreamCaptureInterfaceImpl(this)),
219 device_context_.get(), ipc_task_runner_);
Pawel Osciak 2017/06/13 08:40:16 stream_buffer_manager_ is a scoped_refptr, while d
jcliang 2017/06/14 04:46:05 Yes we can do this. StreamBufferManager only runs
220 device_ops_->Initialize(
221 std::move(callback_ops_ptr),
222 base::Bind(&CameraDeviceDelegate::OnInitialized, this));
223 }
224
225 void CameraDeviceDelegate::OnInitialized(int32_t result) {
226 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
227
228 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
229 DCHECK_EQ(device_context_->GetState(),
230 CameraDeviceContext::State::kStopping);
231 return;
232 }
233 if (result) {
234 device_context_->SetErrorState(
235 FROM_HERE, std::string("Failed to initialize camera device") +
236 std::string(strerror(result)));
237 return;
238 }
239 device_context_->SetState(CameraDeviceContext::State::kInitialized);
240 ConfigureStreams();
241 }
242
243 void CameraDeviceDelegate::ConfigureStreams() {
244 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
245 DCHECK_EQ(device_context_->GetState(),
246 CameraDeviceContext::State::kInitialized);
247
248 // Set up context for preview stream.
249 arc::mojom::Camera3StreamPtr preview_stream =
250 arc::mojom::Camera3Stream::New();
251 preview_stream->id = static_cast<uint64_t>(
252 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
253 preview_stream->stream_type =
254 arc::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
255 preview_stream->width =
256 chrome_capture_params_.requested_format.frame_size.width();
257 preview_stream->height =
258 chrome_capture_params_.requested_format.frame_size.height();
259 preview_stream->format =
260 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888;
Pawel Osciak 2017/06/13 08:40:15 Would it be useful to have a (D)CHECK on chrome_ca
jcliang 2017/06/14 04:46:05 The pixel format given in |chrome_capture_params_.
Pawel Osciak 2017/06/14 09:07:42 Acknowledged.
261 preview_stream->data_space = 0;
262 preview_stream->rotation =
263 arc::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;
264
265 arc::mojom::Camera3StreamConfigurationPtr stream_config =
266 arc::mojom::Camera3StreamConfiguration::New();
267 stream_config->streams.push_back(std::move(preview_stream));
268 stream_config->operation_mode = arc::mojom::Camera3StreamConfigurationMode::
269 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
270 device_ops_->ConfigureStreams(
271 std::move(stream_config),
272 base::Bind(&CameraDeviceDelegate::OnConfiguredStreams, this));
273 }
274
275 void CameraDeviceDelegate::OnConfiguredStreams(
276 int32_t result,
277 arc::mojom::Camera3StreamConfigurationPtr updated_config) {
278 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
279
280 if (device_context_->GetState() != CameraDeviceContext::State::kInitialized) {
281 DCHECK_EQ(device_context_->GetState(),
282 CameraDeviceContext::State::kStopping);
283 return;
284 }
285 if (result) {
286 device_context_->SetErrorState(
287 FROM_HERE, std::string("Failed to configure streams: ") +
288 std::string(strerror(result)));
289 return;
290 }
291 if (!updated_config || updated_config->streams.size() != 1) {
292 device_context_->SetErrorState(
293 FROM_HERE, std::string("Wrong number of streams configured: ") +
294 std::to_string(updated_config->streams.size()));
295 return;
296 }
297
298 VideoCaptureFormat capture_format = chrome_capture_params_.requested_format;
299 // TODO(jcliang): Determine the best format from metadata.
300 capture_format.pixel_format = PIXEL_FORMAT_NV12;
301
302 // The partial result count metadata is optional; defaults to 1 in case it
303 // is not set in the static metadata.
304 uint32_t partial_result_count = 1;
305 const arc::mojom::CameraMetadataEntryPtr* partial_count = GetMetadataEntry(
306 static_metadata_,
307 arc::mojom::CameraMetadataTag::ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
308 if (partial_count) {
309 partial_result_count =
310 *reinterpret_cast<int32_t*>((*partial_count)->data.data());
311 }
312 stream_buffer_manager_->SetUpStreamAndBuffers(
313 capture_format, partial_result_count,
314 std::move(updated_config->streams[0]));
315
316 device_context_->SetState(CameraDeviceContext::State::kStreamConfigured);
317 ConstructDefaultRequestSettings();
318 }
319
320 void CameraDeviceDelegate::ConstructDefaultRequestSettings() {
321 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
322 DCHECK_EQ(device_context_->GetState(),
323 CameraDeviceContext::State::kStreamConfigured);
324
325 device_ops_->ConstructDefaultRequestSettings(
326 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW,
327 base::Bind(&CameraDeviceDelegate::OnConstructedDefaultRequestSettings,
328 this));
329 }
330
331 void CameraDeviceDelegate::OnConstructedDefaultRequestSettings(
332 arc::mojom::CameraMetadataPtr settings) {
333 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
334
335 if (device_context_->GetState() !=
336 CameraDeviceContext::State::kStreamConfigured) {
337 DCHECK_EQ(device_context_->GetState(),
338 CameraDeviceContext::State::kStopping);
339 return;
340 }
341 if (!settings) {
342 device_context_->SetErrorState(FROM_HERE,
343 "Failed to get default request settings");
344 return;
345 }
346 device_context_->SetState(CameraDeviceContext::State::kCapturing);
347 stream_buffer_manager_->StartCapture(std::move(settings));
348 }
349
350 void CameraDeviceDelegate::RegisterBuffer(
351 uint64_t buffer_id,
352 arc::mojom::Camera3DeviceOps::BufferType type,
353 std::vector<mojo::ScopedHandle> fds,
354 uint32_t drm_format,
355 arc::mojom::HalPixelFormat hal_pixel_format,
356 uint32_t width,
357 uint32_t height,
358 std::vector<uint32_t> strides,
359 std::vector<uint32_t> offsets,
360 base::OnceCallback<void(int32_t)> callback) {
361 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
362
363 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
364 DCHECK_EQ(device_context_->GetState(),
365 CameraDeviceContext::State::kStopping);
366 return;
367 }
368 device_ops_->RegisterBuffer(
369 buffer_id, type, std::move(fds), drm_format, hal_pixel_format, width,
370 height, std::move(strides), std::move(offsets), std::move(callback));
371 }
372
373 void CameraDeviceDelegate::ProcessCaptureRequest(
374 arc::mojom::Camera3CaptureRequestPtr request,
375 base::OnceCallback<void(int32_t)> callback) {
376 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
377
378 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
379 DCHECK_EQ(device_context_->GetState(),
380 CameraDeviceContext::State::kStopping);
381 return;
382 }
383 device_ops_->ProcessCaptureRequest(std::move(request), std::move(callback));
384 }
385
386 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698