blob: 88a7d690dec0df54b8ff0c203385a441489bfc0a [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
Shuzhen Wangcd8811c2022-08-29 17:23:52 +0000162void correctMeteringRegions(camera_metadata_t *meta) {
163 if (meta == nullptr) return;
164
165 uint32_t meteringRegionKeys[] = {
166 ANDROID_CONTROL_AE_REGIONS,
167 ANDROID_CONTROL_AWB_REGIONS,
168 ANDROID_CONTROL_AF_REGIONS };
169
170 for (uint32_t key : meteringRegionKeys) {
171 camera_metadata_entry_t entry;
172 int res = find_camera_metadata_entry(meta, key, &entry);
173 if (res != OK) continue;
174
175 for (size_t i = 0; i < entry.count; i += 5) {
176 if (entry.data.i32[0] > entry.data.i32[2]) {
177 ALOGW("%s: Invalid metering region (%d): left: %d, right: %d",
178 __FUNCTION__, key, entry.data.i32[0], entry.data.i32[2]);
179 entry.data.i32[2] = entry.data.i32[0];
180 }
181 if (entry.data.i32[1] > entry.data.i32[3]) {
182 ALOGW("%s: Invalid metering region (%d): top: %d, bottom: %d",
183 __FUNCTION__, key, entry.data.i32[1], entry.data.i32[3]);
184 entry.data.i32[3] = entry.data.i32[1];
185 }
186 }
187 }
188}
189
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800190void insertResultLocked(CaptureOutputStates& states, CaptureResult *result, uint32_t frameNumber) {
191 if (result == nullptr) return;
192
193 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
194 result->mMetadata.getAndLock());
195 set_camera_metadata_vendor_id(meta, states.vendorTagId);
Shuzhen Wangcd8811c2022-08-29 17:23:52 +0000196 correctMeteringRegions(meta);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800197 result->mMetadata.unlock(meta);
198
199 if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
200 (int32_t*)&frameNumber, 1) != OK) {
201 SET_ERR("Failed to set frame number %d in metadata", frameNumber);
202 return;
203 }
204
205 if (result->mMetadata.update(ANDROID_REQUEST_ID, &result->mResultExtras.requestId, 1) != OK) {
206 SET_ERR("Failed to set request ID in metadata for frame %d", frameNumber);
207 return;
208 }
209
210 // Update vendor tag id for physical metadata
211 for (auto& physicalMetadata : result->mPhysicalMetadatas) {
212 camera_metadata_t *pmeta = const_cast<camera_metadata_t *>(
213 physicalMetadata.mPhysicalCameraMetadata.getAndLock());
214 set_camera_metadata_vendor_id(pmeta, states.vendorTagId);
Shuzhen Wangcd8811c2022-08-29 17:23:52 +0000215 correctMeteringRegions(pmeta);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800216 physicalMetadata.mPhysicalCameraMetadata.unlock(pmeta);
217 }
218
219 // Valid result, insert into queue
Jayant Chowdhary8a0be292020-01-08 13:10:38 -0800220 std::list<CaptureResult>::iterator queuedResult =
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800221 states.resultQueue.insert(states.resultQueue.end(), CaptureResult(*result));
Jayant Chowdhary8a0be292020-01-08 13:10:38 -0800222 ALOGV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800223 ", burstId = %" PRId32, __FUNCTION__,
224 queuedResult->mResultExtras.requestId,
225 queuedResult->mResultExtras.frameNumber,
226 queuedResult->mResultExtras.burstId);
227
228 states.resultSignal.notify_one();
229}
230
231
232void sendPartialCaptureResult(CaptureOutputStates& states,
233 const camera_metadata_t * partialResult,
234 const CaptureResultExtras &resultExtras, uint32_t frameNumber) {
235 ATRACE_CALL();
236 std::lock_guard<std::mutex> l(states.outputLock);
237
238 CaptureResult captureResult;
239 captureResult.mResultExtras = resultExtras;
240 captureResult.mMetadata = partialResult;
241
242 // Fix up result metadata for monochrome camera.
243 status_t res = fixupMonochromeTags(states, states.deviceInfo, captureResult.mMetadata);
244 if (res != OK) {
245 SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
246 return;
247 }
248
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700249 // Update partial result by removing keys remapped by DistortionCorrection, ZoomRatio,
250 // and RotationAndCrop mappers.
251 std::set<uint32_t> keysToRemove;
252
Austin Borger1c1bee02023-06-01 16:51:35 -0700253 auto iter = states.distortionMappers.find(states.cameraId);
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700254 if (iter != states.distortionMappers.end()) {
255 const auto& remappedKeys = iter->second.getRemappedKeys();
256 keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
257 }
258
Austin Borger1c1bee02023-06-01 16:51:35 -0700259 const auto& remappedKeys = states.zoomRatioMappers[states.cameraId].getRemappedKeys();
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700260 keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
261
Austin Borger1c1bee02023-06-01 16:51:35 -0700262 auto mapper = states.rotateAndCropMappers.find(states.cameraId);
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700263 if (mapper != states.rotateAndCropMappers.end()) {
Ravneet58485902023-04-07 04:34:48 +0000264 const auto& remappedKeys = mapper->second.getRemappedKeys();
Shuzhen Wang8c75a642020-10-29 21:58:53 -0700265 keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
266 }
267
268 for (uint32_t key : keysToRemove) {
269 captureResult.mMetadata.erase(key);
270 }
271
272 // Send partial result
273 if (captureResult.mMetadata.entryCount() > 0) {
274 insertResultLocked(states, &captureResult, frameNumber);
275 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800276}
277
278void sendCaptureResult(
279 CaptureOutputStates& states,
280 CameraMetadata &pendingMetadata,
281 CaptureResultExtras &resultExtras,
282 CameraMetadata &collectedPartialResult,
283 uint32_t frameNumber,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800284 bool reprocess, bool zslStillCapture, bool rotateAndCropAuto,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800285 const std::set<std::string>& cameraIdsWithZoom,
286 const std::vector<PhysicalCaptureResultInfo>& physicalMetadatas) {
287 ATRACE_CALL();
288 if (pendingMetadata.isEmpty())
289 return;
290
291 std::lock_guard<std::mutex> l(states.outputLock);
292
293 // TODO: need to track errors for tighter bounds on expected frame number
294 if (reprocess) {
295 if (frameNumber < states.nextReprocResultFrameNum) {
296 SET_ERR("Out-of-order reprocess capture result metadata submitted! "
297 "(got frame number %d, expecting %d)",
298 frameNumber, states.nextReprocResultFrameNum);
299 return;
300 }
301 states.nextReprocResultFrameNum = frameNumber + 1;
302 } else if (zslStillCapture) {
303 if (frameNumber < states.nextZslResultFrameNum) {
304 SET_ERR("Out-of-order ZSL still capture result metadata submitted! "
305 "(got frame number %d, expecting %d)",
306 frameNumber, states.nextZslResultFrameNum);
307 return;
308 }
309 states.nextZslResultFrameNum = frameNumber + 1;
310 } else {
311 if (frameNumber < states.nextResultFrameNum) {
312 SET_ERR("Out-of-order capture result metadata submitted! "
313 "(got frame number %d, expecting %d)",
314 frameNumber, states.nextResultFrameNum);
315 return;
316 }
317 states.nextResultFrameNum = frameNumber + 1;
318 }
319
320 CaptureResult captureResult;
321 captureResult.mResultExtras = resultExtras;
322 captureResult.mMetadata = pendingMetadata;
323 captureResult.mPhysicalMetadatas = physicalMetadatas;
324
325 // Append any previous partials to form a complete result
326 if (states.usePartialResult && !collectedPartialResult.isEmpty()) {
327 captureResult.mMetadata.append(collectedPartialResult);
328 }
329
330 captureResult.mMetadata.sort();
331
332 // Check that there's a timestamp in the result metadata
333 camera_metadata_entry timestamp = captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
334 if (timestamp.count == 0) {
335 SET_ERR("No timestamp provided by HAL for frame %d!",
336 frameNumber);
337 return;
338 }
Yin-Chia Yehc530c592020-03-09 14:50:36 -0700339 nsecs_t sensorTimestamp = timestamp.data.i64[0];
340
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800341 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
342 camera_metadata_entry timestamp =
343 physicalMetadata.mPhysicalCameraMetadata.find(ANDROID_SENSOR_TIMESTAMP);
344 if (timestamp.count == 0) {
345 SET_ERR("No timestamp provided by HAL for physical camera %s frame %d!",
Austin Borger1c1bee02023-06-01 16:51:35 -0700346 physicalMetadata.mPhysicalCameraId.c_str(), frameNumber);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800347 return;
348 }
349 }
350
351 // Fix up some result metadata to account for HAL-level distortion correction
Yin-Chia Yeh7ffbd982020-04-13 10:04:23 -0700352 status_t res = OK;
Austin Borger1c1bee02023-06-01 16:51:35 -0700353 auto iter = states.distortionMappers.find(states.cameraId);
Yin-Chia Yeh7ffbd982020-04-13 10:04:23 -0700354 if (iter != states.distortionMappers.end()) {
355 res = iter->second.correctCaptureResult(&captureResult.mMetadata);
356 if (res != OK) {
357 SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
358 frameNumber, strerror(-res), res);
359 return;
360 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800361 }
362
363 // Fix up result metadata to account for zoom ratio availabilities between
364 // HAL and app.
Austin Borger1c1bee02023-06-01 16:51:35 -0700365 bool zoomRatioIs1 = cameraIdsWithZoom.find(states.cameraId) == cameraIdsWithZoom.end();
366 res = states.zoomRatioMappers[states.cameraId].updateCaptureResult(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800367 &captureResult.mMetadata, zoomRatioIs1);
368 if (res != OK) {
369 SET_ERR("Failed to update capture result zoom ratio metadata for frame %d: %s (%d)",
370 frameNumber, strerror(-res), res);
371 return;
372 }
373
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800374 // Fix up result metadata to account for rotateAndCrop in AUTO mode
375 if (rotateAndCropAuto) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700376 auto mapper = states.rotateAndCropMappers.find(states.cameraId);
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800377 if (mapper != states.rotateAndCropMappers.end()) {
378 res = mapper->second.updateCaptureResult(
379 &captureResult.mMetadata);
380 if (res != OK) {
381 SET_ERR("Unable to correct capture result rotate-and-crop for frame %d: %s (%d)",
382 frameNumber, strerror(-res), res);
383 return;
384 }
385 }
386 }
387
Bharatt Kukrejad33fe9f2022-11-23 21:52:52 +0000388 // Fix up autoframing metadata
Bharatt Kukreja0e13db32022-12-07 21:38:45 +0000389 res = fixupAutoframingTags(captureResult.mMetadata);
390 if (res != OK) {
391 SET_ERR("Failed to set autoframing defaults in result metadata: %s (%d)",
392 strerror(-res), res);
393 return;
Bharatt Kukrejad33fe9f2022-11-23 21:52:52 +0000394 }
Bharatt Kukreja0e13db32022-12-07 21:38:45 +0000395 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
396 res = fixupAutoframingTags(physicalMetadata.mPhysicalCameraMetadata);
397 if (res != OK) {
398 SET_ERR("Failed to set autoframing defaults in physical result metadata: %s (%d)",
399 strerror(-res), res);
Bharatt Kukrejad33fe9f2022-11-23 21:52:52 +0000400 return;
401 }
402 }
403
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800404 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700405 const std::string cameraId = physicalMetadata.mPhysicalCameraId;
406 auto mapper = states.distortionMappers.find(cameraId);
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800407 if (mapper != states.distortionMappers.end()) {
408 res = mapper->second.correctCaptureResult(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800409 &physicalMetadata.mPhysicalCameraMetadata);
410 if (res != OK) {
411 SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
412 frameNumber, strerror(-res), res);
413 return;
414 }
415 }
416
Austin Borger1c1bee02023-06-01 16:51:35 -0700417 zoomRatioIs1 = cameraIdsWithZoom.find(cameraId) == cameraIdsWithZoom.end();
418 res = states.zoomRatioMappers[cameraId].updateCaptureResult(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800419 &physicalMetadata.mPhysicalCameraMetadata, zoomRatioIs1);
420 if (res != OK) {
421 SET_ERR("Failed to update camera %s's physical zoom ratio metadata for "
Austin Borger1c1bee02023-06-01 16:51:35 -0700422 "frame %d: %s(%d)", cameraId.c_str(), frameNumber, strerror(-res), res);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800423 return;
424 }
425 }
426
427 // Fix up result metadata for monochrome camera.
428 res = fixupMonochromeTags(states, states.deviceInfo, captureResult.mMetadata);
429 if (res != OK) {
430 SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
431 return;
432 }
433 for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700434 const std::string &cameraId = physicalMetadata.mPhysicalCameraId;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800435 res = fixupMonochromeTags(states,
Austin Borger1c1bee02023-06-01 16:51:35 -0700436 states.physicalDeviceInfoMap.at(cameraId),
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800437 physicalMetadata.mPhysicalCameraMetadata);
438 if (res != OK) {
439 SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
440 return;
441 }
442 }
443
444 std::unordered_map<std::string, CameraMetadata> monitoredPhysicalMetadata;
445 for (auto& m : physicalMetadatas) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700446 monitoredPhysicalMetadata.emplace(m.mPhysicalCameraId,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800447 CameraMetadata(m.mPhysicalCameraMetadata));
448 }
449 states.tagMonitor.monitorMetadata(TagMonitor::RESULT,
Yin-Chia Yehc530c592020-03-09 14:50:36 -0700450 frameNumber, sensorTimestamp, captureResult.mMetadata,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800451 monitoredPhysicalMetadata);
452
453 insertResultLocked(states, &captureResult, frameNumber);
454}
455
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800456void removeInFlightMapEntryLocked(CaptureOutputStates& states, int idx) {
457 ATRACE_CALL();
458 InFlightRequestMap& inflightMap = states.inflightMap;
459 nsecs_t duration = inflightMap.valueAt(idx).maxExpectedDuration;
460 inflightMap.removeItemsAt(idx, 1);
461
462 states.inflightIntf.onInflightEntryRemovedLocked(duration);
463}
464
465void removeInFlightRequestIfReadyLocked(CaptureOutputStates& states, int idx) {
466 InFlightRequestMap& inflightMap = states.inflightMap;
Greg Kaiser51b882c2020-06-10 05:41:44 +0000467 const InFlightRequest &request = inflightMap.valueAt(idx);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800468 const uint32_t frameNumber = inflightMap.keyAt(idx);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700469 SessionStatsBuilder& sessionStatsBuilder = states.sessionStatsBuilder;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800470
471 nsecs_t sensorTimestamp = request.sensorTimestamp;
472 nsecs_t shutterTimestamp = request.shutterTimestamp;
473
474 // Check if it's okay to remove the request from InFlightMap:
475 // In the case of a successful request:
476 // all input and output buffers, all result metadata, shutter callback
477 // arrived.
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700478 // In the case of an unsuccessful request:
479 // all input and output buffers, as well as request/result error notifications, arrived.
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800480 if (request.numBuffersLeft == 0 &&
481 (request.skipResultMetadata ||
482 (request.haveResultMetadata && shutterTimestamp != 0))) {
483 if (request.stillCapture) {
484 ATRACE_ASYNC_END("still capture", frameNumber);
485 }
486
487 ATRACE_ASYNC_END("frame capture", frameNumber);
488
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -0400489 // Validation check - if sensor timestamp matches shutter timestamp in the
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800490 // case of request having callback.
491 if (request.hasCallback && request.requestStatus == OK &&
492 sensorTimestamp != shutterTimestamp) {
493 SET_ERR("sensor timestamp (%" PRId64
494 ") for frame %d doesn't match shutter timestamp (%" PRId64 ")",
495 sensorTimestamp, frameNumber, shutterTimestamp);
496 }
497
498 // for an unsuccessful request, it may have pending output buffers to
499 // return.
500 assert(request.requestStatus != OK ||
501 request.pendingOutputBuffers.size() == 0);
502
Greg Kaiser51b882c2020-06-10 05:41:44 +0000503 returnOutputBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800504 states.useHalBufManager, states.listener,
505 request.pendingOutputBuffers.array(),
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700506 request.pendingOutputBuffers.size(), /*timestamp*/0, /*readoutTimestamp*/0,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700507 /*requested*/true, request.requestTimeNs, states.sessionStatsBuilder,
508 /*timestampIncreasing*/true,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700509 request.outputSurfaces, request.resultExtras,
Emilian Peev5104fe92021-10-21 14:27:09 -0700510 request.errorBufStrategy, request.transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700511
512 // Note down the just completed frame number
513 if (request.hasInputBuffer) {
514 states.lastCompletedReprocessFrameNumber = frameNumber;
Shuzhen Wang828ade32022-01-10 17:19:02 -0800515 } else if (request.zslCapture && request.stillCapture) {
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700516 states.lastCompletedZslFrameNumber = frameNumber;
517 } else {
518 states.lastCompletedRegularFrameNumber = frameNumber;
519 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800520
Shuzhen Wang316781a2020-08-18 18:11:01 -0700521 sessionStatsBuilder.incResultCounter(request.skipResultMetadata);
522
Greg Kaiser51b882c2020-06-10 05:41:44 +0000523 removeInFlightMapEntryLocked(states, idx);
524 ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800525 }
526
527 states.inflightIntf.checkInflightMapLengthLocked();
528}
529
Shuzhen Wang99080502021-03-07 21:08:20 -0800530// Erase the subset of physicalCameraIds that contains id
531bool erasePhysicalCameraIdSet(
Austin Borger1c1bee02023-06-01 16:51:35 -0700532 std::set<std::set<std::string>>& physicalCameraIds, const std::string& id) {
Shuzhen Wang99080502021-03-07 21:08:20 -0800533 bool found = false;
534 for (auto iter = physicalCameraIds.begin(); iter != physicalCameraIds.end(); iter++) {
535 if (iter->count(id) == 1) {
536 physicalCameraIds.erase(iter);
537 found = true;
538 break;
539 }
540 }
541 return found;
542}
543
Shuzhen Wang3c00b092022-11-08 22:53:07 +0000544const std::set<std::string>& getCameraIdsWithZoomLocked(
545 const InFlightRequestMap& inflightMap, const CameraMetadata& metadata,
546 const std::set<std::string>& cameraIdsWithZoom) {
547 camera_metadata_ro_entry overrideEntry =
548 metadata.find(ANDROID_CONTROL_SETTINGS_OVERRIDE);
549 camera_metadata_ro_entry frameNumberEntry =
550 metadata.find(ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER);
551 if (overrideEntry.count != 1
552 || overrideEntry.data.i32[0] != ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM
553 || frameNumberEntry.count != 1) {
554 // No valid overriding frame number, skip
555 return cameraIdsWithZoom;
556 }
557
558 uint32_t overridingFrameNumber = frameNumberEntry.data.i32[0];
559 ssize_t idx = inflightMap.indexOfKey(overridingFrameNumber);
560 if (idx < 0) {
561 ALOGE("%s: Failed to find pending request #%d in inflight map",
562 __FUNCTION__, overridingFrameNumber);
563 return cameraIdsWithZoom;
564 }
565
566 const InFlightRequest &r = inflightMap.valueFor(overridingFrameNumber);
567 return r.cameraIdsWithZoom;
568}
569
Emilian Peevf4816702020-04-03 15:44:51 -0700570void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800571 ATRACE_CALL();
572
573 status_t res;
574
575 uint32_t frameNumber = result->frame_number;
576 if (result->result == NULL && result->num_output_buffers == 0 &&
577 result->input_buffer == NULL) {
578 SET_ERR("No result data provided by HAL for frame %d",
579 frameNumber);
580 return;
581 }
582
583 if (!states.usePartialResult &&
584 result->result != NULL &&
585 result->partial_result != 1) {
586 SET_ERR("Result is malformed for frame %d: partial_result %u must be 1"
587 " if partial result is not supported",
588 frameNumber, result->partial_result);
589 return;
590 }
591
592 bool isPartialResult = false;
593 CameraMetadata collectedPartialResult;
594 bool hasInputBufferInRequest = false;
595
596 // Get shutter timestamp and resultExtras from list of in-flight requests,
597 // where it was added by the shutter notification for this frame. If the
598 // shutter timestamp isn't received yet, append the output buffers to the
599 // in-flight request and they will be returned when the shutter timestamp
600 // arrives. Update the in-flight status and remove the in-flight entry if
601 // all result data and shutter timestamp have been received.
602 nsecs_t shutterTimestamp = 0;
603 {
604 std::lock_guard<std::mutex> l(states.inflightLock);
605 ssize_t idx = states.inflightMap.indexOfKey(frameNumber);
606 if (idx == NAME_NOT_FOUND) {
607 SET_ERR("Unknown frame number for capture result: %d",
608 frameNumber);
609 return;
610 }
611 InFlightRequest &request = states.inflightMap.editValueAt(idx);
612 ALOGVV("%s: got InFlightRequest requestId = %" PRId32
613 ", frameNumber = %" PRId64 ", burstId = %" PRId32
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700614 ", partialResultCount = %d/%d, hasCallback = %d, num_output_buffers %d"
615 ", usePartialResult = %d",
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800616 __FUNCTION__, request.resultExtras.requestId,
617 request.resultExtras.frameNumber, request.resultExtras.burstId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700618 result->partial_result, states.numPartialResults,
619 request.hasCallback, result->num_output_buffers,
620 states.usePartialResult);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800621 // Always update the partial count to the latest one if it's not 0
622 // (buffers only). When framework aggregates adjacent partial results
623 // into one, the latest partial count will be used.
624 if (result->partial_result != 0)
625 request.resultExtras.partialResultCount = result->partial_result;
626
Austin Borgerc8099762023-01-12 17:08:46 -0800627 if (result->result != nullptr) {
Emilian Peev5104fe92021-10-21 14:27:09 -0700628 camera_metadata_ro_entry entry;
629 auto ret = find_camera_metadata_ro_entry(result->result,
630 ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID, &entry);
631 if ((ret == OK) && (entry.count > 0)) {
632 std::string physicalId(reinterpret_cast<const char *>(entry.data.u8));
Austin Borgerc8099762023-01-12 17:08:46 -0800633 if (!states.activePhysicalId.empty() && physicalId != states.activePhysicalId) {
634 states.listener->notifyPhysicalCameraChange(physicalId);
635 }
636 states.activePhysicalId = physicalId;
637
638 if (!states.legacyClient && !states.overrideToPortrait) {
639 auto deviceInfo = states.physicalDeviceInfoMap.find(physicalId);
640 if (deviceInfo != states.physicalDeviceInfoMap.end()) {
641 auto orientation = deviceInfo->second.find(ANDROID_SENSOR_ORIENTATION);
642 if (orientation.count > 0) {
Emilian Peev747be7e2023-03-31 11:10:08 -0700643 int32_t transform;
Austin Borgerc8099762023-01-12 17:08:46 -0800644 ret = CameraUtils::getRotationTransform(deviceInfo->second,
Emilian Peev747be7e2023-03-31 11:10:08 -0700645 OutputConfiguration::MIRROR_MODE_AUTO, &transform);
646 if (ret == OK) {
647 // It is possible for camera providers to return the capture
648 // results after the processed frames. In such scenario, we will
649 // not be able to set the output transformation before the frames
650 // return back to the consumer for the current capture request
651 // but we could still try and configure it for any future requests
652 // that are still in flight. The assumption is that the physical
653 // device id remains the same for the duration of the pending queue.
654 for (size_t i = 0; i < states.inflightMap.size(); i++) {
655 auto &r = states.inflightMap.editValueAt(i);
656 if (r.requestTimeNs >= request.requestTimeNs) {
657 r.transform = transform;
658 }
659 }
660 } else {
Austin Borgerc8099762023-01-12 17:08:46 -0800661 ALOGE("%s: Failed to calculate current stream transformation: %s "
662 "(%d)", __FUNCTION__, strerror(-ret), ret);
663 }
664 } else {
665 ALOGE("%s: Physical device orientation absent!", __FUNCTION__);
Emilian Peev5104fe92021-10-21 14:27:09 -0700666 }
667 } else {
Austin Borgerc8099762023-01-12 17:08:46 -0800668 ALOGE("%s: Physical device not found in device info map found!",
669 __FUNCTION__);
Emilian Peev5104fe92021-10-21 14:27:09 -0700670 }
Emilian Peev5104fe92021-10-21 14:27:09 -0700671 }
672 }
673 }
674
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800675 // Check if this result carries only partial metadata
676 if (states.usePartialResult && result->result != NULL) {
677 if (result->partial_result > states.numPartialResults || result->partial_result < 1) {
678 SET_ERR("Result is malformed for frame %d: partial_result %u must be in"
679 " the range of [1, %d] when metadata is included in the result",
680 frameNumber, result->partial_result, states.numPartialResults);
681 return;
682 }
683 isPartialResult = (result->partial_result < states.numPartialResults);
684 if (isPartialResult && result->num_physcam_metadata) {
685 SET_ERR("Result is malformed for frame %d: partial_result not allowed for"
686 " physical camera result", frameNumber);
687 return;
688 }
689 if (isPartialResult) {
690 request.collectedPartialResult.append(result->result);
691 }
692
693 if (isPartialResult && request.hasCallback) {
694 // Send partial capture result
695 sendPartialCaptureResult(states, result->result, request.resultExtras,
696 frameNumber);
697 }
698 }
699
700 shutterTimestamp = request.shutterTimestamp;
701 hasInputBufferInRequest = request.hasInputBuffer;
702
703 // Did we get the (final) result metadata for this capture?
704 if (result->result != NULL && !isPartialResult) {
705 if (request.physicalCameraIds.size() != result->num_physcam_metadata) {
706 SET_ERR("Expected physical Camera metadata count %d not equal to actual count %d",
707 request.physicalCameraIds.size(), result->num_physcam_metadata);
708 return;
709 }
710 if (request.haveResultMetadata) {
711 SET_ERR("Called multiple times with metadata for frame %d",
712 frameNumber);
713 return;
714 }
715 for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700716 const std::string physicalId = result->physcam_ids[i];
Shuzhen Wang99080502021-03-07 21:08:20 -0800717 bool validPhysicalCameraMetadata =
718 erasePhysicalCameraIdSet(request.physicalCameraIds, physicalId);
719 if (!validPhysicalCameraMetadata) {
720 SET_ERR("Unexpected total result for frame %d camera %s",
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800721 frameNumber, physicalId.c_str());
722 return;
723 }
724 }
725 if (states.usePartialResult &&
726 !request.collectedPartialResult.isEmpty()) {
727 collectedPartialResult.acquire(
728 request.collectedPartialResult);
729 }
730 request.haveResultMetadata = true;
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700731 request.errorBufStrategy = ERROR_BUF_RETURN_NOTIFY;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800732 }
733
734 uint32_t numBuffersReturned = result->num_output_buffers;
735 if (result->input_buffer != NULL) {
736 if (hasInputBufferInRequest) {
737 numBuffersReturned += 1;
738 } else {
739 ALOGW("%s: Input buffer should be NULL if there is no input"
740 " buffer sent in the request",
741 __FUNCTION__);
742 }
743 }
744 request.numBuffersLeft -= numBuffersReturned;
745 if (request.numBuffersLeft < 0) {
746 SET_ERR("Too many buffers returned for frame %d",
747 frameNumber);
748 return;
749 }
750
751 camera_metadata_ro_entry_t entry;
752 res = find_camera_metadata_ro_entry(result->result,
753 ANDROID_SENSOR_TIMESTAMP, &entry);
754 if (res == OK && entry.count == 1) {
755 request.sensorTimestamp = entry.data.i64[0];
756 }
757
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700758 // If shutter event isn't received yet, do not return the pending output
759 // buffers.
760 request.pendingOutputBuffers.appendArray(result->output_buffers,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800761 result->num_output_buffers);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700762 if (shutterTimestamp != 0) {
763 returnAndRemovePendingOutputBuffers(
764 states.useHalBufManager, states.listener,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700765 request, states.sessionStatsBuilder);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800766 }
767
768 if (result->result != NULL && !isPartialResult) {
769 for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
770 CameraMetadata physicalMetadata;
771 physicalMetadata.append(result->physcam_metadata[i]);
Austin Borger1c1bee02023-06-01 16:51:35 -0700772 request.physicalMetadatas.push_back({result->physcam_ids[i],
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800773 physicalMetadata});
774 }
775 if (shutterTimestamp == 0) {
776 request.pendingMetadata = result->result;
777 request.collectedPartialResult = collectedPartialResult;
778 } else if (request.hasCallback) {
779 CameraMetadata metadata;
780 metadata = result->result;
Shuzhen Wang3c00b092022-11-08 22:53:07 +0000781 auto cameraIdsWithZoom = getCameraIdsWithZoomLocked(
782 states.inflightMap, metadata, request.cameraIdsWithZoom);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800783 sendCaptureResult(states, metadata, request.resultExtras,
784 collectedPartialResult, frameNumber,
785 hasInputBufferInRequest, request.zslCapture && request.stillCapture,
Shuzhen Wang3c00b092022-11-08 22:53:07 +0000786 request.rotateAndCropAuto, cameraIdsWithZoom,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800787 request.physicalMetadatas);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800788 }
789 }
790 removeInFlightRequestIfReadyLocked(states, idx);
791 } // scope for states.inFlightLock
792
793 if (result->input_buffer != NULL) {
794 if (hasInputBufferInRequest) {
795 Camera3Stream *stream =
796 Camera3Stream::cast(result->input_buffer->stream);
797 res = stream->returnInputBuffer(*(result->input_buffer));
798 // Note: stream may be deallocated at this point, if this buffer was the
799 // last reference to it.
800 if (res != OK) {
801 ALOGE("%s: RequestThread: Can't return input buffer for frame %d to"
802 " its stream:%s (%d)", __FUNCTION__,
803 frameNumber, strerror(-res), res);
804 }
805 } else {
806 ALOGW("%s: Input buffer should be NULL if there is no input"
807 " buffer sent in the request, skipping input buffer return.",
808 __FUNCTION__);
809 }
810 }
811}
812
Greg Kaiser51b882c2020-06-10 05:41:44 +0000813void returnOutputBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800814 bool useHalBufManager,
815 sp<NotificationListener> listener,
Emilian Peevf4816702020-04-03 15:44:51 -0700816 const camera_stream_buffer_t *outputBuffers, size_t numBuffers,
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700817 nsecs_t timestamp, nsecs_t readoutTimestamp, bool requested,
818 nsecs_t requestTimeNs, SessionStatsBuilder& sessionStatsBuilder,
819 bool timestampIncreasing, const SurfaceMap& outputSurfaces,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700820 const CaptureResultExtras &inResultExtras,
Emilian Peev5104fe92021-10-21 14:27:09 -0700821 ERROR_BUF_STRATEGY errorBufStrategy, int32_t transform) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800822
823 for (size_t i = 0; i < numBuffers; i++)
824 {
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700825 Camera3StreamInterface *stream = Camera3Stream::cast(outputBuffers[i].stream);
826 int streamId = stream->getId();
827
828 // Call notify(ERROR_BUFFER) if necessary.
Emilian Peevf4816702020-04-03 15:44:51 -0700829 if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR &&
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700830 errorBufStrategy == ERROR_BUF_RETURN_NOTIFY) {
831 if (listener != nullptr) {
832 CaptureResultExtras extras = inResultExtras;
833 extras.errorStreamId = streamId;
834 listener->notifyError(
835 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
836 extras);
837 }
838 }
839
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800840 if (outputBuffers[i].buffer == nullptr) {
841 if (!useHalBufManager) {
842 // With HAL buffer management API, HAL sometimes will have to return buffers that
843 // has not got a output buffer handle filled yet. This is though illegal if HAL
844 // buffer management API is not being used.
845 ALOGE("%s: cannot return a null buffer!", __FUNCTION__);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700846 } else {
847 if (requested) {
848 sessionStatsBuilder.incCounter(streamId, /*dropped*/true, 0);
849 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800850 }
851 continue;
852 }
853
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800854 const auto& it = outputSurfaces.find(streamId);
855 status_t res = OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800856
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700857 // Do not return the buffer if the buffer status is error, and the error
858 // buffer strategy is CACHE.
Emilian Peevf4816702020-04-03 15:44:51 -0700859 if (outputBuffers[i].status != CAMERA_BUFFER_STATUS_ERROR ||
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700860 errorBufStrategy != ERROR_BUF_CACHE) {
861 if (it != outputSurfaces.end()) {
862 res = stream->returnBuffer(
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700863 outputBuffers[i], timestamp, readoutTimestamp, timestampIncreasing,
864 it->second, inResultExtras.frameNumber, transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700865 } else {
866 res = stream->returnBuffer(
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700867 outputBuffers[i], timestamp, readoutTimestamp, timestampIncreasing,
Emilian Peev5104fe92021-10-21 14:27:09 -0700868 std::vector<size_t> (), inResultExtras.frameNumber, transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700869 }
870 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800871 // Note: stream may be deallocated at this point, if this buffer was
872 // the last reference to it.
Shuzhen Wang316781a2020-08-18 18:11:01 -0700873 bool dropped = false;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800874 if (res == NO_INIT || res == DEAD_OBJECT) {
875 ALOGV("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700876 sessionStatsBuilder.stopCounter(streamId);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800877 } else if (res != OK) {
878 ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
Shuzhen Wang316781a2020-08-18 18:11:01 -0700879 dropped = true;
880 } else {
Emilian Peevf4816702020-04-03 15:44:51 -0700881 if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR || timestamp == 0) {
Shuzhen Wang316781a2020-08-18 18:11:01 -0700882 dropped = true;
883 }
884 }
885 if (requested) {
886 nsecs_t bufferTimeNs = systemTime();
887 int32_t captureLatencyMs = ns2ms(bufferTimeNs - requestTimeNs);
888 sessionStatsBuilder.incCounter(streamId, dropped, captureLatencyMs);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800889 }
890
891 // Long processing consumers can cause returnBuffer timeout for shared stream
892 // If that happens, cancel the buffer and send a buffer error to client
893 if (it != outputSurfaces.end() && res == TIMED_OUT &&
Emilian Peevf4816702020-04-03 15:44:51 -0700894 outputBuffers[i].status == CAMERA_BUFFER_STATUS_OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800895 // cancel the buffer
Emilian Peevf4816702020-04-03 15:44:51 -0700896 camera_stream_buffer_t sb = outputBuffers[i];
897 sb.status = CAMERA_BUFFER_STATUS_ERROR;
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700898 stream->returnBuffer(sb, /*timestamp*/0, /*readoutTimestamp*/0,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700899 timestampIncreasing, std::vector<size_t> (),
Emilian Peev5104fe92021-10-21 14:27:09 -0700900 inResultExtras.frameNumber, transform);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800901
902 if (listener != nullptr) {
903 CaptureResultExtras extras = inResultExtras;
904 extras.errorStreamId = streamId;
905 listener->notifyError(
906 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
907 extras);
908 }
909 }
910 }
911}
912
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700913void returnAndRemovePendingOutputBuffers(bool useHalBufManager,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700914 sp<NotificationListener> listener, InFlightRequest& request,
915 SessionStatsBuilder& sessionStatsBuilder) {
Shuzhen Wang828ade32022-01-10 17:19:02 -0800916 bool timestampIncreasing =
917 !((request.zslCapture && request.stillCapture) || request.hasInputBuffer);
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700918 nsecs_t readoutTimestamp = request.resultExtras.hasReadoutTimestamp ?
919 request.resultExtras.readoutTimestamp : 0;
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700920 returnOutputBuffers(useHalBufManager, listener,
921 request.pendingOutputBuffers.array(),
922 request.pendingOutputBuffers.size(),
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700923 request.shutterTimestamp, readoutTimestamp,
Shuzhen Wang90708ea2021-11-04 11:40:49 -0700924 /*requested*/true, request.requestTimeNs, sessionStatsBuilder, timestampIncreasing,
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700925 request.outputSurfaces, request.resultExtras,
Emilian Peev5104fe92021-10-21 14:27:09 -0700926 request.errorBufStrategy, request.transform);
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700927
928 // Remove error buffers that are not cached.
929 for (auto iter = request.pendingOutputBuffers.begin();
930 iter != request.pendingOutputBuffers.end(); ) {
931 if (request.errorBufStrategy != ERROR_BUF_CACHE ||
Emilian Peevf4816702020-04-03 15:44:51 -0700932 iter->status != CAMERA_BUFFER_STATUS_ERROR) {
Shuzhen Wangb7b42652020-05-07 11:59:02 -0700933 iter = request.pendingOutputBuffers.erase(iter);
934 } else {
935 iter++;
936 }
937 }
938}
939
Emilian Peevf4816702020-04-03 15:44:51 -0700940void notifyShutter(CaptureOutputStates& states, const camera_shutter_msg_t &msg) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800941 ATRACE_CALL();
942 ssize_t idx;
943
944 // Set timestamp for the request in the in-flight tracking
945 // and get the request ID to send upstream
946 {
947 std::lock_guard<std::mutex> l(states.inflightLock);
948 InFlightRequestMap& inflightMap = states.inflightMap;
949 idx = inflightMap.indexOfKey(msg.frame_number);
950 if (idx >= 0) {
951 InFlightRequest &r = inflightMap.editValueAt(idx);
952
953 // Verify ordering of shutter notifications
954 {
955 std::lock_guard<std::mutex> l(states.outputLock);
956 // TODO: need to track errors for tighter bounds on expected frame number.
957 if (r.hasInputBuffer) {
958 if (msg.frame_number < states.nextReprocShutterFrameNum) {
959 SET_ERR("Reprocess shutter notification out-of-order. Expected "
960 "notification for frame %d, got frame %d",
961 states.nextReprocShutterFrameNum, msg.frame_number);
962 return;
963 }
964 states.nextReprocShutterFrameNum = msg.frame_number + 1;
965 } else if (r.zslCapture && r.stillCapture) {
966 if (msg.frame_number < states.nextZslShutterFrameNum) {
967 SET_ERR("ZSL still capture shutter notification out-of-order. Expected "
968 "notification for frame %d, got frame %d",
969 states.nextZslShutterFrameNum, msg.frame_number);
970 return;
971 }
972 states.nextZslShutterFrameNum = msg.frame_number + 1;
973 } else {
974 if (msg.frame_number < states.nextShutterFrameNum) {
975 SET_ERR("Shutter notification out-of-order. Expected "
976 "notification for frame %d, got frame %d",
977 states.nextShutterFrameNum, msg.frame_number);
978 return;
979 }
980 states.nextShutterFrameNum = msg.frame_number + 1;
981 }
982 }
983
984 r.shutterTimestamp = msg.timestamp;
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700985 if (msg.readout_timestamp_valid) {
986 r.resultExtras.hasReadoutTimestamp = true;
987 r.resultExtras.readoutTimestamp = msg.readout_timestamp;
988 }
Shuzhen Wang696e4da2022-09-08 14:31:13 -0700989 if (r.minExpectedDuration != states.minFrameDuration ||
990 r.isFixedFps != states.isFixedFps) {
Shuzhen Wang00abbeb2022-02-25 17:14:42 -0800991 for (size_t i = 0; i < states.outputStreams.size(); i++) {
992 auto outputStream = states.outputStreams[i];
Shuzhen Wang696e4da2022-09-08 14:31:13 -0700993 outputStream->onMinDurationChanged(r.minExpectedDuration, r.isFixedFps);
Shuzhen Wang00abbeb2022-02-25 17:14:42 -0800994 }
995 states.minFrameDuration = r.minExpectedDuration;
Shuzhen Wang696e4da2022-09-08 14:31:13 -0700996 states.isFixedFps = r.isFixedFps;
Shuzhen Wang00abbeb2022-02-25 17:14:42 -0800997 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800998 if (r.hasCallback) {
999 ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
Austin Borger1c1bee02023-06-01 16:51:35 -07001000 states.cameraId.c_str(), __FUNCTION__,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001001 msg.frame_number, r.resultExtras.requestId, msg.timestamp);
1002 // Call listener, if any
1003 if (states.listener != nullptr) {
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001004 r.resultExtras.lastCompletedRegularFrameNumber =
1005 states.lastCompletedRegularFrameNumber;
1006 r.resultExtras.lastCompletedReprocessFrameNumber =
1007 states.lastCompletedReprocessFrameNumber;
1008 r.resultExtras.lastCompletedZslFrameNumber =
1009 states.lastCompletedZslFrameNumber;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001010 states.listener->notifyShutter(r.resultExtras, msg.timestamp);
1011 }
1012 // send pending result and buffers
Shuzhen Wang3c00b092022-11-08 22:53:07 +00001013 const auto& cameraIdsWithZoom = getCameraIdsWithZoomLocked(
1014 inflightMap, r.pendingMetadata, r.cameraIdsWithZoom);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001015 sendCaptureResult(states,
1016 r.pendingMetadata, r.resultExtras,
1017 r.collectedPartialResult, msg.frame_number,
1018 r.hasInputBuffer, r.zslCapture && r.stillCapture,
Shuzhen Wang3c00b092022-11-08 22:53:07 +00001019 r.rotateAndCropAuto, cameraIdsWithZoom, r.physicalMetadatas);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001020 }
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001021 returnAndRemovePendingOutputBuffers(
Shuzhen Wang316781a2020-08-18 18:11:01 -07001022 states.useHalBufManager, states.listener, r, states.sessionStatsBuilder);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001023
1024 removeInFlightRequestIfReadyLocked(states, idx);
1025 }
1026 }
1027 if (idx < 0) {
1028 SET_ERR("Shutter notification for non-existent frame number %d",
1029 msg.frame_number);
1030 }
1031}
1032
Emilian Peevf4816702020-04-03 15:44:51 -07001033void notifyError(CaptureOutputStates& states, const camera_error_msg_t &msg) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001034 ATRACE_CALL();
1035 // Map camera HAL error codes to ICameraDeviceCallback error codes
1036 // Index into this with the HAL error code
Emilian Peevf4816702020-04-03 15:44:51 -07001037 static const int32_t halErrorMap[CAMERA_MSG_NUM_ERRORS] = {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001038 // 0 = Unused error code
1039 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
Emilian Peevf4816702020-04-03 15:44:51 -07001040 // 1 = CAMERA_MSG_ERROR_DEVICE
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001041 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Emilian Peevf4816702020-04-03 15:44:51 -07001042 // 2 = CAMERA_MSG_ERROR_REQUEST
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001043 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Emilian Peevf4816702020-04-03 15:44:51 -07001044 // 3 = CAMERA_MSG_ERROR_RESULT
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001045 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
Emilian Peevf4816702020-04-03 15:44:51 -07001046 // 4 = CAMERA_MSG_ERROR_BUFFER
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001047 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
1048 };
1049
1050 int32_t errorCode =
1051 ((msg.error_code >= 0) &&
Emilian Peevf4816702020-04-03 15:44:51 -07001052 (msg.error_code < CAMERA_MSG_NUM_ERRORS)) ?
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001053 halErrorMap[msg.error_code] :
1054 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
1055
1056 int streamId = 0;
Austin Borger1c1bee02023-06-01 16:51:35 -07001057 std::string physicalCameraId;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001058 if (msg.error_stream != nullptr) {
1059 Camera3Stream *stream =
1060 Camera3Stream::cast(msg.error_stream);
1061 streamId = stream->getId();
Austin Borger1c1bee02023-06-01 16:51:35 -07001062 physicalCameraId = stream->physicalCameraId();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001063 }
1064 ALOGV("Camera %s: %s: HAL error, frame %d, stream %d: %d",
Austin Borger1c1bee02023-06-01 16:51:35 -07001065 states.cameraId.c_str(), __FUNCTION__, msg.frame_number,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001066 streamId, msg.error_code);
1067
1068 CaptureResultExtras resultExtras;
1069 switch (errorCode) {
1070 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
1071 // SET_ERR calls into listener to notify application
1072 SET_ERR("Camera HAL reported serious device error");
1073 break;
1074 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
1075 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001076 {
1077 std::lock_guard<std::mutex> l(states.inflightLock);
1078 ssize_t idx = states.inflightMap.indexOfKey(msg.frame_number);
1079 if (idx >= 0) {
1080 InFlightRequest &r = states.inflightMap.editValueAt(idx);
1081 r.requestStatus = msg.error_code;
1082 resultExtras = r.resultExtras;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001083 bool physicalDeviceResultError = false;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001084 if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
1085 errorCode) {
1086 if (physicalCameraId.size() > 0) {
Shuzhen Wang99080502021-03-07 21:08:20 -08001087 bool validPhysicalCameraId =
Austin Borger1c1bee02023-06-01 16:51:35 -07001088 erasePhysicalCameraIdSet(r.physicalCameraIds, physicalCameraId);
Shuzhen Wang99080502021-03-07 21:08:20 -08001089 if (!validPhysicalCameraId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001090 ALOGE("%s: Reported result failure for physical camera device: %s "
1091 " which is not part of the respective request!",
Austin Borger1c1bee02023-06-01 16:51:35 -07001092 __FUNCTION__, physicalCameraId.c_str());
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001093 break;
1094 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001095 resultExtras.errorPhysicalCameraId = physicalCameraId;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001096 physicalDeviceResultError = true;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001097 }
1098 }
1099
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001100 if (!physicalDeviceResultError) {
Greg Kaiser51b882c2020-06-10 05:41:44 +00001101 r.skipResultMetadata = true;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001102 if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT
1103 == errorCode) {
1104 r.errorBufStrategy = ERROR_BUF_RETURN_NOTIFY;
1105 } else {
1106 // errorCode is ERROR_CAMERA_REQUEST
1107 r.errorBufStrategy = ERROR_BUF_RETURN;
1108 }
1109
1110 // Check whether the buffers returned. If they returned,
1111 // remove inflight request.
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001112 removeInFlightRequestIfReadyLocked(states, idx);
1113 }
1114 } else {
1115 resultExtras.frameNumber = msg.frame_number;
1116 ALOGE("Camera %s: %s: cannot find in-flight request on "
Austin Borger1c1bee02023-06-01 16:51:35 -07001117 "frame %" PRId64 " error", states.cameraId.c_str(), __FUNCTION__,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001118 resultExtras.frameNumber);
1119 }
1120 }
1121 resultExtras.errorStreamId = streamId;
1122 if (states.listener != nullptr) {
1123 states.listener->notifyError(errorCode, resultExtras);
1124 } else {
1125 ALOGE("Camera %s: %s: no listener available",
Austin Borger1c1bee02023-06-01 16:51:35 -07001126 states.cameraId.c_str(), __FUNCTION__);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001127 }
1128 break;
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001129 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
1130 // Do not depend on HAL ERROR_CAMERA_BUFFER to send buffer error
1131 // callback to the app. Rather, use STATUS_ERROR of image buffers.
1132 break;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001133 default:
1134 // SET_ERR calls notifyError
1135 SET_ERR("Unknown error message from HAL: %d", msg.error_code);
1136 break;
1137 }
1138}
1139
Emilian Peevf4816702020-04-03 15:44:51 -07001140void notify(CaptureOutputStates& states, const camera_notify_msg *msg) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001141 switch (msg->type) {
Emilian Peevf4816702020-04-03 15:44:51 -07001142 case CAMERA_MSG_ERROR: {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001143 notifyError(states, msg->message.error);
1144 break;
1145 }
Emilian Peevf4816702020-04-03 15:44:51 -07001146 case CAMERA_MSG_SHUTTER: {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001147 notifyShutter(states, msg->message.shutter);
1148 break;
1149 }
1150 default:
1151 SET_ERR("Unknown notify message from HAL: %d",
1152 msg->type);
1153 }
1154}
1155
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001156void flushInflightRequests(FlushInflightReqStates& states) {
1157 ATRACE_CALL();
Shuzhen Wang316781a2020-08-18 18:11:01 -07001158 { // First return buffers cached in inFlightMap
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001159 std::lock_guard<std::mutex> l(states.inflightLock);
1160 for (size_t idx = 0; idx < states.inflightMap.size(); idx++) {
Greg Kaiser51b882c2020-06-10 05:41:44 +00001161 const InFlightRequest &request = states.inflightMap.valueAt(idx);
1162 returnOutputBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001163 states.useHalBufManager, states.listener,
1164 request.pendingOutputBuffers.array(),
Shuzhen Wang90708ea2021-11-04 11:40:49 -07001165 request.pendingOutputBuffers.size(), /*timestamp*/0, /*readoutTimestamp*/0,
1166 /*requested*/true, request.requestTimeNs, states.sessionStatsBuilder,
1167 /*timestampIncreasing*/true, request.outputSurfaces, request.resultExtras,
1168 request.errorBufStrategy);
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001169 ALOGW("%s: Frame %d | Timestamp: %" PRId64 ", metadata"
1170 " arrived: %s, buffers left: %d.\n", __FUNCTION__,
1171 states.inflightMap.keyAt(idx), request.shutterTimestamp,
1172 request.haveResultMetadata ? "true" : "false",
1173 request.numBuffersLeft);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001174 }
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001175
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001176 states.inflightMap.clear();
1177 states.inflightIntf.onInflightMapFlushedLocked();
1178 }
1179
1180 // Then return all inflight buffers not returned by HAL
1181 std::vector<std::pair<int32_t, int32_t>> inflightKeys;
1182 states.flushBufferIntf.getInflightBufferKeys(&inflightKeys);
1183
1184 // Inflight buffers for HAL buffer manager
1185 std::vector<uint64_t> inflightRequestBufferKeys;
1186 states.flushBufferIntf.getInflightRequestBufferKeys(&inflightRequestBufferKeys);
1187
1188 // (streamId, frameNumber, buffer_handle_t*) tuple for all inflight buffers.
1189 // frameNumber will be -1 for buffers from HAL buffer manager
1190 std::vector<std::tuple<int32_t, int32_t, buffer_handle_t*>> inflightBuffers;
1191 inflightBuffers.reserve(inflightKeys.size() + inflightRequestBufferKeys.size());
1192
1193 for (auto& pair : inflightKeys) {
1194 int32_t frameNumber = pair.first;
1195 int32_t streamId = pair.second;
1196 buffer_handle_t* buffer;
1197 status_t res = states.bufferRecordsIntf.popInflightBuffer(frameNumber, streamId, &buffer);
1198 if (res != OK) {
1199 ALOGE("%s: Frame %d: No in-flight buffer for stream %d",
1200 __FUNCTION__, frameNumber, streamId);
1201 continue;
1202 }
1203 inflightBuffers.push_back(std::make_tuple(streamId, frameNumber, buffer));
1204 }
1205
1206 for (auto& bufferId : inflightRequestBufferKeys) {
1207 int32_t streamId = -1;
1208 buffer_handle_t* buffer = nullptr;
1209 status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
1210 bufferId, &buffer, &streamId);
1211 if (res != OK) {
1212 ALOGE("%s: cannot find in-flight buffer %" PRIu64, __FUNCTION__, bufferId);
1213 continue;
1214 }
1215 inflightBuffers.push_back(std::make_tuple(streamId, /*frameNumber*/-1, buffer));
1216 }
1217
1218 std::vector<sp<Camera3StreamInterface>> streams = states.flushBufferIntf.getAllStreams();
1219
1220 for (auto& tuple : inflightBuffers) {
1221 status_t res = OK;
1222 int32_t streamId = std::get<0>(tuple);
1223 int32_t frameNumber = std::get<1>(tuple);
1224 buffer_handle_t* buffer = std::get<2>(tuple);
1225
Emilian Peevf4816702020-04-03 15:44:51 -07001226 camera_stream_buffer_t streamBuffer;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001227 streamBuffer.buffer = buffer;
Emilian Peevf4816702020-04-03 15:44:51 -07001228 streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001229 streamBuffer.acquire_fence = -1;
1230 streamBuffer.release_fence = -1;
1231
1232 for (auto& stream : streams) {
1233 if (streamId == stream->getId()) {
1234 // Return buffer to deleted stream
Emilian Peevf4816702020-04-03 15:44:51 -07001235 camera_stream* halStream = stream->asHalStream();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001236 streamBuffer.stream = halStream;
1237 switch (halStream->stream_type) {
Emilian Peevf4816702020-04-03 15:44:51 -07001238 case CAMERA_STREAM_OUTPUT:
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001239 res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0,
Shuzhen Wang90708ea2021-11-04 11:40:49 -07001240 /*readoutTimestamp*/0, /*timestampIncreasing*/true,
Shuzhen Wang316781a2020-08-18 18:11:01 -07001241 std::vector<size_t> (), frameNumber);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001242 if (res != OK) {
1243 ALOGE("%s: Can't return output buffer for frame %d to"
1244 " stream %d: %s (%d)", __FUNCTION__,
1245 frameNumber, streamId, strerror(-res), res);
1246 }
1247 break;
Emilian Peevf4816702020-04-03 15:44:51 -07001248 case CAMERA_STREAM_INPUT:
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001249 res = stream->returnInputBuffer(streamBuffer);
1250 if (res != OK) {
1251 ALOGE("%s: Can't return input buffer for frame %d to"
1252 " stream %d: %s (%d)", __FUNCTION__,
1253 frameNumber, streamId, strerror(-res), res);
1254 }
1255 break;
1256 default: // Bi-direcitonal stream is deprecated
1257 ALOGE("%s: stream %d has unknown stream type %d",
1258 __FUNCTION__, streamId, halStream->stream_type);
1259 break;
1260 }
1261 break;
1262 }
1263 }
1264 }
1265}
1266
1267} // camera3
1268} // namespace android