libcamera v0.3.2
Supporting cameras in Linux since 2019
Loading...
Searching...
No Matches
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
16#include <libcamera/base/log.h>
17
20#include <libcamera/geometry.h>
21
23
25
26namespace libcamera {
27
28LOG_DECLARE_CATEGORY(IPADataSerializer)
29
30namespace {
31
32template<typename T,
33 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
34void 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
41template<typename T,
42 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
43T 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
54template<typename T,
55 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
56T readPOD(std::vector<uint8_t> &vec, size_t pos)
57{
58 return readPOD<T>(vec.cbegin(), pos, vec.end());
59}
60
61} /* namespace */
62
63template<typename T>
65{
66public:
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 */
101template<typename V>
102class IPADataSerializer<std::vector<V>>
103{
104public:
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 */
198template<typename K, typename V>
199class IPADataSerializer<std::map<K, V>>
200{
201public:
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) =
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 */
303template<typename E>
304class IPADataSerializer<Flags<E>>
305{
306public:
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 */
Serializer and deserializer for control-related classes.
Definition control_serializer.h:21
std::underlying_type_t< E > Type
The underlying data type of the enum.
Definition flags.h:21
IPA Data Serializer.
Definition ipa_data_serializer.h:65
static T deserialize(std::vector< uint8_t >::const_iterator dataBegin, std::vector< uint8_t >::const_iterator dataEnd, std::vector< SharedFD >::const_iterator fdsBegin, std::vector< SharedFD >::const_iterator fdsEnd, ControlSerializer *cs=nullptr)
Deserialize byte vector and fd vector into an object.
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.
static T deserialize(std::vector< uint8_t >::const_iterator dataBegin, std::vector< uint8_t >::const_iterator dataEnd, ControlSerializer *cs=nullptr)
Deserialize byte vector into an object.
static T deserialize(const std::vector< uint8_t > &data, const std::vector< SharedFD > &fds, ControlSerializer *cs=nullptr)
Deserialize byte vector and fd vector into an object.
static T deserialize(const std::vector< uint8_t > &data, ControlSerializer *cs=nullptr)
Deserialize byte vector into an object.
Camera controls identifiers.
Serialization and deserialization helpers for controls.
Enum-based bit fields.
Frame buffer handling.
Data structures related to geometric objects.
Image Processing Algorithm interface.
Logging infrastructure.
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
Definition log.h:46
#define ASSERT(condition)
Abort program execution if assertion fails.
Definition log.h:126
Top-level libcamera namespace.
Definition backtrace.h:17