summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/internal/camera_sensor.h2
-rw-r--r--include/libcamera/internal/v4l2_device.h2
-rw-r--r--src/libcamera/camera_sensor.cpp31
-rw-r--r--src/libcamera/v4l2_device.cpp37
4 files changed, 71 insertions, 1 deletions
diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index 3fa3a419..2a5c51a1 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -68,6 +68,8 @@ public:
const ControlList &properties() const { return properties_; }
int sensorInfo(CameraSensorInfo *info) const;
+ void updateControlInfo();
+
protected:
std::string logPrefix() const override;
diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h
index 087f07e7..5ba9b23b 100644
--- a/include/libcamera/internal/v4l2_device.h
+++ b/include/libcamera/internal/v4l2_device.h
@@ -42,6 +42,8 @@ public:
int setFrameStartEnabled(bool enable);
Signal<uint32_t> frameStart;
+ void updateControlInfo();
+
protected:
V4L2Device(const std::string &deviceNode);
~V4L2Device();
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index 1db263cf..eb84d9eb 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -670,15 +670,30 @@ V4L2SubdeviceFormat CameraSensor::getFormat(const std::vector<unsigned int> &mbu
/**
* \brief Set the sensor output format
* \param[in] format The desired sensor output format
+ *
+ * The ranges of any controls associated with the sensor are also updated.
+ *
* \return 0 on success or a negative error code otherwise
*/
int CameraSensor::setFormat(V4L2SubdeviceFormat *format)
{
- return subdev_->setFormat(pad_, format);
+ int ret = subdev_->setFormat(pad_, format);
+ if (ret)
+ return ret;
+
+ updateControlInfo();
+ return 0;
}
/**
* \brief Retrieve the supported V4L2 controls and their information
+ *
+ * Control information is updated automatically to reflect the current sensor
+ * configuration when the setFormat() function is called, without invalidating
+ * any iterator on the ControlInfoMap. A manual update can also be forced by
+ * calling the updateControlInfo() function for pipeline handlers that change
+ * the sensor configuration wihtout using setFormat().
+ *
* \return A map of the V4L2 controls supported by the sensor
*/
const ControlInfoMap &CameraSensor::controls() const
@@ -764,6 +779,10 @@ int CameraSensor::setControls(ControlList *ctrls)
* Sensor information is only available for raw sensors. When called for a YUV
* sensor, this function returns -EINVAL.
*
+ * Pipeline handlers that do not change the sensor format using the setFormat()
+ * method may need to call updateControlInfo() beforehand, to ensure all the
+ * control ranges are up to date.
+ *
* \return 0 on success, a negative error code otherwise
*/
int CameraSensor::sensorInfo(CameraSensorInfo *info) const
@@ -835,6 +854,16 @@ int CameraSensor::sensorInfo(CameraSensorInfo *info) const
return 0;
}
+/**
+ * \fn void CameraSensor::updateControlInfo()
+ * \brief Update the sensor's ControlInfoMap in case they have changed
+ * \sa V4L2Device::updateControlInfo()
+ */
+void CameraSensor::updateControlInfo()
+{
+ subdev_->updateControlInfo();
+}
+
std::string CameraSensor::logPrefix() const
{
return "'" + entity_->name() + "'";
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index 397029ac..515cbdfe 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -511,6 +511,43 @@ void V4L2Device::listControls()
controls_ = std::move(ctrls);
}
+/**
+* \brief Update the information for all device controls
+ *
+ * The V4L2Device class caches information about all controls supported by the
+ * device and exposes it through the controls() and controlInfo() functions.
+ * Control information may change at runtime, for instance when formats on a
+ * subdev are modified. When this occurs, this function can be used to refresh
+ * control information. The information is refreshed in-place, all pointers to
+ * v4l2_query_ext_ctrl instances previously returned by controlInfo() and
+ * iterators to the ControlInfoMap returned by controls() remain valid.
+ *
+ * Note that control information isn't refreshed automatically is it may be an
+ * expensive operation. The V4L2Device users are responsible for calling this
+ * function when required, based on their usage pattern of the class.
+ */
+void V4L2Device::updateControlInfo()
+{
+ for (auto &[controlId, info] : controls_) {
+ unsigned int id = controlId->id();
+
+ /*
+ * Assume controlInfo_ has a corresponding entry, as it has been
+ * generated by listControls().
+ */
+ struct v4l2_query_ext_ctrl &ctrl = controlInfo_[id];
+
+ if (ioctl(VIDIOC_QUERY_EXT_CTRL, &ctrl)) {
+ LOG(V4L2, Debug)
+ << "Could not refresh control "
+ << utils::hex(id);
+ continue;
+ }
+
+ info = V4L2ControlInfo(ctrl);
+ }
+}
+
/*
* \brief Update the value of the first \a count V4L2 controls in \a ctrls using
* values in \a v4l2Ctrls