diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 641816f1d4..c1efa5fef2 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -5549,6 +5549,73 @@ typedef enum acamera_metadata_tag {
ACAMERA_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS =
// int32[n*5]
ACAMERA_DEPTH_START + 5,
+ /**
+ *
The available dynamic depth dataspace stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).
+ *
+ * Type: int32[n*4] (acamera_metadata_enum_android_depth_available_dynamic_depth_stream_configurations_t)
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * These are output stream configurations for use with
+ * dataSpace DYNAMIC_DEPTH. The configurations are
+ * listed as (format, width, height, input?)
tuples.
+ * Only devices that support depth output for at least
+ * the HAL_PIXEL_FORMAT_Y16 dense depth map along with
+ * HAL_PIXEL_FORMAT_BLOB with the same size or size with
+ * the same aspect ratio can have dynamic depth dataspace
+ * stream configuration. ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE also
+ * needs to be set to FALSE.
+ *
+ * @see ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE
+ */
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS =
+ // int32[n*4] (acamera_metadata_enum_android_depth_available_dynamic_depth_stream_configurations_t)
+ ACAMERA_DEPTH_START + 6,
+ /**
+ * This lists the minimum frame duration for each
+ * format/size combination for dynamic depth output streams.
+ *
+ * Type: int64[4*n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * This should correspond to the frame duration when only that
+ * stream is active, with all processing (typically in android.*.mode)
+ * set to either OFF or FAST.
+ * When multiple streams are used in a request, the minimum frame
+ * duration will be max(individual stream min durations).
+ * The minimum frame duration of a stream (of a particular format, size)
+ * is the same regardless of whether the stream is input or output.
+ */
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS = // int64[4*n]
+ ACAMERA_DEPTH_START + 7,
+ /**
+ * This lists the maximum stall duration for each
+ * output format/size combination for dynamic depth streams.
+ *
+ * Type: int64[4*n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * A stall duration is how much extra time would get added
+ * to the normal minimum frame duration for a repeating request
+ * that has streams with non-zero stall.
+ * All dynamic depth output streams may have a nonzero stall
+ * duration.
+ */
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS = // int64[4*n]
+ ACAMERA_DEPTH_START + 8,
ACAMERA_DEPTH_END,
/**
@@ -8246,6 +8313,16 @@ typedef enum acamera_metadata_enum_acamera_depth_depth_is_exclusive {
} acamera_metadata_enum_android_depth_depth_is_exclusive_t;
+// ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_depth_available_dynamic_depth_stream_configurations {
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT
+ = 0,
+
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT
+ = 1,
+
+} acamera_metadata_enum_android_depth_available_dynamic_depth_stream_configurations_t;
+
// ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
typedef enum acamera_metadata_enum_acamera_logical_multi_camera_sensor_sync_type {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index a9cbe72926..cee4a84433 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -500,6 +500,248 @@ void CameraProviderManager::ProviderInfo::DeviceInfo3::queryPhysicalCameraIds()
}
}
+void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedSizes(
+ const CameraMetadata& ch, uint32_t tag, android_pixel_format_t format,
+ std::vector> *sizes/*out*/) {
+ if (sizes == nullptr) {
+ return;
+ }
+
+ auto scalerDims = ch.find(tag);
+ if (scalerDims.count > 0) {
+ // Scaler entry contains 4 elements (format, width, height, type)
+ for (size_t i = 0; i < scalerDims.count; i += 4) {
+ if ((scalerDims.data.i32[i] == format) &&
+ (scalerDims.data.i32[i+3] ==
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT)) {
+ sizes->push_back(std::make_tuple(scalerDims.data.i32[i+1],
+ scalerDims.data.i32[i+2]));
+ }
+ }
+ }
+}
+
+void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedDurations(
+ const CameraMetadata& ch, uint32_t tag, android_pixel_format_t format,
+ const std::vector>& sizes,
+ std::vector *durations/*out*/) {
+ if (durations == nullptr) {
+ return;
+ }
+
+ auto availableDurations = ch.find(tag);
+ if (availableDurations.count > 0) {
+ // Duration entry contains 4 elements (format, width, height, duration)
+ for (size_t i = 0; i < availableDurations.count; i += 4) {
+ for (const auto& size : sizes) {
+ int64_t width = std::get<0>(size);
+ int64_t height = std::get<1>(size);
+ if ((availableDurations.data.i64[i] == format) &&
+ (availableDurations.data.i64[i+1] == width) &&
+ (availableDurations.data.i64[i+2] == height)) {
+ durations->push_back(availableDurations.data.i64[i+3]);
+ }
+ }
+ }
+ }
+}
+void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedDynamicDepthDurations(
+ const std::vector& depthDurations, const std::vector& blobDurations,
+ std::vector *dynamicDepthDurations /*out*/) {
+ if ((dynamicDepthDurations == nullptr) || (depthDurations.size() != blobDurations.size())) {
+ return;
+ }
+
+ // Unfortunately there is no direct way to calculate the dynamic depth stream duration.
+ // Processing time on camera service side can vary greatly depending on multiple
+ // variables which are not under our control. Make a guesstimate by taking the maximum
+ // corresponding duration value from depth and blob.
+ auto depthDuration = depthDurations.begin();
+ auto blobDuration = blobDurations.begin();
+ dynamicDepthDurations->reserve(depthDurations.size());
+ while ((depthDuration != depthDurations.end()) && (blobDuration != blobDurations.end())) {
+ dynamicDepthDurations->push_back(std::max(*depthDuration, *blobDuration));
+ depthDuration++; blobDuration++;
+ }
+}
+
+void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedDynamicDepthSizes(
+ const std::vector>& blobSizes,
+ const std::vector>& depthSizes,
+ std::vector> *dynamicDepthSizes /*out*/,
+ std::vector> *internalDepthSizes /*out*/) {
+ if (dynamicDepthSizes == nullptr || internalDepthSizes == nullptr) {
+ return;
+ }
+
+ // The dynamic depth spec. does not mention how close the AR ratio should be.
+ // Try using something appropriate.
+ float ARTolerance = .01f;
+
+ //TODO: Remove this before merging! This is for testing purposes only
+ ARTolerance = 10.f;
+
+ for (const auto& blobSize : blobSizes) {
+ float jpegAR = static_cast (std::get<0>(blobSize)) /
+ static_cast(std::get<1>(blobSize));
+ bool found = false;
+ for (const auto& depthSize : depthSizes) {
+ if (depthSize == blobSize) {
+ internalDepthSizes->push_back(depthSize);
+ found = true;
+ break;
+ } else {
+ float depthAR = static_cast (std::get<0>(depthSize)) /
+ static_cast(std::get<1>(depthSize));
+ if (std::fabs(jpegAR - depthAR) <= ARTolerance) {
+ internalDepthSizes->push_back(depthSize);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ dynamicDepthSizes->push_back(blobSize);
+ }
+ }
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addDynamicDepthTags() {
+ uint32_t depthExclTag = ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE;
+ uint32_t depthSizesTag = ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS;
+ auto& c = mCameraCharacteristics;
+ std::vector> supportedBlobSizes, supportedDepthSizes,
+ supportedDynamicDepthSizes, internalDepthSizes;
+ auto chTags = c.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+ if (chTags.count == 0) {
+ ALOGE("%s: Supported camera characteristics is empty!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ bool isDepthExclusivePresent = std::find(chTags.data.i32, chTags.data.i32 + chTags.count,
+ depthExclTag) != (chTags.data.i32 + chTags.count);
+ bool isDepthSizePresent = std::find(chTags.data.i32, chTags.data.i32 + chTags.count,
+ depthExclTag) != (chTags.data.i32 + chTags.count);
+ if (!(isDepthExclusivePresent && isDepthSizePresent)) {
+ // No depth support, nothing more to do.
+ return OK;
+ }
+
+ auto depthExclusiveEntry = c.find(depthExclTag);
+ if (depthExclusiveEntry.count > 0) {
+ if (depthExclusiveEntry.data.u8[0] != ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE) {
+ // Depth support is exclusive, nothing more to do.
+ return OK;
+ }
+ } else {
+ ALOGE("%s: Advertised depth exclusive tag but value is not present!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ getSupportedSizes(c, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, HAL_PIXEL_FORMAT_BLOB,
+ &supportedBlobSizes);
+ getSupportedSizes(c, depthSizesTag, HAL_PIXEL_FORMAT_Y16, &supportedDepthSizes);
+ if (supportedBlobSizes.empty() || supportedDepthSizes.empty()) {
+ // Nothing to do in this case.
+ return OK;
+ }
+
+ getSupportedDynamicDepthSizes(supportedBlobSizes, supportedDepthSizes,
+ &supportedDynamicDepthSizes, &internalDepthSizes);
+ if (supportedDynamicDepthSizes.empty()) {
+ ALOGE("%s: No dynamic depth size matched!", __func__);
+ // Nothing more to do.
+ return OK;
+ }
+
+ std::vector dynamicDepthEntries;
+ for (const auto& it : supportedDynamicDepthSizes) {
+ int32_t entry[4] = {HAL_PIXEL_FORMAT_BLOB, static_cast (std::get<0>(it)),
+ static_cast (std::get<1>(it)),
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT };
+ dynamicDepthEntries.insert(dynamicDepthEntries.end(), entry, entry + 4);
+ }
+
+ std::vector depthMinDurations, depthStallDurations;
+ std::vector blobMinDurations, blobStallDurations;
+ std::vector dynamicDepthMinDurations, dynamicDepthStallDurations;
+
+ getSupportedDurations(c, ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
+ HAL_PIXEL_FORMAT_Y16, internalDepthSizes, &depthMinDurations);
+ getSupportedDurations(c, ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ HAL_PIXEL_FORMAT_BLOB, supportedDynamicDepthSizes, &blobMinDurations);
+ if (blobMinDurations.empty() || depthMinDurations.empty() ||
+ (depthMinDurations.size() != blobMinDurations.size())) {
+ ALOGE("%s: Unexpected number of available depth min durations! %zu vs. %zu",
+ __FUNCTION__, depthMinDurations.size(), blobMinDurations.size());
+ return BAD_VALUE;
+ }
+
+ getSupportedDurations(c, ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,
+ HAL_PIXEL_FORMAT_Y16, internalDepthSizes, &depthStallDurations);
+ getSupportedDurations(c, ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+ HAL_PIXEL_FORMAT_BLOB, supportedDynamicDepthSizes, &blobStallDurations);
+ if (blobStallDurations.empty() || depthStallDurations.empty() ||
+ (depthStallDurations.size() != blobStallDurations.size())) {
+ ALOGE("%s: Unexpected number of available depth stall durations! %zu vs. %zu",
+ __FUNCTION__, depthStallDurations.size(), blobStallDurations.size());
+ return BAD_VALUE;
+ }
+
+ getSupportedDynamicDepthDurations(depthMinDurations, blobMinDurations,
+ &dynamicDepthMinDurations);
+ getSupportedDynamicDepthDurations(depthStallDurations, blobStallDurations,
+ &dynamicDepthStallDurations);
+ if (dynamicDepthMinDurations.empty() || dynamicDepthStallDurations.empty() ||
+ (dynamicDepthMinDurations.size() != dynamicDepthStallDurations.size())) {
+ ALOGE("%s: Unexpected number of dynamic depth stall/min durations! %zu vs. %zu",
+ __FUNCTION__, dynamicDepthMinDurations.size(), dynamicDepthStallDurations.size());
+ return BAD_VALUE;
+ }
+
+ std::vector dynamicDepthMinDurationEntries;
+ auto itDuration = dynamicDepthMinDurations.begin();
+ auto itSize = supportedDynamicDepthSizes.begin();
+ while (itDuration != dynamicDepthMinDurations.end()) {
+ int64_t entry[4] = {HAL_PIXEL_FORMAT_BLOB, static_cast (std::get<0>(*itSize)),
+ static_cast (std::get<1>(*itSize)), *itDuration};
+ dynamicDepthMinDurationEntries.insert(dynamicDepthMinDurationEntries.end(), entry,
+ entry + 4);
+ itDuration++; itSize++;
+ }
+
+ std::vector dynamicDepthStallDurationEntries;
+ itDuration = dynamicDepthStallDurations.begin();
+ itSize = supportedDynamicDepthSizes.begin();
+ while (itDuration != dynamicDepthStallDurations.end()) {
+ int64_t entry[4] = {HAL_PIXEL_FORMAT_BLOB, static_cast (std::get<0>(*itSize)),
+ static_cast (std::get<1>(*itSize)), *itDuration};
+ dynamicDepthStallDurationEntries.insert(dynamicDepthStallDurationEntries.end(), entry,
+ entry + 4);
+ itDuration++; itSize++;
+ }
+
+ c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+ dynamicDepthEntries.data(), dynamicDepthEntries.size());
+ c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
+ dynamicDepthMinDurationEntries.data(), dynamicDepthMinDurationEntries.size());
+ c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
+ dynamicDepthStallDurationEntries.data(), dynamicDepthStallDurationEntries.size());
+
+ std::vector supportedChTags;
+ supportedChTags.reserve(chTags.count + 3);
+ supportedChTags.insert(supportedChTags.end(), chTags.data.i32,
+ chTags.data.i32 + chTags.count);
+ supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
+ supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS);
+ supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS);
+ c.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, supportedChTags.data(),
+ supportedChTags.size());
+
+ return OK;
+}
+
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::fixupMonochromeTags() {
status_t res = OK;
auto& c = mCameraCharacteristics;
@@ -1442,6 +1684,12 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string&
__FUNCTION__, strerror(-res), res);
return;
}
+ res = addDynamicDepthTags();
+ if (OK != res) {
+ ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-res),
+ res);
+ return;
+ }
camera_metadata_entry flashAvailable =
mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
if (flashAvailable.count == 1 &&
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 096674314b..1f34f2fc46 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -470,6 +470,22 @@ private:
std::unordered_map mPhysicalCameraCharacteristics;
void queryPhysicalCameraIds();
status_t fixupMonochromeTags();
+ status_t addDynamicDepthTags();
+ static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag,
+ android_pixel_format_t format,
+ std::vector> *sizes /*out*/);
+ void getSupportedDurations( const CameraMetadata& ch, uint32_t tag,
+ android_pixel_format_t format,
+ const std::vector>& sizes,
+ std::vector *durations/*out*/);
+ void getSupportedDynamicDepthDurations(const std::vector& depthDurations,
+ const std::vector& blobDurations,
+ std::vector *dynamicDepthDurations /*out*/);
+ static void getSupportedDynamicDepthSizes(
+ const std::vector>& blobSizes,
+ const std::vector>& depthSizes,
+ std::vector> *dynamicDepthSizes /*out*/,
+ std::vector> *internalDepthSizes /*out*/);
status_t removeAvailableKeys(CameraMetadata& c, const std::vector& keys,
uint32_t keyTag);
};