blob: ed6ee9b89e040697c57f1fdf7da4c26d1a763d2b [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 Chowdhary13f9b2f2020-12-02 22:46:15 -080039void StreamConfiguration::getStreamConfigurations(
40 const CameraMetadata &staticInfo, int configuration,
41 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
42 if (scm == nullptr) {
43 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
44 return;
45 }
46 const int STREAM_FORMAT_OFFSET = 0;
47 const int STREAM_WIDTH_OFFSET = 1;
48 const int STREAM_HEIGHT_OFFSET = 2;
49 const int STREAM_IS_INPUT_OFFSET = 3;
50
51 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
52 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
53 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
54 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
55 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
56 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
57 StreamConfiguration sc = {format, width, height, isInput};
58 (*scm)[format].push_back(sc);
59 }
60}
61
62void StreamConfiguration::getStreamConfigurations(
63 const CameraMetadata &staticInfo, bool maxRes,
64 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
65 int32_t scalerKey =
66 SessionConfigurationUtils::getAppropriateModeTag(
67 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
68
69 int32_t depthKey =
70 SessionConfigurationUtils::getAppropriateModeTag(
71 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
72
73 int32_t dynamicDepthKey =
74 SessionConfigurationUtils::getAppropriateModeTag(
75 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
76
77 int32_t heicKey =
78 SessionConfigurationUtils::getAppropriateModeTag(
79 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
80
81 getStreamConfigurations(staticInfo, scalerKey, scm);
82 getStreamConfigurations(staticInfo, depthKey, scm);
83 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
84 getStreamConfigurations(staticInfo, heicKey, scm);
85}
86
87int32_t SessionConfigurationUtils::getAppropriateModeTag(int32_t defaultTag, bool maxResolution) {
88 if (!maxResolution) {
89 return defaultTag;
90 }
91 switch (defaultTag) {
92 case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS:
93 return ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
94 case ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS:
95 return ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
96 case ANDROID_SCALER_AVAILABLE_STALL_DURATIONS:
97 return ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION;
98 case ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:
99 return ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
100 case ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:
101 return ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
102 case ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:
103 return ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS;
104 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:
105 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
106 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:
107 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
108 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:
109 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS;
110 case ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:
111 return ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
112 case ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:
113 return ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
114 case ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS:
115 return ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS;
116 case ANDROID_SENSOR_OPAQUE_RAW_SIZE:
117 return ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION;
118 case ANDROID_LENS_INTRINSIC_CALIBRATION:
119 return ANDROID_LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION;
120 case ANDROID_LENS_DISTORTION:
121 return ANDROID_LENS_DISTORTION_MAXIMUM_RESOLUTION;
122 default:
123 ALOGE("%s: Tag %d doesn't have a maximum resolution counterpart", __FUNCTION__,
124 defaultTag);
125 return -1;
126 }
127 return -1;
128}
129
130
131StreamConfigurationPair
132SessionConfigurationUtils::getStreamConfigurationPair(const CameraMetadata &staticInfo) {
133 camera3::StreamConfigurationPair streamConfigurationPair;
134 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
135 &streamConfigurationPair.mDefaultStreamConfigurationMap);
136 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
137 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
138 return streamConfigurationPair;
139}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800140
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000141int64_t SessionConfigurationUtils::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
142 int64_t d0 = x0 - x1;
143 int64_t d1 = y0 - y1;
144 return d0 * d0 + d1 * d1;
145}
146
147bool SessionConfigurationUtils::roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800148 int32_t format, android_dataspace dataSpace,
149 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
150 /*out*/int32_t* outHeight) {
151 const int32_t depthSizesTag =
152 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
153 maxResolution);
154 const int32_t scalerSizesTag =
155 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
156 const int32_t heicSizesTag =
157 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000158
159 camera_metadata_ro_entry streamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800160 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000161 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800162 info.find(heicSizesTag) :
163 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000164
165 int32_t bestWidth = -1;
166 int32_t bestHeight = -1;
167
168 // Iterate through listed stream configurations and find the one with the smallest euclidean
169 // distance from the given dimensions for the given format.
170 for (size_t i = 0; i < streamConfigs.count; i += 4) {
171 int32_t fmt = streamConfigs.data.i32[i];
172 int32_t w = streamConfigs.data.i32[i + 1];
173 int32_t h = streamConfigs.data.i32[i + 2];
174
175 // Ignore input/output type for now
176 if (fmt == format) {
177 if (w == width && h == height) {
178 bestWidth = width;
179 bestHeight = height;
180 break;
181 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
182 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
183 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
184 height))) {
185 bestWidth = w;
186 bestHeight = h;
187 }
188 }
189 }
190
191 if (bestWidth == -1) {
192 // Return false if no configurations for this format were listed
193 return false;
194 }
195
196 // Set the outputs to the closet width/height
197 if (outWidth != NULL) {
198 *outWidth = bestWidth;
199 }
200 if (outHeight != NULL) {
201 *outHeight = bestHeight;
202 }
203
204 // Return true if at least one configuration for this format was listed
205 return true;
206}
207
208bool SessionConfigurationUtils::isPublicFormat(int32_t format)
209{
210 switch(format) {
211 case HAL_PIXEL_FORMAT_RGBA_8888:
212 case HAL_PIXEL_FORMAT_RGBX_8888:
213 case HAL_PIXEL_FORMAT_RGB_888:
214 case HAL_PIXEL_FORMAT_RGB_565:
215 case HAL_PIXEL_FORMAT_BGRA_8888:
216 case HAL_PIXEL_FORMAT_YV12:
217 case HAL_PIXEL_FORMAT_Y8:
218 case HAL_PIXEL_FORMAT_Y16:
219 case HAL_PIXEL_FORMAT_RAW16:
220 case HAL_PIXEL_FORMAT_RAW10:
221 case HAL_PIXEL_FORMAT_RAW12:
222 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
223 case HAL_PIXEL_FORMAT_BLOB:
224 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
225 case HAL_PIXEL_FORMAT_YCbCr_420_888:
226 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
227 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
228 case HAL_PIXEL_FORMAT_YCbCr_422_I:
229 return true;
230 default:
231 return false;
232 }
233}
234
235binder::Status SessionConfigurationUtils::createSurfaceFromGbp(
236 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
237 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800238 const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
239 const std::vector<int32_t> &sensorPixelModesUsed){
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000240 // bufferProducer must be non-null
241 if (gbp == nullptr) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800242 String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000243 ALOGW("%s: %s", __FUNCTION__, msg.string());
244 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
245 }
246 // HACK b/10949105
247 // Query consumer usage bits to set async operation mode for
248 // GLConsumer using controlledByApp parameter.
249 bool useAsync = false;
250 uint64_t consumerUsage = 0;
251 status_t err;
252 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
253 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800254 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000255 ALOGE("%s: %s", __FUNCTION__, msg.string());
256 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
257 }
258 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
259 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800260 "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000261 useAsync = true;
262 }
263
264 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
265 GRALLOC_USAGE_RENDERSCRIPT;
266 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
267 GraphicBuffer::USAGE_HW_TEXTURE |
268 GraphicBuffer::USAGE_HW_COMPOSER;
269 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
270 (consumerUsage & allowedFlags) != 0;
271
272 surface = new Surface(gbp, useAsync);
273 ANativeWindow *anw = surface.get();
274
275 int width, height, format;
276 android_dataspace dataSpace;
277 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
278 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800279 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000280 ALOGE("%s: %s", __FUNCTION__, msg.string());
281 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
282 }
283 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
284 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800285 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000286 ALOGE("%s: %s", __FUNCTION__, msg.string());
287 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
288 }
289 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
290 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800291 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000292 ALOGE("%s: %s", __FUNCTION__, msg.string());
293 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
294 }
295 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
296 reinterpret_cast<int*>(&dataSpace))) != OK) {
297 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800298 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000299 ALOGE("%s: %s", __FUNCTION__, msg.string());
300 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
301 }
302
303 // FIXME: remove this override since the default format should be
304 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
305 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
306 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
307 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
308 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800309 __FUNCTION__, logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000310 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
311 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800312 std::unordered_set<int32_t> overriddenSensorPixelModes;
313 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
314 physicalCameraMetadata, flexibleConsumer, &overriddenSensorPixelModes) != OK) {
315 String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
316 "format %#x are not valid",logicalCameraId.string(), format);
317 ALOGE("%s: %s", __FUNCTION__, msg.string());
318 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
319 }
320 bool foundInMaxRes = false;
321 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
322 overriddenSensorPixelModes.end()) {
323 // we can use the default stream configuration map
324 foundInMaxRes = true;
325 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000326 // Round dimensions to the nearest dimensions available for this format
327 if (flexibleConsumer && isPublicFormat(format) &&
328 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800329 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
330 /*out*/&height)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000331 String8 msg = String8::format("Camera %s: No supported stream configurations with "
332 "format %#x defined, failed to create output stream",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800333 logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000334 ALOGE("%s: %s", __FUNCTION__, msg.string());
335 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
336 }
337
338 if (!isStreamInfoValid) {
339 streamInfo.width = width;
340 streamInfo.height = height;
341 streamInfo.format = format;
342 streamInfo.dataSpace = dataSpace;
343 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800344 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000345 return binder::Status::ok();
346 }
347 if (width != streamInfo.width) {
348 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800349 logicalCameraId.string(), width, streamInfo.width);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000350 ALOGE("%s: %s", __FUNCTION__, msg.string());
351 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
352 }
353 if (height != streamInfo.height) {
354 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800355 logicalCameraId.string(), height, streamInfo.height);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000356 ALOGE("%s: %s", __FUNCTION__, msg.string());
357 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
358 }
359 if (format != streamInfo.format) {
360 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800361 logicalCameraId.string(), format, streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000362 ALOGE("%s: %s", __FUNCTION__, msg.string());
363 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
364 }
365 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
366 if (dataSpace != streamInfo.dataSpace) {
367 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800368 logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000369 ALOGE("%s: %s", __FUNCTION__, msg.string());
370 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
371 }
372 //At the native side, there isn't a way to check whether 2 surfaces come from the same
373 //surface class type. Use usage flag to approximate the comparison.
374 if (consumerUsage != streamInfo.consumerUsage) {
375 String8 msg = String8::format(
376 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800377 logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000378 ALOGE("%s: %s", __FUNCTION__, msg.string());
379 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
380 }
381 }
382 return binder::Status::ok();
383}
384
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000385void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700386 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800387 int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000388 if (stream == nullptr) {
389 return;
390 }
391
Shuzhen Wang83bff122020-11-20 15:51:39 -0800392 stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
393 stream->v3_4.v3_2.width = streamInfo.width;
394 stream->v3_4.v3_2.height = streamInfo.height;
395 stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000396 auto u = streamInfo.consumerUsage;
397 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800398 stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
399 stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
400 stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
401 stream->v3_4.v3_2.id = -1; // Invalid stream id
402 stream->v3_4.physicalCameraId = std::string(physicalId.string());
403 stream->v3_4.bufferSize = 0;
404 stream->groupId = groupId;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800405 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
406 size_t idx = 0;
407 for (auto mode : streamInfo.sensorPixelModesUsed) {
408 stream->sensorPixelModesUsed[idx++] =
409 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
410 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000411}
412
413binder::Status SessionConfigurationUtils::checkPhysicalCameraId(
414 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
415 const String8 &logicalCameraId) {
416 if (physicalCameraId.size() == 0) {
417 return binder::Status::ok();
418 }
419 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
420 physicalCameraId.string()) == physicalCameraIds.end()) {
421 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
422 logicalCameraId.string(), physicalCameraId.string());
423 ALOGE("%s: %s", __FUNCTION__, msg.string());
424 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
425 }
426 return binder::Status::ok();
427}
428
429binder::Status SessionConfigurationUtils::checkSurfaceType(size_t numBufferProducers,
430 bool deferredConsumer, int surfaceType) {
431 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
432 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
433 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
434 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
435 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
436 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
437 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
438 }
439
440 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
441 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
442
443 if (deferredConsumer && !validSurfaceType) {
444 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
445 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
446 }
447
448 return binder::Status::ok();
449}
450
451binder::Status SessionConfigurationUtils::checkOperatingMode(int operatingMode,
452 const CameraMetadata &staticInfo, const String8 &cameraId) {
453 if (operatingMode < 0) {
454 String8 msg = String8::format(
455 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
456 ALOGE("%s: %s", __FUNCTION__, msg.string());
457 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
458 msg.string());
459 }
460
461 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
462 if (isConstrainedHighSpeed) {
463 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
464 bool isConstrainedHighSpeedSupported = false;
465 for(size_t i = 0; i < entry.count; ++i) {
466 uint8_t capability = entry.data.u8[i];
467 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
468 isConstrainedHighSpeedSupported = true;
469 break;
470 }
471 }
472 if (!isConstrainedHighSpeedSupported) {
473 String8 msg = String8::format(
474 "Camera %s: Try to create a constrained high speed configuration on a device"
475 " that doesn't support it.", cameraId.string());
476 ALOGE("%s: %s", __FUNCTION__, msg.string());
477 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
478 msg.string());
479 }
480 }
481
482 return binder::Status::ok();
483}
484
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800485binder::Status
486SessionConfigurationUtils::convertToHALStreamCombination(
487 const SessionConfiguration& sessionConfiguration,
488 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
489 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700490 hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
491 bool overrideForPerfClass, bool *earlyExit) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000492
493 auto operatingMode = sessionConfiguration.getOperatingMode();
494 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
495 if (!res.isOk()) {
496 return res;
497 }
498
499 if (earlyExit == nullptr) {
500 String8 msg("earlyExit nullptr");
501 ALOGE("%s: %s", __FUNCTION__, msg.string());
502 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
503 }
504 *earlyExit = false;
505 auto ret = Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700506 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000507 /*out*/ &streamConfiguration.operationMode);
508 if (ret != OK) {
509 String8 msg = String8::format(
510 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
511 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
512 ALOGE("%s: %s", __FUNCTION__, msg.string());
513 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
514 msg.string());
515 }
516
517 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
518 (sessionConfiguration.getInputHeight() > 0) &&
519 (sessionConfiguration.getInputFormat() > 0);
520 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
521 size_t streamCount = outputConfigs.size();
522 streamCount = isInputValid ? streamCount + 1 : streamCount;
523 streamConfiguration.streams.resize(streamCount);
524 size_t streamIdx = 0;
525 if (isInputValid) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800526 hardware::hidl_vec<CameraMetadataEnumAndroidSensorPixelMode> defaultSensorPixelModes;
527 defaultSensorPixelModes.resize(1);
528 defaultSensorPixelModes[0] =
529 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
530 ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800531 streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000532 hardware::camera::device::V3_2::StreamType::INPUT,
533 static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
534 static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
535 Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
536 /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
537 hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800538 /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
Shuzhen Wang83bff122020-11-20 15:51:39 -0800539 streamConfiguration.multiResolutionInputImage =
540 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000541 }
542
543 for (const auto &it : outputConfigs) {
544 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
545 it.getGraphicBufferProducers();
546 bool deferredConsumer = it.isDeferred();
547 String8 physicalCameraId = String8(it.getPhysicalCameraId());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800548
549 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700550 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
551 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800552 const CameraMetadata &metadataChosen =
553 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
554
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000555 size_t numBufferProducers = bufferProducers.size();
556 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800557 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000558 OutputStreamInfo streamInfo;
559
560 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
561 if (!res.isOk()) {
562 return res;
563 }
564 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
565 logicalCameraId);
566 if (!res.isOk()) {
567 return res;
568 }
569
570 if (deferredConsumer) {
571 streamInfo.width = it.getWidth();
572 streamInfo.height = it.getHeight();
573 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
574 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
575 auto surfaceType = it.getSurfaceType();
576 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
577 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
578 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
579 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800580 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
581 streamInfo.format, streamInfo.width,
582 streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
583 &streamInfo.sensorPixelModesUsed) != OK) {
584 ALOGE("%s: Deferred surface sensor pixel modes not valid",
585 __FUNCTION__);
586 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
587 "Deferred surface sensor pixel modes not valid");
588 }
Shuzhen Wang83bff122020-11-20 15:51:39 -0800589 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000590 &streamConfiguration.streams[streamIdx++]);
591 isStreamInfoValid = true;
592
593 if (numBufferProducers == 0) {
594 continue;
595 }
596 }
597
598 for (auto& bufferProducer : bufferProducers) {
599 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000600 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800601 logicalCameraId, metadataChosen, sensorPixelModesUsed);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000602
603 if (!res.isOk())
604 return res;
605
606 if (!isStreamInfoValid) {
607 bool isDepthCompositeStream =
608 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
609 bool isHeicCompositeStream =
610 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
611 if (isDepthCompositeStream || isHeicCompositeStream) {
612 // We need to take in to account that composite streams can have
613 // additional internal camera streams.
614 std::vector<OutputStreamInfo> compositeStreams;
615 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800616 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000617 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
618 deviceInfo, &compositeStreams);
619 } else {
620 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
621 deviceInfo, &compositeStreams);
622 }
623 if (ret != OK) {
624 String8 msg = String8::format(
625 "Camera %s: Failed adding composite streams: %s (%d)",
626 logicalCameraId.string(), strerror(-ret), ret);
627 ALOGE("%s: %s", __FUNCTION__, msg.string());
628 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
629 }
630
631 if (compositeStreams.size() == 0) {
632 // No internal streams means composite stream not
633 // supported.
634 *earlyExit = true;
635 return binder::Status::ok();
636 } else if (compositeStreams.size() > 1) {
637 streamCount += compositeStreams.size() - 1;
638 streamConfiguration.streams.resize(streamCount);
639 }
640
641 for (const auto& compositeStream : compositeStreams) {
642 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700643 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800644 physicalCameraId, groupId,
645 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000646 }
647 } else {
648 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700649 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800650 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000651 }
652 isStreamInfoValid = true;
653 }
654 }
655 }
656 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800657}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000658
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800659static bool inStreamConfigurationMap(int format, int width, int height,
660 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
661 auto scs = sm.find(format);
662 if (scs == sm.end()) {
663 return false;
664 }
665 for (auto &sc : scs->second) {
666 if (sc.width == width && sc.height == height && sc.isInput == 0) {
667 return true;
668 }
669 }
670 return false;
671}
672
673static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
674 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
675}
676
677status_t SessionConfigurationUtils::checkAndOverrideSensorPixelModesUsed(
678 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
679 const CameraMetadata &staticInfo, bool flexibleConsumer,
680 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700681
682 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
683 convertToSet(sensorPixelModesUsed);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800684 if (!isUltraHighResolutionSensor(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700685 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
686 sensorPixelModesUsedSet.end()) {
687 // invalid value for non ultra high res sensors
688 return BAD_VALUE;
689 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800690 overriddenSensorPixelModesUsed->clear();
691 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
692 return OK;
693 }
694
695 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700696
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800697 bool isInDefaultStreamConfigurationMap =
698 inStreamConfigurationMap(format, width, height,
699 streamConfigurationPair.mDefaultStreamConfigurationMap);
700
701 bool isInMaximumResolutionStreamConfigurationMap =
702 inStreamConfigurationMap(format, width, height,
703 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
704
705 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
706 // size + format of the OutputConfiguration is found exclusively in 1.
707 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
708 // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
709 // compatibility.
710 if (sensorPixelModesUsedSet.size() == 0) {
711 // Ambiguous case, default to only 'DEFAULT' mode.
712 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
713 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
714 return OK;
715 }
716 // We don't allow flexible consumer for max resolution mode.
717 if (isInMaximumResolutionStreamConfigurationMap) {
718 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
719 return OK;
720 }
721 if (isInDefaultStreamConfigurationMap || (flexibleConsumer && width < ROUNDING_WIDTH_CAP)) {
722 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
723 return OK;
724 }
725 return BAD_VALUE;
726 }
727
728 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
729 // are valid / err out.
730 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
731 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
732 return BAD_VALUE;
733 }
734
735 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
736 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
737 return BAD_VALUE;
738 }
739 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
740 return OK;
741}
742
743bool SessionConfigurationUtils::isUltraHighResolutionSensor(const CameraMetadata &deviceInfo) {
744 camera_metadata_ro_entry_t entryCap;
745 entryCap = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
746 // Go through the capabilities and check if it has
747 // ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
748 for (size_t i = 0; i < entryCap.count; ++i) {
749 uint8_t capability = entryCap.data.u8[i];
750 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) {
751 return true;
752 }
753 }
754 return false;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800755}
756
Shuzhen Wang83bff122020-11-20 15:51:39 -0800757bool SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
758 hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
759 const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
760 if (streamConfigV37.multiResolutionInputImage) {
761 // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
762 return false;
763 }
764
765 streamConfigV34.streams.resize(streamConfigV37.streams.size());
766 for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
767 if (streamConfigV37.streams[i].groupId != -1) {
768 // ICameraDevice older than 3.7 doesn't support multi-resolution output
769 // image
770 return false;
771 }
772 streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
773 }
774 streamConfigV34.operationMode = streamConfigV37.operationMode;
775 streamConfigV34.sessionParams = streamConfigV37.sessionParams;
776
777 return true;
778}
779
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700780bool SessionConfigurationUtils::targetPerfClassPrimaryCamera(
781 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
782 int targetSdkVersion) {
783 bool isPerfClassPrimaryCamera =
784 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
785 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
786}
787
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800788} // namespace camera3
789} // namespace android