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