summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2020-12-05 19:30:48 +0900
committerPaul Elder <paul.elder@ideasonboard.com>2021-02-16 19:21:18 +0900
commit13f7d58569776b82cfce7f772768973325d878ff (patch)
treed07f79316021c03a357f5c1b04f419461faa485e /include
parentc6d4303b0b6124e7b6c31b34b43755bc740132bb (diff)
libcamera: Add IPADataSerializer
Add an IPADataSerializer which implements (de)serialization of built-in (PODs, vector, map, string) and libcamera data structures. This is intended to be used by the proxy and the proxy worker in the IPC layer. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Diffstat (limited to 'include')
-rw-r--r--include/libcamera/internal/ipa_data_serializer.h307
1 files changed, 307 insertions, 0 deletions
diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h
new file mode 100644
index 00000000..70168acc
--- /dev/null
+++ b/include/libcamera/internal/ipa_data_serializer.h
@@ -0,0 +1,307 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * ipa_data_serializer.h - Image Processing Algorithm data serializer
+ */
+#ifndef __LIBCAMERA_INTERNAL_IPA_DATA_SERIALIZER_H__
+#define __LIBCAMERA_INTERNAL_IPA_DATA_SERIALIZER_H__
+
+#include <deque>
+#include <iostream>
+#include <string.h>
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+#include <libcamera/buffer.h>
+#include <libcamera/control_ids.h>
+#include <libcamera/geometry.h>
+#include <libcamera/ipa/ipa_interface.h>
+
+#include "libcamera/internal/byte_stream_buffer.h"
+#include "libcamera/internal/camera_sensor.h"
+#include "libcamera/internal/control_serializer.h"
+#include "libcamera/internal/log.h"
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(IPADataSerializer)
+
+namespace {
+
+template<typename T,
+ typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
+void appendPOD(std::vector<uint8_t> &vec, T val)
+{
+ constexpr size_t byteWidth = sizeof(val);
+ vec.resize(vec.size() + byteWidth);
+ memcpy(&*(vec.end() - byteWidth), &val, byteWidth);
+}
+
+template<typename T,
+ std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
+T readPOD(std::vector<uint8_t>::const_iterator it, size_t pos,
+ std::vector<uint8_t>::const_iterator end)
+{
+ ASSERT(pos + it < end);
+
+ T ret = 0;
+ memcpy(&ret, &(*(it + pos)), sizeof(ret));
+
+ return ret;
+}
+
+template<typename T,
+ std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
+T readPOD(std::vector<uint8_t> &vec, size_t pos)
+{
+ return readPOD<T>(vec.cbegin(), pos, vec.end());
+}
+
+} /* namespace */
+
+template<typename T>
+class IPADataSerializer
+{
+public:
+ static std::tuple<std::vector<uint8_t>, std::vector<int32_t>>
+ serialize(const T &data, ControlSerializer *cs = nullptr);
+
+ static T deserialize(const std::vector<uint8_t> &data,
+ ControlSerializer *cs = nullptr);
+ static T deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+ std::vector<uint8_t>::const_iterator dataEnd,
+ ControlSerializer *cs = nullptr);
+
+ static T deserialize(const std::vector<uint8_t> &data,
+ const std::vector<int32_t> &fds,
+ ControlSerializer *cs = nullptr);
+ static T deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+ std::vector<uint8_t>::const_iterator dataEnd,
+ std::vector<int32_t>::const_iterator fdsBegin,
+ std::vector<int32_t>::const_iterator fdsEnd,
+ ControlSerializer *cs = nullptr);
+};
+
+#ifndef __DOXYGEN__
+
+/*
+ * Serialization format for vector of type V:
+ *
+ * 4 bytes - uint32_t Length of vector, in number of elements
+ *
+ * For every element in the vector:
+ *
+ * 4 bytes - uint32_t Size of element, in bytes
+ * 4 bytes - uint32_t Number of fds for the element
+ * X bytes - Serialized element
+ *
+ * \todo Support elements that are references
+ */
+template<typename V>
+class IPADataSerializer<std::vector<V>>
+{
+public:
+ static std::tuple<std::vector<uint8_t>, std::vector<int32_t>>
+ serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr)
+ {
+ std::vector<uint8_t> dataVec;
+ std::vector<int32_t> fdsVec;
+
+ /* Serialize the length. */
+ uint32_t vecLen = data.size();
+ appendPOD<uint32_t>(dataVec, vecLen);
+
+ /* Serialize the members. */
+ for (auto const &it : data) {
+ std::vector<uint8_t> dvec;
+ std::vector<int32_t> fvec;
+
+ std::tie(dvec, fvec) =
+ IPADataSerializer<V>::serialize(it, cs);
+
+ appendPOD<uint32_t>(dataVec, dvec.size());
+ appendPOD<uint32_t>(dataVec, fvec.size());
+
+ dataVec.insert(dataVec.end(), dvec.begin(), dvec.end());
+ fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end());
+ }
+
+ return { dataVec, fdsVec };
+ }
+
+ static std::vector<V> deserialize(std::vector<uint8_t> &data, ControlSerializer *cs = nullptr)
+ {
+ return deserialize(data.cbegin(), data.end(), cs);
+ }
+
+ static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+ std::vector<uint8_t>::const_iterator dataEnd,
+ ControlSerializer *cs = nullptr)
+ {
+ std::vector<int32_t> fds;
+ return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs);
+ }
+
+ static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<int32_t> &fds,
+ ControlSerializer *cs = nullptr)
+ {
+ return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs);
+ }
+
+ static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+ std::vector<uint8_t>::const_iterator dataEnd,
+ std::vector<int32_t>::const_iterator fdsBegin,
+ [[maybe_unused]] std::vector<int32_t>::const_iterator fdsEnd,
+ ControlSerializer *cs = nullptr)
+ {
+ uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd);
+ std::vector<V> ret(vecLen);
+
+ std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4;
+ std::vector<int32_t>::const_iterator fdIter = fdsBegin;
+ for (uint32_t i = 0; i < vecLen; i++) {
+ uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd);
+ uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd);
+ dataIter += 8;
+
+ ret[i] = IPADataSerializer<V>::deserialize(dataIter,
+ dataIter + sizeofData,
+ fdIter,
+ fdIter + sizeofFds,
+ cs);
+
+ dataIter += sizeofData;
+ fdIter += sizeofFds;
+ }
+
+ return ret;
+ }
+};
+
+/*
+ * Serialization format for map of key type K and value type V:
+ *
+ * 4 bytes - uint32_t Length of map, in number of pairs
+ *
+ * For every pair in the map:
+ *
+ * 4 bytes - uint32_t Size of key, in bytes
+ * 4 bytes - uint32_t Number of fds for the key
+ * X bytes - Serialized key
+ * 4 bytes - uint32_t Size of value, in bytes
+ * 4 bytes - uint32_t Number of fds for the value
+ * X bytes - Serialized value
+ *
+ * \todo Support keys or values that are references
+ */
+template<typename K, typename V>
+class IPADataSerializer<std::map<K, V>>
+{
+public:
+ static std::tuple<std::vector<uint8_t>, std::vector<int32_t>>
+ serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr)
+ {
+ std::vector<uint8_t> dataVec;
+ std::vector<int32_t> fdsVec;
+
+ /* Serialize the length. */
+ uint32_t mapLen = data.size();
+ appendPOD<uint32_t>(dataVec, mapLen);
+
+ /* Serialize the members. */
+ for (auto const &it : data) {
+ std::vector<uint8_t> dvec;
+ std::vector<int32_t> fvec;
+
+ std::tie(dvec, fvec) =
+ IPADataSerializer<K>::serialize(it.first, cs);
+
+ appendPOD<uint32_t>(dataVec, dvec.size());
+ appendPOD<uint32_t>(dataVec, fvec.size());
+
+ dataVec.insert(dataVec.end(), dvec.begin(), dvec.end());
+ fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end());
+
+ std::tie(dvec, fvec) =
+ IPADataSerializer<V>::serialize(it.second, cs);
+
+ appendPOD<uint32_t>(dataVec, dvec.size());
+ appendPOD<uint32_t>(dataVec, fvec.size());
+
+ dataVec.insert(dataVec.end(), dvec.begin(), dvec.end());
+ fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end());
+ }
+
+ return { dataVec, fdsVec };
+ }
+
+ static std::map<K, V> deserialize(std::vector<uint8_t> &data, ControlSerializer *cs = nullptr)
+ {
+ return deserialize(data.cbegin(), data.end(), cs);
+ }
+
+ static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+ std::vector<uint8_t>::const_iterator dataEnd,
+ ControlSerializer *cs = nullptr)
+ {
+ std::vector<int32_t> fds;
+ return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs);
+ }
+
+ static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<int32_t> &fds,
+ ControlSerializer *cs = nullptr)
+ {
+ return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs);
+ }
+
+ static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+ std::vector<uint8_t>::const_iterator dataEnd,
+ std::vector<int32_t>::const_iterator fdsBegin,
+ [[maybe_unused]] std::vector<int32_t>::const_iterator fdsEnd,
+ ControlSerializer *cs = nullptr)
+ {
+ std::map<K, V> ret;
+
+ uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd);
+
+ std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4;
+ std::vector<int32_t>::const_iterator fdIter = fdsBegin;
+ for (uint32_t i = 0; i < mapLen; i++) {
+ uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd);
+ uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd);
+ dataIter += 8;
+
+ K key = IPADataSerializer<K>::deserialize(dataIter,
+ dataIter + sizeofData,
+ fdIter,
+ fdIter + sizeofFds,
+ cs);
+
+ dataIter += sizeofData;
+ fdIter += sizeofFds;
+ sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd);
+ sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd);
+ dataIter += 8;
+
+ const V value = IPADataSerializer<V>::deserialize(dataIter,
+ dataIter + sizeofData,
+ fdIter,
+ fdIter + sizeofFds,
+ cs);
+ ret.insert({ key, value });
+
+ dataIter += sizeofData;
+ fdIter += sizeofFds;
+ }
+
+ return ret;
+ }
+};
+
+#endif /* __DOXYGEN__ */
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_INTERNAL_IPA_DATA_SERIALIZER_H__ */