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