Move the functionality for the following components to the new base support library: - BoundMethod - EventDispatcher - EventDispatcherPoll - Log - Message - Object - Signal - Semaphore - Thread - Timer While it would be preferable to see these split to move one component per commit, these components are all interdependent upon each other, which leaves us with one big change performing the move for all of them. Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
308 lines
8.7 KiB
C++
308 lines
8.7 KiB
C++
/* 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/base/log.h>
|
|
|
|
#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"
|
|
|
|
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__ */
|