[libcamera-devel] [RFC PATCH 1/2] android: Plumb Sharpness control into EDGE_MODE
Paul Elder
paul.elder at ideasonboard.com
Mon Aug 23 11:48:05 CEST 2021
Plumb the Sharpness control into the HAL for EDGE_MODE and other related
android controls.
Bug: https://bugs.libcamera.org/show_bug.cgi?id=46
Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
src/android/camera_capabilities.cpp | 33 ++++++++++++++++++++++
src/android/camera_device.cpp | 44 +++++++++++++++++++++++++++++
2 files changed, 77 insertions(+)
diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
index bd661675..d12dc048 100644
--- a/src/android/camera_capabilities.cpp
+++ b/src/android/camera_capabilities.cpp
@@ -231,6 +231,11 @@ bool CameraCapabilities::validateManualSensorCapability()
return false;
}
+ if (!staticMetadata_->hasEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES)) {
+ LOG(HAL, Info) << noMode << "missing edge modes";
+ return false;
+ }
+
/*
* \todo Return true here after we satisfy all the requirements:
* https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
@@ -938,6 +943,22 @@ int CameraCapabilities::initializeStaticMetadata()
staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
availableControlModes);
+
+ const auto &edgeInfo = controlsInfo.find(&controls::Sharpness);
+ if (edgeInfo != controlsInfo.end()) {
+ std::vector<uint8_t> availableEdgeModes = {
+ ANDROID_EDGE_MODE_OFF,
+ ANDROID_EDGE_MODE_FAST,
+ ANDROID_EDGE_MODE_HIGH_QUALITY,
+ };
+
+ staticMetadata_->addEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+ availableEdgeModes);
+ availableCharacteristicsKeys_.insert(ANDROID_EDGE_AVAILABLE_EDGE_MODES);
+ availableRequestKeys_.insert(ANDROID_EDGE_MODE);
+ availableResultKeys_.insert(ANDROID_EDGE_MODE);
+ }
+
/* JPEG static metadata. */
/*
@@ -1330,6 +1351,9 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateManual() cons
if (!manualTemplate)
return nullptr;
+ if (availableRequestKeys_.count(ANDROID_EDGE_MODE))
+ manualTemplate->addEntry(ANDROID_EDGE_MODE, ANDROID_EDGE_MODE_OFF);
+
return manualTemplate;
}
@@ -1390,6 +1414,9 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplatePreview() con
uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
requestTemplate->addEntry(ANDROID_CONTROL_AWB_LOCK, awbLock);
+ if (availableRequestKeys_.count(ANDROID_EDGE_MODE))
+ requestTemplate->addEntry(ANDROID_EDGE_MODE, ANDROID_EDGE_MODE_FAST);
+
uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode);
@@ -1428,6 +1455,9 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateStill() const
if (!stillTemplate)
return nullptr;
+ if (availableRequestKeys_.count(ANDROID_EDGE_MODE))
+ stillTemplate->addEntry(ANDROID_EDGE_MODE, ANDROID_EDGE_MODE_HIGH_QUALITY);
+
return stillTemplate;
}
@@ -1445,6 +1475,9 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateVideo() const
staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
&entry);
+ if (availableRequestKeys_.count(ANDROID_EDGE_MODE))
+ previewTemplate->addEntry(ANDROID_EDGE_MODE, ANDROID_EDGE_MODE_FAST);
+
/*
* Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
* has been assembled as {{min, max} {max, max}}.
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index a69b687a..96afec81 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -829,6 +829,24 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor)
controls.set(controls::draft::TestPatternMode, testPatternMode);
}
+ if (settings.getEntry(ANDROID_EDGE_MODE, &entry)) {
+ const auto &info = camera_->controls().find(&controls::Sharpness);
+ if (info != camera_->controls().end()) {
+ float min = info->second.min().get<float>();
+ float def = info->second.def().get<float>();
+ float max = info->second.max().get<float>();
+ /*
+ * The default value might be unusable since control
+ * serialization ignores it. Alternatively the default
+ * could be simply set to zero or the minimum value.
+ * Use the maximum sharpness value in these cases.
+ */
+ float val = (def == 0.0f || def == min) ? max : def;
+ controls.set(controls::Sharpness,
+ *entry.data.u8 == ANDROID_EDGE_MODE_OFF ? min : val);
+ }
+ }
+
return 0;
}
@@ -1371,6 +1389,32 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons
duration);
}
+ if (metadata.contains(controls::Sharpness) &&
+ settings.getEntry(ANDROID_EDGE_MODE, &entry)) {
+ const auto &info = camera_->controls().find(&controls::Sharpness);
+ if (info != camera_->controls().end()) {
+ float min = info->second.min().get<float>();
+ float max = info->second.max().get<float>();
+ float sharpness = metadata.get(controls::Sharpness);
+ /*
+ * 1% of the sharpening value range is considered "no
+ * sharpening".
+ */
+ bool closeToMin = (sharpness - min) < (min + (0.01 * (max - min))) ||
+ min == max;
+
+ /*
+ * libcamera doesn't distinguish between fast vs HQ
+ * sharpening modes. Report the mode that was
+ * requested.
+ */
+ resultMetadata->addEntry(ANDROID_EDGE_MODE,
+ closeToMin ?
+ (uint8_t)ANDROID_EDGE_MODE_OFF :
+ *entry.data.u8);
+ }
+ }
+
if (metadata.contains(controls::ScalerCrop)) {
Rectangle crop = metadata.get(controls::ScalerCrop);
int32_t cropRect[] = {
--
2.27.0
More information about the libcamera-devel
mailing list