From patchwork Wed Jul 28 16:11:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 13141 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 960C3C322E for ; Wed, 28 Jul 2021 16:10:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5C556687DD; Wed, 28 Jul 2021 18:10:35 +0200 (CEST) Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2AA23687C8 for ; Wed, 28 Jul 2021 18:10:33 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id B1BC16000E; Wed, 28 Jul 2021 16:10:32 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Wed, 28 Jul 2021 18:11:13 +0200 Message-Id: <20210728161116.64489-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210728161116.64489-1-jacopo@jmondi.org> References: <20210728161116.64489-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/5] libcamera: controls: Use ControlIdMap in deserialization X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Introduce a new field in the controls serialization protocol to allow discerning which ControlIdMap a ControlInfoMap refers to. The newly introduced IdMapType enumeration describes the possible info maps: - Either the globally available controls::controls and properties::properties maps, which are valid across IPC boundaries - A ControlIdMap created locally by the V4L2 device, which is not valid across the IPC boundaries At de-serialization time the idMapType filed is inspected and - If the idmap is a globally available one, there's no need to create new ControlId instances when populating the de-serialized ControlInfoMap. Use the globally available map to retrieve the ControlId reference and use it - If the idmap is a map only available locally, create a new ControlId as it used to happen before this patch. As a direct consequence, this change allows to perform lookup by ControlId reference on de-serialized ControlIdMap that refers to the libcamera defined controls::controls and properties::properties. Signed-off-by: Jacopo Mondi Reviewed-by: Paul Elder --- include/libcamera/ipa/ipa_controls.h | 9 +++- src/libcamera/control_serializer.cpp | 73 +++++++++++++++++++++++----- src/libcamera/ipa_controls.cpp | 31 ++++++++++++ 3 files changed, 101 insertions(+), 12 deletions(-) diff --git a/include/libcamera/ipa/ipa_controls.h b/include/libcamera/ipa/ipa_controls.h index 6d3bf279c22d..5b1690066314 100644 --- a/include/libcamera/ipa/ipa_controls.h +++ b/include/libcamera/ipa/ipa_controls.h @@ -15,13 +15,20 @@ extern "C" { #define IPA_CONTROLS_FORMAT_VERSION 1 +enum class IdMapType { + LIBCAMERA_CONTROLS, + LIBCAMERA_PROPERTIES, + V4L2_CONTROLS, +}; + struct ipa_controls_header { uint32_t version; uint32_t handle; uint32_t entries; uint32_t size; uint32_t data_offset; - uint32_t reserved[3]; + IdMapType idMapType; + uint32_t reserved[2]; }; struct ipa_control_value_entry { diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index df6ed93f477e..255f9d30fb85 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "libcamera/internal/byte_stream_buffer.h" @@ -188,6 +189,16 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap, for (const auto &ctrl : infoMap) valuesSize += binarySize(ctrl.second); + /* Serialize the id map type to be used when de-serializing. */ + const ControlIdMap *idmap = &infoMap.idmap(); + enum IdMapType idMapType; + if (idmap == &controls::controls) + idMapType = IdMapType::LIBCAMERA_CONTROLS; + else if (idmap == &properties::properties) + idMapType = IdMapType::LIBCAMERA_PROPERTIES; + else + idMapType = IdMapType::V4L2_CONTROLS; + /* Prepare the packet header, assign a handle to the ControlInfoMap. */ struct ipa_controls_header hdr; hdr.version = IPA_CONTROLS_FORMAT_VERSION; @@ -195,6 +206,7 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap, hdr.entries = infoMap.size(); hdr.size = sizeof(hdr) + entriesSize + valuesSize; hdr.data_offset = sizeof(hdr) + entriesSize; + hdr.idMapType = idMapType; buffer.write(&hdr); @@ -368,6 +380,34 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & return {}; } + /* + * Use the id map type to retrieve the ControlId instances associated + * to the serialized numerical identifier. + * + * If a globally available id map such as controls::controls or + * properties::properties is used, the ControlId instances can be + * retrieved from there. + * + * If, otherwise, the idmap is valid only on one side of the IPC + * boundary (as in case it has been created by the V4L2 devices) + * the deserializer shall create new ControlId and store them in an + * locally created id map. + */ + const ControlIdMap *idMap = nullptr; + ControlIdMap *localIdMap; + switch (hdr->idMapType) { + case IdMapType::LIBCAMERA_CONTROLS: + idMap = &controls::controls; + break; + case IdMapType::LIBCAMERA_PROPERTIES: + idMap = &properties::properties; + break; + case IdMapType::V4L2_CONTROLS: + controlIdMaps_.emplace_back(std::make_unique()); + localIdMap = controlIdMaps_.back().get(); + break; + } + ByteStreamBuffer entries = buffer.carveOut(hdr->data_offset - sizeof(*hdr)); ByteStreamBuffer values = buffer.carveOut(hdr->size - hdr->data_offset); @@ -377,9 +417,6 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & } ControlInfoMap::Map ctrls; - controlIdMaps_.emplace_back(std::make_unique()); - ControlIdMap *localIdMap = controlIdMaps_.back().get(); - for (unsigned int i = 0; i < hdr->entries; ++i) { const struct ipa_control_info_entry *entry = entries.read(); @@ -388,15 +425,27 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & return {}; } - /* Create and cache the individual ControlId. */ ControlType type = static_cast(entry->type); - /** - * \todo Find a way to preserve the control name for debugging - * purpose. + + /* + * If we have a valid id map, reuse the control id there stored, + * Otherwise populate the local idmap with a new ControlId + * reference. */ - controlIds_.emplace_back(std::make_unique(entry->id, "", type)); - ControlId *controlId = controlIds_.back().get(); - (*localIdMap)[entry->id] = controlId; + const ControlId *controlId; + if (idMap) { + controlId = idMap->at(entry->id); + ASSERT(controlId); + } else { + /** + * \todo Find a way to preserve the control name for + * debugging purpose. + */ + controlIds_.emplace_back(std::make_unique(entry->id, + "", type)); + controlId = controlIds_.back().get(); + (*localIdMap)[entry->id] = controlId; + } if (entry->offset != values.offset()) { LOG(Serializer, Error) @@ -405,10 +454,12 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & return {}; } - /* Create and store the ControlInfo. */ ctrls.emplace(controlId, loadControlInfo(type, values)); } + if (!idMap) + idMap = localIdMap; + /* * Create the ControlInfoMap in the cache, and store the map to handle * association. diff --git a/src/libcamera/ipa_controls.cpp b/src/libcamera/ipa_controls.cpp index 8fd726513182..1323fa31a28f 100644 --- a/src/libcamera/ipa_controls.cpp +++ b/src/libcamera/ipa_controls.cpp @@ -134,6 +134,35 @@ * \brief The current control serialization format version */ +/** + * \enum IdMapType + * \brief Enumerates the different control id map types + * + * Each ControlInfoMap and ControlList refers to a control id map that + * associates the ControlId references to a numerical identifier. + * During the serialization procedure the raw pointers to the ControlId + * instances cannot be transported on the wire, hence their numerical id is + * used to identify them in the serialized data buffer. At deserialization time + * it is required to associate back to the numerical id the ControlId instance + * it represents. This enumeration describes which ControlIdMap should be + * used to perform such operation. + * + * \var IdMapType::LIBCAMERA_CONTROLS + * \brief The numerical control identifier are resolved to a ControlId * using + * the global controls::controls id map + * + * \var IdMapType::LIBCAMERA_PROPERTIES + * \brief The numerical control identifier are resolved to a ControlId * using + * the global properties::properties id map + * + * \var IdMapType::V4L2_CONTROLS + * \brief ControlId for V4L2 defined controls are created by the video device + * that enumerates them, and are not available across the IPC boundaries. The + * deserializer shall create new ControlId instances for them as well as store + * them in a dedicated ControlIdMap. Only lookup by numerical id can be + * performed on de-serialized ControlInfoMap that represents V4L2 controls. + */ + /** * \struct ipa_controls_header * \brief Serialized control packet header @@ -149,6 +178,8 @@ * The total packet size in bytes * \var ipa_controls_header::data_offset * Offset in bytes from the beginning of the packet of the data section start + * \var ipa_controls_header::idMapType + * The id map type as defined by the IdMapType enumeration * \var ipa_controls_header::reserved * Reserved for future extensions */