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