[libcamera-devel,v3,19/23] ipa: ipu3: Rework IPAIPU3::processStatsBuffer()
diff mbox series

Message ID 20220630133902.321099-20-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
Before removing V4L2 controls from the IPAIPU3::processStatsBuffer()
interface, rationalize the existing code a bit.

1) we have a context_.configuration which collects the per-capture
   session configuration data. At the same time the sensor and lens
   controls info are kept in class member variables.

   Move all per-capture session parameters to context_.configuration.

2) IPAIPU3::setControls() operates on the active state, which is
   implicitly retrieved from the global context. Pass it explicitly
   to make it clear.

3) Now that we have the full IPACameraSensorInfo in the current context
   remove vblank from IPASessionConfiguration::sensor as it can be
   retrieved from IPASessionConfiguration::sensor.info.

4) Rationalize the code of IPAIPU3::processStatsBuffer() to organize it
   in a logical flow of operations:
   - Update the per-frame context with the sensor's controls values
   - Map the stats buffer
   - Run algorithms with the per-frame context and stats
   - setControls() using the active state as computed by algorithms
   - Populate the metadata buffer

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 src/ipa/ipu3/ipa_context.cpp | 14 ++++++--
 src/ipa/ipu3/ipa_context.h   |  9 ++++-
 src/ipa/ipu3/ipu3.cpp        | 68 +++++++++++++++++++-----------------
 3 files changed, 55 insertions(+), 36 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp
index 06fdf2a1efc7..f09d061e2d19 100644
--- a/src/ipa/ipu3/ipa_context.cpp
+++ b/src/ipa/ipu3/ipa_context.cpp
@@ -126,8 +126,18 @@  namespace libcamera::ipa::ipu3 {
  * \var IPASessionConfiguration::sensor.lineDuration
  * \brief Line duration in microseconds
  *
- * \var IPASessionConfiguration::sensor.vBlank
- * \brief The vertical blanking expressed in number of lines
+ * \var IPASessionConfiguration::sensor.info
+ * \brief The IPACameraSensorInfo valid for the session
+ *
+ * \var IPASessionConfiguration::sensor.controls
+ * \brief The ControlInfoMap of camera sensor control limits valid for the
+ * session
+ *
+ * \var IPASessionConfiguration::lens
+ * \brief Lens-specific configuration of the IPA
+ *
+ * \var IPASessionConfiguration::lens.controls
+ * \brief The ControlInfoMap of lens control limits valid for the session
  */
 
 /**
diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h
index a5b878ab7792..35baa17e8708 100644
--- a/src/ipa/ipu3/ipa_context.h
+++ b/src/ipa/ipu3/ipa_context.h
@@ -17,6 +17,8 @@ 
 #include <libcamera/controls.h>
 #include <libcamera/geometry.h>
 
+#include <libcamera/ipa/ipu3_ipa_interface.h>
+
 namespace libcamera {
 
 namespace ipa::ipu3 {
@@ -43,9 +45,14 @@  struct IPASessionConfiguration {
 	} agc;
 
 	struct {
-		int32_t vBlank;
 		utils::Duration lineDuration;
+		ControlInfoMap controls;
+		IPACameraSensorInfo info;
 	} sensor;
+
+	struct {
+		ControlInfoMap controls;
+	} lens;
 };
 
 struct IPAActiveState {
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index eb97c8be5431..f2e28c06a2c2 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -152,16 +152,11 @@  private:
 
 	bool validateSensorControls(const ControlInfoMap &sensorControls);
 
-	void setControls(unsigned int frame);
+	void setControls(unsigned int frame, const IPAActiveState &state);
 	void calculateBdsGrid(const Size &bdsOutputSize);
 
 	std::map<unsigned int, MappedFrameBuffer> buffers_;
 
-	ControlInfoMap sensorCtrls_;
-	ControlInfoMap lensCtrls_;
-
-	IPACameraSensorInfo sensorInfo_;
-
 	/* Interface to the Camera Helper */
 	std::unique_ptr<CameraSensorHelper> camHelper_;
 
@@ -179,7 +174,6 @@  private:
 void IPAIPU3::updateSessionConfiguration(const IPAConfigInfo &info)
 {
 	const IPACameraSensorInfo &sensorInfo = info.sensorInfo;
-	context_.configuration.sensor.vBlank = sensorInfo.vblank;
 	context_.configuration.sensor.lineDuration = sensorInfo.lineLength * 1.0s
 						   / sensorInfo.pixelRate;
 
@@ -199,6 +193,11 @@  void IPAIPU3::updateSessionConfiguration(const IPAConfigInfo &info)
 	const ControlInfo &gain = sensorControls.at(&controls::internal::AnalogueGain);
 	context_.configuration.agc.minAnalogueGain = gain.min().get<float>();
 	context_.configuration.agc.maxAnalogueGain = gain.max().get<float>();
+
+	/* Store the sensor and lens configuration in the current session. */
+	context_.configuration.sensor.info = info.sensorInfo;
+	context_.configuration.sensor.controls = info.sensorControls;
+	context_.configuration.lens.controls = info.lensControls;
 }
 
 /**
@@ -262,7 +261,7 @@  int IPAIPU3::start()
 	 * Set the sensors V4L2 controls before the first frame to ensure that
 	 * we have an expected and known configuration from the start.
 	 */
-	setControls(0);
+	setControls(0, context_.activeState);
 
 	return 0;
 }
@@ -379,10 +378,6 @@  int IPAIPU3::configure(const IPAConfigInfo &configInfo)
 			return ret;
 	}
 
-	sensorInfo_ = configInfo.sensorInfo;
-	lensCtrls_ = configInfo.lensControls;
-	sensorCtrls_ = configInfo.sensorControls;
-
 	return 0;
 }
 
@@ -472,10 +467,10 @@  void IPAIPU3::processStatsBuffer(const uint32_t frame,
 		return;
 	}
 
-	Span<uint8_t> mem = it->second.planes()[0];
-	const ipu3_uapi_stats_3a *stats =
-		reinterpret_cast<ipu3_uapi_stats_3a *>(mem.data());
-
+	/*
+	 * Update the per-frame context storing the sensor exposure and
+	 * gain for later use by algorithms.
+	 */
 	IPAFrameContext &frameContext = context_.frameContexts[frame % kMaxFrameContexts];
 
 	if (frameContext.frame != frame)
@@ -484,23 +479,28 @@  void IPAIPU3::processStatsBuffer(const uint32_t frame,
 	frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
 	frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());
 
-	double lineDuration = context_.configuration.sensor.lineDuration.get<std::micro>();
-	int32_t vBlank = context_.configuration.sensor.vBlank;
-	ControlList ctrls(controls::controls);
+	/* Run algorithms on the statistics and per-frame context. */
+	Span<uint8_t> mem = it->second.planes()[0];
+	const ipu3_uapi_stats_3a *stats = reinterpret_cast<ipu3_uapi_stats_3a *>(mem.data());
 
 	for (auto const &algo : algorithms_)
 		algo->process(context_, &frameContext, stats);
 
-	setControls(frame);
-
-	int64_t frameDuration = (vBlank + sensorInfo_.outputSize.height) * lineDuration;
-	ctrls.set(controls::FrameDuration, frameDuration);
+	/* Set sensor controls using the newly computed values. */
+	setControls(frame, context_.activeState);
 
-	ctrls.set(controls::AnalogueGain, frameContext.sensor.gain);
+	/* Prepare metadata for the frame. */
+	const IPASessionConfiguration &ipaConfig = context_.configuration;
+	const IPACameraSensorInfo &sensorInfo = ipaConfig.sensor.info;
+	double lineDuration = ipaConfig.sensor.lineDuration.get<std::micro>();
+	int64_t frameDuration = (sensorInfo.vblank + sensorInfo.outputSize.height) * lineDuration;
 
-	ctrls.set(controls::ColourTemperature, context_.activeState.awb.temperatureK);
+	ControlList metadata(controls::controls);
 
-	ctrls.set(controls::ExposureTime, frameContext.sensor.exposure * lineDuration);
+	metadata.set(controls::FrameDuration, frameDuration);
+	metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
+	metadata.set(controls::ColourTemperature, context_.activeState.awb.temperatureK);
+	metadata.set(controls::ExposureTime, frameContext.sensor.exposure * lineDuration);
 
 	/*
 	 * \todo The Metadata provides a path to getting extended data
@@ -510,7 +510,7 @@  void IPAIPU3::processStatsBuffer(const uint32_t frame,
 	 * likely want to avoid putting platform specific metadata in.
 	 */
 
-	metadataReady.emit(frame, ctrls);
+	metadataReady.emit(frame, metadata);
 }
 
 /**
@@ -530,22 +530,24 @@  void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls)
 /**
  * \brief Handle sensor controls for a given \a frame number
  * \param[in] frame The frame on which the sensor controls should be set
+ * \param[in] state The IPA active state which contains the control values as
+ * computed by the algorithms
  *
  * Send the desired sensor control values to the pipeline handler to request
  * that they are applied on the camera sensor.
  */
-void IPAIPU3::setControls(unsigned int frame)
+void IPAIPU3::setControls(unsigned int frame, const IPAActiveState &state)
 {
-	int32_t exposure = context_.activeState.agc.exposure;
-	int32_t gain = camHelper_->gainCode(context_.activeState.agc.gain);
+	int32_t exposure = state.agc.exposure;
+	int32_t gain = camHelper_->gainCode(state.agc.gain);
 
-	ControlList ctrls(sensorCtrls_);
+	ControlList ctrls(controls::controls);
 	ctrls.set(V4L2_CID_EXPOSURE, exposure);
 	ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain);
 
-	ControlList lensCtrls(lensCtrls_);
+	ControlList lensCtrls(controls::controls);
 	lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE,
-		      static_cast<int32_t>(context_.activeState.af.focus));
+		      static_cast<int32_t>(state.af.focus));
 
 	setSensorControls.emit(frame, ctrls, lensCtrls);
 }