Skip to content

Commit 7cc59b5

Browse files
Rahi374naushir
authored andcommitted
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
1 parent 559128b commit 7cc59b5

4 files changed

Lines changed: 108 additions & 50 deletions

File tree

include/libcamera/internal/control_serializer.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,13 @@ class ControlSerializer
4747
static void store(const ControlValue &value, ByteStreamBuffer &buffer);
4848
static void store(const ControlInfo &info, ByteStreamBuffer &buffer);
4949

50+
void populateControlValueEntry(struct ipa_control_value_entry &entry,
51+
const ControlValue &value,
52+
uint32_t offset);
53+
5054
ControlValue loadControlValue(ByteStreamBuffer &buffer,
51-
bool isArray = false, unsigned int count = 1);
52-
ControlInfo loadControlInfo(ByteStreamBuffer &buffer);
55+
ControlType type,
56+
bool isArray, unsigned int count);
5357

5458
unsigned int serial_;
5559
unsigned int serialSeed_;

include/libcamera/ipa/ipa_controls.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace libcamera {
1515
extern "C" {
1616
#endif
1717

18-
#define IPA_CONTROLS_FORMAT_VERSION 1
18+
#define IPA_CONTROLS_FORMAT_VERSION 2
1919

2020
enum ipa_controls_id_map_type {
2121
IPA_CONTROL_ID_MAP_CONTROLS,
@@ -34,20 +34,25 @@ struct ipa_controls_header {
3434
};
3535

3636
struct ipa_control_value_entry {
37-
uint32_t id;
3837
uint8_t type;
3938
uint8_t is_array;
4039
uint16_t count;
4140
uint32_t offset;
4241
uint32_t padding[1];
42+
uint32_t reserved;
43+
};
44+
45+
struct ipa_control_list_entry {
46+
uint32_t id;
47+
struct ipa_control_value_entry value;
4348
};
4449

4550
struct ipa_control_info_entry {
4651
uint32_t id;
4752
uint32_t type;
48-
uint32_t offset;
4953
uint8_t direction;
5054
uint8_t padding[3];
55+
uint32_t reserved;
5156
};
5257

5358
#ifdef __cplusplus

src/libcamera/control_serializer.cpp

Lines changed: 78 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ void ControlSerializer::reset()
144144

145145
size_t ControlSerializer::binarySize(const ControlValue &value)
146146
{
147-
return sizeof(ControlType) + value.data().size_bytes();
147+
return value.data().size_bytes();
148148
}
149149

150150
size_t ControlSerializer::binarySize(const ControlInfo &info)
@@ -164,7 +164,8 @@ size_t ControlSerializer::binarySize(const ControlInfo &info)
164164
size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
165165
{
166166
size_t size = sizeof(struct ipa_controls_header)
167-
+ infoMap.size() * sizeof(struct ipa_control_info_entry);
167+
+ infoMap.size() * (sizeof(struct ipa_control_info_entry) +
168+
3 * sizeof(struct ipa_control_value_entry));
168169

169170
for (const auto &ctrl : infoMap)
170171
size += binarySize(ctrl.second);
@@ -184,7 +185,7 @@ size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
184185
size_t ControlSerializer::binarySize(const ControlList &list)
185186
{
186187
size_t size = sizeof(struct ipa_controls_header)
187-
+ list.size() * sizeof(struct ipa_control_value_entry);
188+
+ list.size() * sizeof(struct ipa_control_list_entry);
188189

189190
for (const auto &ctrl : list)
190191
size += binarySize(ctrl.second);
@@ -195,16 +196,17 @@ size_t ControlSerializer::binarySize(const ControlList &list)
195196
void ControlSerializer::store(const ControlValue &value,
196197
ByteStreamBuffer &buffer)
197198
{
198-
const ControlType type = value.type();
199-
buffer.write(&type);
200199
buffer.write(value.data());
201200
}
202201

203-
void ControlSerializer::store(const ControlInfo &info, ByteStreamBuffer &buffer)
202+
void ControlSerializer::populateControlValueEntry(struct ipa_control_value_entry &entry,
203+
const ControlValue &value,
204+
uint32_t offset)
204205
{
205-
store(info.min(), buffer);
206-
store(info.max(), buffer);
207-
store(info.def(), buffer);
206+
entry.type = value.type();
207+
entry.is_array = value.isArray();
208+
entry.count = value.numElements();
209+
entry.offset = offset;
208210
}
209211

210212
/**
@@ -232,7 +234,8 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
232234

233235
/* Compute entries and data required sizes. */
234236
size_t entriesSize = infoMap.size()
235-
* sizeof(struct ipa_control_info_entry);
237+
* (sizeof(struct ipa_control_info_entry) +
238+
3 * sizeof(struct ipa_control_value_entry));
236239
size_t valuesSize = 0;
237240
for (const auto &ctrl : infoMap)
238241
valuesSize += binarySize(ctrl.second);
@@ -280,11 +283,32 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
280283
struct ipa_control_info_entry entry;
281284
entry.id = id->id();
282285
entry.type = id->type();
283-
entry.offset = values.offset();
284286
entry.direction = static_cast<ControlId::DirectionFlags::Type>(id->direction());
285287
entries.write(&entry);
286288

287-
store(info, values);
289+
/*
290+
* Write the metadata for the ControlValue entries as well,
291+
* since we need type, isArray, and numElements information for
292+
* min/max/def of the ControlInfo. Doing it this way is the
293+
* least intrusive in terms of changing the structs in
294+
* ipa_controls.h
295+
*/
296+
struct ipa_control_value_entry valueEntry;
297+
298+
populateControlValueEntry(valueEntry, info.min(),
299+
values.offset());
300+
entries.write(&valueEntry);
301+
store(info.min(), values);
302+
303+
populateControlValueEntry(valueEntry, info.max(),
304+
values.offset());
305+
entries.write(&valueEntry);
306+
store(info.max(), values);
307+
308+
populateControlValueEntry(valueEntry, info.def(),
309+
values.offset());
310+
entries.write(&valueEntry);
311+
store(info.def(), values);
288312
}
289313

290314
if (buffer.overflow())
@@ -341,7 +365,7 @@ int ControlSerializer::serialize(const ControlList &list,
341365
else
342366
idMapType = IPA_CONTROL_ID_MAP_V4L2;
343367

344-
size_t entriesSize = list.size() * sizeof(struct ipa_control_value_entry);
368+
size_t entriesSize = list.size() * sizeof(struct ipa_control_list_entry);
345369
size_t valuesSize = 0;
346370
for (const auto &ctrl : list)
347371
valuesSize += binarySize(ctrl.second);
@@ -365,12 +389,9 @@ int ControlSerializer::serialize(const ControlList &list,
365389
unsigned int id = ctrl.first;
366390
const ControlValue &value = ctrl.second;
367391

368-
struct ipa_control_value_entry entry;
392+
struct ipa_control_list_entry entry;
369393
entry.id = id;
370-
entry.type = value.type();
371-
entry.is_array = value.isArray();
372-
entry.count = value.numElements();
373-
entry.offset = values.offset();
394+
populateControlValueEntry(entry.value, value, values.offset());
374395
entries.write(&entry);
375396

376397
store(value, values);
@@ -383,12 +404,10 @@ int ControlSerializer::serialize(const ControlList &list,
383404
}
384405

385406
ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
407+
ControlType type,
386408
bool isArray,
387409
unsigned int count)
388410
{
389-
ControlType type;
390-
buffer.read(&type);
391-
392411
ControlValue value;
393412

394413
value.reserve(type, isArray, count);
@@ -397,15 +416,6 @@ ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
397416
return value;
398417
}
399418

400-
ControlInfo ControlSerializer::loadControlInfo(ByteStreamBuffer &b)
401-
{
402-
ControlValue min = loadControlValue(b);
403-
ControlValue max = loadControlValue(b);
404-
ControlValue def = loadControlValue(b);
405-
406-
return ControlInfo(min, max, def);
407-
}
408-
409419
/**
410420
* \fn template<typename T> T ControlSerializer::deserialize(ByteStreamBuffer &buffer)
411421
* \brief Deserialize an object from a binary buffer
@@ -483,9 +493,11 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
483493

484494
ControlInfoMap::Map ctrls;
485495
for (unsigned int i = 0; i < hdr->entries; ++i) {
486-
const struct ipa_control_info_entry *entry =
487-
entries.read<decltype(*entry)>();
488-
if (!entry) {
496+
const auto *entry = entries.read<const ipa_control_info_entry>();
497+
const auto *min_entry = entries.read<const ipa_control_value_entry>();
498+
const auto *max_entry = entries.read<const ipa_control_value_entry>();
499+
const auto *def_entry = entries.read<const ipa_control_value_entry>();
500+
if (!entry || !min_entry || !max_entry || !def_entry) {
489501
LOG(Serializer, Error) << "Out of data";
490502
return {};
491503
}
@@ -511,15 +523,39 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
511523
const ControlId *controlId = idMap->at(entry->id);
512524
ASSERT(controlId);
513525

514-
if (entry->offset != values.offset()) {
526+
if (min_entry->offset != values.offset()) {
515527
LOG(Serializer, Error)
516-
<< "Bad data, entry offset mismatch (entry "
528+
<< "Bad data, entry offset mismatch (min entry "
529+
<< i << ")";
530+
return {};
531+
}
532+
ControlValue min =
533+
loadControlValue(values, static_cast<ControlType>(min_entry->type),
534+
min_entry->is_array, min_entry->count);
535+
536+
if (max_entry->offset != values.offset()) {
537+
LOG(Serializer, Error)
538+
<< "Bad data, entry offset mismatch (max entry "
517539
<< i << ")";
518540
return {};
519541
}
542+
ControlValue max =
543+
loadControlValue(values, static_cast<ControlType>(max_entry->type),
544+
max_entry->is_array, max_entry->count);
545+
546+
if (def_entry->offset != values.offset()) {
547+
LOG(Serializer, Error)
548+
<< "Bad data, entry offset mismatch (def entry "
549+
<< i << ")";
550+
return {};
551+
}
552+
ControlValue def =
553+
loadControlValue(values, static_cast<ControlType>(def_entry->type),
554+
def_entry->is_array, def_entry->count);
555+
520556

521557
/* Create and store the ControlInfo. */
522-
ctrls.emplace(controlId, loadControlInfo(values));
558+
ctrls.emplace(controlId, ControlInfo(min, max, def));
523559
}
524560

525561
/*
@@ -618,12 +654,12 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
618654
ControlList ctrls(*idMap);
619655

620656
for (unsigned int i = 0; i < hdr->entries; ++i) {
621-
const struct ipa_control_value_entry *entry =
622-
entries.read<decltype(*entry)>();
623-
if (!entry) {
657+
auto *list_entry = entries.read<const ipa_control_list_entry>();
658+
if (!list_entry) {
624659
LOG(Serializer, Error) << "Out of data";
625660
return {};
626661
}
662+
const ipa_control_value_entry *entry = &list_entry->value;
627663

628664
if (entry->offset != values.offset()) {
629665
LOG(Serializer, Error)
@@ -632,8 +668,9 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
632668
return {};
633669
}
634670

635-
ctrls.set(entry->id,
636-
loadControlValue(values, entry->is_array, entry->count));
671+
ctrls.set(list_entry->id,
672+
loadControlValue(values, static_cast<ControlType>(entry->type),
673+
entry->is_array, entry->count));
637674
}
638675

639676
return ctrls;

src/libcamera/ipa_controls.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,6 @@ static_assert(sizeof(ipa_controls_header) == 32,
192192
/**
193193
* \struct ipa_control_value_entry
194194
* \brief Description of a serialized ControlValue entry
195-
* \var ipa_control_value_entry::id
196-
* The numerical ID of the control
197195
* \var ipa_control_value_entry::type
198196
* The type of the control (defined by enum ControlType)
199197
* \var ipa_control_value_entry::is_array
@@ -205,27 +203,41 @@ static_assert(sizeof(ipa_controls_header) == 32,
205203
* value data (shall be a multiple of 8 bytes).
206204
* \var ipa_control_value_entry::padding
207205
* Padding bytes (shall be set to 0)
206+
* \var ipa_control_value_entry::reserved
207+
* Reserved for future extensions
208208
*/
209209

210210
static_assert(sizeof(ipa_control_value_entry) == 16,
211211
"Invalid ABI size change for struct ipa_control_value_entry");
212212

213+
/**
214+
* \struct ipa_control_list_entry
215+
* \brief Description of a serialized ControlList entry
216+
* \var ipa_control_list_entry::id
217+
* The numerical ID of the control
218+
* \var ipa_control_list_entry::value
219+
* The description of the serialized ControlValue
220+
*/
221+
222+
static_assert(sizeof(ipa_control_list_entry) == 20,
223+
"Invalid ABI size change for struct ipa_control_list_entry");
224+
213225
/**
214226
* \struct ipa_control_info_entry
215227
* \brief Description of a serialized ControlInfo entry
216228
* \var ipa_control_info_entry::id
217229
* The numerical ID of the control
218230
* \var ipa_control_info_entry::type
219231
* The type of the control (defined by enum ControlType)
220-
* \var ipa_control_info_entry::offset
221-
* The offset in bytes from the beginning of the data section to the control
222232
* info data (shall be a multiple of 8 bytes)
223233
* \var ipa_control_info_entry::direction
224234
* The directions in which the control is allowed to be sent. This is a flags
225235
* value, where 0x1 signifies input (as controls), and 0x2 signifies output (as
226236
* metadata). \sa ControlId::Direction
227237
* \var ipa_control_info_entry::padding
228238
* Padding bytes (shall be set to 0)
239+
* \var ipa_control_info_entry::reserved
240+
* Reserved for future extensions
229241
*/
230242

231243
static_assert(sizeof(ipa_control_info_entry) == 16,

0 commit comments

Comments
 (0)