libcamera  v0.4.0+67-32cc6717
Supporting cameras in Linux since 2019
ipa_data_serializer.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2020, Google Inc.
4  *
5  * Image Processing Algorithm data serializer
6  */
7 
8 #pragma once
9 
10 #include <stdint.h>
11 #include <string.h>
12 #include <tuple>
13 #include <type_traits>
14 #include <vector>
15 
16 #include <libcamera/base/flags.h>
17 #include <libcamera/base/log.h>
18 
19 #include <libcamera/control_ids.h>
20 #include <libcamera/framebuffer.h>
21 #include <libcamera/geometry.h>
22 
24 
26 
27 namespace libcamera {
28 
29 LOG_DECLARE_CATEGORY(IPADataSerializer)
30 
31 namespace {
32 
33 template<typename T,
34  std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
35 void appendPOD(std::vector<uint8_t> &vec, T val)
36 {
37  constexpr size_t byteWidth = sizeof(val);
38  vec.resize(vec.size() + byteWidth);
39  memcpy(&*(vec.end() - byteWidth), &val, byteWidth);
40 }
41 
42 template<typename T,
43  std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
44 T readPOD(std::vector<uint8_t>::const_iterator it, size_t pos,
45  std::vector<uint8_t>::const_iterator end)
46 {
47  ASSERT(pos + it < end);
48 
49  T ret = 0;
50  memcpy(&ret, &(*(it + pos)), sizeof(ret));
51 
52  return ret;
53 }
54 
55 template<typename T,
56  std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
57 T readPOD(std::vector<uint8_t> &vec, size_t pos)
58 {
59  return readPOD<T>(vec.cbegin(), pos, vec.end());
60 }
61 
62 } /* namespace */
63 
64 template<typename T>
66 {
67 public:
68  static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>>
69  serialize(const T &data, ControlSerializer *cs = nullptr);
70 
71  static T deserialize(const std::vector<uint8_t> &data,
72  ControlSerializer *cs = nullptr);
73  static T deserialize(std::vector<uint8_t>::const_iterator dataBegin,
74  std::vector<uint8_t>::const_iterator dataEnd,
75  ControlSerializer *cs = nullptr);
76 
77  static T deserialize(const std::vector<uint8_t> &data,
78  const std::vector<SharedFD> &fds,
79  ControlSerializer *cs = nullptr);
80  static T deserialize(std::vector<uint8_t>::const_iterator dataBegin,
81  std::vector<uint8_t>::const_iterator dataEnd,
82  std::vector<SharedFD>::const_iterator fdsBegin,
83  std::vector<SharedFD>::const_iterator fdsEnd,
84  ControlSerializer *cs = nullptr);
85 };
86 
87 #ifndef __DOXYGEN__
88 
89 /*
90  * Serialization format for vector of type V:
91  *
92  * 4 bytes - uint32_t Length of vector, in number of elements
93  *
94  * For every element in the vector:
95  *
96  * 4 bytes - uint32_t Size of element, in bytes
97  * 4 bytes - uint32_t Number of fds for the element
98  * X bytes - Serialized element
99  *
100  * \todo Support elements that are references
101  */
102 template<typename V>
103 class IPADataSerializer<std::vector<V>>
104 {
105 public:
106  static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>>
107  serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr)
108  {
109  std::vector<uint8_t> dataVec;
110  std::vector<SharedFD> fdsVec;
111 
112  /* Serialize the length. */
113  uint32_t vecLen = data.size();
114  appendPOD<uint32_t>(dataVec, vecLen);
115 
116  /* Serialize the members. */
117  for (auto const &it : data) {
118  std::vector<uint8_t> dvec;
119  std::vector<SharedFD> fvec;
120 
121  std::tie(dvec, fvec) =
123 
124  appendPOD<uint32_t>(dataVec, dvec.size());
125  appendPOD<uint32_t>(dataVec, fvec.size());
126 
127  dataVec.insert(dataVec.end(), dvec.begin(), dvec.end());
128  fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end());
129  }
130 
131  return { dataVec, fdsVec };
132  }
133 
134  static std::vector<V> deserialize(std::vector<uint8_t> &data, ControlSerializer *cs = nullptr)
135  {
136  return deserialize(data.cbegin(), data.cend(), cs);
137  }
138 
139  static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
140  std::vector<uint8_t>::const_iterator dataEnd,
141  ControlSerializer *cs = nullptr)
142  {
143  std::vector<SharedFD> fds;
144  return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.cend(), cs);
145  }
146 
147  static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds,
148  ControlSerializer *cs = nullptr)
149  {
150  return deserialize(data.cbegin(), data.cend(), fds.cbegin(), fds.cend(), cs);
151  }
152 
153  static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
154  std::vector<uint8_t>::const_iterator dataEnd,
155  std::vector<SharedFD>::const_iterator fdsBegin,
156  [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd,
157  ControlSerializer *cs = nullptr)
158  {
159  uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd);
160  std::vector<V> ret(vecLen);
161 
162  std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4;
163  std::vector<SharedFD>::const_iterator fdIter = fdsBegin;
164  for (uint32_t i = 0; i < vecLen; i++) {
165  uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd);
166  uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd);
167  dataIter += 8;
168 
169  ret[i] = IPADataSerializer<V>::deserialize(dataIter,
170  dataIter + sizeofData,
171  fdIter,
172  fdIter + sizeofFds,
173  cs);
174 
175  dataIter += sizeofData;
176  fdIter += sizeofFds;
177  }
178 
179  return ret;
180  }
181 };
182 
183 /*
184  * Serialization format for map of key type K and value type V:
185  *
186  * 4 bytes - uint32_t Length of map, in number of pairs
187  *
188  * For every pair in the map:
189  *
190  * 4 bytes - uint32_t Size of key, in bytes
191  * 4 bytes - uint32_t Number of fds for the key
192  * X bytes - Serialized key
193  * 4 bytes - uint32_t Size of value, in bytes
194  * 4 bytes - uint32_t Number of fds for the value
195  * X bytes - Serialized value
196  *
197  * \todo Support keys or values that are references
198  */
199 template<typename K, typename V>
200 class IPADataSerializer<std::map<K, V>>
201 {
202 public:
203  static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>>
204  serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr)
205  {
206  std::vector<uint8_t> dataVec;
207  std::vector<SharedFD> fdsVec;
208 
209  /* Serialize the length. */
210  uint32_t mapLen = data.size();
211  appendPOD<uint32_t>(dataVec, mapLen);
212 
213  /* Serialize the members. */
214  for (auto const &it : data) {
215  std::vector<uint8_t> dvec;
216  std::vector<SharedFD> fvec;
217 
218  std::tie(dvec, fvec) =
219  IPADataSerializer<K>::serialize(it.first, cs);
220 
221  appendPOD<uint32_t>(dataVec, dvec.size());
222  appendPOD<uint32_t>(dataVec, fvec.size());
223 
224  dataVec.insert(dataVec.end(), dvec.begin(), dvec.end());
225  fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end());
226 
227  std::tie(dvec, fvec) =
228  IPADataSerializer<V>::serialize(it.second, cs);
229 
230  appendPOD<uint32_t>(dataVec, dvec.size());
231  appendPOD<uint32_t>(dataVec, fvec.size());
232 
233  dataVec.insert(dataVec.end(), dvec.begin(), dvec.end());
234  fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end());
235  }
236 
237  return { dataVec, fdsVec };
238  }
239 
240  static std::map<K, V> deserialize(std::vector<uint8_t> &data, ControlSerializer *cs = nullptr)
241  {
242  return deserialize(data.cbegin(), data.cend(), cs);
243  }
244 
245  static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
246  std::vector<uint8_t>::const_iterator dataEnd,
247  ControlSerializer *cs = nullptr)
248  {
249  std::vector<SharedFD> fds;
250  return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.cend(), cs);
251  }
252 
253  static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds,
254  ControlSerializer *cs = nullptr)
255  {
256  return deserialize(data.cbegin(), data.cend(), fds.cbegin(), fds.cend(), cs);
257  }
258 
259  static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
260  std::vector<uint8_t>::const_iterator dataEnd,
261  std::vector<SharedFD>::const_iterator fdsBegin,
262  [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd,
263  ControlSerializer *cs = nullptr)
264  {
265  std::map<K, V> ret;
266 
267  uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd);
268 
269  std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4;
270  std::vector<SharedFD>::const_iterator fdIter = fdsBegin;
271  for (uint32_t i = 0; i < mapLen; i++) {
272  uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd);
273  uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd);
274  dataIter += 8;
275 
276  K key = IPADataSerializer<K>::deserialize(dataIter,
277  dataIter + sizeofData,
278  fdIter,
279  fdIter + sizeofFds,
280  cs);
281 
282  dataIter += sizeofData;
283  fdIter += sizeofFds;
284  sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd);
285  sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd);
286  dataIter += 8;
287 
288  const V value = IPADataSerializer<V>::deserialize(dataIter,
289  dataIter + sizeofData,
290  fdIter,
291  fdIter + sizeofFds,
292  cs);
293  ret.insert({ key, value });
294 
295  dataIter += sizeofData;
296  fdIter += sizeofFds;
297  }
298 
299  return ret;
300  }
301 };
302 
303 /* Serialization format for Flags is same as for PODs */
304 template<typename E>
305 class IPADataSerializer<Flags<E>>
306 {
307 public:
308  static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>>
309  serialize(const Flags<E> &data, [[maybe_unused]] ControlSerializer *cs = nullptr)
310  {
311  std::vector<uint8_t> dataVec;
312  dataVec.reserve(sizeof(Flags<E>));
313  appendPOD<uint32_t>(dataVec, static_cast<typename Flags<E>::Type>(data));
314 
315  return { dataVec, {} };
316  }
317 
318  static Flags<E> deserialize(std::vector<uint8_t> &data,
319  [[maybe_unused]] ControlSerializer *cs = nullptr)
320  {
321  return deserialize(data.cbegin(), data.cend());
322  }
323 
324  static Flags<E> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
325  std::vector<uint8_t>::const_iterator dataEnd,
326  [[maybe_unused]] ControlSerializer *cs = nullptr)
327  {
328  return Flags<E>{ static_cast<E>(readPOD<uint32_t>(dataBegin, 0, dataEnd)) };
329  }
330 
331  static Flags<E> deserialize(std::vector<uint8_t> &data,
332  [[maybe_unused]] std::vector<SharedFD> &fds,
333  [[maybe_unused]] ControlSerializer *cs = nullptr)
334  {
335  return deserialize(data.cbegin(), data.cend());
336  }
337 
338  static Flags<E> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
339  std::vector<uint8_t>::const_iterator dataEnd,
340  [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin,
341  [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd,
342  [[maybe_unused]] ControlSerializer *cs = nullptr)
343  {
344  return deserialize(dataBegin, dataEnd);
345  }
346 };
347 
348 #endif /* __DOXYGEN__ */
349 
350 } /* namespace libcamera */
Frame buffer handling.
Camera controls identifiers.
Image Processing Algorithm interface.
Top-level libcamera namespace.
Definition: backtrace.h:17
#define ASSERT(condition)
Abort program execution if assertion fails.
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
Serializer and deserializer for control-related classes.
Definition: control_serializer.h:20
std::underlying_type_t< E > Type
The underlying data type of the enum.
Definition: flags.h:21
static T deserialize(const std::vector< uint8_t > &data, ControlSerializer *cs=nullptr)
Deserialize byte vector into an object.
IPA Data Serializer.
Definition: ipa_data_serializer.h:65
Enum-based bit fields.
static std::tuple< std::vector< uint8_t >, std::vector< SharedFD > > serialize(const T &data, ControlSerializer *cs=nullptr)
Serialize an object into byte vector and fd vector.
Type-safe container for enum-based bitfields.
Definition: flags.h:15
Data structures related to geometric objects.
Logging infrastructure.
Serialization and deserialization helpers for controls.