[libcamera-devel] [PATCH 17/22] ipa: ipu3: Use a IPAFrameContext pointer from the per-frame queue

Jean-Michel Hautbois jeanmichel.hautbois at ideasonboard.com
Mon Nov 8 14:13:45 CET 2021


We have one frame context shared between the algorithms thanks to a
local cached context_ variable in IPAIPU3. Now that we can store the
frame contexts in a queue, implement all the needed functions for that
and convert the frame context to a pointer.

The algorithm are now using the values applied on the frame they are
processing, and not the latest one.

Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois at ideasonboard.com>
---
 src/ipa/ipu3/algorithms/agc.cpp          | 12 ++++----
 src/ipa/ipu3/algorithms/agc.h            |  2 +-
 src/ipa/ipu3/algorithms/awb.cpp          | 14 ++++-----
 src/ipa/ipu3/algorithms/tone_mapping.cpp |  8 ++---
 src/ipa/ipu3/ipa_context.h               |  2 +-
 src/ipa/ipu3/ipu3.cpp                    | 38 +++++++++++++++++++-----
 6 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index 52cf2753..2eee5b6b 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -245,7 +245,7 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain, double curre
  * \param[in] stats The IPU3 statistics and ISP results
  * \param[in] currentYGain The gain calculated on the current brightness level
  */
-double Agc::computeInitialY(IPAFrameContext &frameContext,
+double Agc::computeInitialY(IPAFrameContext *frameContext,
 			    const ipu3_uapi_grid_config &grid,
 			    const ipu3_uapi_stats_3a *stats,
 			    double currentYGain)
@@ -271,9 +271,9 @@ double Agc::computeInitialY(IPAFrameContext &frameContext,
 	 * Estimate the sum of the brightness values, weighted with the gains
 	 * applied on the channels in AWB.
 	 */
-	double Y_sum = redSum * frameContext.awb.gains.red * .299 +
-		       greenSum * frameContext.awb.gains.green * .587 +
-		       blueSum * frameContext.awb.gains.blue * .114;
+	double Y_sum = redSum * frameContext->awb.gains.red * .299 +
+		       greenSum * frameContext->awb.gains.green * .587 +
+		       blueSum * frameContext->awb.gains.blue * .114;
 
 	/* And return the average brightness */
 	return Y_sum / (grid.height * grid.width);
@@ -291,8 +291,8 @@ double Agc::computeInitialY(IPAFrameContext &frameContext,
 void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
 {
 	/* Get the latest exposure and gain applied */
-	uint32_t &exposure = context.frameContext.agc.exposure;
-	double &analogueGain = context.frameContext.agc.gain;
+	uint32_t &exposure = context.frameContext->agc.exposure;
+	double &analogueGain = context.frameContext->agc.gain;
 	measureBrightness(stats, context.configuration.grid.bdsGrid);
 
 	double currentYGain = 1.0;
diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h
index 6f5d71e0..5d6bef9d 100644
--- a/src/ipa/ipu3/algorithms/agc.h
+++ b/src/ipa/ipu3/algorithms/agc.h
@@ -35,7 +35,7 @@ private:
 			       const ipu3_uapi_grid_config &grid);
 	void filterExposure();
 	void computeExposure(uint32_t &exposure, double &gain, double currentYGain);
-	double computeInitialY(IPAFrameContext &frameContext,
+	double computeInitialY(IPAFrameContext *frameContext,
 			       const ipu3_uapi_grid_config &grid,
 			       const ipu3_uapi_stats_3a *stats,
 			       double currentYGain);
diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp
index a4114659..bd55d377 100644
--- a/src/ipa/ipu3/algorithms/awb.cpp
+++ b/src/ipa/ipu3/algorithms/awb.cpp
@@ -382,9 +382,9 @@ void Awb::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
 	 * The results are cached, so if no results were calculated, we set the
 	 * cached values from asyncResults_ here.
 	 */
-	context.frameContext.awb.gains.blue = asyncResults_.blueGain;
-	context.frameContext.awb.gains.green = asyncResults_.greenGain;
-	context.frameContext.awb.gains.red = asyncResults_.redGain;
+	context.frameContext->awb.gains.blue = asyncResults_.blueGain;
+	context.frameContext->awb.gains.green = asyncResults_.greenGain;
+	context.frameContext->awb.gains.red = asyncResults_.redGain;
 }
 
 constexpr uint16_t Awb::threshold(float value)
@@ -432,10 +432,10 @@ void Awb::prepare(IPAContext &context, ipu3_uapi_params *params)
 	params->acc_param.bnr.opt_center_sqr.y_sqr_reset = params->acc_param.bnr.opt_center.y_reset
 							* params->acc_param.bnr.opt_center.y_reset;
 	/* Convert to u3.13 fixed point values */
-	params->acc_param.bnr.wb_gains.gr = 8192 * context.frameContext.awb.gains.green;
-	params->acc_param.bnr.wb_gains.r  = 8192 * context.frameContext.awb.gains.red;
-	params->acc_param.bnr.wb_gains.b  = 8192 * context.frameContext.awb.gains.blue;
-	params->acc_param.bnr.wb_gains.gb = 8192 * context.frameContext.awb.gains.green;
+	params->acc_param.bnr.wb_gains.gr = 8192 * context.frameContext->awb.gains.green;
+	params->acc_param.bnr.wb_gains.r  = 8192 * context.frameContext->awb.gains.red;
+	params->acc_param.bnr.wb_gains.b  = 8192 * context.frameContext->awb.gains.blue;
+	params->acc_param.bnr.wb_gains.gb = 8192 * context.frameContext->awb.gains.green;
 
 	LOG(IPU3Awb, Debug) << "Color temperature estimated: " << asyncResults_.temperatureK;
 
diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp
index 5d74c552..50498f41 100644
--- a/src/ipa/ipu3/algorithms/tone_mapping.cpp
+++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp
@@ -57,7 +57,7 @@ void ToneMapping::prepare([[maybe_unused]] IPAContext &context,
 {
 	/* Copy the calculated LUT into the parameters buffer. */
 	memcpy(params->acc_param.gamma.gc_lut.lut,
-	       context.frameContext.toneMapping.gammaCorrection.lut,
+	       context.frameContext->toneMapping.gammaCorrection.lut,
 	       IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES *
 	       sizeof(params->acc_param.gamma.gc_lut.lut[0]));
 
@@ -84,11 +84,11 @@ void ToneMapping::process(IPAContext &context,
 	 */
 	gamma_ = 1.1;
 
-	if (context.frameContext.toneMapping.gamma == gamma_)
+	if (context.frameContext->toneMapping.gamma == gamma_)
 		return;
 
 	struct ipu3_uapi_gamma_corr_lut &lut =
-		context.frameContext.toneMapping.gammaCorrection;
+		context.frameContext->toneMapping.gammaCorrection;
 
 	for (uint32_t i = 0; i < std::size(lut.lut); i++) {
 		double j = static_cast<double>(i) / (std::size(lut.lut) - 1);
@@ -98,7 +98,7 @@ void ToneMapping::process(IPAContext &context,
 		lut.lut[i] = gamma * 8191;
 	}
 
-	context.frameContext.toneMapping.gamma = gamma_;
+	context.frameContext->toneMapping.gamma = gamma_;
 }
 
 } /* namespace ipa::ipu3::algorithms */
diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h
index ee8f7b55..69780915 100644
--- a/src/ipa/ipu3/ipa_context.h
+++ b/src/ipa/ipu3/ipa_context.h
@@ -57,7 +57,7 @@ struct IPAFrameContext {
 
 struct IPAContext {
 	IPASessionConfiguration configuration;
-	IPAFrameContext frameContext;
+	IPAFrameContext *frameContext;
 };
 
 } /* namespace ipa::ipu3 */
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index 177c5c2f..b60ab7e7 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -522,10 +522,26 @@ void IPAIPU3::unmapBuffers(const std::vector<unsigned int> &ids)
 
 void IPAIPU3::frameStarted([[maybe_unused]] unsigned int frame)
 {
+	/*
+	 * Instantiate a new IPAFrameContext to push to the queue. The lifetime
+	 * of this pointer is indirectly controlled by the
+	 * ActionSetSensorControls event, as this is where we will delete it.
+	 */
+	struct IPAFrameContext *frameContext = new IPAFrameContext;
+	frameContext->frameId = frame;
+	frameContextQueue.push(frameContext);
 }
 
 void IPAIPU3::frameCompleted([[maybe_unused]] unsigned int frame)
 {
+	/*
+	 * Remove the pointer from the queue, it should not be accessed
+	 * anymore and delete it.
+	 */
+	struct IPAFrameContext *frameContext = frameContextQueue.front();
+	ASSERT(frameContext->frameId == frame);
+	frameContextQueue.pop();
+	delete frameContext;
 }
 
 /**
@@ -579,10 +595,6 @@ void IPAIPU3::processEvent(const IPU3Event &event)
 		const ipu3_uapi_stats_3a *stats =
 			reinterpret_cast<ipu3_uapi_stats_3a *>(mem.data());
 
-		/* \todo move those into processControls */
-		context_.frameContext.agc.exposure = event.sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
-		context_.frameContext.agc.gain = camHelper_->gain(event.sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());
-
 		parseStatistics(event.frame, event.frameTimestamp, stats);
 		/*
 		* To save incurring extra IPC calls, we do not send explicit events
@@ -610,9 +622,12 @@ void IPAIPU3::processEvent(const IPU3Event &event)
  */
 void IPAIPU3::processControls([[maybe_unused]] unsigned int frame,
 			      [[maybe_unused]] const ControlList &controls,
-			      [[maybe_unused]] const ControlList &sensorCtrls)
+			      const ControlList &sensorCtrls)
 {
-	/* \todo Start processing for 'frame' based on 'controls'. */
+	struct IPAFrameContext *frameContext = frameContextQueue.back();
+	ASSERT(frameContext->frameId == frame);
+	frameContext->agc.exposure = sensorCtrls.get(V4L2_CID_EXPOSURE).get<int32_t>();
+	frameContext->agc.gain = camHelper_->gain(sensorCtrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());
 }
 
 /**
@@ -636,6 +651,9 @@ void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params)
 	 */
 	params->use = {};
 
+	/* Set the reference to the current frame context */
+	context_.frameContext = frameContextQueue.front();
+
 	for (auto const &algo : algorithms_)
 		algo->prepare(context_, params);
 
@@ -661,6 +679,9 @@ void IPAIPU3::parseStatistics(unsigned int frame,
 {
 	ControlList ctrls(controls::controls);
 
+	/* Set the reference to the current frame context */
+	context_.frameContext = frameContextQueue.front();
+
 	for (auto const &algo : algorithms_)
 		algo->process(context_, stats);
 
@@ -690,8 +711,9 @@ void IPAIPU3::setControls(unsigned int frame)
 	IPU3Action op;
 	op.op = ActionSetSensorControls;
 
-	exposure_ = context_.frameContext.agc.exposure;
-	gain_ = camHelper_->gainCode(context_.frameContext.agc.gain);
+	/* Apply the exposure and gain updated values */
+	exposure_ = context_.frameContext->agc.exposure;
+	gain_ = camHelper_->gainCode(context_.frameContext->agc.gain);
 
 	ControlList ctrls(ctrls_);
 	ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure_));
-- 
2.32.0



More information about the libcamera-devel mailing list