[v3,06/35] ipa: simple: Use libipa CcmAlgorithm
diff mbox series

Message ID 20260706-libipa-algorithms-v3-6-968757b038bb@ideasonboard.com
State Superseded
Headers show
Series
  • ipa: libipa: Introduce libipa algorithms
Related show

Commit Message

Jacopo Mondi July 6, 2026, 8:01 a.m. UTC
From: Kieran Bingham <kieran.bingham@ideasonboard.com>

Now that libipa provides a common CCM algorithm implementation,
replace the custom handling with the common Ccm.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 src/ipa/simple/algorithms/ccm.cpp | 72 ++++++++++++++++++++++-----------------
 src/ipa/simple/algorithms/ccm.h   | 23 ++++++++-----
 src/ipa/simple/ipa_context.h      |  5 +--
 3 files changed, 58 insertions(+), 42 deletions(-)

Comments

Robert Mader July 7, 2026, 11:10 a.m. UTC | #1
On 06.07.26 10:01, Jacopo Mondi wrote:
> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
>
> Now that libipa provides a common CCM algorithm implementation,
> replace the custom handling with the common Ccm.
>
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Tested-by: Robert Mader <robert.mader@collabora.com>
> ---
>   src/ipa/simple/algorithms/ccm.cpp | 72 ++++++++++++++++++++++-----------------
>   src/ipa/simple/algorithms/ccm.h   | 23 ++++++++-----
>   src/ipa/simple/ipa_context.h      |  5 +--
>   3 files changed, 58 insertions(+), 42 deletions(-)
>
> diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp
> index ff37c718c6e4..e0cbd453e32f 100644
> --- a/src/ipa/simple/algorithms/ccm.cpp
> +++ b/src/ipa/simple/algorithms/ccm.cpp
> @@ -8,54 +8,64 @@
>   
>   #include "ccm.h"
>   
> -#include <libcamera/base/log.h>
> -#include <libcamera/base/utils.h>
> -
> -#include <libcamera/control_ids.h>
> -
>   #include "libcamera/internal/matrix.h"
>   
> -namespace {
> -
> -constexpr unsigned int kTemperatureThreshold = 100;
> -
> -}
> -
>   namespace libcamera {
>   
>   namespace ipa::soft::algorithms {
>   
>   LOG_DEFINE_CATEGORY(IPASoftCcm)
>   
> +/**
> + * \copydoc libcamera::ipa::Algorithm::init
> + */
>   int Ccm::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData)
>   {
> -	int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm");
> -	if (ret < 0) {
> -		LOG(IPASoftCcm, Error)
> -			<< "Failed to parse 'ccm' parameter from tuning file.";
> -		return ret;
> -	}
> -
> +	/* Informs the 'adjust' component that CCM is available to apply Saturation */
>   	context.ccmEnabled = true;
>   
> -	return 0;
> +	return ccmAlgo_.init(tuningData, context.ctrlMap);
>   }
>   
> -void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
> -		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
> +/**
> + * \copydoc libcamera::ipa::Algorithm::configure
> + */
> +int Ccm::configure(IPAContext &context,
> +		   [[maybe_unused]] const IPAConfigInfo &configInfo)
>   {
> -	const unsigned int ct = frameContext.awb.temperatureK;
> +	return ccmAlgo_.configure(context.activeState.ccm,
> +				  context.activeState.awb.automatic.temperatureK);
> +}
>   
> -	/* Change CCM only on bigger temperature changes. */
> -	if (!currentCcm_ ||
> -	    utils::abs_diff(ct, lastCt_) >= kTemperatureThreshold) {
> -		currentCcm_ = ccm_.getInterpolated(ct);
> -		lastCt_ = ct;
> -	}
> +/**
> + * \copydoc libcamera::ipa::Algorithm::queueRequest
> + */
> +void Ccm::queueRequest(IPAContext &context,
> +		       [[maybe_unused]] const uint32_t frame,
> +		       IPAFrameContext &frameContext,
> +		       const ControlList &controls)
> +{
> +	/* Nothing to do here, the ccm will be calculated in prepare() */
> +	if (frameContext.awb.autoEnabled)
> +		return;
>   
> +	ccmAlgo_.queueRequest(context.activeState.ccm, frameContext.ccm, controls);
> +}
> +
> +void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
> +		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
> +{
> +	if (frameContext.awb.autoEnabled)
> +		ccmAlgo_.prepare(context.activeState.ccm, frameContext.ccm,
> +				 frame, frameContext.awb.temperatureK);
> +
> +	/*
> +	 * \todo: Split out combined matrix into individual parameters in
> +	 * DebayerParams and perform any pre-multiplication combination in the
> +	 * SoftISP component directly.
> +	 */
>   	context.activeState.combinedMatrix =
> -		currentCcm_.value() * context.activeState.combinedMatrix;
> -	frameContext.ccm = currentCcm_.value();
> +		frameContext.ccm.ccm * context.activeState.combinedMatrix;
>   }
>   
>   void Ccm::process([[maybe_unused]] IPAContext &context,
> @@ -64,7 +74,7 @@ void Ccm::process([[maybe_unused]] IPAContext &context,
>   		  [[maybe_unused]] const SwIspStats *stats,
>   		  ControlList &metadata)
>   {
> -	metadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.data());
> +	ccmAlgo_.process(frameContext.ccm, metadata);
>   }
>   
>   REGISTER_IPA_ALGORITHM(Ccm, "Ccm")
> diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h
> index b20a7da8aa33..0d35347ea583 100644
> --- a/src/ipa/simple/algorithms/ccm.h
> +++ b/src/ipa/simple/algorithms/ccm.h
> @@ -7,13 +7,15 @@
>   
>   #pragma once
>   
> -#include <optional>
> +#include <libcamera/controls.h>
>   
> -#include "libcamera/internal/matrix.h"
> +#include "libcamera/internal/value_node.h"
>   
> -#include <libipa/interpolator.h>
> +#include "libipa/ccm.h"
> +#include "libipa/fixedpoint.h"
>   
>   #include "algorithm.h"
> +#include "ipa_context.h"
>   
>   namespace libcamera {
>   
> @@ -22,10 +24,15 @@ namespace ipa::soft::algorithms {
>   class Ccm : public Algorithm
>   {
>   public:
> -	Ccm() = default;
> -	~Ccm() = default;
> -
>   	int init(IPAContext &context, const ValueNode &tuningData) override;
> +
> +	int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
> +
> +	void queueRequest(IPAContext &context,
> +			  [[maybe_unused]] const uint32_t frame,
> +			  IPAFrameContext &frameContext,
> +			  const ControlList &controls) override;
> +
>   	void prepare(IPAContext &context,
>   		     const uint32_t frame,
>   		     IPAFrameContext &frameContext,
> @@ -36,9 +43,7 @@ public:
>   		     ControlList &metadata) override;
>   
>   private:
> -	unsigned int lastCt_;
> -	Interpolator<Matrix<float, 3, 3>> ccm_;
> -	std::optional<Matrix<float, 3, 3>> currentCcm_;
> +	CcmAlgorithm<Q<4, 16>> ccmAlgo_;
>   };
>   
>   } /* namespace ipa::soft::algorithms */
> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
> index 29643a655ce1..ff312ae8f4e7 100644
> --- a/src/ipa/simple/ipa_context.h
> +++ b/src/ipa/simple/ipa_context.h
> @@ -17,6 +17,7 @@
>   #include "libcamera/internal/vector.h"
>   
>   #include <libipa/awb.h>
> +#include <libipa/ccm.h>
>   #include <libipa/fc_queue.h>
>   
>   #include "core_ipa_interface.h"
> @@ -38,6 +39,7 @@ struct IPASessionConfiguration {
>   
>   struct IPAActiveState {
>   	ipa::awb::ActiveState awb;
> +	ipa::ccm::ActiveState ccm;
>   
>   	struct {
>   		int32_t exposure;
> @@ -63,8 +65,7 @@ struct IPAActiveState {
>   
>   struct IPAFrameContext : public FrameContext {
>   	ipa::awb::FrameContext awb;
> -
> -	Matrix<float, 3, 3> ccm;
> +	ipa::ccm::FrameContext ccm;
>   
>   	struct {
>   		int32_t exposure;
>

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp
index ff37c718c6e4..e0cbd453e32f 100644
--- a/src/ipa/simple/algorithms/ccm.cpp
+++ b/src/ipa/simple/algorithms/ccm.cpp
@@ -8,54 +8,64 @@ 
 
 #include "ccm.h"
 
-#include <libcamera/base/log.h>
-#include <libcamera/base/utils.h>
-
-#include <libcamera/control_ids.h>
-
 #include "libcamera/internal/matrix.h"
 
-namespace {
-
-constexpr unsigned int kTemperatureThreshold = 100;
-
-}
-
 namespace libcamera {
 
 namespace ipa::soft::algorithms {
 
 LOG_DEFINE_CATEGORY(IPASoftCcm)
 
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
 int Ccm::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData)
 {
-	int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm");
-	if (ret < 0) {
-		LOG(IPASoftCcm, Error)
-			<< "Failed to parse 'ccm' parameter from tuning file.";
-		return ret;
-	}
-
+	/* Informs the 'adjust' component that CCM is available to apply Saturation */
 	context.ccmEnabled = true;
 
-	return 0;
+	return ccmAlgo_.init(tuningData, context.ctrlMap);
 }
 
-void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
-		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int Ccm::configure(IPAContext &context,
+		   [[maybe_unused]] const IPAConfigInfo &configInfo)
 {
-	const unsigned int ct = frameContext.awb.temperatureK;
+	return ccmAlgo_.configure(context.activeState.ccm,
+				  context.activeState.awb.automatic.temperatureK);
+}
 
-	/* Change CCM only on bigger temperature changes. */
-	if (!currentCcm_ ||
-	    utils::abs_diff(ct, lastCt_) >= kTemperatureThreshold) {
-		currentCcm_ = ccm_.getInterpolated(ct);
-		lastCt_ = ct;
-	}
+/**
+ * \copydoc libcamera::ipa::Algorithm::queueRequest
+ */
+void Ccm::queueRequest(IPAContext &context,
+		       [[maybe_unused]] const uint32_t frame,
+		       IPAFrameContext &frameContext,
+		       const ControlList &controls)
+{
+	/* Nothing to do here, the ccm will be calculated in prepare() */
+	if (frameContext.awb.autoEnabled)
+		return;
 
+	ccmAlgo_.queueRequest(context.activeState.ccm, frameContext.ccm, controls);
+}
+
+void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
+{
+	if (frameContext.awb.autoEnabled)
+		ccmAlgo_.prepare(context.activeState.ccm, frameContext.ccm,
+				 frame, frameContext.awb.temperatureK);
+
+	/*
+	 * \todo: Split out combined matrix into individual parameters in
+	 * DebayerParams and perform any pre-multiplication combination in the
+	 * SoftISP component directly.
+	 */
 	context.activeState.combinedMatrix =
-		currentCcm_.value() * context.activeState.combinedMatrix;
-	frameContext.ccm = currentCcm_.value();
+		frameContext.ccm.ccm * context.activeState.combinedMatrix;
 }
 
 void Ccm::process([[maybe_unused]] IPAContext &context,
@@ -64,7 +74,7 @@  void Ccm::process([[maybe_unused]] IPAContext &context,
 		  [[maybe_unused]] const SwIspStats *stats,
 		  ControlList &metadata)
 {
-	metadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.data());
+	ccmAlgo_.process(frameContext.ccm, metadata);
 }
 
 REGISTER_IPA_ALGORITHM(Ccm, "Ccm")
diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h
index b20a7da8aa33..0d35347ea583 100644
--- a/src/ipa/simple/algorithms/ccm.h
+++ b/src/ipa/simple/algorithms/ccm.h
@@ -7,13 +7,15 @@ 
 
 #pragma once
 
-#include <optional>
+#include <libcamera/controls.h>
 
-#include "libcamera/internal/matrix.h"
+#include "libcamera/internal/value_node.h"
 
-#include <libipa/interpolator.h>
+#include "libipa/ccm.h"
+#include "libipa/fixedpoint.h"
 
 #include "algorithm.h"
+#include "ipa_context.h"
 
 namespace libcamera {
 
@@ -22,10 +24,15 @@  namespace ipa::soft::algorithms {
 class Ccm : public Algorithm
 {
 public:
-	Ccm() = default;
-	~Ccm() = default;
-
 	int init(IPAContext &context, const ValueNode &tuningData) override;
+
+	int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
+
+	void queueRequest(IPAContext &context,
+			  [[maybe_unused]] const uint32_t frame,
+			  IPAFrameContext &frameContext,
+			  const ControlList &controls) override;
+
 	void prepare(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
@@ -36,9 +43,7 @@  public:
 		     ControlList &metadata) override;
 
 private:
-	unsigned int lastCt_;
-	Interpolator<Matrix<float, 3, 3>> ccm_;
-	std::optional<Matrix<float, 3, 3>> currentCcm_;
+	CcmAlgorithm<Q<4, 16>> ccmAlgo_;
 };
 
 } /* namespace ipa::soft::algorithms */
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 29643a655ce1..ff312ae8f4e7 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -17,6 +17,7 @@ 
 #include "libcamera/internal/vector.h"
 
 #include <libipa/awb.h>
+#include <libipa/ccm.h>
 #include <libipa/fc_queue.h>
 
 #include "core_ipa_interface.h"
@@ -38,6 +39,7 @@  struct IPASessionConfiguration {
 
 struct IPAActiveState {
 	ipa::awb::ActiveState awb;
+	ipa::ccm::ActiveState ccm;
 
 	struct {
 		int32_t exposure;
@@ -63,8 +65,7 @@  struct IPAActiveState {
 
 struct IPAFrameContext : public FrameContext {
 	ipa::awb::FrameContext awb;
-
-	Matrix<float, 3, 3> ccm;
+	ipa::ccm::FrameContext ccm;
 
 	struct {
 		int32_t exposure;