Message ID | 20211221044133.2531278-1-paul.elder@ideasonboard.com |
---|---|
State | New |
Delegated to: | Paul Elder |
Headers | show |
Series |
|
Related | show |
Quoting Paul Elder (2021-12-21 04:41:33) > Plumb the Sharpness control into the HAL for EDGE_MODE and other related > android controls. > > libcamera doesn't distinguish between fast and HQ, but rather with a > floating value for how much sharpening to apply. This is thus > unsufficient information for retaining whether the request was for fast s/unsufficient/insufficient/ > or HQ, so save it in the request, and report what was requested. > > Bug: https://bugs.libcamera.org/show_bug.cgi?id=46 > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > > --- > This patch depends on "android: camera_metadata: Add appendEntry helper" > > Changes in v2: > - fix the assertions in template creation > - report the edge mode that was requested, instead of doing conversion > to and from the floating value and its ControlInfo > - move edge mode capability check out of manual control (as docs say > it's not required) and into the top-level FULL hardware level > validator > --- > src/android/camera_capabilities.cpp | 44 +++++++++++++++++++++++++++++ > src/android/camera_device.cpp | 28 ++++++++++++++++++ > src/android/camera_request.h | 4 +++ > 3 files changed, 76 insertions(+) > > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp > index b9a1f6e5..727204b9 100644 > --- a/src/android/camera_capabilities.cpp > +++ b/src/android/camera_capabilities.cpp > @@ -401,6 +401,11 @@ void CameraCapabilities::computeHwLevel( > if (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE)) > hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; > > + if (!staticMetadata_->hasEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES)) { > + LOG(HAL, Info) << noFull << "missing edge modes"; > + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; > + } > + > found = staticMetadata_->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry); > if (!found || *entry.data.i32 != 0) { > LOG(HAL, Info) << noFull << "missing or invalid max sync latency"; > @@ -1078,6 +1083,21 @@ 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. */ > > /* > @@ -1593,6 +1613,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateManual() cons > manualTemplate->appendEntry(ANDROID_CONTROL_AE_MODE, aeMode); > } > > + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, > + ANDROID_EDGE_MODE_OFF)) { > + uint8_t edgeMode = ANDROID_EDGE_MODE_OFF; > + manualTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); > + } > + > return manualTemplate; > } > > @@ -1675,6 +1701,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplatePreview() con > if (availableRequestKeys_.count(ANDROID_SENSOR_SENSITIVITY)) > requestTemplate->addEntry(ANDROID_SENSOR_SENSITIVITY, minISO_); > > + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, > + ANDROID_EDGE_MODE_FAST)) { > + uint8_t edgeMode = ANDROID_EDGE_MODE_FAST; > + requestTemplate->addEntry(ANDROID_EDGE_MODE, edgeMode); > + } > + > uint8_t flashMode = ANDROID_FLASH_MODE_OFF; > requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode); > > @@ -1713,6 +1745,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateStill() const > if (!stillTemplate) > return nullptr; > > + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, > + ANDROID_EDGE_MODE_HIGH_QUALITY)) { > + uint8_t edgeMode = ANDROID_EDGE_MODE_HIGH_QUALITY; > + stillTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); > + } > + > return stillTemplate; > } > > @@ -1730,6 +1768,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateVideo() const > staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, > &entry); > > + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, > + ANDROID_EDGE_MODE_FAST)) { > + uint8_t edgeMode = ANDROID_EDGE_MODE_FAST; > + previewTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); > + } > + > /* > * 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 1a508923..0d668ea6 100644 > --- a/src/android/camera_device.cpp > +++ b/src/android/camera_device.cpp > @@ -920,6 +920,26 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor) > controls.set(controls::DigitalGain, lastDigitalGain_); > } > > + if (settings.getEntry(ANDROID_EDGE_MODE, &entry)) { > + const auto &info = camera_->controls().find(&controls::Sharpness); > + if (info != camera_->controls().end()) { As the ANDROID_EDGE_MODE is only enabled if the camera has a Sharpness control, this should always be found right? Still, it doesn't hurt to make sure I think. > + 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 Why? Should we fix the serialisation to pass the default values? or is this troublesome? > + * 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); > + > + descriptor->edgeMode_ = *entry.data.u8; So, if I infer correctly this should set: EDGE_MODE_OFF : min EDGE_MODE_FAST : def, unless def == min or def == 0, when max EDGE_MODE_HIGH_QUALITY : same as ^ Should HIGH_QUALITY always set max? descriptor->edgeMode_ = *entry.data.u8; switch (descriptor->edgeMode_) { default: case ANDROID_EDGE_MODE_OFF: val = min; break; case ANDROID_EDGE_MODE_FAST: /* ... comment about def, or fix serialisations? */ val = (def == 0.0f || def == min) ? max : def; break; case ANDROID_EDGE_MODE_HIGH_QUALITY: val = max; break; } Hrm, not quite as concise though, so maybe your way is fine if we don't intend to distinguish between the fast/HQ anyway. If there's a reason we can't or shouldn't be serialising the default values to be able to reference them correctly then: Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > + } > + } > + > return 0; > } > > @@ -1602,6 +1622,14 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons > duration); > } > > + if (metadata.contains(controls::Sharpness)) { > + /* > + * libcamera doesn't distinguish between fast vs HQ sharpening > + * modes. Report the mode that was requested. > + */ > + resultMetadata->addEntry(ANDROID_EDGE_MODE, descriptor.edgeMode_); > + } > + > if (metadata.contains(controls::ScalerCrop)) { > Rectangle crop = metadata.get(controls::ScalerCrop); > int32_t cropRect[] = { > diff --git a/src/android/camera_request.h b/src/android/camera_request.h > index b2809179..69b6c8fc 100644 > --- a/src/android/camera_request.h > +++ b/src/android/camera_request.h > @@ -87,6 +87,10 @@ public: > /* The libcamera internal AE state for this request */ > AutoMode aeMode_ = AutoMode::Auto; > > + /* The android edge mode associated with this request */ > + /* \todo Wrap all such controls? */ > + int32_t edgeMode_; > + > private: > LIBCAMERA_DISABLE_COPY(Camera3RequestDescriptor) > }; > -- > 2.27.0 >
diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index b9a1f6e5..727204b9 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -401,6 +401,11 @@ void CameraCapabilities::computeHwLevel( if (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE)) hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + if (!staticMetadata_->hasEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES)) { + LOG(HAL, Info) << noFull << "missing edge modes"; + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + } + found = staticMetadata_->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry); if (!found || *entry.data.i32 != 0) { LOG(HAL, Info) << noFull << "missing or invalid max sync latency"; @@ -1078,6 +1083,21 @@ 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. */ /* @@ -1593,6 +1613,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateManual() cons manualTemplate->appendEntry(ANDROID_CONTROL_AE_MODE, aeMode); } + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, + ANDROID_EDGE_MODE_OFF)) { + uint8_t edgeMode = ANDROID_EDGE_MODE_OFF; + manualTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); + } + return manualTemplate; } @@ -1675,6 +1701,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplatePreview() con if (availableRequestKeys_.count(ANDROID_SENSOR_SENSITIVITY)) requestTemplate->addEntry(ANDROID_SENSOR_SENSITIVITY, minISO_); + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, + ANDROID_EDGE_MODE_FAST)) { + uint8_t edgeMode = ANDROID_EDGE_MODE_FAST; + requestTemplate->addEntry(ANDROID_EDGE_MODE, edgeMode); + } + uint8_t flashMode = ANDROID_FLASH_MODE_OFF; requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode); @@ -1713,6 +1745,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateStill() const if (!stillTemplate) return nullptr; + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, + ANDROID_EDGE_MODE_HIGH_QUALITY)) { + uint8_t edgeMode = ANDROID_EDGE_MODE_HIGH_QUALITY; + stillTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); + } + return stillTemplate; } @@ -1730,6 +1768,12 @@ std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateVideo() const staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, &entry); + if (staticMetadata_->entryContains<uint8_t>(ANDROID_EDGE_AVAILABLE_EDGE_MODES, + ANDROID_EDGE_MODE_FAST)) { + uint8_t edgeMode = ANDROID_EDGE_MODE_FAST; + previewTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); + } + /* * 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 1a508923..0d668ea6 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -920,6 +920,26 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor) controls.set(controls::DigitalGain, lastDigitalGain_); } + 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); + + descriptor->edgeMode_ = *entry.data.u8; + } + } + return 0; } @@ -1602,6 +1622,14 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons duration); } + if (metadata.contains(controls::Sharpness)) { + /* + * libcamera doesn't distinguish between fast vs HQ sharpening + * modes. Report the mode that was requested. + */ + resultMetadata->addEntry(ANDROID_EDGE_MODE, descriptor.edgeMode_); + } + if (metadata.contains(controls::ScalerCrop)) { Rectangle crop = metadata.get(controls::ScalerCrop); int32_t cropRect[] = { diff --git a/src/android/camera_request.h b/src/android/camera_request.h index b2809179..69b6c8fc 100644 --- a/src/android/camera_request.h +++ b/src/android/camera_request.h @@ -87,6 +87,10 @@ public: /* The libcamera internal AE state for this request */ AutoMode aeMode_ = AutoMode::Auto; + /* The android edge mode associated with this request */ + /* \todo Wrap all such controls? */ + int32_t edgeMode_; + private: LIBCAMERA_DISABLE_COPY(Camera3RequestDescriptor) };
Plumb the Sharpness control into the HAL for EDGE_MODE and other related android controls. libcamera doesn't distinguish between fast and HQ, but rather with a floating value for how much sharpening to apply. This is thus unsufficient information for retaining whether the request was for fast or HQ, so save it in the request, and report what was requested. Bug: https://bugs.libcamera.org/show_bug.cgi?id=46 Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> --- This patch depends on "android: camera_metadata: Add appendEntry helper" Changes in v2: - fix the assertions in template creation - report the edge mode that was requested, instead of doing conversion to and from the floating value and its ControlInfo - move edge mode capability check out of manual control (as docs say it's not required) and into the top-level FULL hardware level validator --- src/android/camera_capabilities.cpp | 44 +++++++++++++++++++++++++++++ src/android/camera_device.cpp | 28 ++++++++++++++++++ src/android/camera_request.h | 4 +++ 3 files changed, 76 insertions(+)