[libcamera-devel] [PATCH v2 07/14] libcamera: controls: Support accessing controls by numerical ID

Niklas Söderlund niklas.soderlund at ragnatech.se
Sun Oct 13 17:50:53 CEST 2019


Hi Laurent,

Thanks for your patch.

On 2019-10-12 21:44:00 +0300, Laurent Pinchart wrote:
> The ControlList class has template get() and set() methods to get and
> set control values. The methods require a reference to a Control
> instance, which is only available when calling them with a hardcoded
> control. In order to support usage of ControlList for V4L2 controls, as
> well as serialisation and deserialisation of ControlList, we need a way
> to get and set control values based on a control numerical ID. Add new
> contains(), get() and set() overload methods to do so.
> 
> As this change prepares the ControlList to be used for other objects
> than camera, update its documentation accordingly.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>

> ---
>  include/libcamera/controls.h   |  10 ++-
>  src/ipa/rkisp1/rkisp1.cpp      |   2 +-
>  src/libcamera/controls.cpp     | 143 ++++++++++++++++++++++++++-------
>  src/libcamera/request.cpp      |   5 +-
>  test/controls/control_list.cpp |   2 +-
>  5 files changed, 125 insertions(+), 37 deletions(-)
> 
> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
> index 999fcf7a3a62..5e6708fe570b 100644
> --- a/include/libcamera/controls.h
> +++ b/include/libcamera/controls.h
> @@ -126,7 +126,7 @@ private:
>  	using ControlListMap = std::unordered_map<const ControlId *, ControlValue>;
>  
>  public:
> -	ControlList(ControlValidator *validator = nullptr);
> +	ControlList(const ControlIdMap &idmap, ControlValidator *validator = nullptr);
>  
>  	using iterator = ControlListMap::iterator;
>  	using const_iterator = ControlListMap::const_iterator;
> @@ -136,11 +136,13 @@ public:
>  	const_iterator begin() const { return controls_.begin(); }
>  	const_iterator end() const { return controls_.end(); }
>  
> -	bool contains(const ControlId &id) const;
>  	bool empty() const { return controls_.empty(); }
>  	std::size_t size() const { return controls_.size(); }
>  	void clear() { controls_.clear(); }
>  
> +	bool contains(const ControlId &id) const;
> +	bool contains(unsigned int id) const;
> +
>  	template<typename T>
>  	const T &get(const Control<T> &ctrl) const
>  	{
> @@ -163,11 +165,15 @@ public:
>  		val->set<T>(value);
>  	}
>  
> +	const ControlValue &get(unsigned int id) const;
> +	void set(unsigned int id, const ControlValue &value);
> +
>  private:
>  	const ControlValue *find(const ControlId &id) const;
>  	ControlValue *find(const ControlId &id);
>  
>  	ControlValidator *validator_;
> +	const ControlIdMap *idmap_;
>  	ControlListMap controls_;
>  };
>  
> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> index 80138f196184..b0d23dd154be 100644
> --- a/src/ipa/rkisp1/rkisp1.cpp
> +++ b/src/ipa/rkisp1/rkisp1.cpp
> @@ -220,7 +220,7 @@ void IPARkISP1::setControls(unsigned int frame)
>  
>  void IPARkISP1::metadataReady(unsigned int frame, unsigned int aeState)
>  {
> -	ControlList ctrls;
> +	ControlList ctrls(controls::controls);
>  
>  	if (aeState)
>  		ctrls.set(controls::AeLocked, aeState == 2);
> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
> index 292e48cd6d25..ddd4e6680ce2 100644
> --- a/src/libcamera/controls.cpp
> +++ b/src/libcamera/controls.cpp
> @@ -7,6 +7,7 @@
>  
>  #include <libcamera/controls.h>
>  
> +#include <iomanip>
>  #include <sstream>
>  #include <string>
>  
> @@ -16,13 +17,13 @@
>  
>  /**
>   * \file controls.h
> - * \brief Describes control framework and controls supported by a camera
> + * \brief Framework to handle manage controls related to an object
>   *
> - * A control is a mean to govern or influence the operation of a camera. Every
> - * control is defined by a unique numerical ID, a name string and the data type
> - * of the value it stores. The libcamera API defines a set of standard controls
> - * in the libcamera::controls namespace, as a set of instances of the Control
> - * class.
> + * A control is a mean to govern or influence the operation of an object, and in
> + * particular of a camera. Every control is defined by a unique numerical ID, a
> + * name string and the data type of the value it stores. The libcamera API
> + * defines a set of standard controls in the libcamera::controls namespace, as
> + * a set of instances of the Control class.
>   *
>   * The main way for applications to interact with controls is through the
>   * ControlList stored in the Request class:
> @@ -274,7 +275,7 @@ bool ControlValue::operator==(const ControlValue &other) const
>   * \class Control
>   * \brief Describe a control and its intrinsic properties
>   *
> - * The Control class models a control exposed by a camera. Its template type
> + * The Control class models a control exposed by an object. Its template type
>   * name T refers to the control data type, and allows methods that operate on
>   * control values to be defined as template methods using the same type T for
>   * the control value. See for instance how the ControlList::get() method
> @@ -293,8 +294,8 @@ bool ControlValue::operator==(const ControlValue &other) const
>   * long int).
>   *
>   * Controls IDs shall be unique. While nothing prevents multiple instances of
> - * the Control class to be created with the same ID, this may lead to undefined
> - * behaviour.
> + * the Control class to be created with the same ID for the same object, doing
> + * so may cause undefined behaviour.
>   */
>  
>  /**
> @@ -398,18 +399,28 @@ std::string ControlRange::toString() const
>  
>  /**
>   * \class ControlList
> - * \brief Associate a list of ControlId with their values for a camera
> + * \brief Associate a list of ControlId with their values for an object
>   *
> - * A ControlList wraps a map of ControlId to ControlValue and optionally
> - * validates controls against a ControlValidator.
> + * The ControlList class stores values of controls exposed by an object. The
> + * lists returned by the Request::controls() and Request::metadata() methods
> + * refer to the camera that the request belongs to.
> + *
> + * Control lists are constructed with a map of all the controls supported by
> + * their object, and an optional ControlValidator to further validate the
> + * controls.
>   */
>  
>  /**
>   * \brief Construct a ControlList with an optional control validator
> + * \param[in] idmap The ControlId map for the control list target object
>   * \param[in] validator The validator (may be null)
> + *
> + * For ControlList containing libcamera controls, a global map of all libcamera
> + * controls is provided by controls::controls and can be used as the \a idmap
> + * argument.
>   */
> -ControlList::ControlList(ControlValidator *validator)
> -	: validator_(validator)
> +ControlList::ControlList(const ControlIdMap &idmap, ControlValidator *validator)
> +	: validator_(validator), idmap_(&idmap)
>  {
>  }
>  
> @@ -449,20 +460,6 @@ ControlList::ControlList(ControlValidator *validator)
>   * list
>   */
>  
> -/**
> - * \brief Check if the list contains a control with the specified \a id
> - * \param[in] id The control ID
> - *
> - * The behaviour is undefined if the control \a id is not supported by the
> - * camera that the ControlList refers to.
> - *
> - * \return True if the list contains a matching control, false otherwise
> - */
> -bool ControlList::contains(const ControlId &id) const
> -{
> -	return controls_.find(&id) != controls_.end();
> -}
> -
>  /**
>   * \fn ControlList::empty()
>   * \brief Identify if the list is empty
> @@ -481,7 +478,33 @@ bool ControlList::contains(const ControlId &id) const
>   */
>  
>  /**
> - * \fn template<typename T> const T &ControlList::get() const
> + * \brief Check if the list contains a control with the specified \a id
> + * \param[in] id The control ID
> + *
> + * \return True if the list contains a matching control, false otherwise
> + */
> +bool ControlList::contains(const ControlId &id) const
> +{
> +	return controls_.find(&id) != controls_.end();
> +}
> +
> +/**
> + * \brief Check if the list contains a control with the specified \a id
> + * \param[in] id The control numerical ID
> + *
> + * \return True if the list contains a matching control, false otherwise
> + */
> +bool ControlList::contains(unsigned int id) const
> +{
> +	const auto iter = idmap_->find(id);
> +	if (iter == idmap_->end())
> +		return false;
> +
> +	return contains(*iter->second);
> +}
> +
> +/**
> + * \fn template<typename T> const T &ControlList::get(const Control<T> &ctrl) const
>   * \brief Get the value of a control
>   * \param[in] ctrl The control
>   *
> @@ -496,7 +519,7 @@ bool ControlList::contains(const ControlId &id) const
>   */
>  
>  /**
> - * \fn template<typename T> void ControlList::set()
> + * \fn template<typename T> void ControlList::set(const Control<T> &ctrl, const T &value)
>   * \brief Set the control value to \a value
>   * \param[in] ctrl The control
>   * \param[in] value The control value
> @@ -506,9 +529,67 @@ bool ControlList::contains(const ControlId &id) const
>   * to the list.
>   *
>   * The behaviour is undefined if the control \a ctrl is not supported by the
> - * camera that the list refers to.
> + * object that the list refers to.
>   */
>  
> +/**
> + * \brief Get the value of control \a id
> + * \param[in] id The control numerical ID
> + *
> + * The behaviour is undefined if the control \a id is not present in the list.
> + * Use ControlList::contains() to test for the presence of a control in the
> + * list before retrieving its value.
> + *
> + * \return The control value
> + */
> +const ControlValue &ControlList::get(unsigned int id) const
> +{
> +	static ControlValue zero;
> +
> +	const auto ctrl = idmap_->find(id);
> +	if (ctrl == idmap_->end()) {
> +		LOG(Controls, Error)
> +			<< std::hex << std::setfill('0')
> +			<< "Control 0x" << std::setw(8) << id << " is not valid";
> +		return zero;
> +	}
> +
> +	const ControlValue *val = find(*ctrl->second);
> +	if (!val)
> +		return zero;
> +
> +	return *val;
> +}
> +
> +/**
> + * \brief Set the value of control \a id to \a value
> + * \param[in] id The control ID
> + * \param[in] value The control value
> + *
> + * This method sets the value of a control in the control list. If the control
> + * is already present in the list, its value is updated, otherwise it is added
> + * to the list.
> + *
> + * The behaviour is undefined if the control \a id is not supported by the
> + * object that the list refers to.
> + */
> +void ControlList::set(unsigned int id, const ControlValue &value)
> +{
> +	const auto ctrl = idmap_->find(id);
> +	if (ctrl == idmap_->end()) {
> +		LOG(Controls, Error)
> +			<< std::hex << std::setfill('0')
> +			<< "Control 0x" << std::setw(8) << id << " is not valid";
> +		return;
> +	}
> +
> +	ControlValue *val = find(*ctrl->second);
> +	if (!val)
> +		return;
> +
> +	*val = value;
> +}
> +
>  const ControlValue *ControlList::find(const ControlId &id) const
>  {
>  	const auto iter = controls_.find(&id);
> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
> index e800f1449888..c14ed1a4d3ce 100644
> --- a/src/libcamera/request.cpp
> +++ b/src/libcamera/request.cpp
> @@ -11,6 +11,7 @@
>  
>  #include <libcamera/buffer.h>
>  #include <libcamera/camera.h>
> +#include <libcamera/control_ids.h>
>  #include <libcamera/stream.h>
>  
>  #include "camera_controls.h"
> @@ -64,12 +65,12 @@ Request::Request(Camera *camera, uint64_t cookie)
>  	 * creating a new instance for each request?
>  	 */
>  	validator_ = new CameraControlValidator(camera);
> -	controls_ = new ControlList(validator_);
> +	controls_ = new ControlList(controls::controls, validator_);
>  
>  	/**
>  	 * \todo: Add a validator for metadata controls.
>  	 */
> -	metadata_ = new ControlList();
> +	metadata_ = new ControlList(controls::controls);
>  }
>  
>  Request::~Request()
> diff --git a/test/controls/control_list.cpp b/test/controls/control_list.cpp
> index 1bcfecc467b5..5af53f64bb6c 100644
> --- a/test/controls/control_list.cpp
> +++ b/test/controls/control_list.cpp
> @@ -42,7 +42,7 @@ protected:
>  	int run()
>  	{
>  		CameraControlValidator validator(camera_.get());
> -		ControlList list(&validator);
> +		ControlList list(controls::controls, &validator);
>  
>  		/* Test that the list is initially empty. */
>  		if (!list.empty()) {
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

-- 
Regards,
Niklas Söderlund


More information about the libcamera-devel mailing list