blob: ad7f6f515e7aa70c242bf1170f4046e369d7d1ac [file] [log] [blame]
Emilian Peeve18057b2017-11-13 16:03:44 +00001/*
Shuzhen Wang82e36b32017-11-28 17:00:43 -08002 * Copyright (C) 2017-2018 The Android Open Source Project
Emilian Peeve18057b2017-11-13 16:03:44 +00003 *
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
17#define LOG_TAG "CamDevSession@3.4-impl"
18#include <android/log.h>
19
20#include <set>
21#include <utils/Trace.h>
22#include <hardware/gralloc.h>
23#include <hardware/gralloc1.h>
24#include "CameraDeviceSession.h"
25
26namespace android {
27namespace hardware {
28namespace camera {
29namespace device {
30namespace V3_4 {
31namespace implementation {
32
33CameraDeviceSession::CameraDeviceSession(
34 camera3_device_t* device,
35 const camera_metadata_t* deviceInfo,
36 const sp<V3_2::ICameraDeviceCallback>& callback) :
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080037 V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback),
38 mResultBatcher_3_4(callback) {
39
40 mHasCallback_3_4 = false;
41
42 auto castResult = ICameraDeviceCallback::castFrom(callback);
43 if (castResult.isOk()) {
44 sp<ICameraDeviceCallback> callback3_4 = castResult;
45 if (callback3_4 != nullptr) {
46 process_capture_result = sProcessCaptureResult_3_4;
47 notify = sNotify_3_4;
48 mHasCallback_3_4 = true;
49 if (!mInitFail) {
50 mResultBatcher_3_4.setResultMetadataQueue(mResultMetadataQueue);
51 }
52 }
53 }
Emilian Peeve18057b2017-11-13 16:03:44 +000054}
55
56CameraDeviceSession::~CameraDeviceSession() {
57}
58
59Return<void> CameraDeviceSession::configureStreams_3_4(
Shuzhen Wang82e36b32017-11-28 17:00:43 -080060 const StreamConfiguration& requestedConfiguration,
61 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
Emilian Peeve18057b2017-11-13 16:03:44 +000062 Status status = initStatus();
63 HalStreamConfiguration outStreams;
64
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080065 // If callback is 3.2, make sure no physical stream is configured
66 if (!mHasCallback_3_4) {
67 for (size_t i = 0; i < requestedConfiguration.streams.size(); i++) {
68 if (requestedConfiguration.streams[i].physicalCameraId.size() > 0) {
69 ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
70 __FUNCTION__);
71 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
72 return Void();
73 }
74 }
75 }
76
Emilian Peeve18057b2017-11-13 16:03:44 +000077 // hold the inflight lock for entire configureStreams scope since there must not be any
78 // inflight request/results during stream configuration.
79 Mutex::Autolock _l(mInflightLock);
80 if (!mInflightBuffers.empty()) {
81 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
82 __FUNCTION__, mInflightBuffers.size());
83 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
84 return Void();
85 }
86
87 if (!mInflightAETriggerOverrides.empty()) {
88 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
89 " trigger overrides!", __FUNCTION__,
90 mInflightAETriggerOverrides.size());
91 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
92 return Void();
93 }
94
95 if (!mInflightRawBoostPresent.empty()) {
96 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
97 " boost overrides!", __FUNCTION__,
98 mInflightRawBoostPresent.size());
99 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
100 return Void();
101 }
102
103 if (status != Status::OK) {
104 _hidl_cb(status, outStreams);
105 return Void();
106 }
107
108 const camera_metadata_t *paramBuffer = nullptr;
109 if (0 < requestedConfiguration.sessionParams.size()) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000110 V3_2::implementation::convertFromHidl(requestedConfiguration.sessionParams, &paramBuffer);
111 }
112
113 camera3_stream_configuration_t stream_list{};
114 hidl_vec<camera3_stream_t*> streams;
115 stream_list.session_parameters = paramBuffer;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800116 if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000117 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
118 return Void();
119 }
120
121 ATRACE_BEGIN("camera3->configure_streams");
122 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
123 ATRACE_END();
124
125 // In case Hal returns error most likely it was not able to release
126 // the corresponding resources of the deleted streams.
127 if (ret == OK) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800128 postProcessConfigurationLocked_3_4(requestedConfiguration);
Emilian Peeve18057b2017-11-13 16:03:44 +0000129 }
130
131 if (ret == -EINVAL) {
132 status = Status::ILLEGAL_ARGUMENT;
133 } else if (ret != OK) {
134 status = Status::INTERNAL_ERROR;
135 } else {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800136 V3_4::implementation::convertToHidl(stream_list, &outStreams);
Emilian Peeve18057b2017-11-13 16:03:44 +0000137 mFirstRequest = true;
138 }
139
140 _hidl_cb(status, outStreams);
141 return Void();
142}
143
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800144bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
145 const StreamConfiguration& requestedConfiguration,
146 camera3_stream_configuration_t *stream_list /*out*/,
147 hidl_vec<camera3_stream_t*> *streams /*out*/) {
148
149 if ((stream_list == nullptr) || (streams == nullptr)) {
150 return false;
151 }
152
153 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
154 stream_list->num_streams = requestedConfiguration.streams.size();
155 streams->resize(stream_list->num_streams);
156 stream_list->streams = streams->data();
157
158 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
159 int id = requestedConfiguration.streams[i].v3_2.id;
160
161 if (mStreamMap.count(id) == 0) {
162 Camera3Stream stream;
163 convertFromHidl(requestedConfiguration.streams[i], &stream);
164 mStreamMap[id] = stream;
165 mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
166 mStreamMap[id].data_space = mapToLegacyDataspace(
167 mStreamMap[id].data_space);
168 mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
169 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
170 } else {
171 // width/height/format must not change, but usage/rotation might need to change
172 if (mStreamMap[id].stream_type !=
173 (int) requestedConfiguration.streams[i].v3_2.streamType ||
174 mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
175 mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
176 mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
177 mStreamMap[id].data_space !=
178 mapToLegacyDataspace( static_cast<android_dataspace_t> (
179 requestedConfiguration.streams[i].v3_2.dataSpace)) ||
180 mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
181 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
182 return false;
183 }
184 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
185 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
186 }
187 (*streams)[i] = &mStreamMap[id];
188 }
189
190 return true;
191}
192
193void CameraDeviceSession::postProcessConfigurationLocked_3_4(
194 const StreamConfiguration& requestedConfiguration) {
195 // delete unused streams, note we do this after adding new streams to ensure new stream
196 // will not have the same address as deleted stream, and HAL has a chance to reference
197 // the to be deleted stream in configure_streams call
198 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
199 int id = it->first;
200 bool found = false;
201 for (const auto& stream : requestedConfiguration.streams) {
202 if (id == stream.v3_2.id) {
203 found = true;
204 break;
205 }
206 }
207 if (!found) {
208 // Unmap all buffers of deleted stream
209 // in case the configuration call succeeds and HAL
210 // is able to release the corresponding resources too.
211 cleanupBuffersLocked(id);
212 it = mStreamMap.erase(it);
213 } else {
214 ++it;
215 }
216 }
217
218 // Track video streams
219 mVideoStreamIds.clear();
220 for (const auto& stream : requestedConfiguration.streams) {
221 if (stream.v3_2.streamType == StreamType::OUTPUT &&
222 stream.v3_2.usage &
223 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
224 mVideoStreamIds.push_back(stream.v3_2.id);
225 }
226 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800227 mResultBatcher_3_4.setBatchedStreams(mVideoStreamIds);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800228}
229
230Return<void> CameraDeviceSession::processCaptureRequest_3_4(
Emilian Peevb75aa352018-01-17 11:00:54 +0000231 const hidl_vec<V3_4::CaptureRequest>& requests,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800232 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
Emilian Peevb75aa352018-01-17 11:00:54 +0000233 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800234 updateBufferCaches(cachesToRemove);
235
236 uint32_t numRequestProcessed = 0;
237 Status s = Status::OK;
238 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
239 s = processOneCaptureRequest_3_4(requests[i]);
240 if (s != Status::OK) {
241 break;
242 }
243 }
244
245 if (s == Status::OK && requests.size() > 1) {
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800246 mResultBatcher_3_4.registerBatch(requests[0].v3_2.frameNumber, requests.size());
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800247 }
248
249 _hidl_cb(s, numRequestProcessed);
250 return Void();
251}
252
Emilian Peevb75aa352018-01-17 11:00:54 +0000253Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800254 Status status = initStatus();
255 if (status != Status::OK) {
256 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
257 return status;
258 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800259 // If callback is 3.2, make sure there are no physical settings.
260 if (!mHasCallback_3_4) {
261 if (request.physicalCameraSettings.size() > 0) {
262 ALOGE("%s: trying to call processCaptureRequest_3_4 with physical camera id "
263 "and V3.2 callback", __FUNCTION__);
264 return Status::INTERNAL_ERROR;
265 }
266 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800267
268 camera3_capture_request_t halRequest;
Emilian Peevb75aa352018-01-17 11:00:54 +0000269 halRequest.frame_number = request.v3_2.frameNumber;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800270
271 bool converted = true;
272 V3_2::CameraMetadata settingsFmq; // settings from FMQ
Emilian Peevb75aa352018-01-17 11:00:54 +0000273 if (request.v3_2.fmqSettingsSize > 0) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800274 // non-blocking read; client must write metadata before calling
275 // processOneCaptureRequest
Emilian Peevb75aa352018-01-17 11:00:54 +0000276 settingsFmq.resize(request.v3_2.fmqSettingsSize);
277 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800278 if (read) {
279 converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
280 } else {
281 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
282 converted = false;
283 }
284 } else {
Emilian Peevb75aa352018-01-17 11:00:54 +0000285 converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
286 &halRequest.settings);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800287 }
288
289 if (!converted) {
290 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
291 return Status::ILLEGAL_ARGUMENT;
292 }
293
294 if (mFirstRequest && halRequest.settings == nullptr) {
295 ALOGE("%s: capture request settings must not be null for first request!",
296 __FUNCTION__);
297 return Status::ILLEGAL_ARGUMENT;
298 }
299
300 hidl_vec<buffer_handle_t*> allBufPtrs;
301 hidl_vec<int> allFences;
Emilian Peevb75aa352018-01-17 11:00:54 +0000302 bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
303 request.v3_2.inputBuffer.bufferId != 0);
304 size_t numOutputBufs = request.v3_2.outputBuffers.size();
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800305 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
306
307 if (numOutputBufs == 0) {
308 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
309 return Status::ILLEGAL_ARGUMENT;
310 }
311
Emilian Peevb75aa352018-01-17 11:00:54 +0000312 status = importRequest(request.v3_2, allBufPtrs, allFences);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800313 if (status != Status::OK) {
314 return status;
315 }
316
317 hidl_vec<camera3_stream_buffer_t> outHalBufs;
318 outHalBufs.resize(numOutputBufs);
319 bool aeCancelTriggerNeeded = false;
320 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
321 {
322 Mutex::Autolock _l(mInflightLock);
323 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000324 auto streamId = request.v3_2.inputBuffer.streamId;
325 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800326 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
327 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000328 allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
329 &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800330 &bufCache);
331 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
332 halRequest.input_buffer = &bufCache;
333 } else {
334 halRequest.input_buffer = nullptr;
335 }
336
337 halRequest.num_output_buffers = numOutputBufs;
338 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000339 auto streamId = request.v3_2.outputBuffers[i].streamId;
340 auto key = std::make_pair(streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800341 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
342 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000343 allBufPtrs[i], request.v3_2.outputBuffers[i].status,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800344 &mStreamMap[streamId], allFences[i],
345 &bufCache);
346 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
347 outHalBufs[i] = bufCache;
348 }
349 halRequest.output_buffers = outHalBufs.data();
350
351 AETriggerCancelOverride triggerOverride;
352 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
353 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
354 if (aeCancelTriggerNeeded) {
355 mInflightAETriggerOverrides[halRequest.frame_number] =
356 triggerOverride;
357 halRequest.settings = settingsOverride.getAndLock();
358 }
359 }
360
Emilian Peevb75aa352018-01-17 11:00:54 +0000361 std::vector<const char *> physicalCameraIds;
362 std::vector<const camera_metadata_t *> physicalCameraSettings;
363 std::vector<V3_2::CameraMetadata> physicalFmq;
364 size_t settingsCount = request.physicalCameraSettings.size();
365 if (settingsCount > 0) {
366 physicalCameraIds.reserve(settingsCount);
367 physicalCameraSettings.reserve(settingsCount);
368 physicalFmq.reserve(settingsCount);
369
370 for (size_t i = 0; i < settingsCount; i++) {
371 uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000372 const camera_metadata_t *settings = nullptr;
Emilian Peevb75aa352018-01-17 11:00:54 +0000373 if (settingsSize > 0) {
374 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
375 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
376 if (read) {
377 converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
378 physicalCameraSettings.push_back(settings);
379 } else {
380 ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
381 __FUNCTION__);
382 converted = false;
383 }
384 } else {
385 converted = V3_2::implementation::convertFromHidl(
386 request.physicalCameraSettings[i].settings, &settings);
387 physicalCameraSettings.push_back(settings);
388 }
389
390 if (!converted) {
391 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
392 return Status::ILLEGAL_ARGUMENT;
393 }
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000394
395 if (mFirstRequest && settings == nullptr) {
396 ALOGE("%s: Individual request settings must not be null for first request!",
397 __FUNCTION__);
398 return Status::ILLEGAL_ARGUMENT;
399 }
400
Emilian Peevb75aa352018-01-17 11:00:54 +0000401 physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
402 }
403 }
404 halRequest.num_physcam_settings = settingsCount;
405 halRequest.physcam_id = physicalCameraIds.data();
406 halRequest.physcam_settings = physicalCameraSettings.data();
407
408 ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800409 ATRACE_BEGIN("camera3->process_capture_request");
410 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
411 ATRACE_END();
412 if (aeCancelTriggerNeeded) {
413 settingsOverride.unlock(halRequest.settings);
414 }
415 if (ret != OK) {
416 Mutex::Autolock _l(mInflightLock);
417 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
418
419 cleanupInflightFences(allFences, numBufs);
420 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000421 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800422 mInflightBuffers.erase(key);
423 }
424 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000425 auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
426 request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800427 mInflightBuffers.erase(key);
428 }
429 if (aeCancelTriggerNeeded) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000430 mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800431 }
Emilian Peevb75aa352018-01-17 11:00:54 +0000432
433 if (ret == BAD_VALUE) {
434 return Status::ILLEGAL_ARGUMENT;
435 } else {
436 return Status::INTERNAL_ERROR;
437 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800438 }
439
440 mFirstRequest = false;
441 return Status::OK;
442}
443
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800444/**
445 * Static callback forwarding methods from HAL to instance
446 */
447void CameraDeviceSession::sProcessCaptureResult_3_4(
448 const camera3_callback_ops *cb,
449 const camera3_capture_result *hal_result) {
450 CameraDeviceSession *d =
451 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
452
Shuzhen Wang17d817a2018-03-09 15:58:43 -0800453 CaptureResult result = {};
454 status_t ret = d->constructCaptureResult(result.v3_2, hal_result);
455 if (ret != OK) {
456 return;
457 }
458
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800459 result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
460 for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
461 std::string physicalId = hal_result->physcam_ids[i];
462 V3_2::CameraMetadata physicalMetadata;
463 V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
464 PhysicalCameraMetadata physicalCameraMetadata = {
465 .fmqMetadataSize = 0,
466 .physicalCameraId = physicalId,
467 .metadata = physicalMetadata };
468 result.physicalCameraMetadata[i] = physicalCameraMetadata;
469 }
470 d->mResultBatcher_3_4.processCaptureResult_3_4(result);
471}
472
473void CameraDeviceSession::sNotify_3_4(
474 const camera3_callback_ops *cb,
475 const camera3_notify_msg *msg) {
476 CameraDeviceSession *d =
477 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
478 V3_2::NotifyMsg hidlMsg;
479 V3_2::implementation::convertToHidl(msg, &hidlMsg);
480
481 if (hidlMsg.type == (V3_2::MsgType) CAMERA3_MSG_ERROR &&
482 hidlMsg.msg.error.errorStreamId != -1) {
483 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
484 ALOGE("%s: unknown stream ID %d reports an error!",
485 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
486 return;
487 }
488 }
489
490 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
491 switch (hidlMsg.msg.error.errorCode) {
492 case V3_2::ErrorCode::ERROR_DEVICE:
493 case V3_2::ErrorCode::ERROR_REQUEST:
494 case V3_2::ErrorCode::ERROR_RESULT: {
495 Mutex::Autolock _l(d->mInflightLock);
496 auto entry = d->mInflightAETriggerOverrides.find(
497 hidlMsg.msg.error.frameNumber);
498 if (d->mInflightAETriggerOverrides.end() != entry) {
499 d->mInflightAETriggerOverrides.erase(
500 hidlMsg.msg.error.frameNumber);
501 }
502
503 auto boostEntry = d->mInflightRawBoostPresent.find(
504 hidlMsg.msg.error.frameNumber);
505 if (d->mInflightRawBoostPresent.end() != boostEntry) {
506 d->mInflightRawBoostPresent.erase(
507 hidlMsg.msg.error.frameNumber);
508 }
509
510 }
511 break;
512 case V3_2::ErrorCode::ERROR_BUFFER:
513 default:
514 break;
515 }
516
517 }
518
519 d->mResultBatcher_3_4.notify(hidlMsg);
520}
521
522CameraDeviceSession::ResultBatcher_3_4::ResultBatcher_3_4(
523 const sp<V3_2::ICameraDeviceCallback>& callback) :
524 V3_3::implementation::CameraDeviceSession::ResultBatcher(callback) {
525 auto castResult = ICameraDeviceCallback::castFrom(callback);
526 if (castResult.isOk()) {
527 mCallback_3_4 = castResult;
528 }
529}
530
531void CameraDeviceSession::ResultBatcher_3_4::processCaptureResult_3_4(CaptureResult& result) {
532 auto pair = getBatch(result.v3_2.frameNumber);
533 int batchIdx = pair.first;
534 if (batchIdx == NOT_BATCHED) {
535 processOneCaptureResult_3_4(result);
536 return;
537 }
538 std::shared_ptr<InflightBatch> batch = pair.second;
539 {
540 Mutex::Autolock _l(batch->mLock);
541 // Check if the batch is removed (mostly by notify error) before lock was acquired
542 if (batch->mRemoved) {
543 // Fall back to non-batch path
544 processOneCaptureResult_3_4(result);
545 return;
546 }
547
548 // queue metadata
549 if (result.v3_2.result.size() != 0) {
550 // Save a copy of metadata
551 batch->mResultMds[result.v3_2.partialResult].mMds.push_back(
552 std::make_pair(result.v3_2.frameNumber, result.v3_2.result));
553 }
554
555 // queue buffer
556 std::vector<int> filledStreams;
557 std::vector<V3_2::StreamBuffer> nonBatchedBuffers;
558 for (auto& buffer : result.v3_2.outputBuffers) {
559 auto it = batch->mBatchBufs.find(buffer.streamId);
560 if (it != batch->mBatchBufs.end()) {
561 InflightBatch::BufferBatch& bb = it->second;
562 pushStreamBuffer(std::move(buffer), bb.mBuffers);
563 filledStreams.push_back(buffer.streamId);
564 } else {
565 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
566 }
567 }
568
569 // send non-batched buffers up
570 if (nonBatchedBuffers.size() > 0 || result.v3_2.inputBuffer.streamId != -1) {
571 CaptureResult nonBatchedResult;
572 nonBatchedResult.v3_2.frameNumber = result.v3_2.frameNumber;
573 nonBatchedResult.v3_2.fmqResultSize = 0;
574 nonBatchedResult.v3_2.outputBuffers.resize(nonBatchedBuffers.size());
575 for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
576 moveStreamBuffer(
577 std::move(nonBatchedBuffers[i]), nonBatchedResult.v3_2.outputBuffers[i]);
578 }
579 moveStreamBuffer(std::move(result.v3_2.inputBuffer), nonBatchedResult.v3_2.inputBuffer);
580 nonBatchedResult.v3_2.partialResult = 0; // 0 for buffer only results
581 processOneCaptureResult_3_4(nonBatchedResult);
582 }
583
584 if (result.v3_2.frameNumber == batch->mLastFrame) {
585 // Send data up
586 if (result.v3_2.partialResult > 0) {
587 sendBatchMetadataLocked(batch, result.v3_2.partialResult);
588 }
589 // send buffer up
590 if (filledStreams.size() > 0) {
591 sendBatchBuffersLocked(batch, filledStreams);
592 }
593 }
594 } // end of batch lock scope
595
596 // see if the batch is complete
597 if (result.v3_2.frameNumber == batch->mLastFrame) {
598 checkAndRemoveFirstBatch();
599 }
600}
601
602void CameraDeviceSession::ResultBatcher_3_4::processOneCaptureResult_3_4(CaptureResult& result) {
603 hidl_vec<CaptureResult> results;
604 results.resize(1);
605 results[0] = std::move(result);
606 invokeProcessCaptureResultCallback_3_4(results, /* tryWriteFmq */true);
607 freeReleaseFences_3_4(results);
608 return;
609}
610
611void CameraDeviceSession::ResultBatcher_3_4::invokeProcessCaptureResultCallback_3_4(
612 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
613 if (mProcessCaptureResultLock.tryLock() != OK) {
614 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
615 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
616 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
617 __FUNCTION__);
618 return;
619 }
620 }
621 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
622 for (CaptureResult &result : results) {
623 if (result.v3_2.result.size() > 0) {
624 if (mResultMetadataQueue->write(result.v3_2.result.data(),
625 result.v3_2.result.size())) {
626 result.v3_2.fmqResultSize = result.v3_2.result.size();
627 result.v3_2.result.resize(0);
628 } else {
629 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
630 result.v3_2.fmqResultSize = 0;
631 }
632 }
633
634 for (auto& onePhysMetadata : result.physicalCameraMetadata) {
635 if (mResultMetadataQueue->write(onePhysMetadata.metadata.data(),
636 onePhysMetadata.metadata.size())) {
637 onePhysMetadata.fmqMetadataSize = onePhysMetadata.metadata.size();
638 onePhysMetadata.metadata.resize(0);
639 } else {
640 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
641 onePhysMetadata.fmqMetadataSize = 0;
642 }
643 }
644 }
645 }
646 mCallback_3_4->processCaptureResult_3_4(results);
647 mProcessCaptureResultLock.unlock();
648}
649
650void CameraDeviceSession::ResultBatcher_3_4::freeReleaseFences_3_4(hidl_vec<CaptureResult>& results) {
651 for (auto& result : results) {
652 if (result.v3_2.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
653 native_handle_t* handle = const_cast<native_handle_t*>(
654 result.v3_2.inputBuffer.releaseFence.getNativeHandle());
655 native_handle_close(handle);
656 native_handle_delete(handle);
657 }
658 for (auto& buf : result.v3_2.outputBuffers) {
659 if (buf.releaseFence.getNativeHandle() != nullptr) {
660 native_handle_t* handle = const_cast<native_handle_t*>(
661 buf.releaseFence.getNativeHandle());
662 native_handle_close(handle);
663 native_handle_delete(handle);
664 }
665 }
666 }
667 return;
668}
669
Emilian Peeve18057b2017-11-13 16:03:44 +0000670} // namespace implementation
671} // namespace V3_4
672} // namespace device
673} // namespace camera
674} // namespace hardware
675} // namespace android