From 7c6f59217ed00fae88b2069b81924879bd79e276 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 29 Feb 2020 01:42:38 +0200 Subject: libcamera: control_serializer: Use zero-copy ByteStreamBuffer::read() Use the zero-copy variant of ByteStreamBuffer::read() to read packet headers and control entries. This enhances the 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 Reviewed-by: Kieran Bingham --- 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 997e87be..b4c1ed41 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -366,39 +366,46 @@ ControlRange ControlSerializer::load(ControlType type, template<> ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer &buffer) { - struct ipa_controls_header hdr; - buffer.read(&hdr); + const struct ipa_controls_header *hdr = buffer.read(); + 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(); + if (!entry) { + LOG(Serializer, Error) << "Out of data"; + return {}; + } /* Create and cache the individual ControlId. */ - ControlType type = static_cast(entry.type); + ControlType type = static_cast(entry->type); /** * \todo Find a way to preserve the control name for debugging * purpose. */ - controlIds_.emplace_back(std::make_unique(entry.id, "", type)); + controlIds_.emplace_back(std::make_unique(entry->id, "", type)); - if (entry.offset != values.offset()) { + if (entry->offset != values.offset()) { LOG(Serializer, Error) << "Bad data, entry offset mismatch (entry " << i << ")"; @@ -414,8 +421,8 @@ ControlInfoMap ControlSerializer::deserialize(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; } @@ -432,21 +439,24 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & template<> ControlList ControlSerializer::deserialize(ByteStreamBuffer &buffer) { - struct ipa_controls_header hdr; - buffer.read(&hdr); + const struct ipa_controls_header *hdr = buffer.read(); + 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 {}; } @@ -458,10 +468,10 @@ ControlList ControlSerializer::deserialize(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) @@ -476,19 +486,23 @@ ControlList ControlSerializer::deserialize(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(); + 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(entry.type); - ctrls.set(entry.id, load(type, values)); + ControlType type = static_cast(entry->type); + ctrls.set(entry->id, load(type, values)); } return ctrls; -- cgit v1.2.1