Message ID | 20210823094806.1434280-1-paul.elder@ideasonboard.com |
---|---|
State | Superseded |
Delegated to: | Paul Elder |
Headers | show |
Series |
|
Related | show |
Hi Paul, Thank you for the patch. On Mon, Aug 23, 2021 at 06:48:05PM +0900, Paul Elder wrote: > 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@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; > + } Where did you see that the manual sensor capability requires edge mode ? I'm looking at https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR and I don't see edge mode control there. It's however required for FULL level, but I'm not entirely sure if FULL level request supporting other modes than OFF. > + > /* > * \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); > > + Extra blank line. > + 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 Isn't this something that needs to be fixed in controls serialization ? We can keep the workaround to avoiding depending on that work, but a todo comment is needed then. > + * 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[] = {
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[] = {
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@ideasonboard.com> --- src/android/camera_capabilities.cpp | 33 ++++++++++++++++++++++ src/android/camera_device.cpp | 44 +++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+)