[libcamera-devel] [PATCH 26/31] libcamera: control_serializer: Use zero-copy ByteStreamBuffer::read()
Kieran Bingham
kieran.bingham at ideasonboard.com
Thu Mar 5 18:19:51 CET 2020
On 29/02/2020 16:42, Laurent Pinchart wrote:
> Use the zero-copy variant of ByteStreamBuffer::read() to read packet
> haders and control entries. This enhance performance of ControlList and
/haders/headers/
/enhance/enhances the/ or /enhance/will enhance the/
> 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>
Very happy to see removal of copies from our serialization :)
Reviewed-by: Kieran Bingham <kieran.bingham 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)>();
Aha, now I see why it doesn't return a span ...
This looks like a lot of template additions ... couldn't they be just as
easily added for this functionality with taking a size parameter and
returning a void pointer?
(or does C++ not like that)
> + 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
--
Kieran
More information about the libcamera-devel
mailing list