1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define LOG_TAG "VsockCameraDeviceSession"
17 #include "vsock_camera_device_session_3_4.h"
18 #include <hidl/Status.h>
19 #include <include/convert.h>
20 #include <inttypes.h>
21 #include <libyuv.h>
22 #include <log/log.h>
23 #include "vsock_camera_metadata.h"
24
25 // Partially copied from ExternalCameraDeviceSession
26 namespace android::hardware::camera::device::V3_4::implementation {
27
VsockCameraDeviceSession(VsockCameraMetadata camera_characteristics,std::shared_ptr<cuttlefish::VsockFrameProvider> frame_provider,const sp<ICameraDeviceCallback> & callback)28 VsockCameraDeviceSession::VsockCameraDeviceSession(
29 VsockCameraMetadata camera_characteristics,
30 std::shared_ptr<cuttlefish::VsockFrameProvider> frame_provider,
31 const sp<ICameraDeviceCallback>& callback)
32 : camera_characteristics_(camera_characteristics),
33 frame_provider_(frame_provider),
34 callback_(callback) {
35 static constexpr size_t kMsgQueueSize = 256 * 1024;
36 request_queue_ =
37 std::make_unique<MessageQueue<uint8_t, kSynchronizedReadWrite>>(
38 kMsgQueueSize, false);
39 result_queue_ =
40 std::make_shared<MessageQueue<uint8_t, kSynchronizedReadWrite>>(
41 kMsgQueueSize, false);
42 unsigned int timeout_ms = 1000 / camera_characteristics.getPreferredFps();
43 process_requests_ = true;
44 request_processor_ =
45 std::thread([this, timeout_ms] { processRequestLoop(timeout_ms); });
46 }
47
~VsockCameraDeviceSession()48 VsockCameraDeviceSession::~VsockCameraDeviceSession() { close(); }
49
constructDefaultRequestSettings(V3_2::RequestTemplate type,V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb)50 Return<void> VsockCameraDeviceSession::constructDefaultRequestSettings(
51 V3_2::RequestTemplate type,
52 V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
53 auto frame_rate = camera_characteristics_.getPreferredFps();
54 auto metadata = VsockCameraRequestMetadata(frame_rate, type);
55 V3_2::CameraMetadata hidl_metadata;
56 Status status = metadata.isValid() ? Status::OK : Status::ILLEGAL_ARGUMENT;
57 if (metadata.isValid()) {
58 camera_metadata_t* metadata_ptr = metadata.release();
59 hidl_metadata.setToExternal((uint8_t*)metadata_ptr,
60 get_camera_metadata_size(metadata_ptr));
61 }
62 _hidl_cb(status, hidl_metadata);
63 return Void();
64 }
65
getCaptureRequestMetadataQueue(ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb)66 Return<void> VsockCameraDeviceSession::getCaptureRequestMetadataQueue(
67 ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
68 _hidl_cb(*request_queue_->getDesc());
69 return Void();
70 }
71
getCaptureResultMetadataQueue(ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb)72 Return<void> VsockCameraDeviceSession::getCaptureResultMetadataQueue(
73 ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
74 _hidl_cb(*result_queue_->getDesc());
75 return Void();
76 }
77
configureStreams(const V3_2::StreamConfiguration & streams,ICameraDeviceSession::configureStreams_cb _hidl_cb)78 Return<void> VsockCameraDeviceSession::configureStreams(
79 const V3_2::StreamConfiguration& streams,
80 ICameraDeviceSession::configureStreams_cb _hidl_cb) {
81 // common configureStreams operate with v3_2 config and v3_3
82 // streams so we need to "downcast" v3_3 streams to v3_2 streams
83 V3_2::HalStreamConfiguration out_v32;
84 V3_3::HalStreamConfiguration out_v33;
85
86 Status status = configureStreams(streams, &out_v33);
87 size_t size = out_v33.streams.size();
88 out_v32.streams.resize(size);
89 for (size_t i = 0; i < size; i++) {
90 out_v32.streams[i] = out_v33.streams[i].v3_2;
91 }
92 _hidl_cb(status, out_v32);
93 return Void();
94 }
95
configureStreams_3_3(const V3_2::StreamConfiguration & streams,ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb)96 Return<void> VsockCameraDeviceSession::configureStreams_3_3(
97 const V3_2::StreamConfiguration& streams,
98 ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb) {
99 V3_3::HalStreamConfiguration out_v33;
100 Status status = configureStreams(streams, &out_v33);
101 _hidl_cb(status, out_v33);
102 return Void();
103 }
104
configureStreams_3_4(const V3_4::StreamConfiguration & requestedConfiguration,ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)105 Return<void> VsockCameraDeviceSession::configureStreams_3_4(
106 const V3_4::StreamConfiguration& requestedConfiguration,
107 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
108 // common configureStreams operate with v3_2 config and v3_3
109 // streams so we need to "downcast" v3_4 config to v3_2 and
110 // "upcast" v3_3 streams to v3_4 streams
111 V3_2::StreamConfiguration config_v32;
112 V3_3::HalStreamConfiguration out_v33;
113 V3_4::HalStreamConfiguration out_v34;
114
115 config_v32.operationMode = requestedConfiguration.operationMode;
116 config_v32.streams.resize(requestedConfiguration.streams.size());
117 for (size_t i = 0; i < config_v32.streams.size(); i++) {
118 config_v32.streams[i] = requestedConfiguration.streams[i].v3_2;
119 }
120 max_blob_size_ = getBlobSize(requestedConfiguration);
121 Status status = configureStreams(config_v32, &out_v33);
122
123 out_v34.streams.resize(out_v33.streams.size());
124 for (size_t i = 0; i < out_v34.streams.size(); i++) {
125 out_v34.streams[i].v3_3 = out_v33.streams[i];
126 }
127 _hidl_cb(status, out_v34);
128 return Void();
129 }
130
processCaptureRequest(const hidl_vec<CaptureRequest> & requests,const hidl_vec<BufferCache> & cachesToRemove,ICameraDeviceSession::processCaptureRequest_cb _hidl_cb)131 Return<void> VsockCameraDeviceSession::processCaptureRequest(
132 const hidl_vec<CaptureRequest>& requests,
133 const hidl_vec<BufferCache>& cachesToRemove,
134 ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
135 updateBufferCaches(cachesToRemove);
136
137 uint32_t count;
138 Status s = Status::OK;
139 for (count = 0; count < requests.size(); count++) {
140 s = processOneCaptureRequest(requests[count]);
141 if (s != Status::OK) {
142 break;
143 }
144 }
145
146 _hidl_cb(s, count);
147 return Void();
148 }
149
processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest> & requests,const hidl_vec<V3_2::BufferCache> & cachesToRemove,ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb)150 Return<void> VsockCameraDeviceSession::processCaptureRequest_3_4(
151 const hidl_vec<V3_4::CaptureRequest>& requests,
152 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
153 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
154 updateBufferCaches(cachesToRemove);
155
156 uint32_t count;
157 Status s = Status::OK;
158 for (count = 0; count < requests.size(); count++) {
159 s = processOneCaptureRequest(requests[count].v3_2);
160 if (s != Status::OK) {
161 break;
162 }
163 }
164
165 _hidl_cb(s, count);
166 return Void();
167 }
168
flush()169 Return<Status> VsockCameraDeviceSession::flush() {
170 auto timeout = std::chrono::seconds(1);
171 std::unique_lock<std::mutex> lock(request_mutex_);
172 flushing_requests_ = true;
173 auto is_empty = [this] { return pending_requests_.empty(); };
174 if (!queue_empty_.wait_for(lock, timeout, is_empty)) {
175 ALOGE("Flush timeout - %zu pending requests", pending_requests_.size());
176 }
177 flushing_requests_ = false;
178 return Status::OK;
179 }
180
close()181 Return<void> VsockCameraDeviceSession::close() {
182 process_requests_ = false;
183 if (request_processor_.joinable()) {
184 request_processor_.join();
185 }
186 frame_provider_->stop();
187 buffer_cache_.clear();
188 ALOGI("%s", __FUNCTION__);
189 return Void();
190 }
191
192 using ::android::hardware::graphics::common::V1_0::BufferUsage;
193 using ::android::hardware::graphics::common::V1_0::PixelFormat;
configureStreams(const V3_2::StreamConfiguration & config,V3_3::HalStreamConfiguration * out)194 Status VsockCameraDeviceSession::configureStreams(
195 const V3_2::StreamConfiguration& config,
196 V3_3::HalStreamConfiguration* out) {
197 Status status = isStreamConfigurationSupported(config);
198 if (status != Status::OK) {
199 return status;
200 }
201 updateStreamInfo(config);
202 out->streams.resize(config.streams.size());
203 for (size_t i = 0; i < config.streams.size(); i++) {
204 out->streams[i].overrideDataSpace = config.streams[i].dataSpace;
205 out->streams[i].v3_2.id = config.streams[i].id;
206 out->streams[i].v3_2.producerUsage =
207 config.streams[i].usage | BufferUsage::CPU_WRITE_OFTEN;
208 out->streams[i].v3_2.consumerUsage = 0;
209 out->streams[i].v3_2.maxBuffers = 2;
210 out->streams[i].v3_2.overrideFormat =
211 config.streams[i].format == PixelFormat::IMPLEMENTATION_DEFINED
212 ? PixelFormat::YCBCR_420_888
213 : config.streams[i].format;
214 }
215 return Status::OK;
216 }
217
218 using ::android::hardware::camera::device::V3_2::StreamRotation;
219 using ::android::hardware::camera::device::V3_2::StreamType;
isStreamConfigurationSupported(const V3_2::StreamConfiguration & config)220 Status VsockCameraDeviceSession::isStreamConfigurationSupported(
221 const V3_2::StreamConfiguration& config) {
222 camera_metadata_entry device_supported_streams = camera_characteristics_.find(
223 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
224 int32_t stall_stream_count = 0;
225 int32_t stream_count = 0;
226 for (const auto& stream : config.streams) {
227 if (stream.rotation != StreamRotation::ROTATION_0) {
228 ALOGE("Unsupported rotation enum value %d", stream.rotation);
229 return Status::ILLEGAL_ARGUMENT;
230 }
231 if (stream.streamType == StreamType::INPUT) {
232 ALOGE("Input stream not supported");
233 return Status::ILLEGAL_ARGUMENT;
234 }
235 bool is_supported = false;
236 // check pixel format and dimensions against camera metadata
237 for (int i = 0; i + 4 <= device_supported_streams.count; i += 4) {
238 auto format =
239 static_cast<PixelFormat>(device_supported_streams.data.i32[i]);
240 int32_t width = device_supported_streams.data.i32[i + 1];
241 int32_t height = device_supported_streams.data.i32[i + 2];
242 if (stream.format == format && stream.width == width &&
243 stream.height == height) {
244 is_supported = true;
245 break;
246 }
247 }
248 if (!is_supported) {
249 ALOGE("Unsupported format %d (%dx%d)", stream.format, stream.width,
250 stream.height);
251 return Status::ILLEGAL_ARGUMENT;
252 }
253 if (stream.format == PixelFormat::BLOB) {
254 stall_stream_count++;
255 } else {
256 stream_count++;
257 }
258 }
259 camera_metadata_entry device_stream_counts =
260 camera_characteristics_.find(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS);
261 static constexpr auto stream_index = 1;
262 auto expected_stream_count = device_stream_counts.count > stream_index
263 ? device_stream_counts.data.i32[stream_index]
264 : 0;
265 if (stream_count > expected_stream_count) {
266 ALOGE("Too many processed streams (expect <= %d, got %d)",
267 expected_stream_count, stream_count);
268 return Status::ILLEGAL_ARGUMENT;
269 }
270 static constexpr auto stall_stream_index = 2;
271 expected_stream_count =
272 device_stream_counts.count > stall_stream_index
273 ? device_stream_counts.data.i32[stall_stream_index]
274 : 0;
275 if (stall_stream_count > expected_stream_count) {
276 ALOGE("Too many stall streams (expect <= %d, got %d)",
277 expected_stream_count, stall_stream_count);
278 return Status::ILLEGAL_ARGUMENT;
279 }
280 return Status::OK;
281 }
282
getBlobSize(const V3_4::StreamConfiguration & requestedConfiguration)283 unsigned int VsockCameraDeviceSession::getBlobSize(
284 const V3_4::StreamConfiguration& requestedConfiguration) {
285 camera_metadata_entry jpeg_entry =
286 camera_characteristics_.find(ANDROID_JPEG_MAX_SIZE);
287 unsigned int blob_size = jpeg_entry.count > 0 ? jpeg_entry.data.i32[0] : 0;
288 for (auto& stream : requestedConfiguration.streams) {
289 if (stream.v3_2.format == PixelFormat::BLOB) {
290 if (stream.bufferSize < blob_size) {
291 blob_size = stream.bufferSize;
292 }
293 }
294 }
295 return blob_size;
296 }
297
updateBufferCaches(const hidl_vec<BufferCache> & to_remove)298 void VsockCameraDeviceSession::updateBufferCaches(
299 const hidl_vec<BufferCache>& to_remove) {
300 for (auto& cache : to_remove) {
301 buffer_cache_.remove(cache.bufferId);
302 }
303 }
304
updateStreamInfo(const V3_2::StreamConfiguration & config)305 void VsockCameraDeviceSession::updateStreamInfo(
306 const V3_2::StreamConfiguration& config) {
307 std::set<int32_t> stream_ids;
308 for (const auto& stream : config.streams) {
309 stream_cache_[stream.id] = stream;
310 stream_ids.emplace(stream.id);
311 }
312 buffer_cache_.removeStreamsExcept(stream_ids);
313 }
314
processOneCaptureRequest(const CaptureRequest & request)315 Status VsockCameraDeviceSession::processOneCaptureRequest(
316 const CaptureRequest& request) {
317 const camera_metadata_t* request_settings = nullptr;
318 V3_2::CameraMetadata hidl_settings;
319 if (request.fmqSettingsSize > 0) {
320 if (!getRequestSettingsFmq(request.fmqSettingsSize, hidl_settings)) {
321 ALOGE("%s: Could not read capture request settings from fmq!",
322 __FUNCTION__);
323 return Status::ILLEGAL_ARGUMENT;
324 } else if (!V3_2::implementation::convertFromHidl(hidl_settings,
325 &request_settings)) {
326 ALOGE("%s: fmq request settings metadata is corrupt!", __FUNCTION__);
327 return Status::ILLEGAL_ARGUMENT;
328 }
329 } else if (!V3_2::implementation::convertFromHidl(request.settings,
330 &request_settings)) {
331 ALOGE("%s: request settings metadata is corrupt!", __FUNCTION__);
332 return Status::ILLEGAL_ARGUMENT;
333 }
334 if (request_settings != nullptr) {
335 // Update request settings. This must happen on first request
336 std::lock_guard<std::mutex> lock(settings_mutex_);
337 latest_request_settings_ = request_settings;
338 } else if (latest_request_settings_.isEmpty()) {
339 ALOGE("%s: Undefined capture request settings!", __FUNCTION__);
340 return Status::ILLEGAL_ARGUMENT;
341 }
342
343 std::vector<uint64_t> buffer_ids;
344 buffer_ids.reserve(request.outputBuffers.size());
345 for (size_t i = 0; i < request.outputBuffers.size(); i++) {
346 buffer_cache_.update(request.outputBuffers[i]);
347 buffer_ids.emplace_back(request.outputBuffers[i].bufferId);
348 }
349 std::lock_guard<std::mutex> lock(settings_mutex_);
350 ReadVsockRequest request_to_process = {
351 .buffer_ids = buffer_ids,
352 .frame_number = request.frameNumber,
353 .timestamp = 0,
354 .settings = latest_request_settings_,
355 .buffer_count = static_cast<uint32_t>(buffer_ids.size())};
356 putRequestToQueue(request_to_process);
357 return Status::OK;
358 }
359
getRequestSettingsFmq(uint64_t size,V3_2::CameraMetadata & hidl_settings)360 bool VsockCameraDeviceSession::getRequestSettingsFmq(
361 uint64_t size, V3_2::CameraMetadata& hidl_settings) {
362 hidl_settings.resize(size);
363 return request_queue_->read(hidl_settings.data(), size);
364 }
365
getRequestFromQueue(ReadVsockRequest & req,unsigned int timeout_ms)366 bool VsockCameraDeviceSession::getRequestFromQueue(ReadVsockRequest& req,
367 unsigned int timeout_ms) {
368 auto timeout = std::chrono::milliseconds(timeout_ms);
369 std::unique_lock<std::mutex> lock(request_mutex_);
370 auto not_empty = [this] { return !pending_requests_.empty(); };
371 if (request_available_.wait_for(lock, timeout, not_empty)) {
372 req = pending_requests_.top();
373 pending_requests_.pop();
374 return true;
375 }
376 queue_empty_.notify_one();
377 return false;
378 }
379
putRequestToQueue(const ReadVsockRequest & request)380 void VsockCameraDeviceSession::putRequestToQueue(
381 const ReadVsockRequest& request) {
382 std::lock_guard<std::mutex> lock(request_mutex_);
383 pending_requests_.push(request);
384 request_available_.notify_one();
385 }
386
fillCaptureResult(common::V1_0::helper::CameraMetadata & md,nsecs_t timestamp)387 void VsockCameraDeviceSession::fillCaptureResult(
388 common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp) {
389 const uint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;
390 md.update(ANDROID_CONTROL_AF_STATE, &af_state, 1);
391
392 const uint8_t aeState = ANDROID_CONTROL_AE_STATE_CONVERGED;
393 md.update(ANDROID_CONTROL_AE_STATE, &aeState, 1);
394
395 const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
396 md.update(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
397
398 const uint8_t awbState = ANDROID_CONTROL_AWB_STATE_CONVERGED;
399 md.update(ANDROID_CONTROL_AWB_STATE, &awbState, 1);
400
401 const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
402 md.update(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
403
404 const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE;
405 md.update(ANDROID_FLASH_STATE, &flashState, 1);
406
407 const uint8_t requestPipelineMaxDepth = 4;
408 md.update(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
409
410 camera_metadata_entry active_array_size =
411 camera_characteristics_.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
412 md.update(ANDROID_SCALER_CROP_REGION, active_array_size.data.i32, 4);
413
414 md.update(ANDROID_SENSOR_TIMESTAMP, ×tamp, 1);
415
416 const uint8_t lensShadingMapMode =
417 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
418 md.update(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &lensShadingMapMode, 1);
419
420 const uint8_t sceneFlicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
421 md.update(ANDROID_STATISTICS_SCENE_FLICKER, &sceneFlicker, 1);
422 }
423
424 using ::android::hardware::camera::device::V3_2::MsgType;
425 using ::android::hardware::camera::device::V3_2::NotifyMsg;
notifyShutter(uint32_t frame_number,nsecs_t timestamp)426 void VsockCameraDeviceSession::notifyShutter(uint32_t frame_number,
427 nsecs_t timestamp) {
428 NotifyMsg msg;
429 msg.type = MsgType::SHUTTER;
430 msg.msg.shutter.frameNumber = frame_number;
431 msg.msg.shutter.timestamp = timestamp;
432 callback_->notify({msg});
433 }
434
notifyError(uint32_t frame_number,int32_t stream_id,ErrorCode code)435 void VsockCameraDeviceSession::notifyError(uint32_t frame_number,
436 int32_t stream_id, ErrorCode code) {
437 NotifyMsg msg;
438 msg.type = MsgType::ERROR;
439 msg.msg.error.frameNumber = frame_number;
440 msg.msg.error.errorStreamId = stream_id;
441 msg.msg.error.errorCode = code;
442 callback_->notify({msg});
443 }
444
tryWriteFmqResult(V3_2::CaptureResult & result)445 void VsockCameraDeviceSession::tryWriteFmqResult(V3_2::CaptureResult& result) {
446 result.fmqResultSize = 0;
447 if (result_queue_->availableToWrite() == 0 || result.result.size() == 0) {
448 return;
449 }
450 if (result_queue_->write(result.result.data(), result.result.size())) {
451 result.fmqResultSize = result.result.size();
452 result.result.resize(0);
453 }
454 }
455
456 using ::android::hardware::camera::device::V3_2::BufferStatus;
457 using ::android::hardware::graphics::common::V1_0::PixelFormat;
processRequestLoop(unsigned int wait_timeout_ms)458 void VsockCameraDeviceSession::processRequestLoop(
459 unsigned int wait_timeout_ms) {
460 while (process_requests_.load()) {
461 ReadVsockRequest request;
462 if (!getRequestFromQueue(request, wait_timeout_ms)) {
463 continue;
464 }
465 if (!frame_provider_->isRunning()) {
466 notifyError(request.frame_number, -1, ErrorCode::ERROR_DEVICE);
467 break;
468 }
469 frame_provider_->waitYUVFrame(wait_timeout_ms);
470 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
471 if (request.timestamp == 0) {
472 request.timestamp = now;
473 notifyShutter(request.frame_number, request.timestamp);
474 }
475 std::vector<ReleaseFence> release_fences;
476 std::vector<StreamBuffer> result_buffers;
477 std::vector<uint64_t> pending_buffers;
478 bool request_ok = true;
479 for (auto buffer_id : request.buffer_ids) {
480 auto buffer = buffer_cache_.get(buffer_id);
481 auto stream_id = buffer ? buffer->streamId() : -1;
482 if (!buffer || stream_cache_.count(stream_id) == 0) {
483 ALOGE("%s: Invalid buffer", __FUNCTION__);
484 notifyError(request.frame_number, -1, ErrorCode::ERROR_REQUEST);
485 request_ok = false;
486 break;
487 }
488 bool has_result = false;
489 auto stream = stream_cache_[stream_id];
490 if (flushing_requests_.load()) {
491 has_result = false;
492 release_fences.emplace_back(buffer->acquireFence());
493 } else if (stream.format == PixelFormat::YCBCR_420_888 ||
494 stream.format == PixelFormat::IMPLEMENTATION_DEFINED) {
495 auto dst_yuv =
496 buffer->acquireAsYUV(stream.width, stream.height, wait_timeout_ms);
497 has_result =
498 frame_provider_->copyYUVFrame(stream.width, stream.height, dst_yuv);
499 release_fences.emplace_back(buffer->release());
500 } else if (stream.format == PixelFormat::BLOB) {
501 auto time_elapsed = now - request.timestamp;
502 if (time_elapsed == 0) {
503 frame_provider_->requestJpeg();
504 pending_buffers.push_back(buffer_id);
505 continue;
506 } else if (frame_provider_->jpegPending()) {
507 static constexpr auto kMaxWaitNs = 2000000000L;
508 if (time_elapsed < kMaxWaitNs) {
509 pending_buffers.push_back(buffer_id);
510 continue;
511 }
512 ALOGE("%s: Blob request timed out after %" PRId64 "ms", __FUNCTION__,
513 ns2ms(time_elapsed));
514 frame_provider_->cancelJpegRequest();
515 has_result = false;
516 release_fences.emplace_back(buffer->acquireFence());
517 notifyError(request.frame_number, buffer->streamId(),
518 ErrorCode::ERROR_BUFFER);
519 } else {
520 ALOGI("%s: Blob ready - capture duration=%" PRId64 "ms", __FUNCTION__,
521 ns2ms(time_elapsed));
522 auto dst_blob =
523 buffer->acquireAsBlob(max_blob_size_, wait_timeout_ms);
524 has_result = frame_provider_->copyJpegData(max_blob_size_, dst_blob);
525 release_fences.emplace_back(buffer->release());
526 }
527 } else {
528 ALOGE("%s: Format %d not supported", __FUNCTION__, stream.format);
529 has_result = false;
530 release_fences.emplace_back(buffer->acquireFence());
531 notifyError(request.frame_number, buffer->streamId(),
532 ErrorCode::ERROR_BUFFER);
533 }
534 result_buffers.push_back(
535 {.streamId = buffer->streamId(),
536 .bufferId = buffer->bufferId(),
537 .buffer = nullptr,
538 .status = has_result ? BufferStatus::OK : BufferStatus::ERROR,
539 .releaseFence = release_fences.back().handle()});
540 }
541 if (!request_ok) {
542 continue;
543 }
544
545 V3_2::CaptureResult result;
546 bool results_filled = request.settings.exists(ANDROID_SENSOR_TIMESTAMP);
547 if (!results_filled) {
548 fillCaptureResult(request.settings, request.timestamp);
549 const camera_metadata_t* metadata = request.settings.getAndLock();
550 V3_2::implementation::convertToHidl(metadata, &result.result);
551 request.settings.unlock(metadata);
552 tryWriteFmqResult(result);
553 }
554 if (!result_buffers.empty() || !results_filled) {
555 result.frameNumber = request.frame_number;
556 result.partialResult = !results_filled ? 1 : 0;
557 result.inputBuffer.streamId = -1;
558 result.outputBuffers = result_buffers;
559 std::vector<V3_2::CaptureResult> results{result};
560 auto status = callback_->processCaptureResult(results);
561 release_fences.clear();
562 if (!status.isOk()) {
563 ALOGE("%s: processCaptureResult error: %s", __FUNCTION__,
564 status.description().c_str());
565 }
566 }
567 if (!pending_buffers.empty()) {
568 // some buffers still pending
569 request.buffer_ids = pending_buffers;
570 putRequestToQueue(request);
571 }
572 }
573 }
574
575 } // namespace android::hardware::camera::device::V3_4::implementation
576