libcamera  v0.3.2+188-9fc86dc0
Supporting cameras in Linux since 2019
controls.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2019, Google Inc.
4  *
5  * Control handling
6  */
7 
8 #pragma once
9 
10 #include <assert.h>
11 #include <map>
12 #include <optional>
13 #include <set>
14 #include <stdint.h>
15 #include <string>
16 #include <unordered_map>
17 #include <vector>
18 
19 #include <libcamera/base/class.h>
20 #include <libcamera/base/span.h>
21 
22 #include <libcamera/geometry.h>
23 
24 namespace libcamera {
25 
26 class ControlValidator;
27 
38  ControlTypeRectangle,
39  ControlTypeSize,
40  ControlTypePoint,
41 };
42 
43 namespace details {
44 
45 template<typename T, typename = std::void_t<>>
46 struct control_type {
47 };
48 
49 template<>
50 struct control_type<void> {
51  static constexpr ControlType value = ControlTypeNone;
52  static constexpr std::size_t size = 0;
53 };
54 
55 template<>
56 struct control_type<bool> {
57  static constexpr ControlType value = ControlTypeBool;
58  static constexpr std::size_t size = 0;
59 };
60 
61 template<>
62 struct control_type<uint8_t> {
63  static constexpr ControlType value = ControlTypeByte;
64  static constexpr std::size_t size = 0;
65 };
66 
67 template<>
68 struct control_type<uint16_t> {
69  static constexpr ControlType value = ControlTypeUnsigned16;
70  static constexpr std::size_t size = 0;
71 };
72 
73 template<>
74 struct control_type<uint32_t> {
75  static constexpr ControlType value = ControlTypeUnsigned32;
76  static constexpr std::size_t size = 0;
77 };
78 
79 template<>
80 struct control_type<int32_t> {
81  static constexpr ControlType value = ControlTypeInteger32;
82  static constexpr std::size_t size = 0;
83 };
84 
85 template<>
86 struct control_type<int64_t> {
87  static constexpr ControlType value = ControlTypeInteger64;
88  static constexpr std::size_t size = 0;
89 };
90 
91 template<>
92 struct control_type<float> {
93  static constexpr ControlType value = ControlTypeFloat;
94  static constexpr std::size_t size = 0;
95 };
96 
97 template<>
98 struct control_type<std::string> {
99  static constexpr ControlType value = ControlTypeString;
100  static constexpr std::size_t size = 0;
101 };
102 
103 template<>
104 struct control_type<Rectangle> {
105  static constexpr ControlType value = ControlTypeRectangle;
106  static constexpr std::size_t size = 0;
107 };
108 
109 template<>
110 struct control_type<Size> {
111  static constexpr ControlType value = ControlTypeSize;
112  static constexpr std::size_t size = 0;
113 };
114 
115 template<>
116 struct control_type<Point> {
117  static constexpr ControlType value = ControlTypePoint;
118  static constexpr std::size_t size = 0;
119 };
120 
121 template<typename T, std::size_t N>
122 struct control_type<Span<T, N>> : public control_type<std::remove_cv_t<T>> {
123  static constexpr std::size_t size = N;
124 };
125 
126 template<typename T>
127 struct control_type<T, std::enable_if_t<std::is_enum_v<T>>> : public control_type<int32_t> {
128 };
129 
130 } /* namespace details */
131 
133 {
134 public:
135  ControlValue();
136 
137 #ifndef __DOXYGEN__
138  template<typename T, std::enable_if_t<!details::is_span<T>::value &&
139  details::control_type<T>::value &&
140  !std::is_same<std::string, std::remove_cv_t<T>>::value,
141  std::nullptr_t> = nullptr>
142  ControlValue(const T &value)
143  : type_(ControlTypeNone), numElements_(0)
144  {
145  set(details::control_type<std::remove_cv_t<T>>::value, false,
146  &value, 1, sizeof(T));
147  }
148 
149  template<typename T, std::enable_if_t<details::is_span<T>::value ||
150  std::is_same<std::string, std::remove_cv_t<T>>::value,
151  std::nullptr_t> = nullptr>
152 #else
153  template<typename T>
154 #endif
155  ControlValue(const T &value)
156  : type_(ControlTypeNone), numElements_(0)
157  {
158  set(details::control_type<std::remove_cv_t<T>>::value, true,
159  value.data(), value.size(), sizeof(typename T::value_type));
160  }
161 
162  ~ControlValue();
163 
164  ControlValue(const ControlValue &other);
165  ControlValue &operator=(const ControlValue &other);
166 
167  ControlType type() const { return type_; }
168  bool isNone() const { return type_ == ControlTypeNone; }
169  bool isArray() const { return isArray_; }
170  std::size_t numElements() const { return numElements_; }
171  Span<const uint8_t> data() const;
172  Span<uint8_t> data();
173 
174  std::string toString() const;
175 
176  bool operator==(const ControlValue &other) const;
177  bool operator!=(const ControlValue &other) const
178  {
179  return !(*this == other);
180  }
181 
182 #ifndef __DOXYGEN__
183  template<typename T, std::enable_if_t<!details::is_span<T>::value &&
184  !std::is_same<std::string, std::remove_cv_t<T>>::value,
185  std::nullptr_t> = nullptr>
186  T get() const
187  {
188  assert(type_ == details::control_type<std::remove_cv_t<T>>::value);
189  assert(!isArray_);
190 
191  return *reinterpret_cast<const T *>(data().data());
192  }
193 
194  template<typename T, std::enable_if_t<details::is_span<T>::value ||
195  std::is_same<std::string, std::remove_cv_t<T>>::value,
196  std::nullptr_t> = nullptr>
197 #else
198  template<typename T>
199 #endif
200  T get() const
201  {
202  assert(type_ == details::control_type<std::remove_cv_t<T>>::value);
203  assert(isArray_);
204 
205  using V = typename T::value_type;
206  const V *value = reinterpret_cast<const V *>(data().data());
207  return T{ value, numElements_ };
208  }
209 
210 #ifndef __DOXYGEN__
211  template<typename T, std::enable_if_t<!details::is_span<T>::value &&
212  !std::is_same<std::string, std::remove_cv_t<T>>::value,
213  std::nullptr_t> = nullptr>
214  void set(const T &value)
215  {
216  set(details::control_type<std::remove_cv_t<T>>::value, false,
217  reinterpret_cast<const void *>(&value), 1, sizeof(T));
218  }
219 
220  template<typename T, std::enable_if_t<details::is_span<T>::value ||
221  std::is_same<std::string, std::remove_cv_t<T>>::value,
222  std::nullptr_t> = nullptr>
223 #else
224  template<typename T>
225 #endif
226  void set(const T &value)
227  {
228  set(details::control_type<std::remove_cv_t<T>>::value, true,
229  value.data(), value.size(), sizeof(typename T::value_type));
230  }
231 
232  void reserve(ControlType type, bool isArray = false,
233  std::size_t numElements = 1);
234 
235 private:
236  ControlType type_ : 8;
237  bool isArray_;
238  std::size_t numElements_ : 32;
239  union {
240  uint64_t value_;
241  void *storage_;
242  };
243 
244  void release();
245  void set(ControlType type, bool isArray, const void *data,
246  std::size_t numElements, std::size_t elementSize);
247 };
248 
250 {
251 public:
252  ControlId(unsigned int id, const std::string &name, const std::string &vendor,
253  ControlType type, std::size_t size = 0,
254  const std::map<std::string, int32_t> &enumStrMap = {});
255 
256  unsigned int id() const { return id_; }
257  const std::string &name() const { return name_; }
258  const std::string &vendor() const { return vendor_; }
259  ControlType type() const { return type_; }
260  bool isArray() const { return size_ > 0; }
261  std::size_t size() const { return size_; }
262  const std::map<int32_t, std::string> &enumerators() const { return reverseMap_; }
263 
264 private:
265  LIBCAMERA_DISABLE_COPY_AND_MOVE(ControlId)
266 
267  unsigned int id_;
268  std::string name_;
269  std::string vendor_;
270  ControlType type_;
271  std::size_t size_;
272  std::map<std::string, int32_t> enumStrMap_;
273  std::map<int32_t, std::string> reverseMap_;
274 };
275 
276 static inline bool operator==(unsigned int lhs, const ControlId &rhs)
277 {
278  return lhs == rhs.id();
279 }
280 
281 static inline bool operator!=(unsigned int lhs, const ControlId &rhs)
282 {
283  return !(lhs == rhs);
284 }
285 
286 static inline bool operator==(const ControlId &lhs, unsigned int rhs)
287 {
288  return lhs.id() == rhs;
289 }
290 
291 static inline bool operator!=(const ControlId &lhs, unsigned int rhs)
292 {
293  return !(lhs == rhs);
294 }
295 
296 template<typename T>
297 class Control : public ControlId
298 {
299 public:
300  using type = T;
301 
302  Control(unsigned int id, const char *name, const char *vendor,
303  const std::map<std::string, int32_t> &enumStrMap = {})
304  : ControlId(id, name, vendor, details::control_type<std::remove_cv_t<T>>::value,
305  details::control_type<std::remove_cv_t<T>>::size, enumStrMap)
306  {
307  }
308 
309 private:
310  LIBCAMERA_DISABLE_COPY_AND_MOVE(Control)
311 };
312 
314 {
315 public:
316  explicit ControlInfo(const ControlValue &min = {},
317  const ControlValue &max = {},
318  const ControlValue &def = {});
319  explicit ControlInfo(Span<const ControlValue> values,
320  const ControlValue &def = {});
321  explicit ControlInfo(std::set<bool> values, bool def);
322  explicit ControlInfo(bool value);
323 
324  const ControlValue &min() const { return min_; }
325  const ControlValue &max() const { return max_; }
326  const ControlValue &def() const { return def_; }
327  const std::vector<ControlValue> &values() const { return values_; }
328 
329  std::string toString() const;
330 
331  bool operator==(const ControlInfo &other) const
332  {
333  return min_ == other.min_ && max_ == other.max_;
334  }
335 
336  bool operator!=(const ControlInfo &other) const
337  {
338  return !(*this == other);
339  }
340 
341 private:
342  ControlValue min_;
343  ControlValue max_;
344  ControlValue def_;
345  std::vector<ControlValue> values_;
346 };
347 
348 using ControlIdMap = std::unordered_map<unsigned int, const ControlId *>;
349 
350 class ControlInfoMap : private std::unordered_map<const ControlId *, ControlInfo>
351 {
352 public:
353  using Map = std::unordered_map<const ControlId *, ControlInfo>;
354 
355  ControlInfoMap() = default;
356  ControlInfoMap(const ControlInfoMap &other) = default;
357  ControlInfoMap(std::initializer_list<Map::value_type> init,
358  const ControlIdMap &idmap);
359  ControlInfoMap(Map &&info, const ControlIdMap &idmap);
360 
361  ControlInfoMap &operator=(const ControlInfoMap &other) = default;
362 
363  using Map::key_type;
364  using Map::mapped_type;
365  using Map::value_type;
366  using Map::size_type;
367  using Map::iterator;
368  using Map::const_iterator;
369 
370  using Map::begin;
371  using Map::cbegin;
372  using Map::end;
373  using Map::cend;
374  using Map::at;
375  using Map::empty;
376  using Map::size;
377  using Map::count;
378  using Map::find;
379 
380  mapped_type &at(unsigned int key);
381  const mapped_type &at(unsigned int key) const;
382  size_type count(unsigned int key) const;
383  iterator find(unsigned int key);
384  const_iterator find(unsigned int key) const;
385 
386  const ControlIdMap &idmap() const { return *idmap_; }
387 
388 private:
389  bool validate();
390 
391  const ControlIdMap *idmap_ = nullptr;
392 };
393 
395 {
396 private:
397  using ControlListMap = std::unordered_map<unsigned int, ControlValue>;
398 
399 public:
400  enum class MergePolicy {
401  KeepExisting = 0,
402  OverwriteExisting,
403  };
404 
405  ControlList();
406  ControlList(const ControlIdMap &idmap, const ControlValidator *validator = nullptr);
407  ControlList(const ControlInfoMap &infoMap, const ControlValidator *validator = nullptr);
408 
409  using iterator = ControlListMap::iterator;
410  using const_iterator = ControlListMap::const_iterator;
411 
412  iterator begin() { return controls_.begin(); }
413  iterator end() { return controls_.end(); }
414  const_iterator begin() const { return controls_.begin(); }
415  const_iterator end() const { return controls_.end(); }
416 
417  bool empty() const { return controls_.empty(); }
418  std::size_t size() const { return controls_.size(); }
419 
420  void clear() { controls_.clear(); }
421  void merge(const ControlList &source, MergePolicy policy = MergePolicy::KeepExisting);
422 
423  bool contains(unsigned int id) const;
424 
425  template<typename T>
426  std::optional<T> get(const Control<T> &ctrl) const
427  {
428  const auto entry = controls_.find(ctrl.id());
429  if (entry == controls_.end())
430  return std::nullopt;
431 
432  const ControlValue &val = entry->second;
433  return val.get<T>();
434  }
435 
436  template<typename T, typename V>
437  void set(const Control<T> &ctrl, const V &value)
438  {
439  ControlValue *val = find(ctrl.id());
440  if (!val)
441  return;
442 
443  val->set<T>(value);
444  }
445 
446  template<typename T, typename V, size_t Size>
447  void set(const Control<Span<T, Size>> &ctrl, const std::initializer_list<V> &value)
448  {
449  ControlValue *val = find(ctrl.id());
450  if (!val)
451  return;
452 
453  val->set(Span<const typename std::remove_cv_t<V>, Size>{ value.begin(), value.size() });
454  }
455 
456  const ControlValue &get(unsigned int id) const;
457  void set(unsigned int id, const ControlValue &value);
458 
459  const ControlInfoMap *infoMap() const { return infoMap_; }
460  const ControlIdMap *idMap() const { return idmap_; }
461 
462 private:
463  const ControlValue *find(unsigned int id) const;
464  ControlValue *find(unsigned int id);
465 
466  const ControlValidator *validator_;
467  const ControlIdMap *idmap_;
468  const ControlInfoMap *infoMap_;
469 
470  ControlListMap controls_;
471 };
472 
473 } /* namespace libcamera */
bool isArray() const
Determine if the control is an array control.
Definition: controls.h:260
ControlType type() const
Retrieve the data type of the value.
Definition: controls.h:167
ControlValue(const T &value)
Construct a ControlValue of type T.
Definition: controls.h:155
bool operator!=(const ControlValue &other) const
Compare ControlValue instances for non equality.
Definition: controls.h:177
Describe the limits of valid values for a Control.
Definition: controls.h:313
const ControlInfoMap * infoMap() const
Retrieve the ControlInfoMap used to construct the ControlList.
Definition: controls.h:459
const std::string & name() const
Retrieve the control name.
Definition: controls.h:257
T type
The Control template type T.
Definition: controls.h:300
bool operator==(const ColorSpace &lhs, const ColorSpace &rhs)
Compare color spaces for equality.
Definition: color_space.cpp:506
const std::string & vendor() const
Retrieve the vendor name.
Definition: controls.h:258
const ControlValue & def() const
Retrieve the default value of the control.
Definition: controls.h:326
Top-level libcamera namespace.
Definition: bound_method.h:15
const std::map< int32_t, std::string > & enumerators() const
Retrieve the map of enum values to enum names.
Definition: controls.h:262
Abstract type representing the value of a control.
Definition: controls.h:132
void set(const T &value)
Set the control value to value.
Definition: controls.h:226
bool isArray() const
Determine if the value stores an array.
Definition: controls.h:169
Definition: controls.h:34
Control static metadata.
Definition: controls.h:249
void clear()
Removes all controls from the list.
Definition: controls.h:420
Describe a two-dimensional size.
Definition: geometry.h:52
Definition: controls.h:33
Describe a control and its intrinsic properties.
Definition: controls.h:297
bool operator!=(const ControlInfo &other) const
Compare ControlInfo instances for non equality.
Definition: controls.h:336
const std::vector< ControlValue > & values() const
Retrieve the list of valid values.
Definition: controls.h:327
const ControlIdMap * idMap() const
Retrieve the ControlId map used to construct the ControlList.
Definition: controls.h:460
A map of ControlId to ControlInfo.
Definition: controls.h:350
Definition: controls.h:29
bool empty() const
Identify if the list is empty.
Definition: controls.h:417
Definition: controls.h:36
std::unordered_map< const ControlId *, ControlInfo > Map
The base std::unsorted_map<> container.
Definition: controls.h:353
Definition: controls.h:30
ControlType
Define the data type of a Control.
Definition: controls.h:28
ControlListMap::iterator iterator
Iterator for the controls contained within the list.
Definition: controls.h:409
const ControlIdMap & idmap() const
Retrieve the ControlId map.
Definition: controls.h:386
std::size_t size() const
Retrieve the size of the control if it is an array control.
Definition: controls.h:261
ControlListMap::const_iterator const_iterator
Const iterator for the controls contained within the list.
Definition: controls.h:410
const ControlValue & min() const
Retrieve the minimum value of the control.
Definition: controls.h:324
iterator end()
Retrieve an iterator pointing to the past-the-end control in the list.
Definition: controls.h:413
Definition: controls.h:35
iterator begin()
Retrieve an iterator to the first Control in the list.
Definition: controls.h:412
Definition: controls.h:32
unsigned int id() const
Retrieve the control numerical ID.
Definition: controls.h:256
Definition: controls.h:37
const_iterator end() const
Retrieve a const iterator pointing to the past-the-end control in the list.
Definition: controls.h:415
Control(unsigned int id, const char *name, const char *vendor, const std::map< std::string, int32_t > &enumStrMap={})
Construct a Control instance.
Definition: controls.h:302
const ControlValue & max() const
Retrieve the maximum value of the control.
Definition: controls.h:325
std::size_t size() const
Retrieve the number of controls in the list.
Definition: controls.h:418
ControlType type() const
Retrieve the control data type.
Definition: controls.h:259
Associate a list of ControlId with their values for an object.
Definition: controls.h:394
Data structures related to geometric objects.
bool isNone() const
Determine if the value is not initialised.
Definition: controls.h:168
Definition: controls.h:31
bool operator==(const ControlInfo &other) const
Compare ControlInfo instances for equality.
Definition: controls.h:331
std::unordered_map< unsigned int, const ControlId * > ControlIdMap
A map of numerical control ID to ControlId.
Definition: controls.h:348
MergePolicy
The policy used by the merge function.
Definition: controls.h:400
T get() const
Get the control value.
Definition: controls.h:200
std::size_t numElements() const
Retrieve the number of elements stored in the ControlValue.
Definition: controls.h:170
const_iterator begin() const
Retrieve a const_iterator to the first Control in the list.
Definition: controls.h:414