[libcamera-devel] [PATCH 3/3] ipa: ipu3: af: AfMode and LensPosition control implementation

Kate Hsuan hpa at redhat.com
Fri Sep 16 12:37:13 CEST 2022


AfMode controls include manual, auto, and continuous modes. For auto
and continuous modes, both of the algorithms try to keep the image
focused. The difference between them is that continuous mode has higher
sensitivity to the change of image variance than auto mode. So, the AF
is frequently triggered in continuous mode. The user-defined lens
position can only be set in manual mode.

Signed-off-by: Kate Hsuan <hpa at redhat.com>
---
 src/ipa/ipu3/algorithms/af.cpp | 106 ++++++++++++++++++++++++++++-----
 src/ipa/ipu3/algorithms/af.h   |  15 +++++
 2 files changed, 105 insertions(+), 16 deletions(-)

diff --git a/src/ipa/ipu3/algorithms/af.cpp b/src/ipa/ipu3/algorithms/af.cpp
index 4835a034..c57d3e18 100644
--- a/src/ipa/ipu3/algorithms/af.cpp
+++ b/src/ipa/ipu3/algorithms/af.cpp
@@ -21,6 +21,8 @@
 
 #include <libcamera/base/log.h>
 
+#include <libcamera/control_ids.h>
+
 #include <libcamera/ipa/core_ipa_interface.h>
 
 #include "libipa/histogram.h"
@@ -109,7 +111,8 @@ static struct ipu3_uapi_af_filter_config afFilterConfigDefault = {
  */
 Af::Af()
 	: focus_(0), bestFocus_(0), currentVariance_(0.0), previousVariance_(0.0),
-	  coarseCompleted_(false), fineCompleted_(false)
+	  coarseCompleted_(false), fineCompleted_(false), maxChange_(kMaxChange),
+	  afMode_(controls::AfModeAuto)
 {
 }
 
@@ -194,6 +197,69 @@ int Af::configure(IPAContext &context, const IPAConfigInfo &configInfo)
 	return 0;
 }
 
+/**
+ * \brief AF controls handler
+ *
+ * Put the control parameter to the corresponding variables when receiving the controls
+ * from the user.
+ * \param[in] context The shared IPA context
+ * \param[in] frame Frame number
+ * \param[in] controls control list of the request
+ */
+void Af::queueRequest([[maybe_unused]] IPAContext &context,
+		      [[maybe_unused]] const uint32_t frame,
+		      const ControlList &controls)
+{
+	for (auto const &ctrl : controls) {
+		unsigned int ctrlEnum = ctrl.first;
+		const ControlValue &ctrlValue = ctrl.second;
+
+		switch (ctrlEnum) {
+		case controls::AF_MODE:
+			afModeSet(ctrlValue.get<int32_t>());
+			break;
+		case controls::LENS_POSITION:
+			lensPosition_ = ctrlValue.get<float>();
+		}
+	}
+}
+
+/**
+ * \brief AF Mode set
+ *
+ * Set AF mode, including manual, auto, and continuous.
+ *
+ * \param[in] AF operation mode 0, 1, 2 are manual, auto, and continuous, respectively.
+ */
+
+void Af::afModeSet(uint32_t mode)
+{
+	switch (mode) {
+	case controls::AfModeManual:
+	case controls::AfModeAuto:
+		afMode_ = mode;
+		break;
+	case controls::AfModeContinuous:
+		afMode_ = mode;
+		maxChange_ = 0.05;
+		break;
+	default:
+		afMode_ = controls::AfModeAuto;
+	}
+
+	LOG(IPU3Af, Debug) << "AfMode set " << mode;
+}
+
+/**
+ * \brief Set lens position
+ *
+ * Set user-defined lens position to the focus steps.
+ */
+void Af::afLensPositionSet(IPAContext &context)
+{
+	context.activeState.af.focus = kMaxFocusSteps * lensPosition_;
+}
+
 /**
  * \brief AF coarse scan
  *
@@ -397,7 +463,7 @@ bool Af::afIsOutOfFocus(IPAContext context)
 			   << " Current VCM step: "
 			   << context.activeState.af.focus;
 
-	if (var_ratio > kMaxChange)
+	if (var_ratio > maxChange_)
 		return true;
 	else
 		return false;
@@ -432,21 +498,29 @@ void Af::process(IPAContext &context, [[maybe_unused]] IPAFrameContext *frameCon
 	Span<const y_table_item_t> y_items(reinterpret_cast<const y_table_item_t *>(&stats->af_raw_buffer.y_table),
 					   afRawBufferLen);
 
-	/*
-	 * Calculate the mean and the variance of AF statistics for a given grid.
-	 * For coarse: y1 are used.
-	 * For fine: y2 results are used.
-	 */
-	currentVariance_ = afEstimateVariance(y_items, !coarseCompleted_);
+	switch (afMode_) {
+	case controls::AfModeManual:
+		afLensPositionSet(context);
+		break;
+	case controls::AfModeContinuous:
+	case controls::AfModeAuto:
+	default:
+		/*
+		 * Calculate the mean and the variance of AF statistics for a given grid.
+		 * For coarse: y1 are used.
+		 * For fine: y2 results are used.
+		 */
+		currentVariance_ = afEstimateVariance(y_items, !coarseCompleted_);
 
-	if (!context.activeState.af.stable) {
-		afCoarseScan(context);
-		afFineScan(context);
-	} else {
-		if (afIsOutOfFocus(context))
-			afReset(context);
-		else
-			afIgnoreFrameReset();
+		if (!context.activeState.af.stable) {
+			afCoarseScan(context);
+			afFineScan(context);
+		} else {
+			if (afIsOutOfFocus(context))
+				afReset(context);
+			else
+				afIgnoreFrameReset();
+		}
 	}
 }
 
diff --git a/src/ipa/ipu3/algorithms/af.h b/src/ipa/ipu3/algorithms/af.h
index ccf015f3..77bab2a7 100644
--- a/src/ipa/ipu3/algorithms/af.h
+++ b/src/ipa/ipu3/algorithms/af.h
@@ -26,6 +26,7 @@ class Af : public Algorithm
 		uint16_t y1_avg;
 		uint16_t y2_avg;
 	} y_table_item_t;
+
 public:
 	Af();
 	~Af() = default;
@@ -34,6 +35,9 @@ public:
 	int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
 	void process(IPAContext &context, IPAFrameContext *frameContext,
 		     const ipu3_uapi_stats_3a *stats) override;
+	void queueRequest([[maybe_unused]] IPAContext &context,
+			  [[maybe_unused]] const uint32_t frame,
+			  [[maybe_unused]] const ControlList &controls) override;
 
 private:
 	void afCoarseScan(IPAContext &context);
@@ -46,6 +50,11 @@ private:
 
 	bool afIsOutOfFocus(IPAContext context);
 
+	void afModeSet(uint32_t mode);
+	void afModeGet();
+
+	void afLensPositionSet(IPAContext &context);
+
 	/* VCM step configuration. It is the current setting of the VCM step. */
 	uint32_t focus_;
 	/* The best VCM step. It is a local optimum VCM step during scanning. */
@@ -62,6 +71,12 @@ private:
 	bool coarseCompleted_;
 	/* If the fine scan completes, it is set to true. */
 	bool fineCompleted_;
+	/* Max focus change ratio to determine */
+	double maxChange_;
+	/* Relative lens position in percentage. */
+	double lensPosition_;
+	/* Af operation mode. */
+	uint32_t afMode_;
 };
 
 } /* namespace ipa::ipu3::algorithms */
-- 
2.37.3



More information about the libcamera-devel mailing list