blob: 23aed6e63449c32f525c8304267653bcccf74484 [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"
Emilian Peev2295df72021-11-12 18:14:10 -080030#include "system/graphics-base-v1.1.h"
Austin Borger1c1bee02023-06-01 16:51:35 -070031#include <camera/StringUtils.h>
Emilian Peev434248e2022-10-06 14:58:54 -070032#include <ui/PublicFormat.h>
Colin Crossb8a9dbb2020-08-27 04:12:26 +000033
Colin Crossb8a9dbb2020-08-27 04:12:26 +000034using android::camera3::OutputStreamInfo;
35using android::camera3::OutputStreamInfo;
36using android::hardware::camera2::ICameraDeviceUser;
Shuzhen Wang045be6c2023-10-12 10:01:10 -070037using aidl::android::hardware::camera::device::RequestTemplate;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080038
39namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080040namespace camera3 {
41
42void StreamConfiguration::getStreamConfigurations(
43 const CameraMetadata &staticInfo, int configuration,
44 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
45 if (scm == nullptr) {
46 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
47 return;
48 }
49 const int STREAM_FORMAT_OFFSET = 0;
50 const int STREAM_WIDTH_OFFSET = 1;
51 const int STREAM_HEIGHT_OFFSET = 2;
52 const int STREAM_IS_INPUT_OFFSET = 3;
53
54 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
55 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
56 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
57 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
58 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
59 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
60 StreamConfiguration sc = {format, width, height, isInput};
61 (*scm)[format].push_back(sc);
62 }
63}
64
65void StreamConfiguration::getStreamConfigurations(
66 const CameraMetadata &staticInfo, bool maxRes,
67 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
68 int32_t scalerKey =
69 SessionConfigurationUtils::getAppropriateModeTag(
70 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
71
72 int32_t depthKey =
73 SessionConfigurationUtils::getAppropriateModeTag(
74 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
75
76 int32_t dynamicDepthKey =
77 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070078 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080079
80 int32_t heicKey =
81 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070082 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080083
84 getStreamConfigurations(staticInfo, scalerKey, scm);
85 getStreamConfigurations(staticInfo, depthKey, scm);
86 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
87 getStreamConfigurations(staticInfo, heicKey, scm);
88}
89
Austin Borgerea931242021-12-13 23:10:41 +000090namespace SessionConfigurationUtils {
91
92int32_t PERF_CLASS_LEVEL =
93 property_get_int32("ro.odm.build.media_performance_class", 0);
94
Shuzhen Wangf18887c2022-05-31 10:24:02 -070095bool IS_PERF_CLASS = (PERF_CLASS_LEVEL >= SDK_VERSION_S);
Austin Borgerea931242021-12-13 23:10:41 +000096
97camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
98 bool ultraHighResolution) {
99 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
100 const int STREAM_CONFIGURATION_SIZE = 4;
101 const int STREAM_FORMAT_OFFSET = 0;
102 const int STREAM_WIDTH_OFFSET = 1;
103 const int STREAM_HEIGHT_OFFSET = 2;
104 const int STREAM_IS_INPUT_OFFSET = 3;
105
106 int32_t scalerSizesTag = ultraHighResolution ?
107 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
108 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
109 camera_metadata_ro_entry_t availableStreamConfigs =
110 metadata.find(scalerSizesTag);
111 if (availableStreamConfigs.count == 0 ||
112 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
113 return camera3::Size(0, 0);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800114 }
Austin Borgerea931242021-12-13 23:10:41 +0000115
116 // Get max jpeg size (area-wise).
117 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
118 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
119 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
120 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
121 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
122 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
123 && format == HAL_PIXEL_FORMAT_BLOB &&
124 (width * height > maxJpegWidth * maxJpegHeight)) {
125 maxJpegWidth = width;
126 maxJpegHeight = height;
127 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800128 }
Austin Borgerea931242021-12-13 23:10:41 +0000129
130 return camera3::Size(maxJpegWidth, maxJpegHeight);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800131}
132
Austin Borgerea931242021-12-13 23:10:41 +0000133size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
134 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
Jayant Chowdharyb2d84202022-07-11 21:46:53 +0000135 return ((float)(uhrMaxJpegSize.width * uhrMaxJpegSize.height)) /
Austin Borgerea931242021-12-13 23:10:41 +0000136 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
137}
138
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800139StreamConfigurationPair
Austin Borgerea931242021-12-13 23:10:41 +0000140getStreamConfigurationPair(const CameraMetadata &staticInfo) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800141 camera3::StreamConfigurationPair streamConfigurationPair;
142 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
143 &streamConfigurationPair.mDefaultStreamConfigurationMap);
144 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
145 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
146 return streamConfigurationPair;
147}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800148
Austin Borgerea931242021-12-13 23:10:41 +0000149int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000150 int64_t d0 = x0 - x1;
151 int64_t d1 = y0 - y1;
152 return d0 * d0 + d1 * d1;
153}
154
Austin Borgerea931242021-12-13 23:10:41 +0000155bool roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800156 int32_t format, android_dataspace dataSpace,
157 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
158 /*out*/int32_t* outHeight) {
159 const int32_t depthSizesTag =
160 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
161 maxResolution);
162 const int32_t scalerSizesTag =
163 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
164 const int32_t heicSizesTag =
165 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Emilian Peevad25a072023-04-05 12:24:13 -0700166 const int32_t jpegRSizesTag = getAppropriateModeTag(
167 ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000168
Emilian Peevad25a072023-04-05 12:24:13 -0700169 bool isJpegRDataSpace = (dataSpace == static_cast<android_dataspace_t>(
170 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000171 camera_metadata_ro_entry streamConfigs =
Emilian Peevad25a072023-04-05 12:24:13 -0700172 (isJpegRDataSpace) ? info.find(jpegRSizesTag) :
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800173 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000174 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800175 info.find(heicSizesTag) :
176 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000177
178 int32_t bestWidth = -1;
179 int32_t bestHeight = -1;
180
181 // Iterate through listed stream configurations and find the one with the smallest euclidean
182 // distance from the given dimensions for the given format.
183 for (size_t i = 0; i < streamConfigs.count; i += 4) {
184 int32_t fmt = streamConfigs.data.i32[i];
185 int32_t w = streamConfigs.data.i32[i + 1];
186 int32_t h = streamConfigs.data.i32[i + 2];
187
188 // Ignore input/output type for now
189 if (fmt == format) {
190 if (w == width && h == height) {
191 bestWidth = width;
192 bestHeight = height;
193 break;
194 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
195 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
196 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
197 height))) {
198 bestWidth = w;
199 bestHeight = h;
200 }
201 }
202 }
203
204 if (bestWidth == -1) {
205 // Return false if no configurations for this format were listed
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -0800206 ALOGE("%s: No configurations for format %d width %d, height %d, maxResolution ? %s",
207 __FUNCTION__, format, width, height, maxResolution ? "true" : "false");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000208 return false;
209 }
210
211 // Set the outputs to the closet width/height
212 if (outWidth != NULL) {
213 *outWidth = bestWidth;
214 }
215 if (outHeight != NULL) {
216 *outHeight = bestHeight;
217 }
218
219 // Return true if at least one configuration for this format was listed
220 return true;
221}
222
Emilian Peev2295df72021-11-12 18:14:10 -0800223//check if format is 10-bit compatible
Emilian Peev434248e2022-10-06 14:58:54 -0700224bool is10bitCompatibleFormat(int32_t format, android_dataspace_t dataSpace) {
Emilian Peev2295df72021-11-12 18:14:10 -0800225 switch(format) {
226 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
227 case HAL_PIXEL_FORMAT_YCBCR_P010:
228 return true;
Emilian Peev434248e2022-10-06 14:58:54 -0700229 case HAL_PIXEL_FORMAT_BLOB:
230 if (dataSpace == static_cast<android_dataspace_t>(
231 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
232 return true;
233 }
234
235 return false;
Emilian Peev2295df72021-11-12 18:14:10 -0800236 default:
237 return false;
238 }
239}
240
Emilian Peevc81a7592022-02-14 17:38:18 -0800241bool isDynamicRangeProfileSupported(int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
Emilian Peev2295df72021-11-12 18:14:10 -0800242 if (dynamicRangeProfile == ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
243 // Supported by default
244 return true;
245 }
246
247 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
248 bool is10bitDynamicRangeSupported = false;
249 for (size_t i = 0; i < entry.count; ++i) {
250 uint8_t capability = entry.data.u8[i];
251 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
252 is10bitDynamicRangeSupported = true;
253 break;
254 }
255 }
256
257 if (!is10bitDynamicRangeSupported) {
258 return false;
259 }
260
261 switch (dynamicRangeProfile) {
262 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
263 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
264 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
265 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
266 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
267 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
268 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
269 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
270 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
271 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
272 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
273 entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
Emilian Peevc81a7592022-02-14 17:38:18 -0800274 for (size_t i = 0; i < entry.count; i += 3) {
275 if (dynamicRangeProfile == entry.data.i64[i]) {
Emilian Peev2295df72021-11-12 18:14:10 -0800276 return true;
277 }
278 }
279
280 return false;
281 default:
282 return false;
283 }
284
285 return false;
286}
287
288//check if format is 10-bit compatible
Emilian Peevc81a7592022-02-14 17:38:18 -0800289bool is10bitDynamicRangeProfile(int64_t dynamicRangeProfile) {
Emilian Peev2295df72021-11-12 18:14:10 -0800290 switch (dynamicRangeProfile) {
291 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
292 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
293 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
294 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
295 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
296 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
297 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
298 return true;
299 default:
300 return false;
301 }
302}
303
Austin Borger9e2b27c2022-07-15 11:27:24 -0700304bool deviceReportsColorSpaces(const CameraMetadata& staticInfo) {
305 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
306 for (size_t i = 0; i < entry.count; ++i) {
307 uint8_t capability = entry.data.u8[i];
308 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES) {
309 return true;
310 }
311 }
312
313 return false;
314}
315
316bool isColorSpaceSupported(int32_t colorSpace, int32_t format, android_dataspace dataSpace,
317 int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
318 int64_t colorSpace64 = colorSpace;
319 int64_t format64 = format;
320
321 // Translate HAL format + data space to public format
322 if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_V0_JFIF) {
323 format64 = 0x100; // JPEG
324 } else if (format == HAL_PIXEL_FORMAT_BLOB
325 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) {
326 format64 = 0x48454946; // HEIC
327 } else if (format == HAL_PIXEL_FORMAT_BLOB
328 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
329 format64 = 0x69656963; // DEPTH_JPEG
330 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_DEPTH) {
331 return false; // DEPTH_POINT_CLOUD, not applicable
332 } else if (format == HAL_PIXEL_FORMAT_Y16 && dataSpace == HAL_DATASPACE_DEPTH) {
333 return false; // DEPTH16, not applicable
334 } else if (format == HAL_PIXEL_FORMAT_RAW16 && dataSpace == HAL_DATASPACE_DEPTH) {
335 return false; // RAW_DEPTH, not applicable
336 } else if (format == HAL_PIXEL_FORMAT_RAW10 && dataSpace == HAL_DATASPACE_DEPTH) {
337 return false; // RAW_DEPTH10, not applicable
Emilian Peev434248e2022-10-06 14:58:54 -0700338 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace ==
339 static_cast<android_dataspace>(
340 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
341 format64 = static_cast<int64_t>(PublicFormat::JPEG_R);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700342 }
343
344 camera_metadata_ro_entry_t entry =
345 staticInfo.find(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP);
346 for (size_t i = 0; i < entry.count; i += 3) {
347 bool isFormatCompatible = (format64 == entry.data.i64[i + 1]);
348 bool isDynamicProfileCompatible =
349 (dynamicRangeProfile & entry.data.i64[i + 2]) != 0;
350
351 if (colorSpace64 == entry.data.i64[i]
352 && isFormatCompatible
353 && isDynamicProfileCompatible) {
354 return true;
355 }
356 }
357
358 ALOGE("Color space %d, image format %" PRId64 ", and dynamic range 0x%" PRIx64
359 " combination not found", colorSpace, format64, dynamicRangeProfile);
360 return false;
361}
362
Austin Borgerea931242021-12-13 23:10:41 +0000363bool isPublicFormat(int32_t format)
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000364{
365 switch(format) {
366 case HAL_PIXEL_FORMAT_RGBA_8888:
367 case HAL_PIXEL_FORMAT_RGBX_8888:
368 case HAL_PIXEL_FORMAT_RGB_888:
369 case HAL_PIXEL_FORMAT_RGB_565:
370 case HAL_PIXEL_FORMAT_BGRA_8888:
371 case HAL_PIXEL_FORMAT_YV12:
372 case HAL_PIXEL_FORMAT_Y8:
373 case HAL_PIXEL_FORMAT_Y16:
374 case HAL_PIXEL_FORMAT_RAW16:
375 case HAL_PIXEL_FORMAT_RAW10:
376 case HAL_PIXEL_FORMAT_RAW12:
377 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
378 case HAL_PIXEL_FORMAT_BLOB:
379 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
380 case HAL_PIXEL_FORMAT_YCbCr_420_888:
381 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
382 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
383 case HAL_PIXEL_FORMAT_YCbCr_422_I:
384 return true;
385 default:
386 return false;
387 }
388}
389
Austin Borger9b263b12023-03-27 17:01:33 -0700390bool dataSpaceFromColorSpace(android_dataspace *dataSpace, int32_t colorSpace) {
391 switch (colorSpace) {
392 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB:
393 *dataSpace = HAL_DATASPACE_V0_SRGB;
394 return true;
395 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3:
396 *dataSpace = HAL_DATASPACE_DISPLAY_P3;
397 return true;
398 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG:
399 *(reinterpret_cast<int32_t*>(dataSpace)) = HAL_DATASPACE_BT2020_HLG;
400 return true;
401 default:
402 ALOGE("%s: Unsupported color space %d", __FUNCTION__, colorSpace);
403 return false;
404 }
405}
406
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800407bool isStreamUseCaseSupported(int64_t streamUseCase,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800408 const CameraMetadata &deviceInfo) {
409 camera_metadata_ro_entry_t availableStreamUseCases =
410 deviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES);
411
412 if (availableStreamUseCases.count == 0 &&
413 streamUseCase == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
414 return true;
415 }
Shuzhen Wangb77131a2022-04-27 15:34:33 -0700416 // Allow vendor stream use case unconditionally.
417 if (streamUseCase >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
418 return true;
419 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800420
421 for (size_t i = 0; i < availableStreamUseCases.count; i++) {
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800422 if (availableStreamUseCases.data.i64[i] == streamUseCase) {
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800423 return true;
424 }
425 }
426 return false;
427}
428
Austin Borgerea931242021-12-13 23:10:41 +0000429binder::Status createSurfaceFromGbp(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000430 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
431 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Austin Borger1c1bee02023-06-01 16:51:35 -0700432 const std::string &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
Emilian Peevc81a7592022-02-14 17:38:18 -0800433 const std::vector<int32_t> &sensorPixelModesUsed, int64_t dynamicRangeProfile,
Austin Borger9e2b27c2022-07-15 11:27:24 -0700434 int64_t streamUseCase, int timestampBase, int mirrorMode,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800435 int32_t colorSpace, bool respectSurfaceSize) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000436 // bufferProducer must be non-null
437 if (gbp == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700438 std::string msg = fmt::sprintf("Camera %s: Surface is NULL", logicalCameraId.c_str());
439 ALOGW("%s: %s", __FUNCTION__, msg.c_str());
440 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000441 }
442 // HACK b/10949105
443 // Query consumer usage bits to set async operation mode for
444 // GLConsumer using controlledByApp parameter.
445 bool useAsync = false;
446 uint64_t consumerUsage = 0;
447 status_t err;
448 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700449 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface consumer usage: %s (%d)",
450 logicalCameraId.c_str(), strerror(-err), err);
451 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
452 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000453 }
454 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
455 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Austin Borger1c1bee02023-06-01 16:51:35 -0700456 "stream", __FUNCTION__, logicalCameraId.c_str(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000457 useAsync = true;
458 }
459
460 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
461 GRALLOC_USAGE_RENDERSCRIPT;
462 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
463 GraphicBuffer::USAGE_HW_TEXTURE |
464 GraphicBuffer::USAGE_HW_COMPOSER;
465 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
466 (consumerUsage & allowedFlags) != 0;
467
468 surface = new Surface(gbp, useAsync);
469 ANativeWindow *anw = surface.get();
470
471 int width, height, format;
472 android_dataspace dataSpace;
473 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700474 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface width: %s (%d)",
475 logicalCameraId.c_str(), strerror(-err), err);
476 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
477 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000478 }
479 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700480 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface height: %s (%d)",
481 logicalCameraId.c_str(), strerror(-err), err);
482 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
483 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000484 }
485 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700486 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface format: %s (%d)",
487 logicalCameraId.c_str(), strerror(-err), err);
488 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
489 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000490 }
491 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
492 reinterpret_cast<int*>(&dataSpace))) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700493 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface dataspace: %s (%d)",
494 logicalCameraId.c_str(), strerror(-err), err);
495 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
496 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000497 }
498
Austin Borger9b263b12023-03-27 17:01:33 -0700499 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
500 format != HAL_PIXEL_FORMAT_BLOB) {
501 if (!dataSpaceFromColorSpace(&dataSpace, colorSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700502 std::string msg = fmt::sprintf("Camera %s: color space %d not supported, failed to "
503 "convert to data space", logicalCameraId.c_str(), colorSpace);
504 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
505 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9b263b12023-03-27 17:01:33 -0700506 }
507 }
508
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000509 // FIXME: remove this override since the default format should be
510 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
511 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
512 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
513 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
514 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Austin Borger1c1bee02023-06-01 16:51:35 -0700515 __FUNCTION__, logicalCameraId.c_str(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000516 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
517 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800518 std::unordered_set<int32_t> overriddenSensorPixelModes;
519 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000520 physicalCameraMetadata, &overriddenSensorPixelModes) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700521 std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
522 "format %#x are not valid",logicalCameraId.c_str(), format);
523 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
524 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800525 }
526 bool foundInMaxRes = false;
527 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
528 overriddenSensorPixelModes.end()) {
529 // we can use the default stream configuration map
530 foundInMaxRes = true;
531 }
Shuzhen Wang0709c282024-02-12 09:09:32 -0800532 // Round dimensions to the nearest dimensions available for this format.
533 // Only do the rounding if the client doesn't ask to respect the surface
534 // size.
535 if (flexibleConsumer && isPublicFormat(format) && !respectSurfaceSize &&
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000536 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800537 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
538 /*out*/&height)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700539 std::string msg = fmt::sprintf("Camera %s: No supported stream configurations with "
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000540 "format %#x defined, failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700541 logicalCameraId.c_str(), format);
542 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
543 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000544 }
Emilian Peev2295df72021-11-12 18:14:10 -0800545 if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
546 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700547 std::string msg = fmt::sprintf("Camera %s: Dynamic range profile 0x%" PRIx64
548 " not supported,failed to create output stream", logicalCameraId.c_str(),
Emilian Peevc81a7592022-02-14 17:38:18 -0800549 dynamicRangeProfile);
Austin Borger1c1bee02023-06-01 16:51:35 -0700550 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
551 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800552 }
553 if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
Emilian Peev434248e2022-10-06 14:58:54 -0700554 !SessionConfigurationUtils::is10bitCompatibleFormat(format, dataSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700555 std::string msg = fmt::sprintf("Camera %s: No 10-bit supported stream configurations with "
Emilian Peevc81a7592022-02-14 17:38:18 -0800556 "format %#x defined and profile %" PRIx64 ", failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700557 logicalCameraId.c_str(), format, dynamicRangeProfile);
558 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
559 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800560 }
Austin Borger9e2b27c2022-07-15 11:27:24 -0700561 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
562 SessionConfigurationUtils::deviceReportsColorSpaces(physicalCameraMetadata) &&
563 !SessionConfigurationUtils::isColorSpaceSupported(colorSpace, format, dataSpace,
564 dynamicRangeProfile, physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700565 std::string msg = fmt::sprintf("Camera %s: Color space %d not supported, failed to "
Austin Borger9e2b27c2022-07-15 11:27:24 -0700566 "create output stream (pixel format %d dynamic range profile %" PRId64 ")",
Austin Borger1c1bee02023-06-01 16:51:35 -0700567 logicalCameraId.c_str(), colorSpace, format, dynamicRangeProfile);
568 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
569 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9e2b27c2022-07-15 11:27:24 -0700570 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800571 if (!SessionConfigurationUtils::isStreamUseCaseSupported(streamUseCase,
572 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700573 std::string msg = fmt::sprintf("Camera %s: stream use case %" PRId64 " not supported,"
574 " failed to create output stream", logicalCameraId.c_str(), streamUseCase);
575 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
576 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800577 }
Shuzhen Wange4208922022-02-01 16:52:48 -0800578 if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700579 timestampBase > OutputConfiguration::TIMESTAMP_BASE_MAX) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700580 std::string msg = fmt::sprintf("Camera %s: invalid timestamp base %d",
581 logicalCameraId.c_str(), timestampBase);
582 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
583 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wange4208922022-02-01 16:52:48 -0800584 }
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800585 if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
586 mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700587 std::string msg = fmt::sprintf("Camera %s: invalid mirroring mode %d",
588 logicalCameraId.c_str(), mirrorMode);
589 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
590 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800591 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000592
593 if (!isStreamInfoValid) {
594 streamInfo.width = width;
595 streamInfo.height = height;
596 streamInfo.format = format;
597 streamInfo.dataSpace = dataSpace;
598 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800599 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Emilian Peev2295df72021-11-12 18:14:10 -0800600 streamInfo.dynamicRangeProfile = dynamicRangeProfile;
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800601 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wange4208922022-02-01 16:52:48 -0800602 streamInfo.timestampBase = timestampBase;
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800603 streamInfo.mirrorMode = mirrorMode;
Austin Borger9e2b27c2022-07-15 11:27:24 -0700604 streamInfo.colorSpace = colorSpace;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000605 return binder::Status::ok();
606 }
607 if (width != streamInfo.width) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700608 std::string msg = fmt::sprintf("Camera %s:Surface width doesn't match: %d vs %d",
609 logicalCameraId.c_str(), width, streamInfo.width);
610 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
611 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000612 }
613 if (height != streamInfo.height) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700614 std::string msg = fmt::sprintf("Camera %s:Surface height doesn't match: %d vs %d",
615 logicalCameraId.c_str(), height, streamInfo.height);
616 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
617 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000618 }
619 if (format != streamInfo.format) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700620 std::string msg = fmt::sprintf("Camera %s:Surface format doesn't match: %d vs %d",
621 logicalCameraId.c_str(), format, streamInfo.format);
622 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
623 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000624 }
625 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
626 if (dataSpace != streamInfo.dataSpace) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700627 std::string msg = fmt::sprintf("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Henri Chataingbcb99452023-11-01 17:40:30 +0000628 logicalCameraId.c_str(), static_cast<int>(dataSpace), static_cast<int>(streamInfo.dataSpace));
Austin Borger1c1bee02023-06-01 16:51:35 -0700629 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
630 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000631 }
632 //At the native side, there isn't a way to check whether 2 surfaces come from the same
633 //surface class type. Use usage flag to approximate the comparison.
634 if (consumerUsage != streamInfo.consumerUsage) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700635 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000636 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Austin Borger1c1bee02023-06-01 16:51:35 -0700637 logicalCameraId.c_str(), consumerUsage, streamInfo.consumerUsage);
638 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
639 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000640 }
641 }
642 return binder::Status::ok();
643}
644
Austin Borgerea931242021-12-13 23:10:41 +0000645void mapStreamInfo(const OutputStreamInfo &streamInfo,
Austin Borger1c1bee02023-06-01 16:51:35 -0700646 camera3::camera_stream_rotation_t rotation, const std::string &physicalId,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000647 int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000648 if (stream == nullptr) {
649 return;
650 }
651
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000652 stream->streamType = aidl::android::hardware::camera::device::StreamType::OUTPUT;
653 stream->width = streamInfo.width;
654 stream->height = streamInfo.height;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000655 stream->format = AidlCamera3Device::mapToAidlPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000656 auto u = streamInfo.consumerUsage;
657 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000658 stream->usage = AidlCamera3Device::mapToAidlConsumerUsage(u);
659 stream->dataSpace = AidlCamera3Device::mapToAidlDataspace(streamInfo.dataSpace);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700660 stream->colorSpace = streamInfo.colorSpace;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000661 stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000662 stream->id = -1; // Invalid stream id
Austin Borger1c1bee02023-06-01 16:51:35 -0700663 stream->physicalCameraId = physicalId;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000664 stream->bufferSize = 0;
665 stream->groupId = groupId;
666 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800667 size_t idx = 0;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000668 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800669 for (auto mode : streamInfo.sensorPixelModesUsed) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000670 stream->sensorPixelModesUsed[idx++] =
671 static_cast<SensorPixelMode>(mode);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800672 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000673 using DynamicRangeProfile =
674 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
675 stream->dynamicRangeProfile = static_cast<DynamicRangeProfile>(streamInfo.dynamicRangeProfile);
676 using StreamUseCases =
677 aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
678 stream->useCase = static_cast<StreamUseCases>(streamInfo.streamUseCase);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000679}
680
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800681binder::Status
Austin Borgerea931242021-12-13 23:10:41 +0000682convertToHALStreamCombination(
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800683 const SessionConfiguration& sessionConfiguration,
Austin Borger1c1bee02023-06-01 16:51:35 -0700684 const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
Emilian Peev15230142023-04-27 20:22:54 +0000685 bool isCompositeJpegRDisabled,
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800686 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000687 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700688 bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
689 bool checkSessionParams, bool *earlyExit) {
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000690 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000691 auto operatingMode = sessionConfiguration.getOperatingMode();
Austin Borger1c1bee02023-06-01 16:51:35 -0700692 binder::Status res = checkOperatingMode(operatingMode, deviceInfo,
693 logicalCameraId);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000694 if (!res.isOk()) {
695 return res;
696 }
697
698 if (earlyExit == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700699 std::string msg("earlyExit nullptr");
700 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
701 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000702 }
703 *earlyExit = false;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000704 auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700705 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000706 /*out*/ &streamConfiguration.operationMode);
707 if (ret != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700708 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000709 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
Austin Borger1c1bee02023-06-01 16:51:35 -0700710 logicalCameraId.c_str(), operatingMode, strerror(-ret), ret);
711 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000712 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -0700713 msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000714 }
715
716 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
717 (sessionConfiguration.getInputHeight() > 0) &&
718 (sessionConfiguration.getInputFormat() > 0);
719 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
720 size_t streamCount = outputConfigs.size();
721 streamCount = isInputValid ? streamCount + 1 : streamCount;
722 streamConfiguration.streams.resize(streamCount);
723 size_t streamIdx = 0;
724 if (isInputValid) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000725 std::vector<SensorPixelMode> defaultSensorPixelModes;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800726 defaultSensorPixelModes.resize(1);
727 defaultSensorPixelModes[0] =
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000728 static_cast<SensorPixelMode>(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
729 aidl::android::hardware::camera::device::Stream stream;
730 stream.id = 0;
731 stream.streamType = aidl::android::hardware::camera::device::StreamType::INPUT;
732 stream.width = static_cast<uint32_t> (sessionConfiguration.getInputWidth());
733 stream.height = static_cast<uint32_t> (sessionConfiguration.getInputHeight());
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000734 stream.format =
735 AidlCamera3Device::AidlCamera3Device::mapToAidlPixelFormat(
736 sessionConfiguration.getInputFormat());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000737 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0);
738 stream.dataSpace =
739 static_cast<aidl::android::hardware::graphics::common::Dataspace>(
740 HAL_DATASPACE_UNKNOWN);
741 stream.rotation = aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
742 stream.bufferSize = 0;
743 stream.groupId = -1;
744 stream.sensorPixelModesUsed = defaultSensorPixelModes;
Emilian Peev065fb0f2022-05-16 15:37:16 -0700745 using DynamicRangeProfile =
746 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
747 stream.dynamicRangeProfile =
748 DynamicRangeProfile::ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000749 streamConfiguration.streams[streamIdx++] = stream;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800750 streamConfiguration.multiResolutionInputImage =
751 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000752 }
753
754 for (const auto &it : outputConfigs) {
755 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
756 it.getGraphicBufferProducers();
757 bool deferredConsumer = it.isDeferred();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800758 bool isConfigurationComplete = it.isComplete();
Austin Borger1c1bee02023-06-01 16:51:35 -0700759 const std::string &physicalCameraId = it.getPhysicalCameraId();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800760
Emilian Peevc81a7592022-02-14 17:38:18 -0800761 int64_t dynamicRangeProfile = it.getDynamicRangeProfile();
Austin Borger9e2b27c2022-07-15 11:27:24 -0700762 int32_t colorSpace = it.getColorSpace();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800763 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700764 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
765 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800766 const CameraMetadata &metadataChosen =
767 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
768
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000769 size_t numBufferProducers = bufferProducers.size();
770 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800771 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000772 OutputStreamInfo streamInfo;
773
Shuzhen Wang0709c282024-02-12 09:09:32 -0800774 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType(),
775 isConfigurationComplete);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000776 if (!res.isOk()) {
777 return res;
778 }
779 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
780 logicalCameraId);
781 if (!res.isOk()) {
782 return res;
783 }
784
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800785 int64_t streamUseCase = it.getStreamUseCase();
Shuzhen Wange4208922022-02-01 16:52:48 -0800786 int timestampBase = it.getTimestampBase();
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800787 int mirrorMode = it.getMirrorMode();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800788 // If the configuration is a deferred consumer, or a not yet completed
789 // configuration with no buffer producers attached.
790 if (deferredConsumer || (!isConfigurationComplete && numBufferProducers == 0)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000791 streamInfo.width = it.getWidth();
792 streamInfo.height = it.getHeight();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000793 auto surfaceType = it.getSurfaceType();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800794 switch (surfaceType) {
795 case OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE:
796 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
797 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
798 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
799 break;
800 case OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW:
801 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE
802 | GraphicBuffer::USAGE_HW_COMPOSER;
803 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
804 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
805 break;
806 case OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER:
807 case OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC:
808 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
809 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
810 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
811 break;
812 case OutputConfiguration::SURFACE_TYPE_IMAGE_READER:
813 streamInfo.consumerUsage = it.getUsage();
814 streamInfo.format = it.getFormat();
815 streamInfo.dataSpace = (android_dataspace)it.getDataspace();
816 break;
817 default:
818 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
819 "Invalid surface type.");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000820 }
Emilian Peev2295df72021-11-12 18:14:10 -0800821 streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800822 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
823 streamInfo.format, streamInfo.width,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000824 streamInfo.height, metadataChosen,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800825 &streamInfo.sensorPixelModesUsed) != OK) {
826 ALOGE("%s: Deferred surface sensor pixel modes not valid",
827 __FUNCTION__);
828 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
829 "Deferred surface sensor pixel modes not valid");
830 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800831 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800832 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000833 &streamConfiguration.streams[streamIdx++]);
834 isStreamInfoValid = true;
835
836 if (numBufferProducers == 0) {
837 continue;
838 }
839 }
840
841 for (auto& bufferProducer : bufferProducers) {
842 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000843 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800844 logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800845 streamUseCase, timestampBase, mirrorMode, colorSpace,
846 /*respectSurfaceSize*/true);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000847
848 if (!res.isOk())
849 return res;
850
851 if (!isStreamInfoValid) {
852 bool isDepthCompositeStream =
853 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
854 bool isHeicCompositeStream =
855 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
Emilian Peev434248e2022-10-06 14:58:54 -0700856 bool isJpegRCompositeStream =
Emilian Peeve579d8b2023-02-28 14:16:08 -0800857 camera3::JpegRCompositeStream::isJpegRCompositeStream(surface) &&
Emilian Peev15230142023-04-27 20:22:54 +0000858 !isCompositeJpegRDisabled;
Emilian Peev434248e2022-10-06 14:58:54 -0700859 if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000860 // We need to take in to account that composite streams can have
861 // additional internal camera streams.
862 std::vector<OutputStreamInfo> compositeStreams;
863 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800864 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000865 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
866 deviceInfo, &compositeStreams);
Emilian Peev434248e2022-10-06 14:58:54 -0700867 } else if (isHeicCompositeStream) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000868 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
869 deviceInfo, &compositeStreams);
Emilian Peev434248e2022-10-06 14:58:54 -0700870 } else {
871 ret = camera3::JpegRCompositeStream::getCompositeStreamInfo(streamInfo,
872 deviceInfo, &compositeStreams);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000873 }
Emilian Peev434248e2022-10-06 14:58:54 -0700874
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000875 if (ret != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700876 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000877 "Camera %s: Failed adding composite streams: %s (%d)",
Austin Borger1c1bee02023-06-01 16:51:35 -0700878 logicalCameraId.c_str(), strerror(-ret), ret);
879 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
880 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000881 }
882
883 if (compositeStreams.size() == 0) {
884 // No internal streams means composite stream not
885 // supported.
886 *earlyExit = true;
887 return binder::Status::ok();
888 } else if (compositeStreams.size() > 1) {
889 streamCount += compositeStreams.size() - 1;
890 streamConfiguration.streams.resize(streamCount);
891 }
892
893 for (const auto& compositeStream : compositeStreams) {
894 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700895 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800896 physicalCameraId, groupId,
897 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000898 }
899 } else {
900 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700901 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800902 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000903 }
904 isStreamInfoValid = true;
905 }
906 }
907 }
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700908
909 if (checkSessionParams) {
910 const CameraMetadata &deviceInfo = getMetadata(logicalCameraId,
911 /*overrideForPerfClass*/false);
912 CameraMetadata filteredParams;
913
914 filterParameters(sessionConfiguration.getSessionParameters(), deviceInfo,
915 vendorTagId, filteredParams);
916
917 camera_metadata_t* metadata = const_cast<camera_metadata_t*>(filteredParams.getAndLock());
918 uint8_t *metadataP = reinterpret_cast<uint8_t*>(metadata);
919 streamConfiguration.sessionParams.metadata.assign(metadataP,
920 metadataP + get_camera_metadata_size(metadata));
921 }
922
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000923 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800924}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000925
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000926binder::Status checkPhysicalCameraId(
Austin Borger1c1bee02023-06-01 16:51:35 -0700927 const std::vector<std::string> &physicalCameraIds, const std::string &physicalCameraId,
928 const std::string &logicalCameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000929 if (physicalCameraId.size() == 0) {
930 return binder::Status::ok();
931 }
932 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
Austin Borger1c1bee02023-06-01 16:51:35 -0700933 physicalCameraId) == physicalCameraIds.end()) {
934 std::string msg = fmt::sprintf("Camera %s: Camera doesn't support physicalCameraId %s.",
935 logicalCameraId.c_str(), physicalCameraId.c_str());
936 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
937 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000938 }
939 return binder::Status::ok();
940}
941
942binder::Status checkSurfaceType(size_t numBufferProducers,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800943 bool deferredConsumer, int surfaceType, bool isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000944 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
945 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
946 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
947 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
Shuzhen Wang0709c282024-02-12 09:09:32 -0800948 } else if ((numBufferProducers == 0) && (!deferredConsumer) && isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000949 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
950 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
951 }
952
Shuzhen Wang0709c282024-02-12 09:09:32 -0800953 if (deferredConsumer) {
954 bool validSurfaceType = (
955 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
956 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
957 if (!validSurfaceType) {
958 std::string msg = fmt::sprintf("Deferred target surface has invalid "
959 "surfaceType = %d.", surfaceType);
960 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
961 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
962 }
963 } else if (!isConfigurationComplete && numBufferProducers == 0) {
964 bool validSurfaceType = (
965 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER) ||
966 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC) ||
967 (surfaceType == OutputConfiguration::SURFACE_TYPE_IMAGE_READER));
968 if (!validSurfaceType) {
969 std::string msg = fmt::sprintf("OutputConfiguration target surface has invalid "
970 "surfaceType = %d.", surfaceType);
971 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
972 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
973 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000974 }
975
976 return binder::Status::ok();
977}
978
979binder::Status checkOperatingMode(int operatingMode,
Austin Borger1c1bee02023-06-01 16:51:35 -0700980 const CameraMetadata &staticInfo, const std::string &cameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000981 if (operatingMode < 0) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700982 std::string msg = fmt::sprintf(
983 "Camera %s: Invalid operating mode %d requested", cameraId.c_str(), operatingMode);
984 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000985 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -0700986 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000987 }
988
989 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
990 if (isConstrainedHighSpeed) {
991 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
992 bool isConstrainedHighSpeedSupported = false;
993 for(size_t i = 0; i < entry.count; ++i) {
994 uint8_t capability = entry.data.u8[i];
995 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
996 isConstrainedHighSpeedSupported = true;
997 break;
998 }
999 }
1000 if (!isConstrainedHighSpeedSupported) {
Austin Borger1c1bee02023-06-01 16:51:35 -07001001 std::string msg = fmt::sprintf(
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001002 "Camera %s: Try to create a constrained high speed configuration on a device"
Austin Borger1c1bee02023-06-01 16:51:35 -07001003 " that doesn't support it.", cameraId.c_str());
1004 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001005 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -07001006 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001007 }
1008 }
1009
1010 return binder::Status::ok();
1011}
1012
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001013static bool inStreamConfigurationMap(int format, int width, int height,
1014 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
1015 auto scs = sm.find(format);
1016 if (scs == sm.end()) {
1017 return false;
1018 }
1019 for (auto &sc : scs->second) {
1020 if (sc.width == width && sc.height == height && sc.isInput == 0) {
1021 return true;
1022 }
1023 }
1024 return false;
1025}
1026
1027static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
1028 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
1029}
1030
Austin Borgerea931242021-12-13 23:10:41 +00001031status_t checkAndOverrideSensorPixelModesUsed(
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001032 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001033 const CameraMetadata &staticInfo,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001034 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001035
1036 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
1037 convertToSet(sensorPixelModesUsed);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001038 if (!supportsUltraHighResolutionCapture(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001039 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1040 sensorPixelModesUsedSet.end()) {
1041 // invalid value for non ultra high res sensors
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001042 ALOGE("%s ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION used on a device which doesn't "
1043 "support ultra high resolution capture", __FUNCTION__);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001044 return BAD_VALUE;
1045 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001046 overriddenSensorPixelModesUsed->clear();
1047 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
1048 return OK;
1049 }
1050
1051 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001052
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001053 bool isInDefaultStreamConfigurationMap =
1054 inStreamConfigurationMap(format, width, height,
1055 streamConfigurationPair.mDefaultStreamConfigurationMap);
1056
1057 bool isInMaximumResolutionStreamConfigurationMap =
1058 inStreamConfigurationMap(format, width, height,
1059 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
1060
1061 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
1062 // size + format of the OutputConfiguration is found exclusively in 1.
1063 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001064 // If no, add 'DEFAULT' and MAXIMUM_RESOLUTION to overriddenSensorPixelModes.
1065 // This maintains backwards compatibility and also tells the framework the stream
1066 // might be used in either sensor pixel mode.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001067 if (sensorPixelModesUsedSet.size() == 0) {
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001068 // Ambiguous case, override to include both cases.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001069 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
1070 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001071 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001072 return OK;
1073 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001074 if (isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001075 overriddenSensorPixelModesUsed->insert(
1076 ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1077 } else {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001078 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001079 }
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001080 return OK;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001081 }
1082
1083 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
1084 // are valid / err out.
1085 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
1086 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001087 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_DEFAULT set by client, but stream f: %d size %d x %d"
1088 " isn't present in default stream configuration map", __FUNCTION__, format, width,
1089 height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001090 return BAD_VALUE;
1091 }
1092
1093 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1094 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001095 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION set by client, but stream f: "
1096 "%d size %d x %d isn't present in default stream configuration map", __FUNCTION__,
1097 format, width, height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001098 return BAD_VALUE;
1099 }
1100 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
1101 return OK;
1102}
1103
Austin Borgerea931242021-12-13 23:10:41 +00001104bool targetPerfClassPrimaryCamera(
Shuzhen Wangd4abdf72021-05-28 11:22:50 -07001105 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
1106 int targetSdkVersion) {
1107 bool isPerfClassPrimaryCamera =
1108 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
1109 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
1110}
1111
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001112binder::Status mapRequestTemplateFromClient(const std::string& cameraId, int templateId,
1113 camera_request_template_t* tempId /*out*/) {
1114 binder::Status ret = binder::Status::ok();
1115
1116 if (tempId == nullptr) {
1117 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1118 "Camera %s: Invalid template argument", cameraId.c_str());
1119 return ret;
1120 }
1121 switch(templateId) {
1122 case ICameraDeviceUser::TEMPLATE_PREVIEW:
1123 *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
1124 break;
1125 case ICameraDeviceUser::TEMPLATE_RECORD:
1126 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
1127 break;
1128 case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
1129 *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
1130 break;
1131 case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
1132 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
1133 break;
1134 case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
1135 *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
1136 break;
1137 case ICameraDeviceUser::TEMPLATE_MANUAL:
1138 *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
1139 break;
1140 default:
1141 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1142 "Camera %s: Template ID %d is invalid or not supported",
1143 cameraId.c_str(), templateId);
1144 return ret;
1145 }
1146
1147 return ret;
1148}
1149
1150status_t mapRequestTemplateToAidl(camera_request_template_t templateId,
1151 RequestTemplate* id /*out*/) {
1152 switch (templateId) {
1153 case CAMERA_TEMPLATE_PREVIEW:
1154 *id = RequestTemplate::PREVIEW;
1155 break;
1156 case CAMERA_TEMPLATE_STILL_CAPTURE:
1157 *id = RequestTemplate::STILL_CAPTURE;
1158 break;
1159 case CAMERA_TEMPLATE_VIDEO_RECORD:
1160 *id = RequestTemplate::VIDEO_RECORD;
1161 break;
1162 case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
1163 *id = RequestTemplate::VIDEO_SNAPSHOT;
1164 break;
1165 case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
1166 *id = RequestTemplate::ZERO_SHUTTER_LAG;
1167 break;
1168 case CAMERA_TEMPLATE_MANUAL:
1169 *id = RequestTemplate::MANUAL;
1170 break;
1171 default:
1172 // Unknown template ID, or this HAL is too old to support it
1173 return BAD_VALUE;
1174 }
1175 return OK;
1176}
1177
1178void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
malikakash9a238f62023-12-14 22:47:55 +00001179 metadata_vendor_id_t vendorTagId, CameraMetadata& dst) {
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001180 const CameraMetadata params(src);
1181 camera_metadata_ro_entry_t availableSessionKeys = deviceInfo.find(
1182 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
1183 CameraMetadata filteredParams(availableSessionKeys.count);
1184 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1185 filteredParams.getAndLock());
1186 set_camera_metadata_vendor_id(meta, vendorTagId);
1187 filteredParams.unlock(meta);
1188 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1189 camera_metadata_ro_entry entry = params.find(
1190 availableSessionKeys.data.i32[i]);
1191 if (entry.count > 0) {
1192 filteredParams.update(entry);
1193 }
1194 }
1195 dst = std::move(filteredParams);
1196}
1197
Austin Borgerea931242021-12-13 23:10:41 +00001198} // namespace SessionConfigurationUtils
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001199} // namespace camera3
1200} // namespace android