From patchwork Fri Jul 3 15:38:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27195 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 4B9E8C331D for ; Fri, 3 Jul 2026 15:38:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7300E66011; Fri, 3 Jul 2026 17:38:44 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="nImFBRzI"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 31F3065FC1 for ; Fri, 3 Jul 2026 17:38:26 +0200 (CEST) Received: from pb-laptop.local (185.221.140.128.nat.pool.zt.hu [185.221.140.128]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 01BA2DF3 for ; Fri, 3 Jul 2026 17:37:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1783093060; bh=IkWf0P3HVc0tMo8+voc9P6z9vWAMhD/CCpLr+aS2F28=; h=From:To:Subject:Date:In-Reply-To:References:From; b=nImFBRzIMk96GWhMbYzBCNELH459RPWmleHm8XnK/EJ7DSadQ5WxpxBljVW1SOP56 MeOgUZ41fRZCxR72dh/GOHmwfxbYD95XUu5WfsvW8crLj20lITNMV51rmq3AmNs9ld f37VPakf0DJsNeUOFEWOqsViZkcvF0gRB8puHPoo= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [RFC PATCH v1 15/17] ipa: libipa: Add `AgcAlgorithm` Date: Fri, 3 Jul 2026 17:38:17 +0200 Message-ID: <20260703153819.1088752-16-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260703153819.1088752-1-barnabas.pocze@ideasonboard.com> References: <20260703153819.1088752-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a class that encompasses the core logic of an agc algorithm with some calculations and control handling. This can be used to simplify the implementation of specific algorithms. Also port `AgcMeanLuminanceAlgorithm` to use it. Signed-off-by: Barnabás Pőcze --- src/ipa/ipu3/algorithms/agc.cpp | 4 +- src/ipa/libipa/agc.cpp | 488 ++++++++++++++++++++++++++ src/ipa/libipa/agc.h | 100 ++++++ src/ipa/libipa/agc_mean_luminance.cpp | 429 ++-------------------- src/ipa/libipa/agc_mean_luminance.h | 61 +--- src/ipa/libipa/meson.build | 2 + src/ipa/mali-c55/algorithms/agc.cpp | 4 +- src/ipa/rkisp1/algorithms/agc.cpp | 4 +- src/ipa/rkisp1/algorithms/wdr.cpp | 2 +- 9 files changed, 627 insertions(+), 467 deletions(-) create mode 100644 src/ipa/libipa/agc.cpp create mode 100644 src/ipa/libipa/agc.h diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 0ca02390bd..fbf887c328 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -74,7 +74,7 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData) return ret; ret = agc_.configure(context.configuration.agc, context.activeState.agc, { - .sensor = *context.camHelper, + .sensor = context.camHelper.get(), .sensorInfo = context.sensorInfo, .sensorControls = context.sensorControls, .ctrlMap = context.ctrlMap, @@ -99,7 +99,7 @@ int Agc::configure(IPAContext &context, bdsGrid_ = context.configuration.grid.bdsGrid; return agc_.configure(context.configuration.agc, context.activeState.agc, { - .sensor = *context.camHelper, + .sensor = context.camHelper.get(), .sensorInfo = context.sensorInfo, .sensorControls = context.sensorControls, .ctrlMap = context.ctrlMap, diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp new file mode 100644 index 0000000000..7fce952171 --- /dev/null +++ b/src/ipa/libipa/agc.cpp @@ -0,0 +1,488 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026 Ideas on Board Oy + */ + +#include "agc.h" + +#include + +#include + +#include + +#include + +namespace libcamera { + +namespace ipa { + +using namespace std::chrono_literals; + +LOG_DEFINE_CATEGORY(Agc) + +/** + * \class AgcAlgorithm + * \brief Commong handling of AGC related controls and calculation + * + * \todo DigitalGain, DigitalGainMode + */ + +/** + * \struct AgcAlgorithm::Session + * \brief Session configuration for AgcAlgorithm + * + * \var AgcAlgorithm::Session::minExposureTime + * \brief Minimum exposure time supported with the configured sensor + * + * \var AgcAlgorithm::Session::maxExposureTime + * \brief Maximum exposure time supported with the configured sensor + * + * \var AgcAlgorithm::Session::minAnalogueGain + * \brief Minimum analogue gain supported with the configured sensor + * + * \var AgcAlgorithm::Session::maxAnalogueGain + * \brief Maximum analogue gain supported with the configured sensor + * + * \var AgcAlgorithm::Session::minFrameDuration + * \brief Minimum frame duration supported with the configured sensor + * + * \var AgcAlgorithm::Session::maxFrameDuration + * \brief Maximum frame duration supported with the configured sensor + * + * \var AgcAlgorithm::Session::lineDuration + * \brief Line duration with the configured sensor and output size + * + * \var AgcAlgorithm::Session::sensor + * \brief Details of the sensor configuration + * + * \var AgcAlgorithm::Session::sensor.outputSize + * \brief Configured output size of the sensor + * + * \var AgcAlgorithm::Session::autoAllowed + * \brief Whether automatic controls are allowed + */ + +/** + * \struct AgcAlgorithm::ActiveState + * \brief Active state for AgcAlgorithm + * + * The \a automatic variables track the latest values computed by algorithm + * based on the latest processed statistics. All other variables track the + * consolidated controls requested in queued requests. + * + * \var AgcAlgorithm::ActiveState::manual + * \brief Manual exposure time and analog gain (set through requests) + * + * \var AgcAlgorithm::ActiveState::manual.exposure + * \brief Manual exposure time expressed as a number of lines as set by the + * ExposureTime control + * + * \var AgcAlgorithm::ActiveState::manual.gain + * \brief Manual analogue gain as set by the AnalogueGain control + * + * \var AgcAlgorithm::ActiveState::automatic + * \brief Automatic exposure time and analog gain (computed by the algorithm) + * + * \var AgcAlgorithm::ActiveState::automatic.exposure + * \brief Automatic exposure time expressed as a number of lines + * + * \var AgcAlgorithm::ActiveState::automatic.gain + * \brief Automatic analogue gain multiplier + * + * \var AgcAlgorithm::ActiveState::autoExposureEnabled + * \brief Manual/automatic AGC state (exposure) as set by the ExposureTimeMode control + * + * \var AgcAlgorithm::ActiveState::autoGainEnabled + * \brief Manual/automatic AGC state (gain) as set by the AnalogueGainMode control + * + * \var AgcAlgorithm::ActiveState::minFrameDuration + * \brief Minimum frame duration as set by the FrameDurationLimits control + * + * \var AgcAlgorithm::ActiveState::maxFrameDuration + * \brief Maximum frame duration as set by the FrameDurationLimits control + */ + +/** + * \struct AgcAlgorithm::FrameContext + * \brief Per-frame context for AgcAlgorithm + * + * \var AgcAlgorithm::FrameContext::exposure + * \brief Exposure time expressed as a number of lines computed by the algorithm + * + * \var AgcAlgorithm::FrameContext::gain + * \brief Analogue gain multiplier computed by the algorithm + * + * The gain should be adapted to the sensor specific gain code before applying. + * + * \var AgcAlgorithm::FrameContext::vblank + * \brief Vertical blanking parameter computed by the algorithm + * + * \var AgcAlgorithm::FrameContext::autoExposureEnabled + * \brief Manual/automatic AGC state (exposure) as set by the ExposureTimeMode control + * + * \var AgcAlgorithm::FrameContext::autoGainEnabled + * \brief Manual/automatic AGC state (gain) as set by the AnalogueGainMode control + * + * \var AgcAlgorithm::FrameContext::minFrameDuration + * \brief Minimum frame duration as set by the FrameDurationLimits control + * + * \var AgcAlgorithm::FrameContext::maxFrameDuration + * \brief Maximum frame duration as set by the FrameDurationLimits control + * + * \var AgcAlgorithm::FrameContext::frameDuration + * \brief The actual FrameDuration used by the algorithm for the frame + * + * \var AgcAlgorithm::FrameContext::autoExposureModeChange + * \brief Indicate if autoExposureEnabled has changed from true in the previous + * frame to false in the current frame, and no manual exposure value has been + * supplied in the current frame. + * + * \var AgcAlgorithm::FrameContext::autoGainModeChange + * \brief Indicate if autoGainEnabled has changed from true in the previous + * frame to false in the current frame, and no manual gain value has been + * supplied in the current frame. + */ + +/** + * \struct AgcAlgorithm::ConfigurationParams + * \brief Parameters for AgcAlgorithm::configure() + * + * \var AgcAlgorithm::ConfigurationParams::sensor + * \brief CameraSensorHelper for the sensor + * + * \var AgcAlgorithm::ConfigurationParams::sensorInfo + * \brief Details of the sensor + * + * \var AgcAlgorithm::ConfigurationParams::sensorControls + * \brief ControlInfoMap of the sensor + * + * \var AgcAlgorithm::ConfigurationParams::ctrlMap + * \brief ControlMap to update with controls + * + * \var AgcAlgorithm::ConfigurationParams::autoAllowed + * \brief Whether to enable auto controls + */ + +/** + * \struct AgcAlgorithm::Limits + * \brief Limits of AGC parameters + * + * This structure contains the limits to consider for the actual + * AGC implementation. + * + * \var AgcAlgorithm::Limits::exposure + * \brief Limits of exposure time + * + * \var AgcAlgorithm::Limits::gain + * \brief Limits of analogue gain + */ + +/** + * \brief Initialize the session configuration and active state + */ +int AgcAlgorithm::configure(Session &session, ActiveState &state, const ConfigurationParams &config) +{ + session = {}; + session.lineDuration = config.sensorInfo.minLineLength * 1.0s + / config.sensorInfo.pixelRate; + session.sensor.outputSize = config.sensorInfo.outputSize; + session.autoAllowed = config.autoAllowed; + + const double lineDurationUs = session.lineDuration.get(); + + /* + * Compute exposure time limits from the V4L2_CID_EXPOSURE control + * limits and the line duration. + */ + + const ControlInfo &v4l2Exposure = config.sensorControls.find(V4L2_CID_EXPOSURE)->second; + int32_t minExposure = v4l2Exposure.min().get(); + int32_t maxExposure = v4l2Exposure.max().get(); + int32_t defExposure = v4l2Exposure.def().get(); + config.ctrlMap[&controls::ExposureTime] = ControlInfo{ + static_cast(minExposure * lineDurationUs), + static_cast(maxExposure * lineDurationUs), + static_cast(defExposure * lineDurationUs), + }; + + /* Compute the analogue gain limits. */ + const auto mapGain = [&](const ControlValue &v) { + auto code = v.get(); + return config.sensor ? config.sensor->gain(code) : code; + }; + + const ControlInfo &v4l2Gain = config.sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second; + float minGain = mapGain(v4l2Gain.min()); + float maxGain = mapGain(v4l2Gain.max()); + float defGain = mapGain(v4l2Gain.def()); + config.ctrlMap[&controls::AnalogueGain] = ControlInfo{ + minGain, + maxGain, + defGain, + }; + + LOG(Agc, Debug) + << "Exposure: [" << minExposure << ", " << maxExposure + << "], gain: [" << minGain << ", " << maxGain << "]"; + + /* + * Compute the frame duration limits. + * + * The frame length is computed assuming a fixed line length combined + * with the vertical frame sizes. + */ + const ControlInfo &v4l2HBlank = config.sensorControls.find(V4L2_CID_HBLANK)->second; + uint32_t hblank = v4l2HBlank.def().get(); + uint32_t lineLength = config.sensorInfo.outputSize.width + hblank; + + const ControlInfo &v4l2VBlank = config.sensorControls.find(V4L2_CID_VBLANK)->second; + std::array frameHeights{ + v4l2VBlank.min().get() + config.sensorInfo.outputSize.height, + v4l2VBlank.max().get() + config.sensorInfo.outputSize.height, + v4l2VBlank.def().get() + config.sensorInfo.outputSize.height, + }; + + std::array frameDurations; + for (unsigned int i = 0; i < frameHeights.size(); ++i) { + uint64_t frameSize = lineLength * frameHeights[i]; + frameDurations[i] = frameSize / (config.sensorInfo.pixelRate / 1000000U); + } + + config.ctrlMap[&controls::FrameDurationLimits] = ControlInfo{ + frameDurations[0], + frameDurations[1], + Span{ { frameDurations[2], frameDurations[2] } }, + }; + + session.minFrameDuration = std::chrono::microseconds(frameDurations[0]); + session.maxFrameDuration = std::chrono::microseconds(frameDurations[1]); + + /* + * When the AGC computes the new exposure values for a frame, it needs + * to know the limits for exposure time and analogue gain. As it depends + * on the sensor, update it with the controls. + * + * \todo take VBLANK into account for maximum exposure time + */ + session.minExposureTime = minExposure * session.lineDuration; + session.maxExposureTime = maxExposure * session.lineDuration; + session.minAnalogueGain = minGain; + session.maxAnalogueGain = maxGain; + + /* Configure the default exposure and gain. */ + state = {}; + state.automatic.gain = session.minAnalogueGain; + state.automatic.exposure = 10ms / session.lineDuration; + state.manual.gain = state.automatic.gain; + state.manual.exposure = state.automatic.exposure; + state.autoExposureEnabled = session.autoAllowed; + state.autoGainEnabled = session.autoAllowed; + state.minFrameDuration = session.minFrameDuration; + state.maxFrameDuration = session.maxFrameDuration; + + const auto add = [&](const ControlId &cid, const auto &automatic, const auto &manual) { + std::array values; + size_t count = 0; + + if (session.autoAllowed) + values[count++] = ControlValue(automatic); + + values[count++] = ControlValue(manual); + + config.ctrlMap[&cid] = ControlInfo{ + { values.data(), count }, + ControlValue(session.autoAllowed ? automatic : manual), + }; + }; + + add(controls::ExposureTimeMode, controls::ExposureTimeModeAuto, controls::ExposureTimeModeManual); + add(controls::AnalogueGainMode, controls::AnalogueGainModeAuto, controls::AnalogueGainModeManual); + + /* \todo Move this to the `Camera` class. */ + config.ctrlMap[&controls::AeEnable] = ControlInfo{ + false, + session.autoAllowed, + session.autoAllowed, + }; + + return 0; +} + +/** + * \brief Handle a \a queueRequest operation + */ +void AgcAlgorithm::queueRequest(const Session &session, ActiveState &state, + FrameContext &frameContext, const ControlList &controls) +{ + if (session.autoAllowed) { + const auto &aeEnable = controls.get(controls::ExposureTimeMode); + if (aeEnable && + (*aeEnable == controls::ExposureTimeModeAuto) != state.autoExposureEnabled) { + state.autoExposureEnabled = (*aeEnable == controls::ExposureTimeModeAuto); + + LOG(Agc, Debug) + << (state.autoExposureEnabled ? "Enabling" : "Disabling") + << " AGC (exposure)"; + + /* + * If we go from auto -> manual with no manual control + * set, use the last computed value, which we don't + * know until prepare() so save this information. + * + * \todo Check the previous frame at prepare() time + * instead of saving a flag here + */ + if (!state.autoExposureEnabled && !controls.get(controls::ExposureTime)) + frameContext.autoExposureModeChange = true; + } + + const auto &agEnable = controls.get(controls::AnalogueGainMode); + if (agEnable && + (*agEnable == controls::AnalogueGainModeAuto) != state.autoGainEnabled) { + state.autoGainEnabled = (*agEnable == controls::AnalogueGainModeAuto); + + LOG(Agc, Debug) + << (state.autoGainEnabled ? "Enabling" : "Disabling") + << " AGC (gain)"; + /* + * If we go from auto -> manual with no manual control + * set, use the last computed value, which we don't + * know until prepare() so save this information. + */ + if (!state.autoGainEnabled && !controls.get(controls::AnalogueGain)) + frameContext.autoGainModeChange = true; + } + } + + const auto &exposure = controls.get(controls::ExposureTime); + if (exposure && !state.autoExposureEnabled) { + state.manual.exposure = *exposure * 1.0us / session.lineDuration; + + LOG(Agc, Debug) + << "Set exposure to " << state.manual.exposure; + } + + const auto &gain = controls.get(controls::AnalogueGain); + if (gain && !state.autoGainEnabled) { + state.manual.gain = *gain; + + LOG(Agc, Debug) << "Set gain to " << state.manual.gain; + } + + frameContext.autoExposureEnabled = state.autoExposureEnabled; + frameContext.autoGainEnabled = state.autoGainEnabled; + + if (!frameContext.autoExposureEnabled) + frameContext.exposure = state.manual.exposure; + if (!frameContext.autoGainEnabled) + frameContext.gain = state.manual.gain; + + const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits); + if (frameDurationLimits) { + /* Limit the control value to the limits in ControlInfo */ + state.minFrameDuration = std::clamp( + std::chrono::microseconds((*frameDurationLimits).front()), + session.minFrameDuration, + session.maxFrameDuration + ); + + state.maxFrameDuration = std::clamp( + std::chrono::microseconds((*frameDurationLimits).back()), + session.minFrameDuration, + session.maxFrameDuration + ); + } + frameContext.minFrameDuration = state.minFrameDuration; + frameContext.maxFrameDuration = state.maxFrameDuration; +} + +/** + * \brief Handle a \a prepare operation + */ +void AgcAlgorithm::prepare(ActiveState &state, FrameContext &frameContext) +{ + uint32_t activeAutoExposure = state.automatic.exposure; + double activeAutoGain = state.automatic.gain; + + /* Populate exposure and gain in auto mode */ + if (frameContext.autoExposureEnabled) + frameContext.exposure = activeAutoExposure; + if (frameContext.autoGainEnabled) + frameContext.gain = activeAutoGain; + + /* + * Populate manual exposure and gain from the active auto values when + * transitioning from auto to manual + */ + if (!frameContext.autoExposureEnabled && frameContext.autoExposureModeChange) { + state.manual.exposure = activeAutoExposure; + frameContext.exposure = activeAutoExposure; + } + if (!frameContext.autoGainEnabled && frameContext.autoGainModeChange) { + state.manual.gain = activeAutoGain; + frameContext.gain = activeAutoGain; + } +} + +/** + * \brief Calculate the AGC limits for the given frame + */ +AgcAlgorithm::Limits AgcAlgorithm::calculateLimits(const Session &session, const FrameContext &frameContext) +{ + /* + * Set the AGC limits using the fixed exposure time and/or gain in + * manual mode, or the sensor limits in auto mode. + */ + Limits result; + + if (frameContext.autoExposureEnabled) { + result.exposure = { + session.minExposureTime, + std::clamp(frameContext.maxFrameDuration, session.minExposureTime, session.maxExposureTime), + }; + } else { + result.exposure.first = session.lineDuration * frameContext.exposure; + result.exposure.second = result.exposure.first; + } + + if (frameContext.autoGainEnabled) + result.gain = { session.minAnalogueGain, session.maxAnalogueGain }; + else + result.gain = { frameContext.gain, frameContext.gain }; + + return result; +} + +/** + * \brief Handle a \a process operation + */ +void AgcAlgorithm::process(const Session& session, FrameContext& frameContext, + utils::Duration newExposureTime, ControlList &metadata) +{ + /* + * Expand the target frame duration so that we do not run faster than + * the minimum frame duration when we have short exposures. + */ + const auto frameDuration = std::max(frameContext.minFrameDuration, newExposureTime); + frameContext.vblank = (frameDuration / session.lineDuration) - session.sensor.outputSize.height; + + /* Update frame duration accounting for line length quantization. */ + frameContext.frameDuration = (session.sensor.outputSize.height + frameContext.vblank) * session.lineDuration; + + metadata.set(controls::AnalogueGain, frameContext.gain); + metadata.set(controls::ExposureTime, utils::Duration(session.lineDuration * frameContext.exposure).get()); + metadata.set(controls::FrameDuration, frameContext.frameDuration.get()); + metadata.set(controls::ExposureTimeMode, + frameContext.autoExposureEnabled + ? controls::ExposureTimeModeAuto + : controls::ExposureTimeModeManual); + metadata.set(controls::AnalogueGainMode, + frameContext.autoGainEnabled + ? controls::AnalogueGainModeAuto + : controls::AnalogueGainModeManual); +} + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h new file mode 100644 index 0000000000..35d321a0a1 --- /dev/null +++ b/src/ipa/libipa/agc.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026 Ideas on Board Oy + */ + +#pragma once + + +#include + +#include +#include + +#include + +#include "camera_sensor_helper.h" + +namespace libcamera { + +namespace ipa { + +class AgcAlgorithm +{ +public: + struct Session { + utils::Duration minExposureTime; + utils::Duration maxExposureTime; + double minAnalogueGain; + double maxAnalogueGain; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; + + utils::Duration lineDuration; + + struct { + Size outputSize; + } sensor; + + bool autoAllowed; + }; + + struct ActiveState { + struct { + uint32_t exposure; + double gain; + } manual; + struct { + uint32_t exposure; + double gain; + } automatic; + + bool autoExposureEnabled; + bool autoGainEnabled; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; + }; + + struct FrameContext { + uint32_t exposure; + double gain; + uint32_t vblank; + bool autoExposureEnabled; + bool autoGainEnabled; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; + utils::Duration frameDuration; + bool autoExposureModeChange; + bool autoGainModeChange; + }; + + struct ConfigurationParams { + const CameraSensorHelper *sensor; + const IPACameraSensorInfo &sensorInfo; + const ControlInfoMap &sensorControls; + ControlInfoMap::Map &ctrlMap; + bool autoAllowed = true; + }; + +protected: + int configure(Session &session, ActiveState &state, const ConfigurationParams &config); + + void queueRequest(const Session &session, ActiveState &state, + FrameContext &frameContext, const ControlList &controls); + + void prepare(ActiveState &state, FrameContext &frameContext); + + struct Limits { + std::pair exposure; + std::pair gain; + }; + + [[nodiscard]] Limits calculateLimits(const Session &session, const FrameContext &frameContext); + + void process(const Session& session, FrameContext& frameContext, + utils::Duration newExposureTime, ControlList &metadata); +}; + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 951a4b0e02..0755c7ccac 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -8,11 +8,8 @@ #include "agc_mean_luminance.h" #include -#include #include -#include - #include #include @@ -748,80 +745,16 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, * \todo DigitalGain, DigitalGainMode */ -/** - * \struct AgcMeanLuminanceAlgorithm::Session - * \brief Session configuration for AgcMeanLuminanceAlgorithm - * - * \var AgcMeanLuminanceAlgorithm::Session::minExposureTime - * \brief Minimum exposure time supported with the configured sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::maxExposureTime - * \brief Maximum exposure time supported with the configured sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::minAnalogueGain - * \brief Minimum analogue gain supported with the configured sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::maxAnalogueGain - * \brief Maximum analogue gain supported with the configured sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::minFrameDuration - * \brief Minimum frame duration supported with the configured sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::maxFrameDuration - * \brief Maximum frame duration supported with the configured sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::lineDuration - * \brief Line duration with the configured sensor and output size - * - * \var AgcMeanLuminanceAlgorithm::Session::sensor - * \brief Details of the sensor configuration - * - * \var AgcMeanLuminanceAlgorithm::Session::sensor.outputSize - * \brief Configured output size of the sensor - * - * \var AgcMeanLuminanceAlgorithm::Session::autoAllowed - * \brief Whether automatic controls are allowed - */ - /** * \struct AgcMeanLuminanceAlgorithm::ActiveState * \brief Active state for AgcMeanLuminanceAlgorithm * - * The \a automatic variables track the latest values computed by algorithm - * based on the latest processed statistics. All other variables track the - * consolidated controls requested in queued requests. - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::manual - * \brief Manual exposure time and analog gain (set through requests) - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::manual.exposure - * \brief Manual exposure time expressed as a number of lines as set by the - * ExposureTime control - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::manual.gain - * \brief Manual analogue gain as set by the AnalogueGain control - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::automatic - * \brief Automatic exposure time and analog gain (computed by the algorithm) - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::automatic.exposure - * \brief Automatic exposure time expressed as a number of lines - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::automatic.gain - * \brief Automatic analogue gain multiplier - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::automatic.quantizationGain + * \var AgcMeanLuminanceAlgorithm::ActiveState::quantizationGain * \brief Automatic quantization gain multiplier * - * \var AgcMeanLuminanceAlgorithm::ActiveState::automatic.yTarget + * \var AgcMeanLuminanceAlgorithm::ActiveState::yTarget * \brief Automatically determined luminance target * - * \var AgcMeanLuminanceAlgorithm::ActiveState::autoExposureEnabled - * \brief Manual/automatic AGC state (exposure) as set by the ExposureTimeMode control - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::autoGainEnabled - * \brief Manual/automatic AGC state (gain) as set by the AnalogueGainMode control - * * \var AgcMeanLuminanceAlgorithm::ActiveState::exposureValue * \brief Exposure value as set by the ExposureValue control * @@ -830,26 +763,12 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, * * \var AgcMeanLuminanceAlgorithm::ActiveState::exposureMode * \brief Exposure mode as set by the AeExposureMode control - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::minFrameDuration - * \brief Minimum frame duration as set by the FrameDurationLimits control - * - * \var AgcMeanLuminanceAlgorithm::ActiveState::maxFrameDuration - * \brief Maximum frame duration as set by the FrameDurationLimits control */ /** * \struct AgcMeanLuminanceAlgorithm::FrameContext * \brief Per-frame context for AgcMeanLuminanceAlgorithm * - * \var AgcMeanLuminanceAlgorithm::FrameContext::exposure - * \brief Exposure time expressed as a number of lines computed by the algorithm - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::gain - * \brief Analogue gain multiplier computed by the algorithm - * - * The gain should be adapted to the sensor specific gain code before applying. - * * \var AgcMeanLuminanceAlgorithm::FrameContext::quantizationGain * \brief Quantization gain multiplier computed by the algorithm * @@ -859,59 +778,11 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, * \var AgcMeanLuminanceAlgorithm::FrameContext::yTarget * \brief Luminance target computed by the algorithm * - * \var AgcMeanLuminanceAlgorithm::FrameContext::vblank - * \brief Vertical blanking parameter computed by the algorithm - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::autoExposureEnabled - * \brief Manual/automatic AGC state (exposure) as set by the ExposureTimeMode control - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::autoGainEnabled - * \brief Manual/automatic AGC state (gain) as set by the AnalogueGainMode control - * * \var AgcMeanLuminanceAlgorithm::FrameContext::constraintMode * \brief Constraint mode as set by the AeConstraintMode control * * \var AgcMeanLuminanceAlgorithm::FrameContext::exposureMode * \brief Exposure mode as set by the AeExposureMode control - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::minFrameDuration - * \brief Minimum frame duration as set by the FrameDurationLimits control - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::maxFrameDuration - * \brief Maximum frame duration as set by the FrameDurationLimits control - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::frameDuration - * \brief The actual FrameDuration used by the algorithm for the frame - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::autoExposureModeChange - * \brief Indicate if autoExposureEnabled has changed from true in the previous - * frame to false in the current frame, and no manual exposure value has been - * supplied in the current frame. - * - * \var AgcMeanLuminanceAlgorithm::FrameContext::autoGainModeChange - * \brief Indicate if autoGainEnabled has changed from true in the previous - * frame to false in the current frame, and no manual gain value has been - * supplied in the current frame. - */ - -/** - * \struct AgcMeanLuminanceAlgorithm::ConfigurationParams - * \brief Parameters for AgcMeanLuminanceAlgorithm::configure() - * - * \var AgcMeanLuminanceAlgorithm::ConfigurationParams::sensor - * \brief CameraSensorHelper for the sensor - * - * \var AgcMeanLuminanceAlgorithm::ConfigurationParams::sensorInfo - * \brief Details of the sensor - * - * \var AgcMeanLuminanceAlgorithm::ConfigurationParams::sensorControls - * \brief ControlInfoMap of the sensor - * - * \var AgcMeanLuminanceAlgorithm::ConfigurationParams::ctrlMap - * \brief ControlMap to update with controls - * - * \var AgcMeanLuminanceAlgorithm::ConfigurationParams::autoAllowed - * \brief Whether to enable auto controls */ /** @@ -954,104 +825,18 @@ int AgcMeanLuminanceAlgorithm::init(const ValueNode &tuningData) */ int AgcMeanLuminanceAlgorithm::configure(Session &session, ActiveState &state, const ConfigurationParams &config) { - session = {}; - session.lineDuration = config.sensorInfo.minLineLength * 1.0s - / config.sensorInfo.pixelRate; - session.sensor.outputSize = config.sensorInfo.outputSize; - session.autoAllowed = config.autoAllowed; - - const double lineDurationUs = session.lineDuration.get(); - - /* - * Compute exposure time limits from the V4L2_CID_EXPOSURE control - * limits and the line duration. - */ - - const ControlInfo &v4l2Exposure = config.sensorControls.find(V4L2_CID_EXPOSURE)->second; - int32_t minExposure = v4l2Exposure.min().get(); - int32_t maxExposure = v4l2Exposure.max().get(); - int32_t defExposure = v4l2Exposure.def().get(); - config.ctrlMap[&controls::ExposureTime] = ControlInfo{ - static_cast(minExposure * lineDurationUs), - static_cast(maxExposure * lineDurationUs), - static_cast(defExposure * lineDurationUs), - }; - - /* Compute the analogue gain limits. */ - const ControlInfo &v4l2Gain = config.sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second; - float minGain = config.sensor.gain(v4l2Gain.min().get()); - float maxGain = config.sensor.gain(v4l2Gain.max().get()); - float defGain = config.sensor.gain(v4l2Gain.def().get()); - config.ctrlMap[&controls::AnalogueGain] = ControlInfo{ - minGain, - maxGain, - defGain, - }; - - LOG(AgcMeanLuminance, Debug) - << "Exposure: [" << minExposure << ", " << maxExposure - << "], gain: [" << minGain << ", " << maxGain << "]"; - - /* - * Compute the frame duration limits. - * - * The frame length is computed assuming a fixed line length combined - * with the vertical frame sizes. - */ - const ControlInfo &v4l2HBlank = config.sensorControls.find(V4L2_CID_HBLANK)->second; - uint32_t hblank = v4l2HBlank.def().get(); - uint32_t lineLength = config.sensorInfo.outputSize.width + hblank; - - const ControlInfo &v4l2VBlank = config.sensorControls.find(V4L2_CID_VBLANK)->second; - std::array frameHeights{ - v4l2VBlank.min().get() + config.sensorInfo.outputSize.height, - v4l2VBlank.max().get() + config.sensorInfo.outputSize.height, - v4l2VBlank.def().get() + config.sensorInfo.outputSize.height, - }; - - std::array frameDurations; - for (unsigned int i = 0; i < frameHeights.size(); ++i) { - uint64_t frameSize = lineLength * frameHeights[i]; - frameDurations[i] = frameSize / (config.sensorInfo.pixelRate / 1000000U); - } - - config.ctrlMap[&controls::FrameDurationLimits] = ControlInfo{ - frameDurations[0], - frameDurations[1], - Span{ { frameDurations[2], frameDurations[2] } }, - }; - - session.minFrameDuration = std::chrono::microseconds(frameDurations[0]); - session.maxFrameDuration = std::chrono::microseconds(frameDurations[1]); - - /* - * When the AGC computes the new exposure values for a frame, it needs - * to know the limits for exposure time and analogue gain. As it depends - * on the sensor, update it with the controls. - * - * \todo take VBLANK into account for maximum exposure time - */ - session.minExposureTime = minExposure * session.lineDuration; - session.maxExposureTime = maxExposure * session.lineDuration; - session.minAnalogueGain = minGain; - session.maxAnalogueGain = maxGain; + int ret = AgcAlgorithm::configure(session, state, config); + if (ret) + return ret; - impl_.configure(session.lineDuration, &config.sensor); + impl_.configure(session.lineDuration, config.sensor); impl_.setLimits(session.minExposureTime, session.maxExposureTime, session.minAnalogueGain, session.maxAnalogueGain, {}); impl_.resetFrameCount(); - /* Configure the default exposure and gain. */ - state = {}; - state.automatic.gain = session.minAnalogueGain; - state.automatic.exposure = 10ms / session.lineDuration; - state.automatic.quantizationGain = 1; - state.automatic.yTarget = impl_.effectiveYTarget(); - state.manual.gain = state.automatic.gain; - state.manual.exposure = state.automatic.exposure; - state.autoExposureEnabled = session.autoAllowed; - state.autoGainEnabled = session.autoAllowed; + state.quantizationGain = 1; + state.yTarget = impl_.effectiveYTarget(); state.exposureValue = 0; state.constraintMode = @@ -1059,34 +844,6 @@ int AgcMeanLuminanceAlgorithm::configure(Session &session, ActiveState &state, c state.exposureMode = static_cast(impl_.exposureModeHelpers().begin()->first); - state.minFrameDuration = session.minFrameDuration; - state.maxFrameDuration = session.maxFrameDuration; - - const auto add = [&](const ControlId &cid, const auto &automatic, const auto &manual) { - std::array values; - size_t count = 0; - - if (session.autoAllowed) - values[count++] = ControlValue(automatic); - - values[count++] = ControlValue(manual); - - config.ctrlMap[&cid] = ControlInfo{ - { values.data(), count }, - ControlValue(session.autoAllowed ? automatic : manual), - }; - }; - - add(controls::ExposureTimeMode, controls::ExposureTimeModeAuto, controls::ExposureTimeModeManual); - add(controls::AnalogueGainMode, controls::AnalogueGainModeAuto, controls::AnalogueGainModeManual); - - /* \todo Move this to the `Camera` class. */ - config.ctrlMap[&controls::AeEnable] = ControlInfo{ - false, - session.autoAllowed, - session.autoAllowed, - }; - // \todo Should these be added/removed based on `session.autoAllowed` ? config.ctrlMap[&controls::ExposureValue] = ControlInfo(-8.0f, 8.0f, 0.0f); @@ -1100,70 +857,9 @@ int AgcMeanLuminanceAlgorithm::configure(Session &session, ActiveState &state, c * \brief Handle a \a queueRequest operation */ void AgcMeanLuminanceAlgorithm::queueRequest(const Session &session, ActiveState &state, - FrameContext &frameContext, const ControlList &controls) + FrameContext &frameContext, const ControlList &controls) { - if (session.autoAllowed) { - const auto &aeEnable = controls.get(controls::ExposureTimeMode); - if (aeEnable && - (*aeEnable == controls::ExposureTimeModeAuto) != state.autoExposureEnabled) { - state.autoExposureEnabled = (*aeEnable == controls::ExposureTimeModeAuto); - - LOG(AgcMeanLuminance, Debug) - << (state.autoExposureEnabled ? "Enabling" : "Disabling") - << " AGC (exposure)"; - - /* - * If we go from auto -> manual with no manual control - * set, use the last computed value, which we don't - * know until prepare() so save this information. - * - * \todo Check the previous frame at prepare() time - * instead of saving a flag here - */ - if (!state.autoExposureEnabled && !controls.get(controls::ExposureTime)) - frameContext.autoExposureModeChange = true; - } - - const auto &agEnable = controls.get(controls::AnalogueGainMode); - if (agEnable && - (*agEnable == controls::AnalogueGainModeAuto) != state.autoGainEnabled) { - state.autoGainEnabled = (*agEnable == controls::AnalogueGainModeAuto); - - LOG(AgcMeanLuminance, Debug) - << (state.autoGainEnabled ? "Enabling" : "Disabling") - << " AGC (gain)"; - /* - * If we go from auto -> manual with no manual control - * set, use the last computed value, which we don't - * know until prepare() so save this information. - */ - if (!state.autoGainEnabled && !controls.get(controls::AnalogueGain)) - frameContext.autoGainModeChange = true; - } - } - - const auto &exposure = controls.get(controls::ExposureTime); - if (exposure && !state.autoExposureEnabled) { - state.manual.exposure = *exposure * 1.0us / session.lineDuration; - - LOG(AgcMeanLuminance, Debug) - << "Set exposure to " << state.manual.exposure; - } - - const auto &gain = controls.get(controls::AnalogueGain); - if (gain && !state.autoGainEnabled) { - state.manual.gain = *gain; - - LOG(AgcMeanLuminance, Debug) << "Set gain to " << state.manual.gain; - } - - frameContext.autoExposureEnabled = state.autoExposureEnabled; - frameContext.autoGainEnabled = state.autoGainEnabled; - - if (!frameContext.autoExposureEnabled) - frameContext.exposure = state.manual.exposure; - if (!frameContext.autoGainEnabled) - frameContext.gain = state.manual.gain; + AgcAlgorithm::queueRequest(session, state, frameContext, controls); if (!frameContext.autoExposureEnabled && !frameContext.autoGainEnabled) @@ -1185,24 +881,6 @@ void AgcMeanLuminanceAlgorithm::queueRequest(const Session &session, ActiveState if (exposureValue) state.exposureValue = *exposureValue; frameContext.exposureValue = state.exposureValue; - - const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits); - if (frameDurationLimits) { - /* Limit the control value to the limits in ControlInfo */ - state.minFrameDuration = std::clamp( - std::chrono::microseconds((*frameDurationLimits).front()), - session.minFrameDuration, - session.maxFrameDuration - ); - - state.maxFrameDuration = std::clamp( - std::chrono::microseconds((*frameDurationLimits).back()), - session.minFrameDuration, - session.maxFrameDuration - ); - } - frameContext.minFrameDuration = state.minFrameDuration; - frameContext.maxFrameDuration = state.maxFrameDuration; } /** @@ -1210,35 +888,17 @@ void AgcMeanLuminanceAlgorithm::queueRequest(const Session &session, ActiveState */ void AgcMeanLuminanceAlgorithm::prepare(ActiveState &state, FrameContext &frameContext) { - uint32_t activeAutoExposure = state.automatic.exposure; - double activeAutoGain = state.automatic.gain; - double activeAutoQGain = state.automatic.quantizationGain; + AgcAlgorithm::prepare(state, frameContext); - /* Populate exposure and gain in auto mode */ - if (frameContext.autoExposureEnabled) { - frameContext.exposure = activeAutoExposure; - frameContext.quantizationGain = activeAutoQGain; - } - if (frameContext.autoGainEnabled) { - frameContext.gain = activeAutoGain; - frameContext.quantizationGain = activeAutoQGain; - } + double activeAutoQGain = state.quantizationGain; - /* - * Populate manual exposure and gain from the active auto values when - * transitioning from auto to manual - */ - if (!frameContext.autoExposureEnabled && frameContext.autoExposureModeChange) { - state.manual.exposure = activeAutoExposure; - frameContext.exposure = activeAutoExposure; - } - if (!frameContext.autoGainEnabled && frameContext.autoGainModeChange) { - state.manual.gain = activeAutoGain; - frameContext.gain = activeAutoGain; + if (frameContext.autoExposureEnabled || frameContext.autoGainEnabled) frameContext.quantizationGain = activeAutoQGain; - } - frameContext.yTarget = state.automatic.yTarget; + if (!frameContext.autoGainEnabled && frameContext.autoGainModeChange) + frameContext.quantizationGain = activeAutoQGain; // \todo WHAT?! + + frameContext.yTarget = state.yTarget; } /** @@ -1254,30 +914,7 @@ void AgcMeanLuminanceAlgorithm::process(const Session &session, ActiveState &sta if (params) { ASSERT(session.autoAllowed); - /* - * Set the AGC limits using the fixed exposure time and/or gain in - * manual mode, or the sensor limits in auto mode. - */ - utils::Duration minExposureTime; - utils::Duration maxExposureTime; - double minAnalogueGain; - double maxAnalogueGain; - - if (frameContext.autoExposureEnabled) { - minExposureTime = session.minExposureTime; - maxExposureTime = std::clamp(frameContext.maxFrameDuration, session.minExposureTime, session.maxExposureTime); - } else { - minExposureTime = lineDuration * frameContext.exposure; - maxExposureTime = minExposureTime; - } - - if (frameContext.autoGainEnabled) { - minAnalogueGain = session.minAnalogueGain; - maxAnalogueGain = session.maxAnalogueGain; - } else { - minAnalogueGain = frameContext.gain; - maxAnalogueGain = frameContext.gain; - } + auto limits = AgcAlgorithm::calculateLimits(session, frameContext); /* * The Agc algorithm needs to know the effective exposure value that was @@ -1286,8 +923,8 @@ void AgcMeanLuminanceAlgorithm::process(const Session &session, ActiveState &sta utils::Duration effectiveExposureValue = lineDuration * params->exposure * params->gain; - impl_.setLimits(minExposureTime, maxExposureTime, - minAnalogueGain, maxAnalogueGain, + impl_.setLimits(limits.exposure.first, limits.exposure.second, + limits.gain.first, limits.gain.second, std::move(params->additionalConstraints)); impl_.setExposureCompensation(pow(2.0, frameContext.exposureValue)); @@ -1306,31 +943,11 @@ void AgcMeanLuminanceAlgorithm::process(const Session &session, ActiveState &sta /* Update the estimated exposure and gain. */ state.automatic.exposure = newExposureTime / lineDuration; state.automatic.gain = aGain; - state.automatic.quantizationGain = qGain; - state.automatic.yTarget = impl_.effectiveYTarget(); + state.quantizationGain = qGain; + state.yTarget = impl_.effectiveYTarget(); } - /* - * Expand the target frame duration so that we do not run faster than - * the minimum frame duration when we have short exposures. - */ - const auto frameDuration = std::max(frameContext.minFrameDuration, newExposureTime); - frameContext.vblank = (frameDuration / lineDuration) - session.sensor.outputSize.height; - - /* Update frame duration accounting for line length quantization. */ - frameContext.frameDuration = (session.sensor.outputSize.height + frameContext.vblank) * lineDuration; - - metadata.set(controls::AnalogueGain, frameContext.gain); - metadata.set(controls::ExposureTime, utils::Duration(lineDuration * frameContext.exposure).get()); - metadata.set(controls::FrameDuration, frameContext.frameDuration.get()); - metadata.set(controls::ExposureTimeMode, - frameContext.autoExposureEnabled - ? controls::ExposureTimeModeAuto - : controls::ExposureTimeModeManual); - metadata.set(controls::AnalogueGainMode, - frameContext.autoGainEnabled - ? controls::AnalogueGainModeAuto - : controls::AnalogueGainModeManual); + AgcAlgorithm::process(session, frameContext, newExposureTime, metadata); metadata.set(controls::AeExposureMode, frameContext.exposureMode); metadata.set(controls::AeConstraintMode, frameContext.constraintMode); diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index e7e2d8ad0d..ceae33ba3e 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -22,6 +22,7 @@ #include "libcamera/internal/value_node.h" +#include "agc.h" #include "exposure_mode_helper.h" #include "histogram.h" #include "pwl.h" @@ -119,71 +120,23 @@ private: ControlInfoMap::Map controls_; }; -class AgcMeanLuminanceAlgorithm +class AgcMeanLuminanceAlgorithm : public AgcAlgorithm { public: - struct Session { - utils::Duration minExposureTime; - utils::Duration maxExposureTime; - double minAnalogueGain; - double maxAnalogueGain; - utils::Duration minFrameDuration; - utils::Duration maxFrameDuration; - - utils::Duration lineDuration; - - struct { - Size outputSize; - } sensor; - - bool autoAllowed; - }; - - struct ActiveState { - struct { - uint32_t exposure; - double gain; - } manual; - struct { - uint32_t exposure; - double gain; - double quantizationGain; - double yTarget; - } automatic; - - bool autoExposureEnabled; - bool autoGainEnabled; + struct ActiveState : AgcAlgorithm::ActiveState { + double quantizationGain; + double yTarget; double exposureValue; controls::AeConstraintModeEnum constraintMode; controls::AeExposureModeEnum exposureMode; - utils::Duration minFrameDuration; - utils::Duration maxFrameDuration; }; - struct FrameContext { - uint32_t exposure; - double gain; + struct FrameContext : AgcAlgorithm::FrameContext { double quantizationGain; - double exposureValue; double yTarget; - uint32_t vblank; - bool autoExposureEnabled; - bool autoGainEnabled; + double exposureValue; controls::AeConstraintModeEnum constraintMode; controls::AeExposureModeEnum exposureMode; - utils::Duration minFrameDuration; - utils::Duration maxFrameDuration; - utils::Duration frameDuration; - bool autoExposureModeChange; - bool autoGainModeChange; - }; - - struct ConfigurationParams { - const CameraSensorHelper &sensor; - const IPACameraSensorInfo &sensorInfo; - const ControlInfoMap &sensorControls; - ControlInfoMap::Map &ctrlMap; - bool autoAllowed = true; }; int init(const ValueNode &tuningData); diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index 963c5ee730..47c027f707 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -2,6 +2,7 @@ libipa_headers = files([ 'agc_mean_luminance.h', + 'agc.h', 'algorithm.h', 'awb_bayes.h', 'awb_grey.h', @@ -23,6 +24,7 @@ libipa_headers = files([ libipa_sources = files([ 'agc_mean_luminance.cpp', + 'agc.cpp', 'algorithm.cpp', 'awb_bayes.cpp', 'awb_grey.cpp', diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index 386541fd58..4c6c2b5acb 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -128,7 +128,7 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData) return ret; ret = agc_.configure(context.configuration.agc, context.activeState.agc, { - .sensor = *context.camHelper, + .sensor = context.camHelper.get(), .sensorInfo = context.sensorInfo, .sensorControls = context.sensorControls, .ctrlMap = context.ctrlMap, @@ -148,7 +148,7 @@ int Agc::configure(IPAContext &context, return ret; ret = agc_.configure(context.configuration.agc, context.activeState.agc, { - .sensor = *context.camHelper, + .sensor = context.camHelper.get(), .sensorInfo = context.sensorInfo, .sensorControls = context.sensorControls, .ctrlMap = context.ctrlMap, diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 0d01ec1bda..ceef60c029 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -141,7 +141,7 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData) return ret; ret = agc_.configure(context.configuration.agc, context.activeState.agc, { - .sensor = *context.camHelper, + .sensor = context.camHelper.get(), .sensorInfo = context.sensorInfo, .sensorControls = context.sensorControls, .ctrlMap = context.ctrlMap, @@ -167,7 +167,7 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData) int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) { int ret = agc_.configure(context.configuration.agc, context.activeState.agc, { - .sensor = *context.camHelper, + .sensor = context.camHelper.get(), .sensorInfo = context.sensorInfo, .sensorControls = context.sensorControls, .ctrlMap = context.ctrlMap, diff --git a/src/ipa/rkisp1/algorithms/wdr.cpp b/src/ipa/rkisp1/algorithms/wdr.cpp index c3d73da2c5..b16aa7dd3b 100644 --- a/src/ipa/rkisp1/algorithms/wdr.cpp +++ b/src/ipa/rkisp1/algorithms/wdr.cpp @@ -464,7 +464,7 @@ void WideDynamicRange::process(IPAContext &context, [[maybe_unused]] const uint3 /* Calculate the gain needed to reach the requested yTarget. */ double value = cumHist.interQuantileMean(0, 1.0) / cumHist.bins(); - double gain = context.activeState.agc.automatic.yTarget / value; + double gain = context.activeState.agc.yTarget / value; gain = std::max(gain, 1.0); double speed = 0.2;