libcamera: control_serializer: Add array info to serialized ControlValue
Array controls (eg. ColourCorrectionMatrix, FrameDurationLimits, ColourGains) are serialized properly by the ControlSerializer, but are not deserialized properly. This is because their arrayness and size are not considered during deserialization. Fix this by adding arrayness and size to the serialized form of all ControlValues. This is achieved by fully serializing the min/max/def ControlValue's metadata associated with each ControlInfo entry in the ControlInfoMap. While at it, clean up the serialization format of ControlValues and ControlLists: - ControlValue's id is only used by ControlList, so add a new struct for ControlList entries to contain it, and remove id from ControlValue - Remove offset from ControlInfo's entry, as it is no longer needed, since the serialized data of a ControlInfo has now been converted to simply three serialized ControlValues - Remove the type from the serialized data of ControlValue, as it is already in the metadata entry The issue regarding array controls was not noticed before because the default value of the ControlInfo of other array controls had been set to scalar values similar to how min/max are set, and ColourCorrectionMatrix was the first control to properly define a non-scalar default value. Bug: https://bugs.libcamera.org/show_bug.cgi?id=285 Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # rkisp1 Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
committed by
Kieran Bingham
parent
7313f046a2
commit
cfdc281100
@@ -144,7 +144,7 @@ void ControlSerializer::reset()
|
||||
|
||||
size_t ControlSerializer::binarySize(const ControlValue &value)
|
||||
{
|
||||
return sizeof(ControlType) + value.data().size_bytes();
|
||||
return value.data().size_bytes();
|
||||
}
|
||||
|
||||
size_t ControlSerializer::binarySize(const ControlInfo &info)
|
||||
@@ -164,7 +164,8 @@ size_t ControlSerializer::binarySize(const ControlInfo &info)
|
||||
size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
|
||||
{
|
||||
size_t size = sizeof(struct ipa_controls_header)
|
||||
+ infoMap.size() * sizeof(struct ipa_control_info_entry);
|
||||
+ infoMap.size() * (sizeof(struct ipa_control_info_entry) +
|
||||
3 * sizeof(struct ipa_control_value_entry));
|
||||
|
||||
for (const auto &ctrl : infoMap)
|
||||
size += binarySize(ctrl.second);
|
||||
@@ -184,7 +185,7 @@ size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
|
||||
size_t ControlSerializer::binarySize(const ControlList &list)
|
||||
{
|
||||
size_t size = sizeof(struct ipa_controls_header)
|
||||
+ list.size() * sizeof(struct ipa_control_value_entry);
|
||||
+ list.size() * sizeof(struct ipa_control_list_entry);
|
||||
|
||||
for (const auto &ctrl : list)
|
||||
size += binarySize(ctrl.second);
|
||||
@@ -195,16 +196,17 @@ size_t ControlSerializer::binarySize(const ControlList &list)
|
||||
void ControlSerializer::store(const ControlValue &value,
|
||||
ByteStreamBuffer &buffer)
|
||||
{
|
||||
const ControlType type = value.type();
|
||||
buffer.write(&type);
|
||||
buffer.write(value.data());
|
||||
}
|
||||
|
||||
void ControlSerializer::store(const ControlInfo &info, ByteStreamBuffer &buffer)
|
||||
void ControlSerializer::populateControlValueEntry(struct ipa_control_value_entry &entry,
|
||||
const ControlValue &value,
|
||||
uint32_t offset)
|
||||
{
|
||||
store(info.min(), buffer);
|
||||
store(info.max(), buffer);
|
||||
store(info.def(), buffer);
|
||||
entry.type = value.type();
|
||||
entry.is_array = value.isArray();
|
||||
entry.count = value.numElements();
|
||||
entry.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +234,8 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
|
||||
|
||||
/* Compute entries and data required sizes. */
|
||||
size_t entriesSize = infoMap.size()
|
||||
* sizeof(struct ipa_control_info_entry);
|
||||
* (sizeof(struct ipa_control_info_entry) +
|
||||
3 * sizeof(struct ipa_control_value_entry));
|
||||
size_t valuesSize = 0;
|
||||
for (const auto &ctrl : infoMap)
|
||||
valuesSize += binarySize(ctrl.second);
|
||||
@@ -280,11 +283,18 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
|
||||
struct ipa_control_info_entry entry;
|
||||
entry.id = id->id();
|
||||
entry.type = id->type();
|
||||
entry.offset = values.offset();
|
||||
entry.direction = static_cast<ControlId::DirectionFlags::Type>(id->direction());
|
||||
entries.write(&entry);
|
||||
|
||||
store(info, values);
|
||||
populateControlValueEntry(entry.min, info.min(), values.offset());
|
||||
store(info.min(), values);
|
||||
|
||||
populateControlValueEntry(entry.max, info.max(), values.offset());
|
||||
store(info.max(), values);
|
||||
|
||||
populateControlValueEntry(entry.def, info.def(), values.offset());
|
||||
store(info.def(), values);
|
||||
|
||||
entries.write(&entry);
|
||||
}
|
||||
|
||||
if (buffer.overflow())
|
||||
@@ -341,7 +351,7 @@ int ControlSerializer::serialize(const ControlList &list,
|
||||
else
|
||||
idMapType = IPA_CONTROL_ID_MAP_V4L2;
|
||||
|
||||
size_t entriesSize = list.size() * sizeof(struct ipa_control_value_entry);
|
||||
size_t entriesSize = list.size() * sizeof(struct ipa_control_list_entry);
|
||||
size_t valuesSize = 0;
|
||||
for (const auto &ctrl : list)
|
||||
valuesSize += binarySize(ctrl.second);
|
||||
@@ -365,12 +375,9 @@ int ControlSerializer::serialize(const ControlList &list,
|
||||
unsigned int id = ctrl.first;
|
||||
const ControlValue &value = ctrl.second;
|
||||
|
||||
struct ipa_control_value_entry entry;
|
||||
struct ipa_control_list_entry entry;
|
||||
entry.id = id;
|
||||
entry.type = value.type();
|
||||
entry.is_array = value.isArray();
|
||||
entry.count = value.numElements();
|
||||
entry.offset = values.offset();
|
||||
populateControlValueEntry(entry.value, value, values.offset());
|
||||
entries.write(&entry);
|
||||
|
||||
store(value, values);
|
||||
@@ -383,12 +390,10 @@ int ControlSerializer::serialize(const ControlList &list,
|
||||
}
|
||||
|
||||
ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
|
||||
ControlType type,
|
||||
bool isArray,
|
||||
unsigned int count)
|
||||
{
|
||||
ControlType type;
|
||||
buffer.read(&type);
|
||||
|
||||
ControlValue value;
|
||||
|
||||
value.reserve(type, isArray, count);
|
||||
@@ -397,15 +402,6 @@ ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
|
||||
return value;
|
||||
}
|
||||
|
||||
ControlInfo ControlSerializer::loadControlInfo(ByteStreamBuffer &b)
|
||||
{
|
||||
ControlValue min = loadControlValue(b);
|
||||
ControlValue max = loadControlValue(b);
|
||||
ControlValue def = loadControlValue(b);
|
||||
|
||||
return ControlInfo(min, max, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn template<typename T> T ControlSerializer::deserialize(ByteStreamBuffer &buffer)
|
||||
* \brief Deserialize an object from a binary buffer
|
||||
@@ -483,8 +479,7 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
|
||||
|
||||
ControlInfoMap::Map ctrls;
|
||||
for (unsigned int i = 0; i < hdr->entries; ++i) {
|
||||
const struct ipa_control_info_entry *entry =
|
||||
entries.read<decltype(*entry)>();
|
||||
const auto *entry = entries.read<const ipa_control_info_entry>();
|
||||
if (!entry) {
|
||||
LOG(Serializer, Error) << "Out of data";
|
||||
return {};
|
||||
@@ -511,15 +506,43 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
|
||||
const ControlId *controlId = idMap->at(entry->id);
|
||||
ASSERT(controlId);
|
||||
|
||||
if (entry->offset != values.offset()) {
|
||||
const ipa_control_value_entry &min_entry = entry->min;
|
||||
const ipa_control_value_entry &max_entry = entry->max;
|
||||
const ipa_control_value_entry &def_entry = entry->def;
|
||||
|
||||
if (min_entry.offset != values.offset()) {
|
||||
LOG(Serializer, Error)
|
||||
<< "Bad data, entry offset mismatch (entry "
|
||||
<< "Bad data, entry offset mismatch (min entry "
|
||||
<< i << ")";
|
||||
return {};
|
||||
}
|
||||
ControlValue min =
|
||||
loadControlValue(values, static_cast<ControlType>(min_entry.type),
|
||||
min_entry.is_array, min_entry.count);
|
||||
|
||||
if (max_entry.offset != values.offset()) {
|
||||
LOG(Serializer, Error)
|
||||
<< "Bad data, entry offset mismatch (max entry "
|
||||
<< i << ")";
|
||||
return {};
|
||||
}
|
||||
ControlValue max =
|
||||
loadControlValue(values, static_cast<ControlType>(max_entry.type),
|
||||
max_entry.is_array, max_entry.count);
|
||||
|
||||
if (def_entry.offset != values.offset()) {
|
||||
LOG(Serializer, Error)
|
||||
<< "Bad data, entry offset mismatch (def entry "
|
||||
<< i << ")";
|
||||
return {};
|
||||
}
|
||||
ControlValue def =
|
||||
loadControlValue(values, static_cast<ControlType>(def_entry.type),
|
||||
def_entry.is_array, def_entry.count);
|
||||
|
||||
|
||||
/* Create and store the ControlInfo. */
|
||||
ctrls.emplace(controlId, loadControlInfo(values));
|
||||
ctrls.emplace(controlId, ControlInfo(min, max, def));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -618,12 +641,12 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
|
||||
ControlList ctrls(*idMap);
|
||||
|
||||
for (unsigned int i = 0; i < hdr->entries; ++i) {
|
||||
const struct ipa_control_value_entry *entry =
|
||||
entries.read<decltype(*entry)>();
|
||||
if (!entry) {
|
||||
auto *list_entry = entries.read<const ipa_control_list_entry>();
|
||||
if (!list_entry) {
|
||||
LOG(Serializer, Error) << "Out of data";
|
||||
return {};
|
||||
}
|
||||
const ipa_control_value_entry *entry = &list_entry->value;
|
||||
|
||||
if (entry->offset != values.offset()) {
|
||||
LOG(Serializer, Error)
|
||||
@@ -632,8 +655,9 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
|
||||
return {};
|
||||
}
|
||||
|
||||
ctrls.set(entry->id,
|
||||
loadControlValue(values, entry->is_array, entry->count));
|
||||
ctrls.set(list_entry->id,
|
||||
loadControlValue(values, static_cast<ControlType>(entry->type),
|
||||
entry->is_array, entry->count));
|
||||
}
|
||||
|
||||
return ctrls;
|
||||
|
||||
Reference in New Issue
Block a user