[libcamera-devel] [PATCH v2 3/3] ipa: ipu3: Introduce a IPAFrameContext queue

Umang Jain umang.jain at ideasonboard.com
Fri May 6 11:53:07 CEST 2022


Introduce a queue of IPAFrameContext which shall maintain the data
required to track each frame. Currently, it is storing only the
sensor controls values applied for the frame but new structures
can be introduced in IPAFrameContext to extend any frame-related
contexts (either in-processing or new frames being queued).

For example, this patch provides the foundation for the extension
of IPAFrameContext to store incoming request controls.

Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
---
 src/ipa/ipu3/algorithms/agc.cpp |  2 +-
 src/ipa/ipu3/ipa_context.cpp    | 16 ++++++++++++++--
 src/ipa/ipu3/ipa_context.h      |  8 +++++++-
 src/ipa/ipu3/ipu3.cpp           | 31 ++++++++++++++++++++++++++-----
 4 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index fdeec09d..4784af00 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -187,7 +187,7 @@ void Agc::computeExposure(IPAContext &context, double yGain,
 			  double iqMeanGain)
 {
 	const IPASessionConfiguration &configuration = context.configuration;
-	IPAFrameContext &frameContext = context.frameContext;
+	IPAFrameContext &frameContext = context.frameContextQueue.front();
 	/* Get the effective exposure and gain applied on the sensor. */
 	uint32_t exposure = frameContext.sensor.exposure;
 	double analogueGain = frameContext.sensor.gain;
diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp
index 06eb2776..fb48bc9b 100644
--- a/src/ipa/ipu3/ipa_context.cpp
+++ b/src/ipa/ipu3/ipa_context.cpp
@@ -58,8 +58,8 @@ namespace libcamera::ipa::ipu3 {
  * \var IPAContext::configuration
  * \brief The IPA session configuration, immutable during the session
  *
- * \var IPAContext::frameContext
- * \brief The frame context for the frame being processed
+ * \var IPAContext::frameContextQueue
+ * \brief FIFO container of IPAFrameContext for all the frames being queued
  *
  * \var IPAContext::activeState
  * \brief The current state of IPA algorithms
@@ -182,6 +182,15 @@ namespace libcamera::ipa::ipu3 {
  * <linux/intel-ipu3.h> struct ipu3_uapi_gamma_corr_lut for further details.
  */
 
+/**
+ * \brief Construct a IPAFrameContext instance
+ */
+IPAFrameContext::IPAFrameContext(uint32_t frame)
+	: frame(frame)
+{
+	sensor = {};
+}
+
 /**
  * \var IPAFrameContext::sensor
  * \brief Effective sensor values that were applied for the frame
@@ -191,6 +200,9 @@ namespace libcamera::ipa::ipu3 {
  *
  * \var IPAFrameContext::sensor.gain
  * \brief Analogue gain multiplier
+ *
+ * \var IPAFrameContext::frame
+ * \brief The frame number associated with this IPAFrameContext
  */
 
 } /* namespace libcamera::ipa::ipu3 */
diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h
index 8d681131..20cccc97 100644
--- a/src/ipa/ipu3/ipa_context.h
+++ b/src/ipa/ipu3/ipa_context.h
@@ -8,6 +8,8 @@
 
 #pragma once
 
+#include <queue>
+
 #include <linux/intel-ipu3.h>
 
 #include <libcamera/base/utils.h>
@@ -71,17 +73,21 @@ struct IPAActiveState {
 };
 
 struct IPAFrameContext {
+	IPAFrameContext(uint32_t frame);
+
 	struct {
 		uint32_t exposure;
 		double gain;
 	} sensor;
+
+	uint32_t frame;
 };
 
 struct IPAContext {
 	IPASessionConfiguration configuration;
 	IPAActiveState activeState;
 
-	IPAFrameContext frameContext;
+	std::queue<IPAFrameContext> frameContextQueue;
 };
 
 } /* namespace ipa::ipu3 */
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index 268c8f61..1b566f14 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -350,6 +350,8 @@ int IPAIPU3::start()
  */
 void IPAIPU3::stop()
 {
+	while (!context_.frameContextQueue.empty())
+		context_.frameContextQueue.pop();
 }
 
 /**
@@ -458,7 +460,7 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo,
 
 	/* Clean IPAActiveState at each reconfiguration. */
 	context_.activeState = {};
-	context_.frameContext = {};
+	context_.frameContextQueue = {};
 
 	if (!validateSensorControls()) {
 		LOG(IPAIPU3, Error) << "Sensor control validation failed.";
@@ -510,6 +512,13 @@ void IPAIPU3::unmapBuffers(const std::vector<unsigned int> &ids)
 
 void IPAIPU3::frameCompleted([[maybe_unused]] const uint32_t frame)
 {
+	while (!context_.frameContextQueue.empty()) {
+		auto &fc = context_.frameContextQueue.front();
+		if (fc.frame <= frame)
+			context_.frameContextQueue.pop();
+		else
+			break;
+	}
 }
 
 /**
@@ -574,8 +583,18 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame,
 	const ipu3_uapi_stats_3a *stats =
 		reinterpret_cast<ipu3_uapi_stats_3a *>(mem.data());
 
-	context_.frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
-	context_.frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());
+	auto &frameContext = context_.frameContextQueue.front();
+
+	/*
+	 * An assert might be too harsh here. We want to know the cases
+	 * where the front of the queue (implies the current frame in processing,
+	 * diverges from the frame parameter of this function
+	 * \todo Identify those cases - e.g. frame drop?
+	 */
+	ASSERT(context_.frameContextQueue.front().frame == 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.defVBlank;
@@ -590,11 +609,11 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame,
 	int64_t frameDuration = (vBlank + sensorInfo_.outputSize.height) * lineDuration;
 	ctrls.set(controls::FrameDuration, frameDuration);
 
-	ctrls.set(controls::AnalogueGain, context_.frameContext.sensor.gain);
+	ctrls.set(controls::AnalogueGain, frameContext.sensor.gain);
 
 	ctrls.set(controls::ColourTemperature, context_.activeState.awb.temperatureK);
 
-	ctrls.set(controls::ExposureTime, context_.frameContext.sensor.exposure * lineDuration);
+	ctrls.set(controls::ExposureTime, frameContext.sensor.exposure * lineDuration);
 
 	/*
 	 * \todo The Metadata provides a path to getting extended data
@@ -621,6 +640,8 @@ void IPAIPU3::queueRequest([[maybe_unused]] const uint32_t frame,
 			   [[maybe_unused]] const ControlList &controls)
 {
 	/* \todo Start processing for 'frame' based on 'controls'. */
+
+	context_.frameContextQueue.emplace(frame);
 }
 
 /**
-- 
2.31.1



More information about the libcamera-devel mailing list