blob: 454c05fd2be6a5fe1dac5f8ade635e5f0c9f25ff [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 */
Shuzhen Wangd4abdf72021-05-28 11:22:50 -070016#include <cutils/properties.h>
17
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080018#include "SessionConfigurationUtils.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000019#include "../api2/DepthCompositeStream.h"
20#include "../api2/HeicCompositeStream.h"
21#include "common/CameraDeviceBase.h"
22#include "../CameraService.h"
23#include "device3/Camera3Device.h"
24#include "device3/Camera3OutputStream.h"
25
Colin Crossb8a9dbb2020-08-27 04:12:26 +000026using android::camera3::OutputStreamInfo;
27using android::camera3::OutputStreamInfo;
28using android::hardware::camera2::ICameraDeviceUser;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080029using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080030
31namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080032namespace camera3 {
33
Shuzhen Wangd4abdf72021-05-28 11:22:50 -070034int32_t SessionConfigurationUtils::PERF_CLASS_LEVEL =
35 property_get_int32("ro.odm.build.media_performance_class", 0);
36
37bool SessionConfigurationUtils::IS_PERF_CLASS = (PERF_CLASS_LEVEL == SDK_VERSION_S);
38
Jayant Chowdharycd3d36b2021-07-10 10:53:53 -070039camera3::Size SessionConfigurationUtils::getMaxJpegResolution(const CameraMetadata &metadata,
40 bool ultraHighResolution) {
41 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
42 const int STREAM_CONFIGURATION_SIZE = 4;
43 const int STREAM_FORMAT_OFFSET = 0;
44 const int STREAM_WIDTH_OFFSET = 1;
45 const int STREAM_HEIGHT_OFFSET = 2;
46 const int STREAM_IS_INPUT_OFFSET = 3;
47
48 int32_t scalerSizesTag = ultraHighResolution ?
49 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
50 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
51 camera_metadata_ro_entry_t availableStreamConfigs =
52 metadata.find(scalerSizesTag);
53 if (availableStreamConfigs.count == 0 ||
54 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
55 return camera3::Size(0, 0);
56 }
57
58 // Get max jpeg size (area-wise).
59 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
60 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
61 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
62 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
63 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
64 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
65 && format == HAL_PIXEL_FORMAT_BLOB &&
66 (width * height > maxJpegWidth * maxJpegHeight)) {
67 maxJpegWidth = width;
68 maxJpegHeight = height;
69 }
70 }
71
72 return camera3::Size(maxJpegWidth, maxJpegHeight);
73}
74
75size_t SessionConfigurationUtils::getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
76 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
77 return (uhrMaxJpegSize.width * uhrMaxJpegSize.height) /
78 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
79}
80
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080081void StreamConfiguration::getStreamConfigurations(
82 const CameraMetadata &staticInfo, int configuration,
83 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
84 if (scm == nullptr) {
85 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
86 return;
87 }
88 const int STREAM_FORMAT_OFFSET = 0;
89 const int STREAM_WIDTH_OFFSET = 1;
90 const int STREAM_HEIGHT_OFFSET = 2;
91 const int STREAM_IS_INPUT_OFFSET = 3;
92
93 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
94 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
95 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
96 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
97 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
98 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
99 StreamConfiguration sc = {format, width, height, isInput};
100 (*scm)[format].push_back(sc);
101 }
102}
103
104void StreamConfiguration::getStreamConfigurations(
105 const CameraMetadata &staticInfo, bool maxRes,
106 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
107 int32_t scalerKey =
108 SessionConfigurationUtils::getAppropriateModeTag(
109 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
110
111 int32_t depthKey =
112 SessionConfigurationUtils::getAppropriateModeTag(
113 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
114
115 int32_t dynamicDepthKey =
116 SessionConfigurationUtils::getAppropriateModeTag(
117 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
118
119 int32_t heicKey =
120 SessionConfigurationUtils::getAppropriateModeTag(
121 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
122
123 getStreamConfigurations(staticInfo, scalerKey, scm);
124 getStreamConfigurations(staticInfo, depthKey, scm);
125 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
126 getStreamConfigurations(staticInfo, heicKey, scm);
127}
128
129int32_t SessionConfigurationUtils::getAppropriateModeTag(int32_t defaultTag, bool maxResolution) {
130 if (!maxResolution) {
131 return defaultTag;
132 }
133 switch (defaultTag) {
134 case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS:
135 return ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
136 case ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS:
137 return ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
138 case ANDROID_SCALER_AVAILABLE_STALL_DURATIONS:
139 return ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION;
140 case ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:
141 return ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
142 case ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:
143 return ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
144 case ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:
145 return ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS;
146 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:
147 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
148 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:
149 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
150 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:
151 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS;
152 case ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:
153 return ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
154 case ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:
155 return ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
156 case ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS:
157 return ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS;
158 case ANDROID_SENSOR_OPAQUE_RAW_SIZE:
159 return ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION;
160 case ANDROID_LENS_INTRINSIC_CALIBRATION:
161 return ANDROID_LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION;
162 case ANDROID_LENS_DISTORTION:
163 return ANDROID_LENS_DISTORTION_MAXIMUM_RESOLUTION;
164 default:
165 ALOGE("%s: Tag %d doesn't have a maximum resolution counterpart", __FUNCTION__,
166 defaultTag);
167 return -1;
168 }
169 return -1;
170}
171
172
173StreamConfigurationPair
174SessionConfigurationUtils::getStreamConfigurationPair(const CameraMetadata &staticInfo) {
175 camera3::StreamConfigurationPair streamConfigurationPair;
176 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
177 &streamConfigurationPair.mDefaultStreamConfigurationMap);
178 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
179 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
180 return streamConfigurationPair;
181}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800182
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000183int64_t SessionConfigurationUtils::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
184 int64_t d0 = x0 - x1;
185 int64_t d1 = y0 - y1;
186 return d0 * d0 + d1 * d1;
187}
188
189bool SessionConfigurationUtils::roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800190 int32_t format, android_dataspace dataSpace,
191 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
192 /*out*/int32_t* outHeight) {
193 const int32_t depthSizesTag =
194 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
195 maxResolution);
196 const int32_t scalerSizesTag =
197 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
198 const int32_t heicSizesTag =
199 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000200
201 camera_metadata_ro_entry streamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800202 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000203 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800204 info.find(heicSizesTag) :
205 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000206
207 int32_t bestWidth = -1;
208 int32_t bestHeight = -1;
209
210 // Iterate through listed stream configurations and find the one with the smallest euclidean
211 // distance from the given dimensions for the given format.
212 for (size_t i = 0; i < streamConfigs.count; i += 4) {
213 int32_t fmt = streamConfigs.data.i32[i];
214 int32_t w = streamConfigs.data.i32[i + 1];
215 int32_t h = streamConfigs.data.i32[i + 2];
216
217 // Ignore input/output type for now
218 if (fmt == format) {
219 if (w == width && h == height) {
220 bestWidth = width;
221 bestHeight = height;
222 break;
223 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
224 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
225 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
226 height))) {
227 bestWidth = w;
228 bestHeight = h;
229 }
230 }
231 }
232
233 if (bestWidth == -1) {
234 // Return false if no configurations for this format were listed
235 return false;
236 }
237
238 // Set the outputs to the closet width/height
239 if (outWidth != NULL) {
240 *outWidth = bestWidth;
241 }
242 if (outHeight != NULL) {
243 *outHeight = bestHeight;
244 }
245
246 // Return true if at least one configuration for this format was listed
247 return true;
248}
249
250bool SessionConfigurationUtils::isPublicFormat(int32_t format)
251{
252 switch(format) {
253 case HAL_PIXEL_FORMAT_RGBA_8888:
254 case HAL_PIXEL_FORMAT_RGBX_8888:
255 case HAL_PIXEL_FORMAT_RGB_888:
256 case HAL_PIXEL_FORMAT_RGB_565:
257 case HAL_PIXEL_FORMAT_BGRA_8888:
258 case HAL_PIXEL_FORMAT_YV12:
259 case HAL_PIXEL_FORMAT_Y8:
260 case HAL_PIXEL_FORMAT_Y16:
261 case HAL_PIXEL_FORMAT_RAW16:
262 case HAL_PIXEL_FORMAT_RAW10:
263 case HAL_PIXEL_FORMAT_RAW12:
264 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
265 case HAL_PIXEL_FORMAT_BLOB:
266 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
267 case HAL_PIXEL_FORMAT_YCbCr_420_888:
268 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
269 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
270 case HAL_PIXEL_FORMAT_YCbCr_422_I:
271 return true;
272 default:
273 return false;
274 }
275}
276
277binder::Status SessionConfigurationUtils::createSurfaceFromGbp(
278 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
279 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800280 const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
281 const std::vector<int32_t> &sensorPixelModesUsed){
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000282 // bufferProducer must be non-null
283 if (gbp == nullptr) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800284 String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000285 ALOGW("%s: %s", __FUNCTION__, msg.string());
286 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
287 }
288 // HACK b/10949105
289 // Query consumer usage bits to set async operation mode for
290 // GLConsumer using controlledByApp parameter.
291 bool useAsync = false;
292 uint64_t consumerUsage = 0;
293 status_t err;
294 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
295 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800296 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000297 ALOGE("%s: %s", __FUNCTION__, msg.string());
298 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
299 }
300 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
301 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800302 "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000303 useAsync = true;
304 }
305
306 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
307 GRALLOC_USAGE_RENDERSCRIPT;
308 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
309 GraphicBuffer::USAGE_HW_TEXTURE |
310 GraphicBuffer::USAGE_HW_COMPOSER;
311 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
312 (consumerUsage & allowedFlags) != 0;
313
314 surface = new Surface(gbp, useAsync);
315 ANativeWindow *anw = surface.get();
316
317 int width, height, format;
318 android_dataspace dataSpace;
319 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
320 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800321 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000322 ALOGE("%s: %s", __FUNCTION__, msg.string());
323 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
324 }
325 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
326 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800327 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000328 ALOGE("%s: %s", __FUNCTION__, msg.string());
329 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
330 }
331 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
332 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800333 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000334 ALOGE("%s: %s", __FUNCTION__, msg.string());
335 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
336 }
337 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
338 reinterpret_cast<int*>(&dataSpace))) != OK) {
339 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800340 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000341 ALOGE("%s: %s", __FUNCTION__, msg.string());
342 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
343 }
344
345 // FIXME: remove this override since the default format should be
346 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
347 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
348 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
349 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
350 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800351 __FUNCTION__, logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000352 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
353 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800354 std::unordered_set<int32_t> overriddenSensorPixelModes;
355 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
356 physicalCameraMetadata, flexibleConsumer, &overriddenSensorPixelModes) != OK) {
357 String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
358 "format %#x are not valid",logicalCameraId.string(), format);
359 ALOGE("%s: %s", __FUNCTION__, msg.string());
360 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
361 }
362 bool foundInMaxRes = false;
363 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
364 overriddenSensorPixelModes.end()) {
365 // we can use the default stream configuration map
366 foundInMaxRes = true;
367 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000368 // Round dimensions to the nearest dimensions available for this format
369 if (flexibleConsumer && isPublicFormat(format) &&
370 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800371 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
372 /*out*/&height)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000373 String8 msg = String8::format("Camera %s: No supported stream configurations with "
374 "format %#x defined, failed to create output stream",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800375 logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000376 ALOGE("%s: %s", __FUNCTION__, msg.string());
377 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
378 }
379
380 if (!isStreamInfoValid) {
381 streamInfo.width = width;
382 streamInfo.height = height;
383 streamInfo.format = format;
384 streamInfo.dataSpace = dataSpace;
385 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800386 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000387 return binder::Status::ok();
388 }
389 if (width != streamInfo.width) {
390 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800391 logicalCameraId.string(), width, streamInfo.width);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000392 ALOGE("%s: %s", __FUNCTION__, msg.string());
393 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
394 }
395 if (height != streamInfo.height) {
396 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800397 logicalCameraId.string(), height, streamInfo.height);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000398 ALOGE("%s: %s", __FUNCTION__, msg.string());
399 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
400 }
401 if (format != streamInfo.format) {
402 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800403 logicalCameraId.string(), format, streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000404 ALOGE("%s: %s", __FUNCTION__, msg.string());
405 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
406 }
407 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
408 if (dataSpace != streamInfo.dataSpace) {
409 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800410 logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000411 ALOGE("%s: %s", __FUNCTION__, msg.string());
412 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
413 }
414 //At the native side, there isn't a way to check whether 2 surfaces come from the same
415 //surface class type. Use usage flag to approximate the comparison.
416 if (consumerUsage != streamInfo.consumerUsage) {
417 String8 msg = String8::format(
418 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800419 logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000420 ALOGE("%s: %s", __FUNCTION__, msg.string());
421 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
422 }
423 }
424 return binder::Status::ok();
425}
426
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000427void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700428 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800429 int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000430 if (stream == nullptr) {
431 return;
432 }
433
Shuzhen Wang83bff122020-11-20 15:51:39 -0800434 stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
435 stream->v3_4.v3_2.width = streamInfo.width;
436 stream->v3_4.v3_2.height = streamInfo.height;
437 stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000438 auto u = streamInfo.consumerUsage;
439 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800440 stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
441 stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
442 stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
443 stream->v3_4.v3_2.id = -1; // Invalid stream id
444 stream->v3_4.physicalCameraId = std::string(physicalId.string());
445 stream->v3_4.bufferSize = 0;
446 stream->groupId = groupId;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800447 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
448 size_t idx = 0;
449 for (auto mode : streamInfo.sensorPixelModesUsed) {
450 stream->sensorPixelModesUsed[idx++] =
451 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
452 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000453}
454
455binder::Status SessionConfigurationUtils::checkPhysicalCameraId(
456 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
457 const String8 &logicalCameraId) {
458 if (physicalCameraId.size() == 0) {
459 return binder::Status::ok();
460 }
461 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
462 physicalCameraId.string()) == physicalCameraIds.end()) {
463 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
464 logicalCameraId.string(), physicalCameraId.string());
465 ALOGE("%s: %s", __FUNCTION__, msg.string());
466 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
467 }
468 return binder::Status::ok();
469}
470
471binder::Status SessionConfigurationUtils::checkSurfaceType(size_t numBufferProducers,
472 bool deferredConsumer, int surfaceType) {
473 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
474 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
475 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
476 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
477 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
478 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
479 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
480 }
481
482 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
483 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
484
485 if (deferredConsumer && !validSurfaceType) {
486 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
487 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
488 }
489
490 return binder::Status::ok();
491}
492
493binder::Status SessionConfigurationUtils::checkOperatingMode(int operatingMode,
494 const CameraMetadata &staticInfo, const String8 &cameraId) {
495 if (operatingMode < 0) {
496 String8 msg = String8::format(
497 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
498 ALOGE("%s: %s", __FUNCTION__, msg.string());
499 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
500 msg.string());
501 }
502
503 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
504 if (isConstrainedHighSpeed) {
505 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
506 bool isConstrainedHighSpeedSupported = false;
507 for(size_t i = 0; i < entry.count; ++i) {
508 uint8_t capability = entry.data.u8[i];
509 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
510 isConstrainedHighSpeedSupported = true;
511 break;
512 }
513 }
514 if (!isConstrainedHighSpeedSupported) {
515 String8 msg = String8::format(
516 "Camera %s: Try to create a constrained high speed configuration on a device"
517 " that doesn't support it.", cameraId.string());
518 ALOGE("%s: %s", __FUNCTION__, msg.string());
519 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
520 msg.string());
521 }
522 }
523
524 return binder::Status::ok();
525}
526
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800527binder::Status
528SessionConfigurationUtils::convertToHALStreamCombination(
529 const SessionConfiguration& sessionConfiguration,
530 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
531 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700532 hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
533 bool overrideForPerfClass, bool *earlyExit) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000534
535 auto operatingMode = sessionConfiguration.getOperatingMode();
536 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
537 if (!res.isOk()) {
538 return res;
539 }
540
541 if (earlyExit == nullptr) {
542 String8 msg("earlyExit nullptr");
543 ALOGE("%s: %s", __FUNCTION__, msg.string());
544 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
545 }
546 *earlyExit = false;
547 auto ret = Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700548 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000549 /*out*/ &streamConfiguration.operationMode);
550 if (ret != OK) {
551 String8 msg = String8::format(
552 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
553 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
554 ALOGE("%s: %s", __FUNCTION__, msg.string());
555 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
556 msg.string());
557 }
558
559 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
560 (sessionConfiguration.getInputHeight() > 0) &&
561 (sessionConfiguration.getInputFormat() > 0);
562 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
563 size_t streamCount = outputConfigs.size();
564 streamCount = isInputValid ? streamCount + 1 : streamCount;
565 streamConfiguration.streams.resize(streamCount);
566 size_t streamIdx = 0;
567 if (isInputValid) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800568 hardware::hidl_vec<CameraMetadataEnumAndroidSensorPixelMode> defaultSensorPixelModes;
569 defaultSensorPixelModes.resize(1);
570 defaultSensorPixelModes[0] =
571 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
572 ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800573 streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000574 hardware::camera::device::V3_2::StreamType::INPUT,
575 static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
576 static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
577 Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
578 /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
579 hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800580 /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
Shuzhen Wang83bff122020-11-20 15:51:39 -0800581 streamConfiguration.multiResolutionInputImage =
582 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000583 }
584
585 for (const auto &it : outputConfigs) {
586 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
587 it.getGraphicBufferProducers();
588 bool deferredConsumer = it.isDeferred();
589 String8 physicalCameraId = String8(it.getPhysicalCameraId());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800590
591 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700592 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
593 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800594 const CameraMetadata &metadataChosen =
595 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
596
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000597 size_t numBufferProducers = bufferProducers.size();
598 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800599 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000600 OutputStreamInfo streamInfo;
601
602 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
603 if (!res.isOk()) {
604 return res;
605 }
606 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
607 logicalCameraId);
608 if (!res.isOk()) {
609 return res;
610 }
611
612 if (deferredConsumer) {
613 streamInfo.width = it.getWidth();
614 streamInfo.height = it.getHeight();
615 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
616 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
617 auto surfaceType = it.getSurfaceType();
618 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
619 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
620 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
621 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800622 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
623 streamInfo.format, streamInfo.width,
624 streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
625 &streamInfo.sensorPixelModesUsed) != OK) {
626 ALOGE("%s: Deferred surface sensor pixel modes not valid",
627 __FUNCTION__);
628 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
629 "Deferred surface sensor pixel modes not valid");
630 }
Shuzhen Wang83bff122020-11-20 15:51:39 -0800631 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000632 &streamConfiguration.streams[streamIdx++]);
633 isStreamInfoValid = true;
634
635 if (numBufferProducers == 0) {
636 continue;
637 }
638 }
639
640 for (auto& bufferProducer : bufferProducers) {
641 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000642 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800643 logicalCameraId, metadataChosen, sensorPixelModesUsed);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000644
645 if (!res.isOk())
646 return res;
647
648 if (!isStreamInfoValid) {
649 bool isDepthCompositeStream =
650 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
651 bool isHeicCompositeStream =
652 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
653 if (isDepthCompositeStream || isHeicCompositeStream) {
654 // We need to take in to account that composite streams can have
655 // additional internal camera streams.
656 std::vector<OutputStreamInfo> compositeStreams;
657 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800658 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000659 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
660 deviceInfo, &compositeStreams);
661 } else {
662 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
663 deviceInfo, &compositeStreams);
664 }
665 if (ret != OK) {
666 String8 msg = String8::format(
667 "Camera %s: Failed adding composite streams: %s (%d)",
668 logicalCameraId.string(), strerror(-ret), ret);
669 ALOGE("%s: %s", __FUNCTION__, msg.string());
670 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
671 }
672
673 if (compositeStreams.size() == 0) {
674 // No internal streams means composite stream not
675 // supported.
676 *earlyExit = true;
677 return binder::Status::ok();
678 } else if (compositeStreams.size() > 1) {
679 streamCount += compositeStreams.size() - 1;
680 streamConfiguration.streams.resize(streamCount);
681 }
682
683 for (const auto& compositeStream : compositeStreams) {
684 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700685 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800686 physicalCameraId, groupId,
687 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000688 }
689 } else {
690 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700691 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800692 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000693 }
694 isStreamInfoValid = true;
695 }
696 }
697 }
698 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800699}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000700
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800701static bool inStreamConfigurationMap(int format, int width, int height,
702 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
703 auto scs = sm.find(format);
704 if (scs == sm.end()) {
705 return false;
706 }
707 for (auto &sc : scs->second) {
708 if (sc.width == width && sc.height == height && sc.isInput == 0) {
709 return true;
710 }
711 }
712 return false;
713}
714
715static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
716 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
717}
718
719status_t SessionConfigurationUtils::checkAndOverrideSensorPixelModesUsed(
720 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
721 const CameraMetadata &staticInfo, bool flexibleConsumer,
722 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700723
724 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
725 convertToSet(sensorPixelModesUsed);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800726 if (!isUltraHighResolutionSensor(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700727 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
728 sensorPixelModesUsedSet.end()) {
729 // invalid value for non ultra high res sensors
730 return BAD_VALUE;
731 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800732 overriddenSensorPixelModesUsed->clear();
733 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
734 return OK;
735 }
736
737 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700738
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800739 bool isInDefaultStreamConfigurationMap =
740 inStreamConfigurationMap(format, width, height,
741 streamConfigurationPair.mDefaultStreamConfigurationMap);
742
743 bool isInMaximumResolutionStreamConfigurationMap =
744 inStreamConfigurationMap(format, width, height,
745 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
746
747 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
748 // size + format of the OutputConfiguration is found exclusively in 1.
749 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
750 // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
751 // compatibility.
752 if (sensorPixelModesUsedSet.size() == 0) {
753 // Ambiguous case, default to only 'DEFAULT' mode.
754 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
755 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
756 return OK;
757 }
758 // We don't allow flexible consumer for max resolution mode.
759 if (isInMaximumResolutionStreamConfigurationMap) {
760 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
761 return OK;
762 }
763 if (isInDefaultStreamConfigurationMap || (flexibleConsumer && width < ROUNDING_WIDTH_CAP)) {
764 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
765 return OK;
766 }
767 return BAD_VALUE;
768 }
769
770 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
771 // are valid / err out.
772 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
773 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
774 return BAD_VALUE;
775 }
776
777 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
778 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
779 return BAD_VALUE;
780 }
781 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
782 return OK;
783}
784
785bool SessionConfigurationUtils::isUltraHighResolutionSensor(const CameraMetadata &deviceInfo) {
786 camera_metadata_ro_entry_t entryCap;
787 entryCap = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
788 // Go through the capabilities and check if it has
789 // ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
790 for (size_t i = 0; i < entryCap.count; ++i) {
791 uint8_t capability = entryCap.data.u8[i];
792 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) {
793 return true;
794 }
795 }
796 return false;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800797}
798
Shuzhen Wang83bff122020-11-20 15:51:39 -0800799bool SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
800 hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
801 const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
802 if (streamConfigV37.multiResolutionInputImage) {
803 // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
804 return false;
805 }
806
807 streamConfigV34.streams.resize(streamConfigV37.streams.size());
808 for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
809 if (streamConfigV37.streams[i].groupId != -1) {
810 // ICameraDevice older than 3.7 doesn't support multi-resolution output
811 // image
812 return false;
813 }
814 streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
815 }
816 streamConfigV34.operationMode = streamConfigV37.operationMode;
817 streamConfigV34.sessionParams = streamConfigV37.sessionParams;
818
819 return true;
820}
821
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700822bool SessionConfigurationUtils::targetPerfClassPrimaryCamera(
823 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
824 int targetSdkVersion) {
825 bool isPerfClassPrimaryCamera =
826 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
827 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
828}
829
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800830} // namespace camera3
831} // namespace android