Message ID | 20210716105631.158153-6-paul.elder@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Paul, On Fri, Jul 16, 2021 at 07:56:15PM +0900, Paul Elder wrote: > Add the infrastructure for checking and reporting capabilities. Use > these capabilities to determine the hardware level as well. > > Bug: https://bugs.libcamera.org/show_bug.cgi?id=55 > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > > --- > Changes in v5: > - change the whole thing to turn on capabilities after they are all > confirmed, instead of disabling them as conditions are not met > > Changes in v4: > - rebase on camera capabilities refactoring > - switch to std::set from std::map > - make hwlevel similar to capabilities > > Changes in v3: > - fix some compiler errors > - go ahead and initialize the capabilities to true, update the commit > message accordingly > > Changes in v2: > - add a flag for FULL, since there are a few requirements that are not > obtained from capabilities alone > - add burst capture capability, since that is required for FULL as well > --- > src/android/camera_capabilities.cpp | 172 +++++++++++++++++++++++++--- > src/android/camera_capabilities.h | 13 +++ > 2 files changed, 170 insertions(+), 15 deletions(-) > > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp > index 9e2714f1..be55db88 100644 > --- a/src/android/camera_capabilities.cpp > +++ b/src/android/camera_capabilities.cpp > @@ -9,6 +9,7 @@ > > #include <array> > #include <cmath> > +#include <map> > > #include <hardware/camera3.h> > > @@ -114,8 +115,148 @@ const std::map<int, const Camera3Format> camera3FormatsMap = { > }, > }; > > +const std::map<camera_metadata_enum_android_info_supported_hardware_level, std::string> > +hwLevelStrings = { > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, "LIMITED" }, > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL, "FULL" }, > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, "LEGACY" }, > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3, "LEVEL_3" }, > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, "EXTERNAL" }, > +}; > + > } /* namespace */ > > +bool CameraCapabilities::validateManualSensorCapability(CameraMetadata *staticMetadata) > +{ > + camera_metadata_ro_entry_t entry; > + bool found; > + > + const char *noMode = "Manual sensor capability unavailable: "; > + > + if (!(found = staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AE_AVAILABLE_MODES, > + ANDROID_CONTROL_AE_MODE_OFF))) { > + LOG(HAL, Info) > + << noMode << "missing AE mode off: " > + << (found ? "not supported" : "not found"); You don't get here if (found) :) > + return false; > + } > + > + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, > + &entry); > + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { Can't this just be entryContains() ? > + LOG(HAL, Info) << noMode << "missing AE lock"; > + return false; > + } > + > + return true; > +} > + > +bool CameraCapabilities::validateManualPostProcessingCapability(CameraMetadata *staticMetadata) > +{ > + camera_metadata_ro_entry_t entry; > + bool found; > + > + const char *noMode = "Manual post processing capability unavailable: "; > + > + if (!staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AWB_AVAILABLE_MODES, > + ANDROID_CONTROL_AWB_MODE_OFF)) { > + LOG(HAL, Info) << noMode << "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)) { same question, can this just be entryContains() ? > + LOG(HAL, Info) << noMode << "missing AWB lock"; > + return false; > + } > + > + return true; > +} > + > +bool CameraCapabilities::validateBurstCaptureCapability(CameraMetadata *staticMetadata) > +{ > + camera_metadata_ro_entry_t entry; > + bool found; > + > + const char *noMode = "Burst capture capability unavailable: "; > + > + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, > + &entry); > + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { ditto, but I suspect I'm missing something as this is a recurring pattern :) > + LOG(HAL, Info) << noMode << "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) << noMode << "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) > + << noMode << "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> > +CameraCapabilities::computeCapabilities(CameraMetadata *staticMetadata, > + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps) > +{ > + std::set<camera_metadata_enum_android_request_available_capabilities> > + capabilities = existingCaps; Can't you just add values to 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); > + > + if (rawStreamAvailable_) > + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); > + > + return capabilities; > +} > + > +camera_metadata_enum_android_info_supported_hardware_level > +CameraCapabilities::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; > + > + hwLevel_ = hwLevel; > + > + return hwLevel; > +} > + > int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera, > int orientation, int facing) > { > @@ -382,6 +523,9 @@ int CameraCapabilities::initializeStaticMetadata() > const ControlInfoMap &controlsInfo = camera_->controls(); > const ControlList &properties = camera_->properties(); > > + std::set<camera_metadata_enum_android_request_available_capabilities> > + capabilities = {}; > + > /* Color correction static metadata. */ > { > std::vector<uint8_t> data; > @@ -840,11 +984,6 @@ int CameraCapabilities::initializeStaticMetadata() > uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY; > staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType); > > - /* Info static metadata. */ > - uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; > - staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, > - supportedHWLevel); > - > /* Request static metadata. */ > int32_t partialResultCount = 1; > staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, > @@ -865,21 +1004,24 @@ int CameraCapabilities::initializeStaticMetadata() > staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, > maxNumInputStreams); > > - std::vector<uint8_t> availableCapabilities = { > - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, > - }; > - > - /* Report if camera supports RAW. */ > - if (rawStreamAvailable_) > - availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); > - > /* Number of { RAW, YUV, JPEG } supported output streams */ > int32_t numOutStreams[] = { rawStreamAvailable_, 2, 1 }; > staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, > numOutStreams); > > - staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, > - availableCapabilities); > + /* Check capabilities */ > + capabilities = computeCapabilities(staticMetadata_.get(), capabilities); Can you declate capabilities here ? It is not used before. Also, what the puropse of 'existingCaps' in computeCapabilities() if it's empty ? Can you just return a vector to avoid the below conversion from set to vec ? I like the overall direction :) Thanks j > + 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: " > + << hwLevelStrings.find((camera_metadata_enum_android_info_supported_hardware_level)hwLevel)->second; > > std::vector<int32_t> availableCharacteristicsKeys = { > ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, > diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h > index 42a976d3..38ee97d0 100644 > --- a/src/android/camera_capabilities.h > +++ b/src/android/camera_capabilities.h > @@ -42,6 +42,18 @@ private: > int androidFormat; > }; > > + bool validateManualSensorCapability(CameraMetadata *staticMetadata); > + bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata); > + bool validateBurstCaptureCapability(CameraMetadata *staticMetadata); > + > + std::set<camera_metadata_enum_android_request_available_capabilities> > + computeCapabilities(CameraMetadata *staticMetadata, > + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps); > + > + camera_metadata_enum_android_info_supported_hardware_level > + computeHwLevel(CameraMetadata *staticMetadata, > + std::set<camera_metadata_enum_android_request_available_capabilities> capabilities); > + > std::vector<libcamera::Size> > initializeYUVResolutions(const libcamera::PixelFormat &pixelFormat, > const std::vector<libcamera::Size> &resolutions); > @@ -56,6 +68,7 @@ private: > int facing_; > int orientation_; > bool rawStreamAvailable_; > + camera_metadata_enum_android_info_supported_hardware_level hwLevel_; > > std::vector<Camera3StreamConfiguration> streamConfigurations_; > std::map<int, libcamera::PixelFormat> formatsMap_; > -- > 2.27.0 >
Hi Jacopo, On Sat, Jul 17, 2021 at 12:11:55PM +0200, Jacopo Mondi wrote: > Hi Paul, > > On Fri, Jul 16, 2021 at 07:56:15PM +0900, Paul Elder wrote: > > Add the infrastructure for checking and reporting capabilities. Use > > these capabilities to determine the hardware level as well. > > > > Bug: https://bugs.libcamera.org/show_bug.cgi?id=55 > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > > > > --- > > Changes in v5: > > - change the whole thing to turn on capabilities after they are all > > confirmed, instead of disabling them as conditions are not met > > > > Changes in v4: > > - rebase on camera capabilities refactoring > > - switch to std::set from std::map > > - make hwlevel similar to capabilities > > > > Changes in v3: > > - fix some compiler errors > > - go ahead and initialize the capabilities to true, update the commit > > message accordingly > > > > Changes in v2: > > - add a flag for FULL, since there are a few requirements that are not > > obtained from capabilities alone > > - add burst capture capability, since that is required for FULL as well > > --- > > src/android/camera_capabilities.cpp | 172 +++++++++++++++++++++++++--- > > src/android/camera_capabilities.h | 13 +++ > > 2 files changed, 170 insertions(+), 15 deletions(-) > > > > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp > > index 9e2714f1..be55db88 100644 > > --- a/src/android/camera_capabilities.cpp > > +++ b/src/android/camera_capabilities.cpp > > @@ -9,6 +9,7 @@ > > > > #include <array> > > #include <cmath> > > +#include <map> > > > > #include <hardware/camera3.h> > > > > @@ -114,8 +115,148 @@ const std::map<int, const Camera3Format> camera3FormatsMap = { > > }, > > }; > > > > +const std::map<camera_metadata_enum_android_info_supported_hardware_level, std::string> > > +hwLevelStrings = { > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, "LIMITED" }, > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL, "FULL" }, > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, "LEGACY" }, > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3, "LEVEL_3" }, > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, "EXTERNAL" }, > > +}; > > + > > } /* namespace */ > > > > +bool CameraCapabilities::validateManualSensorCapability(CameraMetadata *staticMetadata) > > +{ > > + camera_metadata_ro_entry_t entry; > > + bool found; > > + > > + const char *noMode = "Manual sensor capability unavailable: "; > > + > > + if (!(found = staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AE_AVAILABLE_MODES, > > + ANDROID_CONTROL_AE_MODE_OFF))) { > > + LOG(HAL, Info) > > + << noMode << "missing AE mode off: " > > + << (found ? "not supported" : "not found"); > > You don't get here if (found) :) > > > + return false; > > + } > > + > > + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, > > + &entry); > > + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { > > Can't this just be entryContains() ? Entry contains is if the the entry is a list of items. Here (and below) the entry is a single item, so we can't use entryContains(). It's also not worth a helper since it's just "does the value equal X?". > > > + LOG(HAL, Info) << noMode << "missing AE lock"; > > + return false; > > + } > > + > > + return true; > > +} > > + > > +bool CameraCapabilities::validateManualPostProcessingCapability(CameraMetadata *staticMetadata) > > +{ > > + camera_metadata_ro_entry_t entry; > > + bool found; > > + > > + const char *noMode = "Manual post processing capability unavailable: "; > > + > > + if (!staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AWB_AVAILABLE_MODES, > > + ANDROID_CONTROL_AWB_MODE_OFF)) { > > + LOG(HAL, Info) << noMode << "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)) { > > same question, can this just be entryContains() ? > > > + LOG(HAL, Info) << noMode << "missing AWB lock"; > > + return false; > > + } > > + > > + return true; > > +} > > + > > +bool CameraCapabilities::validateBurstCaptureCapability(CameraMetadata *staticMetadata) > > +{ > > + camera_metadata_ro_entry_t entry; > > + bool found; > > + > > + const char *noMode = "Burst capture capability unavailable: "; > > + > > + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, > > + &entry); > > + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { > > ditto, but I suspect I'm missing something as this is a recurring > pattern :) > > > + LOG(HAL, Info) << noMode << "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) << noMode << "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) > > + << noMode << "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> > > +CameraCapabilities::computeCapabilities(CameraMetadata *staticMetadata, > > + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps) > > +{ > > + std::set<camera_metadata_enum_android_request_available_capabilities> > > + capabilities = existingCaps; > > Can't you just add values to existingCaps ? Oh I guess I can. > > > + > > + 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); > > + > > + if (rawStreamAvailable_) > > + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); > > + > > + return capabilities; > > +} > > + > > +camera_metadata_enum_android_info_supported_hardware_level > > +CameraCapabilities::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; > > + > > + hwLevel_ = hwLevel; > > + > > + return hwLevel; > > +} > > + > > int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera, > > int orientation, int facing) > > { > > @@ -382,6 +523,9 @@ int CameraCapabilities::initializeStaticMetadata() > > const ControlInfoMap &controlsInfo = camera_->controls(); > > const ControlList &properties = camera_->properties(); > > > > + std::set<camera_metadata_enum_android_request_available_capabilities> > > + capabilities = {}; > > + > > /* Color correction static metadata. */ > > { > > std::vector<uint8_t> data; > > @@ -840,11 +984,6 @@ int CameraCapabilities::initializeStaticMetadata() > > uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY; > > staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType); > > > > - /* Info static metadata. */ > > - uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; > > - staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, > > - supportedHWLevel); > > - > > /* Request static metadata. */ > > int32_t partialResultCount = 1; > > staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, > > @@ -865,21 +1004,24 @@ int CameraCapabilities::initializeStaticMetadata() > > staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, > > maxNumInputStreams); > > > > - std::vector<uint8_t> availableCapabilities = { > > - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, > > - }; > > - > > - /* Report if camera supports RAW. */ > > - if (rawStreamAvailable_) > > - availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); > > - > > /* Number of { RAW, YUV, JPEG } supported output streams */ > > int32_t numOutStreams[] = { rawStreamAvailable_, 2, 1 }; > > staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, > > numOutStreams); > > > > - staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, > > - availableCapabilities); > > + /* Check capabilities */ > > + capabilities = computeCapabilities(staticMetadata_.get(), capabilities); > > Can you declate capabilities here ? It is not used before. Oh, right. > Also, what the puropse of 'existingCaps' in computeCapabilities() if > it's empty ? Can you just return a vector to avoid the below > conversion from set to vec ? I guess we can return a vector. But we'd still have a conversion, it'll just be in computeCapabilities() instead of out. > > I like the overall direction :) Thanks, Paul > > > + 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: " > > + << hwLevelStrings.find((camera_metadata_enum_android_info_supported_hardware_level)hwLevel)->second; > > > > std::vector<int32_t> availableCharacteristicsKeys = { > > ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, > > diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h > > index 42a976d3..38ee97d0 100644 > > --- a/src/android/camera_capabilities.h > > +++ b/src/android/camera_capabilities.h > > @@ -42,6 +42,18 @@ private: > > int androidFormat; > > }; > > > > + bool validateManualSensorCapability(CameraMetadata *staticMetadata); > > + bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata); > > + bool validateBurstCaptureCapability(CameraMetadata *staticMetadata); > > + > > + std::set<camera_metadata_enum_android_request_available_capabilities> > > + computeCapabilities(CameraMetadata *staticMetadata, > > + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps); > > + > > + camera_metadata_enum_android_info_supported_hardware_level > > + computeHwLevel(CameraMetadata *staticMetadata, > > + std::set<camera_metadata_enum_android_request_available_capabilities> capabilities); > > + > > std::vector<libcamera::Size> > > initializeYUVResolutions(const libcamera::PixelFormat &pixelFormat, > > const std::vector<libcamera::Size> &resolutions); > > @@ -56,6 +68,7 @@ private: > > int facing_; > > int orientation_; > > bool rawStreamAvailable_; > > + camera_metadata_enum_android_info_supported_hardware_level hwLevel_; > > > > std::vector<Camera3StreamConfiguration> streamConfigurations_; > > std::map<int, libcamera::PixelFormat> formatsMap_; > > -- > > 2.27.0 > >
Hi Jacopo, On Mon, Jul 19, 2021 at 02:48:04PM +0900, paul.elder@ideasonboard.com wrote: > Hi Jacopo, > > On Sat, Jul 17, 2021 at 12:11:55PM +0200, Jacopo Mondi wrote: > > Hi Paul, > > > > On Fri, Jul 16, 2021 at 07:56:15PM +0900, Paul Elder wrote: > > > Add the infrastructure for checking and reporting capabilities. Use > > > these capabilities to determine the hardware level as well. > > > > > > Bug: https://bugs.libcamera.org/show_bug.cgi?id=55 > > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > > --- > > > Changes in v5: > > > - change the whole thing to turn on capabilities after they are all > > > confirmed, instead of disabling them as conditions are not met > > > > > > Changes in v4: > > > - rebase on camera capabilities refactoring > > > - switch to std::set from std::map > > > - make hwlevel similar to capabilities > > > > > > Changes in v3: > > > - fix some compiler errors > > > - go ahead and initialize the capabilities to true, update the commit > > > message accordingly > > > > > > Changes in v2: > > > - add a flag for FULL, since there are a few requirements that are not > > > obtained from capabilities alone > > > - add burst capture capability, since that is required for FULL as well > > > --- > > > src/android/camera_capabilities.cpp | 172 +++++++++++++++++++++++++--- > > > src/android/camera_capabilities.h | 13 +++ > > > 2 files changed, 170 insertions(+), 15 deletions(-) > > > > > > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp > > > index 9e2714f1..be55db88 100644 > > > --- a/src/android/camera_capabilities.cpp > > > +++ b/src/android/camera_capabilities.cpp > > > @@ -9,6 +9,7 @@ > > > > > > #include <array> > > > #include <cmath> > > > +#include <map> > > > > > > #include <hardware/camera3.h> > > > > > > @@ -114,8 +115,148 @@ const std::map<int, const Camera3Format> camera3FormatsMap = { > > > }, > > > }; > > > > > > +const std::map<camera_metadata_enum_android_info_supported_hardware_level, std::string> > > > +hwLevelStrings = { > > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, "LIMITED" }, > > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL, "FULL" }, > > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, "LEGACY" }, > > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3, "LEVEL_3" }, > > > + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, "EXTERNAL" }, > > > +}; > > > + > > > } /* namespace */ > > > > > > +bool CameraCapabilities::validateManualSensorCapability(CameraMetadata *staticMetadata) > > > +{ > > > + camera_metadata_ro_entry_t entry; > > > + bool found; > > > + > > > + const char *noMode = "Manual sensor capability unavailable: "; > > > + > > > + if (!(found = staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AE_AVAILABLE_MODES, > > > + ANDROID_CONTROL_AE_MODE_OFF))) { > > > + LOG(HAL, Info) > > > + << noMode << "missing AE mode off: " > > > + << (found ? "not supported" : "not found"); > > > > You don't get here if (found) :) > > > > > + return false; > > > + } > > > + > > > + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, > > > + &entry); > > > + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { > > > > Can't this just be entryContains() ? > > Entry contains is if the the entry is a list of items. Here (and below) > the entry is a single item, so we can't use entryContains(). It's also > not worth a helper since it's just "does the value equal X?". > > > > > > + LOG(HAL, Info) << noMode << "missing AE lock"; > > > + return false; > > > + } > > > + > > > + return true; > > > +} > > > + > > > +bool CameraCapabilities::validateManualPostProcessingCapability(CameraMetadata *staticMetadata) > > > +{ > > > + camera_metadata_ro_entry_t entry; > > > + bool found; > > > + > > > + const char *noMode = "Manual post processing capability unavailable: "; > > > + > > > + if (!staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AWB_AVAILABLE_MODES, > > > + ANDROID_CONTROL_AWB_MODE_OFF)) { > > > + LOG(HAL, Info) << noMode << "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)) { > > > > same question, can this just be entryContains() ? > > > > > + LOG(HAL, Info) << noMode << "missing AWB lock"; > > > + return false; > > > + } > > > + > > > + return true; > > > +} > > > + > > > +bool CameraCapabilities::validateBurstCaptureCapability(CameraMetadata *staticMetadata) > > > +{ > > > + camera_metadata_ro_entry_t entry; > > > + bool found; > > > + > > > + const char *noMode = "Burst capture capability unavailable: "; > > > + > > > + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, > > > + &entry); > > > + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { > > > > ditto, but I suspect I'm missing something as this is a recurring > > pattern :) > > > > > + LOG(HAL, Info) << noMode << "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) << noMode << "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) > > > + << noMode << "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> > > > +CameraCapabilities::computeCapabilities(CameraMetadata *staticMetadata, > > > + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps) > > > +{ > > > + std::set<camera_metadata_enum_android_request_available_capabilities> > > > + capabilities = existingCaps; > > > > Can't you just add values to existingCaps ? > > Oh I guess I can. > > > > > > + > > > + 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); > > > + > > > + if (rawStreamAvailable_) > > > + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); > > > + > > > + return capabilities; > > > +} > > > + > > > +camera_metadata_enum_android_info_supported_hardware_level > > > +CameraCapabilities::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; > > > + > > > + hwLevel_ = hwLevel; > > > + > > > + return hwLevel; > > > +} > > > + > > > int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera, > > > int orientation, int facing) > > > { > > > @@ -382,6 +523,9 @@ int CameraCapabilities::initializeStaticMetadata() > > > const ControlInfoMap &controlsInfo = camera_->controls(); > > > const ControlList &properties = camera_->properties(); > > > > > > + std::set<camera_metadata_enum_android_request_available_capabilities> > > > + capabilities = {}; > > > + > > > /* Color correction static metadata. */ > > > { > > > std::vector<uint8_t> data; > > > @@ -840,11 +984,6 @@ int CameraCapabilities::initializeStaticMetadata() > > > uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY; > > > staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType); > > > > > > - /* Info static metadata. */ > > > - uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; > > > - staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, > > > - supportedHWLevel); > > > - > > > /* Request static metadata. */ > > > int32_t partialResultCount = 1; > > > staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, > > > @@ -865,21 +1004,24 @@ int CameraCapabilities::initializeStaticMetadata() > > > staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, > > > maxNumInputStreams); > > > > > > - std::vector<uint8_t> availableCapabilities = { > > > - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, > > > - }; > > > - > > > - /* Report if camera supports RAW. */ > > > - if (rawStreamAvailable_) > > > - availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); > > > - > > > /* Number of { RAW, YUV, JPEG } supported output streams */ > > > int32_t numOutStreams[] = { rawStreamAvailable_, 2, 1 }; > > > staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, > > > numOutStreams); > > > > > > - staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, > > > - availableCapabilities); > > > + /* Check capabilities */ > > > + capabilities = computeCapabilities(staticMetadata_.get(), capabilities); > > > > Can you declate capabilities here ? It is not used before. > > Oh, right. > > > Also, what the puropse of 'existingCaps' in computeCapabilities() if > > it's empty ? Can you just return a vector to avoid the below Oh, this was from before your raw capability patch. I had the raw capability checker add the capability to the set before passing it in. I guess we can remove existingCaps now that we don't need it anymore. Paul > > conversion from set to vec ? > > I guess we can return a vector. But we'd still have a conversion, it'll > just be in computeCapabilities() instead of out. > > > > > I like the overall direction :) > > > > > > + 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: " > > > + << hwLevelStrings.find((camera_metadata_enum_android_info_supported_hardware_level)hwLevel)->second; > > > > > > std::vector<int32_t> availableCharacteristicsKeys = { > > > ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, > > > diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h > > > index 42a976d3..38ee97d0 100644 > > > --- a/src/android/camera_capabilities.h > > > +++ b/src/android/camera_capabilities.h > > > @@ -42,6 +42,18 @@ private: > > > int androidFormat; > > > }; > > > > > > + bool validateManualSensorCapability(CameraMetadata *staticMetadata); > > > + bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata); > > > + bool validateBurstCaptureCapability(CameraMetadata *staticMetadata); > > > + > > > + std::set<camera_metadata_enum_android_request_available_capabilities> > > > + computeCapabilities(CameraMetadata *staticMetadata, > > > + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps); > > > + > > > + camera_metadata_enum_android_info_supported_hardware_level > > > + computeHwLevel(CameraMetadata *staticMetadata, > > > + std::set<camera_metadata_enum_android_request_available_capabilities> capabilities); > > > + > > > std::vector<libcamera::Size> > > > initializeYUVResolutions(const libcamera::PixelFormat &pixelFormat, > > > const std::vector<libcamera::Size> &resolutions); > > > @@ -56,6 +68,7 @@ private: > > > int facing_; > > > int orientation_; > > > bool rawStreamAvailable_; > > > + camera_metadata_enum_android_info_supported_hardware_level hwLevel_; > > > > > > std::vector<Camera3StreamConfiguration> streamConfigurations_; > > > std::map<int, libcamera::PixelFormat> formatsMap_; > > > -- > > > 2.27.0 > > >
diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 9e2714f1..be55db88 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -9,6 +9,7 @@ #include <array> #include <cmath> +#include <map> #include <hardware/camera3.h> @@ -114,8 +115,148 @@ const std::map<int, const Camera3Format> camera3FormatsMap = { }, }; +const std::map<camera_metadata_enum_android_info_supported_hardware_level, std::string> +hwLevelStrings = { + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, "LIMITED" }, + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL, "FULL" }, + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, "LEGACY" }, + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3, "LEVEL_3" }, + { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, "EXTERNAL" }, +}; + } /* namespace */ +bool CameraCapabilities::validateManualSensorCapability(CameraMetadata *staticMetadata) +{ + camera_metadata_ro_entry_t entry; + bool found; + + const char *noMode = "Manual sensor capability unavailable: "; + + if (!(found = staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AE_AVAILABLE_MODES, + ANDROID_CONTROL_AE_MODE_OFF))) { + LOG(HAL, Info) + << noMode << "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) << noMode << "missing AE lock"; + return false; + } + + return true; +} + +bool CameraCapabilities::validateManualPostProcessingCapability(CameraMetadata *staticMetadata) +{ + camera_metadata_ro_entry_t entry; + bool found; + + const char *noMode = "Manual post processing capability unavailable: "; + + if (!staticMetadata->entryContains<uint8_t>(ANDROID_CONTROL_AWB_AVAILABLE_MODES, + ANDROID_CONTROL_AWB_MODE_OFF)) { + LOG(HAL, Info) << noMode << "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) << noMode << "missing AWB lock"; + return false; + } + + return true; +} + +bool CameraCapabilities::validateBurstCaptureCapability(CameraMetadata *staticMetadata) +{ + camera_metadata_ro_entry_t entry; + bool found; + + const char *noMode = "Burst capture capability unavailable: "; + + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, + &entry); + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { + LOG(HAL, Info) << noMode << "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) << noMode << "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) + << noMode << "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> +CameraCapabilities::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); + + if (rawStreamAvailable_) + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); + + return capabilities; +} + +camera_metadata_enum_android_info_supported_hardware_level +CameraCapabilities::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; + + hwLevel_ = hwLevel; + + return hwLevel; +} + int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera, int orientation, int facing) { @@ -382,6 +523,9 @@ int CameraCapabilities::initializeStaticMetadata() const ControlInfoMap &controlsInfo = camera_->controls(); const ControlList &properties = camera_->properties(); + std::set<camera_metadata_enum_android_request_available_capabilities> + capabilities = {}; + /* Color correction static metadata. */ { std::vector<uint8_t> data; @@ -840,11 +984,6 @@ int CameraCapabilities::initializeStaticMetadata() uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY; staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType); - /* Info static metadata. */ - uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; - staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, - supportedHWLevel); - /* Request static metadata. */ int32_t partialResultCount = 1; staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, @@ -865,21 +1004,24 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, maxNumInputStreams); - std::vector<uint8_t> availableCapabilities = { - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, - }; - - /* Report if camera supports RAW. */ - if (rawStreamAvailable_) - availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); - /* Number of { RAW, YUV, JPEG } supported output streams */ int32_t numOutStreams[] = { rawStreamAvailable_, 2, 1 }; staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, numOutStreams); - staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, - availableCapabilities); + /* Check capabilities */ + 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: " + << hwLevelStrings.find((camera_metadata_enum_android_info_supported_hardware_level)hwLevel)->second; std::vector<int32_t> availableCharacteristicsKeys = { ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h index 42a976d3..38ee97d0 100644 --- a/src/android/camera_capabilities.h +++ b/src/android/camera_capabilities.h @@ -42,6 +42,18 @@ private: int androidFormat; }; + bool validateManualSensorCapability(CameraMetadata *staticMetadata); + bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata); + bool validateBurstCaptureCapability(CameraMetadata *staticMetadata); + + std::set<camera_metadata_enum_android_request_available_capabilities> + computeCapabilities(CameraMetadata *staticMetadata, + std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps); + + camera_metadata_enum_android_info_supported_hardware_level + computeHwLevel(CameraMetadata *staticMetadata, + std::set<camera_metadata_enum_android_request_available_capabilities> capabilities); + std::vector<libcamera::Size> initializeYUVResolutions(const libcamera::PixelFormat &pixelFormat, const std::vector<libcamera::Size> &resolutions); @@ -56,6 +68,7 @@ private: int facing_; int orientation_; bool rawStreamAvailable_; + camera_metadata_enum_android_info_supported_hardware_level hwLevel_; std::vector<Camera3StreamConfiguration> streamConfigurations_; std::map<int, libcamera::PixelFormat> formatsMap_;
Add the infrastructure for checking and reporting capabilities. Use these capabilities to determine the hardware level as well. Bug: https://bugs.libcamera.org/show_bug.cgi?id=55 Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> --- Changes in v5: - change the whole thing to turn on capabilities after they are all confirmed, instead of disabling them as conditions are not met Changes in v4: - rebase on camera capabilities refactoring - switch to std::set from std::map - make hwlevel similar to capabilities Changes in v3: - fix some compiler errors - go ahead and initialize the capabilities to true, update the commit message accordingly Changes in v2: - add a flag for FULL, since there are a few requirements that are not obtained from capabilities alone - add burst capture capability, since that is required for FULL as well --- src/android/camera_capabilities.cpp | 172 +++++++++++++++++++++++++--- src/android/camera_capabilities.h | 13 +++ 2 files changed, 170 insertions(+), 15 deletions(-)