blob: a7a2b5eab5ac490cf4abf04f951ea3f1c7a559d7 [file] [log] [blame]
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -08001/*
2 * Copyright (C) 2020 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 */
Austin Borgerea931242021-12-13 23:10:41 +000016
Shuzhen Wangd4abdf72021-05-28 11:22:50 -070017#include <cutils/properties.h>
18
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080019#include "SessionConfigurationUtils.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000020#include "../api2/DepthCompositeStream.h"
21#include "../api2/HeicCompositeStream.h"
Emilian Peev434248e2022-10-06 14:58:54 -070022#include "aidl/android/hardware/graphics/common/Dataspace.h"
23#include "api2/JpegRCompositeStream.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000024#include "common/CameraDeviceBase.h"
Jayant Chowdharya04055f2022-01-03 02:07:49 +000025#include "common/HalConversionsTemplated.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000026#include "../CameraService.h"
Jayant Chowdhary35642f22022-01-08 00:39:39 +000027#include "device3/aidl/AidlCamera3Device.h"
Jayant Chowdhary22441f32021-12-26 18:35:41 -080028#include "device3/hidl/HidlCamera3Device.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000029#include "device3/Camera3OutputStream.h"
Shuzhen Wang33c84cd2024-01-03 17:45:03 +000030#include "device3/ZoomRatioMapper.h"
Emilian Peev2295df72021-11-12 18:14:10 -080031#include "system/graphics-base-v1.1.h"
Austin Borger1c1bee02023-06-01 16:51:35 -070032#include <camera/StringUtils.h>
Emilian Peev434248e2022-10-06 14:58:54 -070033#include <ui/PublicFormat.h>
Colin Crossb8a9dbb2020-08-27 04:12:26 +000034
Colin Crossb8a9dbb2020-08-27 04:12:26 +000035using android::camera3::OutputStreamInfo;
36using android::camera3::OutputStreamInfo;
37using android::hardware::camera2::ICameraDeviceUser;
Shuzhen Wang045be6c2023-10-12 10:01:10 -070038using aidl::android::hardware::camera::device::RequestTemplate;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080039
40namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080041namespace camera3 {
42
43void StreamConfiguration::getStreamConfigurations(
44 const CameraMetadata &staticInfo, int configuration,
45 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
46 if (scm == nullptr) {
47 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
48 return;
49 }
50 const int STREAM_FORMAT_OFFSET = 0;
51 const int STREAM_WIDTH_OFFSET = 1;
52 const int STREAM_HEIGHT_OFFSET = 2;
53 const int STREAM_IS_INPUT_OFFSET = 3;
54
55 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
56 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
57 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
58 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
59 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
60 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
61 StreamConfiguration sc = {format, width, height, isInput};
62 (*scm)[format].push_back(sc);
63 }
64}
65
66void StreamConfiguration::getStreamConfigurations(
67 const CameraMetadata &staticInfo, bool maxRes,
68 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
69 int32_t scalerKey =
70 SessionConfigurationUtils::getAppropriateModeTag(
71 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
72
73 int32_t depthKey =
74 SessionConfigurationUtils::getAppropriateModeTag(
75 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
76
77 int32_t dynamicDepthKey =
78 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070079 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080080
81 int32_t heicKey =
82 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070083 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080084
85 getStreamConfigurations(staticInfo, scalerKey, scm);
86 getStreamConfigurations(staticInfo, depthKey, scm);
87 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
88 getStreamConfigurations(staticInfo, heicKey, scm);
89}
90
Austin Borgerea931242021-12-13 23:10:41 +000091namespace SessionConfigurationUtils {
92
93int32_t PERF_CLASS_LEVEL =
94 property_get_int32("ro.odm.build.media_performance_class", 0);
95
Shuzhen Wangf18887c2022-05-31 10:24:02 -070096bool IS_PERF_CLASS = (PERF_CLASS_LEVEL >= SDK_VERSION_S);
Austin Borgerea931242021-12-13 23:10:41 +000097
98camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
99 bool ultraHighResolution) {
100 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
101 const int STREAM_CONFIGURATION_SIZE = 4;
102 const int STREAM_FORMAT_OFFSET = 0;
103 const int STREAM_WIDTH_OFFSET = 1;
104 const int STREAM_HEIGHT_OFFSET = 2;
105 const int STREAM_IS_INPUT_OFFSET = 3;
106
107 int32_t scalerSizesTag = ultraHighResolution ?
108 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
109 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
110 camera_metadata_ro_entry_t availableStreamConfigs =
111 metadata.find(scalerSizesTag);
112 if (availableStreamConfigs.count == 0 ||
113 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
114 return camera3::Size(0, 0);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800115 }
Austin Borgerea931242021-12-13 23:10:41 +0000116
117 // Get max jpeg size (area-wise).
118 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
119 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
120 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
121 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
122 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
123 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
124 && format == HAL_PIXEL_FORMAT_BLOB &&
125 (width * height > maxJpegWidth * maxJpegHeight)) {
126 maxJpegWidth = width;
127 maxJpegHeight = height;
128 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800129 }
Austin Borgerea931242021-12-13 23:10:41 +0000130
131 return camera3::Size(maxJpegWidth, maxJpegHeight);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800132}
133
Austin Borgerea931242021-12-13 23:10:41 +0000134size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
135 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
Jayant Chowdharyb2d84202022-07-11 21:46:53 +0000136 return ((float)(uhrMaxJpegSize.width * uhrMaxJpegSize.height)) /
Austin Borgerea931242021-12-13 23:10:41 +0000137 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
138}
139
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800140StreamConfigurationPair
Austin Borgerea931242021-12-13 23:10:41 +0000141getStreamConfigurationPair(const CameraMetadata &staticInfo) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800142 camera3::StreamConfigurationPair streamConfigurationPair;
143 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
144 &streamConfigurationPair.mDefaultStreamConfigurationMap);
145 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
146 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
147 return streamConfigurationPair;
148}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800149
Austin Borgerea931242021-12-13 23:10:41 +0000150int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000151 int64_t d0 = x0 - x1;
152 int64_t d1 = y0 - y1;
153 return d0 * d0 + d1 * d1;
154}
155
Austin Borgerea931242021-12-13 23:10:41 +0000156bool roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800157 int32_t format, android_dataspace dataSpace,
158 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
159 /*out*/int32_t* outHeight) {
160 const int32_t depthSizesTag =
161 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
162 maxResolution);
163 const int32_t scalerSizesTag =
164 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
165 const int32_t heicSizesTag =
166 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Emilian Peevad25a072023-04-05 12:24:13 -0700167 const int32_t jpegRSizesTag = getAppropriateModeTag(
168 ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000169
Emilian Peevad25a072023-04-05 12:24:13 -0700170 bool isJpegRDataSpace = (dataSpace == static_cast<android_dataspace_t>(
171 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000172 camera_metadata_ro_entry streamConfigs =
Emilian Peevad25a072023-04-05 12:24:13 -0700173 (isJpegRDataSpace) ? info.find(jpegRSizesTag) :
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800174 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000175 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800176 info.find(heicSizesTag) :
177 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000178
179 int32_t bestWidth = -1;
180 int32_t bestHeight = -1;
181
182 // Iterate through listed stream configurations and find the one with the smallest euclidean
183 // distance from the given dimensions for the given format.
184 for (size_t i = 0; i < streamConfigs.count; i += 4) {
185 int32_t fmt = streamConfigs.data.i32[i];
186 int32_t w = streamConfigs.data.i32[i + 1];
187 int32_t h = streamConfigs.data.i32[i + 2];
188
189 // Ignore input/output type for now
190 if (fmt == format) {
191 if (w == width && h == height) {
192 bestWidth = width;
193 bestHeight = height;
194 break;
195 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
196 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
197 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
198 height))) {
199 bestWidth = w;
200 bestHeight = h;
201 }
202 }
203 }
204
205 if (bestWidth == -1) {
206 // Return false if no configurations for this format were listed
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -0800207 ALOGE("%s: No configurations for format %d width %d, height %d, maxResolution ? %s",
208 __FUNCTION__, format, width, height, maxResolution ? "true" : "false");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000209 return false;
210 }
211
212 // Set the outputs to the closet width/height
213 if (outWidth != NULL) {
214 *outWidth = bestWidth;
215 }
216 if (outHeight != NULL) {
217 *outHeight = bestHeight;
218 }
219
220 // Return true if at least one configuration for this format was listed
221 return true;
222}
223
Emilian Peev2295df72021-11-12 18:14:10 -0800224//check if format is 10-bit compatible
Emilian Peev434248e2022-10-06 14:58:54 -0700225bool is10bitCompatibleFormat(int32_t format, android_dataspace_t dataSpace) {
Emilian Peev2295df72021-11-12 18:14:10 -0800226 switch(format) {
227 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
228 case HAL_PIXEL_FORMAT_YCBCR_P010:
229 return true;
Emilian Peev434248e2022-10-06 14:58:54 -0700230 case HAL_PIXEL_FORMAT_BLOB:
231 if (dataSpace == static_cast<android_dataspace_t>(
232 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
233 return true;
234 }
235
236 return false;
Emilian Peev2295df72021-11-12 18:14:10 -0800237 default:
238 return false;
239 }
240}
241
Emilian Peevc81a7592022-02-14 17:38:18 -0800242bool isDynamicRangeProfileSupported(int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
Emilian Peev2295df72021-11-12 18:14:10 -0800243 if (dynamicRangeProfile == ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
244 // Supported by default
245 return true;
246 }
247
248 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
249 bool is10bitDynamicRangeSupported = false;
250 for (size_t i = 0; i < entry.count; ++i) {
251 uint8_t capability = entry.data.u8[i];
252 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
253 is10bitDynamicRangeSupported = true;
254 break;
255 }
256 }
257
258 if (!is10bitDynamicRangeSupported) {
259 return false;
260 }
261
262 switch (dynamicRangeProfile) {
263 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
264 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
265 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
266 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
267 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
268 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
269 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
270 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
271 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
272 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
273 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
274 entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
Emilian Peevc81a7592022-02-14 17:38:18 -0800275 for (size_t i = 0; i < entry.count; i += 3) {
276 if (dynamicRangeProfile == entry.data.i64[i]) {
Emilian Peev2295df72021-11-12 18:14:10 -0800277 return true;
278 }
279 }
280
281 return false;
282 default:
283 return false;
284 }
285
286 return false;
287}
288
289//check if format is 10-bit compatible
Emilian Peevc81a7592022-02-14 17:38:18 -0800290bool is10bitDynamicRangeProfile(int64_t dynamicRangeProfile) {
Emilian Peev2295df72021-11-12 18:14:10 -0800291 switch (dynamicRangeProfile) {
292 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
293 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
294 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
295 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
296 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
297 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
298 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
299 return true;
300 default:
301 return false;
302 }
303}
304
Austin Borger9e2b27c2022-07-15 11:27:24 -0700305bool deviceReportsColorSpaces(const CameraMetadata& staticInfo) {
306 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
307 for (size_t i = 0; i < entry.count; ++i) {
308 uint8_t capability = entry.data.u8[i];
309 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES) {
310 return true;
311 }
312 }
313
314 return false;
315}
316
317bool isColorSpaceSupported(int32_t colorSpace, int32_t format, android_dataspace dataSpace,
318 int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
319 int64_t colorSpace64 = colorSpace;
320 int64_t format64 = format;
321
322 // Translate HAL format + data space to public format
323 if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_V0_JFIF) {
324 format64 = 0x100; // JPEG
325 } else if (format == HAL_PIXEL_FORMAT_BLOB
326 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) {
327 format64 = 0x48454946; // HEIC
328 } else if (format == HAL_PIXEL_FORMAT_BLOB
329 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
330 format64 = 0x69656963; // DEPTH_JPEG
331 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_DEPTH) {
332 return false; // DEPTH_POINT_CLOUD, not applicable
333 } else if (format == HAL_PIXEL_FORMAT_Y16 && dataSpace == HAL_DATASPACE_DEPTH) {
334 return false; // DEPTH16, not applicable
335 } else if (format == HAL_PIXEL_FORMAT_RAW16 && dataSpace == HAL_DATASPACE_DEPTH) {
336 return false; // RAW_DEPTH, not applicable
337 } else if (format == HAL_PIXEL_FORMAT_RAW10 && dataSpace == HAL_DATASPACE_DEPTH) {
338 return false; // RAW_DEPTH10, not applicable
Emilian Peev434248e2022-10-06 14:58:54 -0700339 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace ==
340 static_cast<android_dataspace>(
341 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
342 format64 = static_cast<int64_t>(PublicFormat::JPEG_R);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700343 }
344
345 camera_metadata_ro_entry_t entry =
346 staticInfo.find(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP);
347 for (size_t i = 0; i < entry.count; i += 3) {
348 bool isFormatCompatible = (format64 == entry.data.i64[i + 1]);
349 bool isDynamicProfileCompatible =
350 (dynamicRangeProfile & entry.data.i64[i + 2]) != 0;
351
352 if (colorSpace64 == entry.data.i64[i]
353 && isFormatCompatible
354 && isDynamicProfileCompatible) {
355 return true;
356 }
357 }
358
359 ALOGE("Color space %d, image format %" PRId64 ", and dynamic range 0x%" PRIx64
360 " combination not found", colorSpace, format64, dynamicRangeProfile);
361 return false;
362}
363
Austin Borgerea931242021-12-13 23:10:41 +0000364bool isPublicFormat(int32_t format)
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000365{
366 switch(format) {
367 case HAL_PIXEL_FORMAT_RGBA_8888:
368 case HAL_PIXEL_FORMAT_RGBX_8888:
369 case HAL_PIXEL_FORMAT_RGB_888:
370 case HAL_PIXEL_FORMAT_RGB_565:
371 case HAL_PIXEL_FORMAT_BGRA_8888:
372 case HAL_PIXEL_FORMAT_YV12:
373 case HAL_PIXEL_FORMAT_Y8:
374 case HAL_PIXEL_FORMAT_Y16:
375 case HAL_PIXEL_FORMAT_RAW16:
376 case HAL_PIXEL_FORMAT_RAW10:
377 case HAL_PIXEL_FORMAT_RAW12:
378 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
379 case HAL_PIXEL_FORMAT_BLOB:
380 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
381 case HAL_PIXEL_FORMAT_YCbCr_420_888:
382 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
383 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
384 case HAL_PIXEL_FORMAT_YCbCr_422_I:
385 return true;
386 default:
387 return false;
388 }
389}
390
Austin Borger9b263b12023-03-27 17:01:33 -0700391bool dataSpaceFromColorSpace(android_dataspace *dataSpace, int32_t colorSpace) {
392 switch (colorSpace) {
393 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB:
394 *dataSpace = HAL_DATASPACE_V0_SRGB;
395 return true;
396 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3:
397 *dataSpace = HAL_DATASPACE_DISPLAY_P3;
398 return true;
399 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG:
400 *(reinterpret_cast<int32_t*>(dataSpace)) = HAL_DATASPACE_BT2020_HLG;
401 return true;
402 default:
403 ALOGE("%s: Unsupported color space %d", __FUNCTION__, colorSpace);
404 return false;
405 }
406}
407
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800408bool isStreamUseCaseSupported(int64_t streamUseCase,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800409 const CameraMetadata &deviceInfo) {
410 camera_metadata_ro_entry_t availableStreamUseCases =
411 deviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES);
412
413 if (availableStreamUseCases.count == 0 &&
414 streamUseCase == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
415 return true;
416 }
Shuzhen Wangb77131a2022-04-27 15:34:33 -0700417 // Allow vendor stream use case unconditionally.
418 if (streamUseCase >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
419 return true;
420 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800421
422 for (size_t i = 0; i < availableStreamUseCases.count; i++) {
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800423 if (availableStreamUseCases.data.i64[i] == streamUseCase) {
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800424 return true;
425 }
426 }
427 return false;
428}
429
Austin Borgerea931242021-12-13 23:10:41 +0000430binder::Status createSurfaceFromGbp(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000431 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
432 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Austin Borger1c1bee02023-06-01 16:51:35 -0700433 const std::string &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
Emilian Peevc81a7592022-02-14 17:38:18 -0800434 const std::vector<int32_t> &sensorPixelModesUsed, int64_t dynamicRangeProfile,
Austin Borger9e2b27c2022-07-15 11:27:24 -0700435 int64_t streamUseCase, int timestampBase, int mirrorMode,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800436 int32_t colorSpace, bool respectSurfaceSize) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000437 // bufferProducer must be non-null
438 if (gbp == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700439 std::string msg = fmt::sprintf("Camera %s: Surface is NULL", logicalCameraId.c_str());
440 ALOGW("%s: %s", __FUNCTION__, msg.c_str());
441 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000442 }
443 // HACK b/10949105
444 // Query consumer usage bits to set async operation mode for
445 // GLConsumer using controlledByApp parameter.
446 bool useAsync = false;
447 uint64_t consumerUsage = 0;
448 status_t err;
449 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700450 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface consumer usage: %s (%d)",
451 logicalCameraId.c_str(), strerror(-err), err);
452 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
453 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000454 }
455 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
456 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Austin Borger1c1bee02023-06-01 16:51:35 -0700457 "stream", __FUNCTION__, logicalCameraId.c_str(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000458 useAsync = true;
459 }
460
461 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
462 GRALLOC_USAGE_RENDERSCRIPT;
463 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
464 GraphicBuffer::USAGE_HW_TEXTURE |
465 GraphicBuffer::USAGE_HW_COMPOSER;
466 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
467 (consumerUsage & allowedFlags) != 0;
468
469 surface = new Surface(gbp, useAsync);
470 ANativeWindow *anw = surface.get();
471
472 int width, height, format;
473 android_dataspace dataSpace;
474 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700475 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface width: %s (%d)",
476 logicalCameraId.c_str(), strerror(-err), err);
477 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
478 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000479 }
480 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700481 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface height: %s (%d)",
482 logicalCameraId.c_str(), strerror(-err), err);
483 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
484 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000485 }
486 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700487 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface format: %s (%d)",
488 logicalCameraId.c_str(), strerror(-err), err);
489 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
490 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000491 }
492 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
493 reinterpret_cast<int*>(&dataSpace))) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700494 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface dataspace: %s (%d)",
495 logicalCameraId.c_str(), strerror(-err), err);
496 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
497 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000498 }
499
Austin Borger9b263b12023-03-27 17:01:33 -0700500 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
501 format != HAL_PIXEL_FORMAT_BLOB) {
502 if (!dataSpaceFromColorSpace(&dataSpace, colorSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700503 std::string msg = fmt::sprintf("Camera %s: color space %d not supported, failed to "
504 "convert to data space", logicalCameraId.c_str(), colorSpace);
505 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
506 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9b263b12023-03-27 17:01:33 -0700507 }
508 }
509
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000510 // FIXME: remove this override since the default format should be
511 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
512 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
513 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
514 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
515 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Austin Borger1c1bee02023-06-01 16:51:35 -0700516 __FUNCTION__, logicalCameraId.c_str(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000517 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
518 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800519 std::unordered_set<int32_t> overriddenSensorPixelModes;
520 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000521 physicalCameraMetadata, &overriddenSensorPixelModes) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700522 std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
523 "format %#x are not valid",logicalCameraId.c_str(), format);
524 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
525 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800526 }
527 bool foundInMaxRes = false;
528 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
529 overriddenSensorPixelModes.end()) {
530 // we can use the default stream configuration map
531 foundInMaxRes = true;
532 }
Shuzhen Wang0709c282024-02-12 09:09:32 -0800533 // Round dimensions to the nearest dimensions available for this format.
534 // Only do the rounding if the client doesn't ask to respect the surface
535 // size.
536 if (flexibleConsumer && isPublicFormat(format) && !respectSurfaceSize &&
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000537 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800538 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
539 /*out*/&height)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700540 std::string msg = fmt::sprintf("Camera %s: No supported stream configurations with "
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000541 "format %#x defined, failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700542 logicalCameraId.c_str(), format);
543 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
544 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000545 }
Emilian Peev2295df72021-11-12 18:14:10 -0800546 if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
547 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700548 std::string msg = fmt::sprintf("Camera %s: Dynamic range profile 0x%" PRIx64
549 " not supported,failed to create output stream", logicalCameraId.c_str(),
Emilian Peevc81a7592022-02-14 17:38:18 -0800550 dynamicRangeProfile);
Austin Borger1c1bee02023-06-01 16:51:35 -0700551 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
552 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800553 }
554 if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
Emilian Peev434248e2022-10-06 14:58:54 -0700555 !SessionConfigurationUtils::is10bitCompatibleFormat(format, dataSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700556 std::string msg = fmt::sprintf("Camera %s: No 10-bit supported stream configurations with "
Emilian Peevc81a7592022-02-14 17:38:18 -0800557 "format %#x defined and profile %" PRIx64 ", failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700558 logicalCameraId.c_str(), format, dynamicRangeProfile);
559 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
560 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800561 }
Austin Borger9e2b27c2022-07-15 11:27:24 -0700562 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
563 SessionConfigurationUtils::deviceReportsColorSpaces(physicalCameraMetadata) &&
564 !SessionConfigurationUtils::isColorSpaceSupported(colorSpace, format, dataSpace,
565 dynamicRangeProfile, physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700566 std::string msg = fmt::sprintf("Camera %s: Color space %d not supported, failed to "
Austin Borger9e2b27c2022-07-15 11:27:24 -0700567 "create output stream (pixel format %d dynamic range profile %" PRId64 ")",
Austin Borger1c1bee02023-06-01 16:51:35 -0700568 logicalCameraId.c_str(), colorSpace, format, dynamicRangeProfile);
569 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
570 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9e2b27c2022-07-15 11:27:24 -0700571 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800572 if (!SessionConfigurationUtils::isStreamUseCaseSupported(streamUseCase,
573 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700574 std::string msg = fmt::sprintf("Camera %s: stream use case %" PRId64 " not supported,"
575 " failed to create output stream", logicalCameraId.c_str(), streamUseCase);
576 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
577 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800578 }
Shuzhen Wange4208922022-02-01 16:52:48 -0800579 if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700580 timestampBase > OutputConfiguration::TIMESTAMP_BASE_MAX) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700581 std::string msg = fmt::sprintf("Camera %s: invalid timestamp base %d",
582 logicalCameraId.c_str(), timestampBase);
583 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
584 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wange4208922022-02-01 16:52:48 -0800585 }
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800586 if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
587 mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700588 std::string msg = fmt::sprintf("Camera %s: invalid mirroring mode %d",
589 logicalCameraId.c_str(), mirrorMode);
590 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
591 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800592 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000593
594 if (!isStreamInfoValid) {
595 streamInfo.width = width;
596 streamInfo.height = height;
597 streamInfo.format = format;
598 streamInfo.dataSpace = dataSpace;
599 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800600 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Emilian Peev2295df72021-11-12 18:14:10 -0800601 streamInfo.dynamicRangeProfile = dynamicRangeProfile;
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800602 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wange4208922022-02-01 16:52:48 -0800603 streamInfo.timestampBase = timestampBase;
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800604 streamInfo.mirrorMode = mirrorMode;
Austin Borger9e2b27c2022-07-15 11:27:24 -0700605 streamInfo.colorSpace = colorSpace;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000606 return binder::Status::ok();
607 }
608 if (width != streamInfo.width) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700609 std::string msg = fmt::sprintf("Camera %s:Surface width doesn't match: %d vs %d",
610 logicalCameraId.c_str(), width, streamInfo.width);
611 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
612 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000613 }
614 if (height != streamInfo.height) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700615 std::string msg = fmt::sprintf("Camera %s:Surface height doesn't match: %d vs %d",
616 logicalCameraId.c_str(), height, streamInfo.height);
617 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
618 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000619 }
620 if (format != streamInfo.format) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700621 std::string msg = fmt::sprintf("Camera %s:Surface format doesn't match: %d vs %d",
622 logicalCameraId.c_str(), format, streamInfo.format);
623 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
624 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000625 }
626 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
627 if (dataSpace != streamInfo.dataSpace) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700628 std::string msg = fmt::sprintf("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Henri Chataingbcb99452023-11-01 17:40:30 +0000629 logicalCameraId.c_str(), static_cast<int>(dataSpace), static_cast<int>(streamInfo.dataSpace));
Austin Borger1c1bee02023-06-01 16:51:35 -0700630 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
631 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000632 }
633 //At the native side, there isn't a way to check whether 2 surfaces come from the same
634 //surface class type. Use usage flag to approximate the comparison.
635 if (consumerUsage != streamInfo.consumerUsage) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700636 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000637 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Austin Borger1c1bee02023-06-01 16:51:35 -0700638 logicalCameraId.c_str(), consumerUsage, streamInfo.consumerUsage);
639 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
640 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000641 }
642 }
643 return binder::Status::ok();
644}
645
Austin Borgerea931242021-12-13 23:10:41 +0000646void mapStreamInfo(const OutputStreamInfo &streamInfo,
Austin Borger1c1bee02023-06-01 16:51:35 -0700647 camera3::camera_stream_rotation_t rotation, const std::string &physicalId,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000648 int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000649 if (stream == nullptr) {
650 return;
651 }
652
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000653 stream->streamType = aidl::android::hardware::camera::device::StreamType::OUTPUT;
654 stream->width = streamInfo.width;
655 stream->height = streamInfo.height;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000656 stream->format = AidlCamera3Device::mapToAidlPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000657 auto u = streamInfo.consumerUsage;
658 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000659 stream->usage = AidlCamera3Device::mapToAidlConsumerUsage(u);
660 stream->dataSpace = AidlCamera3Device::mapToAidlDataspace(streamInfo.dataSpace);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700661 stream->colorSpace = streamInfo.colorSpace;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000662 stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000663 stream->id = -1; // Invalid stream id
Austin Borger1c1bee02023-06-01 16:51:35 -0700664 stream->physicalCameraId = physicalId;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000665 stream->bufferSize = 0;
666 stream->groupId = groupId;
667 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800668 size_t idx = 0;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000669 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800670 for (auto mode : streamInfo.sensorPixelModesUsed) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000671 stream->sensorPixelModesUsed[idx++] =
672 static_cast<SensorPixelMode>(mode);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800673 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000674 using DynamicRangeProfile =
675 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
676 stream->dynamicRangeProfile = static_cast<DynamicRangeProfile>(streamInfo.dynamicRangeProfile);
677 using StreamUseCases =
678 aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
679 stream->useCase = static_cast<StreamUseCases>(streamInfo.streamUseCase);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000680}
681
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800682binder::Status
Austin Borgerea931242021-12-13 23:10:41 +0000683convertToHALStreamCombination(
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800684 const SessionConfiguration& sessionConfiguration,
Austin Borger1c1bee02023-06-01 16:51:35 -0700685 const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
Emilian Peev15230142023-04-27 20:22:54 +0000686 bool isCompositeJpegRDisabled,
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800687 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000688 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700689 bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +0000690 bool checkSessionParams, const std::vector<int32_t>& additionalKeys,
691 bool *earlyExit) {
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000692 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000693 auto operatingMode = sessionConfiguration.getOperatingMode();
Austin Borger1c1bee02023-06-01 16:51:35 -0700694 binder::Status res = checkOperatingMode(operatingMode, deviceInfo,
695 logicalCameraId);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000696 if (!res.isOk()) {
697 return res;
698 }
699
700 if (earlyExit == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700701 std::string msg("earlyExit nullptr");
702 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
703 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000704 }
705 *earlyExit = false;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000706 auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700707 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000708 /*out*/ &streamConfiguration.operationMode);
709 if (ret != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700710 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000711 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
Austin Borger1c1bee02023-06-01 16:51:35 -0700712 logicalCameraId.c_str(), operatingMode, strerror(-ret), ret);
713 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000714 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -0700715 msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000716 }
717
718 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
719 (sessionConfiguration.getInputHeight() > 0) &&
720 (sessionConfiguration.getInputFormat() > 0);
721 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
722 size_t streamCount = outputConfigs.size();
723 streamCount = isInputValid ? streamCount + 1 : streamCount;
724 streamConfiguration.streams.resize(streamCount);
725 size_t streamIdx = 0;
726 if (isInputValid) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000727 std::vector<SensorPixelMode> defaultSensorPixelModes;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800728 defaultSensorPixelModes.resize(1);
729 defaultSensorPixelModes[0] =
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000730 static_cast<SensorPixelMode>(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
731 aidl::android::hardware::camera::device::Stream stream;
732 stream.id = 0;
733 stream.streamType = aidl::android::hardware::camera::device::StreamType::INPUT;
734 stream.width = static_cast<uint32_t> (sessionConfiguration.getInputWidth());
735 stream.height = static_cast<uint32_t> (sessionConfiguration.getInputHeight());
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000736 stream.format =
737 AidlCamera3Device::AidlCamera3Device::mapToAidlPixelFormat(
738 sessionConfiguration.getInputFormat());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000739 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0);
740 stream.dataSpace =
741 static_cast<aidl::android::hardware::graphics::common::Dataspace>(
742 HAL_DATASPACE_UNKNOWN);
743 stream.rotation = aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
744 stream.bufferSize = 0;
745 stream.groupId = -1;
746 stream.sensorPixelModesUsed = defaultSensorPixelModes;
Emilian Peev065fb0f2022-05-16 15:37:16 -0700747 using DynamicRangeProfile =
748 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
749 stream.dynamicRangeProfile =
750 DynamicRangeProfile::ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000751 streamConfiguration.streams[streamIdx++] = stream;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800752 streamConfiguration.multiResolutionInputImage =
753 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000754 }
755
756 for (const auto &it : outputConfigs) {
757 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
758 it.getGraphicBufferProducers();
759 bool deferredConsumer = it.isDeferred();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800760 bool isConfigurationComplete = it.isComplete();
Austin Borger1c1bee02023-06-01 16:51:35 -0700761 const std::string &physicalCameraId = it.getPhysicalCameraId();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800762
Emilian Peevc81a7592022-02-14 17:38:18 -0800763 int64_t dynamicRangeProfile = it.getDynamicRangeProfile();
Austin Borger9e2b27c2022-07-15 11:27:24 -0700764 int32_t colorSpace = it.getColorSpace();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800765 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700766 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
767 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800768 const CameraMetadata &metadataChosen =
769 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
770
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000771 size_t numBufferProducers = bufferProducers.size();
772 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800773 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000774 OutputStreamInfo streamInfo;
775
Shuzhen Wang0709c282024-02-12 09:09:32 -0800776 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType(),
777 isConfigurationComplete);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000778 if (!res.isOk()) {
779 return res;
780 }
781 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
782 logicalCameraId);
783 if (!res.isOk()) {
784 return res;
785 }
786
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800787 int64_t streamUseCase = it.getStreamUseCase();
Shuzhen Wange4208922022-02-01 16:52:48 -0800788 int timestampBase = it.getTimestampBase();
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800789 int mirrorMode = it.getMirrorMode();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800790 // If the configuration is a deferred consumer, or a not yet completed
791 // configuration with no buffer producers attached.
792 if (deferredConsumer || (!isConfigurationComplete && numBufferProducers == 0)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000793 streamInfo.width = it.getWidth();
794 streamInfo.height = it.getHeight();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000795 auto surfaceType = it.getSurfaceType();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800796 switch (surfaceType) {
797 case OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE:
798 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
799 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
800 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
801 break;
802 case OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW:
803 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE
804 | GraphicBuffer::USAGE_HW_COMPOSER;
805 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
806 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
807 break;
808 case OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER:
809 case OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC:
810 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
811 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
812 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
813 break;
814 case OutputConfiguration::SURFACE_TYPE_IMAGE_READER:
815 streamInfo.consumerUsage = it.getUsage();
816 streamInfo.format = it.getFormat();
817 streamInfo.dataSpace = (android_dataspace)it.getDataspace();
818 break;
819 default:
820 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
821 "Invalid surface type.");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000822 }
Emilian Peev2295df72021-11-12 18:14:10 -0800823 streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800824 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
825 streamInfo.format, streamInfo.width,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000826 streamInfo.height, metadataChosen,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800827 &streamInfo.sensorPixelModesUsed) != OK) {
828 ALOGE("%s: Deferred surface sensor pixel modes not valid",
829 __FUNCTION__);
830 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
831 "Deferred surface sensor pixel modes not valid");
832 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800833 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800834 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000835 &streamConfiguration.streams[streamIdx++]);
836 isStreamInfoValid = true;
837
838 if (numBufferProducers == 0) {
839 continue;
840 }
841 }
842
843 for (auto& bufferProducer : bufferProducers) {
844 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000845 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800846 logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800847 streamUseCase, timestampBase, mirrorMode, colorSpace,
848 /*respectSurfaceSize*/true);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000849
850 if (!res.isOk())
851 return res;
852
853 if (!isStreamInfoValid) {
854 bool isDepthCompositeStream =
855 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
856 bool isHeicCompositeStream =
857 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
Emilian Peev434248e2022-10-06 14:58:54 -0700858 bool isJpegRCompositeStream =
Emilian Peeve579d8b2023-02-28 14:16:08 -0800859 camera3::JpegRCompositeStream::isJpegRCompositeStream(surface) &&
Emilian Peev15230142023-04-27 20:22:54 +0000860 !isCompositeJpegRDisabled;
Emilian Peev434248e2022-10-06 14:58:54 -0700861 if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000862 // We need to take in to account that composite streams can have
863 // additional internal camera streams.
864 std::vector<OutputStreamInfo> compositeStreams;
865 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800866 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000867 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
868 deviceInfo, &compositeStreams);
Emilian Peev434248e2022-10-06 14:58:54 -0700869 } else if (isHeicCompositeStream) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000870 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
871 deviceInfo, &compositeStreams);
Emilian Peev434248e2022-10-06 14:58:54 -0700872 } else {
873 ret = camera3::JpegRCompositeStream::getCompositeStreamInfo(streamInfo,
874 deviceInfo, &compositeStreams);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000875 }
Emilian Peev434248e2022-10-06 14:58:54 -0700876
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000877 if (ret != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700878 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000879 "Camera %s: Failed adding composite streams: %s (%d)",
Austin Borger1c1bee02023-06-01 16:51:35 -0700880 logicalCameraId.c_str(), strerror(-ret), ret);
881 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
882 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000883 }
884
885 if (compositeStreams.size() == 0) {
886 // No internal streams means composite stream not
887 // supported.
888 *earlyExit = true;
889 return binder::Status::ok();
890 } else if (compositeStreams.size() > 1) {
891 streamCount += compositeStreams.size() - 1;
892 streamConfiguration.streams.resize(streamCount);
893 }
894
895 for (const auto& compositeStream : compositeStreams) {
896 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700897 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800898 physicalCameraId, groupId,
899 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000900 }
901 } else {
902 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700903 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800904 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000905 }
906 isStreamInfoValid = true;
907 }
908 }
909 }
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700910
911 if (checkSessionParams) {
912 const CameraMetadata &deviceInfo = getMetadata(logicalCameraId,
913 /*overrideForPerfClass*/false);
914 CameraMetadata filteredParams;
915
916 filterParameters(sessionConfiguration.getSessionParameters(), deviceInfo,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +0000917 additionalKeys, vendorTagId, filteredParams);
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700918
919 camera_metadata_t* metadata = const_cast<camera_metadata_t*>(filteredParams.getAndLock());
920 uint8_t *metadataP = reinterpret_cast<uint8_t*>(metadata);
921 streamConfiguration.sessionParams.metadata.assign(metadataP,
922 metadataP + get_camera_metadata_size(metadata));
923 }
924
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000925 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800926}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000927
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000928binder::Status checkPhysicalCameraId(
Austin Borger1c1bee02023-06-01 16:51:35 -0700929 const std::vector<std::string> &physicalCameraIds, const std::string &physicalCameraId,
930 const std::string &logicalCameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000931 if (physicalCameraId.size() == 0) {
932 return binder::Status::ok();
933 }
934 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
Austin Borger1c1bee02023-06-01 16:51:35 -0700935 physicalCameraId) == physicalCameraIds.end()) {
936 std::string msg = fmt::sprintf("Camera %s: Camera doesn't support physicalCameraId %s.",
937 logicalCameraId.c_str(), physicalCameraId.c_str());
938 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
939 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000940 }
941 return binder::Status::ok();
942}
943
944binder::Status checkSurfaceType(size_t numBufferProducers,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800945 bool deferredConsumer, int surfaceType, bool isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000946 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
947 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
948 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
949 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
Shuzhen Wang0709c282024-02-12 09:09:32 -0800950 } else if ((numBufferProducers == 0) && (!deferredConsumer) && isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000951 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
952 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
953 }
954
Shuzhen Wang0709c282024-02-12 09:09:32 -0800955 if (deferredConsumer) {
956 bool validSurfaceType = (
957 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
958 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
959 if (!validSurfaceType) {
960 std::string msg = fmt::sprintf("Deferred target surface has invalid "
961 "surfaceType = %d.", surfaceType);
962 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
963 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
964 }
965 } else if (!isConfigurationComplete && numBufferProducers == 0) {
966 bool validSurfaceType = (
967 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER) ||
968 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC) ||
969 (surfaceType == OutputConfiguration::SURFACE_TYPE_IMAGE_READER));
970 if (!validSurfaceType) {
971 std::string msg = fmt::sprintf("OutputConfiguration target surface has invalid "
972 "surfaceType = %d.", surfaceType);
973 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
974 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
975 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000976 }
977
978 return binder::Status::ok();
979}
980
981binder::Status checkOperatingMode(int operatingMode,
Austin Borger1c1bee02023-06-01 16:51:35 -0700982 const CameraMetadata &staticInfo, const std::string &cameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000983 if (operatingMode < 0) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700984 std::string msg = fmt::sprintf(
985 "Camera %s: Invalid operating mode %d requested", cameraId.c_str(), operatingMode);
986 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000987 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -0700988 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000989 }
990
991 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
992 if (isConstrainedHighSpeed) {
993 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
994 bool isConstrainedHighSpeedSupported = false;
995 for(size_t i = 0; i < entry.count; ++i) {
996 uint8_t capability = entry.data.u8[i];
997 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
998 isConstrainedHighSpeedSupported = true;
999 break;
1000 }
1001 }
1002 if (!isConstrainedHighSpeedSupported) {
Austin Borger1c1bee02023-06-01 16:51:35 -07001003 std::string msg = fmt::sprintf(
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001004 "Camera %s: Try to create a constrained high speed configuration on a device"
Austin Borger1c1bee02023-06-01 16:51:35 -07001005 " that doesn't support it.", cameraId.c_str());
1006 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001007 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -07001008 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001009 }
1010 }
1011
1012 return binder::Status::ok();
1013}
1014
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001015static bool inStreamConfigurationMap(int format, int width, int height,
1016 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
1017 auto scs = sm.find(format);
1018 if (scs == sm.end()) {
1019 return false;
1020 }
1021 for (auto &sc : scs->second) {
1022 if (sc.width == width && sc.height == height && sc.isInput == 0) {
1023 return true;
1024 }
1025 }
1026 return false;
1027}
1028
1029static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
1030 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
1031}
1032
Austin Borgerea931242021-12-13 23:10:41 +00001033status_t checkAndOverrideSensorPixelModesUsed(
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001034 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001035 const CameraMetadata &staticInfo,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001036 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001037
1038 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
1039 convertToSet(sensorPixelModesUsed);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001040 if (!supportsUltraHighResolutionCapture(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001041 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1042 sensorPixelModesUsedSet.end()) {
1043 // invalid value for non ultra high res sensors
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001044 ALOGE("%s ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION used on a device which doesn't "
1045 "support ultra high resolution capture", __FUNCTION__);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001046 return BAD_VALUE;
1047 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001048 overriddenSensorPixelModesUsed->clear();
1049 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
1050 return OK;
1051 }
1052
1053 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001054
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001055 bool isInDefaultStreamConfigurationMap =
1056 inStreamConfigurationMap(format, width, height,
1057 streamConfigurationPair.mDefaultStreamConfigurationMap);
1058
1059 bool isInMaximumResolutionStreamConfigurationMap =
1060 inStreamConfigurationMap(format, width, height,
1061 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
1062
1063 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
1064 // size + format of the OutputConfiguration is found exclusively in 1.
1065 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001066 // If no, add 'DEFAULT' and MAXIMUM_RESOLUTION to overriddenSensorPixelModes.
1067 // This maintains backwards compatibility and also tells the framework the stream
1068 // might be used in either sensor pixel mode.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001069 if (sensorPixelModesUsedSet.size() == 0) {
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001070 // Ambiguous case, override to include both cases.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001071 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
1072 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001073 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001074 return OK;
1075 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001076 if (isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001077 overriddenSensorPixelModesUsed->insert(
1078 ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1079 } else {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001080 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001081 }
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001082 return OK;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001083 }
1084
1085 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
1086 // are valid / err out.
1087 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
1088 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001089 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_DEFAULT set by client, but stream f: %d size %d x %d"
1090 " isn't present in default stream configuration map", __FUNCTION__, format, width,
1091 height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001092 return BAD_VALUE;
1093 }
1094
1095 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1096 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001097 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION set by client, but stream f: "
1098 "%d size %d x %d isn't present in default stream configuration map", __FUNCTION__,
1099 format, width, height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001100 return BAD_VALUE;
1101 }
1102 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
1103 return OK;
1104}
1105
Austin Borgerea931242021-12-13 23:10:41 +00001106bool targetPerfClassPrimaryCamera(
Shuzhen Wangd4abdf72021-05-28 11:22:50 -07001107 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
1108 int targetSdkVersion) {
1109 bool isPerfClassPrimaryCamera =
1110 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
1111 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
1112}
1113
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001114binder::Status mapRequestTemplateFromClient(const std::string& cameraId, int templateId,
1115 camera_request_template_t* tempId /*out*/) {
1116 binder::Status ret = binder::Status::ok();
1117
1118 if (tempId == nullptr) {
1119 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1120 "Camera %s: Invalid template argument", cameraId.c_str());
1121 return ret;
1122 }
1123 switch(templateId) {
1124 case ICameraDeviceUser::TEMPLATE_PREVIEW:
1125 *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
1126 break;
1127 case ICameraDeviceUser::TEMPLATE_RECORD:
1128 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
1129 break;
1130 case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
1131 *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
1132 break;
1133 case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
1134 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
1135 break;
1136 case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
1137 *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
1138 break;
1139 case ICameraDeviceUser::TEMPLATE_MANUAL:
1140 *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
1141 break;
1142 default:
1143 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1144 "Camera %s: Template ID %d is invalid or not supported",
1145 cameraId.c_str(), templateId);
1146 return ret;
1147 }
1148
1149 return ret;
1150}
1151
1152status_t mapRequestTemplateToAidl(camera_request_template_t templateId,
1153 RequestTemplate* id /*out*/) {
1154 switch (templateId) {
1155 case CAMERA_TEMPLATE_PREVIEW:
1156 *id = RequestTemplate::PREVIEW;
1157 break;
1158 case CAMERA_TEMPLATE_STILL_CAPTURE:
1159 *id = RequestTemplate::STILL_CAPTURE;
1160 break;
1161 case CAMERA_TEMPLATE_VIDEO_RECORD:
1162 *id = RequestTemplate::VIDEO_RECORD;
1163 break;
1164 case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
1165 *id = RequestTemplate::VIDEO_SNAPSHOT;
1166 break;
1167 case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
1168 *id = RequestTemplate::ZERO_SHUTTER_LAG;
1169 break;
1170 case CAMERA_TEMPLATE_MANUAL:
1171 *id = RequestTemplate::MANUAL;
1172 break;
1173 default:
1174 // Unknown template ID, or this HAL is too old to support it
1175 return BAD_VALUE;
1176 }
1177 return OK;
1178}
1179
1180void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001181 const std::vector<int32_t>& additionalTags, metadata_vendor_id_t vendorTagId,
1182 CameraMetadata& dst) {
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001183 const CameraMetadata params(src);
1184 camera_metadata_ro_entry_t availableSessionKeys = deviceInfo.find(
1185 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
1186 CameraMetadata filteredParams(availableSessionKeys.count);
1187 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1188 filteredParams.getAndLock());
1189 set_camera_metadata_vendor_id(meta, vendorTagId);
1190 filteredParams.unlock(meta);
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001191
1192 std::unordered_set<int32_t> filteredTags(availableSessionKeys.data.i32,
1193 availableSessionKeys.data.i32 + availableSessionKeys.count);
1194 filteredTags.insert(additionalTags.begin(), additionalTags.end());
1195 for (int32_t tag : filteredTags) {
1196 camera_metadata_ro_entry entry = params.find(tag);
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001197 if (entry.count > 0) {
1198 filteredParams.update(entry);
1199 }
1200 }
1201 dst = std::move(filteredParams);
1202}
1203
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001204status_t overrideDefaultRequestKeys(CameraMetadata *request) {
1205 // Override the template request with ZoomRatioMapper
1206 status_t res = ZoomRatioMapper::initZoomRatioInTemplate(request);
1207 if (res != OK) {
1208 ALOGE("Failed to update zoom ratio: %s (%d)", strerror(-res), res);
1209 return res;
1210 }
1211
1212 // Fill in JPEG_QUALITY if not available
1213 if (!request->exists(ANDROID_JPEG_QUALITY)) {
1214 static const uint8_t kDefaultJpegQuality = 95;
1215 request->update(ANDROID_JPEG_QUALITY, &kDefaultJpegQuality, 1);
1216 }
1217
1218 // Fill in AUTOFRAMING if not available
1219 if (!request->exists(ANDROID_CONTROL_AUTOFRAMING)) {
1220 static const uint8_t kDefaultAutoframingMode = ANDROID_CONTROL_AUTOFRAMING_OFF;
1221 request->update(ANDROID_CONTROL_AUTOFRAMING, &kDefaultAutoframingMode, 1);
1222 }
1223
1224 return OK;
1225}
1226
Austin Borgerea931242021-12-13 23:10:41 +00001227} // namespace SessionConfigurationUtils
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001228} // namespace camera3
1229} // namespace android