blob: 08f6314c6334a8f3bfc9ec2f0d9a31ef847471e8 [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 {
44
45void StreamConfiguration::getStreamConfigurations(
46 const CameraMetadata &staticInfo, int configuration,
47 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
48 if (scm == nullptr) {
49 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
50 return;
51 }
52 const int STREAM_FORMAT_OFFSET = 0;
53 const int STREAM_WIDTH_OFFSET = 1;
54 const int STREAM_HEIGHT_OFFSET = 2;
55 const int STREAM_IS_INPUT_OFFSET = 3;
56
57 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
58 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
59 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
60 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
61 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
62 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
63 StreamConfiguration sc = {format, width, height, isInput};
64 (*scm)[format].push_back(sc);
65 }
66}
67
68void StreamConfiguration::getStreamConfigurations(
69 const CameraMetadata &staticInfo, bool maxRes,
70 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
71 int32_t scalerKey =
72 SessionConfigurationUtils::getAppropriateModeTag(
73 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
74
75 int32_t depthKey =
76 SessionConfigurationUtils::getAppropriateModeTag(
77 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
78
79 int32_t dynamicDepthKey =
80 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070081 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080082
83 int32_t heicKey =
84 SessionConfigurationUtils::getAppropriateModeTag(
Jayant Chowdhary9492b072023-06-13 18:07:42 -070085 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxRes);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080086
87 getStreamConfigurations(staticInfo, scalerKey, scm);
88 getStreamConfigurations(staticInfo, depthKey, scm);
89 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
90 getStreamConfigurations(staticInfo, heicKey, scm);
91}
92
Austin Borgerea931242021-12-13 23:10:41 +000093namespace SessionConfigurationUtils {
94
95int32_t PERF_CLASS_LEVEL =
96 property_get_int32("ro.odm.build.media_performance_class", 0);
97
Shuzhen Wangf18887c2022-05-31 10:24:02 -070098bool IS_PERF_CLASS = (PERF_CLASS_LEVEL >= SDK_VERSION_S);
Austin Borgerea931242021-12-13 23:10:41 +000099
100camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
101 bool ultraHighResolution) {
102 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
103 const int STREAM_CONFIGURATION_SIZE = 4;
104 const int STREAM_FORMAT_OFFSET = 0;
105 const int STREAM_WIDTH_OFFSET = 1;
106 const int STREAM_HEIGHT_OFFSET = 2;
107 const int STREAM_IS_INPUT_OFFSET = 3;
108
109 int32_t scalerSizesTag = ultraHighResolution ?
110 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
111 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
112 camera_metadata_ro_entry_t availableStreamConfigs =
113 metadata.find(scalerSizesTag);
114 if (availableStreamConfigs.count == 0 ||
115 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
116 return camera3::Size(0, 0);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800117 }
Austin Borgerea931242021-12-13 23:10:41 +0000118
119 // Get max jpeg size (area-wise).
120 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
121 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
122 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
123 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
124 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
125 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
126 && format == HAL_PIXEL_FORMAT_BLOB &&
127 (width * height > maxJpegWidth * maxJpegHeight)) {
128 maxJpegWidth = width;
129 maxJpegHeight = height;
130 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800131 }
Austin Borgerea931242021-12-13 23:10:41 +0000132
133 return camera3::Size(maxJpegWidth, maxJpegHeight);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800134}
135
Austin Borgerea931242021-12-13 23:10:41 +0000136size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
137 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
Jayant Chowdharyb2d84202022-07-11 21:46:53 +0000138 return ((float)(uhrMaxJpegSize.width * uhrMaxJpegSize.height)) /
Austin Borgerea931242021-12-13 23:10:41 +0000139 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
140}
141
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800142StreamConfigurationPair
Austin Borgerea931242021-12-13 23:10:41 +0000143getStreamConfigurationPair(const CameraMetadata &staticInfo) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800144 camera3::StreamConfigurationPair streamConfigurationPair;
145 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
146 &streamConfigurationPair.mDefaultStreamConfigurationMap);
147 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
148 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
149 return streamConfigurationPair;
150}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800151
Austin Borgerea931242021-12-13 23:10:41 +0000152int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000153 int64_t d0 = x0 - x1;
154 int64_t d1 = y0 - y1;
155 return d0 * d0 + d1 * d1;
156}
157
Austin Borgerea931242021-12-13 23:10:41 +0000158bool roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800159 int32_t format, android_dataspace dataSpace,
160 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
161 /*out*/int32_t* outHeight) {
162 const int32_t depthSizesTag =
163 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
164 maxResolution);
165 const int32_t scalerSizesTag =
166 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
167 const int32_t heicSizesTag =
168 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Emilian Peevad25a072023-04-05 12:24:13 -0700169 const int32_t jpegRSizesTag = getAppropriateModeTag(
170 ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS, maxResolution);
Emilian Peev0a2f9332024-09-20 22:13:54 +0000171 const int32_t heicUltraHDRSizesTag = getAppropriateModeTag(
172 ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000173
Emilian Peevad25a072023-04-05 12:24:13 -0700174 bool isJpegRDataSpace = (dataSpace == static_cast<android_dataspace_t>(
175 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R));
Emilian Peev0a2f9332024-09-20 22:13:54 +0000176 bool isHeicUltraHDRDataSpace = (dataSpace == static_cast<android_dataspace_t>(
177 ADATASPACE_HEIF_ULTRAHDR));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000178 camera_metadata_ro_entry streamConfigs =
Emilian Peevad25a072023-04-05 12:24:13 -0700179 (isJpegRDataSpace) ? info.find(jpegRSizesTag) :
Emilian Peev0a2f9332024-09-20 22:13:54 +0000180 (isHeicUltraHDRDataSpace) ? info.find(heicUltraHDRSizesTag) :
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800181 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000182 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800183 info.find(heicSizesTag) :
184 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000185
186 int32_t bestWidth = -1;
187 int32_t bestHeight = -1;
188
189 // Iterate through listed stream configurations and find the one with the smallest euclidean
190 // distance from the given dimensions for the given format.
191 for (size_t i = 0; i < streamConfigs.count; i += 4) {
192 int32_t fmt = streamConfigs.data.i32[i];
193 int32_t w = streamConfigs.data.i32[i + 1];
194 int32_t h = streamConfigs.data.i32[i + 2];
195
196 // Ignore input/output type for now
197 if (fmt == format) {
198 if (w == width && h == height) {
199 bestWidth = width;
200 bestHeight = height;
201 break;
202 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
203 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
204 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
205 height))) {
206 bestWidth = w;
207 bestHeight = h;
208 }
209 }
210 }
211
212 if (bestWidth == -1) {
213 // Return false if no configurations for this format were listed
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -0800214 ALOGE("%s: No configurations for format %d width %d, height %d, maxResolution ? %s",
215 __FUNCTION__, format, width, height, maxResolution ? "true" : "false");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000216 return false;
217 }
218
219 // Set the outputs to the closet width/height
220 if (outWidth != NULL) {
221 *outWidth = bestWidth;
222 }
223 if (outHeight != NULL) {
224 *outHeight = bestHeight;
225 }
226
227 // Return true if at least one configuration for this format was listed
228 return true;
229}
230
Emilian Peev2295df72021-11-12 18:14:10 -0800231//check if format is 10-bit compatible
Emilian Peev434248e2022-10-06 14:58:54 -0700232bool is10bitCompatibleFormat(int32_t format, android_dataspace_t dataSpace) {
Emilian Peev2295df72021-11-12 18:14:10 -0800233 switch(format) {
234 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
235 case HAL_PIXEL_FORMAT_YCBCR_P010:
236 return true;
Emilian Peev434248e2022-10-06 14:58:54 -0700237 case HAL_PIXEL_FORMAT_BLOB:
238 if (dataSpace == static_cast<android_dataspace_t>(
239 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
240 return true;
Emilian Peev0a2f9332024-09-20 22:13:54 +0000241 } else if (dataSpace == static_cast<android_dataspace_t>(ADATASPACE_HEIF_ULTRAHDR)) {
242 return true;
Emilian Peev434248e2022-10-06 14:58:54 -0700243 }
244
245 return false;
Emilian Peev2295df72021-11-12 18:14:10 -0800246 default:
247 return false;
248 }
249}
250
Emilian Peevc81a7592022-02-14 17:38:18 -0800251bool isDynamicRangeProfileSupported(int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
Emilian Peev2295df72021-11-12 18:14:10 -0800252 if (dynamicRangeProfile == ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
253 // Supported by default
254 return true;
255 }
256
257 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
258 bool is10bitDynamicRangeSupported = false;
259 for (size_t i = 0; i < entry.count; ++i) {
260 uint8_t capability = entry.data.u8[i];
261 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
262 is10bitDynamicRangeSupported = true;
263 break;
264 }
265 }
266
267 if (!is10bitDynamicRangeSupported) {
268 return false;
269 }
270
271 switch (dynamicRangeProfile) {
272 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
273 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
274 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
275 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
276 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
277 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
278 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
279 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
280 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
281 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
282 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
283 entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
Emilian Peevc81a7592022-02-14 17:38:18 -0800284 for (size_t i = 0; i < entry.count; i += 3) {
285 if (dynamicRangeProfile == entry.data.i64[i]) {
Emilian Peev2295df72021-11-12 18:14:10 -0800286 return true;
287 }
288 }
289
290 return false;
291 default:
292 return false;
293 }
294
295 return false;
296}
297
298//check if format is 10-bit compatible
Emilian Peevc81a7592022-02-14 17:38:18 -0800299bool is10bitDynamicRangeProfile(int64_t dynamicRangeProfile) {
Emilian Peev2295df72021-11-12 18:14:10 -0800300 switch (dynamicRangeProfile) {
301 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
302 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
303 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
304 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
305 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
306 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
307 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
308 return true;
309 default:
310 return false;
311 }
312}
313
Austin Borger9e2b27c2022-07-15 11:27:24 -0700314bool deviceReportsColorSpaces(const CameraMetadata& staticInfo) {
315 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
316 for (size_t i = 0; i < entry.count; ++i) {
317 uint8_t capability = entry.data.u8[i];
318 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES) {
319 return true;
320 }
321 }
322
323 return false;
324}
325
326bool isColorSpaceSupported(int32_t colorSpace, int32_t format, android_dataspace dataSpace,
327 int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
328 int64_t colorSpace64 = colorSpace;
329 int64_t format64 = format;
330
331 // Translate HAL format + data space to public format
332 if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_V0_JFIF) {
333 format64 = 0x100; // JPEG
334 } else if (format == HAL_PIXEL_FORMAT_BLOB
335 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) {
336 format64 = 0x48454946; // HEIC
337 } else if (format == HAL_PIXEL_FORMAT_BLOB
338 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
339 format64 = 0x69656963; // DEPTH_JPEG
340 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_DEPTH) {
341 return false; // DEPTH_POINT_CLOUD, not applicable
342 } else if (format == HAL_PIXEL_FORMAT_Y16 && dataSpace == HAL_DATASPACE_DEPTH) {
343 return false; // DEPTH16, not applicable
344 } else if (format == HAL_PIXEL_FORMAT_RAW16 && dataSpace == HAL_DATASPACE_DEPTH) {
345 return false; // RAW_DEPTH, not applicable
346 } else if (format == HAL_PIXEL_FORMAT_RAW10 && dataSpace == HAL_DATASPACE_DEPTH) {
347 return false; // RAW_DEPTH10, not applicable
Emilian Peev434248e2022-10-06 14:58:54 -0700348 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace ==
349 static_cast<android_dataspace>(
350 ::aidl::android::hardware::graphics::common::Dataspace::JPEG_R)) {
351 format64 = static_cast<int64_t>(PublicFormat::JPEG_R);
Emilian Peev0a2f9332024-09-20 22:13:54 +0000352 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace ==
353 static_cast<android_dataspace>(ADATASPACE_HEIF_ULTRAHDR)) {
354 format64 = static_cast<int64_t>(HEIC_ULTRAHDR);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700355 }
356
357 camera_metadata_ro_entry_t entry =
358 staticInfo.find(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP);
359 for (size_t i = 0; i < entry.count; i += 3) {
360 bool isFormatCompatible = (format64 == entry.data.i64[i + 1]);
361 bool isDynamicProfileCompatible =
362 (dynamicRangeProfile & entry.data.i64[i + 2]) != 0;
363
364 if (colorSpace64 == entry.data.i64[i]
365 && isFormatCompatible
366 && isDynamicProfileCompatible) {
367 return true;
368 }
369 }
370
371 ALOGE("Color space %d, image format %" PRId64 ", and dynamic range 0x%" PRIx64
372 " combination not found", colorSpace, format64, dynamicRangeProfile);
373 return false;
374}
375
Austin Borgerea931242021-12-13 23:10:41 +0000376bool isPublicFormat(int32_t format)
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000377{
378 switch(format) {
379 case HAL_PIXEL_FORMAT_RGBA_8888:
380 case HAL_PIXEL_FORMAT_RGBX_8888:
381 case HAL_PIXEL_FORMAT_RGB_888:
382 case HAL_PIXEL_FORMAT_RGB_565:
383 case HAL_PIXEL_FORMAT_BGRA_8888:
384 case HAL_PIXEL_FORMAT_YV12:
385 case HAL_PIXEL_FORMAT_Y8:
386 case HAL_PIXEL_FORMAT_Y16:
387 case HAL_PIXEL_FORMAT_RAW16:
388 case HAL_PIXEL_FORMAT_RAW10:
389 case HAL_PIXEL_FORMAT_RAW12:
390 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
391 case HAL_PIXEL_FORMAT_BLOB:
392 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
393 case HAL_PIXEL_FORMAT_YCbCr_420_888:
394 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
395 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
396 case HAL_PIXEL_FORMAT_YCbCr_422_I:
397 return true;
398 default:
399 return false;
400 }
401}
402
Austin Borger9b263b12023-03-27 17:01:33 -0700403bool dataSpaceFromColorSpace(android_dataspace *dataSpace, int32_t colorSpace) {
404 switch (colorSpace) {
405 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB:
406 *dataSpace = HAL_DATASPACE_V0_SRGB;
407 return true;
408 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3:
409 *dataSpace = HAL_DATASPACE_DISPLAY_P3;
410 return true;
411 case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG:
412 *(reinterpret_cast<int32_t*>(dataSpace)) = HAL_DATASPACE_BT2020_HLG;
413 return true;
414 default:
415 ALOGE("%s: Unsupported color space %d", __FUNCTION__, colorSpace);
416 return false;
417 }
418}
419
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800420bool isStreamUseCaseSupported(int64_t streamUseCase,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800421 const CameraMetadata &deviceInfo) {
422 camera_metadata_ro_entry_t availableStreamUseCases =
423 deviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES);
424
425 if (availableStreamUseCases.count == 0 &&
426 streamUseCase == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
427 return true;
428 }
Shuzhen Wangb77131a2022-04-27 15:34:33 -0700429 // Allow vendor stream use case unconditionally.
430 if (streamUseCase >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
431 return true;
432 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800433
434 for (size_t i = 0; i < availableStreamUseCases.count; i++) {
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800435 if (availableStreamUseCases.data.i64[i] == streamUseCase) {
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800436 return true;
437 }
438 }
439 return false;
440}
441
Austin Borgerea931242021-12-13 23:10:41 +0000442binder::Status createSurfaceFromGbp(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000443 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
444 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Austin Borger1c1bee02023-06-01 16:51:35 -0700445 const std::string &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
Emilian Peevc81a7592022-02-14 17:38:18 -0800446 const std::vector<int32_t> &sensorPixelModesUsed, int64_t dynamicRangeProfile,
Austin Borger9e2b27c2022-07-15 11:27:24 -0700447 int64_t streamUseCase, int timestampBase, int mirrorMode,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800448 int32_t colorSpace, bool respectSurfaceSize) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000449 // bufferProducer must be non-null
450 if (gbp == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700451 std::string msg = fmt::sprintf("Camera %s: Surface is NULL", logicalCameraId.c_str());
452 ALOGW("%s: %s", __FUNCTION__, msg.c_str());
453 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000454 }
455 // HACK b/10949105
456 // Query consumer usage bits to set async operation mode for
457 // GLConsumer using controlledByApp parameter.
458 bool useAsync = false;
459 uint64_t consumerUsage = 0;
460 status_t err;
461 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700462 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface consumer usage: %s (%d)",
463 logicalCameraId.c_str(), strerror(-err), err);
464 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
465 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000466 }
467 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
468 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Austin Borger1c1bee02023-06-01 16:51:35 -0700469 "stream", __FUNCTION__, logicalCameraId.c_str(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000470 useAsync = true;
471 }
472
473 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
474 GRALLOC_USAGE_RENDERSCRIPT;
475 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
476 GraphicBuffer::USAGE_HW_TEXTURE |
477 GraphicBuffer::USAGE_HW_COMPOSER;
478 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
479 (consumerUsage & allowedFlags) != 0;
480
481 surface = new Surface(gbp, useAsync);
482 ANativeWindow *anw = surface.get();
483
484 int width, height, format;
485 android_dataspace dataSpace;
486 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700487 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface width: %s (%d)",
488 logicalCameraId.c_str(), strerror(-err), err);
489 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
490 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000491 }
492 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700493 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface height: %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 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700499 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface format: %s (%d)",
500 logicalCameraId.c_str(), strerror(-err), err);
501 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
502 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000503 }
504 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
505 reinterpret_cast<int*>(&dataSpace))) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700506 std::string msg = fmt::sprintf("Camera %s: Failed to query Surface dataspace: %s (%d)",
507 logicalCameraId.c_str(), strerror(-err), err);
508 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
509 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000510 }
511
Austin Borger9b263b12023-03-27 17:01:33 -0700512 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
513 format != HAL_PIXEL_FORMAT_BLOB) {
514 if (!dataSpaceFromColorSpace(&dataSpace, colorSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700515 std::string msg = fmt::sprintf("Camera %s: color space %d not supported, failed to "
516 "convert to data space", logicalCameraId.c_str(), colorSpace);
517 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
518 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9b263b12023-03-27 17:01:33 -0700519 }
520 }
521
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000522 // FIXME: remove this override since the default format should be
523 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
524 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
525 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
526 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
527 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Austin Borger1c1bee02023-06-01 16:51:35 -0700528 __FUNCTION__, logicalCameraId.c_str(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000529 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
530 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800531 std::unordered_set<int32_t> overriddenSensorPixelModes;
532 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000533 physicalCameraMetadata, &overriddenSensorPixelModes) != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700534 std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
535 "format %#x are not valid",logicalCameraId.c_str(), format);
536 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
537 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800538 }
539 bool foundInMaxRes = false;
540 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
541 overriddenSensorPixelModes.end()) {
542 // we can use the default stream configuration map
543 foundInMaxRes = true;
544 }
Shuzhen Wang0709c282024-02-12 09:09:32 -0800545 // Round dimensions to the nearest dimensions available for this format.
546 // Only do the rounding if the client doesn't ask to respect the surface
547 // size.
548 if (flexibleConsumer && isPublicFormat(format) && !respectSurfaceSize &&
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000549 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800550 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
551 /*out*/&height)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700552 std::string msg = fmt::sprintf("Camera %s: No supported stream configurations with "
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000553 "format %#x defined, failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700554 logicalCameraId.c_str(), format);
555 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
556 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000557 }
Emilian Peev2295df72021-11-12 18:14:10 -0800558 if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
559 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700560 std::string msg = fmt::sprintf("Camera %s: Dynamic range profile 0x%" PRIx64
561 " not supported,failed to create output stream", logicalCameraId.c_str(),
Emilian Peevc81a7592022-02-14 17:38:18 -0800562 dynamicRangeProfile);
Austin Borger1c1bee02023-06-01 16:51:35 -0700563 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
564 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800565 }
566 if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
Emilian Peev434248e2022-10-06 14:58:54 -0700567 !SessionConfigurationUtils::is10bitCompatibleFormat(format, dataSpace)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700568 std::string msg = fmt::sprintf("Camera %s: No 10-bit supported stream configurations with "
Emilian Peevc81a7592022-02-14 17:38:18 -0800569 "format %#x defined and profile %" PRIx64 ", failed to create output stream",
Austin Borger1c1bee02023-06-01 16:51:35 -0700570 logicalCameraId.c_str(), format, dynamicRangeProfile);
571 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
572 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Emilian Peev2295df72021-11-12 18:14:10 -0800573 }
Austin Borger9e2b27c2022-07-15 11:27:24 -0700574 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
575 SessionConfigurationUtils::deviceReportsColorSpaces(physicalCameraMetadata) &&
576 !SessionConfigurationUtils::isColorSpaceSupported(colorSpace, format, dataSpace,
577 dynamicRangeProfile, physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700578 std::string msg = fmt::sprintf("Camera %s: Color space %d not supported, failed to "
Austin Borger9e2b27c2022-07-15 11:27:24 -0700579 "create output stream (pixel format %d dynamic range profile %" PRId64 ")",
Austin Borger1c1bee02023-06-01 16:51:35 -0700580 logicalCameraId.c_str(), colorSpace, format, dynamicRangeProfile);
581 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
582 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Austin Borger9e2b27c2022-07-15 11:27:24 -0700583 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800584 if (!SessionConfigurationUtils::isStreamUseCaseSupported(streamUseCase,
585 physicalCameraMetadata)) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700586 std::string msg = fmt::sprintf("Camera %s: stream use case %" PRId64 " not supported,"
587 " failed to create output stream", logicalCameraId.c_str(), streamUseCase);
588 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
589 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800590 }
Shuzhen Wange4208922022-02-01 16:52:48 -0800591 if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700592 timestampBase > OutputConfiguration::TIMESTAMP_BASE_MAX) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700593 std::string msg = fmt::sprintf("Camera %s: invalid timestamp base %d",
594 logicalCameraId.c_str(), timestampBase);
595 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
596 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wange4208922022-02-01 16:52:48 -0800597 }
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800598 if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
599 mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700600 std::string msg = fmt::sprintf("Camera %s: invalid mirroring mode %d",
601 logicalCameraId.c_str(), mirrorMode);
602 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
603 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800604 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000605
606 if (!isStreamInfoValid) {
607 streamInfo.width = width;
608 streamInfo.height = height;
609 streamInfo.format = format;
610 streamInfo.dataSpace = dataSpace;
611 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800612 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Emilian Peev2295df72021-11-12 18:14:10 -0800613 streamInfo.dynamicRangeProfile = dynamicRangeProfile;
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800614 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wange4208922022-02-01 16:52:48 -0800615 streamInfo.timestampBase = timestampBase;
Austin Borger9e2b27c2022-07-15 11:27:24 -0700616 streamInfo.colorSpace = colorSpace;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000617 return binder::Status::ok();
618 }
619 if (width != streamInfo.width) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700620 std::string msg = fmt::sprintf("Camera %s:Surface width doesn't match: %d vs %d",
621 logicalCameraId.c_str(), width, streamInfo.width);
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 (height != streamInfo.height) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700626 std::string msg = fmt::sprintf("Camera %s:Surface height doesn't match: %d vs %d",
627 logicalCameraId.c_str(), height, streamInfo.height);
628 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
629 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000630 }
631 if (format != streamInfo.format) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700632 std::string msg = fmt::sprintf("Camera %s:Surface format doesn't match: %d vs %d",
633 logicalCameraId.c_str(), format, streamInfo.format);
634 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
635 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000636 }
637 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
638 if (dataSpace != streamInfo.dataSpace) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700639 std::string msg = fmt::sprintf("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Henri Chataingbcb99452023-11-01 17:40:30 +0000640 logicalCameraId.c_str(), static_cast<int>(dataSpace), static_cast<int>(streamInfo.dataSpace));
Austin Borger1c1bee02023-06-01 16:51:35 -0700641 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
642 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000643 }
644 //At the native side, there isn't a way to check whether 2 surfaces come from the same
645 //surface class type. Use usage flag to approximate the comparison.
646 if (consumerUsage != streamInfo.consumerUsage) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700647 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000648 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Austin Borger1c1bee02023-06-01 16:51:35 -0700649 logicalCameraId.c_str(), consumerUsage, streamInfo.consumerUsage);
650 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
651 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000652 }
653 }
654 return binder::Status::ok();
655}
656
Austin Borgerea931242021-12-13 23:10:41 +0000657void mapStreamInfo(const OutputStreamInfo &streamInfo,
Austin Borger1c1bee02023-06-01 16:51:35 -0700658 camera3::camera_stream_rotation_t rotation, const std::string &physicalId,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000659 int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000660 if (stream == nullptr) {
661 return;
662 }
663
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000664 stream->streamType = aidl::android::hardware::camera::device::StreamType::OUTPUT;
665 stream->width = streamInfo.width;
666 stream->height = streamInfo.height;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000667 stream->format = AidlCamera3Device::mapToAidlPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000668 auto u = streamInfo.consumerUsage;
669 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000670 stream->usage = AidlCamera3Device::mapToAidlConsumerUsage(u);
671 stream->dataSpace = AidlCamera3Device::mapToAidlDataspace(streamInfo.dataSpace);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700672 stream->colorSpace = streamInfo.colorSpace;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000673 stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000674 stream->id = -1; // Invalid stream id
Austin Borger1c1bee02023-06-01 16:51:35 -0700675 stream->physicalCameraId = physicalId;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000676 stream->bufferSize = 0;
677 stream->groupId = groupId;
678 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800679 size_t idx = 0;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000680 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800681 for (auto mode : streamInfo.sensorPixelModesUsed) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000682 stream->sensorPixelModesUsed[idx++] =
683 static_cast<SensorPixelMode>(mode);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800684 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000685 using DynamicRangeProfile =
686 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
687 stream->dynamicRangeProfile = static_cast<DynamicRangeProfile>(streamInfo.dynamicRangeProfile);
688 using StreamUseCases =
689 aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
690 stream->useCase = static_cast<StreamUseCases>(streamInfo.streamUseCase);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000691}
692
Emilian Peeve75a2852024-05-20 22:35:15 +0000693binder::Status mapStream(const OutputStreamInfo& streamInfo, bool isCompositeJpegRDisabled,
694 const CameraMetadata& deviceInfo, camera_stream_rotation_t rotation,
695 size_t* streamIdx/*out*/, const std::string &physicalId, int32_t groupId,
696 const std::string& logicalCameraId,
697 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration /*out*/,
698 bool *earlyExit /*out*/) {
699 bool isDepthCompositeStream =
700 camera3::DepthCompositeStream::isDepthCompositeStreamInfo(streamInfo);
701 bool isHeicCompositeStream =
702 camera3::HeicCompositeStream::isHeicCompositeStreamInfo(streamInfo);
703 bool isJpegRCompositeStream =
704 camera3::JpegRCompositeStream::isJpegRCompositeStreamInfo(streamInfo) &&
705 !isCompositeJpegRDisabled;
706 if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
707 // We need to take in to account that composite streams can have
708 // additional internal camera streams.
709 std::vector<OutputStreamInfo> compositeStreams;
710 status_t ret;
711 if (isDepthCompositeStream) {
712 // TODO: Take care of composite streams.
713 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
714 deviceInfo, &compositeStreams);
715 } else if (isHeicCompositeStream) {
716 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
717 deviceInfo, &compositeStreams);
718 } else {
719 ret = camera3::JpegRCompositeStream::getCompositeStreamInfo(streamInfo,
720 deviceInfo, &compositeStreams);
721 }
722
723 if (ret != OK) {
724 std::string msg = fmt::sprintf(
725 "Camera %s: Failed adding composite streams: %s (%d)",
726 logicalCameraId.c_str(), strerror(-ret), ret);
727 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
728 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
729 }
730
731 if (compositeStreams.size() == 0) {
732 // No internal streams means composite stream not
733 // supported.
734 *earlyExit = true;
735 return binder::Status::ok();
736 } else if (compositeStreams.size() > 1) {
737 size_t streamCount = streamConfiguration.streams.size() + compositeStreams.size() - 1;
738 streamConfiguration.streams.resize(streamCount);
739 }
740
741 for (const auto& compositeStream : compositeStreams) {
742 mapStreamInfo(compositeStream, rotation,
743 physicalId, groupId,
744 &streamConfiguration.streams[(*streamIdx)++]);
745 }
746 } else {
747 mapStreamInfo(streamInfo, rotation,
748 physicalId, groupId, &streamConfiguration.streams[(*streamIdx)++]);
749 }
750
751 return binder::Status::ok();
752}
753
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800754binder::Status
Austin Borgerea931242021-12-13 23:10:41 +0000755convertToHALStreamCombination(
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800756 const SessionConfiguration& sessionConfiguration,
Austin Borger1c1bee02023-06-01 16:51:35 -0700757 const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
Emilian Peev15230142023-04-27 20:22:54 +0000758 bool isCompositeJpegRDisabled,
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800759 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000760 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700761 bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +0000762 bool checkSessionParams, const std::vector<int32_t>& additionalKeys,
763 bool *earlyExit) {
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000764 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000765 auto operatingMode = sessionConfiguration.getOperatingMode();
Austin Borger1c1bee02023-06-01 16:51:35 -0700766 binder::Status res = checkOperatingMode(operatingMode, deviceInfo,
767 logicalCameraId);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000768 if (!res.isOk()) {
769 return res;
770 }
771
772 if (earlyExit == nullptr) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700773 std::string msg("earlyExit nullptr");
774 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
775 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000776 }
777 *earlyExit = false;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000778 auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700779 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000780 /*out*/ &streamConfiguration.operationMode);
781 if (ret != OK) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700782 std::string msg = fmt::sprintf(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000783 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
Austin Borger1c1bee02023-06-01 16:51:35 -0700784 logicalCameraId.c_str(), operatingMode, strerror(-ret), ret);
785 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000786 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -0700787 msg.c_str());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000788 }
789
790 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
791 (sessionConfiguration.getInputHeight() > 0) &&
792 (sessionConfiguration.getInputFormat() > 0);
793 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
794 size_t streamCount = outputConfigs.size();
795 streamCount = isInputValid ? streamCount + 1 : streamCount;
796 streamConfiguration.streams.resize(streamCount);
797 size_t streamIdx = 0;
798 if (isInputValid) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000799 std::vector<SensorPixelMode> defaultSensorPixelModes;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800800 defaultSensorPixelModes.resize(1);
801 defaultSensorPixelModes[0] =
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000802 static_cast<SensorPixelMode>(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
803 aidl::android::hardware::camera::device::Stream stream;
804 stream.id = 0;
805 stream.streamType = aidl::android::hardware::camera::device::StreamType::INPUT;
806 stream.width = static_cast<uint32_t> (sessionConfiguration.getInputWidth());
807 stream.height = static_cast<uint32_t> (sessionConfiguration.getInputHeight());
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000808 stream.format =
809 AidlCamera3Device::AidlCamera3Device::mapToAidlPixelFormat(
810 sessionConfiguration.getInputFormat());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000811 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0);
812 stream.dataSpace =
813 static_cast<aidl::android::hardware::graphics::common::Dataspace>(
814 HAL_DATASPACE_UNKNOWN);
815 stream.rotation = aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
816 stream.bufferSize = 0;
817 stream.groupId = -1;
818 stream.sensorPixelModesUsed = defaultSensorPixelModes;
Emilian Peev065fb0f2022-05-16 15:37:16 -0700819 using DynamicRangeProfile =
820 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
821 stream.dynamicRangeProfile =
822 DynamicRangeProfile::ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000823 streamConfiguration.streams[streamIdx++] = stream;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800824 streamConfiguration.multiResolutionInputImage =
825 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000826 }
827
828 for (const auto &it : outputConfigs) {
829 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
830 it.getGraphicBufferProducers();
831 bool deferredConsumer = it.isDeferred();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800832 bool isConfigurationComplete = it.isComplete();
Austin Borger1c1bee02023-06-01 16:51:35 -0700833 const std::string &physicalCameraId = it.getPhysicalCameraId();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800834
Emilian Peevc81a7592022-02-14 17:38:18 -0800835 int64_t dynamicRangeProfile = it.getDynamicRangeProfile();
Austin Borger9e2b27c2022-07-15 11:27:24 -0700836 int32_t colorSpace = it.getColorSpace();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800837 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700838 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
839 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800840 const CameraMetadata &metadataChosen =
841 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
842
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000843 size_t numBufferProducers = bufferProducers.size();
844 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800845 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000846 OutputStreamInfo streamInfo;
847
Shuzhen Wang0709c282024-02-12 09:09:32 -0800848 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType(),
849 isConfigurationComplete);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000850 if (!res.isOk()) {
851 return res;
852 }
853 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
854 logicalCameraId);
855 if (!res.isOk()) {
856 return res;
857 }
858
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800859 int64_t streamUseCase = it.getStreamUseCase();
Shuzhen Wange4208922022-02-01 16:52:48 -0800860 int timestampBase = it.getTimestampBase();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800861 // If the configuration is a deferred consumer, or a not yet completed
862 // configuration with no buffer producers attached.
863 if (deferredConsumer || (!isConfigurationComplete && numBufferProducers == 0)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000864 streamInfo.width = it.getWidth();
865 streamInfo.height = it.getHeight();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000866 auto surfaceType = it.getSurfaceType();
Shuzhen Wang0709c282024-02-12 09:09:32 -0800867 switch (surfaceType) {
868 case OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE:
869 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
870 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
871 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
872 break;
873 case OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW:
874 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE
875 | GraphicBuffer::USAGE_HW_COMPOSER;
876 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
877 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
878 break;
879 case OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER:
880 case OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC:
881 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
882 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
883 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
884 break;
885 case OutputConfiguration::SURFACE_TYPE_IMAGE_READER:
886 streamInfo.consumerUsage = it.getUsage();
887 streamInfo.format = it.getFormat();
888 streamInfo.dataSpace = (android_dataspace)it.getDataspace();
889 break;
890 default:
891 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
892 "Invalid surface type.");
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000893 }
Emilian Peev2295df72021-11-12 18:14:10 -0800894 streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800895 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
896 streamInfo.format, streamInfo.width,
Jayant Chowdharya80ad242023-03-17 00:49:47 +0000897 streamInfo.height, metadataChosen,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800898 &streamInfo.sensorPixelModesUsed) != OK) {
899 ALOGE("%s: Deferred surface sensor pixel modes not valid",
900 __FUNCTION__);
901 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
902 "Deferred surface sensor pixel modes not valid");
903 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800904 streamInfo.streamUseCase = streamUseCase;
Emilian Peeve75a2852024-05-20 22:35:15 +0000905 auto status = mapStream(streamInfo, isCompositeJpegRDisabled, deviceInfo,
906 camera3::CAMERA_STREAM_ROTATION_0, &streamIdx, physicalCameraId, groupId,
907 logicalCameraId, streamConfiguration, earlyExit);
908 if (*earlyExit || !status.isOk()) {
909 return status;
910 }
911
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000912 isStreamInfoValid = true;
913
914 if (numBufferProducers == 0) {
915 continue;
916 }
917 }
918
919 for (auto& bufferProducer : bufferProducers) {
Shuzhen Wang38df0ca2024-10-09 11:33:44 -0700920 int mirrorMode = it.getMirrorMode(bufferProducer);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000921 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000922 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800923 logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800924 streamUseCase, timestampBase, mirrorMode, colorSpace,
925 /*respectSurfaceSize*/true);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000926
927 if (!res.isOk())
928 return res;
929
930 if (!isStreamInfoValid) {
Emilian Peeve75a2852024-05-20 22:35:15 +0000931 auto status = mapStream(streamInfo, isCompositeJpegRDisabled, deviceInfo,
932 static_cast<camera_stream_rotation_t> (it.getRotation()), &streamIdx,
933 physicalCameraId, groupId, logicalCameraId, streamConfiguration, earlyExit);
934 if (*earlyExit || !status.isOk()) {
935 return status;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000936 }
937 isStreamInfoValid = true;
938 }
939 }
940 }
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700941
942 if (checkSessionParams) {
943 const CameraMetadata &deviceInfo = getMetadata(logicalCameraId,
944 /*overrideForPerfClass*/false);
945 CameraMetadata filteredParams;
946
947 filterParameters(sessionConfiguration.getSessionParameters(), deviceInfo,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +0000948 additionalKeys, vendorTagId, filteredParams);
Shuzhen Wang045be6c2023-10-12 10:01:10 -0700949
950 camera_metadata_t* metadata = const_cast<camera_metadata_t*>(filteredParams.getAndLock());
951 uint8_t *metadataP = reinterpret_cast<uint8_t*>(metadata);
952 streamConfiguration.sessionParams.metadata.assign(metadataP,
953 metadataP + get_camera_metadata_size(metadata));
954 }
955
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000956 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800957}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000958
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000959binder::Status checkPhysicalCameraId(
Austin Borger1c1bee02023-06-01 16:51:35 -0700960 const std::vector<std::string> &physicalCameraIds, const std::string &physicalCameraId,
961 const std::string &logicalCameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000962 if (physicalCameraId.size() == 0) {
963 return binder::Status::ok();
964 }
965 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
Austin Borger1c1bee02023-06-01 16:51:35 -0700966 physicalCameraId) == physicalCameraIds.end()) {
967 std::string msg = fmt::sprintf("Camera %s: Camera doesn't support physicalCameraId %s.",
968 logicalCameraId.c_str(), physicalCameraId.c_str());
969 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
970 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000971 }
972 return binder::Status::ok();
973}
974
975binder::Status checkSurfaceType(size_t numBufferProducers,
Shuzhen Wang0709c282024-02-12 09:09:32 -0800976 bool deferredConsumer, int surfaceType, bool isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000977 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
978 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
979 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
980 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
Shuzhen Wang0709c282024-02-12 09:09:32 -0800981 } else if ((numBufferProducers == 0) && (!deferredConsumer) && isConfigurationComplete) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000982 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
983 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
984 }
985
Shuzhen Wang0709c282024-02-12 09:09:32 -0800986 if (deferredConsumer) {
987 bool validSurfaceType = (
988 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
989 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
990 if (!validSurfaceType) {
991 std::string msg = fmt::sprintf("Deferred target surface has invalid "
992 "surfaceType = %d.", surfaceType);
993 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
994 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
995 }
996 } else if (!isConfigurationComplete && numBufferProducers == 0) {
997 bool validSurfaceType = (
998 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER) ||
999 (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC) ||
1000 (surfaceType == OutputConfiguration::SURFACE_TYPE_IMAGE_READER));
1001 if (!validSurfaceType) {
1002 std::string msg = fmt::sprintf("OutputConfiguration target surface has invalid "
1003 "surfaceType = %d.", surfaceType);
1004 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
1005 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
1006 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001007 }
1008
1009 return binder::Status::ok();
1010}
1011
1012binder::Status checkOperatingMode(int operatingMode,
Austin Borger1c1bee02023-06-01 16:51:35 -07001013 const CameraMetadata &staticInfo, const std::string &cameraId) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001014 if (operatingMode < 0) {
Austin Borger1c1bee02023-06-01 16:51:35 -07001015 std::string msg = fmt::sprintf(
1016 "Camera %s: Invalid operating mode %d requested", cameraId.c_str(), operatingMode);
1017 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001018 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -07001019 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001020 }
1021
1022 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
1023 if (isConstrainedHighSpeed) {
1024 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
1025 bool isConstrainedHighSpeedSupported = false;
1026 for(size_t i = 0; i < entry.count; ++i) {
1027 uint8_t capability = entry.data.u8[i];
1028 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
1029 isConstrainedHighSpeedSupported = true;
1030 break;
1031 }
1032 }
1033 if (!isConstrainedHighSpeedSupported) {
Austin Borger1c1bee02023-06-01 16:51:35 -07001034 std::string msg = fmt::sprintf(
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001035 "Camera %s: Try to create a constrained high speed configuration on a device"
Austin Borger1c1bee02023-06-01 16:51:35 -07001036 " that doesn't support it.", cameraId.c_str());
1037 ALOGE("%s: %s", __FUNCTION__, msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001038 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Austin Borger1c1bee02023-06-01 16:51:35 -07001039 msg.c_str());
Jayant Chowdharya04055f2022-01-03 02:07:49 +00001040 }
1041 }
1042
1043 return binder::Status::ok();
1044}
1045
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001046static bool inStreamConfigurationMap(int format, int width, int height,
1047 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
1048 auto scs = sm.find(format);
1049 if (scs == sm.end()) {
1050 return false;
1051 }
1052 for (auto &sc : scs->second) {
1053 if (sc.width == width && sc.height == height && sc.isInput == 0) {
1054 return true;
1055 }
1056 }
1057 return false;
1058}
1059
1060static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
1061 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
1062}
1063
Austin Borgerea931242021-12-13 23:10:41 +00001064status_t checkAndOverrideSensorPixelModesUsed(
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001065 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001066 const CameraMetadata &staticInfo,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001067 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001068
1069 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
1070 convertToSet(sensorPixelModesUsed);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001071 if (!supportsUltraHighResolutionCapture(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001072 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1073 sensorPixelModesUsedSet.end()) {
1074 // invalid value for non ultra high res sensors
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001075 ALOGE("%s ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION used on a device which doesn't "
1076 "support ultra high resolution capture", __FUNCTION__);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001077 return BAD_VALUE;
1078 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001079 overriddenSensorPixelModesUsed->clear();
1080 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
1081 return OK;
1082 }
1083
1084 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -07001085
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001086 bool isInDefaultStreamConfigurationMap =
1087 inStreamConfigurationMap(format, width, height,
1088 streamConfigurationPair.mDefaultStreamConfigurationMap);
1089
1090 bool isInMaximumResolutionStreamConfigurationMap =
1091 inStreamConfigurationMap(format, width, height,
1092 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
1093
1094 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
1095 // size + format of the OutputConfiguration is found exclusively in 1.
1096 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001097 // If no, add 'DEFAULT' and MAXIMUM_RESOLUTION to overriddenSensorPixelModes.
1098 // This maintains backwards compatibility and also tells the framework the stream
1099 // might be used in either sensor pixel mode.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001100 if (sensorPixelModesUsedSet.size() == 0) {
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001101 // Ambiguous case, override to include both cases.
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001102 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
1103 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdharydbd1efb2023-02-07 16:14:48 -08001104 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001105 return OK;
1106 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001107 if (isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001108 overriddenSensorPixelModesUsed->insert(
1109 ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
1110 } else {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001111 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001112 }
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001113 return OK;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001114 }
1115
1116 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
1117 // are valid / err out.
1118 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
1119 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001120 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_DEFAULT set by client, but stream f: %d size %d x %d"
1121 " isn't present in default stream configuration map", __FUNCTION__, format, width,
1122 height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001123 return BAD_VALUE;
1124 }
1125
1126 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1127 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
Jayant Chowdharya80ad242023-03-17 00:49:47 +00001128 ALOGE("%s: ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION set by client, but stream f: "
1129 "%d size %d x %d isn't present in default stream configuration map", __FUNCTION__,
1130 format, width, height);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001131 return BAD_VALUE;
1132 }
1133 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
1134 return OK;
1135}
1136
Austin Borgerea931242021-12-13 23:10:41 +00001137bool targetPerfClassPrimaryCamera(
Shuzhen Wangd4abdf72021-05-28 11:22:50 -07001138 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
1139 int targetSdkVersion) {
1140 bool isPerfClassPrimaryCamera =
1141 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
1142 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
1143}
1144
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001145binder::Status mapRequestTemplateFromClient(const std::string& cameraId, int templateId,
1146 camera_request_template_t* tempId /*out*/) {
1147 binder::Status ret = binder::Status::ok();
1148
1149 if (tempId == nullptr) {
1150 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1151 "Camera %s: Invalid template argument", cameraId.c_str());
1152 return ret;
1153 }
1154 switch(templateId) {
1155 case ICameraDeviceUser::TEMPLATE_PREVIEW:
1156 *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
1157 break;
1158 case ICameraDeviceUser::TEMPLATE_RECORD:
1159 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
1160 break;
1161 case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
1162 *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
1163 break;
1164 case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
1165 *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
1166 break;
1167 case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
1168 *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
1169 break;
1170 case ICameraDeviceUser::TEMPLATE_MANUAL:
1171 *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
1172 break;
1173 default:
1174 ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
1175 "Camera %s: Template ID %d is invalid or not supported",
1176 cameraId.c_str(), templateId);
1177 return ret;
1178 }
1179
1180 return ret;
1181}
1182
1183status_t mapRequestTemplateToAidl(camera_request_template_t templateId,
1184 RequestTemplate* id /*out*/) {
1185 switch (templateId) {
1186 case CAMERA_TEMPLATE_PREVIEW:
1187 *id = RequestTemplate::PREVIEW;
1188 break;
1189 case CAMERA_TEMPLATE_STILL_CAPTURE:
1190 *id = RequestTemplate::STILL_CAPTURE;
1191 break;
1192 case CAMERA_TEMPLATE_VIDEO_RECORD:
1193 *id = RequestTemplate::VIDEO_RECORD;
1194 break;
1195 case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
1196 *id = RequestTemplate::VIDEO_SNAPSHOT;
1197 break;
1198 case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
1199 *id = RequestTemplate::ZERO_SHUTTER_LAG;
1200 break;
1201 case CAMERA_TEMPLATE_MANUAL:
1202 *id = RequestTemplate::MANUAL;
1203 break;
1204 default:
1205 // Unknown template ID, or this HAL is too old to support it
1206 return BAD_VALUE;
1207 }
1208 return OK;
1209}
1210
1211void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001212 const std::vector<int32_t>& additionalTags, metadata_vendor_id_t vendorTagId,
1213 CameraMetadata& dst) {
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001214 const CameraMetadata params(src);
1215 camera_metadata_ro_entry_t availableSessionKeys = deviceInfo.find(
1216 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
1217 CameraMetadata filteredParams(availableSessionKeys.count);
1218 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1219 filteredParams.getAndLock());
1220 set_camera_metadata_vendor_id(meta, vendorTagId);
1221 filteredParams.unlock(meta);
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001222
1223 std::unordered_set<int32_t> filteredTags(availableSessionKeys.data.i32,
1224 availableSessionKeys.data.i32 + availableSessionKeys.count);
1225 filteredTags.insert(additionalTags.begin(), additionalTags.end());
1226 for (int32_t tag : filteredTags) {
1227 camera_metadata_ro_entry entry = params.find(tag);
Shuzhen Wang045be6c2023-10-12 10:01:10 -07001228 if (entry.count > 0) {
1229 filteredParams.update(entry);
1230 }
1231 }
1232 dst = std::move(filteredParams);
1233}
1234
Shuzhen Wang33c84cd2024-01-03 17:45:03 +00001235status_t overrideDefaultRequestKeys(CameraMetadata *request) {
1236 // Override the template request with ZoomRatioMapper
1237 status_t res = ZoomRatioMapper::initZoomRatioInTemplate(request);
1238 if (res != OK) {
1239 ALOGE("Failed to update zoom ratio: %s (%d)", strerror(-res), res);
1240 return res;
1241 }
1242
1243 // Fill in JPEG_QUALITY if not available
1244 if (!request->exists(ANDROID_JPEG_QUALITY)) {
1245 static const uint8_t kDefaultJpegQuality = 95;
1246 request->update(ANDROID_JPEG_QUALITY, &kDefaultJpegQuality, 1);
1247 }
1248
1249 // Fill in AUTOFRAMING if not available
1250 if (!request->exists(ANDROID_CONTROL_AUTOFRAMING)) {
1251 static const uint8_t kDefaultAutoframingMode = ANDROID_CONTROL_AUTOFRAMING_OFF;
1252 request->update(ANDROID_CONTROL_AUTOFRAMING, &kDefaultAutoframingMode, 1);
1253 }
1254
1255 return OK;
1256}
1257
Austin Borgerea931242021-12-13 23:10:41 +00001258} // namespace SessionConfigurationUtils
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001259} // namespace camera3
1260} // namespace android