blob: 423748a197f44ce3c7cbe9f18ca7a3851b80a3d9 [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
Eino-Ville Talvala658d30d2018-01-18 12:55:07 -080059Return<void> CameraDeviceSession::constructDefaultRequestSettings_3_4(
60 RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
61 V3_2::CameraMetadata outMetadata;
62 Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata);
63 _hidl_cb(status, outMetadata);
64 return Void();
65}
66
Emilian Peeve18057b2017-11-13 16:03:44 +000067Return<void> CameraDeviceSession::configureStreams_3_4(
Shuzhen Wang82e36b32017-11-28 17:00:43 -080068 const StreamConfiguration& requestedConfiguration,
69 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
Emilian Peeve18057b2017-11-13 16:03:44 +000070 Status status = initStatus();
71 HalStreamConfiguration outStreams;
72
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080073 // If callback is 3.2, make sure no physical stream is configured
74 if (!mHasCallback_3_4) {
75 for (size_t i = 0; i < requestedConfiguration.streams.size(); i++) {
76 if (requestedConfiguration.streams[i].physicalCameraId.size() > 0) {
77 ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
78 __FUNCTION__);
79 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
80 return Void();
81 }
82 }
83 }
84
Emilian Peeve18057b2017-11-13 16:03:44 +000085 // hold the inflight lock for entire configureStreams scope since there must not be any
86 // inflight request/results during stream configuration.
87 Mutex::Autolock _l(mInflightLock);
88 if (!mInflightBuffers.empty()) {
89 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
90 __FUNCTION__, mInflightBuffers.size());
91 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
92 return Void();
93 }
94
95 if (!mInflightAETriggerOverrides.empty()) {
96 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
97 " trigger overrides!", __FUNCTION__,
98 mInflightAETriggerOverrides.size());
99 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
100 return Void();
101 }
102
103 if (!mInflightRawBoostPresent.empty()) {
104 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
105 " boost overrides!", __FUNCTION__,
106 mInflightRawBoostPresent.size());
107 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
108 return Void();
109 }
110
111 if (status != Status::OK) {
112 _hidl_cb(status, outStreams);
113 return Void();
114 }
115
116 const camera_metadata_t *paramBuffer = nullptr;
117 if (0 < requestedConfiguration.sessionParams.size()) {
118 ::android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams;
119 V3_2::implementation::convertFromHidl(requestedConfiguration.sessionParams, &paramBuffer);
120 }
121
122 camera3_stream_configuration_t stream_list{};
123 hidl_vec<camera3_stream_t*> streams;
124 stream_list.session_parameters = paramBuffer;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800125 if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000126 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
127 return Void();
128 }
129
130 ATRACE_BEGIN("camera3->configure_streams");
131 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
132 ATRACE_END();
133
134 // In case Hal returns error most likely it was not able to release
135 // the corresponding resources of the deleted streams.
136 if (ret == OK) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800137 postProcessConfigurationLocked_3_4(requestedConfiguration);
Emilian Peeve18057b2017-11-13 16:03:44 +0000138 }
139
140 if (ret == -EINVAL) {
141 status = Status::ILLEGAL_ARGUMENT;
142 } else if (ret != OK) {
143 status = Status::INTERNAL_ERROR;
144 } else {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800145 V3_4::implementation::convertToHidl(stream_list, &outStreams);
Emilian Peeve18057b2017-11-13 16:03:44 +0000146 mFirstRequest = true;
147 }
148
149 _hidl_cb(status, outStreams);
150 return Void();
151}
152
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800153bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
154 const StreamConfiguration& requestedConfiguration,
155 camera3_stream_configuration_t *stream_list /*out*/,
156 hidl_vec<camera3_stream_t*> *streams /*out*/) {
157
158 if ((stream_list == nullptr) || (streams == nullptr)) {
159 return false;
160 }
161
162 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
163 stream_list->num_streams = requestedConfiguration.streams.size();
164 streams->resize(stream_list->num_streams);
165 stream_list->streams = streams->data();
166
167 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
168 int id = requestedConfiguration.streams[i].v3_2.id;
169
170 if (mStreamMap.count(id) == 0) {
171 Camera3Stream stream;
172 convertFromHidl(requestedConfiguration.streams[i], &stream);
173 mStreamMap[id] = stream;
174 mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
175 mStreamMap[id].data_space = mapToLegacyDataspace(
176 mStreamMap[id].data_space);
177 mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
178 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
179 } else {
180 // width/height/format must not change, but usage/rotation might need to change
181 if (mStreamMap[id].stream_type !=
182 (int) requestedConfiguration.streams[i].v3_2.streamType ||
183 mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
184 mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
185 mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
186 mStreamMap[id].data_space !=
187 mapToLegacyDataspace( static_cast<android_dataspace_t> (
188 requestedConfiguration.streams[i].v3_2.dataSpace)) ||
189 mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
190 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
191 return false;
192 }
193 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
194 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
195 }
196 (*streams)[i] = &mStreamMap[id];
197 }
198
199 return true;
200}
201
202void CameraDeviceSession::postProcessConfigurationLocked_3_4(
203 const StreamConfiguration& requestedConfiguration) {
204 // delete unused streams, note we do this after adding new streams to ensure new stream
205 // will not have the same address as deleted stream, and HAL has a chance to reference
206 // the to be deleted stream in configure_streams call
207 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
208 int id = it->first;
209 bool found = false;
210 for (const auto& stream : requestedConfiguration.streams) {
211 if (id == stream.v3_2.id) {
212 found = true;
213 break;
214 }
215 }
216 if (!found) {
217 // Unmap all buffers of deleted stream
218 // in case the configuration call succeeds and HAL
219 // is able to release the corresponding resources too.
220 cleanupBuffersLocked(id);
221 it = mStreamMap.erase(it);
222 } else {
223 ++it;
224 }
225 }
226
227 // Track video streams
228 mVideoStreamIds.clear();
229 for (const auto& stream : requestedConfiguration.streams) {
230 if (stream.v3_2.streamType == StreamType::OUTPUT &&
231 stream.v3_2.usage &
232 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
233 mVideoStreamIds.push_back(stream.v3_2.id);
234 }
235 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800236 mResultBatcher_3_4.setBatchedStreams(mVideoStreamIds);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800237}
238
239Return<void> CameraDeviceSession::processCaptureRequest_3_4(
Emilian Peevb75aa352018-01-17 11:00:54 +0000240 const hidl_vec<V3_4::CaptureRequest>& requests,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800241 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
Emilian Peevb75aa352018-01-17 11:00:54 +0000242 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800243 updateBufferCaches(cachesToRemove);
244
245 uint32_t numRequestProcessed = 0;
246 Status s = Status::OK;
247 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
248 s = processOneCaptureRequest_3_4(requests[i]);
249 if (s != Status::OK) {
250 break;
251 }
252 }
253
254 if (s == Status::OK && requests.size() > 1) {
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800255 mResultBatcher_3_4.registerBatch(requests[0].v3_2.frameNumber, requests.size());
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800256 }
257
258 _hidl_cb(s, numRequestProcessed);
259 return Void();
260}
261
Emilian Peevb75aa352018-01-17 11:00:54 +0000262Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800263 Status status = initStatus();
264 if (status != Status::OK) {
265 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
266 return status;
267 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800268 // If callback is 3.2, make sure there are no physical settings.
269 if (!mHasCallback_3_4) {
270 if (request.physicalCameraSettings.size() > 0) {
271 ALOGE("%s: trying to call processCaptureRequest_3_4 with physical camera id "
272 "and V3.2 callback", __FUNCTION__);
273 return Status::INTERNAL_ERROR;
274 }
275 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800276
277 camera3_capture_request_t halRequest;
Emilian Peevb75aa352018-01-17 11:00:54 +0000278 halRequest.frame_number = request.v3_2.frameNumber;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800279
280 bool converted = true;
281 V3_2::CameraMetadata settingsFmq; // settings from FMQ
Emilian Peevb75aa352018-01-17 11:00:54 +0000282 if (request.v3_2.fmqSettingsSize > 0) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800283 // non-blocking read; client must write metadata before calling
284 // processOneCaptureRequest
Emilian Peevb75aa352018-01-17 11:00:54 +0000285 settingsFmq.resize(request.v3_2.fmqSettingsSize);
286 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800287 if (read) {
288 converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
289 } else {
290 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
291 converted = false;
292 }
293 } else {
Emilian Peevb75aa352018-01-17 11:00:54 +0000294 converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
295 &halRequest.settings);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800296 }
297
298 if (!converted) {
299 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
300 return Status::ILLEGAL_ARGUMENT;
301 }
302
303 if (mFirstRequest && halRequest.settings == nullptr) {
304 ALOGE("%s: capture request settings must not be null for first request!",
305 __FUNCTION__);
306 return Status::ILLEGAL_ARGUMENT;
307 }
308
309 hidl_vec<buffer_handle_t*> allBufPtrs;
310 hidl_vec<int> allFences;
Emilian Peevb75aa352018-01-17 11:00:54 +0000311 bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
312 request.v3_2.inputBuffer.bufferId != 0);
313 size_t numOutputBufs = request.v3_2.outputBuffers.size();
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800314 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
315
316 if (numOutputBufs == 0) {
317 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
318 return Status::ILLEGAL_ARGUMENT;
319 }
320
Emilian Peevb75aa352018-01-17 11:00:54 +0000321 status = importRequest(request.v3_2, allBufPtrs, allFences);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800322 if (status != Status::OK) {
323 return status;
324 }
325
326 hidl_vec<camera3_stream_buffer_t> outHalBufs;
327 outHalBufs.resize(numOutputBufs);
328 bool aeCancelTriggerNeeded = false;
329 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
330 {
331 Mutex::Autolock _l(mInflightLock);
332 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000333 auto streamId = request.v3_2.inputBuffer.streamId;
334 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800335 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
336 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000337 allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
338 &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800339 &bufCache);
340 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
341 halRequest.input_buffer = &bufCache;
342 } else {
343 halRequest.input_buffer = nullptr;
344 }
345
346 halRequest.num_output_buffers = numOutputBufs;
347 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000348 auto streamId = request.v3_2.outputBuffers[i].streamId;
349 auto key = std::make_pair(streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800350 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
351 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000352 allBufPtrs[i], request.v3_2.outputBuffers[i].status,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800353 &mStreamMap[streamId], allFences[i],
354 &bufCache);
355 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
356 outHalBufs[i] = bufCache;
357 }
358 halRequest.output_buffers = outHalBufs.data();
359
360 AETriggerCancelOverride triggerOverride;
361 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
362 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
363 if (aeCancelTriggerNeeded) {
364 mInflightAETriggerOverrides[halRequest.frame_number] =
365 triggerOverride;
366 halRequest.settings = settingsOverride.getAndLock();
367 }
368 }
369
Emilian Peevb75aa352018-01-17 11:00:54 +0000370 std::vector<const char *> physicalCameraIds;
371 std::vector<const camera_metadata_t *> physicalCameraSettings;
372 std::vector<V3_2::CameraMetadata> physicalFmq;
373 size_t settingsCount = request.physicalCameraSettings.size();
374 if (settingsCount > 0) {
375 physicalCameraIds.reserve(settingsCount);
376 physicalCameraSettings.reserve(settingsCount);
377 physicalFmq.reserve(settingsCount);
378
379 for (size_t i = 0; i < settingsCount; i++) {
380 uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000381 const camera_metadata_t *settings = nullptr;
Emilian Peevb75aa352018-01-17 11:00:54 +0000382 if (settingsSize > 0) {
383 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
384 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
385 if (read) {
386 converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
387 physicalCameraSettings.push_back(settings);
388 } else {
389 ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
390 __FUNCTION__);
391 converted = false;
392 }
393 } else {
394 converted = V3_2::implementation::convertFromHidl(
395 request.physicalCameraSettings[i].settings, &settings);
396 physicalCameraSettings.push_back(settings);
397 }
398
399 if (!converted) {
400 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
401 return Status::ILLEGAL_ARGUMENT;
402 }
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000403
404 if (mFirstRequest && settings == nullptr) {
405 ALOGE("%s: Individual request settings must not be null for first request!",
406 __FUNCTION__);
407 return Status::ILLEGAL_ARGUMENT;
408 }
409
Emilian Peevb75aa352018-01-17 11:00:54 +0000410 physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
411 }
412 }
413 halRequest.num_physcam_settings = settingsCount;
414 halRequest.physcam_id = physicalCameraIds.data();
415 halRequest.physcam_settings = physicalCameraSettings.data();
416
417 ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800418 ATRACE_BEGIN("camera3->process_capture_request");
419 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
420 ATRACE_END();
421 if (aeCancelTriggerNeeded) {
422 settingsOverride.unlock(halRequest.settings);
423 }
424 if (ret != OK) {
425 Mutex::Autolock _l(mInflightLock);
426 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
427
428 cleanupInflightFences(allFences, numBufs);
429 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000430 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800431 mInflightBuffers.erase(key);
432 }
433 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000434 auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
435 request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800436 mInflightBuffers.erase(key);
437 }
438 if (aeCancelTriggerNeeded) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000439 mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800440 }
Emilian Peevb75aa352018-01-17 11:00:54 +0000441
442 if (ret == BAD_VALUE) {
443 return Status::ILLEGAL_ARGUMENT;
444 } else {
445 return Status::INTERNAL_ERROR;
446 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800447 }
448
449 mFirstRequest = false;
450 return Status::OK;
451}
452
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800453/**
454 * Static callback forwarding methods from HAL to instance
455 */
456void CameraDeviceSession::sProcessCaptureResult_3_4(
457 const camera3_callback_ops *cb,
458 const camera3_capture_result *hal_result) {
459 CameraDeviceSession *d =
460 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
461
462 CaptureResult result;
463 d->constructCaptureResult(result.v3_2, hal_result);
464 result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
465 for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
466 std::string physicalId = hal_result->physcam_ids[i];
467 V3_2::CameraMetadata physicalMetadata;
468 V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
469 PhysicalCameraMetadata physicalCameraMetadata = {
470 .fmqMetadataSize = 0,
471 .physicalCameraId = physicalId,
472 .metadata = physicalMetadata };
473 result.physicalCameraMetadata[i] = physicalCameraMetadata;
474 }
475 d->mResultBatcher_3_4.processCaptureResult_3_4(result);
476}
477
478void CameraDeviceSession::sNotify_3_4(
479 const camera3_callback_ops *cb,
480 const camera3_notify_msg *msg) {
481 CameraDeviceSession *d =
482 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
483 V3_2::NotifyMsg hidlMsg;
484 V3_2::implementation::convertToHidl(msg, &hidlMsg);
485
486 if (hidlMsg.type == (V3_2::MsgType) CAMERA3_MSG_ERROR &&
487 hidlMsg.msg.error.errorStreamId != -1) {
488 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
489 ALOGE("%s: unknown stream ID %d reports an error!",
490 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
491 return;
492 }
493 }
494
495 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
496 switch (hidlMsg.msg.error.errorCode) {
497 case V3_2::ErrorCode::ERROR_DEVICE:
498 case V3_2::ErrorCode::ERROR_REQUEST:
499 case V3_2::ErrorCode::ERROR_RESULT: {
500 Mutex::Autolock _l(d->mInflightLock);
501 auto entry = d->mInflightAETriggerOverrides.find(
502 hidlMsg.msg.error.frameNumber);
503 if (d->mInflightAETriggerOverrides.end() != entry) {
504 d->mInflightAETriggerOverrides.erase(
505 hidlMsg.msg.error.frameNumber);
506 }
507
508 auto boostEntry = d->mInflightRawBoostPresent.find(
509 hidlMsg.msg.error.frameNumber);
510 if (d->mInflightRawBoostPresent.end() != boostEntry) {
511 d->mInflightRawBoostPresent.erase(
512 hidlMsg.msg.error.frameNumber);
513 }
514
515 }
516 break;
517 case V3_2::ErrorCode::ERROR_BUFFER:
518 default:
519 break;
520 }
521
522 }
523
524 d->mResultBatcher_3_4.notify(hidlMsg);
525}
526
527CameraDeviceSession::ResultBatcher_3_4::ResultBatcher_3_4(
528 const sp<V3_2::ICameraDeviceCallback>& callback) :
529 V3_3::implementation::CameraDeviceSession::ResultBatcher(callback) {
530 auto castResult = ICameraDeviceCallback::castFrom(callback);
531 if (castResult.isOk()) {
532 mCallback_3_4 = castResult;
533 }
534}
535
536void CameraDeviceSession::ResultBatcher_3_4::processCaptureResult_3_4(CaptureResult& result) {
537 auto pair = getBatch(result.v3_2.frameNumber);
538 int batchIdx = pair.first;
539 if (batchIdx == NOT_BATCHED) {
540 processOneCaptureResult_3_4(result);
541 return;
542 }
543 std::shared_ptr<InflightBatch> batch = pair.second;
544 {
545 Mutex::Autolock _l(batch->mLock);
546 // Check if the batch is removed (mostly by notify error) before lock was acquired
547 if (batch->mRemoved) {
548 // Fall back to non-batch path
549 processOneCaptureResult_3_4(result);
550 return;
551 }
552
553 // queue metadata
554 if (result.v3_2.result.size() != 0) {
555 // Save a copy of metadata
556 batch->mResultMds[result.v3_2.partialResult].mMds.push_back(
557 std::make_pair(result.v3_2.frameNumber, result.v3_2.result));
558 }
559
560 // queue buffer
561 std::vector<int> filledStreams;
562 std::vector<V3_2::StreamBuffer> nonBatchedBuffers;
563 for (auto& buffer : result.v3_2.outputBuffers) {
564 auto it = batch->mBatchBufs.find(buffer.streamId);
565 if (it != batch->mBatchBufs.end()) {
566 InflightBatch::BufferBatch& bb = it->second;
567 pushStreamBuffer(std::move(buffer), bb.mBuffers);
568 filledStreams.push_back(buffer.streamId);
569 } else {
570 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
571 }
572 }
573
574 // send non-batched buffers up
575 if (nonBatchedBuffers.size() > 0 || result.v3_2.inputBuffer.streamId != -1) {
576 CaptureResult nonBatchedResult;
577 nonBatchedResult.v3_2.frameNumber = result.v3_2.frameNumber;
578 nonBatchedResult.v3_2.fmqResultSize = 0;
579 nonBatchedResult.v3_2.outputBuffers.resize(nonBatchedBuffers.size());
580 for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
581 moveStreamBuffer(
582 std::move(nonBatchedBuffers[i]), nonBatchedResult.v3_2.outputBuffers[i]);
583 }
584 moveStreamBuffer(std::move(result.v3_2.inputBuffer), nonBatchedResult.v3_2.inputBuffer);
585 nonBatchedResult.v3_2.partialResult = 0; // 0 for buffer only results
586 processOneCaptureResult_3_4(nonBatchedResult);
587 }
588
589 if (result.v3_2.frameNumber == batch->mLastFrame) {
590 // Send data up
591 if (result.v3_2.partialResult > 0) {
592 sendBatchMetadataLocked(batch, result.v3_2.partialResult);
593 }
594 // send buffer up
595 if (filledStreams.size() > 0) {
596 sendBatchBuffersLocked(batch, filledStreams);
597 }
598 }
599 } // end of batch lock scope
600
601 // see if the batch is complete
602 if (result.v3_2.frameNumber == batch->mLastFrame) {
603 checkAndRemoveFirstBatch();
604 }
605}
606
607void CameraDeviceSession::ResultBatcher_3_4::processOneCaptureResult_3_4(CaptureResult& result) {
608 hidl_vec<CaptureResult> results;
609 results.resize(1);
610 results[0] = std::move(result);
611 invokeProcessCaptureResultCallback_3_4(results, /* tryWriteFmq */true);
612 freeReleaseFences_3_4(results);
613 return;
614}
615
616void CameraDeviceSession::ResultBatcher_3_4::invokeProcessCaptureResultCallback_3_4(
617 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
618 if (mProcessCaptureResultLock.tryLock() != OK) {
619 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
620 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
621 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
622 __FUNCTION__);
623 return;
624 }
625 }
626 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
627 for (CaptureResult &result : results) {
628 if (result.v3_2.result.size() > 0) {
629 if (mResultMetadataQueue->write(result.v3_2.result.data(),
630 result.v3_2.result.size())) {
631 result.v3_2.fmqResultSize = result.v3_2.result.size();
632 result.v3_2.result.resize(0);
633 } else {
634 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
635 result.v3_2.fmqResultSize = 0;
636 }
637 }
638
639 for (auto& onePhysMetadata : result.physicalCameraMetadata) {
640 if (mResultMetadataQueue->write(onePhysMetadata.metadata.data(),
641 onePhysMetadata.metadata.size())) {
642 onePhysMetadata.fmqMetadataSize = onePhysMetadata.metadata.size();
643 onePhysMetadata.metadata.resize(0);
644 } else {
645 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
646 onePhysMetadata.fmqMetadataSize = 0;
647 }
648 }
649 }
650 }
651 mCallback_3_4->processCaptureResult_3_4(results);
652 mProcessCaptureResultLock.unlock();
653}
654
655void CameraDeviceSession::ResultBatcher_3_4::freeReleaseFences_3_4(hidl_vec<CaptureResult>& results) {
656 for (auto& result : results) {
657 if (result.v3_2.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
658 native_handle_t* handle = const_cast<native_handle_t*>(
659 result.v3_2.inputBuffer.releaseFence.getNativeHandle());
660 native_handle_close(handle);
661 native_handle_delete(handle);
662 }
663 for (auto& buf : result.v3_2.outputBuffers) {
664 if (buf.releaseFence.getNativeHandle() != nullptr) {
665 native_handle_t* handle = const_cast<native_handle_t*>(
666 buf.releaseFence.getNativeHandle());
667 native_handle_close(handle);
668 native_handle_delete(handle);
669 }
670 }
671 }
672 return;
673}
674
Emilian Peeve18057b2017-11-13 16:03:44 +0000675} // namespace implementation
676} // namespace V3_4
677} // namespace device
678} // namespace camera
679} // namespace hardware
680} // namespace android