[libcamera-devel] [PATCH v3 13/23] libcamera: camera_sensor: Cache the sensor configuration

Jacopo Mondi jacopo at jmondi.org
Thu Jun 30 15:38:52 CEST 2022


The sensor configuration parameters, which include the output format
the blanking lengths and the current pixel rate, are updated everytime
a new format is set on the sensor.

The sensor configuration parameters will be used in order to
translate libcamera controls in the corresponding V4L2 control values
(and vice-versa).

The same parameters are also used to populate the CameraSensorInfo
to pass it to IPA modules.

In order to avoid re-querying the V4L2 subdevice for the control
values and the output format everytime, cache the current sensor
configuration in a class member field, updated when a new format
is set on the sensor and at initialization time.

As the function that updates the configuration was originally only
meant to update the CameraSensor ControlInfoMap limits, rename it
from updateControls() to updateConfiguration().

Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
 include/libcamera/internal/camera_sensor.h    |  9 ++-
 src/libcamera/camera_sensor/camera_sensor.cpp | 69 +++++++------------
 2 files changed, 32 insertions(+), 46 deletions(-)

diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index a606bc5d1cb5..bb9327646bc1 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -81,6 +81,13 @@ protected:
 private:
 	LIBCAMERA_DISABLE_COPY(CameraSensor)
 
+	struct {
+		V4L2SubdeviceFormat outputFormat;
+		uint64_t pixelRate;
+		uint32_t hblank;
+		double lineDuration;
+	} config_;
+
 	int generateId();
 	int validateSensorDriver();
 	void initVimcDefaultProperties();
@@ -88,7 +95,7 @@ private:
 	void initTestPatternModes();
 	int initProperties();
 	int initDelayedControls();
-	int updateControls();
+	int updateConfiguration();
 	int applyTestPatternMode(controls::draft::TestPatternModeEnum mode);
 	int discoverAncillaryDevices();
 
diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp
index e1770e8fa130..cc4cbd4ad509 100644
--- a/src/libcamera/camera_sensor/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor/camera_sensor.cpp
@@ -181,7 +181,7 @@ int CameraSensor::init()
 		return -ENODEV;
 	}
 
-	ret = updateControls();
+	ret = updateConfiguration();
 	if (ret)
 		return ret;
 
@@ -501,7 +501,7 @@ int CameraSensor::initDelayedControls()
 	return 0;
 }
 
-int CameraSensor::updateControls()
+int CameraSensor::updateConfiguration()
 {
 	if (!bayerFormat_)
 		return 0;
@@ -511,12 +511,11 @@ int CameraSensor::updateControls()
 	/* 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>();
+	config_.pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();
+	config_.hblank = subdevControls.get(V4L2_CID_HBLANK).get<int32_t>();
 
 	/*  Assume the sensor has a single source pad #0. */
-	V4L2SubdeviceFormat subdevFormat;
-	subdev_->getFormat(0, &subdevFormat);
+	subdev_->getFormat(0, &config_.outputFormat);
 
 	const ControlInfoMap &subdevControlsInfo = subdev_->controls();
 
@@ -526,12 +525,14 @@ int CameraSensor::updateControls()
 	 * 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;
+	const Size &outputSize = config_.outputFormat.size;
+	uint32_t lineLength = outputSize.width + config_.hblank;
+	config_.lineDuration = lineLength / (config_.pixelRate / 1000000.0F);
+
+	ControlInfo v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE);
+	int32_t minExposure = v4l2Exposure.min().get<int32_t>() * config_.lineDuration;
+	int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * config_.lineDuration;
+	int32_t defExposure = v4l2Exposure.def().get<int32_t>() * config_.lineDuration;
 
 	controlsMap[&controls::internal::ExposureTime] =
 		ControlInfo(minExposure, maxExposure, defExposure);
@@ -544,15 +545,15 @@ int CameraSensor::updateControls()
 	 */
 	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,
+		v4l2VBlank.min().get<int32_t>() + outputSize.height,
+		v4l2VBlank.max().get<int32_t>() + outputSize.height,
+		v4l2VBlank.def().get<int32_t>() + outputSize.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);
+		frameDurations[i] = frameSize / (config_.pixelRate / 1000000.0F);
 	}
 
 	controlsMap[&controls::internal::FrameDuration] =
@@ -989,6 +990,8 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
 			<< "The analogue crop rectangle has been defaulted to the active area size";
 	}
 
+	const ControlInfo vblank = subdev_->controls().at(V4L2_CID_VBLANK);
+
 	/*
 	 * IPACameraSensorInfo::analogCrop::x and IPACameraSensorInfo::analogCrop::y
 	 * are defined relatively to the active pixel area, while V4L2's
@@ -998,34 +1001,10 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
 	 */
 	info->analogCrop.x -= activeArea_.x;
 	info->analogCrop.y -= activeArea_.y;
-
-	/* The bit depth and image size depend on the currently applied format. */
-	V4L2SubdeviceFormat format{};
-	ret = subdev_->getFormat(pad_, &format);
-	if (ret)
-		return ret;
-	info->bitsPerPixel = format.bitsPerPixel();
-	info->outputSize = format.size;
-
-	/*
-	 * Retrieve the pixel rate, line length and minimum/maximum frame
-	 * duration through V4L2 controls. Support for the V4L2_CID_PIXEL_RATE,
-	 * V4L2_CID_HBLANK and V4L2_CID_VBLANK controls is mandatory.
-	 */
-	ControlList ctrls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,
-						   V4L2_CID_HBLANK,
-						   V4L2_CID_VBLANK });
-	if (ctrls.empty()) {
-		LOG(CameraSensor, Error)
-			<< "Failed to retrieve camera info controls";
-		return -EINVAL;
-	}
-
-	int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();
-	info->lineLength = info->outputSize.width + hblank;
-	info->pixelRate = ctrls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();
-
-	const ControlInfo vblank = ctrls.infoMap()->at(V4L2_CID_VBLANK);
+	info->bitsPerPixel = config_.outputFormat.bitsPerPixel();
+	info->outputSize = config_.outputFormat.size;
+	info->lineLength = info->outputSize.width + config_.hblank;
+	info->pixelRate = config_.pixelRate;
 	info->minFrameLength = info->outputSize.height + vblank.min().get<int32_t>();
 	info->maxFrameLength = info->outputSize.height + vblank.max().get<int32_t>();
 
@@ -1040,7 +1019,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
 void CameraSensor::updateControlInfo()
 {
 	subdev_->updateControlInfo();
-	updateControls();
+	updateConfiguration();
 }
 
 /**
-- 
2.36.1



More information about the libcamera-devel mailing list