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

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_metadata_utils.h"
9 #include "media/capture/video/chromeos/pixel_format_utils.h"
10 #include "mojo/edk/embedder/embedder.h"
11 #include "mojo/edk/embedder/scoped_platform_handle.h"
12 #include "third_party/libsync/include/sync/sync.h"
13
14 namespace media {
15
16 CameraDeviceDelegate::CameraDeviceDelegate(
17 VideoCaptureDeviceDescriptor device_descriptor,
18 scoped_refptr<CameraHalDelegate> camera_hal_delegate,
19 scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
20 : device_descriptor_(device_descriptor),
21 camera_hal_delegate_(std::move(camera_hal_delegate)),
22 ipc_task_runner_(std::move(ipc_task_runner)) {}
23
24 void CameraDeviceDelegate::AllocateAndStart(
25 const VideoCaptureParams& params,
26 std::unique_ptr<VideoCaptureDevice::Client> client) {
27 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
28
29 chrome_capture_params_ = params;
30 device_context_.reset(new CameraDeviceContext(std::move(client)));
31 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStopped);
chfremer 2017/06/08 21:58:38 This check looks like something that could be chec
jcliang 2017/06/09 05:16:01 Done.Let me remove this DCHECK. It's kind of unnec
32 device_context_->SetState(CameraDeviceContext::State::kStarting);
33
34 int32_t camera_id = std::stoi(device_descriptor_.device_id);
chfremer 2017/06/08 21:58:38 Can this fail? It is probably illegal to call Came
jcliang 2017/06/09 05:16:01 Done.
35 // We need to get the static camera metadata of the camera deivce first.
36 camera_hal_delegate_->GetCameraInfo(
37 camera_id, BindToCurrentLoop(
38 base::Bind(&CameraDeviceDelegate::OnGotCameraInfo, this)));
39 }
40
41 void CameraDeviceDelegate::StopAndDeAllocate() {
42 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
43 // StopAndDeAllocate may be called at any state except
44 // CameraDeviceContext::State::kStopping.
45 DCHECK_NE(device_context_->GetState(), CameraDeviceContext::State::kStopping);
46
47 if (device_context_->GetState() == CameraDeviceContext::State::kStopped) {
48 // In case of Mojo connection error the device may be stopped before
49 // StopAndDeAllocate is called.
50 return;
51 }
52
53 device_context_->SetState(CameraDeviceContext::State::kStopping);
54 if (!device_ops_.is_bound()) {
55 // The device delegate is in the process of opening the camera device.
56 return;
57 }
58 stream_buffer_manager_->StopCapture();
59 device_ops_->Close(base::Bind(&CameraDeviceDelegate::OnClosed, this));
60 }
61
62 void CameraDeviceDelegate::TakePhoto(
63 VideoCaptureDevice::TakePhotoCallback callback) {
64 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
65 // TODO(jcliang): Implement TakePhoto.
66 }
67
68 void CameraDeviceDelegate::GetPhotoCapabilities(
69 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
70 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
71 // TODO(jcliang): Implement GetPhotoCapabilities.
72 }
73
74 void CameraDeviceDelegate::SetPhotoOptions(
75 mojom::PhotoSettingsPtr settings,
76 VideoCaptureDevice::SetPhotoOptionsCallback callback) {
77 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
78 // TODO(jcliang): Implement SetPhotoOptions.
79 }
80
81 void CameraDeviceDelegate::SetRotation(int rotation) {
82 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
83 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
84 device_context_->SetRotation(rotation);
85 }
86
87 void CameraDeviceDelegate::RegisterBuffer(
88 uint64_t buffer_id,
89 arc::mojom::Camera3DeviceOps::BufferType type,
90 std::vector<mojo::ScopedHandle> fds,
91 uint32_t drm_format,
92 arc::mojom::HalPixelFormat hal_pixel_format,
93 uint32_t width,
94 uint32_t height,
95 std::vector<uint32_t> strides,
96 std::vector<uint32_t> offsets,
97 base::OnceCallback<void(int32_t)> callback) {
98 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
99
100 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
101 DCHECK_EQ(device_context_->GetState(),
102 CameraDeviceContext::State::kStopping);
103 return;
104 }
105 device_ops_->RegisterBuffer(
106 buffer_id, type, std::move(fds), drm_format, hal_pixel_format, width,
107 height, std::move(strides), std::move(offsets), std::move(callback));
108 }
109
110 void CameraDeviceDelegate::ProcessCaptureRequest(
111 arc::mojom::Camera3CaptureRequestPtr request,
112 base::OnceCallback<void(int32_t)> callback) {
113 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
114
115 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
116 DCHECK_EQ(device_context_->GetState(),
117 CameraDeviceContext::State::kStopping);
118 return;
119 }
120 device_ops_->ProcessCaptureRequest(std::move(request), std::move(callback));
121 }
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
129 // called.
130 OnClosed(0);
131 } else {
132 // The Mojo channel terminated unexpectedly.
133 stream_buffer_manager_->StopCapture();
134 ResetMojoInterface();
135 device_context_->SetState(CameraDeviceContext::State::kStopped);
136 device_context_->SetErrorState(FROM_HERE, "Mojo connection error");
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 std::string error_msg = "Failed to get camera info";
174 LOG(ERROR) << error_msg;
175 device_context_->SetErrorState(FROM_HERE, error_msg);
176 return;
177 }
178 static_metadata_ = std::move(camera_info->static_camera_characteristics);
179 int32_t camera_id = std::stoi(device_descriptor_.device_id);
chfremer 2017/06/08 21:58:38 Can probably be removed here if we did this in the
jcliang 2017/06/09 05:16:01 Done.
180 arc::mojom::Camera3DeviceOpsRequest device_ops_request =
181 mojo::MakeRequest(&device_ops_);
182 device_ops_.set_connection_error_handler(
183 base::Bind(&CameraDeviceDelegate::OnMojoConnectionError, this));
184 camera_hal_delegate_->OpenDevice(
185 camera_id, std::move(device_ops_request),
186 BindToCurrentLoop(
187 base::Bind(&CameraDeviceDelegate::OnOpenedDevice, this)));
188 }
189
190 void CameraDeviceDelegate::OnOpenedDevice(int32_t result) {
191 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
192
193 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
194 DCHECK_EQ(device_context_->GetState(),
195 CameraDeviceContext::State::kStopping);
196 OnClosed(0);
197 return;
198 }
199
200 if (result) {
201 std::string error_msg = "Failed to open camera device";
202 LOG(ERROR) << error_msg;
203 device_context_->SetErrorState(FROM_HERE, error_msg);
204 return;
205 }
206 Initialize();
207 }
208
209 void CameraDeviceDelegate::Initialize() {
210 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
211 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStarting);
212
213 arc::mojom::Camera3CallbackOpsPtr callback_ops_ptr;
214 arc::mojom::Camera3CallbackOpsRequest callback_ops_request =
215 mojo::MakeRequest(&callback_ops_ptr);
216 stream_buffer_manager_ =
217 new StreamBufferManager(std::move(callback_ops_request), this,
218 device_context_.get(), ipc_task_runner_);
219 device_ops_->Initialize(
220 std::move(callback_ops_ptr),
221 base::Bind(&CameraDeviceDelegate::OnInitialized, this));
222 }
223
224 void CameraDeviceDelegate::OnInitialized(int32_t result) {
225 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
226
227 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
228 DCHECK_EQ(device_context_->GetState(),
229 CameraDeviceContext::State::kStopping);
chfremer 2017/06/08 21:58:37 Do we need to call OnClosed(0) here? Since the st
jcliang 2017/06/09 05:16:01 We don't need to call OnClosed(0) because it will
230 return;
231 }
232 if (result) {
chfremer 2017/06/08 21:58:38 In the other methods, at this spot we are doing a
jcliang 2017/06/09 05:16:01 I should remove the LOG(ERROR) in other methods th
233 device_context_->SetErrorState(
234 FROM_HERE, std::string("Failed to initialize camera device") +
235 std::string(strerror(result)));
236 return;
237 }
238 device_context_->SetState(CameraDeviceContext::State::kInitialized);
239 ConfigureStreams();
240 }
241
242 void CameraDeviceDelegate::ConfigureStreams() {
243 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
244 DCHECK_EQ(device_context_->GetState(),
245 CameraDeviceContext::State::kInitialized);
246
247 // Set up context for preview stream.
248 arc::mojom::Camera3StreamPtr preview_stream =
249 arc::mojom::Camera3Stream::New();
250 preview_stream->id = static_cast<uint64_t>(
251 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
252 preview_stream->stream_type =
253 arc::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
254 preview_stream->width =
255 chrome_capture_params_.requested_format.frame_size.width();
256 preview_stream->height =
257 chrome_capture_params_.requested_format.frame_size.height();
258 preview_stream->format =
259 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888;
260 preview_stream->data_space = 0;
261 preview_stream->rotation =
262 arc::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;
263
264 arc::mojom::Camera3StreamConfigurationPtr stream_config =
265 arc::mojom::Camera3StreamConfiguration::New();
266 stream_config->streams.push_back(std::move(preview_stream));
267 stream_config->operation_mode = arc::mojom::Camera3StreamConfigurationMode::
268 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
269 device_ops_->ConfigureStreams(
270 std::move(stream_config),
271 base::Bind(&CameraDeviceDelegate::OnConfiguredStreams, this));
272 }
273
274 void CameraDeviceDelegate::OnConfiguredStreams(
275 int32_t result,
276 arc::mojom::Camera3StreamConfigurationPtr updated_config) {
277 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
278
279 if (device_context_->GetState() != CameraDeviceContext::State::kInitialized) {
280 DCHECK_EQ(device_context_->GetState(),
281 CameraDeviceContext::State::kStopping);
282 return;
283 }
284 if (result) {
285 device_context_->SetErrorState(
286 FROM_HERE, std::string("Failed to configure streams: ") +
287 std::string(strerror(result)));
288 return;
289 }
290 if (!updated_config || updated_config->streams.size() != 1) {
291 device_context_->SetErrorState(
292 FROM_HERE, std::string("Wrong number of streams configured: ") +
293 std::to_string(updated_config->streams.size()));
294 return;
295 }
296
297 VideoCaptureFormat capture_format = chrome_capture_params_.requested_format;
298 // TODO(jcliang): Determine the best format from metadata.
299 capture_format.pixel_format = PIXEL_FORMAT_NV12;
300
301 // The partial result count metadata is optional; defaults to 1 in case it
302 // is not set in the static metadata.
303 uint32_t partial_result_count = 1;
304 const arc::mojom::CameraMetadataEntryPtr* partial_count = GetMetadataEntry(
305 static_metadata_,
306 arc::mojom::CameraMetadataTag::ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
307 if (partial_count) {
308 partial_result_count =
309 *reinterpret_cast<int32_t*>((*partial_count)->data.data());
310 }
311 stream_buffer_manager_->SetUpStreamAndBuffers(
312 capture_format, partial_result_count,
313 std::move(updated_config->streams[0]));
314
315 device_context_->SetState(CameraDeviceContext::State::kStreamConfigured);
316 ConstructDefaultRequestSettings();
317 }
318
319 void CameraDeviceDelegate::ConstructDefaultRequestSettings() {
320 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
321 DCHECK_EQ(device_context_->GetState(),
322 CameraDeviceContext::State::kStreamConfigured);
323
324 device_ops_->ConstructDefaultRequestSettings(
325 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW,
326 base::Bind(&CameraDeviceDelegate::OnConstructedDefaultRequestSettings,
327 this));
328 }
329
330 void CameraDeviceDelegate::OnConstructedDefaultRequestSettings(
331 arc::mojom::CameraMetadataPtr settings) {
332 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
333
334 if (device_context_->GetState() !=
335 CameraDeviceContext::State::kStreamConfigured) {
336 DCHECK_EQ(device_context_->GetState(),
337 CameraDeviceContext::State::kStopping);
338 return;
339 }
340 if (!settings) {
341 device_context_->SetErrorState(FROM_HERE,
342 "Failed to get default request settings");
343 return;
344 }
345 device_context_->SetState(CameraDeviceContext::State::kCapturing);
346 stream_buffer_manager_->StartCapture(std::move(settings));
347 }
348
349 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698