blob: 5a7166cd3a5bac669f20a944b7ff6b758cf40231 [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
Jayant Chowdhary9255ce02021-07-15 11:18:17 -0700130bool SessionConfigurationUtils::getArrayWidthAndHeight(const CameraMetadata *deviceInfo,
131 int32_t arrayTag, int32_t *width, int32_t *height) {
132 if (width == nullptr || height == nullptr) {
133 ALOGE("%s: width / height nullptr", __FUNCTION__);
134 return false;
135 }
136 camera_metadata_ro_entry_t entry;
137 entry = deviceInfo->find(arrayTag);
138 if (entry.count != 4) return false;
139 *width = entry.data.i32[2];
140 *height = entry.data.i32[3];
141 return true;
142}
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800143
144StreamConfigurationPair
145SessionConfigurationUtils::getStreamConfigurationPair(const CameraMetadata &staticInfo) {
146 camera3::StreamConfigurationPair streamConfigurationPair;
147 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
148 &streamConfigurationPair.mDefaultStreamConfigurationMap);
149 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
150 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
151 return streamConfigurationPair;
152}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800153
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000154int64_t SessionConfigurationUtils::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
155 int64_t d0 = x0 - x1;
156 int64_t d1 = y0 - y1;
157 return d0 * d0 + d1 * d1;
158}
159
160bool SessionConfigurationUtils::roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800161 int32_t format, android_dataspace dataSpace,
162 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
163 /*out*/int32_t* outHeight) {
164 const int32_t depthSizesTag =
165 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
166 maxResolution);
167 const int32_t scalerSizesTag =
168 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
169 const int32_t heicSizesTag =
170 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000171
172 camera_metadata_ro_entry streamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800173 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000174 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800175 info.find(heicSizesTag) :
176 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000177
178 int32_t bestWidth = -1;
179 int32_t bestHeight = -1;
180
181 // Iterate through listed stream configurations and find the one with the smallest euclidean
182 // distance from the given dimensions for the given format.
183 for (size_t i = 0; i < streamConfigs.count; i += 4) {
184 int32_t fmt = streamConfigs.data.i32[i];
185 int32_t w = streamConfigs.data.i32[i + 1];
186 int32_t h = streamConfigs.data.i32[i + 2];
187
188 // Ignore input/output type for now
189 if (fmt == format) {
190 if (w == width && h == height) {
191 bestWidth = width;
192 bestHeight = height;
193 break;
194 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
195 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
196 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
197 height))) {
198 bestWidth = w;
199 bestHeight = h;
200 }
201 }
202 }
203
204 if (bestWidth == -1) {
205 // Return false if no configurations for this format were listed
206 return false;
207 }
208
209 // Set the outputs to the closet width/height
210 if (outWidth != NULL) {
211 *outWidth = bestWidth;
212 }
213 if (outHeight != NULL) {
214 *outHeight = bestHeight;
215 }
216
217 // Return true if at least one configuration for this format was listed
218 return true;
219}
220
221bool SessionConfigurationUtils::isPublicFormat(int32_t format)
222{
223 switch(format) {
224 case HAL_PIXEL_FORMAT_RGBA_8888:
225 case HAL_PIXEL_FORMAT_RGBX_8888:
226 case HAL_PIXEL_FORMAT_RGB_888:
227 case HAL_PIXEL_FORMAT_RGB_565:
228 case HAL_PIXEL_FORMAT_BGRA_8888:
229 case HAL_PIXEL_FORMAT_YV12:
230 case HAL_PIXEL_FORMAT_Y8:
231 case HAL_PIXEL_FORMAT_Y16:
232 case HAL_PIXEL_FORMAT_RAW16:
233 case HAL_PIXEL_FORMAT_RAW10:
234 case HAL_PIXEL_FORMAT_RAW12:
235 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
236 case HAL_PIXEL_FORMAT_BLOB:
237 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
238 case HAL_PIXEL_FORMAT_YCbCr_420_888:
239 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
240 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
241 case HAL_PIXEL_FORMAT_YCbCr_422_I:
242 return true;
243 default:
244 return false;
245 }
246}
247
248binder::Status SessionConfigurationUtils::createSurfaceFromGbp(
249 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
250 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800251 const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
252 const std::vector<int32_t> &sensorPixelModesUsed){
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000253 // bufferProducer must be non-null
254 if (gbp == nullptr) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800255 String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000256 ALOGW("%s: %s", __FUNCTION__, msg.string());
257 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
258 }
259 // HACK b/10949105
260 // Query consumer usage bits to set async operation mode for
261 // GLConsumer using controlledByApp parameter.
262 bool useAsync = false;
263 uint64_t consumerUsage = 0;
264 status_t err;
265 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
266 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800267 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000268 ALOGE("%s: %s", __FUNCTION__, msg.string());
269 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
270 }
271 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
272 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800273 "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000274 useAsync = true;
275 }
276
277 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
278 GRALLOC_USAGE_RENDERSCRIPT;
279 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
280 GraphicBuffer::USAGE_HW_TEXTURE |
281 GraphicBuffer::USAGE_HW_COMPOSER;
282 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
283 (consumerUsage & allowedFlags) != 0;
284
285 surface = new Surface(gbp, useAsync);
286 ANativeWindow *anw = surface.get();
287
288 int width, height, format;
289 android_dataspace dataSpace;
290 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
291 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800292 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000293 ALOGE("%s: %s", __FUNCTION__, msg.string());
294 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
295 }
296 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
297 String8 msg = String8::format("Camera %s: Failed to query Surface height: %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 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
303 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800304 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000305 ALOGE("%s: %s", __FUNCTION__, msg.string());
306 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
307 }
308 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
309 reinterpret_cast<int*>(&dataSpace))) != OK) {
310 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800311 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000312 ALOGE("%s: %s", __FUNCTION__, msg.string());
313 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
314 }
315
316 // FIXME: remove this override since the default format should be
317 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
318 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
319 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
320 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
321 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800322 __FUNCTION__, logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000323 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
324 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800325 std::unordered_set<int32_t> overriddenSensorPixelModes;
326 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
327 physicalCameraMetadata, flexibleConsumer, &overriddenSensorPixelModes) != OK) {
328 String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
329 "format %#x are not valid",logicalCameraId.string(), format);
330 ALOGE("%s: %s", __FUNCTION__, msg.string());
331 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
332 }
333 bool foundInMaxRes = false;
334 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
335 overriddenSensorPixelModes.end()) {
336 // we can use the default stream configuration map
337 foundInMaxRes = true;
338 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000339 // Round dimensions to the nearest dimensions available for this format
340 if (flexibleConsumer && isPublicFormat(format) &&
341 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800342 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
343 /*out*/&height)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000344 String8 msg = String8::format("Camera %s: No supported stream configurations with "
345 "format %#x defined, failed to create output stream",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800346 logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000347 ALOGE("%s: %s", __FUNCTION__, msg.string());
348 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
349 }
350
351 if (!isStreamInfoValid) {
352 streamInfo.width = width;
353 streamInfo.height = height;
354 streamInfo.format = format;
355 streamInfo.dataSpace = dataSpace;
356 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800357 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000358 return binder::Status::ok();
359 }
360 if (width != streamInfo.width) {
361 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800362 logicalCameraId.string(), width, streamInfo.width);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000363 ALOGE("%s: %s", __FUNCTION__, msg.string());
364 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
365 }
366 if (height != streamInfo.height) {
367 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800368 logicalCameraId.string(), height, streamInfo.height);
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 if (format != streamInfo.format) {
373 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800374 logicalCameraId.string(), format, streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000375 ALOGE("%s: %s", __FUNCTION__, msg.string());
376 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
377 }
378 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
379 if (dataSpace != streamInfo.dataSpace) {
380 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800381 logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000382 ALOGE("%s: %s", __FUNCTION__, msg.string());
383 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
384 }
385 //At the native side, there isn't a way to check whether 2 surfaces come from the same
386 //surface class type. Use usage flag to approximate the comparison.
387 if (consumerUsage != streamInfo.consumerUsage) {
388 String8 msg = String8::format(
389 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800390 logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000391 ALOGE("%s: %s", __FUNCTION__, msg.string());
392 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
393 }
394 }
395 return binder::Status::ok();
396}
397
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000398void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700399 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800400 int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000401 if (stream == nullptr) {
402 return;
403 }
404
Shuzhen Wang83bff122020-11-20 15:51:39 -0800405 stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
406 stream->v3_4.v3_2.width = streamInfo.width;
407 stream->v3_4.v3_2.height = streamInfo.height;
408 stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000409 auto u = streamInfo.consumerUsage;
410 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800411 stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
412 stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
413 stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
414 stream->v3_4.v3_2.id = -1; // Invalid stream id
415 stream->v3_4.physicalCameraId = std::string(physicalId.string());
416 stream->v3_4.bufferSize = 0;
417 stream->groupId = groupId;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800418 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
419 size_t idx = 0;
420 for (auto mode : streamInfo.sensorPixelModesUsed) {
421 stream->sensorPixelModesUsed[idx++] =
422 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
423 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000424}
425
426binder::Status SessionConfigurationUtils::checkPhysicalCameraId(
427 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
428 const String8 &logicalCameraId) {
429 if (physicalCameraId.size() == 0) {
430 return binder::Status::ok();
431 }
432 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
433 physicalCameraId.string()) == physicalCameraIds.end()) {
434 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
435 logicalCameraId.string(), physicalCameraId.string());
436 ALOGE("%s: %s", __FUNCTION__, msg.string());
437 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
438 }
439 return binder::Status::ok();
440}
441
442binder::Status SessionConfigurationUtils::checkSurfaceType(size_t numBufferProducers,
443 bool deferredConsumer, int surfaceType) {
444 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
445 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
446 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
447 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
448 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
449 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
450 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
451 }
452
453 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
454 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
455
456 if (deferredConsumer && !validSurfaceType) {
457 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
458 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
459 }
460
461 return binder::Status::ok();
462}
463
464binder::Status SessionConfigurationUtils::checkOperatingMode(int operatingMode,
465 const CameraMetadata &staticInfo, const String8 &cameraId) {
466 if (operatingMode < 0) {
467 String8 msg = String8::format(
468 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
469 ALOGE("%s: %s", __FUNCTION__, msg.string());
470 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
471 msg.string());
472 }
473
474 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
475 if (isConstrainedHighSpeed) {
476 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
477 bool isConstrainedHighSpeedSupported = false;
478 for(size_t i = 0; i < entry.count; ++i) {
479 uint8_t capability = entry.data.u8[i];
480 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
481 isConstrainedHighSpeedSupported = true;
482 break;
483 }
484 }
485 if (!isConstrainedHighSpeedSupported) {
486 String8 msg = String8::format(
487 "Camera %s: Try to create a constrained high speed configuration on a device"
488 " that doesn't support it.", cameraId.string());
489 ALOGE("%s: %s", __FUNCTION__, msg.string());
490 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
491 msg.string());
492 }
493 }
494
495 return binder::Status::ok();
496}
497
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800498binder::Status
499SessionConfigurationUtils::convertToHALStreamCombination(
500 const SessionConfiguration& sessionConfiguration,
501 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
502 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700503 hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
504 bool overrideForPerfClass, bool *earlyExit) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000505
506 auto operatingMode = sessionConfiguration.getOperatingMode();
507 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
508 if (!res.isOk()) {
509 return res;
510 }
511
512 if (earlyExit == nullptr) {
513 String8 msg("earlyExit nullptr");
514 ALOGE("%s: %s", __FUNCTION__, msg.string());
515 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
516 }
517 *earlyExit = false;
518 auto ret = Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700519 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000520 /*out*/ &streamConfiguration.operationMode);
521 if (ret != OK) {
522 String8 msg = String8::format(
523 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
524 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
525 ALOGE("%s: %s", __FUNCTION__, msg.string());
526 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
527 msg.string());
528 }
529
530 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
531 (sessionConfiguration.getInputHeight() > 0) &&
532 (sessionConfiguration.getInputFormat() > 0);
533 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
534 size_t streamCount = outputConfigs.size();
535 streamCount = isInputValid ? streamCount + 1 : streamCount;
536 streamConfiguration.streams.resize(streamCount);
537 size_t streamIdx = 0;
538 if (isInputValid) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800539 hardware::hidl_vec<CameraMetadataEnumAndroidSensorPixelMode> defaultSensorPixelModes;
540 defaultSensorPixelModes.resize(1);
541 defaultSensorPixelModes[0] =
542 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
543 ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800544 streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000545 hardware::camera::device::V3_2::StreamType::INPUT,
546 static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
547 static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
548 Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
549 /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
550 hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800551 /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
Shuzhen Wang83bff122020-11-20 15:51:39 -0800552 streamConfiguration.multiResolutionInputImage =
553 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000554 }
555
556 for (const auto &it : outputConfigs) {
557 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
558 it.getGraphicBufferProducers();
559 bool deferredConsumer = it.isDeferred();
560 String8 physicalCameraId = String8(it.getPhysicalCameraId());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800561
562 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700563 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
564 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800565 const CameraMetadata &metadataChosen =
566 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
567
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000568 size_t numBufferProducers = bufferProducers.size();
569 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800570 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000571 OutputStreamInfo streamInfo;
572
573 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
574 if (!res.isOk()) {
575 return res;
576 }
577 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
578 logicalCameraId);
579 if (!res.isOk()) {
580 return res;
581 }
582
583 if (deferredConsumer) {
584 streamInfo.width = it.getWidth();
585 streamInfo.height = it.getHeight();
586 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
587 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
588 auto surfaceType = it.getSurfaceType();
589 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
590 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
591 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
592 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800593 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
594 streamInfo.format, streamInfo.width,
595 streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
596 &streamInfo.sensorPixelModesUsed) != OK) {
597 ALOGE("%s: Deferred surface sensor pixel modes not valid",
598 __FUNCTION__);
599 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
600 "Deferred surface sensor pixel modes not valid");
601 }
Shuzhen Wang83bff122020-11-20 15:51:39 -0800602 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000603 &streamConfiguration.streams[streamIdx++]);
604 isStreamInfoValid = true;
605
606 if (numBufferProducers == 0) {
607 continue;
608 }
609 }
610
611 for (auto& bufferProducer : bufferProducers) {
612 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000613 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800614 logicalCameraId, metadataChosen, sensorPixelModesUsed);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000615
616 if (!res.isOk())
617 return res;
618
619 if (!isStreamInfoValid) {
620 bool isDepthCompositeStream =
621 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
622 bool isHeicCompositeStream =
623 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
624 if (isDepthCompositeStream || isHeicCompositeStream) {
625 // We need to take in to account that composite streams can have
626 // additional internal camera streams.
627 std::vector<OutputStreamInfo> compositeStreams;
628 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800629 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000630 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
631 deviceInfo, &compositeStreams);
632 } else {
633 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
634 deviceInfo, &compositeStreams);
635 }
636 if (ret != OK) {
637 String8 msg = String8::format(
638 "Camera %s: Failed adding composite streams: %s (%d)",
639 logicalCameraId.string(), strerror(-ret), ret);
640 ALOGE("%s: %s", __FUNCTION__, msg.string());
641 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
642 }
643
644 if (compositeStreams.size() == 0) {
645 // No internal streams means composite stream not
646 // supported.
647 *earlyExit = true;
648 return binder::Status::ok();
649 } else if (compositeStreams.size() > 1) {
650 streamCount += compositeStreams.size() - 1;
651 streamConfiguration.streams.resize(streamCount);
652 }
653
654 for (const auto& compositeStream : compositeStreams) {
655 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700656 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800657 physicalCameraId, groupId,
658 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000659 }
660 } else {
661 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700662 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800663 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000664 }
665 isStreamInfoValid = true;
666 }
667 }
668 }
669 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800670}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000671
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800672static bool inStreamConfigurationMap(int format, int width, int height,
673 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
674 auto scs = sm.find(format);
675 if (scs == sm.end()) {
676 return false;
677 }
678 for (auto &sc : scs->second) {
679 if (sc.width == width && sc.height == height && sc.isInput == 0) {
680 return true;
681 }
682 }
683 return false;
684}
685
686static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
687 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
688}
689
690status_t SessionConfigurationUtils::checkAndOverrideSensorPixelModesUsed(
691 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
692 const CameraMetadata &staticInfo, bool flexibleConsumer,
693 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700694
695 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
696 convertToSet(sensorPixelModesUsed);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800697 if (!isUltraHighResolutionSensor(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700698 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
699 sensorPixelModesUsedSet.end()) {
700 // invalid value for non ultra high res sensors
701 return BAD_VALUE;
702 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800703 overriddenSensorPixelModesUsed->clear();
704 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
705 return OK;
706 }
707
708 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700709
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800710 bool isInDefaultStreamConfigurationMap =
711 inStreamConfigurationMap(format, width, height,
712 streamConfigurationPair.mDefaultStreamConfigurationMap);
713
714 bool isInMaximumResolutionStreamConfigurationMap =
715 inStreamConfigurationMap(format, width, height,
716 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
717
718 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
719 // size + format of the OutputConfiguration is found exclusively in 1.
720 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
721 // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
722 // compatibility.
723 if (sensorPixelModesUsedSet.size() == 0) {
724 // Ambiguous case, default to only 'DEFAULT' mode.
725 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
726 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
727 return OK;
728 }
729 // We don't allow flexible consumer for max resolution mode.
730 if (isInMaximumResolutionStreamConfigurationMap) {
731 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
732 return OK;
733 }
734 if (isInDefaultStreamConfigurationMap || (flexibleConsumer && width < ROUNDING_WIDTH_CAP)) {
735 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
736 return OK;
737 }
738 return BAD_VALUE;
739 }
740
741 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
742 // are valid / err out.
743 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
744 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
745 return BAD_VALUE;
746 }
747
748 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
749 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
750 return BAD_VALUE;
751 }
752 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
753 return OK;
754}
755
756bool SessionConfigurationUtils::isUltraHighResolutionSensor(const CameraMetadata &deviceInfo) {
757 camera_metadata_ro_entry_t entryCap;
758 entryCap = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
759 // Go through the capabilities and check if it has
760 // ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
761 for (size_t i = 0; i < entryCap.count; ++i) {
762 uint8_t capability = entryCap.data.u8[i];
763 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) {
764 return true;
765 }
766 }
767 return false;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800768}
769
Shuzhen Wang83bff122020-11-20 15:51:39 -0800770bool SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
771 hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
772 const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
773 if (streamConfigV37.multiResolutionInputImage) {
774 // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
775 return false;
776 }
777
778 streamConfigV34.streams.resize(streamConfigV37.streams.size());
779 for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
780 if (streamConfigV37.streams[i].groupId != -1) {
781 // ICameraDevice older than 3.7 doesn't support multi-resolution output
782 // image
783 return false;
784 }
785 streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
786 }
787 streamConfigV34.operationMode = streamConfigV37.operationMode;
788 streamConfigV34.sessionParams = streamConfigV37.sessionParams;
789
790 return true;
791}
792
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700793bool SessionConfigurationUtils::targetPerfClassPrimaryCamera(
794 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
795 int targetSdkVersion) {
796 bool isPerfClassPrimaryCamera =
797 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
798 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
799}
800
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800801} // namespace camera3
802} // namespace android