[PATCH 5/5] ipa: rkisp1: agc: Plumb mode-selection and frame duration controls
Paul Elder
paul.elder at ideasonboard.com
Fri Apr 5 16:47:29 CEST 2024
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.
Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
src/ipa/rkisp1/algorithms/agc.cpp | 67 ++++++++++++++++++++-------
src/ipa/rkisp1/algorithms/agc.h | 5 ++
src/ipa/rkisp1/algorithms/algorithm.h | 2 +
src/ipa/rkisp1/ipa_context.h | 4 ++
src/ipa/rkisp1/rkisp1.cpp | 10 ++++
5 files changed, 72 insertions(+), 16 deletions(-)
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index a1b6eb39..ed4d6330 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -11,6 +11,7 @@
#include <chrono>
#include <cmath>
#include <tuple>
+#include <vector>
#include <libcamera/base/log.h>
#include <libcamera/base/utils.h>
@@ -49,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()) {
@@ -67,9 +69,14 @@ 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);
}
+ Algorithm::controls_[&controls::AeMeteringMode] =
+ ControlInfo(availableMeteringModes);
+
return 0;
}
@@ -131,9 +138,25 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData)
context.ctrlMap.merge(controls());
+ defaultConstraintMode_ = constraintModes().begin()->first;
+ defaultExposureMode_ = exposureModeHelpers().begin()->first;
+ defaultMeteringMode_ = meteringModes_.begin()->first;
+
+ Algorithm::controls_.merge(ControlInfoMap::Map(controls()));
+
return 0;
}
+void Agc::configureExposureModeHelpers(IPAContext &context, utils::Duration maxShutterSpeed)
+{
+ for (auto &[id, helper] : exposureModeHelpers()) {
+ helper->configure(context.configuration.sensor.minShutterSpeed,
+ maxShutterSpeed,
+ context.configuration.sensor.minAnalogueGain,
+ context.configuration.sensor.maxAnalogueGain);
+ }
+}
+
/**
* \brief Configure the AGC given a configInfo
* \param[in] context The shared IPA context
@@ -153,12 +176,8 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
context.activeState.agc.manual.dgain = 1;
context.activeState.agc.autoEnabled = !context.configuration.raw;
- /*
- * \todo We should use the first available mode rather than assume that
- * the "Normal" modes are present in tuning data.
- */
- context.activeState.agc.constraintMode = controls::ConstraintNormal;
- context.activeState.agc.exposureMode = controls::ExposureNormal;
+ context.activeState.agc.constraintMode = defaultConstraintMode_;
+ context.activeState.agc.exposureMode = defaultExposureMode_;
/*
* Define the measurement window for AGC as a centered rectangle
@@ -169,13 +188,7 @@ 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;
- for (auto &[id, helper] : exposureModeHelpers()) {
- /* \todo Run this again when FrameDurationLimits is passed in */
- helper->configure(context.configuration.sensor.minShutterSpeed,
- context.configuration.sensor.maxShutterSpeed,
- context.configuration.sensor.minAnalogueGain,
- context.configuration.sensor.maxAnalogueGain);
- }
+ configureExposureModeHelpers(context, context.configuration.sensor.maxShutterSpeed);
return 0;
}
@@ -223,6 +236,20 @@ void Agc::queueRequest(IPAContext &context,
frameContext.agc.exposure = agc.manual.exposure;
frameContext.agc.gain = agc.manual.gain;
}
+
+ const auto &meteringMode = controls.get(controls::AeMeteringMode);
+ frameContext.agc.meteringMode = meteringMode.value_or(defaultMeteringMode_);
+
+ const auto &exposureMode = controls.get(controls::AeExposureMode);
+ frameContext.agc.exposureMode = exposureMode.value_or(defaultExposureMode_);
+
+ const auto &constraintMode = controls.get(controls::AeConstraintMode);
+ frameContext.agc.constraintMode = constraintMode.value_or(defaultConstraintMode_);
+
+ const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits);
+ frameContext.agc.maxShutterSpeed = frameDurationLimits
+ ? std::chrono::milliseconds((*frameDurationLimits).back())
+ : 60ms;
}
/**
@@ -262,8 +289,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;
@@ -290,6 +316,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
@@ -297,6 +324,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);
}
void Agc::parseStatistics(const rkisp1_stat_buffer *stats,
@@ -378,6 +409,10 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
ASSERT(stats->meas_type & RKISP1_CIF_ISP_STAT_AUTOEXP);
+ utils::Duration maxShutterSpeed = std::min(context.configuration.sensor.maxShutterSpeed,
+ frameContext.agc.maxShutterSpeed);
+ configureExposureModeHelpers(context, maxShutterSpeed);
+
parseStatistics(stats, context);
/*
diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h
index 43e3d5b2..c05ba4be 100644
--- a/src/ipa/rkisp1/algorithms/agc.h
+++ b/src/ipa/rkisp1/algorithms/agc.h
@@ -47,6 +47,7 @@ private:
int parseMeteringModes(IPAContext &context, const YamlObject &tuningData,
const char *prop);
uint8_t predivider(Size &size);
+ void configureExposureModeHelpers(IPAContext &context, utils::Duration maxShutterSpeed);
void fillMetadata(IPAContext &context, IPAFrameContext &frameContext,
ControlList &metadata);
@@ -58,6 +59,10 @@ private:
Span<const uint8_t> expMeans_;
std::map<int32_t, std::vector<uint8_t>> meteringModes_;
+
+ int32_t defaultConstraintMode_;
+ int32_t defaultExposureMode_;
+ int32_t defaultMeteringMode_;
};
} /* namespace ipa::rkisp1::algorithms */
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 a70c7eb3..dc876da0 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -114,6 +114,10 @@ struct IPAFrameContext : public FrameContext {
double gain;
double dgain;
bool autoEnabled;
+ int32_t meteringMode;
+ int32_t exposureMode;
+ int32_t constraintMode;
+ utils::Duration maxShutterSpeed;
} agc;
struct {
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index d66dfdd7..3654b5a6 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
--
2.39.2
More information about the libcamera-devel
mailing list