[libcamera-devel] [RFC] libcamera: v4l2_device: Update control info
Jacopo Mondi
jacopo at jmondi.org
Fri Jun 5 16:20:37 CEST 2020
Setting controls on a V4L2 device might update the limits of other
related controls (in example, setting a new vertical/horizontal blanking
value might modify the available exposure time duration).
Add a funtion to update the ControlInfo that represents a control
minimum, maximum and default values and call it after a new control has
been set and format is changed on a V4L2 subdevice.
Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
We'll soon need something like that.
However, seems like an expensive operation to perform after every control
and format update.
Opinions ?
---
include/libcamera/controls.h | 4 ++
include/libcamera/internal/v4l2_device.h | 2 +
src/libcamera/controls.cpp | 18 +++++++++
src/libcamera/v4l2_device.cpp | 48 ++++++++++++++++++++++++
src/libcamera/v4l2_subdevice.cpp | 3 ++
5 files changed, 75 insertions(+)
diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
index 80944efc133a..74b0c6b26517 100644
--- a/include/libcamera/controls.h
+++ b/include/libcamera/controls.h
@@ -273,6 +273,10 @@ public:
const ControlValue &max() const { return max_; }
const ControlValue &def() const { return def_; }
+ void setMin(ControlValue val) { min_ = val; }
+ void setMax(ControlValue val) { max_ = val; }
+ void setDef(ControlValue val) { def_ = val; }
+
std::string toString() const;
bool operator==(const ControlInfo &other) const
diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h
index d491eafd262e..1563ec7272c7 100644
--- a/include/libcamera/internal/v4l2_device.h
+++ b/include/libcamera/internal/v4l2_device.h
@@ -42,6 +42,8 @@ protected:
int fd() { return fd_; }
+ void updateControlsInfo();
+
private:
void listControls();
void updateControls(ControlList *ctrls,
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
index dca782667d88..f92128dd1878 100644
--- a/src/libcamera/controls.cpp
+++ b/src/libcamera/controls.cpp
@@ -519,6 +519,24 @@ ControlInfo::ControlInfo(const ControlValue &min,
* \return A ControlValue with the default value for the control
*/
+/**
+ * \fn ControlInfo::setMin()
+ * \brief Set the minimum value for the control
+ * \param[in] val The control minimum value
+ */
+
+/**
+ * \fn ControlInfo::setMax()
+ * \brief Set the maximum value for the control
+ * \param[in] val The control maximum value
+ */
+
+/**
+ * \fn ControlInfo::setDef()
+ * \brief Set the default value for the control
+ * \param[in] val The control default value
+ */
+
/**
* \brief Provide a string representation of the ControlInfo
*/
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index 56ea1ddda2c1..7e1286d7ddd0 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -346,6 +346,7 @@ int V4L2Device::setControls(ControlList *ctrls)
}
updateControls(ctrls, v4l2Ctrls, count);
+ updateControlsInfo();
return ret;
}
@@ -380,6 +381,53 @@ int V4L2Device::ioctl(unsigned long request, void *argp)
* \return The V4L2 device file descriptor, -1 if the device node is not open
*/
+/**
+ * \brief Update the control info
+ *
+ * Update all control limits (min and max) and default value.
+ */
+void V4L2Device::updateControlsInfo()
+{
+ for (auto &it : controls_) {
+ const ControlId *id = it.first;
+ ControlInfo &info = it.second;
+ struct v4l2_query_ext_ctrl ctrl = {};
+ ctrl.id = id->id();
+ int ret = ioctl(VIDIOC_QUERY_EXT_CTRL, &ctrl);
+ if (ret) {
+ LOG(V4L2, Error) << "Unable to query control "
+ << ctrl.id << ": " << strerror(-ret);
+ return;
+ }
+
+ switch (ctrl.type) {
+ case V4L2_CTRL_TYPE_U8:
+ info.setMin({ static_cast<uint8_t>(ctrl.minimum) });
+ info.setMax({ static_cast<uint8_t>(ctrl.maximum) });
+ info.setDef({ static_cast<uint8_t>(ctrl.default_value) });
+ break;
+
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ info.setMin({ static_cast<bool>(ctrl.minimum) });
+ info.setMax({ static_cast<bool>(ctrl.maximum) });
+ info.setDef({ static_cast<bool>(ctrl.default_value) });
+ break;
+
+ case V4L2_CTRL_TYPE_INTEGER64:
+ info.setMin({ static_cast<bool>(ctrl.minimum) });
+ info.setMax({ static_cast<bool>(ctrl.maximum) });
+ info.setDef({ static_cast<bool>(ctrl.default_value) });
+ break;
+
+ default:
+ info.setMin({ static_cast<bool>(ctrl.minimum) });
+ info.setMax({ static_cast<bool>(ctrl.maximum) });
+ info.setDef({ static_cast<bool>(ctrl.default_value) });
+ break;
+ }
+ }
+}
+
/*
* \brief List and store information about all controls supported by the
* V4L2 device
diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
index 7aefc1be032d..c0dc036a09cc 100644
--- a/src/libcamera/v4l2_subdevice.cpp
+++ b/src/libcamera/v4l2_subdevice.cpp
@@ -411,6 +411,9 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format,
format->size.height = subdevFmt.format.height;
format->mbus_code = subdevFmt.format.code;
+ /* Changing the format could update the contol limits. */
+ updateControlsInfo();
+
return 0;
}
--
2.27.0
More information about the libcamera-devel
mailing list