blob: 450f3ddc311b93716f7446d3143ff2af0a859093 [file] [log] [blame]
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001/*
2 * Copyright (C) 2019 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
17#define LOG_TAG "Camera3-OutputUtils"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20//#define LOG_NNDEBUG 0 // Per-frame verbose logging
21
22#ifdef LOG_NNDEBUG
23#define ALOGVV(...) ALOGV(__VA_ARGS__)
24#else
25#define ALOGVV(...) ((void)0)
26#endif
27
28// Convenience macros for transitioning to the error state
29#define SET_ERR(fmt, ...) states.setErrIntf.setErrorState( \
30 "%s: " fmt, __FUNCTION__, \
31 ##__VA_ARGS__)
32
33#include <inttypes.h>
34
35#include <utils/Log.h>
36#include <utils/SortedVector.h>
37#include <utils/Trace.h>
38
39#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
40
41#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
42#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
43#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
44
Emilian Peev5104fe92021-10-21 14:27:09 -070045#include <camera/CameraUtils.h>
Austin Borger1c1bee02023-06-01 16:51:35 -070046#include <camera/StringUtils.h>
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080047#include <camera_metadata_hidden.h>
48
49#include "device3/Camera3OutputUtils.h"
50
Emilian Peev5104fe92021-10-21 14:27:09 -070051#include "system/camera_metadata.h"
52
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080053using namespace android::camera3;
54using namespace android::hardware::camera;
55
56namespace android {
57namespace camera3 {
58
59status_t fixupMonochromeTags(
60 CaptureOutputStates& states,
61 const CameraMetadata& deviceInfo,
62 CameraMetadata& resultMetadata) {
63 status_t res = OK;
64 if (!states.needFixupMonoChrome) {
65 return res;
66 }
67
68 // Remove tags that are not applicable to monochrome camera.
69 int32_t tagsToRemove[] = {
70 ANDROID_SENSOR_GREEN_SPLIT,
71 ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
72 ANDROID_COLOR_CORRECTION_MODE,
73 ANDROID_COLOR_CORRECTION_TRANSFORM,
74 ANDROID_COLOR_CORRECTION_GAINS,
75 };
76 for (auto tag : tagsToRemove) {
77 res = resultMetadata.erase(tag);
78 if (res != OK) {
79 ALOGE("%s: Failed to remove tag %d for monochrome camera", __FUNCTION__, tag);
80 return res;
81 }
82 }
83
84 // ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL
85 camera_metadata_entry blEntry = resultMetadata.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
86 for (size_t i = 1; i < blEntry.count; i++) {
87 blEntry.data.f[i] = blEntry.data.f[0];
88 }
89
90 // ANDROID_SENSOR_NOISE_PROFILE
91 camera_metadata_entry npEntry = resultMetadata.find(ANDROID_SENSOR_NOISE_PROFILE);
92 if (npEntry.count > 0 && npEntry.count % 2 == 0) {
93 double np[] = {npEntry.data.d[0], npEntry.data.d[1]};
94 res = resultMetadata.update(ANDROID_SENSOR_NOISE_PROFILE, np, 2);
95 if (res != OK) {
96 ALOGE("%s: Failed to update SENSOR_NOISE_PROFILE: %s (%d)",
97 __FUNCTION__, strerror(-res), res);
98 return res;
99 }
100 }
101
102 // ANDROID_STATISTICS_LENS_SHADING_MAP
103 camera_metadata_ro_entry lsSizeEntry = deviceInfo.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
104 camera_metadata_entry lsEntry = resultMetadata.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
105 if (lsSizeEntry.count == 2 && lsEntry.count > 0
106 && (int32_t)lsEntry.count == 4 * lsSizeEntry.data.i32[0] * lsSizeEntry.data.i32[1]) {
107 for (int32_t i = 0; i < lsSizeEntry.data.i32[0] * lsSizeEntry.data.i32[1]; i++) {
108 lsEntry.data.f[4*i+1] = lsEntry.data.f[4*i];
109 lsEntry.data.f[4*i+2] = lsEntry.data.f[4*i];
110 lsEntry.data.f[4*i+3] = lsEntry.data.f[4*i];
111 }
112 }
113
114 // ANDROID_TONEMAP_CURVE_BLUE
115 // ANDROID_TONEMAP_CURVE_GREEN
116 // ANDROID_TONEMAP_CURVE_RED
117 camera_metadata_entry tcbEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_BLUE);
118 camera_metadata_entry tcgEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_GREEN);
119 camera_metadata_entry tcrEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_RED);
120 if (tcbEntry.count > 0
121 && tcbEntry.count == tcgEntry.count
122 && tcbEntry.count == tcrEntry.count) {
123 for (size_t i = 0; i < tcbEntry.count; i++) {
124 tcbEntry.data.f[i] = tcrEntry.data.f[i];
125 tcgEntry.data.f[i] = tcrEntry.data.f[i];
126 }
127 }
128
129 return res;
130}
131
Bharatt Kukreja0e13db32022-12-07 21:38:45 +0000132status_t fixupAutoframingTags(CameraMetadata& resultMetadata) {
133 status_t res = OK;
134 camera_metadata_entry autoframingEntry =
135 resultMetadata.find(ANDROID_CONTROL_AUTOFRAMING);
136 if (autoframingEntry.count == 0) {
137 const uint8_t defaultAutoframingEntry = ANDROID_CONTROL_AUTOFRAMING_OFF;
138 res = resultMetadata.update(ANDROID_CONTROL_AUTOFRAMING, &defaultAutoframingEntry, 1);
139 if (res != OK) {
140 ALOGE("%s: Failed to update ANDROID_CONTROL_AUTOFRAMING: %s (%d)",
141 __FUNCTION__, strerror(-res), res);
142 return res;
143 }
144 }
145
146 camera_metadata_entry autoframingStateEntry =
147 resultMetadata.find(ANDROID_CONTROL_AUTOFRAMING_STATE);
148 if (autoframingStateEntry.count == 0) {
149 const uint8_t defaultAutoframingStateEntry = ANDROID_CONTROL_AUTOFRAMING_STATE_INACTIVE;
150 res = resultMetadata.update(ANDROID_CONTROL_AUTOFRAMING_STATE,
151 &defaultAutoframingStateEntry, 1);
152 if (res != OK) {
153 ALOGE("%s: Failed to update ANDROID_CONTROL_AUTOFRAMING_STATE: %s (%d)",
154 __FUNCTION__, strerror(-res), res);
155 return res;
156 }
157 }
158
159 return res;
160}
161
Rucha Katakwar47c2e7c2023-11-09 12:08:35 -0800162status_t fixupManualFlashStrengthControlTags(CameraMetadata& resultMetadata) {
163 status_t res = OK;
164 camera_metadata_entry strengthLevelEntry =
165 resultMetadata.find(ANDROID_FLASH_STRENGTH_LEVEL);
166 if (strengthLevelEntry.count == 0) {
167 const int32_t defaultStrengthLevelEntry = ANDROID_FLASH_STRENGTH_LEVEL;
168 res = resultMetadata.update(ANDROID_FLASH_STRENGTH_LEVEL, &defaultStrengthLevelEntry, 1);
169 if (res != OK) {
170 ALOGE("%s: Failed to update ANDROID_FLASH_STRENGTH_LEVEL: %s (%d)",
171 __FUNCTION__, strerror(-res), res);
172 return res;
173 }
174 }
175
176 return res;
177}
178
Shuzhen Wangcd8811c2022-08-29 17:23:52 +0000179void correctMeteringRegions(camera_metadata_t *meta) {
180 if (meta == nullptr) return;
181
182 uint32_t meteringRegionKeys[] = {
183 ANDROID_CONTROL_AE_REGIONS,
184 ANDROID_CONTROL_AWB_REGIONS,
185 ANDROID_CONTROL_AF_REGIONS };
186
187 for (uint32_t key : meteringRegionKeys) {
188 camera_metadata_entry_t entry;
189 int res = find_camera_metadata_entry(meta, key, &entry);
190 if (res != OK) continue;
191
192 for (size_t i = 0; i < entry.count; i += 5) {
193 if (entry.data.i32[0] > entry.data.i32[2]) {
194 ALOGW("%s: Invalid metering region (%d): left: %d, right: %d",
195 __FUNCTION__, key, entry.data.i32[0], entry.data.i32[2]);
196 entry.data.i32[2] = entry.data.i32[0];
197 }
198 if (entry.data.i32[1] > entry.data.i32[3]) {
199 ALOGW("%s: Invalid metering region (%d): top: %d, bottom: %d",
200 __FUNCTION__, key, entry.data.i32[1], entry.data.i32[3]);
201 entry.data.i32[3] = entry.data.i32[1];
202 }
203 }
204 }
205}
206
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800207void insertResultLocked(CaptureOutputStates& states, CaptureResult *result, uint32_t frameNumber) {
208 if (result == nullptr) return;
209
210 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
211 result->mMetadata.getAndLock());
212 set_camera_metadata_vendor_id(meta, states.vendorTagId);
Shuzhen Wangcd8811c2022-08-29 17:23:52 +0000213 correctMeteringRegions(meta);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800214 result->mMetadata.unlock(meta);
215
216 if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
217 (int32_t*)&frameNumber, 1) != OK) {
218 SET_ERR("Failed to set frame number %d in metadata", frameNumber);
219 return;
220 }
221
222 if (result->mMetadata.update(ANDROID_REQUEST_ID, &result->mResultExtras.requestId, 1) != OK) {
223 SET_ERR("Failed to set request ID in metadata for frame %d", frameNumber);
224 return;
225 }
226
227 // Update vendor tag id for physical metadata
228 for (auto& physicalMetadata : result->mPhysicalMetadatas) {
229 camera_metadata_t *pmeta = const_cast<camera_metadata_t *>(
230 physicalMetadata.mPhysicalCameraMetadata.getAndLock());
231 set_camera_metadata_vendor_id(pmeta, states.vendorTagId);
Shuzhen Wangcd8811c2022-08-29 17:23:52 +0000232 correctMeteringRegions(pmeta);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800233 physicalMetadata.mPhysicalCameraMetadata.unlock(pmeta);
234 }
235
236 // Valid result, insert into queue
Jayant Chowdhary8a0be292020-01-08 13:10:38 -0800237 std::list<CaptureResult>::iterator queuedResult =
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800238 states.resultQueue.insert(states.resultQueue.end(), CaptureResult(*result));
Jayant Chowdhary8a0be292020-01-08 13:10:38 -0800239 ALOGV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800240 ", burstId = %" PRId32, __FUNCTION__,
241 queuedResult->mResultExtras.requestId,
242 queuedResult->mResultExtras.frameNumber,
243 queuedResult->mResultExtras.burstId);
244
245 states.resultSignal.notify_one();
246}
247
248
249void sendPartialCaptureResult(CaptureOutputStates& states,
250 const camera_metadata_t * partialResult,
251 const CaptureResultExtras &resultExtras, uint32_t frameNumber) {
252 ATRACE_CALL();
253 std::lock_guard<std::mutex> l(states.outputLock);
254
255 CaptureResult captureResult;
256 captureResult.mResultExtras = resultExtras;
257 captureResult.mMetadata = partialResult;
258
259 // Fix up result metadata for monochrome camera.
260 status_t res = fixupMonochromeTags(states, states.deviceInfo, captureResult.mMetadata);
261 if (res != OK) {
262 SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
263 return;
264 }
265
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700266 // Update partial result by removing keys remapped by DistortionCorrection, ZoomRatio,
267 // and RotationAndCrop mappers.
268 std::set<uint32_t> keysToRemove;
269
Austin Borger1c1bee02023-06-01 16:51:35 -0700270 auto iter = states.distortionMappers.find(states.cameraId);
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700271 if (iter != states.distortionMappers.end()) {
272 const auto& remappedKeys = iter->second.getRemappedKeys();
273 keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
274 }
275
Austin Borger1c1bee02023-06-01 16:51:35 -0700276 const auto& remappedKeys = states.zoomRatioMappers[states.cameraId].getRemappedKeys();
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700277 keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
278
Austin Borger1c1bee02023-06-01 16:51:35 -0700279 auto mapper = states.rotateAndCropMappers.find(states.cameraId);
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700280 if (mapper != states.rotateAndCropMappers.end()) {
Ravneet58485902023-04-07 04:34:48 +0000281 const auto& remappedKeys = mapper->second.getRemappedKeys();
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700282 keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
283 }
284
285 for (uint32_t key : keysToRemove) {
286 captureResult.mMetadata.erase(key);
287 }
288
289 // Send partial result
290 if (captureResult.mMetadata.entryCount() > 0) {
291 insertResultLocked(states, &captureResult, frameNumber);
292 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800293}
294
295void sendCaptureResult(
296 CaptureOutputStates& states,
297 CameraMetadata &pendingMetadata,
298 CaptureResultExtras &resultExtras,
299 CameraMetadata &collectedPartialResult,
300 uint32_t frameNumber,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800301 bool reprocess, bool zslStillCapture, bool rotateAndCropAuto,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800302 const std::set<std::string>& cameraIdsWithZoom,
303 const std::vector<PhysicalCaptureResultInfo>& physicalMetadatas) {
304 ATRACE_CALL();
305 if (pendingMetadata.isEmpty())
306 return;
307
308 std::lock_guard<std::mutex> l(states.outputLock);
309
310 // TODO: need to track errors for tighter bounds on expected frame number
311 if (reprocess) {
312 if (frameNumber < states.nextReprocResultFrameNum) {
313 SET_ERR("Out-of-order reprocess capture result metadata submitted! "
314 "(got frame number %d, expecting %d)",
315 frameNumber, states.nextReprocResultFrameNum);
316 return;
317 }
318 states.nextReprocResultFrameNum = frameNumber + 1;
319 } else if (zslStillCapture) {
320 if (frameNumber < states.nextZslResultFrameNum) {
321 SET_ERR("Out-of-order ZSL still capture result metadata submitted! "
322 "(got frame number %d, expecting %d)",
323 frameNumber, states.nextZslResultFrameNum);
324 return;
325 }
326 states.nextZslResultFrameNum = frameNumber + 1;
327 } else {
328 if (frameNumber < states.nextResultFrameNum) {
329 SET_ERR("Out-of-order capture result metadata submitted! "
330 "(got frame number %d, expecting %d)",
331 frameNumber, states.nextResultFrameNum);
332 return;
333 }
334 states.nextResultFrameNum = frameNumber + 1;
335 }
336
337 CaptureResult captureResult;
338 captureResult.mResultExtras = resultExtras;
339 captureResult.mMetadata = pendingMetadata;
340 captureResult.mPhysicalMetadatas = physicalMetadatas;
341
342 // Append any previous partials to form a complete result
343 if (states.usePartialResult && !collectedPartialResult.isEmpty()) {
344 captureResult.mMetadata.append(collectedPartialResult);
345 }
346
347 captureResult.mMetadata.sort();
348
349 // Check that there's a timestamp in the result metadata
350 camera_metadata_entry timestamp = captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
351 if (timestamp.count == 0) {
352 SET_ERR("No timestamp provided by HAL for frame %d!",
353 frameNumber);
354 return;
355 }
Yin-Chia Yehc530c592020-03-09 14:50:36 -0700356 nsecs_t sensorTimestamp = timestamp.data.i64[0];
357
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800358 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
359 camera_metadata_entry timestamp =
360 physicalMetadata.mPhysicalCameraMetadata.find(ANDROID_SENSOR_TIMESTAMP);
361 if (timestamp.count == 0) {
362 SET_ERR("No timestamp provided by HAL for physical camera %s frame %d!",
Austin Borger1c1bee02023-06-01 16:51:35 -0700363 physicalMetadata.mPhysicalCameraId.c_str(), frameNumber);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800364 return;
365 }
366 }
367
368 // Fix up some result metadata to account for HAL-level distortion correction
Yin-Chia Yeh7ffbd982020-04-13 10:04:23 -0700369 status_t res = OK;
Austin Borger1c1bee02023-06-01 16:51:35 -0700370 auto iter = states.distortionMappers.find(states.cameraId);
Yin-Chia Yeh7ffbd982020-04-13 10:04:23 -0700371 if (iter != states.distortionMappers.end()) {
372 res = iter->second.correctCaptureResult(&captureResult.mMetadata);
373 if (res != OK) {
374 SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
375 frameNumber, strerror(-res), res);
376 return;
377 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800378 }
379
380 // Fix up result metadata to account for zoom ratio availabilities between
381 // HAL and app.
Austin Borger1c1bee02023-06-01 16:51:35 -0700382 bool zoomRatioIs1 = cameraIdsWithZoom.find(states.cameraId) == cameraIdsWithZoom.end();
383 res = states.zoomRatioMappers[states.cameraId].updateCaptureResult(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800384 &captureResult.mMetadata, zoomRatioIs1);
385 if (res != OK) {
386 SET_ERR("Failed to update capture result zoom ratio metadata for frame %d: %s (%d)",
387 frameNumber, strerror(-res), res);
388 return;
389 }
390
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800391 // Fix up result metadata to account for rotateAndCrop in AUTO mode
392 if (rotateAndCropAuto) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700393 auto mapper = states.rotateAndCropMappers.find(states.cameraId);
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800394 if (mapper != states.rotateAndCropMappers.end()) {
395 res = mapper->second.updateCaptureResult(
396 &captureResult.mMetadata);
397 if (res != OK) {
398 SET_ERR("Unable to correct capture result rotate-and-crop for frame %d: %s (%d)",
399 frameNumber, strerror(-res), res);
400 return;
401 }
402 }
403 }
404
Rucha Katakwar47c2e7c2023-11-09 12:08:35 -0800405 // Fix up manual flash strength control metadata
406 res = fixupManualFlashStrengthControlTags(captureResult.mMetadata);
407 if (res != OK) {
408 SET_ERR("Failed to set flash strength level defaults in result metadata: %s (%d)",
409 strerror(-res), res);
410 return;
411 }
412 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
413 res = fixupManualFlashStrengthControlTags(physicalMetadata.mPhysicalCameraMetadata);
414 if (res != OK) {
415 SET_ERR("Failed to set flash strength level defaults in physical result"
416 " metadata: %s (%d)", strerror(-res), res);
417 return;
418 }
419 }
420
Bharatt Kukrejad33fe9f2022-11-23 21:52:52 +0000421 // Fix up autoframing metadata
Bharatt Kukreja0e13db32022-12-07 21:38:45 +0000422 res = fixupAutoframingTags(captureResult.mMetadata);
423 if (res != OK) {
424 SET_ERR("Failed to set autoframing defaults in result metadata: %s (%d)",
425 strerror(-res), res);
426 return;
Bharatt Kukrejad33fe9f2022-11-23 21:52:52 +0000427 }
Bharatt Kukreja0e13db32022-12-07 21:38:45 +0000428 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
429 res = fixupAutoframingTags(physicalMetadata.mPhysicalCameraMetadata);
430 if (res != OK) {
431 SET_ERR("Failed to set autoframing defaults in physical result metadata: %s (%d)",
432 strerror(-res), res);
Bharatt Kukrejad33fe9f2022-11-23 21:52:52 +0000433 return;
434 }
435 }
436
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800437 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700438 const std::string cameraId = physicalMetadata.mPhysicalCameraId;
439 auto mapper = states.distortionMappers.find(cameraId);
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800440 if (mapper != states.distortionMappers.end()) {
441 res = mapper->second.correctCaptureResult(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800442 &physicalMetadata.mPhysicalCameraMetadata);
443 if (res != OK) {
444 SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
445 frameNumber, strerror(-res), res);
446 return;
447 }
448 }
449
Austin Borger1c1bee02023-06-01 16:51:35 -0700450 zoomRatioIs1 = cameraIdsWithZoom.find(cameraId) == cameraIdsWithZoom.end();
451 res = states.zoomRatioMappers[cameraId].updateCaptureResult(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800452 &physicalMetadata.mPhysicalCameraMetadata, zoomRatioIs1);
453 if (res != OK) {
454 SET_ERR("Failed to update camera %s's physical zoom ratio metadata for "
Austin Borger1c1bee02023-06-01 16:51:35 -0700455 "frame %d: %s(%d)", cameraId.c_str(), frameNumber, strerror(-res), res);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800456 return;
457 }
458 }
459
460 // Fix up result metadata for monochrome camera.
461 res = fixupMonochromeTags(states, states.deviceInfo, captureResult.mMetadata);
462 if (res != OK) {
463 SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
464 return;
465 }
466 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700467 const std::string &cameraId = physicalMetadata.mPhysicalCameraId;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800468 res = fixupMonochromeTags(states,
Austin Borger1c1bee02023-06-01 16:51:35 -0700469 states.physicalDeviceInfoMap.at(cameraId),
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800470 physicalMetadata.mPhysicalCameraMetadata);
471 if (res != OK) {
472 SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
473 return;
474 }
475 }
476
477 std::unordered_map<std::string, CameraMetadata> monitoredPhysicalMetadata;
478 for (auto& m : physicalMetadatas) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700479 monitoredPhysicalMetadata.emplace(m.mPhysicalCameraId,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800480 CameraMetadata(m.mPhysicalCameraMetadata));
481 }
482 states.tagMonitor.monitorMetadata(TagMonitor::RESULT,
Yin-Chia Yehc530c592020-03-09 14:50:36 -0700483 frameNumber, sensorTimestamp, captureResult.mMetadata,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800484 monitoredPhysicalMetadata);
485
486 insertResultLocked(states, &captureResult, frameNumber);
487}
488
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800489void removeInFlightMapEntryLocked(CaptureOutputStates& states, int idx) {
490 ATRACE_CALL();
491 InFlightRequestMap& inflightMap = states.inflightMap;
492 nsecs_t duration = inflightMap.valueAt(idx).maxExpectedDuration;
493 inflightMap.removeItemsAt(idx, 1);
494
495 states.inflightIntf.onInflightEntryRemovedLocked(duration);
496}
497
498void removeInFlightRequestIfReadyLocked(CaptureOutputStates& states, int idx) {
499 InFlightRequestMap& inflightMap = states.inflightMap;
Greg Kaiser51b882c2020-06-10 05:41:44 +0000500 const InFlightRequest &request = inflightMap.valueAt(idx);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800501 const uint32_t frameNumber = inflightMap.keyAt(idx);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700502 SessionStatsBuilder& sessionStatsBuilder = states.sessionStatsBuilder;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800503
504 nsecs_t sensorTimestamp = request.sensorTimestamp;
505 nsecs_t shutterTimestamp = request.shutterTimestamp;
506
507 // Check if it's okay to remove the request from InFlightMap:
508 // In the case of a successful request:
509 // all input and output buffers, all result metadata, shutter callback
510 // arrived.
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700511 // In the case of an unsuccessful request:
512 // all input and output buffers, as well as request/result error notifications, arrived.
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800513 if (request.numBuffersLeft == 0 &&
514 (request.skipResultMetadata ||
515 (request.haveResultMetadata && shutterTimestamp != 0))) {
516 if (request.stillCapture) {
517 ATRACE_ASYNC_END("still capture", frameNumber);
518 }
519
520 ATRACE_ASYNC_END("frame capture", frameNumber);
521
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -0400522 // Validation check - if sensor timestamp matches shutter timestamp in the
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800523 // case of request having callback.
524 if (request.hasCallback && request.requestStatus == OK &&
525 sensorTimestamp != shutterTimestamp) {
526 SET_ERR("sensor timestamp (%" PRId64
527 ") for frame %d doesn't match shutter timestamp (%" PRId64 ")",
528 sensorTimestamp, frameNumber, shutterTimestamp);
529 }
530
531 // for an unsuccessful request, it may have pending output buffers to
532 // return.
533 assert(request.requestStatus != OK ||
534 request.pendingOutputBuffers.size() == 0);
535
Greg Kaiser51b882c2020-06-10 05:41:44 +0000536 returnOutputBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800537 states.useHalBufManager, states.listener,
538 request.pendingOutputBuffers.array(),
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700539 request.pendingOutputBuffers.size(), /*timestamp*/0, /*readoutTimestamp*/0,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700540 /*requested*/true, request.requestTimeNs, states.sessionStatsBuilder,
541 /*timestampIncreasing*/true,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700542 request.outputSurfaces, request.resultExtras,
Emilian Peev5104fe92021-10-21 14:27:09 -0700543 request.errorBufStrategy, request.transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700544
545 // Note down the just completed frame number
546 if (request.hasInputBuffer) {
547 states.lastCompletedReprocessFrameNumber = frameNumber;
Shuzhen Wang828ade32022-01-10 17:19:02 -0800548 } else if (request.zslCapture && request.stillCapture) {
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700549 states.lastCompletedZslFrameNumber = frameNumber;
550 } else {
551 states.lastCompletedRegularFrameNumber = frameNumber;
552 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800553
Shuzhen Wang316781a2020-08-18 18:11:01 -0700554 sessionStatsBuilder.incResultCounter(request.skipResultMetadata);
555
Greg Kaiser51b882c2020-06-10 05:41:44 +0000556 removeInFlightMapEntryLocked(states, idx);
557 ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800558 }
559
560 states.inflightIntf.checkInflightMapLengthLocked();
561}
562
Shuzhen Wang99080502021-03-07 21:08:20 -0800563// Erase the subset of physicalCameraIds that contains id
564bool erasePhysicalCameraIdSet(
Austin Borger1c1bee02023-06-01 16:51:35 -0700565 std::set<std::set<std::string>>& physicalCameraIds, const std::string& id) {
Shuzhen Wang99080502021-03-07 21:08:20 -0800566 bool found = false;
567 for (auto iter = physicalCameraIds.begin(); iter != physicalCameraIds.end(); iter++) {
568 if (iter->count(id) == 1) {
569 physicalCameraIds.erase(iter);
570 found = true;
571 break;
572 }
573 }
574 return found;
575}
576
Shuzhen Wang3c00b092022-11-08 22:53:07 +0000577const std::set<std::string>& getCameraIdsWithZoomLocked(
578 const InFlightRequestMap& inflightMap, const CameraMetadata& metadata,
579 const std::set<std::string>& cameraIdsWithZoom) {
580 camera_metadata_ro_entry overrideEntry =
581 metadata.find(ANDROID_CONTROL_SETTINGS_OVERRIDE);
582 camera_metadata_ro_entry frameNumberEntry =
583 metadata.find(ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER);
584 if (overrideEntry.count != 1
585 || overrideEntry.data.i32[0] != ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM
586 || frameNumberEntry.count != 1) {
587 // No valid overriding frame number, skip
588 return cameraIdsWithZoom;
589 }
590
591 uint32_t overridingFrameNumber = frameNumberEntry.data.i32[0];
592 ssize_t idx = inflightMap.indexOfKey(overridingFrameNumber);
593 if (idx < 0) {
594 ALOGE("%s: Failed to find pending request #%d in inflight map",
595 __FUNCTION__, overridingFrameNumber);
596 return cameraIdsWithZoom;
597 }
598
599 const InFlightRequest &r = inflightMap.valueFor(overridingFrameNumber);
600 return r.cameraIdsWithZoom;
601}
602
Emilian Peevf4816702020-04-03 15:44:51 -0700603void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800604 ATRACE_CALL();
605
606 status_t res;
607
608 uint32_t frameNumber = result->frame_number;
609 if (result->result == NULL && result->num_output_buffers == 0 &&
610 result->input_buffer == NULL) {
611 SET_ERR("No result data provided by HAL for frame %d",
612 frameNumber);
613 return;
614 }
615
616 if (!states.usePartialResult &&
617 result->result != NULL &&
618 result->partial_result != 1) {
619 SET_ERR("Result is malformed for frame %d: partial_result %u must be 1"
620 " if partial result is not supported",
621 frameNumber, result->partial_result);
622 return;
623 }
624
625 bool isPartialResult = false;
626 CameraMetadata collectedPartialResult;
627 bool hasInputBufferInRequest = false;
628
629 // Get shutter timestamp and resultExtras from list of in-flight requests,
630 // where it was added by the shutter notification for this frame. If the
631 // shutter timestamp isn't received yet, append the output buffers to the
632 // in-flight request and they will be returned when the shutter timestamp
633 // arrives. Update the in-flight status and remove the in-flight entry if
634 // all result data and shutter timestamp have been received.
635 nsecs_t shutterTimestamp = 0;
636 {
637 std::lock_guard<std::mutex> l(states.inflightLock);
638 ssize_t idx = states.inflightMap.indexOfKey(frameNumber);
639 if (idx == NAME_NOT_FOUND) {
640 SET_ERR("Unknown frame number for capture result: %d",
641 frameNumber);
642 return;
643 }
644 InFlightRequest &request = states.inflightMap.editValueAt(idx);
645 ALOGVV("%s: got InFlightRequest requestId = %" PRId32
646 ", frameNumber = %" PRId64 ", burstId = %" PRId32
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700647 ", partialResultCount = %d/%d, hasCallback = %d, num_output_buffers %d"
648 ", usePartialResult = %d",
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800649 __FUNCTION__, request.resultExtras.requestId,
650 request.resultExtras.frameNumber, request.resultExtras.burstId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700651 result->partial_result, states.numPartialResults,
652 request.hasCallback, result->num_output_buffers,
653 states.usePartialResult);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800654 // Always update the partial count to the latest one if it's not 0
655 // (buffers only). When framework aggregates adjacent partial results
656 // into one, the latest partial count will be used.
657 if (result->partial_result != 0)
658 request.resultExtras.partialResultCount = result->partial_result;
659
Austin Borgerc8099762023-01-12 17:08:46 -0800660 if (result->result != nullptr) {
Emilian Peev5104fe92021-10-21 14:27:09 -0700661 camera_metadata_ro_entry entry;
662 auto ret = find_camera_metadata_ro_entry(result->result,
663 ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID, &entry);
664 if ((ret == OK) && (entry.count > 0)) {
665 std::string physicalId(reinterpret_cast<const char *>(entry.data.u8));
Austin Borgerc8099762023-01-12 17:08:46 -0800666 if (!states.activePhysicalId.empty() && physicalId != states.activePhysicalId) {
667 states.listener->notifyPhysicalCameraChange(physicalId);
668 }
669 states.activePhysicalId = physicalId;
670
671 if (!states.legacyClient && !states.overrideToPortrait) {
672 auto deviceInfo = states.physicalDeviceInfoMap.find(physicalId);
673 if (deviceInfo != states.physicalDeviceInfoMap.end()) {
674 auto orientation = deviceInfo->second.find(ANDROID_SENSOR_ORIENTATION);
675 if (orientation.count > 0) {
Emilian Peev747be7e2023-03-31 11:10:08 -0700676 int32_t transform;
Austin Borgerc8099762023-01-12 17:08:46 -0800677 ret = CameraUtils::getRotationTransform(deviceInfo->second,
Emilian Peev747be7e2023-03-31 11:10:08 -0700678 OutputConfiguration::MIRROR_MODE_AUTO, &transform);
679 if (ret == OK) {
680 // It is possible for camera providers to return the capture
681 // results after the processed frames. In such scenario, we will
682 // not be able to set the output transformation before the frames
683 // return back to the consumer for the current capture request
684 // but we could still try and configure it for any future requests
685 // that are still in flight. The assumption is that the physical
686 // device id remains the same for the duration of the pending queue.
687 for (size_t i = 0; i < states.inflightMap.size(); i++) {
688 auto &r = states.inflightMap.editValueAt(i);
689 if (r.requestTimeNs >= request.requestTimeNs) {
690 r.transform = transform;
691 }
692 }
693 } else {
Austin Borgerc8099762023-01-12 17:08:46 -0800694 ALOGE("%s: Failed to calculate current stream transformation: %s "
695 "(%d)", __FUNCTION__, strerror(-ret), ret);
696 }
697 } else {
698 ALOGE("%s: Physical device orientation absent!", __FUNCTION__);
Emilian Peev5104fe92021-10-21 14:27:09 -0700699 }
700 } else {
Austin Borgerc8099762023-01-12 17:08:46 -0800701 ALOGE("%s: Physical device not found in device info map found!",
702 __FUNCTION__);
Emilian Peev5104fe92021-10-21 14:27:09 -0700703 }
Emilian Peev5104fe92021-10-21 14:27:09 -0700704 }
705 }
706 }
707
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800708 // Check if this result carries only partial metadata
709 if (states.usePartialResult && result->result != NULL) {
710 if (result->partial_result > states.numPartialResults || result->partial_result < 1) {
711 SET_ERR("Result is malformed for frame %d: partial_result %u must be in"
712 " the range of [1, %d] when metadata is included in the result",
713 frameNumber, result->partial_result, states.numPartialResults);
714 return;
715 }
716 isPartialResult = (result->partial_result < states.numPartialResults);
717 if (isPartialResult && result->num_physcam_metadata) {
718 SET_ERR("Result is malformed for frame %d: partial_result not allowed for"
719 " physical camera result", frameNumber);
720 return;
721 }
722 if (isPartialResult) {
723 request.collectedPartialResult.append(result->result);
724 }
725
726 if (isPartialResult && request.hasCallback) {
727 // Send partial capture result
728 sendPartialCaptureResult(states, result->result, request.resultExtras,
729 frameNumber);
730 }
731 }
732
733 shutterTimestamp = request.shutterTimestamp;
734 hasInputBufferInRequest = request.hasInputBuffer;
735
736 // Did we get the (final) result metadata for this capture?
737 if (result->result != NULL && !isPartialResult) {
738 if (request.physicalCameraIds.size() != result->num_physcam_metadata) {
739 SET_ERR("Expected physical Camera metadata count %d not equal to actual count %d",
740 request.physicalCameraIds.size(), result->num_physcam_metadata);
741 return;
742 }
743 if (request.haveResultMetadata) {
744 SET_ERR("Called multiple times with metadata for frame %d",
745 frameNumber);
746 return;
747 }
748 for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700749 const std::string physicalId = result->physcam_ids[i];
Shuzhen Wang99080502021-03-07 21:08:20 -0800750 bool validPhysicalCameraMetadata =
751 erasePhysicalCameraIdSet(request.physicalCameraIds, physicalId);
752 if (!validPhysicalCameraMetadata) {
753 SET_ERR("Unexpected total result for frame %d camera %s",
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800754 frameNumber, physicalId.c_str());
755 return;
756 }
757 }
758 if (states.usePartialResult &&
759 !request.collectedPartialResult.isEmpty()) {
760 collectedPartialResult.acquire(
761 request.collectedPartialResult);
762 }
763 request.haveResultMetadata = true;
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700764 request.errorBufStrategy = ERROR_BUF_RETURN_NOTIFY;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800765 }
766
767 uint32_t numBuffersReturned = result->num_output_buffers;
768 if (result->input_buffer != NULL) {
769 if (hasInputBufferInRequest) {
770 numBuffersReturned += 1;
771 } else {
772 ALOGW("%s: Input buffer should be NULL if there is no input"
773 " buffer sent in the request",
774 __FUNCTION__);
775 }
776 }
777 request.numBuffersLeft -= numBuffersReturned;
778 if (request.numBuffersLeft < 0) {
779 SET_ERR("Too many buffers returned for frame %d",
780 frameNumber);
781 return;
782 }
783
784 camera_metadata_ro_entry_t entry;
785 res = find_camera_metadata_ro_entry(result->result,
786 ANDROID_SENSOR_TIMESTAMP, &entry);
787 if (res == OK && entry.count == 1) {
788 request.sensorTimestamp = entry.data.i64[0];
789 }
790
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700791 // If shutter event isn't received yet, do not return the pending output
792 // buffers.
793 request.pendingOutputBuffers.appendArray(result->output_buffers,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800794 result->num_output_buffers);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700795 if (shutterTimestamp != 0) {
796 returnAndRemovePendingOutputBuffers(
797 states.useHalBufManager, states.listener,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700798 request, states.sessionStatsBuilder);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800799 }
800
801 if (result->result != NULL && !isPartialResult) {
802 for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
803 CameraMetadata physicalMetadata;
804 physicalMetadata.append(result->physcam_metadata[i]);
Austin Borger1c1bee02023-06-01 16:51:35 -0700805 request.physicalMetadatas.push_back({result->physcam_ids[i],
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800806 physicalMetadata});
807 }
808 if (shutterTimestamp == 0) {
809 request.pendingMetadata = result->result;
810 request.collectedPartialResult = collectedPartialResult;
811 } else if (request.hasCallback) {
812 CameraMetadata metadata;
813 metadata = result->result;
Shuzhen Wang3c00b092022-11-08 22:53:07 +0000814 auto cameraIdsWithZoom = getCameraIdsWithZoomLocked(
815 states.inflightMap, metadata, request.cameraIdsWithZoom);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800816 sendCaptureResult(states, metadata, request.resultExtras,
817 collectedPartialResult, frameNumber,
818 hasInputBufferInRequest, request.zslCapture && request.stillCapture,
Shuzhen Wang3c00b092022-11-08 22:53:07 +0000819 request.rotateAndCropAuto, cameraIdsWithZoom,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800820 request.physicalMetadatas);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800821 }
822 }
823 removeInFlightRequestIfReadyLocked(states, idx);
824 } // scope for states.inFlightLock
825
826 if (result->input_buffer != NULL) {
827 if (hasInputBufferInRequest) {
828 Camera3Stream *stream =
829 Camera3Stream::cast(result->input_buffer->stream);
830 res = stream->returnInputBuffer(*(result->input_buffer));
831 // Note: stream may be deallocated at this point, if this buffer was the
832 // last reference to it.
833 if (res != OK) {
834 ALOGE("%s: RequestThread: Can't return input buffer for frame %d to"
835 " its stream:%s (%d)", __FUNCTION__,
836 frameNumber, strerror(-res), res);
837 }
838 } else {
839 ALOGW("%s: Input buffer should be NULL if there is no input"
840 " buffer sent in the request, skipping input buffer return.",
841 __FUNCTION__);
842 }
843 }
844}
845
Greg Kaiser51b882c2020-06-10 05:41:44 +0000846void returnOutputBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800847 bool useHalBufManager,
848 sp<NotificationListener> listener,
Emilian Peevf4816702020-04-03 15:44:51 -0700849 const camera_stream_buffer_t *outputBuffers, size_t numBuffers,
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700850 nsecs_t timestamp, nsecs_t readoutTimestamp, bool requested,
851 nsecs_t requestTimeNs, SessionStatsBuilder& sessionStatsBuilder,
852 bool timestampIncreasing, const SurfaceMap& outputSurfaces,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700853 const CaptureResultExtras &inResultExtras,
Emilian Peev5104fe92021-10-21 14:27:09 -0700854 ERROR_BUF_STRATEGY errorBufStrategy, int32_t transform) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800855
856 for (size_t i = 0; i < numBuffers; i++)
857 {
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700858 Camera3StreamInterface *stream = Camera3Stream::cast(outputBuffers[i].stream);
859 int streamId = stream->getId();
860
861 // Call notify(ERROR_BUFFER) if necessary.
Emilian Peevf4816702020-04-03 15:44:51 -0700862 if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR &&
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700863 errorBufStrategy == ERROR_BUF_RETURN_NOTIFY) {
864 if (listener != nullptr) {
865 CaptureResultExtras extras = inResultExtras;
866 extras.errorStreamId = streamId;
867 listener->notifyError(
868 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
869 extras);
870 }
871 }
872
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800873 if (outputBuffers[i].buffer == nullptr) {
874 if (!useHalBufManager) {
875 // With HAL buffer management API, HAL sometimes will have to return buffers that
876 // has not got a output buffer handle filled yet. This is though illegal if HAL
877 // buffer management API is not being used.
878 ALOGE("%s: cannot return a null buffer!", __FUNCTION__);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700879 } else {
880 if (requested) {
881 sessionStatsBuilder.incCounter(streamId, /*dropped*/true, 0);
882 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800883 }
884 continue;
885 }
886
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800887 const auto& it = outputSurfaces.find(streamId);
888 status_t res = OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800889
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700890 // Do not return the buffer if the buffer status is error, and the error
891 // buffer strategy is CACHE.
Emilian Peevf4816702020-04-03 15:44:51 -0700892 if (outputBuffers[i].status != CAMERA_BUFFER_STATUS_ERROR ||
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700893 errorBufStrategy != ERROR_BUF_CACHE) {
894 if (it != outputSurfaces.end()) {
895 res = stream->returnBuffer(
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700896 outputBuffers[i], timestamp, readoutTimestamp, timestampIncreasing,
897 it->second, inResultExtras.frameNumber, transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700898 } else {
899 res = stream->returnBuffer(
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700900 outputBuffers[i], timestamp, readoutTimestamp, timestampIncreasing,
Emilian Peev5104fe92021-10-21 14:27:09 -0700901 std::vector<size_t> (), inResultExtras.frameNumber, transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700902 }
903 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800904 // Note: stream may be deallocated at this point, if this buffer was
905 // the last reference to it.
Shuzhen Wang316781a2020-08-18 18:11:01 -0700906 bool dropped = false;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800907 if (res == NO_INIT || res == DEAD_OBJECT) {
908 ALOGV("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700909 sessionStatsBuilder.stopCounter(streamId);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800910 } else if (res != OK) {
911 ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700912 dropped = true;
913 } else {
Emilian Peevf4816702020-04-03 15:44:51 -0700914 if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR || timestamp == 0) {
Shuzhen Wang316781a2020-08-18 18:11:01 -0700915 dropped = true;
916 }
917 }
918 if (requested) {
919 nsecs_t bufferTimeNs = systemTime();
920 int32_t captureLatencyMs = ns2ms(bufferTimeNs - requestTimeNs);
921 sessionStatsBuilder.incCounter(streamId, dropped, captureLatencyMs);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800922 }
923
924 // Long processing consumers can cause returnBuffer timeout for shared stream
925 // If that happens, cancel the buffer and send a buffer error to client
926 if (it != outputSurfaces.end() && res == TIMED_OUT &&
Emilian Peevf4816702020-04-03 15:44:51 -0700927 outputBuffers[i].status == CAMERA_BUFFER_STATUS_OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800928 // cancel the buffer
Emilian Peevf4816702020-04-03 15:44:51 -0700929 camera_stream_buffer_t sb = outputBuffers[i];
930 sb.status = CAMERA_BUFFER_STATUS_ERROR;
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700931 stream->returnBuffer(sb, /*timestamp*/0, /*readoutTimestamp*/0,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700932 timestampIncreasing, std::vector<size_t> (),
Emilian Peev5104fe92021-10-21 14:27:09 -0700933 inResultExtras.frameNumber, transform);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800934
935 if (listener != nullptr) {
936 CaptureResultExtras extras = inResultExtras;
937 extras.errorStreamId = streamId;
938 listener->notifyError(
939 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
940 extras);
941 }
942 }
943 }
944}
945
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700946void returnAndRemovePendingOutputBuffers(bool useHalBufManager,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700947 sp<NotificationListener> listener, InFlightRequest& request,
948 SessionStatsBuilder& sessionStatsBuilder) {
Shuzhen Wang828ade32022-01-10 17:19:02 -0800949 bool timestampIncreasing =
950 !((request.zslCapture && request.stillCapture) || request.hasInputBuffer);
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700951 nsecs_t readoutTimestamp = request.resultExtras.hasReadoutTimestamp ?
952 request.resultExtras.readoutTimestamp : 0;
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700953 returnOutputBuffers(useHalBufManager, listener,
954 request.pendingOutputBuffers.array(),
955 request.pendingOutputBuffers.size(),
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700956 request.shutterTimestamp, readoutTimestamp,
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700957 /*requested*/true, request.requestTimeNs, sessionStatsBuilder, timestampIncreasing,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700958 request.outputSurfaces, request.resultExtras,
Emilian Peev5104fe92021-10-21 14:27:09 -0700959 request.errorBufStrategy, request.transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700960
961 // Remove error buffers that are not cached.
962 for (auto iter = request.pendingOutputBuffers.begin();
963 iter != request.pendingOutputBuffers.end(); ) {
964 if (request.errorBufStrategy != ERROR_BUF_CACHE ||
Emilian Peevf4816702020-04-03 15:44:51 -0700965 iter->status != CAMERA_BUFFER_STATUS_ERROR) {
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700966 iter = request.pendingOutputBuffers.erase(iter);
967 } else {
968 iter++;
969 }
970 }
971}
972
Emilian Peevf4816702020-04-03 15:44:51 -0700973void notifyShutter(CaptureOutputStates& states, const camera_shutter_msg_t &msg) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800974 ATRACE_CALL();
975 ssize_t idx;
976
977 // Set timestamp for the request in the in-flight tracking
978 // and get the request ID to send upstream
979 {
980 std::lock_guard<std::mutex> l(states.inflightLock);
981 InFlightRequestMap& inflightMap = states.inflightMap;
982 idx = inflightMap.indexOfKey(msg.frame_number);
983 if (idx >= 0) {
984 InFlightRequest &r = inflightMap.editValueAt(idx);
985
986 // Verify ordering of shutter notifications
987 {
988 std::lock_guard<std::mutex> l(states.outputLock);
989 // TODO: need to track errors for tighter bounds on expected frame number.
990 if (r.hasInputBuffer) {
991 if (msg.frame_number < states.nextReprocShutterFrameNum) {
992 SET_ERR("Reprocess shutter notification out-of-order. Expected "
993 "notification for frame %d, got frame %d",
994 states.nextReprocShutterFrameNum, msg.frame_number);
995 return;
996 }
997 states.nextReprocShutterFrameNum = msg.frame_number + 1;
998 } else if (r.zslCapture && r.stillCapture) {
999 if (msg.frame_number < states.nextZslShutterFrameNum) {
1000 SET_ERR("ZSL still capture shutter notification out-of-order. Expected "
1001 "notification for frame %d, got frame %d",
1002 states.nextZslShutterFrameNum, msg.frame_number);
1003 return;
1004 }
1005 states.nextZslShutterFrameNum = msg.frame_number + 1;
1006 } else {
1007 if (msg.frame_number < states.nextShutterFrameNum) {
1008 SET_ERR("Shutter notification out-of-order. Expected "
1009 "notification for frame %d, got frame %d",
1010 states.nextShutterFrameNum, msg.frame_number);
1011 return;
1012 }
1013 states.nextShutterFrameNum = msg.frame_number + 1;
1014 }
1015 }
1016
1017 r.shutterTimestamp = msg.timestamp;
Shuzhen Wangffc4c012022-04-20 15:55:46 -07001018 if (msg.readout_timestamp_valid) {
1019 r.resultExtras.hasReadoutTimestamp = true;
1020 r.resultExtras.readoutTimestamp = msg.readout_timestamp;
1021 }
Shuzhen Wang696e4da2022-09-08 14:31:13 -07001022 if (r.minExpectedDuration != states.minFrameDuration ||
1023 r.isFixedFps != states.isFixedFps) {
Shuzhen Wang00abbeb2022-02-25 17:14:42 -08001024 for (size_t i = 0; i < states.outputStreams.size(); i++) {
1025 auto outputStream = states.outputStreams[i];
Shuzhen Wang696e4da2022-09-08 14:31:13 -07001026 outputStream->onMinDurationChanged(r.minExpectedDuration, r.isFixedFps);
Shuzhen Wang00abbeb2022-02-25 17:14:42 -08001027 }
1028 states.minFrameDuration = r.minExpectedDuration;
Shuzhen Wang696e4da2022-09-08 14:31:13 -07001029 states.isFixedFps = r.isFixedFps;
Shuzhen Wang00abbeb2022-02-25 17:14:42 -08001030 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001031 if (r.hasCallback) {
1032 ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
Austin Borger1c1bee02023-06-01 16:51:35 -07001033 states.cameraId.c_str(), __FUNCTION__,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001034 msg.frame_number, r.resultExtras.requestId, msg.timestamp);
1035 // Call listener, if any
1036 if (states.listener != nullptr) {
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001037 r.resultExtras.lastCompletedRegularFrameNumber =
1038 states.lastCompletedRegularFrameNumber;
1039 r.resultExtras.lastCompletedReprocessFrameNumber =
1040 states.lastCompletedReprocessFrameNumber;
1041 r.resultExtras.lastCompletedZslFrameNumber =
1042 states.lastCompletedZslFrameNumber;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001043 states.listener->notifyShutter(r.resultExtras, msg.timestamp);
1044 }
1045 // send pending result and buffers
Shuzhen Wang3c00b092022-11-08 22:53:07 +00001046 const auto& cameraIdsWithZoom = getCameraIdsWithZoomLocked(
1047 inflightMap, r.pendingMetadata, r.cameraIdsWithZoom);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001048 sendCaptureResult(states,
1049 r.pendingMetadata, r.resultExtras,
1050 r.collectedPartialResult, msg.frame_number,
1051 r.hasInputBuffer, r.zslCapture && r.stillCapture,
Shuzhen Wang3c00b092022-11-08 22:53:07 +00001052 r.rotateAndCropAuto, cameraIdsWithZoom, r.physicalMetadatas);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001053 }
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001054 returnAndRemovePendingOutputBuffers(
Shuzhen Wang316781a2020-08-18 18:11:01 -07001055 states.useHalBufManager, states.listener, r, states.sessionStatsBuilder);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001056
1057 removeInFlightRequestIfReadyLocked(states, idx);
1058 }
1059 }
1060 if (idx < 0) {
1061 SET_ERR("Shutter notification for non-existent frame number %d",
1062 msg.frame_number);
1063 }
1064}
1065
Emilian Peevf4816702020-04-03 15:44:51 -07001066void notifyError(CaptureOutputStates& states, const camera_error_msg_t &msg) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001067 ATRACE_CALL();
1068 // Map camera HAL error codes to ICameraDeviceCallback error codes
1069 // Index into this with the HAL error code
Emilian Peevf4816702020-04-03 15:44:51 -07001070 static const int32_t halErrorMap[CAMERA_MSG_NUM_ERRORS] = {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001071 // 0 = Unused error code
1072 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
Emilian Peevf4816702020-04-03 15:44:51 -07001073 // 1 = CAMERA_MSG_ERROR_DEVICE
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001074 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Emilian Peevf4816702020-04-03 15:44:51 -07001075 // 2 = CAMERA_MSG_ERROR_REQUEST
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001076 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Emilian Peevf4816702020-04-03 15:44:51 -07001077 // 3 = CAMERA_MSG_ERROR_RESULT
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001078 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
Emilian Peevf4816702020-04-03 15:44:51 -07001079 // 4 = CAMERA_MSG_ERROR_BUFFER
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001080 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
1081 };
1082
1083 int32_t errorCode =
1084 ((msg.error_code >= 0) &&
Emilian Peevf4816702020-04-03 15:44:51 -07001085 (msg.error_code < CAMERA_MSG_NUM_ERRORS)) ?
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001086 halErrorMap[msg.error_code] :
1087 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
1088
1089 int streamId = 0;
Austin Borger1c1bee02023-06-01 16:51:35 -07001090 std::string physicalCameraId;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001091 if (msg.error_stream != nullptr) {
1092 Camera3Stream *stream =
1093 Camera3Stream::cast(msg.error_stream);
1094 streamId = stream->getId();
Austin Borger1c1bee02023-06-01 16:51:35 -07001095 physicalCameraId = stream->physicalCameraId();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001096 }
1097 ALOGV("Camera %s: %s: HAL error, frame %d, stream %d: %d",
Austin Borger1c1bee02023-06-01 16:51:35 -07001098 states.cameraId.c_str(), __FUNCTION__, msg.frame_number,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001099 streamId, msg.error_code);
1100
1101 CaptureResultExtras resultExtras;
1102 switch (errorCode) {
1103 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
1104 // SET_ERR calls into listener to notify application
1105 SET_ERR("Camera HAL reported serious device error");
1106 break;
1107 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
1108 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001109 {
1110 std::lock_guard<std::mutex> l(states.inflightLock);
1111 ssize_t idx = states.inflightMap.indexOfKey(msg.frame_number);
1112 if (idx >= 0) {
1113 InFlightRequest &r = states.inflightMap.editValueAt(idx);
1114 r.requestStatus = msg.error_code;
1115 resultExtras = r.resultExtras;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001116 bool physicalDeviceResultError = false;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001117 if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
1118 errorCode) {
1119 if (physicalCameraId.size() > 0) {
Shuzhen Wang99080502021-03-07 21:08:20 -08001120 bool validPhysicalCameraId =
Austin Borger1c1bee02023-06-01 16:51:35 -07001121 erasePhysicalCameraIdSet(r.physicalCameraIds, physicalCameraId);
Shuzhen Wang99080502021-03-07 21:08:20 -08001122 if (!validPhysicalCameraId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001123 ALOGE("%s: Reported result failure for physical camera device: %s "
1124 " which is not part of the respective request!",
Austin Borger1c1bee02023-06-01 16:51:35 -07001125 __FUNCTION__, physicalCameraId.c_str());
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001126 break;
1127 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001128 resultExtras.errorPhysicalCameraId = physicalCameraId;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001129 physicalDeviceResultError = true;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001130 }
1131 }
1132
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001133 if (!physicalDeviceResultError) {
Greg Kaiser51b882c2020-06-10 05:41:44 +00001134 r.skipResultMetadata = true;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001135 if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT
1136 == errorCode) {
1137 r.errorBufStrategy = ERROR_BUF_RETURN_NOTIFY;
1138 } else {
1139 // errorCode is ERROR_CAMERA_REQUEST
1140 r.errorBufStrategy = ERROR_BUF_RETURN;
1141 }
1142
1143 // Check whether the buffers returned. If they returned,
1144 // remove inflight request.
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001145 removeInFlightRequestIfReadyLocked(states, idx);
1146 }
1147 } else {
1148 resultExtras.frameNumber = msg.frame_number;
1149 ALOGE("Camera %s: %s: cannot find in-flight request on "
Austin Borger1c1bee02023-06-01 16:51:35 -07001150 "frame %" PRId64 " error", states.cameraId.c_str(), __FUNCTION__,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001151 resultExtras.frameNumber);
1152 }
1153 }
1154 resultExtras.errorStreamId = streamId;
1155 if (states.listener != nullptr) {
1156 states.listener->notifyError(errorCode, resultExtras);
1157 } else {
1158 ALOGE("Camera %s: %s: no listener available",
Austin Borger1c1bee02023-06-01 16:51:35 -07001159 states.cameraId.c_str(), __FUNCTION__);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001160 }
1161 break;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001162 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
1163 // Do not depend on HAL ERROR_CAMERA_BUFFER to send buffer error
1164 // callback to the app. Rather, use STATUS_ERROR of image buffers.
1165 break;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001166 default:
1167 // SET_ERR calls notifyError
1168 SET_ERR("Unknown error message from HAL: %d", msg.error_code);
1169 break;
1170 }
1171}
1172
Emilian Peevf4816702020-04-03 15:44:51 -07001173void notify(CaptureOutputStates& states, const camera_notify_msg *msg) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001174 switch (msg->type) {
Emilian Peevf4816702020-04-03 15:44:51 -07001175 case CAMERA_MSG_ERROR: {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001176 notifyError(states, msg->message.error);
1177 break;
1178 }
Emilian Peevf4816702020-04-03 15:44:51 -07001179 case CAMERA_MSG_SHUTTER: {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001180 notifyShutter(states, msg->message.shutter);
1181 break;
1182 }
1183 default:
1184 SET_ERR("Unknown notify message from HAL: %d",
1185 msg->type);
1186 }
1187}
1188
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001189void flushInflightRequests(FlushInflightReqStates& states) {
1190 ATRACE_CALL();
Shuzhen Wang316781a2020-08-18 18:11:01 -07001191 { // First return buffers cached in inFlightMap
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001192 std::lock_guard<std::mutex> l(states.inflightLock);
1193 for (size_t idx = 0; idx < states.inflightMap.size(); idx++) {
Greg Kaiser51b882c2020-06-10 05:41:44 +00001194 const InFlightRequest &request = states.inflightMap.valueAt(idx);
1195 returnOutputBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001196 states.useHalBufManager, states.listener,
1197 request.pendingOutputBuffers.array(),
Shuzhen Wang90708ea2021-11-04 11:40:49 -07001198 request.pendingOutputBuffers.size(), /*timestamp*/0, /*readoutTimestamp*/0,
1199 /*requested*/true, request.requestTimeNs, states.sessionStatsBuilder,
1200 /*timestampIncreasing*/true, request.outputSurfaces, request.resultExtras,
1201 request.errorBufStrategy);
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001202 ALOGW("%s: Frame %d | Timestamp: %" PRId64 ", metadata"
1203 " arrived: %s, buffers left: %d.\n", __FUNCTION__,
1204 states.inflightMap.keyAt(idx), request.shutterTimestamp,
1205 request.haveResultMetadata ? "true" : "false",
1206 request.numBuffersLeft);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001207 }
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001208
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001209 states.inflightMap.clear();
1210 states.inflightIntf.onInflightMapFlushedLocked();
1211 }
1212
1213 // Then return all inflight buffers not returned by HAL
1214 std::vector<std::pair<int32_t, int32_t>> inflightKeys;
1215 states.flushBufferIntf.getInflightBufferKeys(&inflightKeys);
1216
1217 // Inflight buffers for HAL buffer manager
1218 std::vector<uint64_t> inflightRequestBufferKeys;
1219 states.flushBufferIntf.getInflightRequestBufferKeys(&inflightRequestBufferKeys);
1220
1221 // (streamId, frameNumber, buffer_handle_t*) tuple for all inflight buffers.
1222 // frameNumber will be -1 for buffers from HAL buffer manager
1223 std::vector<std::tuple<int32_t, int32_t, buffer_handle_t*>> inflightBuffers;
1224 inflightBuffers.reserve(inflightKeys.size() + inflightRequestBufferKeys.size());
1225
1226 for (auto& pair : inflightKeys) {
1227 int32_t frameNumber = pair.first;
1228 int32_t streamId = pair.second;
1229 buffer_handle_t* buffer;
1230 status_t res = states.bufferRecordsIntf.popInflightBuffer(frameNumber, streamId, &buffer);
1231 if (res != OK) {
1232 ALOGE("%s: Frame %d: No in-flight buffer for stream %d",
1233 __FUNCTION__, frameNumber, streamId);
1234 continue;
1235 }
1236 inflightBuffers.push_back(std::make_tuple(streamId, frameNumber, buffer));
1237 }
1238
1239 for (auto& bufferId : inflightRequestBufferKeys) {
1240 int32_t streamId = -1;
1241 buffer_handle_t* buffer = nullptr;
1242 status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
1243 bufferId, &buffer, &streamId);
1244 if (res != OK) {
1245 ALOGE("%s: cannot find in-flight buffer %" PRIu64, __FUNCTION__, bufferId);
1246 continue;
1247 }
1248 inflightBuffers.push_back(std::make_tuple(streamId, /*frameNumber*/-1, buffer));
1249 }
1250
1251 std::vector<sp<Camera3StreamInterface>> streams = states.flushBufferIntf.getAllStreams();
1252
1253 for (auto& tuple : inflightBuffers) {
1254 status_t res = OK;
1255 int32_t streamId = std::get<0>(tuple);
1256 int32_t frameNumber = std::get<1>(tuple);
1257 buffer_handle_t* buffer = std::get<2>(tuple);
1258
Emilian Peevf4816702020-04-03 15:44:51 -07001259 camera_stream_buffer_t streamBuffer;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001260 streamBuffer.buffer = buffer;
Emilian Peevf4816702020-04-03 15:44:51 -07001261 streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001262 streamBuffer.acquire_fence = -1;
1263 streamBuffer.release_fence = -1;
1264
1265 for (auto& stream : streams) {
1266 if (streamId == stream->getId()) {
1267 // Return buffer to deleted stream
Emilian Peevf4816702020-04-03 15:44:51 -07001268 camera_stream* halStream = stream->asHalStream();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001269 streamBuffer.stream = halStream;
1270 switch (halStream->stream_type) {
Emilian Peevf4816702020-04-03 15:44:51 -07001271 case CAMERA_STREAM_OUTPUT:
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001272 res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0,
Shuzhen Wang90708ea2021-11-04 11:40:49 -07001273 /*readoutTimestamp*/0, /*timestampIncreasing*/true,
Shuzhen Wang316781a2020-08-18 18:11:01 -07001274 std::vector<size_t> (), frameNumber);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001275 if (res != OK) {
1276 ALOGE("%s: Can't return output buffer for frame %d to"
1277 " stream %d: %s (%d)", __FUNCTION__,
1278 frameNumber, streamId, strerror(-res), res);
1279 }
1280 break;
Emilian Peevf4816702020-04-03 15:44:51 -07001281 case CAMERA_STREAM_INPUT:
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001282 res = stream->returnInputBuffer(streamBuffer);
1283 if (res != OK) {
1284 ALOGE("%s: Can't return input buffer for frame %d to"
1285 " stream %d: %s (%d)", __FUNCTION__,
1286 frameNumber, streamId, strerror(-res), res);
1287 }
1288 break;
1289 default: // Bi-direcitonal stream is deprecated
1290 ALOGE("%s: stream %d has unknown stream type %d",
1291 __FUNCTION__, streamId, halStream->stream_type);
1292 break;
1293 }
1294 break;
1295 }
1296 }
1297 }
1298}
1299
1300} // camera3
1301} // namespace android