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