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

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: revise some code comments Created 3 years, 7 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 <libdrm/drm_fourcc.h>
8
9 #include "media/capture/video/chromeos/camera_metadata_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 namespace {
17
18 struct SupportedFormat {
19 VideoPixelFormat chromium_format;
20 arc::mojom::HalPixelFormat hal_format;
21 uint32_t drm_format;
22 } const kSupportedFormats[] = {
23 {PIXEL_FORMAT_I420,
24 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888,
25 DRM_FORMAT_YUV420},
26 // TODO(jcliang): Do not use IMPLEMENTATION_DEFINED formats at all as it is
27 // nearly impossible to get it right across all boards.
28 {PIXEL_FORMAT_RGB32,
29 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
30 DRM_FORMAT_XBGR8888},
31 };
32
33 } // namespace
34
35 CameraDeviceDelegate::CameraDeviceDelegate(
36 VideoCaptureDeviceDescriptor device_descriptor,
37 arc::mojom::CameraMetadataPtr static_metadata,
38 mojo::InterfacePtrInfo<arc::mojom::Camera3DeviceOps> device_ops_info,
39 const scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
40 : device_descriptor_(device_descriptor),
41 static_metadata_(std::move(static_metadata)),
42 state_(kStopped),
43 rotation_(0),
44 device_ops_info_(std::move(device_ops_info)),
45 callback_ops_(this),
46 ipc_task_runner_(ipc_task_runner),
47 frame_number_(0),
48 partial_result_count_(1),
49 first_frame_shutter_time_(base::TimeTicks::Now()) {}
50
51 // static
52 VideoPixelFormat CameraDeviceDelegate::PixFormatHalToChromium(
53 arc::mojom::HalPixelFormat from) {
54 auto it =
55 std::find_if(std::begin(kSupportedFormats), std::end(kSupportedFormats),
56 [from](SupportedFormat f) { return f.hal_format == from; });
57 if (it == std::end(kSupportedFormats)) {
58 return PIXEL_FORMAT_UNKNOWN;
59 }
60 return it->chromium_format;
61 }
62
63 // static
64 uint32_t CameraDeviceDelegate::PixFormatChromiumToDrm(VideoPixelFormat from) {
65 auto it = std::find_if(
66 std::begin(kSupportedFormats), std::end(kSupportedFormats),
67 [from](SupportedFormat f) { return f.chromium_format == from; });
68 if (it == std::end(kSupportedFormats)) {
69 return 0;
70 }
71 return it->drm_format;
72 }
73
74 void CameraDeviceDelegate::AllocateAndStart(
75 const VideoCaptureParams& params,
76 std::unique_ptr<VideoCaptureDevice::Client> client) {
77 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
78 DCHECK(!client_);
79 DCHECK(state_ = kStopped);
80 const arc::mojom::CameraMetadataEntryPtr* partial_count = GetMetadataEntry(
81 static_metadata_,
82 arc::mojom::CameraMetadataTag::ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
83 // The partial result count metadata is optional. It defaults to 1 in case it
84 // is not set in the static metadata.
85 if (partial_count) {
86 partial_result_count_ =
87 *reinterpret_cast<int32_t*>((*partial_count)->data.data());
88 }
89
90 client_ = std::move(client);
91 device_ops_.Bind(std::move(device_ops_info_), ipc_task_runner_);
92 device_ops_.set_connection_error_handler(
93 base::Bind(&CameraDeviceDelegate::OnMojoConnectionError, this));
94 frame_number_ = 0;
95 streams_.clear();
96 partial_results_.clear();
97
98 // Set up context for preview stream.
99 arc::mojom::Camera3StreamPtr preview_stream =
100 arc::mojom::Camera3Stream::New();
101 preview_stream->id = static_cast<uint64_t>(
102 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
103 preview_stream->stream_type =
104 arc::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
105 preview_stream->width = params.requested_format.frame_size.width();
106 preview_stream->height = params.requested_format.frame_size.height();
107 // preview_stream->format = HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888;
108 // TODO(jcliang): We should not use implementation defined format here.
109 preview_stream->format =
110 arc::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
111 preview_stream->data_space = 0;
112 preview_stream->rotation =
113 arc::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;
114 streams_[arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW] = {
115 .params = params, .stream = std::move(preview_stream),
116 };
117 // TODO(jcliang): Set up context for still capture stream.
118
119 SetState(kStarting);
120 Initialize();
121 }
122
123 void CameraDeviceDelegate::StopAndDeAllocate(base::WaitableEvent* closed) {
124 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
125 // StopAndDeAllocate may be called at any state.
126
127 if (!device_ops_.is_bound() || state_ == kStopping) {
128 // In case of Mojo connection error |device_ops_| and |callback_ops_| are
129 // unbound.
130 return;
131 }
132 SetState(kStopping);
133 device_ops_->Close(base::Bind(&CameraDeviceDelegate::OnClosed, this,
134 base::Unretained(closed)));
135 }
136
137 void CameraDeviceDelegate::TakePhoto(
138 VideoCaptureDevice::TakePhotoCallback callback) {
139 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
140 // TODO(jcliang): Implement TakePhoto.
141 }
142
143 void CameraDeviceDelegate::GetPhotoCapabilities(
144 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
145 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
146 // TODO(jcliang): Implement GetPhotoCapabilities.
147 }
148
149 void CameraDeviceDelegate::SetPhotoOptions(
150 mojom::PhotoSettingsPtr settings,
151 VideoCaptureDevice::SetPhotoOptionsCallback callback) {
152 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
153 // TODO(jcliang): Implement SetPhotoOptions.
154 }
155
156 void CameraDeviceDelegate::SetRotation(int rotation) {
157 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
158 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
159 rotation_ = rotation;
160 }
161
162 void CameraDeviceDelegate::SetState(State state) {
163 state_ = state;
164 }
165
166 void CameraDeviceDelegate::SetErrorState(
167 const tracked_objects::Location& from_here,
168 const std::string& reason) {
169 state_ = kError;
170 client_->OnError(from_here, reason);
171 }
172
173 void CameraDeviceDelegate::ResetMojoInterface() {
174 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
175 device_ops_.reset();
176 if (callback_ops_.is_bound()) {
177 callback_ops_.Unbind();
178 }
179 }
180
181 void CameraDeviceDelegate::OnMojoConnectionError() {
182 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
183 ResetMojoInterface();
184 SetErrorState(FROM_HERE, "Mojo connection error");
185 }
186
187 void CameraDeviceDelegate::OnClosed(base::WaitableEvent* closed,
188 int32_t result) {
189 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
190 ResetMojoInterface();
191 client_.reset();
192 SetState(kStopped);
193 closed->Signal();
194 }
195
196 void CameraDeviceDelegate::Initialize() {
197 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
198 DCHECK(state_ == kStarting);
199
200 device_ops_->Initialize(
201 callback_ops_.CreateInterfacePtrAndBind(),
202 base::Bind(&CameraDeviceDelegate::OnInitialized, this));
203 callback_ops_.set_connection_error_handler(
204 base::Bind(&CameraDeviceDelegate::OnMojoConnectionError, this));
205 }
206
207 void CameraDeviceDelegate::OnInitialized(int32_t result) {
208 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
209 DCHECK(state_ == kStarting || state_ == kStopping);
210
211 if (state_ == kStopping) {
212 return;
213 }
214 if (result) {
215 SetErrorState(FROM_HERE, "Failed to initialize camera device");
216 return;
217 }
218 SetState(kInitialized);
219 ConfigureStreams();
220 }
221
222 void CameraDeviceDelegate::ConfigureStreams() {
223 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
224 DCHECK(state_ == kInitialized || state_ == kStopping);
225
226 arc::mojom::Camera3StreamConfigurationPtr stream_config =
227 arc::mojom::Camera3StreamConfiguration::New();
228 stream_config->num_streams = streams_.size();
229 for (const auto& context : streams_) {
230 stream_config->streams.push_back(context.second.stream.Clone());
231 }
232 stream_config->operation_mode = arc::mojom::Camera3StreamConfigurationMode::
233 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
234 device_ops_->ConfigureStreams(
235 std::move(stream_config),
236 base::Bind(&CameraDeviceDelegate::OnConfiguredStreams, this));
237 }
238
239 void CameraDeviceDelegate::OnConfiguredStreams(
240 arc::mojom::Camera3StreamConfigurationPtr updated_config) {
241 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
242 DCHECK(state_ == kInitialized || state_ == kStopping);
243
244 if (state_ == kStopping) {
245 return;
246 }
247 for (size_t i = 0; i < updated_config->num_streams; ++i) {
248 auto& updated_stream = updated_config->streams[i];
249 arc::mojom::Camera3RequestTemplate stream_type =
250 static_cast<arc::mojom::Camera3RequestTemplate>(updated_stream->id);
251 StreamContext* stream_context = GetStreamContext(stream_type);
252 if (!stream_context) {
253 SetErrorState(FROM_HERE, "ConfigureStreams returned invalid stream");
254 continue;
255 }
256 // TODO(jcliang): Determine the best format from metadata.
257 VideoCaptureFormat capture_format = stream_context->params.requested_format;
258 capture_format.pixel_format = PIXEL_FORMAT_RGB32;
259 stream_context->capture_format = capture_format;
260 stream_context->stream->usage = updated_stream->usage;
261 stream_context->stream->max_buffers = updated_stream->max_buffers;
262
263 VLOG(2) << "Stream " << updated_stream->id
264 << " configured: usage=" << updated_stream->usage
265 << " max_buffers=" << updated_stream->max_buffers;
266
267 // Allocate buffers.
268 size_t num_buffers = stream_context->stream->max_buffers;
269 stream_context->buffers.resize(num_buffers);
270 for (size_t j = 0; j < num_buffers; ++j) {
271 const VideoCaptureFormat frame_format(
272 gfx::Size(stream_context->stream->width,
273 stream_context->stream->height),
274 0.0, stream_context->capture_format.pixel_format);
275 std::unique_ptr<base::SharedMemory> buffer(new base::SharedMemory());
276 base::SharedMemoryCreateOptions options;
277 options.size = frame_format.ImageAllocationSize();
278 options.share_read_only = false;
279 buffer->Create(options);
280 buffer->Map(buffer->requested_size());
281 stream_context->buffers[j] = std::move(buffer);
282 stream_context->free_buffers.push(j);
283 }
284 VLOG(2) << "Allocated " << stream_context->stream->max_buffers
285 << " buffers for stream " << stream_type;
286
287 // TODO(jcliang): Construct default request settings for still capture.
288 ConstructDefaultRequestSettings(
289 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
290 }
291
292 client_->OnStarted();
293 }
294
295 void CameraDeviceDelegate::ConstructDefaultRequestSettings(
296 arc::mojom::Camera3RequestTemplate stream_type) {
297 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
298 DCHECK(GetStreamContext(stream_type));
299
300 device_ops_->ConstructDefaultRequestSettings(
301 stream_type,
302 base::Bind(&CameraDeviceDelegate::OnConstructedDefaultRequestSettings,
303 this, stream_type));
304 }
305
306 void CameraDeviceDelegate::OnConstructedDefaultRequestSettings(
307 arc::mojom::Camera3RequestTemplate stream_type,
308 arc::mojom::CameraMetadataPtr settings) {
309 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
310
311 if (state_ == kStopping) {
312 return;
313 }
314 StreamContext* stream_context = GetStreamContext(stream_type);
315 DCHECK(stream_context);
316 stream_context->request_settings = std::move(settings);
317 // TODO(jcliang): Once we have the still capture stream we need to change it
318 // to only SetState when both preview and still capture streams
319 // are configured.
320 SetState(kStreamConfigured);
321 if (stream_type ==
322 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW) {
323 StartCapture(stream_type);
324 }
325 }
326
327 void CameraDeviceDelegate::StartCapture(
328 arc::mojom::Camera3RequestTemplate stream_type) {
329 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
330 // We may get here when either after the streams are configured, or when we
331 // start still capture while the preview capture is running.
332 DCHECK(state_ == kStreamConfigured || state_ == kCapturing ||
333 state_ == kStopping);
334
335 if (state_ == kStopping) {
336 return;
337 }
338 StreamContext* stream_context = GetStreamContext(stream_type);
339 DCHECK(stream_context);
340 DCHECK(!stream_context->request_settings.is_null());
341 SetState(kCapturing);
342 RegisterBuffer(stream_type);
343 }
344
345 void CameraDeviceDelegate::RegisterBuffer(
346 arc::mojom::Camera3RequestTemplate stream_type) {
347 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
348 DCHECK(state_ == kCapturing || state_ == kStopping);
349
350 if (state_ == kStopping) {
351 return;
352 }
353 StreamContext* stream_context = GetStreamContext(stream_type);
354 DCHECK(stream_context);
355 if (stream_context->free_buffers.empty()) {
356 return;
357 }
358
359 const VideoCaptureParams& params = stream_context->params;
360 const arc::mojom::Camera3StreamPtr& stream = stream_context->stream;
361 size_t buffer_id = stream_context->free_buffers.front();
362 stream_context->free_buffers.pop();
363 const base::SharedMemory* buffer = stream_context->buffers[buffer_id].get();
364
365 VideoPixelFormat buffer_format = stream_context->capture_format.pixel_format;
366 uint32_t drm_format = PixFormatChromiumToDrm(buffer_format);
367 if (!drm_format) {
368 SetErrorState(FROM_HERE, "Unsupported video pixel format");
369 return;
370 }
371 arc::mojom::HalPixelFormat hal_pixel_format = stream->format;
372
373 size_t num_planes = VideoFrame::NumPlanes(buffer_format);
374 std::vector<mojo::ScopedHandle> fds(num_planes);
375 std::vector<uint32_t> strides(num_planes);
376 std::vector<uint32_t> offsets(num_planes);
377 for (size_t i = 0; i < num_planes; ++i) {
378 base::SharedMemoryHandle shm_handle = buffer->handle();
379 // Wrap the platform handle.
380 MojoHandle wrapped_handle;
381 MojoResult result = mojo::edk::CreatePlatformHandleWrapper(
382 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(
383 base::SharedMemory::DuplicateHandle(shm_handle).fd)),
384 &wrapped_handle);
385 if (result != MOJO_RESULT_OK) {
386 SetErrorState(FROM_HERE, "Failed to wrap shared memory handle");
387 return;
388 }
389 fds[i].reset(mojo::Handle(wrapped_handle));
390 strides[i] = VideoFrame::RowBytes(i, buffer_format, stream->width);
391 if (!i) {
392 offsets[i] = 0;
393 } else {
394 offsets[i] = offsets[i - 1] +
395 VideoFrame::PlaneSize(buffer_format, i,
396 params.requested_format.frame_size)
397 .GetArea();
398 }
399 }
400 device_ops_->RegisterBuffer(
401 buffer_id, arc::mojom::Camera3DeviceOps::BufferType::SHM, std::move(fds),
402 drm_format, hal_pixel_format, stream_context->stream->width,
403 stream_context->stream->height, std::move(strides), std::move(offsets),
404 base::Bind(&CameraDeviceDelegate::OnRegisteredBuffer, this, stream_type,
405 buffer_id));
406 VLOG(2) << "Registered buffer " << buffer_id << " of stream " << stream_type;
407 }
408
409 void CameraDeviceDelegate::OnRegisteredBuffer(
410 arc::mojom::Camera3RequestTemplate stream_type,
411 size_t buffer_index,
412 int32_t result) {
413 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
414 DCHECK(state_ == kCapturing || state_ == kStopping);
415
416 if (state_ == kStopping) {
417 return;
418 }
419 if (result) {
420 SetErrorState(FROM_HERE, "Failed to register buffer");
421 return;
422 }
423 ProcessCaptureRequest(stream_type, buffer_index);
424 }
425
426 void CameraDeviceDelegate::ProcessCaptureRequest(
427 arc::mojom::Camera3RequestTemplate stream_type,
428 size_t buffer_index) {
429 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
430 DCHECK(state_ == kCapturing || state_ == kStopping);
431
432 StreamContext* stream_context = GetStreamContext(stream_type);
433 DCHECK(stream_context);
434
435 arc::mojom::Camera3StreamBufferPtr buffer =
436 arc::mojom::Camera3StreamBuffer::New();
437 buffer->stream_id = static_cast<uint64_t>(
438 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW);
439 buffer->buffer_id = buffer_index;
440 buffer->status = arc::mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_OK;
441
442 // TODO(jcliang): Also process still capture buffers after we enabled still
443 // capture stream.
444 arc::mojom::Camera3CaptureRequestPtr request =
445 arc::mojom::Camera3CaptureRequest::New();
446 request->frame_number = frame_number_;
447 request->settings = stream_context->request_settings.Clone();
448 request->num_output_buffers = 1;
449 request->output_buffers.push_back(std::move(buffer));
450
451 device_ops_->ProcessCaptureRequest(
452 std::move(request),
453 base::Bind(&CameraDeviceDelegate::OnProcessedCaptureRequest, this,
454 stream_type));
455 VLOG(2) << "Requested capture for frame " << frame_number_ << " with buffer "
456 << buffer_index << " of stream " << stream_type;
457 frame_number_++;
458 }
459
460 void CameraDeviceDelegate::OnProcessedCaptureRequest(
461 arc::mojom::Camera3RequestTemplate stream_type,
462 int32_t result) {
463 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
464 DCHECK(state_ == kCapturing || state_ == kStopping);
465
466 if (state_ == kStopping) {
467 return;
468 }
469 if (result) {
470 SetErrorState(FROM_HERE, "Process capture request failed");
471 return;
472 }
473 RegisterBuffer(stream_type);
474 }
475
476 void CameraDeviceDelegate::ProcessCaptureResult(
477 arc::mojom::Camera3CaptureResultPtr result) {
478 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
479
480 uint32_t frame_number = result->frame_number;
481 CaptureResult& partial_result = partial_results_[frame_number];
482 for (size_t i = 0; i < result->num_output_buffers; ++i) {
kenrb 2017/05/01 23:08:34 This looks like it causes a problem if num_output_
jcliang 2017/05/02 12:57:20 You're right we don't need num_output_buffers here
483 arc::mojom::Camera3StreamBufferPtr& stream_buffer =
484 result->output_buffers.value()[i];
485 arc::mojom::Camera3RequestTemplate stream_type =
486 static_cast<arc::mojom::Camera3RequestTemplate>(
487 stream_buffer->stream_id);
488 // The camera HAL v3 API specifies that only one capture result can carry
489 // the result buffer for any given frame number.
490 if (partial_result.buffers.find(stream_type) !=
491 partial_result.buffers.end()) {
492 client_->OnLog(
493 std::string("Received multiple result buffers for frame ") +
494 std::to_string(frame_number));
495 continue;
496 }
497 if (stream_buffer->status ==
498 arc::mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_ERROR) {
499 // TODO(jcliang): Discard buffer and continue maybe?
500 SetErrorState(FROM_HERE, "HAL encountered error while filling buffer");
501 return;
502 }
503 partial_results_[frame_number].buffers[stream_type] =
504 std::move(stream_buffer);
505 }
506
507 // |result->partial_result| is set to 0 if the capture result contains only
508 // the result buffer handles and no result metadata.
509 if (result->partial_result) {
510 partial_results_[frame_number].partial_stage = result->partial_result;
511 MergeMetadata(&partial_results_[frame_number].metadata, result->result);
512 }
513
514 if (partial_result.partial_stage == partial_result_count_) {
515 // This is the last capture results for the requests of this frame number.
516 auto it = partial_results_.find(frame_number);
517 // We can only submit the result buffer after we receive the shutter time.
518 if (it->second.reference_time != base::TimeTicks()) {
519 SubmitCaptureResult(frame_number);
520 }
521 }
522 }
523
524 void CameraDeviceDelegate::Notify(arc::mojom::Camera3NotifyMsgPtr message) {
525 // TODO(jcliang): unit tests.
526 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
527
528 if (message->type == arc::mojom::Camera3MsgType::CAMERA3_MSG_ERROR) {
529 // TODO(jcliang): Handle error notify.
530 } else { // arc::mojom::Camera3MsgType::CAMERA3_MSG_SHUTTER
531 uint32_t frame_number = message->message->get_shutter()->frame_number;
532 uint64_t shutter_time = message->message->get_shutter()->timestamp;
533 CaptureResult& partial_result = partial_results_[frame_number];
534 // Shutter timestamp is in ns.
535 base::TimeTicks reference_time =
536 base::TimeTicks::FromInternalValue(shutter_time / 1000);
537 partial_result.reference_time = reference_time;
538 if (!frame_number) {
539 // Record the shutter time of the first frame for calculating the
540 // timestamp.
541 first_frame_shutter_time_ = reference_time;
542 partial_result.timestamp = base::TimeDelta::FromMicroseconds(0);
543 } else {
544 partial_result.timestamp = reference_time - first_frame_shutter_time_;
545 }
546 if (partial_result.partial_stage == partial_result_count_) {
547 SubmitCaptureResult(frame_number);
548 }
549 }
550 }
551
552 void CameraDeviceDelegate::SubmitCaptureResult(uint32_t frame_number) {
553 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
554
555 if (partial_results_.begin()->first != frame_number) {
556 SetErrorState(FROM_HERE, "Received out-of-order frames from HAL");
557 return;
558 }
559
560 CaptureResult& partial_result = partial_results_[frame_number];
561 DCHECK_EQ(partial_result.partial_stage, partial_result_count_);
562 for (const auto& it : partial_result.buffers) {
563 arc::mojom::Camera3RequestTemplate stream_type = it.first;
564 StreamContext* stream_context = GetStreamContext(stream_type);
565 const arc::mojom::Camera3StreamBufferPtr& buffer = it.second;
566 uint32_t buffer_id = buffer->buffer_id;
567
568 // Wait on release fence before delivering the result buffer to client.
569 if (buffer->release_fence.is_valid()) {
570 const int kSyncWaitTimeoutMs = 1000;
571 mojo::edk::ScopedPlatformHandle fence;
572 MojoResult result = mojo::edk::PassWrappedPlatformHandle(
573 buffer->release_fence.release().value(), &fence);
574 if (result != MOJO_RESULT_OK) {
575 SetErrorState(FROM_HERE, "Failed to unwrap release fence fd");
576 return;
577 }
578 if (!sync_wait(fence.get().handle, kSyncWaitTimeoutMs)) {
579 SetErrorState(FROM_HERE, "Sync wait on release fence timed out");
580 return;
581 }
582 }
583
584 if (stream_type ==
585 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW) {
586 // Deliver the captured data to client and then re-queue the buffer.
587 const base::SharedMemory* buffer =
588 stream_context->buffers[buffer_id].get();
589 client_->OnIncomingCapturedData(
590 reinterpret_cast<uint8_t*>(buffer->memory()), buffer->mapped_size(),
591 stream_context->capture_format, rotation_,
592 partial_result.reference_time, partial_result.timestamp);
593 stream_context->free_buffers.push(buffer_id);
594 ipc_task_runner_->PostTask(
595 FROM_HERE,
596 base::Bind(
597 &CameraDeviceDelegate::RegisterBuffer, this,
598 arc::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW));
599 }
600 // TODO(jcliang): Handle still capture result for TakePhoto.
601 }
602 partial_results_.erase(frame_number);
603 }
604
605 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698