blob: f9afd410a68f2d412aebe888e073488b8e5bcd49 [file] [log] [blame]
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Austin Borgerea931242021-12-13 23:10:41 +000016
Shuzhen Wangd4abdf72021-05-28 11:22:50 -070017#include <cutils/properties.h>
18
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080019#include "SessionConfigurationUtils.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000020#include "../api2/DepthCompositeStream.h"
21#include "../api2/HeicCompositeStream.h"
22#include "common/CameraDeviceBase.h"
Jayant Chowdharya04055f2022-01-03 02:07:49 +000023#include "common/HalConversionsTemplated.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000024#include "../CameraService.h"
Jayant Chowdhary35642f22022-01-08 00:39:39 +000025#include "device3/aidl/AidlCamera3Device.h"
Jayant Chowdhary22441f32021-12-26 18:35:41 -080026#include "device3/hidl/HidlCamera3Device.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000027#include "device3/Camera3OutputStream.h"
Emilian Peev2295df72021-11-12 18:14:10 -080028#include "system/graphics-base-v1.1.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000029
Colin Crossb8a9dbb2020-08-27 04:12:26 +000030using android::camera3::OutputStreamInfo;
31using android::camera3::OutputStreamInfo;
32using android::hardware::camera2::ICameraDeviceUser;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080033
34namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080035namespace camera3 {
36
37void StreamConfiguration::getStreamConfigurations(
38 const CameraMetadata &staticInfo, int configuration,
39 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
40 if (scm == nullptr) {
41 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
42 return;
43 }
44 const int STREAM_FORMAT_OFFSET = 0;
45 const int STREAM_WIDTH_OFFSET = 1;
46 const int STREAM_HEIGHT_OFFSET = 2;
47 const int STREAM_IS_INPUT_OFFSET = 3;
48
49 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
50 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
51 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
52 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
53 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
54 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
55 StreamConfiguration sc = {format, width, height, isInput};
56 (*scm)[format].push_back(sc);
57 }
58}
59
60void StreamConfiguration::getStreamConfigurations(
61 const CameraMetadata &staticInfo, bool maxRes,
62 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
63 int32_t scalerKey =
64 SessionConfigurationUtils::getAppropriateModeTag(
65 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
66
67 int32_t depthKey =
68 SessionConfigurationUtils::getAppropriateModeTag(
69 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
70
71 int32_t dynamicDepthKey =
72 SessionConfigurationUtils::getAppropriateModeTag(
73 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
74
75 int32_t heicKey =
76 SessionConfigurationUtils::getAppropriateModeTag(
77 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
78
79 getStreamConfigurations(staticInfo, scalerKey, scm);
80 getStreamConfigurations(staticInfo, depthKey, scm);
81 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
82 getStreamConfigurations(staticInfo, heicKey, scm);
83}
84
Austin Borgerea931242021-12-13 23:10:41 +000085namespace SessionConfigurationUtils {
86
87int32_t PERF_CLASS_LEVEL =
88 property_get_int32("ro.odm.build.media_performance_class", 0);
89
Shuzhen Wangf18887c2022-05-31 10:24:02 -070090bool IS_PERF_CLASS = (PERF_CLASS_LEVEL >= SDK_VERSION_S);
Austin Borgerea931242021-12-13 23:10:41 +000091
92camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
93 bool ultraHighResolution) {
94 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
95 const int STREAM_CONFIGURATION_SIZE = 4;
96 const int STREAM_FORMAT_OFFSET = 0;
97 const int STREAM_WIDTH_OFFSET = 1;
98 const int STREAM_HEIGHT_OFFSET = 2;
99 const int STREAM_IS_INPUT_OFFSET = 3;
100
101 int32_t scalerSizesTag = ultraHighResolution ?
102 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
103 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
104 camera_metadata_ro_entry_t availableStreamConfigs =
105 metadata.find(scalerSizesTag);
106 if (availableStreamConfigs.count == 0 ||
107 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
108 return camera3::Size(0, 0);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800109 }
Austin Borgerea931242021-12-13 23:10:41 +0000110
111 // Get max jpeg size (area-wise).
112 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
113 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
114 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
115 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
116 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
117 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
118 && format == HAL_PIXEL_FORMAT_BLOB &&
119 (width * height > maxJpegWidth * maxJpegHeight)) {
120 maxJpegWidth = width;
121 maxJpegHeight = height;
122 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800123 }
Austin Borgerea931242021-12-13 23:10:41 +0000124
125 return camera3::Size(maxJpegWidth, maxJpegHeight);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800126}
127
Austin Borgerea931242021-12-13 23:10:41 +0000128size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
129 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
Jayant Chowdharyb2d84202022-07-11 21:46:53 +0000130 return ((float)(uhrMaxJpegSize.width * uhrMaxJpegSize.height)) /
Austin Borgerea931242021-12-13 23:10:41 +0000131 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
132}
133
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800134StreamConfigurationPair
Austin Borgerea931242021-12-13 23:10:41 +0000135getStreamConfigurationPair(const CameraMetadata &staticInfo) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800136 camera3::StreamConfigurationPair streamConfigurationPair;
137 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
138 &streamConfigurationPair.mDefaultStreamConfigurationMap);
139 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
140 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
141 return streamConfigurationPair;
142}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800143
Austin Borgerea931242021-12-13 23:10:41 +0000144int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000145 int64_t d0 = x0 - x1;
146 int64_t d1 = y0 - y1;
147 return d0 * d0 + d1 * d1;
148}
149
Austin Borgerea931242021-12-13 23:10:41 +0000150bool roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800151 int32_t format, android_dataspace dataSpace,
152 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
153 /*out*/int32_t* outHeight) {
154 const int32_t depthSizesTag =
155 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
156 maxResolution);
157 const int32_t scalerSizesTag =
158 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
159 const int32_t heicSizesTag =
160 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000161
162 camera_metadata_ro_entry streamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800163 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000164 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800165 info.find(heicSizesTag) :
166 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000167
168 int32_t bestWidth = -1;
169 int32_t bestHeight = -1;
170
171 // Iterate through listed stream configurations and find the one with the smallest euclidean
172 // distance from the given dimensions for the given format.
173 for (size_t i = 0; i < streamConfigs.count; i += 4) {
174 int32_t fmt = streamConfigs.data.i32[i];
175 int32_t w = streamConfigs.data.i32[i + 1];
176 int32_t h = streamConfigs.data.i32[i + 2];
177
178 // Ignore input/output type for now
179 if (fmt == format) {
180 if (w == width && h == height) {
181 bestWidth = width;
182 bestHeight = height;
183 break;
184 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
185 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
186 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
187 height))) {
188 bestWidth = w;
189 bestHeight = h;
190 }
191 }
192 }
193
194 if (bestWidth == -1) {
195 // Return false if no configurations for this format were listed
196 return false;
197 }
198
199 // Set the outputs to the closet width/height
200 if (outWidth != NULL) {
201 *outWidth = bestWidth;
202 }
203 if (outHeight != NULL) {
204 *outHeight = bestHeight;
205 }
206
207 // Return true if at least one configuration for this format was listed
208 return true;
209}
210
Emilian Peev2295df72021-11-12 18:14:10 -0800211//check if format is 10-bit compatible
212bool is10bitCompatibleFormat(int32_t format) {
213 switch(format) {
214 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
215 case HAL_PIXEL_FORMAT_YCBCR_P010:
216 return true;
217 default:
218 return false;
219 }
220}
221
Emilian Peevc81a7592022-02-14 17:38:18 -0800222bool isDynamicRangeProfileSupported(int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
Emilian Peev2295df72021-11-12 18:14:10 -0800223 if (dynamicRangeProfile == ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
224 // Supported by default
225 return true;
226 }
227
228 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
229 bool is10bitDynamicRangeSupported = false;
230 for (size_t i = 0; i < entry.count; ++i) {
231 uint8_t capability = entry.data.u8[i];
232 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
233 is10bitDynamicRangeSupported = true;
234 break;
235 }
236 }
237
238 if (!is10bitDynamicRangeSupported) {
239 return false;
240 }
241
242 switch (dynamicRangeProfile) {
243 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
244 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
245 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
246 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
247 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
248 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
249 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
250 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
251 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
252 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
253 case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
254 entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
Emilian Peevc81a7592022-02-14 17:38:18 -0800255 for (size_t i = 0; i < entry.count; i += 3) {
256 if (dynamicRangeProfile == entry.data.i64[i]) {
Emilian Peev2295df72021-11-12 18:14:10 -0800257 return true;
258 }
259 }
260
261 return false;
262 default:
263 return false;
264 }
265
266 return false;
267}
268
269//check if format is 10-bit compatible
Emilian Peevc81a7592022-02-14 17:38:18 -0800270bool is10bitDynamicRangeProfile(int64_t dynamicRangeProfile) {
Emilian Peev2295df72021-11-12 18:14:10 -0800271 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 return true;
280 default:
281 return false;
282 }
283}
284
Austin Borger9e2b27c2022-07-15 11:27:24 -0700285bool deviceReportsColorSpaces(const CameraMetadata& staticInfo) {
286 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
287 for (size_t i = 0; i < entry.count; ++i) {
288 uint8_t capability = entry.data.u8[i];
289 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES) {
290 return true;
291 }
292 }
293
294 return false;
295}
296
297bool isColorSpaceSupported(int32_t colorSpace, int32_t format, android_dataspace dataSpace,
298 int64_t dynamicRangeProfile, const CameraMetadata& staticInfo) {
299 int64_t colorSpace64 = colorSpace;
300 int64_t format64 = format;
301
302 // Translate HAL format + data space to public format
303 if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_V0_JFIF) {
304 format64 = 0x100; // JPEG
305 } else if (format == HAL_PIXEL_FORMAT_BLOB
306 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) {
307 format64 = 0x48454946; // HEIC
308 } else if (format == HAL_PIXEL_FORMAT_BLOB
309 && dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
310 format64 = 0x69656963; // DEPTH_JPEG
311 } else if (format == HAL_PIXEL_FORMAT_BLOB && dataSpace == HAL_DATASPACE_DEPTH) {
312 return false; // DEPTH_POINT_CLOUD, not applicable
313 } else if (format == HAL_PIXEL_FORMAT_Y16 && dataSpace == HAL_DATASPACE_DEPTH) {
314 return false; // DEPTH16, not applicable
315 } else if (format == HAL_PIXEL_FORMAT_RAW16 && dataSpace == HAL_DATASPACE_DEPTH) {
316 return false; // RAW_DEPTH, not applicable
317 } else if (format == HAL_PIXEL_FORMAT_RAW10 && dataSpace == HAL_DATASPACE_DEPTH) {
318 return false; // RAW_DEPTH10, not applicable
319 }
320
321 camera_metadata_ro_entry_t entry =
322 staticInfo.find(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP);
323 for (size_t i = 0; i < entry.count; i += 3) {
324 bool isFormatCompatible = (format64 == entry.data.i64[i + 1]);
325 bool isDynamicProfileCompatible =
326 (dynamicRangeProfile & entry.data.i64[i + 2]) != 0;
327
328 if (colorSpace64 == entry.data.i64[i]
329 && isFormatCompatible
330 && isDynamicProfileCompatible) {
331 return true;
332 }
333 }
334
335 ALOGE("Color space %d, image format %" PRId64 ", and dynamic range 0x%" PRIx64
336 " combination not found", colorSpace, format64, dynamicRangeProfile);
337 return false;
338}
339
Austin Borgerea931242021-12-13 23:10:41 +0000340bool isPublicFormat(int32_t format)
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000341{
342 switch(format) {
343 case HAL_PIXEL_FORMAT_RGBA_8888:
344 case HAL_PIXEL_FORMAT_RGBX_8888:
345 case HAL_PIXEL_FORMAT_RGB_888:
346 case HAL_PIXEL_FORMAT_RGB_565:
347 case HAL_PIXEL_FORMAT_BGRA_8888:
348 case HAL_PIXEL_FORMAT_YV12:
349 case HAL_PIXEL_FORMAT_Y8:
350 case HAL_PIXEL_FORMAT_Y16:
351 case HAL_PIXEL_FORMAT_RAW16:
352 case HAL_PIXEL_FORMAT_RAW10:
353 case HAL_PIXEL_FORMAT_RAW12:
354 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
355 case HAL_PIXEL_FORMAT_BLOB:
356 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
357 case HAL_PIXEL_FORMAT_YCbCr_420_888:
358 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
359 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
360 case HAL_PIXEL_FORMAT_YCbCr_422_I:
361 return true;
362 default:
363 return false;
364 }
365}
366
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800367bool isStreamUseCaseSupported(int64_t streamUseCase,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800368 const CameraMetadata &deviceInfo) {
369 camera_metadata_ro_entry_t availableStreamUseCases =
370 deviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES);
371
372 if (availableStreamUseCases.count == 0 &&
373 streamUseCase == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
374 return true;
375 }
Shuzhen Wangb77131a2022-04-27 15:34:33 -0700376 // Allow vendor stream use case unconditionally.
377 if (streamUseCase >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
378 return true;
379 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800380
381 for (size_t i = 0; i < availableStreamUseCases.count; i++) {
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800382 if (availableStreamUseCases.data.i64[i] == streamUseCase) {
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800383 return true;
384 }
385 }
386 return false;
387}
388
Austin Borgerea931242021-12-13 23:10:41 +0000389binder::Status createSurfaceFromGbp(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000390 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
391 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800392 const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
Emilian Peevc81a7592022-02-14 17:38:18 -0800393 const std::vector<int32_t> &sensorPixelModesUsed, int64_t dynamicRangeProfile,
Austin Borger9e2b27c2022-07-15 11:27:24 -0700394 int64_t streamUseCase, int timestampBase, int mirrorMode,
395 int32_t colorSpace) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000396 // bufferProducer must be non-null
397 if (gbp == nullptr) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800398 String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000399 ALOGW("%s: %s", __FUNCTION__, msg.string());
400 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
401 }
402 // HACK b/10949105
403 // Query consumer usage bits to set async operation mode for
404 // GLConsumer using controlledByApp parameter.
405 bool useAsync = false;
406 uint64_t consumerUsage = 0;
407 status_t err;
408 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
409 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800410 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000411 ALOGE("%s: %s", __FUNCTION__, msg.string());
412 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
413 }
414 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
415 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800416 "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000417 useAsync = true;
418 }
419
420 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
421 GRALLOC_USAGE_RENDERSCRIPT;
422 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
423 GraphicBuffer::USAGE_HW_TEXTURE |
424 GraphicBuffer::USAGE_HW_COMPOSER;
425 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
426 (consumerUsage & allowedFlags) != 0;
427
428 surface = new Surface(gbp, useAsync);
429 ANativeWindow *anw = surface.get();
430
431 int width, height, format;
432 android_dataspace dataSpace;
433 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
434 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800435 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000436 ALOGE("%s: %s", __FUNCTION__, msg.string());
437 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
438 }
439 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
440 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800441 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000442 ALOGE("%s: %s", __FUNCTION__, msg.string());
443 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
444 }
445 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
446 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800447 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000448 ALOGE("%s: %s", __FUNCTION__, msg.string());
449 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
450 }
451 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
452 reinterpret_cast<int*>(&dataSpace))) != OK) {
453 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800454 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000455 ALOGE("%s: %s", __FUNCTION__, msg.string());
456 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
457 }
458
459 // FIXME: remove this override since the default format should be
460 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
461 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
462 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
463 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
464 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800465 __FUNCTION__, logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000466 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
467 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800468 std::unordered_set<int32_t> overriddenSensorPixelModes;
469 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
470 physicalCameraMetadata, flexibleConsumer, &overriddenSensorPixelModes) != OK) {
471 String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
472 "format %#x are not valid",logicalCameraId.string(), format);
473 ALOGE("%s: %s", __FUNCTION__, msg.string());
474 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
475 }
476 bool foundInMaxRes = false;
477 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
478 overriddenSensorPixelModes.end()) {
479 // we can use the default stream configuration map
480 foundInMaxRes = true;
481 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000482 // Round dimensions to the nearest dimensions available for this format
483 if (flexibleConsumer && isPublicFormat(format) &&
484 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800485 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
486 /*out*/&height)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000487 String8 msg = String8::format("Camera %s: No supported stream configurations with "
488 "format %#x defined, failed to create output stream",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800489 logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000490 ALOGE("%s: %s", __FUNCTION__, msg.string());
491 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
492 }
Emilian Peev2295df72021-11-12 18:14:10 -0800493 if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
494 physicalCameraMetadata)) {
Emilian Peevc81a7592022-02-14 17:38:18 -0800495 String8 msg = String8::format("Camera %s: Dynamic range profile 0x%" PRIx64
496 " not supported,failed to create output stream", logicalCameraId.string(),
497 dynamicRangeProfile);
Emilian Peev2295df72021-11-12 18:14:10 -0800498 ALOGE("%s: %s", __FUNCTION__, msg.string());
499 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
500 }
501 if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
502 !SessionConfigurationUtils::is10bitCompatibleFormat(format)) {
503 String8 msg = String8::format("Camera %s: No 10-bit supported stream configurations with "
Emilian Peevc81a7592022-02-14 17:38:18 -0800504 "format %#x defined and profile %" PRIx64 ", failed to create output stream",
Emilian Peev2295df72021-11-12 18:14:10 -0800505 logicalCameraId.string(), format, dynamicRangeProfile);
506 ALOGE("%s: %s", __FUNCTION__, msg.string());
507 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
508 }
Austin Borger9e2b27c2022-07-15 11:27:24 -0700509 if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
510 SessionConfigurationUtils::deviceReportsColorSpaces(physicalCameraMetadata) &&
511 !SessionConfigurationUtils::isColorSpaceSupported(colorSpace, format, dataSpace,
512 dynamicRangeProfile, physicalCameraMetadata)) {
513 String8 msg = String8::format("Camera %s: Color space %d not supported, failed to "
514 "create output stream (pixel format %d dynamic range profile %" PRId64 ")",
515 logicalCameraId.string(), colorSpace, format, dynamicRangeProfile);
516 ALOGE("%s: %s", __FUNCTION__, msg.string());
517 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
518 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800519 if (!SessionConfigurationUtils::isStreamUseCaseSupported(streamUseCase,
520 physicalCameraMetadata)) {
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800521 String8 msg = String8::format("Camera %s: stream use case %" PRId64 " not supported,"
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800522 " failed to create output stream", logicalCameraId.string(), streamUseCase);
523 ALOGE("%s: %s", __FUNCTION__, msg.string());
524 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
525 }
Shuzhen Wange4208922022-02-01 16:52:48 -0800526 if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
Shuzhen Wangffc4c012022-04-20 15:55:46 -0700527 timestampBase > OutputConfiguration::TIMESTAMP_BASE_MAX) {
Shuzhen Wange4208922022-02-01 16:52:48 -0800528 String8 msg = String8::format("Camera %s: invalid timestamp base %d",
529 logicalCameraId.string(), timestampBase);
530 ALOGE("%s: %s", __FUNCTION__, msg.string());
531 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
532 }
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800533 if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
534 mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
535 String8 msg = String8::format("Camera %s: invalid mirroring mode %d",
536 logicalCameraId.string(), mirrorMode);
537 ALOGE("%s: %s", __FUNCTION__, msg.string());
538 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
539 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000540
541 if (!isStreamInfoValid) {
542 streamInfo.width = width;
543 streamInfo.height = height;
544 streamInfo.format = format;
545 streamInfo.dataSpace = dataSpace;
546 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800547 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Emilian Peev2295df72021-11-12 18:14:10 -0800548 streamInfo.dynamicRangeProfile = dynamicRangeProfile;
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800549 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wange4208922022-02-01 16:52:48 -0800550 streamInfo.timestampBase = timestampBase;
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800551 streamInfo.mirrorMode = mirrorMode;
Austin Borger9e2b27c2022-07-15 11:27:24 -0700552 streamInfo.colorSpace = colorSpace;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000553 return binder::Status::ok();
554 }
555 if (width != streamInfo.width) {
556 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800557 logicalCameraId.string(), width, streamInfo.width);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000558 ALOGE("%s: %s", __FUNCTION__, msg.string());
559 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
560 }
561 if (height != streamInfo.height) {
562 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800563 logicalCameraId.string(), height, streamInfo.height);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000564 ALOGE("%s: %s", __FUNCTION__, msg.string());
565 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
566 }
567 if (format != streamInfo.format) {
568 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800569 logicalCameraId.string(), format, streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000570 ALOGE("%s: %s", __FUNCTION__, msg.string());
571 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
572 }
573 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
574 if (dataSpace != streamInfo.dataSpace) {
575 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800576 logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000577 ALOGE("%s: %s", __FUNCTION__, msg.string());
578 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
579 }
580 //At the native side, there isn't a way to check whether 2 surfaces come from the same
581 //surface class type. Use usage flag to approximate the comparison.
582 if (consumerUsage != streamInfo.consumerUsage) {
583 String8 msg = String8::format(
584 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800585 logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000586 ALOGE("%s: %s", __FUNCTION__, msg.string());
587 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
588 }
589 }
590 return binder::Status::ok();
591}
592
Austin Borgerea931242021-12-13 23:10:41 +0000593void mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700594 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000595 int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000596 if (stream == nullptr) {
597 return;
598 }
599
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000600 stream->streamType = aidl::android::hardware::camera::device::StreamType::OUTPUT;
601 stream->width = streamInfo.width;
602 stream->height = streamInfo.height;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000603 stream->format = AidlCamera3Device::mapToAidlPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000604 auto u = streamInfo.consumerUsage;
605 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000606 stream->usage = AidlCamera3Device::mapToAidlConsumerUsage(u);
607 stream->dataSpace = AidlCamera3Device::mapToAidlDataspace(streamInfo.dataSpace);
Austin Borger9e2b27c2022-07-15 11:27:24 -0700608 stream->colorSpace = streamInfo.colorSpace;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000609 stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000610 stream->id = -1; // Invalid stream id
611 stream->physicalCameraId = std::string(physicalId.string());
612 stream->bufferSize = 0;
613 stream->groupId = groupId;
614 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800615 size_t idx = 0;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000616 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800617 for (auto mode : streamInfo.sensorPixelModesUsed) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000618 stream->sensorPixelModesUsed[idx++] =
619 static_cast<SensorPixelMode>(mode);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800620 }
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000621 using DynamicRangeProfile =
622 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
623 stream->dynamicRangeProfile = static_cast<DynamicRangeProfile>(streamInfo.dynamicRangeProfile);
624 using StreamUseCases =
625 aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
626 stream->useCase = static_cast<StreamUseCases>(streamInfo.streamUseCase);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000627}
628
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800629binder::Status
Austin Borgerea931242021-12-13 23:10:41 +0000630convertToHALStreamCombination(
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800631 const SessionConfiguration& sessionConfiguration,
632 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
633 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000634 aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700635 bool overrideForPerfClass, bool *earlyExit) {
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000636 using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000637 auto operatingMode = sessionConfiguration.getOperatingMode();
638 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
639 if (!res.isOk()) {
640 return res;
641 }
642
643 if (earlyExit == nullptr) {
644 String8 msg("earlyExit nullptr");
645 ALOGE("%s: %s", __FUNCTION__, msg.string());
646 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
647 }
648 *earlyExit = false;
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000649 auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700650 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000651 /*out*/ &streamConfiguration.operationMode);
652 if (ret != OK) {
653 String8 msg = String8::format(
654 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
655 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
656 ALOGE("%s: %s", __FUNCTION__, msg.string());
657 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
658 msg.string());
659 }
660
661 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
662 (sessionConfiguration.getInputHeight() > 0) &&
663 (sessionConfiguration.getInputFormat() > 0);
664 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
665 size_t streamCount = outputConfigs.size();
666 streamCount = isInputValid ? streamCount + 1 : streamCount;
667 streamConfiguration.streams.resize(streamCount);
668 size_t streamIdx = 0;
669 if (isInputValid) {
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000670 std::vector<SensorPixelMode> defaultSensorPixelModes;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800671 defaultSensorPixelModes.resize(1);
672 defaultSensorPixelModes[0] =
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000673 static_cast<SensorPixelMode>(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
674 aidl::android::hardware::camera::device::Stream stream;
675 stream.id = 0;
676 stream.streamType = aidl::android::hardware::camera::device::StreamType::INPUT;
677 stream.width = static_cast<uint32_t> (sessionConfiguration.getInputWidth());
678 stream.height = static_cast<uint32_t> (sessionConfiguration.getInputHeight());
Jayant Chowdhary35642f22022-01-08 00:39:39 +0000679 stream.format =
680 AidlCamera3Device::AidlCamera3Device::mapToAidlPixelFormat(
681 sessionConfiguration.getInputFormat());
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000682 stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0);
683 stream.dataSpace =
684 static_cast<aidl::android::hardware::graphics::common::Dataspace>(
685 HAL_DATASPACE_UNKNOWN);
686 stream.rotation = aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
687 stream.bufferSize = 0;
688 stream.groupId = -1;
689 stream.sensorPixelModesUsed = defaultSensorPixelModes;
Emilian Peev065fb0f2022-05-16 15:37:16 -0700690 using DynamicRangeProfile =
691 aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
692 stream.dynamicRangeProfile =
693 DynamicRangeProfile::ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000694 streamConfiguration.streams[streamIdx++] = stream;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800695 streamConfiguration.multiResolutionInputImage =
696 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000697 }
698
699 for (const auto &it : outputConfigs) {
700 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
701 it.getGraphicBufferProducers();
702 bool deferredConsumer = it.isDeferred();
703 String8 physicalCameraId = String8(it.getPhysicalCameraId());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800704
Emilian Peevc81a7592022-02-14 17:38:18 -0800705 int64_t dynamicRangeProfile = it.getDynamicRangeProfile();
Austin Borger9e2b27c2022-07-15 11:27:24 -0700706 int32_t colorSpace = it.getColorSpace();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800707 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700708 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
709 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800710 const CameraMetadata &metadataChosen =
711 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
712
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000713 size_t numBufferProducers = bufferProducers.size();
714 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800715 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000716 OutputStreamInfo streamInfo;
717
718 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
719 if (!res.isOk()) {
720 return res;
721 }
722 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
723 logicalCameraId);
724 if (!res.isOk()) {
725 return res;
726 }
727
Shuzhen Wang8ed1e872022-03-08 16:34:33 -0800728 int64_t streamUseCase = it.getStreamUseCase();
Shuzhen Wange4208922022-02-01 16:52:48 -0800729 int timestampBase = it.getTimestampBase();
Shuzhen Wang610d7b82022-02-08 14:37:22 -0800730 int mirrorMode = it.getMirrorMode();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000731 if (deferredConsumer) {
732 streamInfo.width = it.getWidth();
733 streamInfo.height = it.getHeight();
734 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
735 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
736 auto surfaceType = it.getSurfaceType();
737 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
738 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
739 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
740 }
Emilian Peev2295df72021-11-12 18:14:10 -0800741 streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800742 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
743 streamInfo.format, streamInfo.width,
744 streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
745 &streamInfo.sensorPixelModesUsed) != OK) {
746 ALOGE("%s: Deferred surface sensor pixel modes not valid",
747 __FUNCTION__);
748 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
749 "Deferred surface sensor pixel modes not valid");
750 }
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800751 streamInfo.streamUseCase = streamUseCase;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800752 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000753 &streamConfiguration.streams[streamIdx++]);
754 isStreamInfoValid = true;
755
756 if (numBufferProducers == 0) {
757 continue;
758 }
759 }
760
761 for (auto& bufferProducer : bufferProducers) {
762 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000763 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Shuzhen Wangc8ab4522021-12-14 20:12:42 -0800764 logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
Austin Borger9e2b27c2022-07-15 11:27:24 -0700765 streamUseCase, timestampBase, mirrorMode, colorSpace);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000766
767 if (!res.isOk())
768 return res;
769
770 if (!isStreamInfoValid) {
771 bool isDepthCompositeStream =
772 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
773 bool isHeicCompositeStream =
774 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
775 if (isDepthCompositeStream || isHeicCompositeStream) {
776 // We need to take in to account that composite streams can have
777 // additional internal camera streams.
778 std::vector<OutputStreamInfo> compositeStreams;
779 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800780 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000781 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
782 deviceInfo, &compositeStreams);
783 } else {
784 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
785 deviceInfo, &compositeStreams);
786 }
787 if (ret != OK) {
788 String8 msg = String8::format(
789 "Camera %s: Failed adding composite streams: %s (%d)",
790 logicalCameraId.string(), strerror(-ret), ret);
791 ALOGE("%s: %s", __FUNCTION__, msg.string());
792 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
793 }
794
795 if (compositeStreams.size() == 0) {
796 // No internal streams means composite stream not
797 // supported.
798 *earlyExit = true;
799 return binder::Status::ok();
800 } else if (compositeStreams.size() > 1) {
801 streamCount += compositeStreams.size() - 1;
802 streamConfiguration.streams.resize(streamCount);
803 }
804
805 for (const auto& compositeStream : compositeStreams) {
806 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700807 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800808 physicalCameraId, groupId,
809 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000810 }
811 } else {
812 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700813 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800814 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000815 }
816 isStreamInfoValid = true;
817 }
818 }
819 }
820 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800821}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000822
Jayant Chowdharya04055f2022-01-03 02:07:49 +0000823binder::Status checkPhysicalCameraId(
824 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
825 const String8 &logicalCameraId) {
826 if (physicalCameraId.size() == 0) {
827 return binder::Status::ok();
828 }
829 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
830 physicalCameraId.string()) == physicalCameraIds.end()) {
831 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
832 logicalCameraId.string(), physicalCameraId.string());
833 ALOGE("%s: %s", __FUNCTION__, msg.string());
834 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
835 }
836 return binder::Status::ok();
837}
838
839binder::Status checkSurfaceType(size_t numBufferProducers,
840 bool deferredConsumer, int surfaceType) {
841 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
842 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
843 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
844 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
845 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
846 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
847 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
848 }
849
850 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
851 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
852
853 if (deferredConsumer && !validSurfaceType) {
854 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
855 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
856 }
857
858 return binder::Status::ok();
859}
860
861binder::Status checkOperatingMode(int operatingMode,
862 const CameraMetadata &staticInfo, const String8 &cameraId) {
863 if (operatingMode < 0) {
864 String8 msg = String8::format(
865 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
866 ALOGE("%s: %s", __FUNCTION__, msg.string());
867 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
868 msg.string());
869 }
870
871 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
872 if (isConstrainedHighSpeed) {
873 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
874 bool isConstrainedHighSpeedSupported = false;
875 for(size_t i = 0; i < entry.count; ++i) {
876 uint8_t capability = entry.data.u8[i];
877 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
878 isConstrainedHighSpeedSupported = true;
879 break;
880 }
881 }
882 if (!isConstrainedHighSpeedSupported) {
883 String8 msg = String8::format(
884 "Camera %s: Try to create a constrained high speed configuration on a device"
885 " that doesn't support it.", cameraId.string());
886 ALOGE("%s: %s", __FUNCTION__, msg.string());
887 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
888 msg.string());
889 }
890 }
891
892 return binder::Status::ok();
893}
894
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800895static bool inStreamConfigurationMap(int format, int width, int height,
896 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
897 auto scs = sm.find(format);
898 if (scs == sm.end()) {
899 return false;
900 }
901 for (auto &sc : scs->second) {
902 if (sc.width == width && sc.height == height && sc.isInput == 0) {
903 return true;
904 }
905 }
906 return false;
907}
908
909static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
910 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
911}
912
Austin Borgerea931242021-12-13 23:10:41 +0000913status_t checkAndOverrideSensorPixelModesUsed(
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800914 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
915 const CameraMetadata &staticInfo, bool flexibleConsumer,
916 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700917
918 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
919 convertToSet(sensorPixelModesUsed);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800920 if (!isUltraHighResolutionSensor(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700921 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
922 sensorPixelModesUsedSet.end()) {
923 // invalid value for non ultra high res sensors
924 return BAD_VALUE;
925 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800926 overriddenSensorPixelModesUsed->clear();
927 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
928 return OK;
929 }
930
931 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700932
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800933 bool isInDefaultStreamConfigurationMap =
934 inStreamConfigurationMap(format, width, height,
935 streamConfigurationPair.mDefaultStreamConfigurationMap);
936
937 bool isInMaximumResolutionStreamConfigurationMap =
938 inStreamConfigurationMap(format, width, height,
939 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
940
941 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
942 // size + format of the OutputConfiguration is found exclusively in 1.
943 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
944 // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
945 // compatibility.
946 if (sensorPixelModesUsedSet.size() == 0) {
947 // Ambiguous case, default to only 'DEFAULT' mode.
948 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
949 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
950 return OK;
951 }
952 // We don't allow flexible consumer for max resolution mode.
953 if (isInMaximumResolutionStreamConfigurationMap) {
954 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
955 return OK;
956 }
957 if (isInDefaultStreamConfigurationMap || (flexibleConsumer && width < ROUNDING_WIDTH_CAP)) {
958 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
959 return OK;
960 }
961 return BAD_VALUE;
962 }
963
964 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
965 // are valid / err out.
966 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
967 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
968 return BAD_VALUE;
969 }
970
971 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
972 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
973 return BAD_VALUE;
974 }
975 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
976 return OK;
977}
978
Austin Borgerea931242021-12-13 23:10:41 +0000979bool targetPerfClassPrimaryCamera(
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700980 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
981 int targetSdkVersion) {
982 bool isPerfClassPrimaryCamera =
983 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
984 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
985}
986
Austin Borgerea931242021-12-13 23:10:41 +0000987} // namespace SessionConfigurationUtils
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800988} // namespace camera3
989} // namespace android