[libcamera-devel] [RFC PATCH] wip: android: capabilities: Capability detection by population

Paul Elder paul.elder at ideasonboard.com
Fri Jul 9 13:28:14 CEST 2021


Implement capability and hardware level detection based on the static
metadata that has been set, instead of disabling them as requirements
are not met. This results in cleaner code where the static metadata is
set.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>

---
This currently does not work as the ControlInfo constructor for Spans is
broken. This is more of an RFC for Jacopo to check that this is the
direction that he wants.

Clearly this is not meant to be merged, as the actual capability
requirements are not fully specified yet. Plus they belong in separate
patches anyway.

This patch does not apply either, as it depends on many unreleased
patches.
---
 src/android/camera_capabilities.cpp | 219 ++++++++++++++++++++--------
 1 file changed, 157 insertions(+), 62 deletions(-)

diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
index 83c7f0d0..ceb5cfe8 100644
--- a/src/android/camera_capabilities.cpp
+++ b/src/android/camera_capabilities.cpp
@@ -262,6 +262,149 @@ std::vector<T> setMetadata(CameraMetadata *metadata, uint32_t tag,
 	return ret;
 }
 
+
+template<typename T>
+bool metadataContains(camera_metadata_ro_entry_t &entry, T value);
+
+template<>
+bool metadataContains<uint8_t>(camera_metadata_ro_entry_t &entry, uint8_t value)
+{
+	for (unsigned int i = 0; i < entry.count; i++)
+		if (entry.data.u8[i] == value)
+			return true;
+
+	return false;
+}
+
+bool validateManualSensorCapability(CameraMetadata *staticMetadata)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
+					 &entry);
+	if (!found || !metadataContains<uint8_t>(entry, ANDROID_CONTROL_AE_MODE_OFF)) {
+		LOG(HAL, Info)
+			<< "Missing AE mode off: "
+			<< (found ? "not supported" : "not found");
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AE lock";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+					 &entry);
+	if (!found) {
+		LOG(HAL, Info) << "Missing edge modes";
+		return false;
+	}
+
+	return true;
+}
+
+bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+					 &entry);
+	if (!found || !metadataContains<uint8_t>(entry, ANDROID_CONTROL_AWB_MODE_OFF)) {
+		LOG(HAL, Info) << "Missing AWB mode off";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AWB lock";
+		return false;
+	}
+
+	return true;
+}
+
+bool validateBurstCaptureCapability(CameraMetadata *staticMetadata)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AE lock";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AWB lock";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry);
+	if (!found || *entry.data.i32 < 0 || 4 < *entry.data.i32) {
+		LOG(HAL, Info)
+			<< "Max sync latency is "
+			<< (found ? std::to_string(*entry.data.i32) : "not present");
+		return false;
+	}
+
+	return true;
+}
+
+std::set<camera_metadata_enum_android_request_available_capabilities>
+computeCapabilities(CameraMetadata *staticMetadata,
+		    std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps)
+{
+	std::set<camera_metadata_enum_android_request_available_capabilities>
+	capabilities = existingCaps;
+
+	capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+
+	if (validateManualSensorCapability(staticMetadata))
+		capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
+
+	if (validateManualPostProcessingCapability(staticMetadata))
+		capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
+
+	if (validateBurstCaptureCapability(staticMetadata))
+		capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
+
+	return capabilities;
+}
+
+camera_metadata_enum_android_info_supported_hardware_level
+computeHwLevel(CameraMetadata *staticMetadata,
+	       std::set<camera_metadata_enum_android_request_available_capabilities> capabilities)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+	camera_metadata_enum_android_info_supported_hardware_level
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
+
+	if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR))
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING))
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE))
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	found = staticMetadata->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry);
+	if (!found || *entry.data.i32 != 0)
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	return hwLevel;
+}
+
 } /* namespace */
 
 int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera,
@@ -655,17 +798,7 @@ int CameraCapabilities::initializeStaticMetadata()
 	};
 
 	std::set<camera_metadata_enum_android_request_available_capabilities>
-	capabilities = {
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
-	};
-
-	std::set<camera_metadata_enum_android_info_supported_hardware_level>
-	hwLevels = {
-		ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
-	};
+	capabilities = {};
 
 	/* Color correction static metadata. */
 	{
@@ -692,19 +825,12 @@ int CameraCapabilities::initializeStaticMetadata()
 	staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
 				  aeAvailableAntiBandingModes);
 
-	std::vector<uint8_t> aeModes = setMetadata<uint8_t, bool>(
+	setMetadata<uint8_t, bool>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AE_AVAILABLE_MODES,
 		controlsInfo, &controls::AeEnable,
 		{ ANDROID_CONTROL_AE_MODE_ON });
 
-	if (std::find(aeModes.begin(), aeModes.end(),
-		      ANDROID_CONTROL_AE_MODE_OFF) == aeModes.end()) {
-		LOG(HAL, Info) << "AE cannot be turned off";
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
-	}
-
 	int64_t minFrameDurationNsec = -1;
 	int64_t maxFrameDurationNsec = -1;
 	const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);
@@ -791,17 +917,11 @@ int CameraCapabilities::initializeStaticMetadata()
 	staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
 				  availableStabilizationModes);
 
-	std::vector<uint8_t> awbModes = setMetadata<uint8_t, int32_t>(
+	setMetadata<uint8_t, int32_t>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AWB_AVAILABLE_MODES,
 		controlsInfo, &controls::AwbMode,
 		{ ANDROID_CONTROL_AWB_MODE_AUTO });
-	if (std::find(awbModes.begin(), awbModes.end(),
-		      ANDROID_CONTROL_AWB_MODE_OFF) == awbModes.end()) {
-		LOG(HAL, Info) << "AWB cannot be turned off";
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
-	}
 
 	std::vector<int32_t> availableMaxRegions = {
 		0, 0, 0,
@@ -817,29 +937,19 @@ int CameraCapabilities::initializeStaticMetadata()
 	staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
 				  sceneModesOverride);
 
-	uint8_t aeLockAvailable = setMetadata<uint8_t, bool>(
+	setMetadata<uint8_t, bool>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AE_LOCK_AVAILABLE,
 		controlsInfo, &controls::AeLock,
 		ControlRange::Max,
 		ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE);
-	if (aeLockAvailable != ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE) {
-		LOG(HAL, Info) << "AE lock is unavailable";
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
-	}
 
-	uint8_t awbLockAvailable = setMetadata<uint8_t, bool>(
+	setMetadata<uint8_t, bool>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
 		controlsInfo, &controls::AwbLock,
 		ControlRange::Max,
 		ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE);
-	if (awbLockAvailable != ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE) {
-		LOG(HAL, Info) << "AWB lock is unavailable";
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
-	}
 
 	char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
 	staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
@@ -859,10 +969,6 @@ int CameraCapabilities::initializeStaticMetadata()
 		availableCharacteristicsKeys_.insert(ANDROID_EDGE_AVAILABLE_EDGE_MODES);
 		availableRequestKeys_.insert(ANDROID_EDGE_MODE);
 		availableResultKeys_.insert(ANDROID_EDGE_MODE);
-	} else {
-		LOG(HAL, Info) << "Edge mode unavailable";
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
 	}
 
 	/* JPEG static metadata. */
@@ -1046,17 +1152,11 @@ int CameraCapabilities::initializeStaticMetadata()
 	}
 
 	/* Sync static metadata. */
-	int32_t maxLatency = setMetadata<int32_t, int32_t>(
+	setMetadata<int32_t, int32_t>(
 		staticMetadata_.get(), ANDROID_SYNC_MAX_LATENCY,
 		controlsInfo, &controls::draft::MaxLatency,
 		ControlRange::Def,
 		ANDROID_SYNC_MAX_LATENCY_UNKNOWN);
-	LOG(HAL, Info) << "Max sync latency is " << maxLatency;
-	/* CTS allows a sync latency of up to 4 for burst capture capability */
-	if (maxLatency < 0 || 4 < maxLatency)
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
-	if (maxLatency != 0)
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
 
 	/* Flash static metadata. */
 	char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
@@ -1220,19 +1320,14 @@ int CameraCapabilities::initializeStaticMetadata()
 				  numOutStreams);
 
 	/* Check capabilities */
-	std::vector<uint8_t> availableCapabilities(capabilities.begin(),
-						   capabilities.end());
-	staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
-				  availableCapabilities);
-
-	uint8_t hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
-	if (capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) &&
-	    capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING) &&
-	    capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) &&
-	    hwLevels.count(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL))
-		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
-	staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
-				  hwLevel);
+	capabilities = computeCapabilities(staticMetadata_.get(), capabilities);
+	std::vector<camera_metadata_enum_android_request_available_capabilities>
+		capsVec = std::vector<camera_metadata_enum_android_request_available_capabilities>(capabilities.begin(), capabilities.end());
+	staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capsVec);
+
+	camera_metadata_enum_android_info_supported_hardware_level hwLevel =
+		computeHwLevel(staticMetadata_.get(), capabilities);
+	staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, hwLevel);
 
 	LOG(HAL, Info)
 		<< "Hardware level: "
-- 
2.27.0



More information about the libcamera-devel mailing list