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

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

Powered by Google App Engine
This is Rietveld 408576698