[v3,39/41] ipa: rkisp1: Handle frame jumps in calls to computeParams()
diff mbox series

Message ID 20260914140309.3354666-40-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • rkisp1: pipeline rework for PFC
Related show

Commit Message

Stefan Klug Sept. 14, 2026, 2:02 p.m. UTC
In the situation of a parameter buffer underrun (due to some external
event) the calls to computeParams will jump frames. It must be
guaranteed that every change in the jumped frames still gets applied to
the isp. To do that, call computeParams() on every missed frame or issue
a full reinitialization if more than 3 frames were lost. The number of 3
is arbitrarily chosen but fits to the subjective observation that we
either lose 1-2 frames due to signal issues or way more than 3 because
something else blocked the system.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
---
 src/ipa/rkisp1/rkisp1.cpp | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index ca3b0d31d9f6..7147de4a0f02 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -86,6 +86,7 @@  private:
 	/* Local parameter storage */
 	struct IPAContext context_;
 	bool initializeParams_;
+	uint32_t lastParamsComputed_;
 };
 
 namespace {
@@ -220,6 +221,7 @@  void IPARkISP1::start(const ControlList &controls, const uint32_t paramBufferId,
 	IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(0, controls);
 	ASSERT(frameContext);
 	initializeParams_ = true;
+	lastParamsComputed_ = 0;
 
 	if (paramBufferId != 0)
 		result->paramBufferBytesUsed = computeParamsInternal(*frameContext,
@@ -332,10 +334,37 @@  uint32_t IPARkISP1::computeParamsInternal(IPAFrameContext &frameContext, const u
 			    mappedBuffers_.at(bufferId).planes()[0]);
 
 	unsigned int frame = frameContext.frame();
+
+	/*
+	 * In the corner case that the previous params buffer was not computed
+	 * (due to resynchronization), there is a risk that a change was missed
+	 * and not sent to the kernel. This can have quite negative side
+	 * effects, if e.g. a lsc table was not written. To mitigate that, run
+	 * over all missed frames and apply them in turn or do a full reinit if
+	 * too many frames were missed.
+	 */
+	while (!initializeParams_ && lastParamsComputed_ + 1 < frame) {
+		lastParamsComputed_++;
+		IPAFrameContext *fc = context_.frameContexts.getOrInitContext(lastParamsComputed_);
+		if (!fc || frame - lastParamsComputed_ > 3) {
+			LOG(IPARkISP1, Warning)
+				<< "Collect missed params with full reinit";
+			initializeParams_ = true;
+			break;
+		}
+
+		LOG(IPARkISP1, Warning) << "Collect missed params for frame: "
+					<< lastParamsComputed_;
+		for (const auto &algo : algorithms())
+			algo->prepare(context_, lastParamsComputed_, *fc,
+				      &params, false);
+	}
+
 	for (const auto &algo : algorithms())
 		algo->prepare(context_, frame, frameContext,
 			      &params, initializeParams_);
 
+	lastParamsComputed_ = std::max(frame, lastParamsComputed_);
 	initializeParams_ = false;
 
 	return params.bytesused();
@@ -376,6 +405,11 @@  void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId,
 		return;
 	}
 
+	if (frame > lastParamsComputed_) {
+		LOG(IPARkISP1, Debug) << "Process stats on frame " << frame
+				      << " without prior compute params";
+	}
+
 	/*
 	 * In raw capture mode, the ISP is bypassed and no statistics buffer is
 	 * provided.