[v2,3/3] ipa: rkisp1: agc: Plumb mode-selection and frame duration controls
diff mbox series

Message ID 20240509175555.43121-4-paul.elder@ideasonboard.com
State Superseded
Headers show
Series
  • ipa: rkisp1: Improve AGC (plumbing)
Related show

Commit Message

Paul Elder May 9, 2024, 5:55 p.m. UTC
Plumb controls for setting metering mode, exposure mode, constraint
mode, and frame duration limits. Also report them as available controls,
as well as in metadata.

While at it, add the missing #include for tuple, as a std::tie is used.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>

---
Changes in v2:
- add #include <tuple>
- don't overwrite metering/exposure/constraint mode controls to default
  if no control is supplied, and retain the old value instead (same for
  frame duration limits)
---
 src/ipa/rkisp1/algorithms/agc.cpp     | 52 ++++++++++++++++++++++++---
 src/ipa/rkisp1/algorithms/algorithm.h |  2 ++
 src/ipa/rkisp1/ipa_context.h          | 10 ++++--
 src/ipa/rkisp1/rkisp1.cpp             | 10 ++++++
 4 files changed, 67 insertions(+), 7 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index bd9a6a66..74bbda1a 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -10,6 +10,8 @@ 
 #include <algorithm>
 #include <chrono>
 #include <cmath>
+#include <tuple>
+#include <vector>
 
 #include <libcamera/base/log.h>
 #include <libcamera/base/utils.h>
@@ -48,6 +50,7 @@  int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData,
 		return -EINVAL;
 	}
 
+	std::vector<ControlValue> availableMeteringModes;
 	for (const auto &[key, value] : yamlMeteringModes.asDict()) {
 		if (controls::AeMeteringModeNameValueMap.find(key) ==
 		    controls::AeMeteringModeNameValueMap.end()) {
@@ -66,10 +69,12 @@  int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData,
 			return -ENODATA;
 		}
 
-		meteringModes_[controls::AeMeteringModeNameValueMap.at(key)] = weights;
+		int32_t control = controls::AeMeteringModeNameValueMap.at(key);
+		meteringModes_[control] = weights;
+		availableMeteringModes.push_back(control);
 	}
 
-	if (meteringModes_.empty()) {
+	if (availableMeteringModes.empty()) {
 		int32_t meteringModeId = controls::AeMeteringModeNameValueMap.at("MeteringMatrix");
 		std::vector<uint8_t> weights = {
 			1, 1, 1, 1, 1,
@@ -80,8 +85,12 @@  int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData,
 		};
 
 		meteringModes_[meteringModeId] = weights;
+		availableMeteringModes.push_back(meteringModeId);
 	}
 
+	Algorithm::controls_[&controls::AeMeteringMode] =
+		ControlInfo(availableMeteringModes);
+
 	return 0;
 }
 
@@ -142,6 +151,8 @@  int Agc::init(IPAContext &context, const YamlObject &tuningData)
 
 	context.ctrlMap.merge(controls());
 
+	Algorithm::controls_.merge(ControlInfoMap::Map(controls()));
+
 	return 0;
 }
 
@@ -164,6 +175,7 @@  int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
 
 	context.activeState.agc.constraintMode = constraintModes().begin()->first;
 	context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first;
+	context.activeState.agc.meteringMode = meteringModes_.begin()->first;
 
 	/*
 	 * Define the measurement window for AGC as a centered rectangle
@@ -174,7 +186,6 @@  int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
 	context.configuration.agc.measureWindow.h_size = 3 * configInfo.outputSize.width / 4;
 	context.configuration.agc.measureWindow.v_size = 3 * configInfo.outputSize.height / 4;
 
-	/* \todo Run this again when FrameDurationLimits is passed in */
 	setLimits(context.configuration.sensor.minShutterSpeed,
 		  context.configuration.sensor.maxShutterSpeed,
 		  context.configuration.sensor.minAnalogueGain,
@@ -228,6 +239,26 @@  void Agc::queueRequest(IPAContext &context,
 		frameContext.agc.exposure = agc.manual.exposure;
 		frameContext.agc.gain = agc.manual.gain;
 	}
+
+	const auto &meteringMode = controls.get(controls::AeMeteringMode);
+	if (meteringMode)
+		agc.meteringMode = *meteringMode;
+	frameContext.agc.meteringMode = agc.meteringMode;
+
+	const auto &exposureMode = controls.get(controls::AeExposureMode);
+	if (exposureMode)
+		agc.exposureMode = *exposureMode;
+	frameContext.agc.exposureMode = agc.exposureMode;
+
+	const auto &constraintMode = controls.get(controls::AeConstraintMode);
+	if (constraintMode)
+		agc.constraintMode = *constraintMode;
+	frameContext.agc.constraintMode = agc.constraintMode;
+
+	const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits);
+	if (frameDurationLimits)
+		agc.maxShutterSpeed = std::chrono::milliseconds((*frameDurationLimits).back());
+	frameContext.agc.maxShutterSpeed = agc.maxShutterSpeed;
 }
 
 /**
@@ -266,8 +297,7 @@  void Agc::prepare(IPAContext &context, const uint32_t frame,
 		params->meas.hst_config.hist_weight,
 		context.hw->numHistogramWeights
 	};
-	/* \todo Get this from control */
-	std::vector<uint8_t> &modeWeights = meteringModes_.at(controls::MeteringMatrix);
+	std::vector<uint8_t> &modeWeights = meteringModes_.at(frameContext.agc.meteringMode);
 	std::copy(modeWeights.begin(), modeWeights.end(), weights.begin());
 
 	std::stringstream str;
@@ -294,6 +324,7 @@  void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext,
 				     * frameContext.sensor.exposure;
 	metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
 	metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
+	metadata.set(controls::AeEnable, frameContext.agc.autoEnabled);
 
 	/* \todo Use VBlank value calculated from each frame exposure. */
 	uint32_t vTotal = context.configuration.sensor.size.height
@@ -301,6 +332,10 @@  void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext,
 	utils::Duration frameDuration = context.configuration.sensor.lineDuration
 				      * vTotal;
 	metadata.set(controls::FrameDuration, frameDuration.get<std::micro>());
+
+	metadata.set(controls::AeMeteringMode, frameContext.agc.meteringMode);
+	metadata.set(controls::AeExposureMode, frameContext.agc.exposureMode);
+	metadata.set(controls::AeConstraintMode, frameContext.agc.constraintMode);
 }
 
 /**
@@ -375,6 +410,13 @@  void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 		       [](uint32_t x) { return x >> 4; });
 	expMeans_ = { params->ae.exp_mean, context.hw->numAeCells };
 
+	utils::Duration maxShutterSpeed = std::min(context.configuration.sensor.maxShutterSpeed,
+						   frameContext.agc.maxShutterSpeed);
+	setLimits(context.configuration.sensor.minShutterSpeed,
+		  maxShutterSpeed,
+		  context.configuration.sensor.minAnalogueGain,
+		  context.configuration.sensor.maxAnalogueGain);
+
 	/*
 	 * The Agc algorithm needs to know the effective exposure value that was
 	 * applied to the sensor when the statistics were collected.
diff --git a/src/ipa/rkisp1/algorithms/algorithm.h b/src/ipa/rkisp1/algorithms/algorithm.h
index 9454c9a1..c3a002b8 100644
--- a/src/ipa/rkisp1/algorithms/algorithm.h
+++ b/src/ipa/rkisp1/algorithms/algorithm.h
@@ -25,6 +25,8 @@  public:
 
 	bool disabled_;
 	bool supportsRaw_;
+
+	ControlInfoMap::Map controls_;
 };
 
 } /* namespace ipa::rkisp1 */
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index 256b75eb..26c39570 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -68,8 +68,10 @@  struct IPAActiveState {
 		} automatic;
 
 		bool autoEnabled;
-		uint32_t constraintMode;
-		uint32_t exposureMode;
+		int32_t constraintMode;
+		int32_t exposureMode;
+		int32_t meteringMode;
+		utils::Duration maxShutterSpeed;
 	} agc;
 
 	struct {
@@ -111,6 +113,10 @@  struct IPAFrameContext : public FrameContext {
 		uint32_t exposure;
 		double gain;
 		bool autoEnabled;
+		int32_t exposureMode;
+		int32_t constraintMode;
+		int32_t meteringMode;
+		utils::Duration maxShutterSpeed;
 	} agc;
 
 	struct {
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 963cdbab..7716c11b 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -80,6 +80,7 @@  private:
 	std::map<unsigned int, MappedFrameBuffer> mappedBuffers_;
 
 	ControlInfoMap sensorControls_;
+	ControlInfoMap::Map algoControls_;
 
 	/* Interface to the Camera Helper */
 	std::unique_ptr<CameraSensorHelper> camHelper_;
@@ -193,6 +194,14 @@  int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
 	if (ret)
 		return ret;
 
+	for (auto const &a : algorithms()) {
+		Algorithm *algo = static_cast<Algorithm *>(a.get());
+
+		/* \todo Avoid merging duplicate controls */
+		if (!algo->controls_.empty())
+			algoControls_.merge(ControlInfoMap::Map(algo->controls_));
+	}
+
 	/* Initialize controls. */
 	updateControls(sensorInfo, sensorControls, ipaControls);
 
@@ -377,6 +386,7 @@  void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,
 			       ControlInfoMap *ipaControls)
 {
 	ControlInfoMap::Map ctrlMap = rkisp1Controls;
+	ctrlMap.merge(algoControls_);
 
 	/*
 	 * Compute exposure time limits from the V4L2_CID_EXPOSURE control