[libcamera-devel] [PATCH v3 06/14] libcamera: controls: Generate a vector of enumerated values

Jacopo Mondi jacopo at jmondi.org
Fri Oct 23 13:11:42 CEST 2020


Hi Laurent,

On Thu, Oct 22, 2020 at 05:41:13AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Wed, Oct 21, 2020 at 04:36:27PM +0200, Jacopo Mondi wrote:
> > For each Control that support enumerated values generate a vector
> > of ControlValues which contains the full list of values.
> >
> > At the expense of a slight increase in memory occupation this change
> > allows the construction of the ControlInfo associated with a Control
> > from the values list, defaulting the minimum and maximum values
> > reported by the ControlInfo.
> >
> > Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> > Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> > ---
> >  src/libcamera/control_ids.cpp.in |  2 ++
> >  utils/gen-controls.py            | 10 ++++++++++
> >  2 files changed, 12 insertions(+)
> >
> > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in
> > index 056645cfbdfb..ca0b5b22f899 100644
> > --- a/src/libcamera/control_ids.cpp.in
> > +++ b/src/libcamera/control_ids.cpp.in
> > @@ -6,8 +6,10 @@
> >   *
> >   * This file is auto-generated. Do not edit.
> >   */
> > +#include <vector>
>
> This should go to control_ids.h.in as that's where you add
> std::vector<>.
>
> >  #include <libcamera/control_ids.h>
> > +#include <libcamera/controls.h>
> >
> >  /**
> >   * \file control_ids.h
> > diff --git a/utils/gen-controls.py b/utils/gen-controls.py
> > index bf681503f86a..23aace50f666 100755
> > --- a/utils/gen-controls.py
> > +++ b/utils/gen-controls.py
> > @@ -100,6 +100,8 @@ ${description}
> >  def generate_h(controls):
> >      enum_template_start = string.Template('''enum ${name}Enum {''')
> >      enum_value_template = string.Template('''\t${name} = ${value},''')
> > +    enum_list_start = string.Template('''static const std::vector<ControlValue> ${name}Values = {''')
> > +    enum_list_values = string.Template('''\tstatic_cast<int32_t>(${name}),''')
>
> Shouldn't you declare the vector as extern const here, and define it in
> control_ids.cpp ? Otherwise you'll duplicate the values in every
> compilation unit that includes control_ids.h.

Right right right!

I used a static const as I was wrongly generating the vector
definition in the .h file as extern const, as I got a rightfull linker
error for a redefinition.

What I do have now looks like (for AeMeteringControl)

control_ids.h:
enum AeMeteringModeEnum {
	MeteringCentreWeighted = 0,
	MeteringSpot = 1,
	MeteringMatrix = 2,
	MeteringCustom = 3,
};
extern const std::vector<ControlValue> AeMeteringModeValues;
extern const Control<int32_t> AeMeteringMode;

control_ids.cpp:
extern const std::vector<ControlValue> AeMeteringModeValues = {
	static_cast<int32_t>(MeteringCentreWeighted),
	static_cast<int32_t>(MeteringSpot),
	static_cast<int32_t>(MeteringMatrix),
	static_cast<int32_t>(MeteringCustom),
};
extern const Control<int32_t> AeMeteringMode(AE_METERING_MODE, "AeMeteringMode");

Which sounds about right to me.

>
> I would also make it an std::array, to avoid global objects that have
> non-trivial constructors. But the ControlValue stored in the vector has
> a non-trivial constructor :-/ Do you expect enumerated controls with
> other types than Integer32 ? If not we could make the API more specific,
> but maybe that's not a very good idea in case we need to extend it
> later.
>
> std::array may be best anyway, even with ControlValue, as it will be
> simpler. Given that we know here how many enumerated values we generate,
> setting the number of elements in the std::array template parameter
> shouldn't be a problem. Then, you would need to modify the ControlInfo
> constructor to take a Span<ControlValue> instead of a std::vector<>.
>

I struggled for the last hour to have a construct like this one work
using std::array<> and Span<>

Using std::array<> is fine, I can easily generate that.
Using Span<> to transport the array content in the ControlInfo is not
as passing a new Span<ControlValue> contructed from an array<ControlValue, N>
calls the ControlValue contructor

	ControlValue(const T &value)
		: type_(ControlTypeNone), numElements_(0)
	{
		set(details::control_type<std::remove_cv_t<T>>::value, true,
		    value.data(), value.size(), sizeof(typename T::value_type));
	}

and not the copy constructor. The construction than fails at
        details::control_type<std::remove_cv_t<T>>::value

As no specialization is provided for control_type<ControlValue>
(rightfully.

I got away with:
        ControlInfo(ControlValue *data, unsigned int size);
Which can be easily retrieved from std::array::data() and std::array::size()

In example (raspberrypi.h)
	{
          &controls::AeMeteringMode,
          ControlInfo(controls::AeMeteringModeValues.data(),
          controls::AeMeteringModeValues.size())
        }

Which is rather ugly but can be shortened with some macro magic

To sum up:
- array: yes
- Span<ControlValue>: no
- so using array I access the raw data and transport them to the
  ControlInfo (copying them in an class member vector at the moment,
  but it can be improved)

Sincerely, I don't see much gain in all this churn compared to using a
plain std::container but I might be missing something.


> >      template = string.Template('''extern const Control<${type}> ${name};''')
> >
> >      ctrls = []
> > @@ -140,6 +142,14 @@ def generate_h(controls):
> >                  target_ctrls.append(enum_value_template.substitute(value_info))
> >              target_ctrls.append("};")
> >
> > +            target_ctrls.append(enum_list_start.substitute(info))
> > +            for entry in enum:
> > +                value_info = {
> > +                    'name': entry['name'],
> > +                }
> > +                target_ctrls.append(enum_list_values.substitute(value_info))
> > +            target_ctrls.append("};")
> > +
>
> Not a candidate for this series, but given that we will soon depend on
> jinja at build time (for IPA IPC and for tracing), I think we could
> upgrade the control and property templates to jinja templates, it should
> simplify this code.
>
> >          target_ctrls.append(template.substitute(info))
> >          id_value += 1
> >
>
> --
> Regards,
>
> Laurent Pinchart


More information about the libcamera-devel mailing list