diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-02-28 17:01:43 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-03-23 16:45:16 +0200 |
commit | 8daf20485b90af2065e3db0e3fd0cd5b72fd7ac4 (patch) | |
tree | 7d01521858283e8da927f2b429e3ea5b7d4f6bb9 /src/libcamera/controls.cpp | |
parent | 9ab024f7c27d9b6b3ab433502eab02d4a29a3da4 (diff) |
libcamera: controls: Add zero-copy set API for ControlValue
Extend the ControlValue class with a reserve() function to set the value
without actually copying data, and a non-const data() function that
allows writing data directly to the ControlValue storage. This allows
allocating memory directly in ControlValue, potentially removing a data
copy.
Note that this change was implemented before ByteStreamBuffer gained the
zero-copy read() variant, and doesn't actually save a copy in the
control serializer. It however still simplifies
ControlSerializer::loadControlValue().
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Diffstat (limited to 'src/libcamera/controls.cpp')
-rw-r--r-- | src/libcamera/controls.cpp | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 25684474..540cc026 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -190,6 +190,15 @@ Span<const uint8_t> ControlValue::data() const } /** + * \copydoc ControlValue::data() const + */ +Span<uint8_t> ControlValue::data() +{ + Span<const uint8_t> data = const_cast<const ControlValue *>(this)->data(); + return { const_cast<uint8_t *>(data.data()), data.size() }; +} + +/** * \brief Assemble and return a string describing the value * \return A string describing the ControlValue */ @@ -312,23 +321,44 @@ void ControlValue::set(ControlType type, bool isArray, const void *data, { ASSERT(elementSize == ControlValueSize[type]); - release(); + reserve(type, isArray, numElements); + + Span<uint8_t> storage = ControlValue::data(); + memcpy(storage.data(), data, storage.size()); +} + +/** + * \brief Set the control type and reserve memory + * \param[in] type The control type + * \param[in] isArray True to make the value an array + * \param[in] numElements The number of elements + * + * This function sets the type of the control value to \a type, and reserves + * memory to store the control value. If \a isArray is true, the instance + * becomes an array control and storage for \a numElements is reserved. + * Otherwise the instance becomes a simple control, numElements is ignored, and + * storage for the single element is reserved. + */ +void ControlValue::reserve(ControlType type, bool isArray, std::size_t numElements) +{ + if (!isArray) + numElements = 1; + + std::size_t oldSize = numElements_ * ControlValueSize[type_]; + std::size_t newSize = numElements * ControlValueSize[type]; + + if (oldSize != newSize) + release(); type_ = type; - numElements_ = numElements; isArray_ = isArray; + numElements_ = numElements; - std::size_t size = elementSize * numElements; - void *storage; - - if (size > sizeof(value_)) { - storage_ = reinterpret_cast<void *>(new uint8_t[size]); - storage = storage_; - } else { - storage = reinterpret_cast<void *>(&value_); - } + if (oldSize == newSize) + return; - memcpy(storage, data, size); + if (newSize > sizeof(value_)) + storage_ = reinterpret_cast<void *>(new uint8_t[newSize]); } /** |