diff options
author | Paul Elder <paul.elder@ideasonboard.com> | 2024-03-13 19:25:16 +0900 |
---|---|---|
committer | Paul Elder <paul.elder@ideasonboard.com> | 2024-06-14 22:16:01 +0900 |
commit | 248374feca901d79c5df24b06e01fc0113e84638 (patch) | |
tree | 963706a1df59cc0e55018d8b11d93a31c1254759 /src/ipa/rkisp1/algorithms | |
parent | 35233938ee5d7a560dd4a93c0a1b08eae4935ae4 (diff) |
ipa: rkisp1: agc: Plumb mode-selection and frame duration controls
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>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/ipa/rkisp1/algorithms')
-rw-r--r-- | src/ipa/rkisp1/algorithms/agc.cpp | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 5a9c6be1..87021451 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> @@ -74,6 +76,13 @@ int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData) meteringModes_[meteringModeId] = weights; } + std::vector<ControlValue> meteringModes; + std::vector<int> meteringModeKeys = utils::map_keys(meteringModes_); + std::transform(meteringModeKeys.begin(), meteringModeKeys.end(), + std::back_inserter(meteringModes), + [](int x) { return ControlValue(x); }); + context.ctrlMap[&controls::AeMeteringMode] = ControlInfo(meteringModes); + return 0; } @@ -167,8 +176,19 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure; context.activeState.agc.autoEnabled = !context.configuration.raw; - context.activeState.agc.constraintMode = constraintModes().begin()->first; - context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first; + context.activeState.agc.constraintMode = + static_cast<controls::AeConstraintModeEnum>(constraintModes().begin()->first); + context.activeState.agc.exposureMode = + static_cast<controls::AeExposureModeEnum>(exposureModeHelpers().begin()->first); + context.activeState.agc.meteringMode = + static_cast<controls::AeMeteringModeEnum>(meteringModes_.begin()->first); + + /* + * \todo This should probably come from FrameDurationLimits instead, + * except it's computed in the IPA and not here so we'd have to + * recompute it. + */ + context.activeState.agc.maxShutterSpeed = context.configuration.sensor.maxShutterSpeed; /* * Define the measurement window for AGC as a centered rectangle @@ -179,7 +199,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, @@ -233,6 +252,39 @@ 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) { + frameContext.agc.update = agc.meteringMode != *meteringMode; + agc.meteringMode = + static_cast<controls::AeMeteringModeEnum>(*meteringMode); + } + frameContext.agc.meteringMode = agc.meteringMode; + + const auto &exposureMode = controls.get(controls::AeExposureMode); + if (exposureMode) { + frameContext.agc.update = agc.exposureMode != *exposureMode; + agc.exposureMode = + static_cast<controls::AeExposureModeEnum>(*exposureMode); + } + frameContext.agc.exposureMode = agc.exposureMode; + + const auto &constraintMode = controls.get(controls::AeConstraintMode); + if (constraintMode) { + frameContext.agc.update = agc.constraintMode != *constraintMode; + agc.constraintMode = + static_cast<controls::AeConstraintModeEnum>(*constraintMode); + } + frameContext.agc.constraintMode = agc.constraintMode; + + const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits); + if (frameDurationLimits) { + utils::Duration maxShutterSpeed = + std::chrono::milliseconds((*frameDurationLimits).back()); + frameContext.agc.update = agc.maxShutterSpeed != maxShutterSpeed; + agc.maxShutterSpeed = maxShutterSpeed; + } + frameContext.agc.maxShutterSpeed = agc.maxShutterSpeed; } /** @@ -246,8 +298,7 @@ void Agc::prepare(IPAContext &context, const uint32_t frame, frameContext.agc.gain = context.activeState.agc.automatic.gain; } - /* \todo Remove this when we can set the below with controls */ - if (frame > 0) + if (frame > 0 && !frameContext.agc.update) return; /* Configure the measurement window. */ @@ -271,8 +322,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()); struct rkisp1_cif_isp_window window = params->meas.hst_config.meas_window; @@ -295,6 +345,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 @@ -302,6 +353,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); } /** @@ -376,6 +431,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. |