summaryrefslogtreecommitdiff
path: root/src/ipa
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2022-10-18 14:49:13 +0900
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-11-25 10:52:06 +0200
commit4cf3c96493084dba77a4e5707f96db2e0b4481a5 (patch)
tree5b2bcdbe660ede47d8091e203d5e8e38232c3dc9 /src/ipa
parent947b8627f9a27e2966c05443f1d2af5561efdb64 (diff)
ipa: rkisp1: Add support for manual gain and exposure
Add support for manual gain and exposure in the rkisp1 IPA. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Diffstat (limited to 'src/ipa')
-rw-r--r--src/ipa/rkisp1/algorithms/agc.cpp63
-rw-r--r--src/ipa/rkisp1/algorithms/agc.h4
-rw-r--r--src/ipa/rkisp1/ipa_context.h13
-rw-r--r--src/ipa/rkisp1/rkisp1.cpp25
4 files changed, 96 insertions, 9 deletions
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index dba58c90..322e837d 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -74,9 +74,14 @@ Agc::Agc()
int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
{
/* Configure the default exposure and gain. */
- context.activeState.agc.gain = std::max(context.configuration.sensor.minAnalogueGain,
- kMinAnalogueGain);
- context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration;
+ context.activeState.agc.automatic.gain =
+ std::max(context.configuration.sensor.minAnalogueGain,
+ kMinAnalogueGain);
+ context.activeState.agc.automatic.exposure =
+ 10ms / context.configuration.sensor.lineDuration;
+ context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain;
+ context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure;
+ context.activeState.agc.autoEnabled = true;
/*
* According to the RkISP1 documentation:
@@ -109,13 +114,57 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
}
/**
+ * \copydoc libcamera::ipa::Algorithm::queueRequest
+ */
+void Agc::queueRequest(IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext,
+ const ControlList &controls)
+{
+ auto &agc = context.activeState.agc;
+
+ const auto &agcEnable = controls.get(controls::AeEnable);
+ if (agcEnable && *agcEnable != agc.autoEnabled) {
+ agc.autoEnabled = *agcEnable;
+
+ LOG(RkISP1Agc, Debug)
+ << (agc.autoEnabled ? "Enabling" : "Disabling") << " AGC";
+ }
+
+ const auto &exposure = controls.get(controls::ExposureTime);
+ if (exposure && !agc.autoEnabled) {
+ agc.manual.exposure = *exposure * 1.0us
+ / context.configuration.sensor.lineDuration;
+
+ LOG(RkISP1Agc, Debug)
+ << "Set exposure to " << agc.manual.exposure;
+ }
+
+ const auto &gain = controls.get(controls::AnalogueGain);
+ if (gain && !agc.autoEnabled) {
+ agc.manual.gain = *gain;
+
+ LOG(RkISP1Agc, Debug) << "Set gain to " << agc.manual.gain;
+ }
+
+ frameContext.agc.autoEnabled = agc.autoEnabled;
+
+ if (!frameContext.agc.autoEnabled) {
+ frameContext.agc.exposure = agc.manual.exposure;
+ frameContext.agc.gain = agc.manual.gain;
+ }
+}
+
+/**
* \copydoc libcamera::ipa::Algorithm::prepare
*/
void Agc::prepare(IPAContext &context, const uint32_t frame,
IPAFrameContext &frameContext, rkisp1_params_cfg *params)
{
- frameContext.agc.exposure = context.activeState.agc.exposure;
- frameContext.agc.gain = context.activeState.agc.gain;
+ if (frameContext.agc.autoEnabled) {
+ frameContext.agc.exposure = context.activeState.agc.automatic.exposure;
+ frameContext.agc.gain = context.activeState.agc.automatic.gain;
+ }
if (frame > 0)
return;
@@ -263,8 +312,8 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
<< stepGain;
/* Update the estimated exposure and gain. */
- activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;
- activeState.agc.gain = stepGain;
+ activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration;
+ activeState.agc.automatic.gain = stepGain;
}
/**
diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h
index da4d2d4e..a228d0c3 100644
--- a/src/ipa/rkisp1/algorithms/agc.h
+++ b/src/ipa/rkisp1/algorithms/agc.h
@@ -26,6 +26,10 @@ public:
~Agc() = default;
int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override;
+ void queueRequest(IPAContext &context,
+ const uint32_t frame,
+ IPAFrameContext &frameContext,
+ const ControlList &controls) override;
void prepare(IPAContext &context, const uint32_t frame,
IPAFrameContext &frameContext,
rkisp1_params_cfg *params) override;
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index 3e47ac66..b9b20653 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -54,8 +54,16 @@ struct IPASessionConfiguration {
struct IPAActiveState {
struct {
- uint32_t exposure;
- double gain;
+ struct {
+ uint32_t exposure;
+ double gain;
+ } manual;
+ struct {
+ uint32_t exposure;
+ double gain;
+ } automatic;
+
+ bool autoEnabled;
} agc;
struct {
@@ -96,6 +104,7 @@ struct IPAFrameContext : public FrameContext {
struct {
uint32_t exposure;
double gain;
+ bool autoEnabled;
} agc;
struct {
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index dd551c7b..52dffc09 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -157,6 +157,9 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
return -ENODEV;
}
+ context_.configuration.sensor.lineDuration = sensorInfo.minLineLength
+ * 1.0s / sensorInfo.pixelRate;
+
/* Load the tuning data file. */
File file(settings.configurationFile);
if (!file.open(File::OpenModeFlag::ReadOnly)) {
@@ -377,6 +380,28 @@ void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,
ControlInfoMap::Map ctrlMap = rkisp1Controls;
/*
+ * Compute exposure time limits from the V4L2_CID_EXPOSURE control
+ * limits and the line duration.
+ */
+ double lineDuration = context_.configuration.sensor.lineDuration.get<std::micro>();
+ const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;
+ int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;
+ int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;
+ int32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;
+ ctrlMap.emplace(std::piecewise_construct,
+ std::forward_as_tuple(&controls::ExposureTime),
+ std::forward_as_tuple(minExposure, maxExposure, defExposure));
+
+ /* Compute the analogue gain limits. */
+ const ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;
+ float minGain = camHelper_->gain(v4l2Gain.min().get<int32_t>());
+ float maxGain = camHelper_->gain(v4l2Gain.max().get<int32_t>());
+ float defGain = camHelper_->gain(v4l2Gain.def().get<int32_t>());
+ ctrlMap.emplace(std::piecewise_construct,
+ std::forward_as_tuple(&controls::AnalogueGain),
+ std::forward_as_tuple(minGain, maxGain, defGain));
+
+ /*
* Compute the frame duration limits.
*
* The frame length is computed assuming a fixed line length combined