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

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: restore patch set 24 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_hal_delegate_(std::move(camera_hal_delegate)),
57 ipc_task_runner_(std::move(ipc_task_runner)) {}
58
59 void CameraDeviceDelegate::AllocateAndStart(
60 const VideoCaptureParams& params,
61 std::unique_ptr<VideoCaptureDevice::Client> client) {
62 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
63
64 chrome_capture_params_ = params;
65 device_context_.reset(new CameraDeviceContext(std::move(client)));
66 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStopped);
67 device_context_->SetState(CameraDeviceContext::State::kStarting);
68
69 int32_t camera_id = std::stoi(device_descriptor_.device_id);
70 // We need to get the static camera metadata of the camera deivce first.
71 camera_hal_delegate_->GetCameraInfo(
72 camera_id, BindToCurrentLoop(
73 base::Bind(&CameraDeviceDelegate::OnGotCameraInfo, this)));
74 }
75
76 void CameraDeviceDelegate::StopAndDeAllocate() {
77 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
78 // StopAndDeAllocate may be called at any state except
79 // CameraDeviceContext::State::kStopping.
80 DCHECK_NE(device_context_->GetState(), CameraDeviceContext::State::kStopping);
81
82 if (device_context_->GetState() == CameraDeviceContext::State::kStopped) {
83 // In case of Mojo connection error the device may be stopped before
84 // StopAndDeAllocate is called.
85 return;
86 }
87
88 device_context_->SetState(CameraDeviceContext::State::kStopping);
89 if (!device_ops_.is_bound()) {
90 // The device delegate is in the process of opening the camera device.
91 return;
92 }
93 stream_buffer_manager_->StopCapture();
94 device_ops_->Close(base::Bind(&CameraDeviceDelegate::OnClosed, this));
95 }
96
97 void CameraDeviceDelegate::TakePhoto(
98 VideoCaptureDevice::TakePhotoCallback callback) {
99 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
100 // TODO(jcliang): Implement TakePhoto.
101 }
102
103 void CameraDeviceDelegate::GetPhotoCapabilities(
104 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
105 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
106 // TODO(jcliang): Implement GetPhotoCapabilities.
107 }
108
109 void CameraDeviceDelegate::SetPhotoOptions(
110 mojom::PhotoSettingsPtr settings,
111 VideoCaptureDevice::SetPhotoOptionsCallback callback) {
112 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
113 // TODO(jcliang): Implement SetPhotoOptions.
114 }
115
116 void CameraDeviceDelegate::SetRotation(int rotation) {
117 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
118 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
119 device_context_->SetRotation(rotation);
120 }
121
122 CameraDeviceDelegate::~CameraDeviceDelegate() {}
123
124 void CameraDeviceDelegate::OnMojoConnectionError() {
125 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
126
127 if (device_context_->GetState() == CameraDeviceContext::State::kStopping) {
128 // When in stopping state the camera HAL adapter may terminate the Mojo
129 // channel before we do, in which case the OnClosed callback would not be
130 // called.
131 OnClosed(0);
132 } else {
133 // The Mojo channel terminated unexpectedly.
134 stream_buffer_manager_->StopCapture();
135 ResetMojoInterface();
136 device_context_->SetState(CameraDeviceContext::State::kStopped);
137 device_context_->SetErrorState(FROM_HERE, "Mojo connection error");
138 }
139 }
140
141 void CameraDeviceDelegate::OnClosed(int32_t result) {
142 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
143 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStopping);
144
145 device_context_->SetState(CameraDeviceContext::State::kStopped);
146 if (result) {
147 device_context_->LogToClient(std::string("Failed to close device: ") +
148 std::string(strerror(result)));
149 }
150 ResetMojoInterface();
151 device_context_.reset();
152 }
153
154 void CameraDeviceDelegate::ResetMojoInterface() {
155 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
156
157 device_ops_.reset();
158 stream_buffer_manager_ = nullptr;
159 }
160
161 void CameraDeviceDelegate::OnGotCameraInfo(
162 int32_t result,
163 arc::mojom::CameraInfoPtr camera_info) {
164 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
165
166 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
167 DCHECK_EQ(device_context_->GetState(),
168 CameraDeviceContext::State::kStopping);
169 OnClosed(0);
170 return;
171 }
172
173 if (result) {
174 std::string error_msg = "Failed to get camera info";
175 LOG(ERROR) << error_msg;
176 device_context_->SetErrorState(FROM_HERE, error_msg);
177 return;
178 }
179 static_metadata_ = std::move(camera_info->static_camera_characteristics);
180 int32_t camera_id = std::stoi(device_descriptor_.device_id);
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 std::string error_msg = "Failed to open camera device";
203 LOG(ERROR) << error_msg;
204 device_context_->SetErrorState(FROM_HERE, error_msg);
205 return;
206 }
207 Initialize();
208 }
209
210 void CameraDeviceDelegate::Initialize() {
211 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
212 DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStarting);
213
214 arc::mojom::Camera3CallbackOpsPtr callback_ops_ptr;
215 arc::mojom::Camera3CallbackOpsRequest callback_ops_request =
216 mojo::MakeRequest(&callback_ops_ptr);
217 stream_buffer_manager_ =
218 new StreamBufferManager(std::move(callback_ops_request),
219 std::unique_ptr<StreamCaptureInterface>(
220 new StreamCaptureInterfaceImpl(this)),
chfremer 2017/06/08 21:58:38 Would it be possible to have CameraDeviceDelegate
jcliang 2017/06/09 05:16:01 IMHO making StreamBufferManager a refptr complicat
chfremer 2017/06/09 17:53:17 Just to make sure this is not a misunderstanding:
221 device_context_.get(), ipc_task_runner_);
222 device_ops_->Initialize(
223 std::move(callback_ops_ptr),
224 base::Bind(&CameraDeviceDelegate::OnInitialized, this));
225 }
226
227 void CameraDeviceDelegate::OnInitialized(int32_t result) {
228 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
229
230 if (device_context_->GetState() != CameraDeviceContext::State::kStarting) {
231 DCHECK_EQ(device_context_->GetState(),
232 CameraDeviceContext::State::kStopping);
233 return;
234 }
235 if (result) {
236 device_context_->SetErrorState(
237 FROM_HERE, std::string("Failed to initialize camera device") +
238 std::string(strerror(result)));
239 return;
240 }
241 device_context_->SetState(CameraDeviceContext::State::kInitialized);
242 ConfigureStreams();
243 }
244
245 void CameraDeviceDelegate::ConfigureStreams() {
246 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
247 DCHECK_EQ(device_context_->GetState(),
248 CameraDeviceContext::State::kInitialized);
249
250 // Set up context for preview stream.
251 arc::mojom::Camera3StreamPtr preview_stream =
252 arc::mojom::Camera3Stream::New();
253 preview_stream->id = static_cast<uint64_t>(
254 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
255 preview_stream->stream_type =
256 arc::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
257 preview_stream->width =
258 chrome_capture_params_.requested_format.frame_size.width();
259 preview_stream->height =
260 chrome_capture_params_.requested_format.frame_size.height();
261 preview_stream->format =
262 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888;
263 preview_stream->data_space = 0;
264 preview_stream->rotation =
265 arc::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;
266
267 arc::mojom::Camera3StreamConfigurationPtr stream_config =
268 arc::mojom::Camera3StreamConfiguration::New();
269 stream_config->streams.push_back(std::move(preview_stream));
270 stream_config->operation_mode = arc::mojom::Camera3StreamConfigurationMode::
271 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
272 device_ops_->ConfigureStreams(
273 std::move(stream_config),
274 base::Bind(&CameraDeviceDelegate::OnConfiguredStreams, this));
275 }
276
277 void CameraDeviceDelegate::OnConfiguredStreams(
278 int32_t result,
279 arc::mojom::Camera3StreamConfigurationPtr updated_config) {
280 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
281
282 if (device_context_->GetState() != CameraDeviceContext::State::kInitialized) {
283 DCHECK_EQ(device_context_->GetState(),
284 CameraDeviceContext::State::kStopping);
285 return;
286 }
287 if (result) {
288 device_context_->SetErrorState(
289 FROM_HERE, std::string("Failed to configure streams: ") +
290 std::string(strerror(result)));
291 return;
292 }
293 if (!updated_config || updated_config->streams.size() != 1) {
294 device_context_->SetErrorState(
295 FROM_HERE, std::string("Wrong number of streams configured: ") +
296 std::to_string(updated_config->streams.size()));
297 return;
298 }
299
300 VideoCaptureFormat capture_format = chrome_capture_params_.requested_format;
301 // TODO(jcliang): Determine the best format from metadata.
302 capture_format.pixel_format = PIXEL_FORMAT_NV12;
303
304 // The partial result count metadata is optional; defaults to 1 in case it
305 // is not set in the static metadata.
306 uint32_t partial_result_count = 1;
307 const arc::mojom::CameraMetadataEntryPtr* partial_count = GetMetadataEntry(
308 static_metadata_,
309 arc::mojom::CameraMetadataTag::ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
310 if (partial_count) {
311 partial_result_count =
312 *reinterpret_cast<int32_t*>((*partial_count)->data.data());
313 }
314 stream_buffer_manager_->SetUpStreamAndBuffers(
315 capture_format, partial_result_count,
316 std::move(updated_config->streams[0]));
317
318 device_context_->SetState(CameraDeviceContext::State::kStreamConfigured);
319 ConstructDefaultRequestSettings();
320 }
321
322 void CameraDeviceDelegate::ConstructDefaultRequestSettings() {
323 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
324 DCHECK_EQ(device_context_->GetState(),
325 CameraDeviceContext::State::kStreamConfigured);
326
327 device_ops_->ConstructDefaultRequestSettings(
328 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW,
329 base::Bind(&CameraDeviceDelegate::OnConstructedDefaultRequestSettings,
330 this));
331 }
332
333 void CameraDeviceDelegate::OnConstructedDefaultRequestSettings(
334 arc::mojom::CameraMetadataPtr settings) {
335 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
336
337 if (device_context_->GetState() !=
338 CameraDeviceContext::State::kStreamConfigured) {
339 DCHECK_EQ(device_context_->GetState(),
340 CameraDeviceContext::State::kStopping);
341 return;
342 }
343 if (!settings) {
344 device_context_->SetErrorState(FROM_HERE,
345 "Failed to get default request settings");
346 return;
347 }
348 device_context_->SetState(CameraDeviceContext::State::kCapturing);
349 stream_buffer_manager_->StartCapture(std::move(settings));
350 }
351
352 void CameraDeviceDelegate::RegisterBuffer(
353 uint64_t buffer_id,
354 arc::mojom::Camera3DeviceOps::BufferType type,
355 std::vector<mojo::ScopedHandle> fds,
356 uint32_t drm_format,
357 arc::mojom::HalPixelFormat hal_pixel_format,
358 uint32_t width,
359 uint32_t height,
360 std::vector<uint32_t> strides,
361 std::vector<uint32_t> offsets,
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 device_ops_->RegisterBuffer(
371 buffer_id, type, std::move(fds), drm_format, hal_pixel_format, width,
372 height, std::move(strides), std::move(offsets), std::move(callback));
373 }
374
375 void CameraDeviceDelegate::ProcessCaptureRequest(
376 arc::mojom::Camera3CaptureRequestPtr request,
377 base::OnceCallback<void(int32_t)> callback) {
378 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
379
380 if (device_context_->GetState() != CameraDeviceContext::State::kCapturing) {
381 DCHECK_EQ(device_context_->GetState(),
382 CameraDeviceContext::State::kStopping);
383 return;
384 }
385 device_ops_->ProcessCaptureRequest(std::move(request), std::move(callback));
386 }
387
388 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698