[libcamera-devel] [RFC 2/2] controls: Define controls as compound

Jacopo Mondi jacopo at jmondi.org
Wed Dec 11 15:53:27 CET 2019


Add 'isCompound' flag to the control framework.

Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
 include/libcamera/controls.h         | 12 +++++--
 src/libcamera/control_ids.yaml       |  3 +-
 src/libcamera/control_serializer.cpp |  4 ++-
 src/libcamera/controls.cpp           | 24 +++++++-------
 src/libcamera/gen-controls.py        | 12 ++++++-
 src/libcamera/v4l2_controls.cpp      |  4 ++-
 test/controls/compound_controls.cpp  | 48 +++++++++++++++++-----------
 7 files changed, 70 insertions(+), 37 deletions(-)

diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
index b9f8d4db0bea..ddd641e01655 100644
--- a/include/libcamera/controls.h
+++ b/include/libcamera/controls.h
@@ -94,14 +94,16 @@ private:
 class ControlId
 {
 public:
-	ControlId(unsigned int id, const std::string &name, ControlType type)
-		: id_(id), name_(name), type_(type)
+	ControlId(unsigned int id, const std::string &name, ControlType type,
+		  bool isCompound)
+		: id_(id), name_(name), type_(type), isCompound_(isCompound)
 	{
 	}
 
 	unsigned int id() const { return id_; }
 	const std::string &name() const { return name_; }
 	ControlType type() const { return type_; }
+	bool isCompound() const { return isCompound_; }
 
 private:
 	ControlId &operator=(const ControlId &) = delete;
@@ -110,6 +112,7 @@ private:
 	unsigned int id_;
 	std::string name_;
 	ControlType type_;
+	bool isCompound_;
 };
 
 static inline bool operator==(unsigned int lhs, const ControlId &rhs)
@@ -138,7 +141,7 @@ class Control : public ControlId
 public:
 	using type = T;
 
-	Control(unsigned int id, const char *name);
+	Control(unsigned int id, const char *name, bool isCompound = false);
 
 private:
 	Control(const Control &) = delete;
@@ -272,6 +275,9 @@ public:
 	template<typename T>
 	void set(const Control<T> &ctrl, const Span<T> &values)
 	{
+		if (!ctrl.isCompound())
+			return;
+
 		ControlValue *val = find(ctrl.id());
 		if (!val)
 			return;
diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml
index b72e81dae060..1bdece651638 100644
--- a/src/libcamera/control_ids.yaml
+++ b/src/libcamera/control_ids.yaml
@@ -51,7 +51,8 @@ controls:
       description: Specify a fixed gain parameter
 
   - CompoundControl:
-      type: int8_t
+      type: int32_t
       description: A fictional compound control
+      compound: true
 
 ...
diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp
index 2140d3a5dd3f..82502285c5ca 100644
--- a/src/libcamera/control_serializer.cpp
+++ b/src/libcamera/control_serializer.cpp
@@ -415,8 +415,10 @@ ControlInfoMap ControlSerializer::deserialize<ControlInfoMap>(ByteStreamBuffer &
 		/**
 		 * \todo Find a way to preserve the control name for debugging
 		 * purpose.
+		 *
+		 * FIXME: set isCompound to false unconditionally
 		 */
-		controlIds_.emplace_back(utils::make_unique<ControlId>(entry.id, "", type));
+		controlIds_.emplace_back(utils::make_unique<ControlId>(entry.id, "", type, false));
 
 		if (entry.offset != values.offset()) {
 			LOG(Serializer, Error)
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
index 64d99f7669b6..8fb0088150d0 100644
--- a/src/libcamera/controls.cpp
+++ b/src/libcamera/controls.cpp
@@ -581,38 +581,38 @@ bool ControlValue::operator==(const ControlValue &other) const
 
 #ifndef __DOXYGEN__
 template<>
-Control<void>::Control(unsigned int id, const char *name)
-	: ControlId(id, name, ControlTypeNone)
+Control<void>::Control(unsigned int id, const char *name, bool isCompound)
+	: ControlId(id, name, ControlTypeNone, isCompound)
 {
 }
 
 template<>
-Control<bool>::Control(unsigned int id, const char *name)
-	: ControlId(id, name, ControlTypeBool)
+Control<bool>::Control(unsigned int id, const char *name, bool isCompound)
+	: ControlId(id, name, ControlTypeBool, isCompound)
 {
 }
 
 template<>
-Control<int8_t>::Control(unsigned int id, const char *name)
-	: ControlId(id, name, ControlTypeInteger8)
+Control<int8_t>::Control(unsigned int id, const char *name, bool isCompound)
+	: ControlId(id, name, ControlTypeInteger8, isCompound)
 {
 }
 
 template<>
-Control<int32_t>::Control(unsigned int id, const char *name)
-	: ControlId(id, name, ControlTypeInteger32)
+Control<int32_t>::Control(unsigned int id, const char *name, bool isCompound)
+	: ControlId(id, name, ControlTypeInteger32, isCompound)
 {
 }
 
 template<>
-Control<int64_t>::Control(unsigned int id, const char *name)
-	: ControlId(id, name, ControlTypeInteger64)
+Control<int64_t>::Control(unsigned int id, const char *name, bool isCompound)
+	: ControlId(id, name, ControlTypeInteger64, isCompound)
 {
 }
 
 template<>
-Control<float>::Control(unsigned int id, const char *name)
-	: ControlId(id, name, ControlTypeFloat)
+Control<float>::Control(unsigned int id, const char *name, bool isCompound)
+	: ControlId(id, name, ControlTypeFloat, isCompound)
 {
 }
 #endif /* __DOXYGEN__ */
diff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py
index 4a1ee52cdb04..820b862dcf01 100755
--- a/src/libcamera/gen-controls.py
+++ b/src/libcamera/gen-controls.py
@@ -26,6 +26,7 @@ ${description}\n *\n''')
 ${description}
  */''')
     def_template = string.Template('extern const Control<${type}> ${name}(${id_name}, "${name}");')
+    def_compound_template = string.Template('extern const Control<${type}> ${name}(${id_name}, "${name}", true);')
 
     ctrls_doc = []
     ctrls_def = []
@@ -67,8 +68,17 @@ ${description}
         except KeyError:
             pass
 
+        try:
+            compound = ctrl['compound']
+            isCompound = True
+        except KeyError:
+            isCompound = False
+
         ctrls_doc.append(doc_template.substitute(info))
-        ctrls_def.append(def_template.substitute(info))
+        if isCompound:
+            ctrls_def.append(def_compound_template.substitute(info))
+        else:
+            ctrls_def.append(def_template.substitute(info))
         ctrls_map.append('\t{ ' + id_name + ', &' + name + ' },')
 
     return {
diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp
index 7446c3880330..cd1b39a1a4b3 100644
--- a/src/libcamera/v4l2_controls.cpp
+++ b/src/libcamera/v4l2_controls.cpp
@@ -97,9 +97,11 @@ ControlType v4l2_ctrl_type(const struct v4l2_query_ext_ctrl &ctrl)
 /**
  * \brief Construct a V4L2ControlId from a struct v4l2_query_ext_ctrl
  * \param[in] ctrl The struct v4l2_query_ext_ctrl as returned by the kernel
+ *
+ * FIXME: set isCompound to false unconditionally
  */
 V4L2ControlId::V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl)
-	: ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl))
+	: ControlId(ctrl.id, v4l2_ctrl_name(ctrl), v4l2_ctrl_type(ctrl), false)
 {
 }
 
diff --git a/test/controls/compound_controls.cpp b/test/controls/compound_controls.cpp
index de00573df141..0ca72f683d1f 100644
--- a/test/controls/compound_controls.cpp
+++ b/test/controls/compound_controls.cpp
@@ -53,40 +53,52 @@ protected:
 		cout << span[0] << endl;
 
 		/*
-		 * Compound Controls
-		 *
-		 * As of now, all Controls are now 'compounds' when set with a
-		 * Span<> of values.
-		 *
-		 * We need to define how to establish that a Control is actually
-		 * a compound or supports a single value.
+		 * Compound Controls: can be set with a span of values
 		 */
-		list.set(controls::Brightness, {0, 125, 255});
-		Span<int32_t> iSpan = list.get(controls::Brightness);
+		list.set(controls::CompoundControl, { 0, 125, 253 });
+		Span<int32_t> iSpan = list.get(controls::CompoundControl);
 
 		cout << iSpan.size() << endl;
 		for (uint32_t i : iSpan)
 			cout << i << endl;
 
 		/*
-		 * But they can still be accessed and operated with a single
-		 * value.
+		 * But they can still be accessed and operated as a single
+		 * value control.
 		 */
-		list.set(controls::Brightness, 112);
-		cout << list.get(controls::Brightness) << endl;
+		list.set(controls::CompoundControl, 112);
+		cout << list.get(controls::CompoundControl) << endl;
 
 		/*
 		 * Or set with a Span and accessed by value. The first item
-		 * is returned.
+		 * is returned in this case.
 		 */
-		list.set(controls::Brightness, {50, 125});
-		cout << list.get(controls::Brightness) << endl;
+		list.set(controls::CompoundControl, { 50, 125 });
+		cout << list.get(controls::CompoundControl) << endl;
 
 		/* The other way around works as well. */
-		list.set(controls::Brightness, 133);
-		Span<int32_t> s = list.get(controls::Brightness);
+		list.set(controls::CompoundControl, 133);
+		Span<int32_t> s = list.get(controls::CompoundControl);
 		cout << s << endl;
 
+		/*
+		 * Try to set a non-compound control with a span<> and make
+		 * sure it fails.
+		 */
+		list.set(controls::Brightness, 55);
+		uint32_t brightness = list.get(controls::Brightness);
+		if (brightness != 55) {
+			cerr << "Failed to set non-compound control" << endl;
+			return TestFail;
+		}
+
+		list.set(controls::Brightness, { 45, 30 });
+		brightness = list.get(controls::Brightness);
+		if (brightness != 55) {
+			cerr << "non-compound control set with span<>" << endl;
+			return TestFail;
+		}
+
 		return TestPass;
 	}
 };
-- 
2.24.0



More information about the libcamera-devel mailing list