/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Google Inc. * * ipa_data_serializer.h - Image Processing Algorithm data serializer */ #pragma once #include #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" 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 */