blob: 5afdfb9d46a3df13d5eb08a7b83bfb624795ae34 [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 */
16#include "SessionConfigurationUtils.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000017#include "../api2/DepthCompositeStream.h"
18#include "../api2/HeicCompositeStream.h"
19#include "common/CameraDeviceBase.h"
20#include "../CameraService.h"
21#include "device3/Camera3Device.h"
22#include "device3/Camera3OutputStream.h"
23
Colin Crossb8a9dbb2020-08-27 04:12:26 +000024using android::camera3::OutputStreamInfo;
25using android::camera3::OutputStreamInfo;
26using android::hardware::camera2::ICameraDeviceUser;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080027using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080028
29namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080030namespace camera3 {
31
32void StreamConfiguration::getStreamConfigurations(
33 const CameraMetadata &staticInfo, int configuration,
34 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
35 if (scm == nullptr) {
36 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
37 return;
38 }
39 const int STREAM_FORMAT_OFFSET = 0;
40 const int STREAM_WIDTH_OFFSET = 1;
41 const int STREAM_HEIGHT_OFFSET = 2;
42 const int STREAM_IS_INPUT_OFFSET = 3;
43
44 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
45 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
46 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
47 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
48 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
49 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
50 StreamConfiguration sc = {format, width, height, isInput};
51 (*scm)[format].push_back(sc);
52 }
53}
54
55void StreamConfiguration::getStreamConfigurations(
56 const CameraMetadata &staticInfo, bool maxRes,
57 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
58 int32_t scalerKey =
59 SessionConfigurationUtils::getAppropriateModeTag(
60 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
61
62 int32_t depthKey =
63 SessionConfigurationUtils::getAppropriateModeTag(
64 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
65
66 int32_t dynamicDepthKey =
67 SessionConfigurationUtils::getAppropriateModeTag(
68 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
69
70 int32_t heicKey =
71 SessionConfigurationUtils::getAppropriateModeTag(
72 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
73
74 getStreamConfigurations(staticInfo, scalerKey, scm);
75 getStreamConfigurations(staticInfo, depthKey, scm);
76 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
77 getStreamConfigurations(staticInfo, heicKey, scm);
78}
79
80int32_t SessionConfigurationUtils::getAppropriateModeTag(int32_t defaultTag, bool maxResolution) {
81 if (!maxResolution) {
82 return defaultTag;
83 }
84 switch (defaultTag) {
85 case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS:
86 return ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
87 case ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS:
88 return ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
89 case ANDROID_SCALER_AVAILABLE_STALL_DURATIONS:
90 return ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION;
91 case ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:
92 return ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
93 case ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:
94 return ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
95 case ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:
96 return ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS;
97 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:
98 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
99 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:
100 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
101 case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:
102 return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS;
103 case ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:
104 return ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
105 case ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:
106 return ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
107 case ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS:
108 return ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS;
109 case ANDROID_SENSOR_OPAQUE_RAW_SIZE:
110 return ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION;
111 case ANDROID_LENS_INTRINSIC_CALIBRATION:
112 return ANDROID_LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION;
113 case ANDROID_LENS_DISTORTION:
114 return ANDROID_LENS_DISTORTION_MAXIMUM_RESOLUTION;
115 default:
116 ALOGE("%s: Tag %d doesn't have a maximum resolution counterpart", __FUNCTION__,
117 defaultTag);
118 return -1;
119 }
120 return -1;
121}
122
123
124StreamConfigurationPair
125SessionConfigurationUtils::getStreamConfigurationPair(const CameraMetadata &staticInfo) {
126 camera3::StreamConfigurationPair streamConfigurationPair;
127 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
128 &streamConfigurationPair.mDefaultStreamConfigurationMap);
129 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
130 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
131 return streamConfigurationPair;
132}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800133
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000134int64_t SessionConfigurationUtils::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
135 int64_t d0 = x0 - x1;
136 int64_t d1 = y0 - y1;
137 return d0 * d0 + d1 * d1;
138}
139
140bool SessionConfigurationUtils::roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800141 int32_t format, android_dataspace dataSpace,
142 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
143 /*out*/int32_t* outHeight) {
144 const int32_t depthSizesTag =
145 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
146 maxResolution);
147 const int32_t scalerSizesTag =
148 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
149 const int32_t heicSizesTag =
150 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000151
152 camera_metadata_ro_entry streamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800153 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000154 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800155 info.find(heicSizesTag) :
156 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000157
158 int32_t bestWidth = -1;
159 int32_t bestHeight = -1;
160
161 // Iterate through listed stream configurations and find the one with the smallest euclidean
162 // distance from the given dimensions for the given format.
163 for (size_t i = 0; i < streamConfigs.count; i += 4) {
164 int32_t fmt = streamConfigs.data.i32[i];
165 int32_t w = streamConfigs.data.i32[i + 1];
166 int32_t h = streamConfigs.data.i32[i + 2];
167
168 // Ignore input/output type for now
169 if (fmt == format) {
170 if (w == width && h == height) {
171 bestWidth = width;
172 bestHeight = height;
173 break;
174 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
175 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
176 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
177 height))) {
178 bestWidth = w;
179 bestHeight = h;
180 }
181 }
182 }
183
184 if (bestWidth == -1) {
185 // Return false if no configurations for this format were listed
186 return false;
187 }
188
189 // Set the outputs to the closet width/height
190 if (outWidth != NULL) {
191 *outWidth = bestWidth;
192 }
193 if (outHeight != NULL) {
194 *outHeight = bestHeight;
195 }
196
197 // Return true if at least one configuration for this format was listed
198 return true;
199}
200
201bool SessionConfigurationUtils::isPublicFormat(int32_t format)
202{
203 switch(format) {
204 case HAL_PIXEL_FORMAT_RGBA_8888:
205 case HAL_PIXEL_FORMAT_RGBX_8888:
206 case HAL_PIXEL_FORMAT_RGB_888:
207 case HAL_PIXEL_FORMAT_RGB_565:
208 case HAL_PIXEL_FORMAT_BGRA_8888:
209 case HAL_PIXEL_FORMAT_YV12:
210 case HAL_PIXEL_FORMAT_Y8:
211 case HAL_PIXEL_FORMAT_Y16:
212 case HAL_PIXEL_FORMAT_RAW16:
213 case HAL_PIXEL_FORMAT_RAW10:
214 case HAL_PIXEL_FORMAT_RAW12:
215 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
216 case HAL_PIXEL_FORMAT_BLOB:
217 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
218 case HAL_PIXEL_FORMAT_YCbCr_420_888:
219 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
220 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
221 case HAL_PIXEL_FORMAT_YCbCr_422_I:
222 return true;
223 default:
224 return false;
225 }
226}
227
228binder::Status SessionConfigurationUtils::createSurfaceFromGbp(
229 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
230 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800231 const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
232 const std::vector<int32_t> &sensorPixelModesUsed){
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000233 // bufferProducer must be non-null
234 if (gbp == nullptr) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800235 String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000236 ALOGW("%s: %s", __FUNCTION__, msg.string());
237 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
238 }
239 // HACK b/10949105
240 // Query consumer usage bits to set async operation mode for
241 // GLConsumer using controlledByApp parameter.
242 bool useAsync = false;
243 uint64_t consumerUsage = 0;
244 status_t err;
245 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
246 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800247 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000248 ALOGE("%s: %s", __FUNCTION__, msg.string());
249 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
250 }
251 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
252 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800253 "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000254 useAsync = true;
255 }
256
257 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
258 GRALLOC_USAGE_RENDERSCRIPT;
259 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
260 GraphicBuffer::USAGE_HW_TEXTURE |
261 GraphicBuffer::USAGE_HW_COMPOSER;
262 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
263 (consumerUsage & allowedFlags) != 0;
264
265 surface = new Surface(gbp, useAsync);
266 ANativeWindow *anw = surface.get();
267
268 int width, height, format;
269 android_dataspace dataSpace;
270 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
271 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800272 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000273 ALOGE("%s: %s", __FUNCTION__, msg.string());
274 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
275 }
276 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
277 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800278 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000279 ALOGE("%s: %s", __FUNCTION__, msg.string());
280 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
281 }
282 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
283 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800284 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000285 ALOGE("%s: %s", __FUNCTION__, msg.string());
286 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
287 }
288 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
289 reinterpret_cast<int*>(&dataSpace))) != OK) {
290 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %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
296 // FIXME: remove this override since the default format should be
297 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
298 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
299 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
300 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
301 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800302 __FUNCTION__, logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000303 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
304 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800305 std::unordered_set<int32_t> overriddenSensorPixelModes;
306 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
307 physicalCameraMetadata, flexibleConsumer, &overriddenSensorPixelModes) != OK) {
308 String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
309 "format %#x are not valid",logicalCameraId.string(), format);
310 ALOGE("%s: %s", __FUNCTION__, msg.string());
311 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
312 }
313 bool foundInMaxRes = false;
314 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
315 overriddenSensorPixelModes.end()) {
316 // we can use the default stream configuration map
317 foundInMaxRes = true;
318 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000319 // Round dimensions to the nearest dimensions available for this format
320 if (flexibleConsumer && isPublicFormat(format) &&
321 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800322 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
323 /*out*/&height)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000324 String8 msg = String8::format("Camera %s: No supported stream configurations with "
325 "format %#x defined, failed to create output stream",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800326 logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000327 ALOGE("%s: %s", __FUNCTION__, msg.string());
328 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
329 }
330
331 if (!isStreamInfoValid) {
332 streamInfo.width = width;
333 streamInfo.height = height;
334 streamInfo.format = format;
335 streamInfo.dataSpace = dataSpace;
336 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800337 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000338 return binder::Status::ok();
339 }
340 if (width != streamInfo.width) {
341 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800342 logicalCameraId.string(), width, streamInfo.width);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000343 ALOGE("%s: %s", __FUNCTION__, msg.string());
344 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
345 }
346 if (height != streamInfo.height) {
347 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800348 logicalCameraId.string(), height, streamInfo.height);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000349 ALOGE("%s: %s", __FUNCTION__, msg.string());
350 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
351 }
352 if (format != streamInfo.format) {
353 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800354 logicalCameraId.string(), format, streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000355 ALOGE("%s: %s", __FUNCTION__, msg.string());
356 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
357 }
358 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
359 if (dataSpace != streamInfo.dataSpace) {
360 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800361 logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
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 //At the native side, there isn't a way to check whether 2 surfaces come from the same
366 //surface class type. Use usage flag to approximate the comparison.
367 if (consumerUsage != streamInfo.consumerUsage) {
368 String8 msg = String8::format(
369 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800370 logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000371 ALOGE("%s: %s", __FUNCTION__, msg.string());
372 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
373 }
374 }
375 return binder::Status::ok();
376}
377
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000378void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700379 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800380 int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000381 if (stream == nullptr) {
382 return;
383 }
384
Shuzhen Wang83bff122020-11-20 15:51:39 -0800385 stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
386 stream->v3_4.v3_2.width = streamInfo.width;
387 stream->v3_4.v3_2.height = streamInfo.height;
388 stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000389 auto u = streamInfo.consumerUsage;
390 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800391 stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
392 stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
393 stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
394 stream->v3_4.v3_2.id = -1; // Invalid stream id
395 stream->v3_4.physicalCameraId = std::string(physicalId.string());
396 stream->v3_4.bufferSize = 0;
397 stream->groupId = groupId;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800398 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
399 size_t idx = 0;
400 for (auto mode : streamInfo.sensorPixelModesUsed) {
401 stream->sensorPixelModesUsed[idx++] =
402 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
403 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000404}
405
406binder::Status SessionConfigurationUtils::checkPhysicalCameraId(
407 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
408 const String8 &logicalCameraId) {
409 if (physicalCameraId.size() == 0) {
410 return binder::Status::ok();
411 }
412 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
413 physicalCameraId.string()) == physicalCameraIds.end()) {
414 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
415 logicalCameraId.string(), physicalCameraId.string());
416 ALOGE("%s: %s", __FUNCTION__, msg.string());
417 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
418 }
419 return binder::Status::ok();
420}
421
422binder::Status SessionConfigurationUtils::checkSurfaceType(size_t numBufferProducers,
423 bool deferredConsumer, int surfaceType) {
424 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
425 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
426 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
427 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
428 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
429 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
430 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
431 }
432
433 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
434 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
435
436 if (deferredConsumer && !validSurfaceType) {
437 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
438 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
439 }
440
441 return binder::Status::ok();
442}
443
444binder::Status SessionConfigurationUtils::checkOperatingMode(int operatingMode,
445 const CameraMetadata &staticInfo, const String8 &cameraId) {
446 if (operatingMode < 0) {
447 String8 msg = String8::format(
448 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
449 ALOGE("%s: %s", __FUNCTION__, msg.string());
450 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
451 msg.string());
452 }
453
454 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
455 if (isConstrainedHighSpeed) {
456 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
457 bool isConstrainedHighSpeedSupported = false;
458 for(size_t i = 0; i < entry.count; ++i) {
459 uint8_t capability = entry.data.u8[i];
460 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
461 isConstrainedHighSpeedSupported = true;
462 break;
463 }
464 }
465 if (!isConstrainedHighSpeedSupported) {
466 String8 msg = String8::format(
467 "Camera %s: Try to create a constrained high speed configuration on a device"
468 " that doesn't support it.", cameraId.string());
469 ALOGE("%s: %s", __FUNCTION__, msg.string());
470 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
471 msg.string());
472 }
473 }
474
475 return binder::Status::ok();
476}
477
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800478binder::Status
479SessionConfigurationUtils::convertToHALStreamCombination(
480 const SessionConfiguration& sessionConfiguration,
481 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
482 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800483 hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration, bool *earlyExit) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000484
485 auto operatingMode = sessionConfiguration.getOperatingMode();
486 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
487 if (!res.isOk()) {
488 return res;
489 }
490
491 if (earlyExit == nullptr) {
492 String8 msg("earlyExit nullptr");
493 ALOGE("%s: %s", __FUNCTION__, msg.string());
494 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
495 }
496 *earlyExit = false;
497 auto ret = Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700498 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000499 /*out*/ &streamConfiguration.operationMode);
500 if (ret != OK) {
501 String8 msg = String8::format(
502 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
503 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
504 ALOGE("%s: %s", __FUNCTION__, msg.string());
505 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
506 msg.string());
507 }
508
509 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
510 (sessionConfiguration.getInputHeight() > 0) &&
511 (sessionConfiguration.getInputFormat() > 0);
512 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
513 size_t streamCount = outputConfigs.size();
514 streamCount = isInputValid ? streamCount + 1 : streamCount;
515 streamConfiguration.streams.resize(streamCount);
516 size_t streamIdx = 0;
517 if (isInputValid) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800518 hardware::hidl_vec<CameraMetadataEnumAndroidSensorPixelMode> defaultSensorPixelModes;
519 defaultSensorPixelModes.resize(1);
520 defaultSensorPixelModes[0] =
521 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
522 ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800523 streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000524 hardware::camera::device::V3_2::StreamType::INPUT,
525 static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
526 static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
527 Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
528 /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
529 hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800530 /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
Shuzhen Wang83bff122020-11-20 15:51:39 -0800531 streamConfiguration.multiResolutionInputImage =
532 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000533 }
534
535 for (const auto &it : outputConfigs) {
536 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
537 it.getGraphicBufferProducers();
538 bool deferredConsumer = it.isDeferred();
539 String8 physicalCameraId = String8(it.getPhysicalCameraId());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800540
541 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
542 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId);
543 const CameraMetadata &metadataChosen =
544 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
545
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000546 size_t numBufferProducers = bufferProducers.size();
547 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800548 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000549 OutputStreamInfo streamInfo;
550
551 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
552 if (!res.isOk()) {
553 return res;
554 }
555 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
556 logicalCameraId);
557 if (!res.isOk()) {
558 return res;
559 }
560
561 if (deferredConsumer) {
562 streamInfo.width = it.getWidth();
563 streamInfo.height = it.getHeight();
564 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
565 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
566 auto surfaceType = it.getSurfaceType();
567 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
568 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
569 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
570 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800571 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
572 streamInfo.format, streamInfo.width,
573 streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
574 &streamInfo.sensorPixelModesUsed) != OK) {
575 ALOGE("%s: Deferred surface sensor pixel modes not valid",
576 __FUNCTION__);
577 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
578 "Deferred surface sensor pixel modes not valid");
579 }
Shuzhen Wang83bff122020-11-20 15:51:39 -0800580 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000581 &streamConfiguration.streams[streamIdx++]);
582 isStreamInfoValid = true;
583
584 if (numBufferProducers == 0) {
585 continue;
586 }
587 }
588
589 for (auto& bufferProducer : bufferProducers) {
590 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000591 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800592 logicalCameraId, metadataChosen, sensorPixelModesUsed);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000593
594 if (!res.isOk())
595 return res;
596
597 if (!isStreamInfoValid) {
598 bool isDepthCompositeStream =
599 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
600 bool isHeicCompositeStream =
601 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
602 if (isDepthCompositeStream || isHeicCompositeStream) {
603 // We need to take in to account that composite streams can have
604 // additional internal camera streams.
605 std::vector<OutputStreamInfo> compositeStreams;
606 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800607 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000608 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
609 deviceInfo, &compositeStreams);
610 } else {
611 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
612 deviceInfo, &compositeStreams);
613 }
614 if (ret != OK) {
615 String8 msg = String8::format(
616 "Camera %s: Failed adding composite streams: %s (%d)",
617 logicalCameraId.string(), strerror(-ret), ret);
618 ALOGE("%s: %s", __FUNCTION__, msg.string());
619 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
620 }
621
622 if (compositeStreams.size() == 0) {
623 // No internal streams means composite stream not
624 // supported.
625 *earlyExit = true;
626 return binder::Status::ok();
627 } else if (compositeStreams.size() > 1) {
628 streamCount += compositeStreams.size() - 1;
629 streamConfiguration.streams.resize(streamCount);
630 }
631
632 for (const auto& compositeStream : compositeStreams) {
633 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700634 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800635 physicalCameraId, groupId,
636 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000637 }
638 } else {
639 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700640 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800641 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000642 }
643 isStreamInfoValid = true;
644 }
645 }
646 }
647 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800648}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000649
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800650static bool inStreamConfigurationMap(int format, int width, int height,
651 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
652 auto scs = sm.find(format);
653 if (scs == sm.end()) {
654 return false;
655 }
656 for (auto &sc : scs->second) {
657 if (sc.width == width && sc.height == height && sc.isInput == 0) {
658 return true;
659 }
660 }
661 return false;
662}
663
664static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
665 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
666}
667
668status_t SessionConfigurationUtils::checkAndOverrideSensorPixelModesUsed(
669 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
670 const CameraMetadata &staticInfo, bool flexibleConsumer,
671 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700672
673 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
674 convertToSet(sensorPixelModesUsed);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800675 if (!isUltraHighResolutionSensor(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700676 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
677 sensorPixelModesUsedSet.end()) {
678 // invalid value for non ultra high res sensors
679 return BAD_VALUE;
680 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800681 overriddenSensorPixelModesUsed->clear();
682 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
683 return OK;
684 }
685
686 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700687
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800688 bool isInDefaultStreamConfigurationMap =
689 inStreamConfigurationMap(format, width, height,
690 streamConfigurationPair.mDefaultStreamConfigurationMap);
691
692 bool isInMaximumResolutionStreamConfigurationMap =
693 inStreamConfigurationMap(format, width, height,
694 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
695
696 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
697 // size + format of the OutputConfiguration is found exclusively in 1.
698 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
699 // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
700 // compatibility.
701 if (sensorPixelModesUsedSet.size() == 0) {
702 // Ambiguous case, default to only 'DEFAULT' mode.
703 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
704 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
705 return OK;
706 }
707 // We don't allow flexible consumer for max resolution mode.
708 if (isInMaximumResolutionStreamConfigurationMap) {
709 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
710 return OK;
711 }
712 if (isInDefaultStreamConfigurationMap || (flexibleConsumer && width < ROUNDING_WIDTH_CAP)) {
713 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
714 return OK;
715 }
716 return BAD_VALUE;
717 }
718
719 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
720 // are valid / err out.
721 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
722 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
723 return BAD_VALUE;
724 }
725
726 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
727 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
728 return BAD_VALUE;
729 }
730 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
731 return OK;
732}
733
734bool SessionConfigurationUtils::isUltraHighResolutionSensor(const CameraMetadata &deviceInfo) {
735 camera_metadata_ro_entry_t entryCap;
736 entryCap = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
737 // Go through the capabilities and check if it has
738 // ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
739 for (size_t i = 0; i < entryCap.count; ++i) {
740 uint8_t capability = entryCap.data.u8[i];
741 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) {
742 return true;
743 }
744 }
745 return false;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800746}
747
Shuzhen Wang83bff122020-11-20 15:51:39 -0800748bool SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
749 hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
750 const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
751 if (streamConfigV37.multiResolutionInputImage) {
752 // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
753 return false;
754 }
755
756 streamConfigV34.streams.resize(streamConfigV37.streams.size());
757 for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
758 if (streamConfigV37.streams[i].groupId != -1) {
759 // ICameraDevice older than 3.7 doesn't support multi-resolution output
760 // image
761 return false;
762 }
763 streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
764 }
765 streamConfigV34.operationMode = streamConfigV37.operationMode;
766 streamConfigV34.sessionParams = streamConfigV37.sessionParams;
767
768 return true;
769}
770
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800771} // namespace camera3
772} // namespace android