[libcamera-devel] [PATCH 22/23] libcamera: control_serializer: Add support for compound controls

Jacopo Mondi jacopo at jmondi.org
Mon Jan 13 17:42:44 CET 2020


Add support for serializing and deserializing control values which
transport compound values.

Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
 src/libcamera/control_serializer.cpp       | 123 ++++++++++++++++++---
 src/libcamera/include/control_serializer.h |  10 +-
 2 files changed, 117 insertions(+), 16 deletions(-)

diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp
index fd91baf15156..75e8ebc3d9d3 100644
--- a/src/libcamera/control_serializer.cpp
+++ b/src/libcamera/control_serializer.cpp
@@ -14,6 +14,7 @@
 #include <ipa/ipa_controls.h>
 #include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
+#include <libcamera/span.h>
 
 #include "byte_stream_buffer.h"
 #include "log.h"
@@ -30,11 +31,15 @@ LOG_DEFINE_CATEGORY(Serializer)
 namespace {
 
 static constexpr size_t ControlValueSize[] = {
-	[ControlTypeNone]	= 1,
-	[ControlTypeBool]	= sizeof(bool),
-	[ControlTypeInteger32]	= sizeof(int32_t),
-	[ControlTypeInteger64]	= sizeof(int64_t),
-	[ControlTypeFloat]	= sizeof(float),
+	[ControlTypeNone]		= 1,
+	[ControlTypeBool]		= sizeof(bool),
+	[ControlTypeInteger32]		= sizeof(int32_t),
+	[ControlTypeInteger64]		= sizeof(int64_t),
+	[ControlTypeFloat]		= sizeof(float),
+	[ControlTypeCompoundBool]	= sizeof(bool),
+	[ControlTypeCompoundInt32]	= sizeof(int32_t),
+	[ControlTypeCompoundInt64]	= sizeof(int64_t),
+	[ControlTypeCompoundFloat]	= sizeof(float),
 };
 
 } /* namespace */
@@ -107,7 +112,7 @@ void ControlSerializer::reset()
 
 size_t ControlSerializer::binarySize(const ControlValue &value)
 {
-	return ControlValueSize[value.type()];
+	return ControlValueSize[value.type()] * value.numElements();
 }
 
 size_t ControlSerializer::binarySize(const ControlRange &range)
@@ -183,6 +188,30 @@ void ControlSerializer::store(const ControlValue &value,
 		break;
 	}
 
+	case ControlTypeCompoundBool: {
+		Span<bool> data = value.get<Span<bool>>();
+		buffer.write(&data);
+		break;
+	}
+
+	case ControlTypeCompoundInt32: {
+		Span<int32_t> data = value.get<Span<int32_t>>();
+		buffer.write(data);
+		break;
+	}
+
+	case ControlTypeCompoundInt64: {
+		Span<int64_t> data = value.get<Span<int64_t>>();
+		buffer.write(data);
+		break;
+	}
+
+	case ControlTypeCompoundFloat: {
+		Span<float> data = value.get<Span<float>>();
+		buffer.write(data);
+		break;
+	}
+
 	default:
 		break;
 	}
@@ -318,7 +347,7 @@ int ControlSerializer::serialize(const ControlList &list,
 
 		struct ipa_control_value_entry entry;
 		entry.id = id;
-		entry.count = 1;
+		entry.count = value.numElements();
 		entry.type = value.type();
 		entry.offset = values.offset();
 		entries.write(&entry);
@@ -332,35 +361,74 @@ int ControlSerializer::serialize(const ControlList &list,
 	return 0;
 }
 
+template<typename T>
+void ControlSerializer::loadData(ByteStreamBuffer &buffer, unsigned int count,
+				 ControlValue *value)
+{
+	Span<T> data(new T[count], count);
+	buffer.read(&data);
+
+	/*
+	 * Use of ControlValue::set() guarantees the memory content
+	 * is copied into the ControlValue.
+	 */
+	value->set(data);
+}
+
 template<>
 ControlValue ControlSerializer::load<ControlValue>(ControlType type,
-						   ByteStreamBuffer &b)
+						   ByteStreamBuffer &buffer,
+						   unsigned int count)
 {
 	switch (type) {
 	case ControlTypeBool: {
 		bool value;
-		b.read(&value);
+		buffer.read(&value);
 		return ControlValue(value);
 	}
 
 	case ControlTypeInteger32: {
 		int32_t value;
-		b.read(&value);
+		buffer.read(&value);
 		return ControlValue(value);
 	}
 
 	case ControlTypeInteger64: {
 		int64_t value;
-		b.read(&value);
+		buffer.read(&value);
 		return ControlValue(value);
 	}
 
 	case ControlTypeFloat: {
 		float value;
-		b.read(&value);
+		buffer.read(&value);
 		return ControlValue(value);
 	}
 
+	case ControlTypeCompoundBool: {
+		ControlValue value;
+		loadData<bool>(buffer, count, &value);
+		return value;
+	}
+
+	case ControlTypeCompoundInt32: {
+		ControlValue value;
+		loadData<int32_t>(buffer, count, &value);
+		return value;
+	}
+
+	case ControlTypeCompoundInt64: {
+		ControlValue value;
+		loadData<int64_t>(buffer, count, &value);
+		return value;
+	}
+
+	case ControlTypeCompoundFloat: {
+		ControlValue value;
+		loadData<float>(buffer, count, &value);
+		return value;
+	}
+
 	default:
 		return ControlValue();
 	}
@@ -370,8 +438,32 @@ template<>
 ControlRange ControlSerializer::load<ControlRange>(ControlType type,
 						   ByteStreamBuffer &b)
 {
-	ControlValue min = load<ControlValue>(type, b);
-	ControlValue max = load<ControlValue>(type, b);
+	/*
+	 * The 'type' parameter represents the type of the Control
+	 * the ControlRange refers to. Even if the Control is a compound,
+	 * its range elements are not: adjust the type opportunely.
+	 */
+	ControlType rangeType;
+	switch (type) {
+	case ControlTypeCompoundBool:
+		rangeType = ControlTypeBool;
+		break;
+	case ControlTypeCompoundInt32:
+		rangeType = ControlTypeInteger32;
+		break;
+	case ControlTypeCompoundInt64:
+		rangeType = ControlTypeInteger64;
+		break;
+	case ControlTypeCompoundFloat:
+		rangeType = ControlTypeFloat;
+		break;
+	default:
+		rangeType = type;
+		break;
+	}
+
+	ControlValue min = load<ControlValue>(rangeType, b);
+	ControlValue max = load<ControlValue>(rangeType, b);
 
 	return ControlRange(min, max);
 }
@@ -519,7 +611,8 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer
 		}
 
 		ControlType type = static_cast<ControlType>(entry.type);
-		ctrls.set(entry.id, load<ControlValue>(type, values));
+		ctrls.set(entry.id,
+			  load<ControlValue>(type, values, entry.count));
 	}
 
 	return ctrls;
diff --git a/src/libcamera/include/control_serializer.h b/src/libcamera/include/control_serializer.h
index 55259913a2ca..2d76ffe7ed84 100644
--- a/src/libcamera/include/control_serializer.h
+++ b/src/libcamera/include/control_serializer.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <memory>
 #include <vector>
+#include <type_traits>
 
 #include <libcamera/controls.h>
 
@@ -40,8 +41,15 @@ private:
 	static void store(const ControlValue &value, ByteStreamBuffer &buffer);
 	static void store(const ControlRange &range, ByteStreamBuffer &buffer);
 
+	template<typename T,
+		 typename std::enable_if<std::is_same<ControlValue, T>::value>::type * = nullptr>
+	T load(ControlType type, ByteStreamBuffer &buffer, unsigned int count = 1);
+	template<typename T,
+		 typename std::enable_if<std::is_same<ControlRange, T>::value>::type * = nullptr>
+	T load(ControlType type, ByteStreamBuffer &buffer);
 	template<typename T>
-	T load(ControlType type, ByteStreamBuffer &b);
+	void loadData(ByteStreamBuffer &buffer, unsigned int count,
+		      ControlValue *value);
 
 	unsigned int serial_;
 	std::vector<std::unique_ptr<ControlId>> controlIds_;
-- 
2.24.0



More information about the libcamera-devel mailing list