blob: 8f42a8514814941de17cf2541e296848d4c64670 [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
24// Convenience methods for constructing binder::Status objects for error returns
25
26#define STATUS_ERROR(errorCode, errorString) \
27 binder::Status::fromServiceSpecificError(errorCode, \
28 String8::format("%s:%d: %s", __FUNCTION__, __LINE__, errorString))
29
30#define STATUS_ERROR_FMT(errorCode, errorString, ...) \
31 binder::Status::fromServiceSpecificError(errorCode, \
32 String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, \
33 __VA_ARGS__))
34
35using android::camera3::OutputStreamInfo;
36using android::camera3::OutputStreamInfo;
37using android::hardware::camera2::ICameraDeviceUser;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080038
39namespace android {
40
Colin Crossb8a9dbb2020-08-27 04:12:26 +000041int64_t SessionConfigurationUtils::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
42 int64_t d0 = x0 - x1;
43 int64_t d1 = y0 - y1;
44 return d0 * d0 + d1 * d1;
45}
46
47bool SessionConfigurationUtils::roundBufferDimensionNearest(int32_t width, int32_t height,
48 int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
49 /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
50
51 camera_metadata_ro_entry streamConfigs =
52 (dataSpace == HAL_DATASPACE_DEPTH) ?
53 info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
54 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
55 info.find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS) :
56 info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
57
58 int32_t bestWidth = -1;
59 int32_t bestHeight = -1;
60
61 // Iterate through listed stream configurations and find the one with the smallest euclidean
62 // distance from the given dimensions for the given format.
63 for (size_t i = 0; i < streamConfigs.count; i += 4) {
64 int32_t fmt = streamConfigs.data.i32[i];
65 int32_t w = streamConfigs.data.i32[i + 1];
66 int32_t h = streamConfigs.data.i32[i + 2];
67
68 // Ignore input/output type for now
69 if (fmt == format) {
70 if (w == width && h == height) {
71 bestWidth = width;
72 bestHeight = height;
73 break;
74 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
75 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
76 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
77 height))) {
78 bestWidth = w;
79 bestHeight = h;
80 }
81 }
82 }
83
84 if (bestWidth == -1) {
85 // Return false if no configurations for this format were listed
86 return false;
87 }
88
89 // Set the outputs to the closet width/height
90 if (outWidth != NULL) {
91 *outWidth = bestWidth;
92 }
93 if (outHeight != NULL) {
94 *outHeight = bestHeight;
95 }
96
97 // Return true if at least one configuration for this format was listed
98 return true;
99}
100
101bool SessionConfigurationUtils::isPublicFormat(int32_t format)
102{
103 switch(format) {
104 case HAL_PIXEL_FORMAT_RGBA_8888:
105 case HAL_PIXEL_FORMAT_RGBX_8888:
106 case HAL_PIXEL_FORMAT_RGB_888:
107 case HAL_PIXEL_FORMAT_RGB_565:
108 case HAL_PIXEL_FORMAT_BGRA_8888:
109 case HAL_PIXEL_FORMAT_YV12:
110 case HAL_PIXEL_FORMAT_Y8:
111 case HAL_PIXEL_FORMAT_Y16:
112 case HAL_PIXEL_FORMAT_RAW16:
113 case HAL_PIXEL_FORMAT_RAW10:
114 case HAL_PIXEL_FORMAT_RAW12:
115 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
116 case HAL_PIXEL_FORMAT_BLOB:
117 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
118 case HAL_PIXEL_FORMAT_YCbCr_420_888:
119 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
120 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
121 case HAL_PIXEL_FORMAT_YCbCr_422_I:
122 return true;
123 default:
124 return false;
125 }
126}
127
128binder::Status SessionConfigurationUtils::createSurfaceFromGbp(
129 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
130 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
131 const String8 &cameraId, const CameraMetadata &physicalCameraMetadata) {
132
133 // bufferProducer must be non-null
134 if (gbp == nullptr) {
135 String8 msg = String8::format("Camera %s: Surface is NULL", cameraId.string());
136 ALOGW("%s: %s", __FUNCTION__, msg.string());
137 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
138 }
139 // HACK b/10949105
140 // Query consumer usage bits to set async operation mode for
141 // GLConsumer using controlledByApp parameter.
142 bool useAsync = false;
143 uint64_t consumerUsage = 0;
144 status_t err;
145 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
146 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
147 cameraId.string(), strerror(-err), err);
148 ALOGE("%s: %s", __FUNCTION__, msg.string());
149 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
150 }
151 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
152 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
153 "stream", __FUNCTION__, cameraId.string(), consumerUsage);
154 useAsync = true;
155 }
156
157 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
158 GRALLOC_USAGE_RENDERSCRIPT;
159 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
160 GraphicBuffer::USAGE_HW_TEXTURE |
161 GraphicBuffer::USAGE_HW_COMPOSER;
162 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
163 (consumerUsage & allowedFlags) != 0;
164
165 surface = new Surface(gbp, useAsync);
166 ANativeWindow *anw = surface.get();
167
168 int width, height, format;
169 android_dataspace dataSpace;
170 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
171 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
172 cameraId.string(), strerror(-err), err);
173 ALOGE("%s: %s", __FUNCTION__, msg.string());
174 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
175 }
176 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
177 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
178 cameraId.string(), strerror(-err), err);
179 ALOGE("%s: %s", __FUNCTION__, msg.string());
180 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
181 }
182 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
183 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
184 cameraId.string(), strerror(-err), err);
185 ALOGE("%s: %s", __FUNCTION__, msg.string());
186 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
187 }
188 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
189 reinterpret_cast<int*>(&dataSpace))) != OK) {
190 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
191 cameraId.string(), strerror(-err), err);
192 ALOGE("%s: %s", __FUNCTION__, msg.string());
193 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
194 }
195
196 // FIXME: remove this override since the default format should be
197 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
198 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
199 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
200 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
201 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
202 __FUNCTION__, cameraId.string(), format);
203 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
204 }
205 // Round dimensions to the nearest dimensions available for this format
206 if (flexibleConsumer && isPublicFormat(format) &&
207 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
208 format, dataSpace, physicalCameraMetadata, /*out*/&width, /*out*/&height)) {
209 String8 msg = String8::format("Camera %s: No supported stream configurations with "
210 "format %#x defined, failed to create output stream",
211 cameraId.string(), format);
212 ALOGE("%s: %s", __FUNCTION__, msg.string());
213 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
214 }
215
216 if (!isStreamInfoValid) {
217 streamInfo.width = width;
218 streamInfo.height = height;
219 streamInfo.format = format;
220 streamInfo.dataSpace = dataSpace;
221 streamInfo.consumerUsage = consumerUsage;
222 return binder::Status::ok();
223 }
224 if (width != streamInfo.width) {
225 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
226 cameraId.string(), width, streamInfo.width);
227 ALOGE("%s: %s", __FUNCTION__, msg.string());
228 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
229 }
230 if (height != streamInfo.height) {
231 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
232 cameraId.string(), height, streamInfo.height);
233 ALOGE("%s: %s", __FUNCTION__, msg.string());
234 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
235 }
236 if (format != streamInfo.format) {
237 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
238 cameraId.string(), format, streamInfo.format);
239 ALOGE("%s: %s", __FUNCTION__, msg.string());
240 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
241 }
242 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
243 if (dataSpace != streamInfo.dataSpace) {
244 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
245 cameraId.string(), dataSpace, streamInfo.dataSpace);
246 ALOGE("%s: %s", __FUNCTION__, msg.string());
247 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
248 }
249 //At the native side, there isn't a way to check whether 2 surfaces come from the same
250 //surface class type. Use usage flag to approximate the comparison.
251 if (consumerUsage != streamInfo.consumerUsage) {
252 String8 msg = String8::format(
253 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
254 cameraId.string(), consumerUsage, streamInfo.consumerUsage);
255 ALOGE("%s: %s", __FUNCTION__, msg.string());
256 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
257 }
258 }
259 return binder::Status::ok();
260}
261
262
263void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700264 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800265 int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000266 if (stream == nullptr) {
267 return;
268 }
269
Shuzhen Wang83bff122020-11-20 15:51:39 -0800270 stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
271 stream->v3_4.v3_2.width = streamInfo.width;
272 stream->v3_4.v3_2.height = streamInfo.height;
273 stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000274 auto u = streamInfo.consumerUsage;
275 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800276 stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
277 stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
278 stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
279 stream->v3_4.v3_2.id = -1; // Invalid stream id
280 stream->v3_4.physicalCameraId = std::string(physicalId.string());
281 stream->v3_4.bufferSize = 0;
282 stream->groupId = groupId;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000283}
284
285binder::Status SessionConfigurationUtils::checkPhysicalCameraId(
286 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
287 const String8 &logicalCameraId) {
288 if (physicalCameraId.size() == 0) {
289 return binder::Status::ok();
290 }
291 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
292 physicalCameraId.string()) == physicalCameraIds.end()) {
293 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
294 logicalCameraId.string(), physicalCameraId.string());
295 ALOGE("%s: %s", __FUNCTION__, msg.string());
296 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
297 }
298 return binder::Status::ok();
299}
300
301binder::Status SessionConfigurationUtils::checkSurfaceType(size_t numBufferProducers,
302 bool deferredConsumer, int surfaceType) {
303 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
304 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
305 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
306 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
307 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
308 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
309 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
310 }
311
312 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
313 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
314
315 if (deferredConsumer && !validSurfaceType) {
316 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
317 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
318 }
319
320 return binder::Status::ok();
321}
322
323binder::Status SessionConfigurationUtils::checkOperatingMode(int operatingMode,
324 const CameraMetadata &staticInfo, const String8 &cameraId) {
325 if (operatingMode < 0) {
326 String8 msg = String8::format(
327 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
328 ALOGE("%s: %s", __FUNCTION__, msg.string());
329 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
330 msg.string());
331 }
332
333 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
334 if (isConstrainedHighSpeed) {
335 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
336 bool isConstrainedHighSpeedSupported = false;
337 for(size_t i = 0; i < entry.count; ++i) {
338 uint8_t capability = entry.data.u8[i];
339 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
340 isConstrainedHighSpeedSupported = true;
341 break;
342 }
343 }
344 if (!isConstrainedHighSpeedSupported) {
345 String8 msg = String8::format(
346 "Camera %s: Try to create a constrained high speed configuration on a device"
347 " that doesn't support it.", cameraId.string());
348 ALOGE("%s: %s", __FUNCTION__, msg.string());
349 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
350 msg.string());
351 }
352 }
353
354 return binder::Status::ok();
355}
356
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800357binder::Status
358SessionConfigurationUtils::convertToHALStreamCombination(
359 const SessionConfiguration& sessionConfiguration,
360 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
361 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800362 hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration, bool *earlyExit) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000363
364 auto operatingMode = sessionConfiguration.getOperatingMode();
365 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
366 if (!res.isOk()) {
367 return res;
368 }
369
370 if (earlyExit == nullptr) {
371 String8 msg("earlyExit nullptr");
372 ALOGE("%s: %s", __FUNCTION__, msg.string());
373 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
374 }
375 *earlyExit = false;
376 auto ret = Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700377 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000378 /*out*/ &streamConfiguration.operationMode);
379 if (ret != OK) {
380 String8 msg = String8::format(
381 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
382 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
383 ALOGE("%s: %s", __FUNCTION__, msg.string());
384 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
385 msg.string());
386 }
387
388 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
389 (sessionConfiguration.getInputHeight() > 0) &&
390 (sessionConfiguration.getInputFormat() > 0);
391 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
392 size_t streamCount = outputConfigs.size();
393 streamCount = isInputValid ? streamCount + 1 : streamCount;
394 streamConfiguration.streams.resize(streamCount);
395 size_t streamIdx = 0;
396 if (isInputValid) {
Shuzhen Wang83bff122020-11-20 15:51:39 -0800397 streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000398 hardware::camera::device::V3_2::StreamType::INPUT,
399 static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
400 static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
401 Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
402 /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
403 hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
Shuzhen Wang83bff122020-11-20 15:51:39 -0800404 /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1};
405 streamConfiguration.multiResolutionInputImage =
406 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000407 }
408
409 for (const auto &it : outputConfigs) {
410 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
411 it.getGraphicBufferProducers();
412 bool deferredConsumer = it.isDeferred();
413 String8 physicalCameraId = String8(it.getPhysicalCameraId());
414 size_t numBufferProducers = bufferProducers.size();
415 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800416 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000417 OutputStreamInfo streamInfo;
418
419 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
420 if (!res.isOk()) {
421 return res;
422 }
423 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
424 logicalCameraId);
425 if (!res.isOk()) {
426 return res;
427 }
428
429 if (deferredConsumer) {
430 streamInfo.width = it.getWidth();
431 streamInfo.height = it.getHeight();
432 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
433 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
434 auto surfaceType = it.getSurfaceType();
435 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
436 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
437 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
438 }
Shuzhen Wang83bff122020-11-20 15:51:39 -0800439 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000440 &streamConfiguration.streams[streamIdx++]);
441 isStreamInfoValid = true;
442
443 if (numBufferProducers == 0) {
444 continue;
445 }
446 }
447
448 for (auto& bufferProducer : bufferProducers) {
449 sp<Surface> surface;
450 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId);
451 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
452 logicalCameraId,
453 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo );
454
455 if (!res.isOk())
456 return res;
457
458 if (!isStreamInfoValid) {
459 bool isDepthCompositeStream =
460 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
461 bool isHeicCompositeStream =
462 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
463 if (isDepthCompositeStream || isHeicCompositeStream) {
464 // We need to take in to account that composite streams can have
465 // additional internal camera streams.
466 std::vector<OutputStreamInfo> compositeStreams;
467 if (isDepthCompositeStream) {
468 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
469 deviceInfo, &compositeStreams);
470 } else {
471 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
472 deviceInfo, &compositeStreams);
473 }
474 if (ret != OK) {
475 String8 msg = String8::format(
476 "Camera %s: Failed adding composite streams: %s (%d)",
477 logicalCameraId.string(), strerror(-ret), ret);
478 ALOGE("%s: %s", __FUNCTION__, msg.string());
479 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
480 }
481
482 if (compositeStreams.size() == 0) {
483 // No internal streams means composite stream not
484 // supported.
485 *earlyExit = true;
486 return binder::Status::ok();
487 } else if (compositeStreams.size() > 1) {
488 streamCount += compositeStreams.size() - 1;
489 streamConfiguration.streams.resize(streamCount);
490 }
491
492 for (const auto& compositeStream : compositeStreams) {
493 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700494 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800495 physicalCameraId, groupId,
496 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000497 }
498 } else {
499 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700500 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800501 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000502 }
503 isStreamInfoValid = true;
504 }
505 }
506 }
507 return binder::Status::ok();
508
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800509}
510
Shuzhen Wang83bff122020-11-20 15:51:39 -0800511bool SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
512 hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
513 const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
514 if (streamConfigV37.multiResolutionInputImage) {
515 // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
516 return false;
517 }
518
519 streamConfigV34.streams.resize(streamConfigV37.streams.size());
520 for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
521 if (streamConfigV37.streams[i].groupId != -1) {
522 // ICameraDevice older than 3.7 doesn't support multi-resolution output
523 // image
524 return false;
525 }
526 streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
527 }
528 streamConfigV34.operationMode = streamConfigV37.operationMode;
529 streamConfigV34.sessionParams = streamConfigV37.sessionParams;
530
531 return true;
532}
533
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800534}// namespace android