mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-26 01:55:51 +03:00
libcamera: controls: Use ControlIdMap in deserialization
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 field is inspected and - If the idmap is a globally defined 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 us 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 <jacopo@jmondi.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
0d7db1b511
commit
62c82ab93f
3 changed files with 91 additions and 13 deletions
|
@ -15,13 +15,20 @@ extern "C" {
|
||||||
|
|
||||||
#define IPA_CONTROLS_FORMAT_VERSION 1
|
#define IPA_CONTROLS_FORMAT_VERSION 1
|
||||||
|
|
||||||
|
enum ipa_controls_id_map_type {
|
||||||
|
IPA_CONTROL_ID_MAP_CONTROLS,
|
||||||
|
IPA_CONTROL_ID_MAP_PROPERTIES,
|
||||||
|
IPA_CONTROL_ID_MAP_V4L2,
|
||||||
|
};
|
||||||
|
|
||||||
struct ipa_controls_header {
|
struct ipa_controls_header {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
uint32_t entries;
|
uint32_t entries;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t data_offset;
|
uint32_t data_offset;
|
||||||
uint32_t reserved[3];
|
enum ipa_controls_id_map_type id_map_type;
|
||||||
|
uint32_t reserved[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipa_control_value_entry {
|
struct ipa_control_value_entry {
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include <libcamera/control_ids.h>
|
#include <libcamera/control_ids.h>
|
||||||
#include <libcamera/controls.h>
|
#include <libcamera/controls.h>
|
||||||
|
#include <libcamera/property_ids.h>
|
||||||
|
|
||||||
#include <libcamera/ipa/ipa_controls.h>
|
#include <libcamera/ipa/ipa_controls.h>
|
||||||
|
|
||||||
#include "libcamera/internal/byte_stream_buffer.h"
|
#include "libcamera/internal/byte_stream_buffer.h"
|
||||||
|
@ -188,6 +190,15 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
|
||||||
for (const auto &ctrl : infoMap)
|
for (const auto &ctrl : infoMap)
|
||||||
valuesSize += binarySize(ctrl.second);
|
valuesSize += binarySize(ctrl.second);
|
||||||
|
|
||||||
|
const ControlIdMap *idmap = &infoMap.idmap();
|
||||||
|
enum ipa_controls_id_map_type idMapType;
|
||||||
|
if (idmap == &controls::controls)
|
||||||
|
idMapType = IPA_CONTROL_ID_MAP_CONTROLS;
|
||||||
|
else if (idmap == &properties::properties)
|
||||||
|
idMapType = IPA_CONTROL_ID_MAP_PROPERTIES;
|
||||||
|
else
|
||||||
|
idMapType = IPA_CONTROL_ID_MAP_V4L2;
|
||||||
|
|
||||||
/* Prepare the packet header, assign a handle to the ControlInfoMap. */
|
/* Prepare the packet header, assign a handle to the ControlInfoMap. */
|
||||||
struct ipa_controls_header hdr;
|
struct ipa_controls_header hdr;
|
||||||
hdr.version = IPA_CONTROLS_FORMAT_VERSION;
|
hdr.version = IPA_CONTROLS_FORMAT_VERSION;
|
||||||
|
@ -195,6 +206,7 @@ int ControlSerializer::serialize(const ControlInfoMap &infoMap,
|
||||||
hdr.entries = infoMap.size();
|
hdr.entries = infoMap.size();
|
||||||
hdr.size = sizeof(hdr) + entriesSize + valuesSize;
|
hdr.size = sizeof(hdr) + entriesSize + valuesSize;
|
||||||
hdr.data_offset = sizeof(hdr) + entriesSize;
|
hdr.data_offset = sizeof(hdr) + entriesSize;
|
||||||
|
hdr.id_map_type = idMapType;
|
||||||
|
|
||||||
buffer.write(&hdr);
|
buffer.write(&hdr);
|
||||||
|
|
||||||
|
@ -368,6 +380,33 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the ControlIdMap corresponding to the id map type. If the type
|
||||||
|
* references a globally defined id map (such as controls::controls
|
||||||
|
* or properties::properties), use it. Otherwise, create a local id map
|
||||||
|
* that will be populated with dynamically created ControlId instances
|
||||||
|
* when deserializing individual ControlInfoMap entries.
|
||||||
|
*/
|
||||||
|
const ControlIdMap *idMap = nullptr;
|
||||||
|
ControlIdMap *localIdMap = nullptr;
|
||||||
|
switch (hdr->id_map_type) {
|
||||||
|
case IPA_CONTROL_ID_MAP_CONTROLS:
|
||||||
|
idMap = &controls::controls;
|
||||||
|
break;
|
||||||
|
case IPA_CONTROL_ID_MAP_PROPERTIES:
|
||||||
|
idMap = &properties::properties;
|
||||||
|
break;
|
||||||
|
case IPA_CONTROL_ID_MAP_V4L2:
|
||||||
|
controlIdMaps_.emplace_back(std::make_unique<ControlIdMap>());
|
||||||
|
localIdMap = controlIdMaps_.back().get();
|
||||||
|
idMap = localIdMap;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(Serializer, Error)
|
||||||
|
<< "Unknown id map type: " << hdr->id_map_type;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
ByteStreamBuffer entries = buffer.carveOut(hdr->data_offset - sizeof(*hdr));
|
ByteStreamBuffer entries = buffer.carveOut(hdr->data_offset - sizeof(*hdr));
|
||||||
ByteStreamBuffer values = buffer.carveOut(hdr->size - hdr->data_offset);
|
ByteStreamBuffer values = buffer.carveOut(hdr->size - hdr->data_offset);
|
||||||
|
|
||||||
|
@ -377,9 +416,6 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlInfoMap::Map ctrls;
|
ControlInfoMap::Map ctrls;
|
||||||
controlIdMaps_.emplace_back(std::make_unique<ControlIdMap>());
|
|
||||||
ControlIdMap *localIdMap = controlIdMaps_.back().get();
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < hdr->entries; ++i) {
|
for (unsigned int i = 0; i < hdr->entries; ++i) {
|
||||||
const struct ipa_control_info_entry *entry =
|
const struct ipa_control_info_entry *entry =
|
||||||
entries.read<decltype(*entry)>();
|
entries.read<decltype(*entry)>();
|
||||||
|
@ -388,15 +424,21 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
|
||||||
return {};
|
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
|
/* If we're using a local id map, populate it. */
|
||||||
* purpose.
|
if (localIdMap) {
|
||||||
*/
|
/**
|
||||||
controlIds_.emplace_back(std::make_unique<ControlId>(entry->id, "", type));
|
* \todo Find a way to preserve the control name for
|
||||||
ControlId *controlId = controlIds_.back().get();
|
* debugging purpose.
|
||||||
(*localIdMap)[entry->id] = controlId;
|
*/
|
||||||
|
controlIds_.emplace_back(std::make_unique<ControlId>(entry->id,
|
||||||
|
"", type));
|
||||||
|
(*localIdMap)[entry->id] = controlIds_.back().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ControlId *controlId = idMap->at(entry->id);
|
||||||
|
ASSERT(controlId);
|
||||||
|
|
||||||
if (entry->offset != values.offset()) {
|
if (entry->offset != values.offset()) {
|
||||||
LOG(Serializer, Error)
|
LOG(Serializer, Error)
|
||||||
|
@ -413,7 +455,7 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
|
||||||
* Create the ControlInfoMap in the cache, and store the map to handle
|
* Create the ControlInfoMap in the cache, and store the map to handle
|
||||||
* association.
|
* association.
|
||||||
*/
|
*/
|
||||||
infoMaps_[hdr->handle] = ControlInfoMap(std::move(ctrls), *localIdMap);
|
infoMaps_[hdr->handle] = ControlInfoMap(std::move(ctrls), *idMap);
|
||||||
ControlInfoMap &map = infoMaps_[hdr->handle];
|
ControlInfoMap &map = infoMaps_[hdr->handle];
|
||||||
infoMapHandles_[&map] = hdr->handle;
|
infoMapHandles_[&map] = hdr->handle;
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,33 @@
|
||||||
* \brief The current control serialization format version
|
* \brief The current control serialization format version
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \var ipa_controls_id_map_type
|
||||||
|
* \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 ipa_controls_id_map_type::IPA_CONTROL_ID_MAP_CONTROLS
|
||||||
|
* \brief The numerical control identifier are resolved to a ControlId * using
|
||||||
|
* the global controls::controls id map
|
||||||
|
* \var ipa_controls_id_map_type::IPA_CONTROL_ID_MAP_PROPERTIES
|
||||||
|
* \brief The numerical control identifier are resolved to a ControlId * using
|
||||||
|
* the global properties::properties id map
|
||||||
|
* \var ipa_controls_id_map_type::IPA_CONTROL_ID_MAP_V4L2
|
||||||
|
* \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
|
* \struct ipa_controls_header
|
||||||
* \brief Serialized control packet header
|
* \brief Serialized control packet header
|
||||||
|
@ -149,6 +176,8 @@
|
||||||
* The total packet size in bytes
|
* The total packet size in bytes
|
||||||
* \var ipa_controls_header::data_offset
|
* \var ipa_controls_header::data_offset
|
||||||
* Offset in bytes from the beginning of the packet of the data section start
|
* Offset in bytes from the beginning of the packet of the data section start
|
||||||
|
* \var ipa_controls_header::id_map_type
|
||||||
|
* The id map type as defined by the ipa_controls_id_map_type enumeration
|
||||||
* \var ipa_controls_header::reserved
|
* \var ipa_controls_header::reserved
|
||||||
* Reserved for future extensions
|
* Reserved for future extensions
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue