blob: ee4df4e11c2b1b81b247536ce7d60dba2f1fb578 [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"
Emilian Peev0a2f9332024-09-20 22:13:54 +000020#include <android/data_space.h>
Colin Crossb8a9dbb2020-08-27 04:12:26 +000021#include "../api2/DepthCompositeStream.h"
22#include "../api2/HeicCompositeStream.h"
Emilian Peev434248e2022-10-06 14:58:54 -070023#include "aidl/android/hardware/graphics/common/Dataspace.h"
24#include "api2/JpegRCompositeStream.h"
Emilian Peeve75a2852024-05-20 22:35:15 +000025#include "binder/Status.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000026#include "common/CameraDeviceBase.h"
Jayant Chowdharya04055f2022-01-03 02:07:49 +000027#include "common/HalConversionsTemplated.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000028#include "../CameraService.h"
Jayant Chowdhary35642f22022-01-08 00:39:39 +000029#include "device3/aidl/AidlCamera3Device.h"
Jayant Chowdhary22441f32021-12-26 18:35:41 -080030#include "device3/hidl/HidlCamera3Device.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000031#include "device3/Camera3OutputStream.h"
Shuzhen Wang33c84cd2024-01-03 17:45:03 +000032#include "device3/ZoomRatioMapper.h"
Emilian Peev2295df72021-11-12 18:14:10 -080033#include "system/graphics-base-v1.1.h"
Austin Borger1c1bee02023-06-01 16:51:35 -070034#include <camera/StringUtils.h>
Emilian Peev434248e2022-10-06 14:58:54 -070035#include <ui/PublicFormat.h>
Colin Crossb8a9dbb2020-08-27 04:12:26 +000036
Colin Crossb8a9dbb2020-08-27 04:12:26 +000037using android::camera3::OutputStreamInfo;
38using android::camera3::OutputStreamInfo;
39using android::hardware::camera2::ICameraDeviceUser;
Shuzhen Wang045be6c2023-10-12 10:01:10 -070040using aidl::android::hardware::camera::device::RequestTemplate;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080041
42namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080043namespace camera3 {
Ravneet Dhanjalf8c01052024-11-05 23:48:37 +000044namespace flags = com::android::internal::camera::flags;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080045
46void StreamConfiguration::getStreamConfigurations(
47 const CameraMetadata &staticInfo, int configuration,
48 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
49 if (scm == nullptr) {
50 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
51 return;
52 }
53 const int STREAM_FORMAT_OFFSET = 0;
54 const int STREAM_WIDTH_OFFSET = 1;
55 const int STREAM_HEIGHT_OFFSET = 2;
56 const int STREAM_IS_INPUT_OFFSET = 3;
57
58 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
59 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
60 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
61 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
62 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
63 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
64 StreamConfiguration sc = {format, width, height, isInput};
65 (*scm)[format].push_back(sc);
66 }
67}
68
69void StreamConfiguration::getStreamConfigurations(
70 const CameraMetadata &staticInfo, bool maxRes,
71 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
72 int32_t scalerKey =
73 SessionConfigurationUtils::getAppropriateModeTag(
74 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
75
76 int32_t depthKey =
77 SessionConfigurationUtils::getAppropriateModeTag(
78 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
79
80 int32_t dynamicDepthKey =
81 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070082 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080083
84 int32_t heicKey =
85 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070086 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080087
88 getStreamConfigurations(staticInfo, scalerKey, scm);
89 getStreamConfigurations(staticInfo, depthKey, scm);
90 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
91 getStreamConfigurations(staticInfo, heicKey, scm);
92}
93
Austin Borgerea931242021-12-13 23:10:41 +000094namespace SessionConfigurationUtils {
95
96int32_t PERF_CLASS_LEVEL =
97 property_get_int32("ro.odm.build.media_performance_class", 0);
98
Shuzhen Wangf18887c2022-05-31 10:24:02 -070099bool IS_PERF_CLASS = (PERF_CLASS_LEVEL >= SDK_VERSION_S);
Austin Borgerea931242021-12-13 23:10:41 +0000100
101camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
102 bool ultraHighResolution) {
103 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
104 const int STREAM_CONFIGURATION_SIZE = 4;
105 const int STREAM_FORMAT_OFFSET = 0;
106 const int STREAM_WIDTH_OFFSET = 1;
107 const int STREAM_HEIGHT_OFFSET = 2;
108 const int STREAM_IS_INPUT_OFFSET = 3;
109
110 int32_t scalerSizesTag = ultraHighResolution ?
111 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
112 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
113 camera_metadata_ro_entry_t availableStreamConfigs =
114 metadata.find(scalerSizesTag);
115 if (availableStreamConfigs.count == 0 ||
116 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
117 return camera3::Size(0, 0);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800118 }
Austin Borgerea931242021-12-13 23:10:41 +0000119
120 // Get max jpeg size (area-wise).
121 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
122 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
123 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
124 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
125 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
126 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
127 && format == HAL_PIXEL_FORMAT_BLOB &&
128 (width * height > maxJpegWidth * maxJpegHeight)) {
129 maxJpegWidth = width;
130 maxJpegHeight = height;
131 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800132 }
Austin Borgerea931242021-12-13 23:10:41 +0000133
134 return camera3::Size(maxJpegWidth, maxJpegHeight);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800135}
136
Austin Borgerea931242021-12-13 23:10:41 +0000137size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
138 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
Jayant Chowdharyb2d84202022-07-11 21:46:53 +0000139 return ((float)(uhrMaxJpegSize.width * uhrMaxJpegSize.height)) /
Austin Borgerea931242021-12-13 23:10:41 +0000140 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
141}
142
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800143StreamConfigurationPair
Austin Borgerea931242021-12-13 23:10:41 +0000144getStreamConfigurationPair(const CameraMetadata &staticInfo) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800145 camera3::StreamConfigurationPair streamConfigurationPair;
146 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
147 &streamConfigurationPair.mDefaultStreamConfigurationMap);
148 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
149 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
150 return streamConfigurationPair;
151}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800152
Austin Borgerea931242021-12-13 23:10:41 +0000153int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000154 int64_t d0 = x0 - x1;
155 int64_t d1 = y0 - y1;
156 return d0 * d0 + d1 * d1;
157}
158
Austin Borgerea931242021-12-13 23:10:41 +0000159bool roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800160 int32_t format, android_dataspace dataSpace,
161 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
162 /*out*/int32_t* outHeight) {
163 const int32_t depthSizesTag =
164 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
165 maxResolution);
166 const int32_t scalerSizesTag =
167 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
168 const int32_t heicSizesTag =
169 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Emilian Peevad25a072023-04-05 12:24:13 -0700170 const int32_t jpegRSizesTag = getAppropriateModeTag(
171 ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS, maxResolution);
Emilian Peev0a2f9332024-09-20 22:13:54 +0000172 const int32_t heicUltraHDRSizesTag = getAppropriateModeTag(
173 ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000174
Emilian Peevad25a072023-04-05 12:24:13 -0700175 bool isJpegRDataSpace = (dataSpace == static_cast<android_dataspace_t>(
176 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R));
Emilian Peev0a2f9332024-09-20 22:13:54 +0000177 bool isHeicUltraHDRDataSpace = (dataSpace == static_cast<android_dataspace_t>(
178 ADATASPACE_HEIF_ULTRAHDR));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000179 camera_metadata_ro_entry streamConfigs =
Emilian Peevad25a072023-04-05 12:24:13 -0700180 (isJpegRDataSpace) ? info.find(jpegRSizesTag) :
Emilian Peev0a2f9332024-09-20 22:13:54 +0000181 (isHeicUltraHDRDataSpace) ? info.find(heicUltraHDRSizesTag) :
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800182 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000183 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800184 info.find(heicSizesTag) :
185 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000186
187 int32_t bestWidth = -1;
188 int32_t bestHeight = -1;
189
190 // Iterate through listed stream configurations and find the one with the smallest euclidean
191 // distance from the given dimensions for the given format.
192 for (size_t i = 0; i < streamConfigs.count; i += 4) {
193 int32_t fmt = streamConfigs.data.i32[i];
194 int32_t w = streamConfigs.data.i32[i + 1];
195 int32_t h = streamConfigs.data.i32[i + 2];
196
197 // Ignore input/output type for now
198 if (fmt == format) {
199 if (w == width && h == height) {
200 bestWidth = width;
201 bestHeight = height;
202 break;
203 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
204 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
205 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
206 height))) {
207 bestWidth = w;
208 bestHeight = h;
209 }
210 }
211 }
212
213 if (bestWidth == -1) {
214 // Return false if no configurations for this format were listed
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -0800215 ALOGE("%s: No configurations for format %d width %d, height %d, maxResolution ? %s",
216 __FUNCTION__, format, width, height, maxResolution ? "true" : "false");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000217 return false;
218 }
219
220 // Set the outputs to the closet width/height
221 if (outWidth != NULL) {
222 *outWidth = bestWidth;
223 }
224 if (outHeight != NULL) {
225 *outHeight = bestHeight;
226 }
227
228 // Return true if at least one configuration for this format was listed
229 return true;
230}
231
Emilian Peev2295df72021-11-12 18:14:10 -0800232//check if format is 10-bit compatible
Emilian Peev434248e2022-10-06 14:58:54 -0700233bool is10bitCompatibleFormat(int32_t format, android_dataspace_t dataSpace) {
Emilian Peev2295df72021-11-12 18:14:10 -0800234 switch(format) {
235 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
236 case HAL_PIXEL_FORMAT_YCBCR_P010:
237 return true;
Emilian Peev434248e2022-10-06 14:58:54 -0700238 case HAL_PIXEL_FORMAT_BLOB:
239 if (dataSpace == static_cast<android_dataspace_t>(
240 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
241 return true;
Emilian Peev0a2f9332024-09-20 22:13:54 +0000242 } else if (dataSpace == static_cast<android_dataspace_t>(ADATASPACE_HEIF_ULTRAHDR)) {
243 return true;
Emilian Peev434248e2022-10-06 14:58:54 -0700244 }
245
246 return false;
Emilian Peev2295df72021-11-12 18:14:10 -0800247 default:
248 return false;
249 }
250}
251
Emilian Peevc81a7592022-02-14 17:38:18 -0800252bool isDynamicRangeProfileSupported(int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
Emilian Peev2295df72021-11-12 18:14:10 -0800253 if (dynamicRangeProfile == ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
254 // Supported by default
255 return true;
256 }
257
258 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
259 bool is10bitDynamicRangeSupported = false;
260 for (size_t i = 0; i < entry.count; ++i) {
261 uint8_t capability = entry.data.u8[i];
262 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
263 is10bitDynamicRangeSupported = true;
264 break;
265 }
266 }
267
268 if (!is10bitDynamicRangeSupported) {
269 return false;
270 }
271
272 switch (dynamicRangeProfile) {
273 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
274 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
275 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
276 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
277 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
278 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
279 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
280 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
281 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
282 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
283 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
284 entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
Emilian Peevc81a7592022-02-14 17:38:18 -0800285 for (size_t i = 0; i < entry.count; i += 3) {
286 if (dynamicRangeProfile == entry.data.i64[i]) {
Emilian Peev2295df72021-11-12 18:14:10 -0800287 return true;
288 }
289 }
290
291 return false;
292 default:
293 return false;
294 }
295
296 return false;
297}
298
299//check if format is 10-bit compatible
Emilian Peevc81a7592022-02-14 17:38:18 -0800300bool is10bitDynamicRangeProfile(int64_t dynamicRangeProfile) {
Emilian Peev2295df72021-11-12 18:14:10 -0800301 switch (dynamicRangeProfile) {
302 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
303 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
304 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
305 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
306 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
307 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
308 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
309 return true;
310 default:
311 return false;
312 }
313}
314
Austin Borger9e2b27c2022-07-15 11:27:24 -0700315bool deviceReportsColorSpaces(const CameraMetadata& staticInfo) {
316 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
317 for (size_t i = 0; i < entry.count; ++i) {
318 uint8_t capability = entry.data.u8[i];
319 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES) {
320 return true;
321 }
322 }
323
324 return false;
325}
326
327bool isColorSpaceSupported(int32_t colorSpace, int32_t format, android_dataspace dataSpace,
328 int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
329 int64_t colorSpace64 = colorSpace;
330 int64_t format64 = format;
331
332 // Translate HAL format + data space to public format
333 if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_V0_JFIF) {
334 format64 = 0x100; // JPEG
335 } else if (format == HAL_PIXEL_FORMAT_BLOB
336 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) {
337 format64 = 0x48454946; // HEIC
338 } else if (format == HAL_PIXEL_FORMAT_BLOB
339 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
340 format64 = 0x69656963; // DEPTH_JPEG
341 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_DEPTH) {
342 return false; // DEPTH_POINT_CLOUD, not applicable
343 } else if (format == HAL_PIXEL_FORMAT_Y16 && dataSpace == HAL_DATASPACE_DEPTH) {
344 return false; // DEPTH16, not applicable
345 } else if (format == HAL_PIXEL_FORMAT_RAW16 && dataSpace == HAL_DATASPACE_DEPTH) {
346 return false; // RAW_DEPTH, not applicable
347 } else if (format == HAL_PIXEL_FORMAT_RAW10 && dataSpace == HAL_DATASPACE_DEPTH) {
348 return false; // RAW_DEPTH10, not applicable
Emilian Peev434248e2022-10-06 14:58:54 -0700349 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace ==
350 static_cast<android_dataspace>(
351 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
352 format64 = static_cast<int64_t>(PublicFormat::JPEG_R);
Emilian Peev0a2f9332024-09-20 22:13:54 +0000353 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace ==
354 static_cast<android_dataspace>(ADATASPACE_HEIF_ULTRAHDR)) {
355 format64 = static_cast<int64_t>(HEIC_ULTRAHDR);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700356 }
357
358 camera_metadata_ro_entry_t entry =
359 staticInfo.find(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP);
360 for (size_t i = 0; i < entry.count; i += 3) {
361 bool isFormatCompatible = (format64 == entry.data.i64[i + 1]);
362 bool isDynamicProfileCompatible =
363 (dynamicRangeProfile & entry.data.i64[i + 2]) != 0;
364
365 if (colorSpace64 == entry.data.i64[i]
366 && isFormatCompatible
367 && isDynamicProfileCompatible) {
368 return true;
369 }
370 }
371
372 ALOGE("Color space %d, image format %" PRId64 ", and dynamic range 0x%" PRIx64
373 " combination not found", colorSpace, format64, dynamicRangeProfile);
374 return false;
375}
376
Austin Borgerea931242021-12-13 23:10:41 +0000377bool isPublicFormat(int32_t format)
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000378{
379 switch(format) {
380 case HAL_PIXEL_FORMAT_RGBA_8888:
381 case HAL_PIXEL_FORMAT_RGBX_8888:
382 case HAL_PIXEL_FORMAT_RGB_888:
383 case HAL_PIXEL_FORMAT_RGB_565:
384 case HAL_PIXEL_FORMAT_BGRA_8888:
385 case HAL_PIXEL_FORMAT_YV12:
386 case HAL_PIXEL_FORMAT_Y8:
387 case HAL_PIXEL_FORMAT_Y16:
388 case HAL_PIXEL_FORMAT_RAW16:
389 case HAL_PIXEL_FORMAT_RAW10:
390 case HAL_PIXEL_FORMAT_RAW12:
391 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
392 case HAL_PIXEL_FORMAT_BLOB:
393 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
394 case HAL_PIXEL_FORMAT_YCbCr_420_888:
395 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
396 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
397 case HAL_PIXEL_FORMAT_YCbCr_422_I:
398 return true;
399 default:
400 return false;
401 }
402}
403
Austin Borger9b263b12023-03-27 17:01:33 -0700404bool dataSpaceFromColorSpace(android_dataspace *dataSpace, int32_t colorSpace) {
405 switch (colorSpace) {
406 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB:
407 *dataSpace = HAL_DATASPACE_V0_SRGB;
408 return true;
409 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3:
410 *dataSpace = HAL_DATASPACE_DISPLAY_P3;
411 return true;
412 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG:
413 *(reinterpret_cast<int32_t*>(dataSpace)) = HAL_DATASPACE_BT2020_HLG;
414 return true;
415 default:
416 ALOGE("%s: Unsupported color space %d", __FUNCTION__, colorSpace);
417 return false;
418 }
419}
420
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800421bool isStreamUseCaseSupported(int64_t streamUseCase,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800422 const CameraMetadata &deviceInfo) {
423 camera_metadata_ro_entry_t availableStreamUseCases =
424 deviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES);
425
426 if (availableStreamUseCases.count == 0 &&
427 streamUseCase == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
428 return true;
429 }
Shuzhen Wangb77131a2022-04-27 15:34:33 -0700430 // Allow vendor stream use case unconditionally.
431 if (streamUseCase >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
432 return true;
433 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800434
435 for (size_t i = 0; i < availableStreamUseCases.count; i++) {
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800436 if (availableStreamUseCases.data.i64[i] == streamUseCase) {
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800437 return true;
438 }
439 }
440 return false;
441}
442
Austin Borgerea931242021-12-13 23:10:41 +0000443binder::Status createSurfaceFromGbp(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000444 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
445 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Austin Borger1c1bee02023-06-01 16:51:35 -0700446 const std::string &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
Emilian Peevc81a7592022-02-14 17:38:18 -0800447 const std::vector<int32_t> &sensorPixelModesUsed, int64_t dynamicRangeProfile,
Austin Borger9e2b27c2022-07-15 11:27:24 -0700448 int64_t streamUseCase, int timestampBase, int mirrorMode,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800449 int32_t colorSpace, bool respectSurfaceSize) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000450 // bufferProducer must be non-null
451 if (gbp == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700452 std::string msg = fmt::sprintf("Camera %s: Surface is NULL", logicalCameraId.c_str());
453 ALOGW("%s: %s", __FUNCTION__, msg.c_str());
454 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000455 }
456 // HACK b/10949105
457 // Query consumer usage bits to set async operation mode for
458 // GLConsumer using controlledByApp parameter.
459 bool useAsync = false;
460 uint64_t consumerUsage = 0;
461 status_t err;
462 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700463 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface consumer usage: %s (%d)",
464 logicalCameraId.c_str(), strerror(-err), err);
465 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
466 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000467 }
468 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
469 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Austin Borger1c1bee02023-06-01 16:51:35 -0700470 "stream", __FUNCTION__, logicalCameraId.c_str(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000471 useAsync = true;
472 }
473
474 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
475 GRALLOC_USAGE_RENDERSCRIPT;
476 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
477 GraphicBuffer::USAGE_HW_TEXTURE |
478 GraphicBuffer::USAGE_HW_COMPOSER;
479 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
480 (consumerUsage & allowedFlags) != 0;
481
482 surface = new Surface(gbp, useAsync);
483 ANativeWindow *anw = surface.get();
484
485 int width, height, format;
486 android_dataspace dataSpace;
487 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700488 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface width: %s (%d)",
489 logicalCameraId.c_str(), strerror(-err), err);
490 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
491 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000492 }
493 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700494 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface height: %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 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700500 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface format: %s (%d)",
501 logicalCameraId.c_str(), strerror(-err), err);
502 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
503 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000504 }
505 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
506 reinterpret_cast<int*>(&dataSpace))) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700507 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface dataspace: %s (%d)",
508 logicalCameraId.c_str(), strerror(-err), err);
509 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
510 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000511 }
512
Austin Borger9b263b12023-03-27 17:01:33 -0700513 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
514 format != HAL_PIXEL_FORMAT_BLOB) {
515 if (!dataSpaceFromColorSpace(&dataSpace, colorSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700516 std::string msg = fmt::sprintf("Camera %s: color space %d not supported, failed to "
517 "convert to data space", logicalCameraId.c_str(), colorSpace);
518 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
519 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9b263b12023-03-27 17:01:33 -0700520 }
521 }
522
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000523 // FIXME: remove this override since the default format should be
524 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
525 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
526 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
527 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
528 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Austin Borger1c1bee02023-06-01 16:51:35 -0700529 __FUNCTION__, logicalCameraId.c_str(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000530 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
531 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800532 std::unordered_set<int32_t> overriddenSensorPixelModes;
533 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000534 physicalCameraMetadata, &overriddenSensorPixelModes) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700535 std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
536 "format %#x are not valid",logicalCameraId.c_str(), format);
537 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
538 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800539 }
540 bool foundInMaxRes = false;
541 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
542 overriddenSensorPixelModes.end()) {
543 // we can use the default stream configuration map
544 foundInMaxRes = true;
545 }
Shuzhen Wang0709c282024-02-12 09:09:32 -0800546 // Round dimensions to the nearest dimensions available for this format.
547 // Only do the rounding if the client doesn't ask to respect the surface
548 // size.
549 if (flexibleConsumer && isPublicFormat(format) && !respectSurfaceSize &&
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000550 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800551 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
552 /*out*/&height)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700553 std::string msg = fmt::sprintf("Camera %s: No supported stream configurations with "
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000554 "format %#x defined, failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700555 logicalCameraId.c_str(), format);
556 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
557 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000558 }
Emilian Peev2295df72021-11-12 18:14:10 -0800559 if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
560 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700561 std::string msg = fmt::sprintf("Camera %s: Dynamic range profile 0x%" PRIx64
562 " not supported,failed to create output stream", logicalCameraId.c_str(),
Emilian Peevc81a7592022-02-14 17:38:18 -0800563 dynamicRangeProfile);
Austin Borger1c1bee02023-06-01 16:51:35 -0700564 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
565 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800566 }
567 if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
Emilian Peev434248e2022-10-06 14:58:54 -0700568 !SessionConfigurationUtils::is10bitCompatibleFormat(format, dataSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700569 std::string msg = fmt::sprintf("Camera %s: No 10-bit supported stream configurations with "
Emilian Peevc81a7592022-02-14 17:38:18 -0800570 "format %#x defined and profile %" PRIx64 ", failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700571 logicalCameraId.c_str(), format, dynamicRangeProfile);
572 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
573 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800574 }
Austin Borger9e2b27c2022-07-15 11:27:24 -0700575 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
576 SessionConfigurationUtils::deviceReportsColorSpaces(physicalCameraMetadata) &&
577 !SessionConfigurationUtils::isColorSpaceSupported(colorSpace, format, dataSpace,
578 dynamicRangeProfile, physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700579 std::string msg = fmt::sprintf("Camera %s: Color space %d not supported, failed to "
Austin Borger9e2b27c2022-07-15 11:27:24 -0700580 "create output stream (pixel format %d dynamic range profile %" PRId64 ")",
Austin Borger1c1bee02023-06-01 16:51:35 -0700581 logicalCameraId.c_str(), colorSpace, format, dynamicRangeProfile);
582 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
583 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9e2b27c2022-07-15 11:27:24 -0700584 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800585 if (!SessionConfigurationUtils::isStreamUseCaseSupported(streamUseCase,
586 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700587 std::string msg = fmt::sprintf("Camera %s: stream use case %" PRId64 " not supported,"
588 " failed to create output stream", logicalCameraId.c_str(), streamUseCase);
589 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
590 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800591 }
Shuzhen Wange4208922022-02-01 16:52:48 -0800592 if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700593 timestampBase > OutputConfiguration::TIMESTAMP_BASE_MAX) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700594 std::string msg = fmt::sprintf("Camera %s: invalid timestamp base %d",
595 logicalCameraId.c_str(), timestampBase);
596 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
597 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wange4208922022-02-01 16:52:48 -0800598 }
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800599 if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
600 mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700601 std::string msg = fmt::sprintf("Camera %s: invalid mirroring mode %d",
602 logicalCameraId.c_str(), mirrorMode);
603 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
604 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800605 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000606
607 if (!isStreamInfoValid) {
608 streamInfo.width = width;
609 streamInfo.height = height;
610 streamInfo.format = format;
611 streamInfo.dataSpace = dataSpace;
612 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800613 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Emilian Peev2295df72021-11-12 18:14:10 -0800614 streamInfo.dynamicRangeProfile = dynamicRangeProfile;
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800615 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wange4208922022-02-01 16:52:48 -0800616 streamInfo.timestampBase = timestampBase;
Austin Borger9e2b27c2022-07-15 11:27:24 -0700617 streamInfo.colorSpace = colorSpace;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000618 return binder::Status::ok();
619 }
620 if (width != streamInfo.width) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700621 std::string msg = fmt::sprintf("Camera %s:Surface width doesn't match: %d vs %d",
622 logicalCameraId.c_str(), width, streamInfo.width);
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 (height != streamInfo.height) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700627 std::string msg = fmt::sprintf("Camera %s:Surface height doesn't match: %d vs %d",
628 logicalCameraId.c_str(), height, streamInfo.height);
629 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 if (format != streamInfo.format) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700633 std::string msg = fmt::sprintf("Camera %s:Surface format doesn't match: %d vs %d",
634 logicalCameraId.c_str(), format, streamInfo.format);
635 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
636 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000637 }
638 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
639 if (dataSpace != streamInfo.dataSpace) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700640 std::string msg = fmt::sprintf("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Henri Chataingbcb99452023-11-01 17:40:30 +0000641 logicalCameraId.c_str(), static_cast<int>(dataSpace), static_cast<int>(streamInfo.dataSpace));
Austin Borger1c1bee02023-06-01 16:51:35 -0700642 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
643 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000644 }
645 //At the native side, there isn't a way to check whether 2 surfaces come from the same
646 //surface class type. Use usage flag to approximate the comparison.
647 if (consumerUsage != streamInfo.consumerUsage) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700648 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000649 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Austin Borger1c1bee02023-06-01 16:51:35 -0700650 logicalCameraId.c_str(), consumerUsage, streamInfo.consumerUsage);
651 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
652 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000653 }
654 }
655 return binder::Status::ok();
656}
657
Austin Borgerea931242021-12-13 23:10:41 +0000658void mapStreamInfo(const OutputStreamInfo &streamInfo,
Austin Borger1c1bee02023-06-01 16:51:35 -0700659 camera3::camera_stream_rotation_t rotation, const std::string &physicalId,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000660 int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000661 if (stream == nullptr) {
662 return;
663 }
664
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000665 stream->streamType = aidl::android::hardware::camera::device::StreamType::OUTPUT;
666 stream->width = streamInfo.width;
667 stream->height = streamInfo.height;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000668 stream->format = AidlCamera3Device::mapToAidlPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000669 auto u = streamInfo.consumerUsage;
670 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000671 stream->usage = AidlCamera3Device::mapToAidlConsumerUsage(u);
672 stream->dataSpace = AidlCamera3Device::mapToAidlDataspace(streamInfo.dataSpace);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700673 stream->colorSpace = streamInfo.colorSpace;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000674 stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000675 stream->id = -1; // Invalid stream id
Austin Borger1c1bee02023-06-01 16:51:35 -0700676 stream->physicalCameraId = physicalId;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000677 stream->bufferSize = 0;
678 stream->groupId = groupId;
679 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800680 size_t idx = 0;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000681 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800682 for (auto mode : streamInfo.sensorPixelModesUsed) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000683 stream->sensorPixelModesUsed[idx++] =
684 static_cast<SensorPixelMode>(mode);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800685 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000686 using DynamicRangeProfile =
687 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
688 stream->dynamicRangeProfile = static_cast<DynamicRangeProfile>(streamInfo.dynamicRangeProfile);
689 using StreamUseCases =
690 aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
691 stream->useCase = static_cast<StreamUseCases>(streamInfo.streamUseCase);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000692}
693
Emilian Peeve75a2852024-05-20 22:35:15 +0000694binder::Status mapStream(const OutputStreamInfo& streamInfo, bool isCompositeJpegRDisabled,
695 const CameraMetadata& deviceInfo, camera_stream_rotation_t rotation,
696 size_t* streamIdx/*out*/, const std::string &physicalId, int32_t groupId,
697 const std::string& logicalCameraId,
698 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration /*out*/,
699 bool *earlyExit /*out*/) {
700 bool isDepthCompositeStream =
701 camera3::DepthCompositeStream::isDepthCompositeStreamInfo(streamInfo);
702 bool isHeicCompositeStream =
703 camera3::HeicCompositeStream::isHeicCompositeStreamInfo(streamInfo);
704 bool isJpegRCompositeStream =
705 camera3::JpegRCompositeStream::isJpegRCompositeStreamInfo(streamInfo) &&
706 !isCompositeJpegRDisabled;
707 if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
708 // We need to take in to account that composite streams can have
709 // additional internal camera streams.
710 std::vector<OutputStreamInfo> compositeStreams;
711 status_t ret;
712 if (isDepthCompositeStream) {
713 // TODO: Take care of composite streams.
714 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
715 deviceInfo, &compositeStreams);
716 } else if (isHeicCompositeStream) {
717 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
718 deviceInfo, &compositeStreams);
719 } else {
720 ret = camera3::JpegRCompositeStream::getCompositeStreamInfo(streamInfo,
721 deviceInfo, &compositeStreams);
722 }
723
724 if (ret != OK) {
725 std::string msg = fmt::sprintf(
726 "Camera %s: Failed adding composite streams: %s (%d)",
727 logicalCameraId.c_str(), strerror(-ret), ret);
728 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
729 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
730 }
731
732 if (compositeStreams.size() == 0) {
733 // No internal streams means composite stream not
734 // supported.
735 *earlyExit = true;
736 return binder::Status::ok();
737 } else if (compositeStreams.size() > 1) {
738 size_t streamCount = streamConfiguration.streams.size() + compositeStreams.size() - 1;
739 streamConfiguration.streams.resize(streamCount);
740 }
741
742 for (const auto& compositeStream : compositeStreams) {
743 mapStreamInfo(compositeStream, rotation,
744 physicalId, groupId,
745 &streamConfiguration.streams[(*streamIdx)++]);
746 }
747 } else {
748 mapStreamInfo(streamInfo, rotation,
749 physicalId, groupId, &streamConfiguration.streams[(*streamIdx)++]);
750 }
751
752 return binder::Status::ok();
753}
754
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800755binder::Status
Austin Borgerea931242021-12-13 23:10:41 +0000756convertToHALStreamCombination(
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800757 const SessionConfiguration& sessionConfiguration,
Austin Borger1c1bee02023-06-01 16:51:35 -0700758 const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
Emilian Peev15230142023-04-27 20:22:54 +0000759 bool isCompositeJpegRDisabled,
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800760 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000761 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700762 bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +0000763 bool checkSessionParams, const std::vector<int32_t>& additionalKeys,
764 bool *earlyExit) {
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000765 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000766 auto operatingMode = sessionConfiguration.getOperatingMode();
Austin Borger1c1bee02023-06-01 16:51:35 -0700767 binder::Status res = checkOperatingMode(operatingMode, deviceInfo,
768 logicalCameraId);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000769 if (!res.isOk()) {
770 return res;
771 }
772
773 if (earlyExit == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700774 std::string msg("earlyExit nullptr");
775 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
776 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000777 }
778 *earlyExit = false;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000779 auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700780 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000781 /*out*/ &streamConfiguration.operationMode);
782 if (ret != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700783 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000784 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
Austin Borger1c1bee02023-06-01 16:51:35 -0700785 logicalCameraId.c_str(), operatingMode, strerror(-ret), ret);
786 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000787 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -0700788 msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000789 }
790
791 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
792 (sessionConfiguration.getInputHeight() > 0) &&
793 (sessionConfiguration.getInputFormat() > 0);
794 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
795 size_t streamCount = outputConfigs.size();
796 streamCount = isInputValid ? streamCount + 1 : streamCount;
797 streamConfiguration.streams.resize(streamCount);
798 size_t streamIdx = 0;
799 if (isInputValid) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000800 std::vector<SensorPixelMode> defaultSensorPixelModes;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800801 defaultSensorPixelModes.resize(1);
802 defaultSensorPixelModes[0] =
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000803 static_cast<SensorPixelMode>(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
804 aidl::android::hardware::camera::device::Stream stream;
805 stream.id = 0;
806 stream.streamType = aidl::android::hardware::camera::device::StreamType::INPUT;
807 stream.width = static_cast<uint32_t> (sessionConfiguration.getInputWidth());
808 stream.height = static_cast<uint32_t> (sessionConfiguration.getInputHeight());
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000809 stream.format =
810 AidlCamera3Device::AidlCamera3Device::mapToAidlPixelFormat(
811 sessionConfiguration.getInputFormat());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000812 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0);
813 stream.dataSpace =
814 static_cast<aidl::android::hardware::graphics::common::Dataspace>(
815 HAL_DATASPACE_UNKNOWN);
816 stream.rotation = aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
817 stream.bufferSize = 0;
818 stream.groupId = -1;
819 stream.sensorPixelModesUsed = defaultSensorPixelModes;
Emilian Peev065fb0f2022-05-16 15:37:16 -0700820 using DynamicRangeProfile =
821 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
822 stream.dynamicRangeProfile =
823 DynamicRangeProfile::ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000824 streamConfiguration.streams[streamIdx++] = stream;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800825 streamConfiguration.multiResolutionInputImage =
826 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000827 }
828
829 for (const auto &it : outputConfigs) {
830 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
831 it.getGraphicBufferProducers();
832 bool deferredConsumer = it.isDeferred();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800833 bool isConfigurationComplete = it.isComplete();
Austin Borger1c1bee02023-06-01 16:51:35 -0700834 const std::string &physicalCameraId = it.getPhysicalCameraId();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800835
Emilian Peevc81a7592022-02-14 17:38:18 -0800836 int64_t dynamicRangeProfile = it.getDynamicRangeProfile();
Austin Borger9e2b27c2022-07-15 11:27:24 -0700837 int32_t colorSpace = it.getColorSpace();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800838 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700839 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
840 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800841 const CameraMetadata &metadataChosen =
842 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
843
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000844 size_t numBufferProducers = bufferProducers.size();
845 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800846 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000847 OutputStreamInfo streamInfo;
848
Shuzhen Wang0709c282024-02-12 09:09:32 -0800849 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType(),
850 isConfigurationComplete);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000851 if (!res.isOk()) {
852 return res;
853 }
854 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
855 logicalCameraId);
856 if (!res.isOk()) {
857 return res;
858 }
859
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800860 int64_t streamUseCase = it.getStreamUseCase();
Shuzhen Wange4208922022-02-01 16:52:48 -0800861 int timestampBase = it.getTimestampBase();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800862 // If the configuration is a deferred consumer, or a not yet completed
863 // configuration with no buffer producers attached.
864 if (deferredConsumer || (!isConfigurationComplete && numBufferProducers == 0)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000865 streamInfo.width = it.getWidth();
866 streamInfo.height = it.getHeight();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000867 auto surfaceType = it.getSurfaceType();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800868 switch (surfaceType) {
869 case OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE:
870 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
871 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
872 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
873 break;
874 case OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW:
875 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE
876 | GraphicBuffer::USAGE_HW_COMPOSER;
877 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
878 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
879 break;
880 case OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER:
881 case OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC:
882 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
883 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
884 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
885 break;
886 case OutputConfiguration::SURFACE_TYPE_IMAGE_READER:
887 streamInfo.consumerUsage = it.getUsage();
888 streamInfo.format = it.getFormat();
889 streamInfo.dataSpace = (android_dataspace)it.getDataspace();
890 break;
891 default:
892 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
893 "Invalid surface type.");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000894 }
Emilian Peev2295df72021-11-12 18:14:10 -0800895 streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800896 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
897 streamInfo.format, streamInfo.width,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000898 streamInfo.height, metadataChosen,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800899 &streamInfo.sensorPixelModesUsed) != OK) {
900 ALOGE("%s: Deferred surface sensor pixel modes not valid",
901 __FUNCTION__);
902 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
903 "Deferred surface sensor pixel modes not valid");
904 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800905 streamInfo.streamUseCase = streamUseCase;
Emilian Peeve75a2852024-05-20 22:35:15 +0000906 auto status = mapStream(streamInfo, isCompositeJpegRDisabled, deviceInfo,
907 camera3::CAMERA_STREAM_ROTATION_0, &streamIdx, physicalCameraId, groupId,
908 logicalCameraId, streamConfiguration, earlyExit);
909 if (*earlyExit || !status.isOk()) {
910 return status;
911 }
912
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000913 isStreamInfoValid = true;
914
915 if (numBufferProducers == 0) {
916 continue;
917 }
918 }
919
920 for (auto& bufferProducer : bufferProducers) {
Shuzhen Wang38df0ca2024-10-09 11:33:44 -0700921 int mirrorMode = it.getMirrorMode(bufferProducer);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000922 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000923 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800924 logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800925 streamUseCase, timestampBase, mirrorMode, colorSpace,
926 /*respectSurfaceSize*/true);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000927
928 if (!res.isOk())
929 return res;
930
931 if (!isStreamInfoValid) {
Emilian Peeve75a2852024-05-20 22:35:15 +0000932 auto status = mapStream(streamInfo, isCompositeJpegRDisabled, deviceInfo,
933 static_cast<camera_stream_rotation_t> (it.getRotation()), &streamIdx,
934 physicalCameraId, groupId, logicalCameraId, streamConfiguration, earlyExit);
935 if (*earlyExit || !status.isOk()) {
936 return status;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000937 }
938 isStreamInfoValid = true;
939 }
940 }
941 }
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700942
943 if (checkSessionParams) {
944 const CameraMetadata &deviceInfo = getMetadata(logicalCameraId,
945 /*overrideForPerfClass*/false);
946 CameraMetadata filteredParams;
947
948 filterParameters(sessionConfiguration.getSessionParameters(), deviceInfo,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +0000949 additionalKeys, vendorTagId, filteredParams);
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700950
951 camera_metadata_t* metadata = const_cast<camera_metadata_t*>(filteredParams.getAndLock());
952 uint8_t *metadataP = reinterpret_cast<uint8_t*>(metadata);
953 streamConfiguration.sessionParams.metadata.assign(metadataP,
954 metadataP + get_camera_metadata_size(metadata));
955 }
956
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000957 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800958}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000959
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000960binder::Status checkPhysicalCameraId(
Austin Borger1c1bee02023-06-01 16:51:35 -0700961 const std::vector<std::string> &physicalCameraIds, const std::string &physicalCameraId,
962 const std::string &logicalCameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000963 if (physicalCameraId.size() == 0) {
964 return binder::Status::ok();
965 }
966 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
Austin Borger1c1bee02023-06-01 16:51:35 -0700967 physicalCameraId) == physicalCameraIds.end()) {
968 std::string msg = fmt::sprintf("Camera %s: Camera doesn't support physicalCameraId %s.",
969 logicalCameraId.c_str(), physicalCameraId.c_str());
970 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
971 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000972 }
973 return binder::Status::ok();
974}
975
976binder::Status checkSurfaceType(size_t numBufferProducers,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800977 bool deferredConsumer, int surfaceType, bool isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000978 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
979 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
980 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
981 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
Shuzhen Wang0709c282024-02-12 09:09:32 -0800982 } else if ((numBufferProducers == 0) && (!deferredConsumer) && isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000983 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
984 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
985 }
986
Shuzhen Wang0709c282024-02-12 09:09:32 -0800987 if (deferredConsumer) {
988 bool validSurfaceType = (
989 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
990 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
991 if (!validSurfaceType) {
992 std::string msg = fmt::sprintf("Deferred target surface has invalid "
993 "surfaceType = %d.", surfaceType);
994 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
995 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
996 }
997 } else if (!isConfigurationComplete && numBufferProducers == 0) {
998 bool validSurfaceType = (
999 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER) ||
1000 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC) ||
1001 (surfaceType == OutputConfiguration::SURFACE_TYPE_IMAGE_READER));
1002 if (!validSurfaceType) {
1003 std::string msg = fmt::sprintf("OutputConfiguration target surface has invalid "
1004 "surfaceType = %d.", surfaceType);
1005 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
1006 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
1007 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001008 }
1009
1010 return binder::Status::ok();
1011}
1012
1013binder::Status checkOperatingMode(int operatingMode,
Austin Borger1c1bee02023-06-01 16:51:35 -07001014 const CameraMetadata &staticInfo, const std::string &cameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001015 if (operatingMode < 0) {
Austin Borger1c1bee02023-06-01 16:51:35 -07001016 std::string msg = fmt::sprintf(
1017 "Camera %s: Invalid operating mode %d requested", cameraId.c_str(), operatingMode);
1018 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001019 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -07001020 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001021 }
1022
1023 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
1024 if (isConstrainedHighSpeed) {
1025 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
1026 bool isConstrainedHighSpeedSupported = false;
1027 for(size_t i = 0; i < entry.count; ++i) {
1028 uint8_t capability = entry.data.u8[i];
1029 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
1030 isConstrainedHighSpeedSupported = true;
1031 break;
1032 }
1033 }
1034 if (!isConstrainedHighSpeedSupported) {
Austin Borger1c1bee02023-06-01 16:51:35 -07001035 std::string msg = fmt::sprintf(
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001036 "Camera %s: Try to create a constrained high speed configuration on a device"
Austin Borger1c1bee02023-06-01 16:51:35 -07001037 " that doesn't support it.", cameraId.c_str());
1038 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001039 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -07001040 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001041 }
1042 }
1043
1044 return binder::Status::ok();
1045}
1046
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001047static bool inStreamConfigurationMap(int format, int width, int height,
1048 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
1049 auto scs = sm.find(format);
1050 if (scs == sm.end()) {
1051 return false;
1052 }
1053 for (auto &sc : scs->second) {
1054 if (sc.width == width && sc.height == height && sc.isInput == 0) {
1055 return true;
1056 }
1057 }
1058 return false;
1059}
1060
1061static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
1062 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
1063}
1064
Austin Borgerea931242021-12-13 23:10:41 +00001065status_t checkAndOverrideSensorPixelModesUsed(
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001066 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001067 const CameraMetadata &staticInfo,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001068 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001069
1070 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
1071 convertToSet(sensorPixelModesUsed);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001072 if (!supportsUltraHighResolutionCapture(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001073 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1074 sensorPixelModesUsedSet.end()) {
1075 // invalid value for non ultra high res sensors
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001076 ALOGE("%s ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION used on a device which doesn't "
1077 "support ultra high resolution capture", __FUNCTION__);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001078 return BAD_VALUE;
1079 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001080 overriddenSensorPixelModesUsed->clear();
1081 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
1082 return OK;
1083 }
1084
1085 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001086
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001087 bool isInDefaultStreamConfigurationMap =
1088 inStreamConfigurationMap(format, width, height,
1089 streamConfigurationPair.mDefaultStreamConfigurationMap);
1090
1091 bool isInMaximumResolutionStreamConfigurationMap =
1092 inStreamConfigurationMap(format, width, height,
1093 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
1094
1095 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
1096 // size + format of the OutputConfiguration is found exclusively in 1.
1097 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001098 // If no, add 'DEFAULT' and MAXIMUM_RESOLUTION to overriddenSensorPixelModes.
1099 // This maintains backwards compatibility and also tells the framework the stream
1100 // might be used in either sensor pixel mode.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001101 if (sensorPixelModesUsedSet.size() == 0) {
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001102 // Ambiguous case, override to include both cases.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001103 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
1104 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001105 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001106 return OK;
1107 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001108 if (isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001109 overriddenSensorPixelModesUsed->insert(
1110 ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1111 } else {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001112 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001113 }
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001114 return OK;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001115 }
1116
1117 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
1118 // are valid / err out.
1119 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
1120 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001121 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_DEFAULT set by client, but stream f: %d size %d x %d"
1122 " isn't present in default stream configuration map", __FUNCTION__, format, width,
1123 height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001124 return BAD_VALUE;
1125 }
1126
1127 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1128 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001129 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION set by client, but stream f: "
1130 "%d size %d x %d isn't present in default stream configuration map", __FUNCTION__,
1131 format, width, height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001132 return BAD_VALUE;
1133 }
1134 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
1135 return OK;
1136}
1137
Austin Borgerea931242021-12-13 23:10:41 +00001138bool targetPerfClassPrimaryCamera(
Shuzhen Wangd4abdf72021-05-28 11:22:50 -07001139 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
1140 int targetSdkVersion) {
1141 bool isPerfClassPrimaryCamera =
1142 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
1143 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
1144}
1145
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001146binder::Status mapRequestTemplateFromClient(const std::string& cameraId, int templateId,
1147 camera_request_template_t* tempId /*out*/) {
1148 binder::Status ret = binder::Status::ok();
1149
1150 if (tempId == nullptr) {
1151 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1152 "Camera %s: Invalid template argument", cameraId.c_str());
1153 return ret;
1154 }
1155 switch(templateId) {
1156 case ICameraDeviceUser::TEMPLATE_PREVIEW:
1157 *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
1158 break;
1159 case ICameraDeviceUser::TEMPLATE_RECORD:
1160 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
1161 break;
1162 case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
1163 *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
1164 break;
1165 case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
1166 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
1167 break;
1168 case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
1169 *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
1170 break;
1171 case ICameraDeviceUser::TEMPLATE_MANUAL:
1172 *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
1173 break;
1174 default:
1175 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1176 "Camera %s: Template ID %d is invalid or not supported",
1177 cameraId.c_str(), templateId);
1178 return ret;
1179 }
1180
1181 return ret;
1182}
1183
1184status_t mapRequestTemplateToAidl(camera_request_template_t templateId,
1185 RequestTemplate* id /*out*/) {
1186 switch (templateId) {
1187 case CAMERA_TEMPLATE_PREVIEW:
1188 *id = RequestTemplate::PREVIEW;
1189 break;
1190 case CAMERA_TEMPLATE_STILL_CAPTURE:
1191 *id = RequestTemplate::STILL_CAPTURE;
1192 break;
1193 case CAMERA_TEMPLATE_VIDEO_RECORD:
1194 *id = RequestTemplate::VIDEO_RECORD;
1195 break;
1196 case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
1197 *id = RequestTemplate::VIDEO_SNAPSHOT;
1198 break;
1199 case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
1200 *id = RequestTemplate::ZERO_SHUTTER_LAG;
1201 break;
1202 case CAMERA_TEMPLATE_MANUAL:
1203 *id = RequestTemplate::MANUAL;
1204 break;
1205 default:
1206 // Unknown template ID, or this HAL is too old to support it
1207 return BAD_VALUE;
1208 }
1209 return OK;
1210}
1211
1212void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001213 const std::vector<int32_t>& additionalTags, metadata_vendor_id_t vendorTagId,
1214 CameraMetadata& dst) {
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001215 const CameraMetadata params(src);
1216 camera_metadata_ro_entry_t availableSessionKeys = deviceInfo.find(
1217 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
1218 CameraMetadata filteredParams(availableSessionKeys.count);
1219 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1220 filteredParams.getAndLock());
1221 set_camera_metadata_vendor_id(meta, vendorTagId);
1222 filteredParams.unlock(meta);
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001223
1224 std::unordered_set<int32_t> filteredTags(availableSessionKeys.data.i32,
1225 availableSessionKeys.data.i32 + availableSessionKeys.count);
1226 filteredTags.insert(additionalTags.begin(), additionalTags.end());
1227 for (int32_t tag : filteredTags) {
1228 camera_metadata_ro_entry entry = params.find(tag);
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001229 if (entry.count > 0) {
1230 filteredParams.update(entry);
1231 }
1232 }
1233 dst = std::move(filteredParams);
1234}
1235
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001236status_t overrideDefaultRequestKeys(CameraMetadata *request) {
1237 // Override the template request with ZoomRatioMapper
1238 status_t res = ZoomRatioMapper::initZoomRatioInTemplate(request);
1239 if (res != OK) {
1240 ALOGE("Failed to update zoom ratio: %s (%d)", strerror(-res), res);
1241 return res;
1242 }
1243
1244 // Fill in JPEG_QUALITY if not available
1245 if (!request->exists(ANDROID_JPEG_QUALITY)) {
1246 static const uint8_t kDefaultJpegQuality = 95;
1247 request->update(ANDROID_JPEG_QUALITY, &kDefaultJpegQuality, 1);
1248 }
1249
1250 // Fill in AUTOFRAMING if not available
1251 if (!request->exists(ANDROID_CONTROL_AUTOFRAMING)) {
1252 static const uint8_t kDefaultAutoframingMode = ANDROID_CONTROL_AUTOFRAMING_OFF;
1253 request->update(ANDROID_CONTROL_AUTOFRAMING, &kDefaultAutoframingMode, 1);
1254 }
1255
Ravneet Dhanjalf8c01052024-11-05 23:48:37 +00001256 if (flags::ae_priority()) {
1257 // Fill in CONTROL_AE_PRIORITY_MODE if not available
1258 if (!request->exists(ANDROID_CONTROL_AE_PRIORITY_MODE)) {
1259 static const uint8_t kDefaultAePriorityMode = ANDROID_CONTROL_AE_PRIORITY_MODE_OFF;
1260 request->update(ANDROID_CONTROL_AE_PRIORITY_MODE, &kDefaultAePriorityMode, 1);
1261 }
1262 }
1263
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001264 return OK;
1265}
1266
Austin Borgerea931242021-12-13 23:10:41 +00001267} // namespace SessionConfigurationUtils
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001268} // namespace camera3
1269} // namespace android