[libcamera-devel] [PATCH v3 08/23] libcamera: camera_sensor: Initialize controls
Jacopo Mondi
jacopo at jmondi.org
Thu Jun 30 15:38:47 CEST 2022
Initialize the control interface of the CameraSensor class by
registering the control limits for controls::internal::ExposureTime,
controls::internal::FrameDuration and controls::internal::AnalogueGain.
Update the CameraSensor controls in the CameraSensor::updateControlInfo()
function after having updated the subdevice V4L2 controls.
Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
include/libcamera/internal/camera_sensor.h | 3 +
src/libcamera/camera_sensor/camera_sensor.cpp | 90 +++++++++++++++++++
2 files changed, 93 insertions(+)
diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index 2a850dedc0aa..1eab5e9d53f0 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -63,6 +63,7 @@ public:
V4L2Subdevice *device() { return subdev_.get(); }
const ControlList &properties() const { return properties_; }
+ const ControlInfoMap &controls() const { return controls_; }
int sensorInfo(IPACameraSensorInfo *info) const;
void updateControlInfo();
@@ -81,6 +82,7 @@ private:
void initStaticProperties();
void initTestPatternModes();
int initProperties();
+ int updateControls();
int applyTestPatternMode(controls::draft::TestPatternModeEnum mode);
int discoverAncillaryDevices();
@@ -104,6 +106,7 @@ private:
const BayerFormat *bayerFormat_;
ControlList properties_;
+ ControlInfoMap controls_;
std::unique_ptr<CameraLens> focusLens_;
std::unique_ptr<CameraSensorHelper> helper_;
diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp
index 26cfa7d0f65a..976d34aaf876 100644
--- a/src/libcamera/camera_sensor/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor/camera_sensor.cpp
@@ -22,6 +22,7 @@
#include "libcamera/internal/bayer_format.h"
#include "libcamera/internal/camera_lens.h"
#include "libcamera/internal/camera_sensor_properties.h"
+#include "libcamera/internal/control_ids.h"
#include "libcamera/internal/formats.h"
#include "libcamera/internal/sysfs.h"
@@ -180,6 +181,10 @@ int CameraSensor::init()
return -ENODEV;
}
+ ret = updateControls();
+ if (ret)
+ return ret;
+
ret = discoverAncillaryDevices();
if (ret)
return ret;
@@ -455,6 +460,84 @@ int CameraSensor::initProperties()
return 0;
}
+int CameraSensor::updateControls()
+{
+ if (!bayerFormat_)
+ return 0;
+
+ ControlInfoMap::Map controlsMap;
+
+ /* The subdev driver has been validate already, the controls are there! */
+ ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,
+ V4L2_CID_HBLANK });
+ uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();
+ uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get<int32_t>();
+
+ /* Assume the sensor has a single source pad #0. */
+ V4L2SubdeviceFormat subdevFormat;
+ subdev_->getFormat(0, &subdevFormat);
+
+ const ControlInfoMap &subdevControlsInfo = subdev_->controls();
+
+ /*
+ * Compute controls::ExposureTime limits by using line length and pixel
+ * rate converted to microseconds. Use the V4L2_CID_EXPOSURE control to
+ * get exposure min, max and default and convert it from lines to
+ * microseconds.
+ */
+ uint32_t lineLength = subdevFormat.size.width + hblank;
+ double lineDuration = lineLength / (pixelRate / 1000000.0F);
+ const ControlInfo &v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE);
+ int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;
+ int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;
+ int32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;
+
+ controlsMap[&controls::internal::ExposureTime] =
+ ControlInfo(minExposure, maxExposure, defExposure);
+
+ /*
+ * Compute the frame duration limits.
+ *
+ * The frame length is computed assuming a fixed line length combined
+ * with the vertical frame sizes.
+ */
+ const ControlInfo &v4l2VBlank = subdevControlsInfo.at(V4L2_CID_VBLANK);
+ std::array<uint32_t, 3> frameHeights{
+ v4l2VBlank.min().get<int32_t>() + subdevFormat.size.height,
+ v4l2VBlank.max().get<int32_t>() + subdevFormat.size.height,
+ v4l2VBlank.def().get<int32_t>() + subdevFormat.size.height,
+ };
+
+ std::array<int64_t, 3> frameDurations;
+ for (unsigned int i = 0; i < frameHeights.size(); ++i) {
+ uint64_t frameSize = lineLength * frameHeights[i];
+ frameDurations[i] = frameSize / (pixelRate / 1000000.0F);
+ }
+
+ controlsMap[&controls::internal::FrameDuration] =
+ ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]);
+
+ /*
+ * Analogue gain values.
+ *
+ * Translate the V4L2 analogue gain, expressed in sensor-specific
+ * gain codes, and translate them to analogue gain values.
+ *
+ * \todo: CameraSensorHelper returns a double; there's no ControlValue
+ * overload for the double type.
+ */
+ const ControlInfo &v4l2AGain = subdevControlsInfo.at(V4L2_CID_ANALOGUE_GAIN);
+ controlsMap[&controls::internal::AnalogueGain] =
+ ControlInfo(static_cast<float>(helper_->gain(v4l2AGain.min().get<int32_t>())),
+ static_cast<float>(helper_->gain(v4l2AGain.max().get<int32_t>())),
+ static_cast<float>(helper_->gain(v4l2AGain.def().get<int32_t>())));
+
+ controls_ = ControlInfoMap(std::move(controlsMap),
+ controls::internal::controls);
+
+ return 0;
+}
+
/**
* \brief Check for and initialise any ancillary devices
*
@@ -815,6 +898,12 @@ int CameraSensor::setV4L2Controls(ControlList *ctrls)
* \return The list of camera sensor properties
*/
+/**
+ * \fn CameraSensor::controls()
+ * \brief Retrieve the map of the camera sensor controls limits
+ * \return The map of camera sensor control information
+ */
+
/**
* \brief Assemble and return the camera sensor info
* \param[out] info The camera sensor info
@@ -910,6 +999,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
void CameraSensor::updateControlInfo()
{
subdev_->updateControlInfo();
+ updateControls();
}
/**
--
2.36.1
More information about the libcamera-devel
mailing list