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>
This commit is contained in:
parent
9ab024f7c2
commit
8daf20485b
4 changed files with 50 additions and 72 deletions
|
@ -115,6 +115,7 @@ public:
|
||||||
bool isArray() const { return isArray_; }
|
bool isArray() const { return isArray_; }
|
||||||
std::size_t numElements() const { return numElements_; }
|
std::size_t numElements() const { return numElements_; }
|
||||||
Span<const uint8_t> data() const;
|
Span<const uint8_t> data() const;
|
||||||
|
Span<uint8_t> data();
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
@ -174,6 +175,9 @@ public:
|
||||||
value.data(), value.size(), sizeof(typename T::value_type));
|
value.data(), value.size(), sizeof(typename T::value_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reserve(ControlType type, bool isArray = false,
|
||||||
|
std::size_t numElements = 1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ControlType type_ : 8;
|
ControlType type_ : 8;
|
||||||
bool isArray_;
|
bool isArray_;
|
||||||
|
|
|
@ -295,70 +295,17 @@ int ControlSerializer::serialize(const ControlList &list,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
|
|
||||||
bool isArray,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
ControlValue value;
|
|
||||||
|
|
||||||
const T *data = buffer.read<T>(count);
|
|
||||||
if (!data)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
if (isArray)
|
|
||||||
value.set(Span<const T>{ data, count });
|
|
||||||
else
|
|
||||||
value.set(*data);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
ControlValue ControlSerializer::loadControlValue<std::string>(ByteStreamBuffer &buffer,
|
|
||||||
bool isArray,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
ControlValue value;
|
|
||||||
|
|
||||||
const char *data = buffer.read<char>(count);
|
|
||||||
if (!data)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
value.set(std::string{ data, count });
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControlValue ControlSerializer::loadControlValue(ControlType type,
|
ControlValue ControlSerializer::loadControlValue(ControlType type,
|
||||||
ByteStreamBuffer &buffer,
|
ByteStreamBuffer &buffer,
|
||||||
bool isArray,
|
bool isArray,
|
||||||
unsigned int count)
|
unsigned int count)
|
||||||
{
|
{
|
||||||
switch (type) {
|
ControlValue value;
|
||||||
case ControlTypeBool:
|
|
||||||
return loadControlValue<bool>(buffer, isArray, count);
|
|
||||||
|
|
||||||
case ControlTypeByte:
|
value.reserve(type, isArray, count);
|
||||||
return loadControlValue<uint8_t>(buffer, isArray, count);
|
buffer.read(value.data());
|
||||||
|
|
||||||
case ControlTypeInteger32:
|
return value;
|
||||||
return loadControlValue<int32_t>(buffer, isArray, count);
|
|
||||||
|
|
||||||
case ControlTypeInteger64:
|
|
||||||
return loadControlValue<int64_t>(buffer, isArray, count);
|
|
||||||
|
|
||||||
case ControlTypeFloat:
|
|
||||||
return loadControlValue<float>(buffer, isArray, count);
|
|
||||||
|
|
||||||
case ControlTypeString:
|
|
||||||
return loadControlValue<std::string>(buffer, isArray, count);
|
|
||||||
|
|
||||||
case ControlTypeNone:
|
|
||||||
return ControlValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ControlValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlInfo ControlSerializer::loadControlInfo(ControlType type,
|
ControlInfo ControlSerializer::loadControlInfo(ControlType type,
|
||||||
|
|
|
@ -189,6 +189,15 @@ Span<const uint8_t> ControlValue::data() const
|
||||||
return { data, size };
|
return { data, size };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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
|
* \brief Assemble and return a string describing the value
|
||||||
* \return A string describing the ControlValue
|
* \return A string describing the ControlValue
|
||||||
|
@ -312,23 +321,44 @@ void ControlValue::set(ControlType type, bool isArray, const void *data,
|
||||||
{
|
{
|
||||||
ASSERT(elementSize == ControlValueSize[type]);
|
ASSERT(elementSize == ControlValueSize[type]);
|
||||||
|
|
||||||
|
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();
|
release();
|
||||||
|
|
||||||
type_ = type;
|
type_ = type;
|
||||||
numElements_ = numElements;
|
|
||||||
isArray_ = isArray;
|
isArray_ = isArray;
|
||||||
|
numElements_ = numElements;
|
||||||
|
|
||||||
std::size_t size = elementSize * numElements;
|
if (oldSize == newSize)
|
||||||
void *storage;
|
return;
|
||||||
|
|
||||||
if (size > sizeof(value_)) {
|
if (newSize > sizeof(value_))
|
||||||
storage_ = reinterpret_cast<void *>(new uint8_t[size]);
|
storage_ = reinterpret_cast<void *>(new uint8_t[newSize]);
|
||||||
storage = storage_;
|
|
||||||
} else {
|
|
||||||
storage = reinterpret_cast<void *>(&value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(storage, data, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,9 +40,6 @@ private:
|
||||||
static void store(const ControlValue &value, ByteStreamBuffer &buffer);
|
static void store(const ControlValue &value, ByteStreamBuffer &buffer);
|
||||||
static void store(const ControlInfo &info, ByteStreamBuffer &buffer);
|
static void store(const ControlInfo &info, ByteStreamBuffer &buffer);
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ControlValue loadControlValue(ByteStreamBuffer &buffer, bool isArray,
|
|
||||||
unsigned int count);
|
|
||||||
ControlValue loadControlValue(ControlType type, ByteStreamBuffer &buffer,
|
ControlValue loadControlValue(ControlType type, ByteStreamBuffer &buffer,
|
||||||
bool isArray = false, unsigned int count = 1);
|
bool isArray = false, unsigned int count = 1);
|
||||||
ControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer);
|
ControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue