[libcamera-devel] [PATCH 26/31] libcamera: control_serializer: Use zero-copy ByteStreamBuffer::read()
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Sat Feb 29 17:42:49 CET 2020
Use the zero-copy variant of ByteStreamBuffer::read() to read packet
haders and control entries. This enhance performance of ControlList and
ControlInfoMap deserialization.
Deserialization of the actual ControlValue is untouched for now and will
be optimized later.
Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
src/libcamera/control_serializer.cpp | 74 +++++++++++++++++-----------
1 file changed, 44 insertions(+), 30 deletions(-)
diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp
index dc87b96f384b..6cac70739468 100644
--- a/src/libcamera/control_serializer.cpp
+++ b/src/libcamera/control_serializer.cpp
@@ -364,39 +364,46 @@ ControlRange ControlSerializer::load<ControlRange>(ControlType type,
template<>
ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &buffer)
{
- struct ipa_controls_header hdr;
- buffer.read(&hdr);
+ const struct ipa_controls_header *hdr = buffer.read<decltype(*hdr)>();
+ if (!hdr) {
+ LOG(Serializer, Error) << "Out of data";
+ return {};
+ }
- if (hdr.version != IPA_CONTROLS_FORMAT_VERSION) {
+ if (hdr->version != IPA_CONTROLS_FORMAT_VERSION) {
LOG(Serializer, Error)
<< "Unsupported controls format version "
- << hdr.version;
+ << hdr->version;
return {};
}
- ByteStreamBuffer entries = buffer.carveOut(hdr.data_offset - sizeof(hdr));
- ByteStreamBuffer values = buffer.carveOut(hdr.size - hdr.data_offset);
+ ByteStreamBuffer entries = buffer.carveOut(hdr->data_offset - sizeof(*hdr));
+ ByteStreamBuffer values = buffer.carveOut(hdr->size - hdr->data_offset);
if (buffer.overflow()) {
- LOG(Serializer, Error) << "Serialized packet too small";
+ LOG(Serializer, Error) << "Out of data";
return {};
}
ControlInfoMap::Map ctrls;
- for (unsigned int i = 0; i < hdr.entries; ++i) {
- struct ipa_control_range_entry entry;
- entries.read(&entry);
+ for (unsigned int i = 0; i < hdr->entries; ++i) {
+ const struct ipa_control_range_entry *entry =
+ entries.read<decltype(*entry)>();
+ if (!entry) {
+ LOG(Serializer, Error) << "Out of data";
+ return {};
+ }
/* Create and cache the individual ControlId. */
- ControlType type = static_cast<ControlType>(entry.type);
+ ControlType type = static_cast<ControlType>(entry->type);
/**
* \todo Find a way to preserve the control name for debugging
* purpose.
*/
- controlIds_.emplace_back(std::make_unique<ControlId>(entry.id, "", type));
+ controlIds_.emplace_back(std::make_unique<ControlId>(entry->id, "", type));
- if (entry.offset != values.offset()) {
+ if (entry->offset != values.offset()) {
LOG(Serializer, Error)
<< "Bad data, entry offset mismatch (entry "
<< i << ")";
@@ -412,8 +419,8 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
* Create the ControlInfoMap in the cache, and store the map to handle
* association.
*/
- ControlInfoMap &map = infoMaps_[hdr.handle] = std::move(ctrls);
- infoMapHandles_[&map] = hdr.handle;
+ ControlInfoMap &map = infoMaps_[hdr->handle] = std::move(ctrls);
+ infoMapHandles_[&map] = hdr->handle;
return map;
}
@@ -430,21 +437,24 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
template<>
ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer)
{
- struct ipa_controls_header hdr;
- buffer.read(&hdr);
+ const struct ipa_controls_header *hdr = buffer.read<decltype(*hdr)>();
+ if (!hdr) {
+ LOG(Serializer, Error) << "Out of data";
+ return {};
+ }
- if (hdr.version != IPA_CONTROLS_FORMAT_VERSION) {
+ if (hdr->version != IPA_CONTROLS_FORMAT_VERSION) {
LOG(Serializer, Error)
<< "Unsupported controls format version "
- << hdr.version;
+ << hdr->version;
return {};
}
- ByteStreamBuffer entries = buffer.carveOut(hdr.data_offset - sizeof(hdr));
- ByteStreamBuffer values = buffer.carveOut(hdr.size - hdr.data_offset);
+ ByteStreamBuffer entries = buffer.carveOut(hdr->data_offset - sizeof(*hdr));
+ ByteStreamBuffer values = buffer.carveOut(hdr->size - hdr->data_offset);
if (buffer.overflow()) {
- LOG(Serializer, Error) << "Serialized packet too small";
+ LOG(Serializer, Error) << "Out of data";
return {};
}
@@ -456,10 +466,10 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
* use the global control::control idmap.
*/
const ControlInfoMap *infoMap;
- if (hdr.handle) {
+ if (hdr->handle) {
auto iter = std::find_if(infoMapHandles_.begin(), infoMapHandles_.end(),
[&](decltype(infoMapHandles_)::value_type &entry) {
- return entry.second == hdr.handle;
+ return entry.second == hdr->handle;
});
if (iter == infoMapHandles_.end()) {
LOG(Serializer, Error)
@@ -474,19 +484,23 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
ControlList ctrls(infoMap ? infoMap->idmap() : controls::controls);
- for (unsigned int i = 0; i < hdr.entries; ++i) {
- struct ipa_control_value_entry entry;
- entries.read(&entry);
+ for (unsigned int i = 0; i < hdr->entries; ++i) {
+ const struct ipa_control_value_entry *entry =
+ entries.read<decltype(*entry)>();
+ if (!entry) {
+ LOG(Serializer, Error) << "Out of data";
+ return {};
+ }
- if (entry.offset != values.offset()) {
+ if (entry->offset != values.offset()) {
LOG(Serializer, Error)
<< "Bad data, entry offset mismatch (entry "
<< i << ")";
return {};
}
- ControlType type = static_cast<ControlType>(entry.type);
- ctrls.set(entry.id, load<ControlValue>(type, values));
+ ControlType type = static_cast<ControlType>(entry->type);
+ ctrls.set(entry->id, load<ControlValue>(type, values));
}
return ctrls;
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list