[libcamera-devel,v3,14/23] libcamera: camera_sensor: Translate libcamera/V4L2 controls
diff mbox series

Message ID 20220630133902.321099-15-jacopo@jmondi.org
State Not Applicable, archived
Headers show
Series
  • Internal controls, sensor delays and IPA rework
Related show

Commit Message

Jacopo Mondi June 30, 2022, 1:38 p.m. UTC
In the process of moving the CameraSensor class control interface
to use libcamera::internal controls modify the
CameraSensor::pushControls() and CameraSensor::getControls() to
use lists of libcamera controls and translate to and from V4L2 controls
to interface with DelayedControls, which will actually take care of
applying controls to the V4L2 subdevice.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 src/libcamera/camera_sensor/camera_sensor.cpp | 67 ++++++++++++++++++-
 1 file changed, 65 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp
index cc4cbd4ad509..02810c7c5ad0 100644
--- a/src/libcamera/camera_sensor/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor/camera_sensor.cpp
@@ -1038,19 +1038,82 @@  void CameraSensor::frameStart(uint32_t sequence)
 /**
  * \brief Push a new set of controls to the CameraSensor
  * \param[in] ctrls The list of controls to push to the sensor
+ *
+ * \a ctrls contains a list of libcamera::controls::internal controls
  */
 void CameraSensor::pushControls(const ControlList &ctrls)
 {
-	delayedCtrls_->push(ctrls);
+	ControlList v4l2Ctrls(subdev_->controls());
+
+	/*
+	 * DelayedControls applies V4L2 controls for us to the subdevice.
+	 * Translate here between libcamera controls and V4L2 controls.
+	 *
+	 * The currently supported controls are V4L2_CID_VBLANK,
+	 * V4L2_CID_EXPOSURE and V4L2_CID_ANALOGUE_GAIN.
+	 */
+
+	if (ctrls.contains(controls::internal::AnalogueGain)) {
+		float gain = ctrls.get(controls::internal::AnalogueGain);
+		int32_t gainCode = helper_->gainCode(gain);
+
+		v4l2Ctrls.set(V4L2_CID_ANALOGUE_GAIN, ControlValue(gainCode));
+	}
+
+	if (ctrls.contains(controls::internal::ExposureTime)) {
+		uint32_t exposureTime = ctrls.get(controls::internal::ExposureTime);
+		int32_t exposure = exposureTime / config_.lineDuration;
+
+		v4l2Ctrls.set(V4L2_CID_EXPOSURE, ControlValue(exposure));
+	}
+
+	if (ctrls.contains(controls::internal::FrameDuration)) {
+		uint64_t duration = ctrls.get(controls::internal::FrameDuration);
+		uint32_t frameSize = duration / (1000000.0F / config_.pixelRate);
+		uint32_t lineLength = config_.outputFormat.size.width + config_.hblank;
+		int32_t vblank = frameSize / lineLength - config_.outputFormat.size.height;
+
+		v4l2Ctrls.set(V4L2_CID_VBLANK, vblank);
+	}
+
+	delayedCtrls_->push(v4l2Ctrls);
 }
 
 /**
  * \brief Get the list of controls applied at frame \a sequence
  * \param[in] sequence The frame sequence number
+ *
+ * The returned controls list contains libcamera::controls::internal controls
  */
 ControlList CameraSensor::getControls(uint32_t sequence)
 {
-	return delayedCtrls_->get(sequence);
+	ControlList ctrls(controls::internal::controls);
+	ControlList v4l2Ctrls = delayedCtrls_->get(sequence);
+
+	if (v4l2Ctrls.contains(V4L2_CID_ANALOGUE_GAIN)) {
+		uint32_t gainCode = v4l2Ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
+		float gain = static_cast<float>(helper_->gain(gainCode));
+
+		ctrls.set(controls::internal::AnalogueGain, gain);
+	}
+
+	if (v4l2Ctrls.contains(V4L2_CID_EXPOSURE)) {
+		uint32_t exposure = v4l2Ctrls.get(V4L2_CID_EXPOSURE).get<int32_t>();
+		uint32_t exposureTime = exposure * config_.lineDuration;
+
+		ctrls.set(controls::internal::ExposureTime, exposureTime);
+	}
+
+	if (v4l2Ctrls.contains(V4L2_CID_VBLANK)) {
+		uint32_t vblank = v4l2Ctrls.get(V4L2_CID_VBLANK).get<int32_t>();
+		uint32_t frameSize = (config_.outputFormat.size.width + config_.hblank)
+				   * (config_.outputFormat.size.height + vblank);
+		uint64_t duration = frameSize / (config_.pixelRate / 1000000.0F);
+
+		ctrls.set(controls::internal::FrameDuration, duration);
+	}
+
+	return ctrls;
 }
 
 /**