[libcamera-devel] [RFC PATCH v3 03/16] android: Add helpers for setting android metadata from libcamera controls
Jacopo Mondi
jacopo at jmondi.org
Mon Jul 5 17:44:58 CEST 2021
Hi Paul,
On Fri, Jul 02, 2021 at 07:37:47PM +0900, Paul Elder wrote:
> Add helpers for setting android metadata from libcamera controls.
>
> There are two versions, for scalars and collections, both of which take
> a default value to fill in the android control if the libcamera control
> is not found. A version for scalars exists for no default, to not set
> the android control at all if it is not found in libcamera. The
> functions take two template parameters, the first for the android type,
> and the second for the libcamera type of the control. They can be
> different, for example, if the former is an enum and the latter is a
> boolean, or if the former is an enum (uint8_t) and the latter is an enum
> (int32_t).
>
> The versions that take a default value return the value that was set in
> the android metadata.
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
>
> ---
> Changes in v3:
> - setMetadata for collection only works with vectors
> - change enum to enum class
> - add two template parameters for android type and libcamera type
> - add docs
>
> New in v2
>
> TODO: make ControlList versions so that we can use them in result
> metadata
> ---
> src/android/camera_capabilities.cpp | 137 ++++++++++++++++++++++++++++
> 1 file changed, 137 insertions(+)
>
> diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
> index 54bd71da..1d4c44ce 100644
> --- a/src/android/camera_capabilities.cpp
> +++ b/src/android/camera_capabilities.cpp
> @@ -124,6 +124,143 @@ hwLevelStrings = {
> { ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, "EXTERNAL" },
> };
>
> +enum class ControlRange {
> + Min,
> + Def,
> + Max,
> +};
> +
> +/**
We don't parse the HAL with doxygen so you can spare the additional *
But it's more than fine to use the Doxygen syntax when documenting
things imho, mostly for consistency
> + * \brief Set android metadata from libcamera ControlInfo
> + * \tparam T Type of the control in android
> + * \tparam V Type of the control in libcamera
> + * \param[in] metadata Android metadata to add the control value to
s/Android metadata/Android metadata pack/
> + * \param[in] tag Android metadata tag to add
s/to add// ?
> + * \param[in] controlsInfo libcamera ControlInfoMap from which to find the control info
> + * \param[in] control libcamera ControlId to find from \a controlsInfo
> + * \param[in] controlRange Whether to use the min, def, or max value from the control info
> + *
> + * Set the android metadata entry in \a metadata with tag \a tag based on the
Set the android metadata \a tag in the \a metadata pack based on
the...
> + * control info found for the libcamera control \a control in the libcamera
> + * ControlInfoMap \a controlsInfo. If no libcamera ControlInfo is found, then
> + * the function returns without modifying anything.
> + *
> + * This function is for scalar values.
> + */
> +template<typename T,
> + std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr,
You should include <type_traits>
Do you need this to solve which overload ? I see three functions here
with the following prototypes
void setMetadata(CameraMetadata *metadata, uint32_t tag,
const ControlInfoMap &controlsInfo, const ControlId *control,
enum ControlRange controlRange)
T setMetadata(CameraMetadata *metadata, uint32_t tag,
const ControlInfoMap &controlsInfo, const ControlId *control,
enum ControlRange controlRange, const V defaultValue)
std::vector<T> setMetadata(CameraMetadata *metadata, uint32_t tag,
const ControlInfoMap &controlsInfo,
const ControlId *control,
const std::vector<T> &defaultVector)
There doesn't seem to be any need to distinguish them on the template parameter
type.
> + typename V>
> +void setMetadata(CameraMetadata *metadata, uint32_t tag,
> + const ControlInfoMap &controlsInfo, const ControlId *control,
> + enum ControlRange controlRange)
> +{
> + const auto &info = controlsInfo.find(control);
> + if (info == controlsInfo.end())
> + return;
> +
> + T ret;
> + switch (controlRange) {
> + case ControlRange::Min:
> + ret = info->second.min().get<V>();
> + break;
> + case ControlRange::Def:
> + ret = info->second.def().get<V>();
> + break;
> + case ControlRange::Max:
> + ret = info->second.max().get<V>();
> + break;
> + }
> +
> + metadata->addEntry(tag, ret);
> + return;
> +}
> +
> +/**
> + * \brief Set android metadata from libcamera ControlInfo or a default value
> + * \tparam T Type of the control in android
> + * \tparam U Type of the control in libcamera
> + * \param[in] metadata Android metadata to add the control value to
> + * \param[in] tag Android metadata tag to add
> + * \param[in] controlsInfo libcamera ControlInfoMap from which to find the control info
> + * \param[in] control libcamera ControlId to find from \a controlsInfo
> + * \param[in] controlRange Whether to use the min, def, or max value from the control info
> + * \param[in] defaultValue The value to set in \a metadata if \a control is not found
> + *
> + * Set the android metadata entry in \a metadata with tag \a tag based on the
> + * control info found for the libcamera control \a control in the libcamera
> + * ControlInfoMap \a controlsInfo. If no libcamera ControlInfo is found, then
> + * the android metadata entry is set to \a defaultValue.
> + *
> + * This function is for scalar values.
> + */
> +template<typename T,
> + typename U,
> + typename V,
Isn't V the same type as T ?
> + std::enable_if_t<std::is_arithmetic_v<V>> * = nullptr>
This is probably functionally equivalent for now, but in the previous
version you were checking for the type T to be an arithmetic type.
> +T setMetadata(CameraMetadata *metadata, uint32_t tag,
> + const ControlInfoMap &controlsInfo, const ControlId *control,
> + enum ControlRange controlRange, const V defaultValue)
> +{
> + T ret = defaultValue;
> +
> + const auto &info = controlsInfo.find(control);
> + if (info != controlsInfo.end()) {
> + switch (controlRange) {
> + case ControlRange::Min:
> + ret = info->second.min().get<U>();
> + break;
> + case ControlRange::Def:
> + ret = info->second.def().get<U>();
> + break;
> + case ControlRange::Max:
> + ret = info->second.max().get<U>();
> + break;
> + }
> + }
> +
> + metadata->addEntry(tag, ret);
> + return ret;
> +}
> +
> +/**
> + * \brief Set android metadata from libcamera ControlInfo or a default value
> + * \tparam T Type of the control in android
> + * \tparam V Type of the control in libcamera
> + * \param[in] metadata Android metadata to add the control value to
> + * \param[in] tag Android metadata tag to add
> + * \param[in] controlsInfo libcamera ControlInfoMap from which to find the control info
> + * \param[in] control libcamera ControlId to find from \a controlsInfo
> + * \param[in] defaultVector The value to set in \a metadata if \a control is not found
> + *
> + * Set the android metadata entry in \a metadata with tag \a tag based on the
> + * control info found for the libcamera control \a control in the libcamera
> + * ControlInfoMap \a controlsInfo. If no libcamera ControlInfo is found, then
> + * the android metadata entry is set to \a defaultVector.
> + *
> + * This function is for vector values.
> + */
> +template<typename T,
> + typename V>
Fits on one line
> +std::vector<T> setMetadata(CameraMetadata *metadata, uint32_t tag,
> + const ControlInfoMap &controlsInfo,
> + const ControlId *control,
> + const std::vector<T> &defaultVector)
> +{
> + std::vector<T> ret = {};
> +
> + const auto &info = controlsInfo.find(control);
> + if (info != controlsInfo.end()) {
> + ret.reserve(info->second.values().size());
> + for (const auto &value : info->second.values())
> + ret.push_back(value.get<V>());
> + } else {
> + ret = defaultVector;
this is a copy that could be avoided by calling addEntry() in each
branch. Something like
const auto &info = controlsInfo.find(control);
if (info == controlsInfo.end()) {
metadata->addEntry(tag, defaultVector);
return defaultVector;
}
std::vector<T> ret(info->second.values().size());
for (const auto &value : info->second.values())
ret.push_back(value.get<V>());
metadata->addEntry(tag, ret);
return ret;
> + }
> +
> + metadata->addEntry(tag, ret);
> + return ret;
> +}
> +
> } /* namespace */
>
> int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera,
> --
> 2.27.0
>
More information about the libcamera-devel
mailing list