[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