From 13f7d58569776b82cfce7f772768973325d878ff Mon Sep 17 00:00:00 2001 From: Paul Elder Date: Sat, 5 Dec 2020 19:30:48 +0900 Subject: libcamera: Add IPADataSerializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Acked-by: Niklas Söderlund --- include/libcamera/internal/ipa_data_serializer.h | 307 +++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 include/libcamera/internal/ipa_data_serializer.h (limited to 'include/libcamera/internal') 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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> * = nullptr> +void appendPOD(std::vector &vec, T val) +{ + constexpr size_t byteWidth = sizeof(val); + vec.resize(vec.size() + byteWidth); + memcpy(&*(vec.end() - byteWidth), &val, byteWidth); +} + +template> * = nullptr> +T readPOD(std::vector::const_iterator it, size_t pos, + std::vector::const_iterator end) +{ + ASSERT(pos + it < end); + + T ret = 0; + memcpy(&ret, &(*(it + pos)), sizeof(ret)); + + return ret; +} + +template> * = nullptr> +T readPOD(std::vector &vec, size_t pos) +{ + return readPOD(vec.cbegin(), pos, vec.end()); +} + +} /* namespace */ + +template +class IPADataSerializer +{ +public: + static std::tuple, std::vector> + serialize(const T &data, ControlSerializer *cs = nullptr); + + static T deserialize(const std::vector &data, + ControlSerializer *cs = nullptr); + static T deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + ControlSerializer *cs = nullptr); + + static T deserialize(const std::vector &data, + const std::vector &fds, + ControlSerializer *cs = nullptr); + static T deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + std::vector::const_iterator fdsBegin, + std::vector::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 +class IPADataSerializer> +{ +public: + static std::tuple, std::vector> + serialize(const std::vector &data, ControlSerializer *cs = nullptr) + { + std::vector dataVec; + std::vector fdsVec; + + /* Serialize the length. */ + uint32_t vecLen = data.size(); + appendPOD(dataVec, vecLen); + + /* Serialize the members. */ + for (auto const &it : data) { + std::vector dvec; + std::vector fvec; + + std::tie(dvec, fvec) = + IPADataSerializer::serialize(it, cs); + + appendPOD(dataVec, dvec.size()); + appendPOD(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 deserialize(std::vector &data, ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.end(), cs); + } + + static std::vector deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + ControlSerializer *cs = nullptr) + { + std::vector fds; + return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); + } + + static std::vector deserialize(std::vector &data, std::vector &fds, + ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); + } + + static std::vector deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + std::vector::const_iterator fdsBegin, + [[maybe_unused]] std::vector::const_iterator fdsEnd, + ControlSerializer *cs = nullptr) + { + uint32_t vecLen = readPOD(dataBegin, 0, dataEnd); + std::vector ret(vecLen); + + std::vector::const_iterator dataIter = dataBegin + 4; + std::vector::const_iterator fdIter = fdsBegin; + for (uint32_t i = 0; i < vecLen; i++) { + uint32_t sizeofData = readPOD(dataIter, 0, dataEnd); + uint32_t sizeofFds = readPOD(dataIter, 4, dataEnd); + dataIter += 8; + + ret[i] = IPADataSerializer::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 +class IPADataSerializer> +{ +public: + static std::tuple, std::vector> + serialize(const std::map &data, ControlSerializer *cs = nullptr) + { + std::vector dataVec; + std::vector fdsVec; + + /* Serialize the length. */ + uint32_t mapLen = data.size(); + appendPOD(dataVec, mapLen); + + /* Serialize the members. */ + for (auto const &it : data) { + std::vector dvec; + std::vector fvec; + + std::tie(dvec, fvec) = + IPADataSerializer::serialize(it.first, cs); + + appendPOD(dataVec, dvec.size()); + appendPOD(dataVec, fvec.size()); + + dataVec.insert(dataVec.end(), dvec.begin(), dvec.end()); + fdsVec.insert(fdsVec.end(), fvec.begin(), fvec.end()); + + std::tie(dvec, fvec) = + IPADataSerializer::serialize(it.second, cs); + + appendPOD(dataVec, dvec.size()); + appendPOD(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 deserialize(std::vector &data, ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.end(), cs); + } + + static std::map deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + ControlSerializer *cs = nullptr) + { + std::vector fds; + return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); + } + + static std::map deserialize(std::vector &data, std::vector &fds, + ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); + } + + static std::map deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + std::vector::const_iterator fdsBegin, + [[maybe_unused]] std::vector::const_iterator fdsEnd, + ControlSerializer *cs = nullptr) + { + std::map ret; + + uint32_t mapLen = readPOD(dataBegin, 0, dataEnd); + + std::vector::const_iterator dataIter = dataBegin + 4; + std::vector::const_iterator fdIter = fdsBegin; + for (uint32_t i = 0; i < mapLen; i++) { + uint32_t sizeofData = readPOD(dataIter, 0, dataEnd); + uint32_t sizeofFds = readPOD(dataIter, 4, dataEnd); + dataIter += 8; + + K key = IPADataSerializer::deserialize(dataIter, + dataIter + sizeofData, + fdIter, + fdIter + sizeofFds, + cs); + + dataIter += sizeofData; + fdIter += sizeofFds; + sizeofData = readPOD(dataIter, 0, dataEnd); + sizeofFds = readPOD(dataIter, 4, dataEnd); + dataIter += 8; + + const V value = IPADataSerializer::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__ */ -- cgit v1.2.1