[libcamera-devel] [PATCH v7 5/9] android: Add infrastructure for determining capabilities and hardware level
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Aug 2 03:19:10 CEST 2021
Hi Paul,
Thank you for the patch.
On Fri, Jul 30, 2021 at 07:35:32PM +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 at ideasonboard.com>
>
> ---
> Changes in v7:
> - use entryContains for the single-presence checks
> - go back to set
> - use the staticMetadata_ member variable instead of passing it
> - return false in the capaibilities detector, with a todo item
>
> Changes in v6:
> - make all args const
> - convert the caps list from set to vector
>
> 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 | 202 +++++++++++++++++++++++++---
> src/android/camera_capabilities.h | 11 ++
> 2 files changed, 198 insertions(+), 15 deletions(-)
>
> diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
> index 3596b136..b59a854f 100644
> --- a/src/android/camera_capabilities.cpp
> +++ b/src/android/camera_capabilities.cpp
> @@ -7,8 +7,10 @@
>
> #include "camera_capabilities.h"
>
> +#include <algorithm>
> #include <array>
> #include <cmath>
> +#include <map>
>
> #include <hardware/camera3.h>
>
> @@ -114,8 +116,180 @@ 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()
> +{
> + const char *noMode = "Manual sensor capability unavailable: ";
> +
> + if (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AE_AVAILABLE_MODES,
> + ANDROID_CONTROL_AE_MODE_OFF)) {
> + LOG(HAL, Info) << noMode << "missing AE mode off";
> + return false;
> + }
> +
> + if (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
> + ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {
> + LOG(HAL, Info) << noMode << "missing AE lock";
> + 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
> + * Manual frame duration control
> + * android.sensor.frameDuration
> + * android.sensor.info.maxFrameDuration
> + * Manual exposure control
> + * android.sensor.exposureTime
> + * android.sensor.info.exposureTimeRange
> + * Manual sensitivity control
> + * android.sensor.sensitivity
> + * android.sensor.info.sensitivityRange
> + * Manual lens control (if the lens is adjustable)
> + * android.lens.*
> + * Manual flash control (if a flash unit is present)
> + * android.flash.*
> + * Manual black level locking
> + * android.blackLevel.lock
> + * Auto exposure lock
> + * android.control.aeLock
> + */
> + return false;
> +}
> +
> +bool CameraCapabilities::validateManualPostProcessingCapability()
> +{
> + 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;
> + }
> +
> + if (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
> + ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {
> + LOG(HAL, Info) << noMode << "missing AWB lock";
> + 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_POST_PROCESSING
> + * Manual tonemap control
> + * android.tonemap.curve
> + * android.tonemap.mode
> + * android.tonemap.maxCurvePoints
> + * android.tonemap.gamma
> + * android.tonemap.presetCurve
> + * Manual white balance control
> + * android.colorCorrection.transform
> + * android.colorCorrection.gains
> + * Manual lens shading map control
> + * android.shading.mode
> + * android.statistics.lensShadingMapMode
> + * android.statistics.lensShadingMap
> + * android.lens.info.shadingMapSize
> + * Manual aberration correction control (if aberration correction is supported)
> + * android.colorCorrection.aberrationMode
> + * android.colorCorrection.availableAberrationModes
> + * Auto white balance lock
> + * android.control.awbLock
> + */
> + return false;
> +}
> +
> +bool CameraCapabilities::validateBurstCaptureCapability()
> +{
> + camera_metadata_ro_entry_t entry;
> + bool found;
> +
> + const char *noMode = "Burst capture capability unavailable: ";
> +
> + if (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
> + ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {
> + LOG(HAL, Info) << noMode << "missing AE lock";
> + return false;
> + }
> +
> + if (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
> + 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) {
Not sure if you've seen my last e-mail about this in v5 :-)
> + LOG(HAL, Info)
> + << noMode << "max sync latency is "
> + << (found ? std::to_string(*entry.data.i32) : "not present");
> + return false;
> + }
> +
> + /*
> + * \todo return true here after we satisfy all the requirements
> + * https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
> + */
> + return false;
> +}
> +
> +std::set<camera_metadata_enum_android_request_available_capabilities>
> +CameraCapabilities::computeCapabilities()
> +{
> + std::set<camera_metadata_enum_android_request_available_capabilities>
> + capabilities;
> +
> + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
> +
> + if (validateManualSensorCapability())
> + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
> +
> + if (validateManualPostProcessingCapability())
> + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
> +
> + if (validateBurstCaptureCapability())
> + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
> +
> + if (rawStreamAvailable_)
> + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
> +
> + return capabilities;
> +}
> +
> +void CameraCapabilities::computeHwLevel(
> + const std::set<camera_metadata_enum_android_request_available_capabilities> &caps)
> +{
> + camera_metadata_ro_entry_t entry;
> + bool found;
> + camera_metadata_enum_android_info_supported_hardware_level
> + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
> +
> + if (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR))
> + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
> +
> + if (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING))
> + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
> +
> + if (!caps.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;
You could use hwLevel_ through the function and drop the local variable,
up to you.
> +}
> +
> int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera,
> int orientation, int facing)
> {
> @@ -851,11 +1025,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,
> @@ -876,21 +1045,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 */
> + std::set<camera_metadata_enum_android_request_available_capabilities>
> + capabilities = computeCapabilities();
> + std::vector<camera_metadata_enum_android_request_available_capabilities>
> + capsVec(capabilities.begin(), capabilities.end());
> + staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capsVec);
> +
> + computeHwLevel(capabilities);
> + staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, hwLevel_);
> +
> + LOG(HAL, Info)
> + << "Hardware level: "
> + << hwLevelStrings.find(hwLevel_)->second;
The last two lines hold on a single line.
With these comments addressed or not,
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>
> 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..c7a966ce 100644
> --- a/src/android/camera_capabilities.h
> +++ b/src/android/camera_capabilities.h
> @@ -42,6 +42,16 @@ private:
> int androidFormat;
> };
>
> + bool validateManualSensorCapability();
> + bool validateManualPostProcessingCapability();
> + bool validateBurstCaptureCapability();
> +
> + std::set<camera_metadata_enum_android_request_available_capabilities>
> + computeCapabilities();
> +
> + void computeHwLevel(
> + const std::set<camera_metadata_enum_android_request_available_capabilities> &caps);
> +
> std::vector<libcamera::Size>
> initializeYUVResolutions(const libcamera::PixelFormat &pixelFormat,
> const std::vector<libcamera::Size> &resolutions);
> @@ -56,6 +66,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_;
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list