diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-02-29 01:42:38 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-03-06 18:10:49 +0200 |
commit | 7c6f59217ed00fae88b2069b81924879bd79e276 (patch) | |
tree | f2e849eda34bbb095266e30fb01d12d4b9e2c4db | |
parent | 5467d619251c05f04f737351eb45e191776a420c (diff) |
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 <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.binghm@ideasonboard.com>
-rw-r--r-- | src/libcamera/control_serializer.cpp | 74 |
1 files 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<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 << ")"; @@ -414,8 +421,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; } @@ -432,21 +439,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 {}; } @@ -458,10 +468,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) @@ -476,19 +486,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; |