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