Patch Detail
Show a patch.
GET /api/patches/27475/?format=api
{ "id": 27475, "url": "https://patchwork.libcamera.org/api/patches/27475/?format=api", "web_url": "https://patchwork.libcamera.org/patch/27475/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260723154327.1357866-28-barnabas.pocze@ideasonboard.com>", "date": "2026-07-23T15:43:10", "name": "[RFC,v2,27/43] ipa: mali-c55: agc: Port to `AgcAlgorithm`", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "5e9d378d16af278717e841aad4072c0ecc516948", "submitter": { "id": 216, "url": "https://patchwork.libcamera.org/api/people/216/?format=api", "name": "Barnabás Pőcze", "email": "barnabas.pocze@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/27475/mbox/", "series": [ { "id": 6075, "url": "https://patchwork.libcamera.org/api/series/6075/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=6075", "date": "2026-07-23T15:42:43", "name": "ipa: libipa: agc rework", "version": 2, "mbox": "https://patchwork.libcamera.org/series/6075/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/27475/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/27475/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A9E1BC3301\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 23 Jul 2026 15:44:11 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 310EB67F02;\n\tThu, 23 Jul 2026 17:44:11 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5EC0367ED9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Jul 2026 17:43:37 +0200 (CEST)", "from pb-laptop.local (185.182.215.156.nat.pool.zt.hu\n\t[185.182.215.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7863B2C0B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Jul 2026 17:42:36 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"C0V/KkGh\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1784821356;\n\tbh=1pcctY2ceejlO861K6gJI0E7BflUz4f0bBMItBsIl/c=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=C0V/KkGhHQy78cQbZ3wcwtgmDHEmqUPKeewnEYcxnUlp7ZpZS35WC9VgxxviSz4WJ\n\t3sw3X+FncSFtkfm4fOsp3sEXKTGVfSOafkmPK2Y8Dc0Hk+TYTW6m13OEk8FKdq75O6\n\t7Ed9tfqSCOwjpxA2c02SXZvpE3rz/WOcTbijXJeE=", "From": "=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Subject": "[RFC PATCH v2 27/43] ipa: mali-c55: agc: Port to `AgcAlgorithm`", "Date": "Thu, 23 Jul 2026 17:43:10 +0200", "Message-ID": "<20260723154327.1357866-28-barnabas.pocze@ideasonboard.com>", "X-Mailer": "git-send-email 2.55.0", "In-Reply-To": "<20260723154327.1357866-1-barnabas.pocze@ideasonboard.com>", "References": "<20260723154327.1357866-1-barnabas.pocze@ideasonboard.com>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "Use the `AgcAlgorithm` class to implement the mali-c55 agc algorithm.\n\nCloses: https://gitlab.freedesktop.org/camera/libcamera/-/work_items/262\nSigned-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n---\n src/ipa/mali-c55/algorithms/agc.cpp | 130 ++++++----------------\n src/ipa/mali-c55/algorithms/agc.h | 4 +-\n src/ipa/mali-c55/ipa_context.h | 35 +++---\n src/ipa/mali-c55/mali-c55.cpp | 160 +++++-----------------------\n 4 files changed, 75 insertions(+), 254 deletions(-)", "diff": "diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp\nindex 821f43e9fd..8af4df53e7 100644\n--- a/src/ipa/mali-c55/algorithms/agc.cpp\n+++ b/src/ipa/mali-c55/algorithms/agc.cpp\n@@ -123,12 +123,19 @@ Agc::Agc()\n \n int Agc::init(IPAContext &context, const ValueNode &tuningData)\n {\n-\tint ret = agc_.parseTuningData(tuningData);\n+\tint ret = agc_.init(tuningData);\n \tif (ret)\n \t\treturn ret;\n \n-\tcontext.ctrlMap[&controls::AeEnable] = ControlInfo(false, true);\n-\tcontext.ctrlMap.merge(agc_.controls());\n+\tret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n+\t\t.sensor = context.camHelper.get(),\n+\t\t.sensorInfo = context.sensorInfo,\n+\t\t.sensorControls = context.sensorControls,\n+\t\t.ctrlMap = context.ctrlMap,\n+\t\t.autoAllowed = true, // \\todo if not raw?\n+\t});\n+\tif (ret)\n+\t\treturn ret;\n \n \treturn 0;\n }\n@@ -140,79 +147,24 @@ int Agc::configure(IPAContext &context,\n \tif (ret)\n \t\treturn ret;\n \n-\t/*\n-\t * Defaults; we use whatever the sensor's default exposure is and the\n-\t * minimum analogue gain. AEGC is _active_ by default.\n-\t */\n-\tcontext.activeState.agc.autoEnabled = true;\n-\tcontext.activeState.agc.automatic.sensorGain = context.configuration.agc.minAnalogueGain;\n-\tcontext.activeState.agc.automatic.exposure = context.configuration.agc.defaultExposure;\n-\tcontext.activeState.agc.manual.sensorGain = context.configuration.agc.minAnalogueGain;\n-\tcontext.activeState.agc.manual.exposure = context.configuration.agc.defaultExposure;\n-\tcontext.activeState.agc.constraintMode = agc_.constraintModes().begin()->first;\n-\tcontext.activeState.agc.exposureMode = agc_.exposureModeHelpers().begin()->first;\n-\n-\t/* \\todo Run this again when FrameDurationLimits is passed in */\n-\tagc_.setLimits(context.configuration.agc.minShutterSpeed,\n-\t\t context.configuration.agc.maxShutterSpeed,\n-\t\t context.configuration.agc.minAnalogueGain,\n-\t\t context.configuration.agc.maxAnalogueGain,\n-\t\t {});\n-\n-\tagc_.resetFrameCount();\n+\tret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n+\t\t.sensor = context.camHelper.get(),\n+\t\t.sensorInfo = context.sensorInfo,\n+\t\t.sensorControls = context.sensorControls,\n+\t\t.ctrlMap = context.ctrlMap,\n+\t\t.autoAllowed = true, // \\todo if not raw?\n+\t});\n+\tif (ret)\n+\t\treturn ret;\n \n \treturn 0;\n }\n \n-void Agc::queueRequest(IPAContext &context, const uint32_t frame,\n-\t\t [[maybe_unused]] IPAFrameContext &frameContext,\n+void Agc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n+\t\t IPAFrameContext &frameContext,\n \t\t const ControlList &controls)\n {\n-\tauto &agc = context.activeState.agc;\n-\n-\tconst auto &constraintMode = controls.get(controls::AeConstraintMode);\n-\tagc.constraintMode = constraintMode.value_or(agc.constraintMode);\n-\n-\tconst auto &exposureMode = controls.get(controls::AeExposureMode);\n-\tagc.exposureMode = exposureMode.value_or(agc.exposureMode);\n-\n-\tconst auto &agcEnable = controls.get(controls::AeEnable);\n-\tif (agcEnable && *agcEnable != agc.autoEnabled) {\n-\t\tagc.autoEnabled = *agcEnable;\n-\n-\t\tLOG(MaliC55Agc, Info)\n-\t\t\t<< (agc.autoEnabled ? \"Enabling\" : \"Disabling\")\n-\t\t\t<< \" AGC\";\n-\t}\n-\n-\t/*\n-\t * If the automatic exposure and gain is enabled we have no further work\n-\t * to do here...\n-\t */\n-\tif (agc.autoEnabled)\n-\t\treturn;\n-\n-\t/*\n-\t * ...otherwise we need to look for exposure and gain controls and use\n-\t * those to set the activeState.\n-\t */\n-\tconst auto &exposure = controls.get(controls::ExposureTime);\n-\tif (exposure) {\n-\t\tagc.manual.exposure = *exposure * 1.0us / context.configuration.sensor.lineDuration;\n-\n-\t\tLOG(MaliC55Agc, Debug)\n-\t\t\t<< \"Exposure set to \" << agc.manual.exposure\n-\t\t\t<< \" on request sequence \" << frame;\n-\t}\n-\n-\tconst auto &analogueGain = controls.get(controls::AnalogueGain);\n-\tif (analogueGain) {\n-\t\tagc.manual.sensorGain = *analogueGain;\n-\n-\t\tLOG(MaliC55Agc, Debug)\n-\t\t\t<< \"Analogue gain set to \" << agc.manual.sensorGain\n-\t\t\t<< \" on request sequence \" << frame;\n-\t}\n+\tagc_.queueRequest(context.configuration.agc, context.activeState.agc, frameContext.agc, controls);\n }\n \n void Agc::fillParamsBuffer(MaliC55Params *params, enum MaliC55Blocks type)\n@@ -265,9 +217,11 @@ void Agc::fillWeightsArrayBuffer(MaliC55Params *params, const enum MaliC55Blocks\n \tstd::fill(weights.begin(), weights.end(), 1);\n }\n \n-void Agc::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame,\n-\t\t [[maybe_unused]] IPAFrameContext &frameContext, MaliC55Params *params)\n+void Agc::prepare(IPAContext &context, const uint32_t frame,\n+\t\t IPAFrameContext &frameContext, MaliC55Params *params)\n {\n+\tagc_.prepare(context.activeState.agc, frameContext.agc);\n+\n \tif (frame > 0)\n \t\treturn;\n \n@@ -310,9 +264,6 @@ void Agc::process(IPAContext &context,\n \t\t const mali_c55_stats_buffer *stats,\n \t\t [[maybe_unused]] ControlList &metadata)\n {\n-\tIPASessionConfiguration &configuration = context.configuration;\n-\tIPAActiveState &activeState = context.activeState;\n-\n \tif (!stats) {\n \t\tLOG(MaliC55Agc, Error) << \"No statistics buffer passed to Agc\";\n \t\treturn;\n@@ -323,33 +274,12 @@ void Agc::process(IPAContext &context,\n \t\t\t\t\t\t\t statistics_.gHist.interQuantileMean(0, 1),\n \t\t\t\t\t\t\t statistics_.bHist.interQuantileMean(0, 1) } });\n \n-\t/*\n-\t * The Agc algorithm needs to know the effective exposure value that was\n-\t * applied to the sensor when the statistics were collected.\n-\t */\n-\tuint32_t exposure = frameContext.agc.exposure;\n-\tdouble analogueGain = frameContext.agc.sensorGain;\n-\tutils::Duration currentShutter = exposure * configuration.sensor.lineDuration;\n-\tutils::Duration effectiveExposureValue = currentShutter * analogueGain;\n-\n-\tconst auto &newEv = agc_.calculateNewEv({\n+\tagc_.process(context.configuration.agc, context.activeState.agc, frameContext.agc, {{\n \t\t.traits = AgcTraits(statistics_),\n \t\t.yHist = statistics_.yHist,\n-\t\t.effectiveExposureValue = effectiveExposureValue,\n-\t\t.constraintModeIndex = activeState.agc.constraintMode,\n-\t\t.exposureModeIndex = activeState.agc.exposureMode,\n-\t});\n-\n-\tLOG(MaliC55Agc, Debug)\n-\t\t<< \"Divided up shutter, analogue gain and digital gain are \"\n-\t\t<< newEv.exposureTime << \", \" << newEv.analogueGain << \" and \" << newEv.digitalGain;\n-\n-\tactiveState.agc.automatic.exposure = newEv.exposureTime / configuration.sensor.lineDuration;\n-\tactiveState.agc.automatic.sensorGain = newEv.analogueGain;\n-\n-\tmetadata.set(controls::ExposureTime, currentShutter.get<std::micro>());\n-\tmetadata.set(controls::AnalogueGain, frameContext.agc.sensorGain);\n-\tmetadata.set(controls::ColourTemperature, context.activeState.agc.temperatureK);\n+\t\t.exposure = frameContext.sensor.exposure,\n+\t\t.gain = frameContext.sensor.gain,\n+\t}}, metadata);\n }\n \n REGISTER_IPA_ALGORITHM(Agc, \"Agc\")\ndiff --git a/src/ipa/mali-c55/algorithms/agc.h b/src/ipa/mali-c55/algorithms/agc.h\nindex ec7fe28c17..809a57c53a 100644\n--- a/src/ipa/mali-c55/algorithms/agc.h\n+++ b/src/ipa/mali-c55/algorithms/agc.h\n@@ -11,7 +11,7 @@\n \n #include \"libcamera/internal/bayer_format.h\"\n \n-#include \"libipa/agc_mean_luminance.h\"\n+#include \"libipa/agc.h\"\n #include \"libipa/histogram.h\"\n \n #include \"algorithm.h\"\n@@ -68,7 +68,7 @@ private:\n \tvoid fillWeightsArrayBuffer(MaliC55Params *params, enum MaliC55Blocks type);\n \n \tAgcStatistics statistics_;\n-\tAgcMeanLuminance agc_;\n+\tAgcAlgorithm agc_;\n };\n \n } /* namespace ipa::mali_c55::algorithms */\ndiff --git a/src/ipa/mali-c55/ipa_context.h b/src/ipa/mali-c55/ipa_context.h\nindex 075d6f66ef..9dd947d7fc 100644\n--- a/src/ipa/mali-c55/ipa_context.h\n+++ b/src/ipa/mali-c55/ipa_context.h\n@@ -12,6 +12,8 @@\n \n #include \"libcamera/internal/bayer_format.h\"\n \n+#include <libipa/agc.h>\n+#include <libipa/camera_sensor_helper.h>\n #include <libipa/fc_queue.h>\n \n #include \"libipa/fixedpoint.h\"\n@@ -21,34 +23,17 @@ namespace libcamera {\n namespace ipa::mali_c55 {\n \n struct IPASessionConfiguration {\n-\tstruct {\n-\t\tutils::Duration minShutterSpeed;\n-\t\tutils::Duration maxShutterSpeed;\n-\t\tuint32_t defaultExposure;\n-\t\tdouble minAnalogueGain;\n-\t\tdouble maxAnalogueGain;\n+\tstruct Agc : agc::Session {\n \t} agc;\n \n \tstruct {\n \t\tBayerFormat::Order bayerOrder;\n-\t\tutils::Duration lineDuration;\n \t\tuint32_t blackLevel;\n \t} sensor;\n };\n \n struct IPAActiveState {\n-\tstruct {\n-\t\tstruct {\n-\t\t\tuint32_t exposure;\n-\t\t\tdouble sensorGain;\n-\t\t} automatic;\n-\t\tstruct {\n-\t\t\tuint32_t exposure;\n-\t\t\tdouble sensorGain;\n-\t\t} manual;\n-\t\tbool autoEnabled;\n-\t\tuint32_t constraintMode;\n-\t\tuint32_t exposureMode;\n+\tstruct Agc : agc::ActiveState {\n \t\tuint32_t temperatureK;\n \t} agc;\n \n@@ -59,10 +44,13 @@ struct IPAActiveState {\n };\n \n struct IPAFrameContext : public FrameContext {\n+\tstruct Agc : agc::FrameContext {\n+\t} agc;\n+\n \tstruct {\n \t\tuint32_t exposure;\n-\t\tdouble sensorGain;\n-\t} agc;\n+\t\tdouble gain;\n+\t} sensor;\n \n \tstruct {\n \t\tUQ<4, 8> rGain;\n@@ -77,10 +65,15 @@ struct IPAContext {\n \t}\n \n \tIPASessionConfiguration configuration;\n+\tIPACameraSensorInfo sensorInfo;\n \tIPAActiveState activeState;\n \n \tFCQueue<IPAFrameContext> frameContexts;\n \n+\tControlInfoMap sensorControls;\n+\n+\tstd::unique_ptr<CameraSensorHelper> camHelper;\n+\n \tControlInfoMap::Map ctrlMap;\n };\n \ndiff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp\nindex 65e5297766..c0c2c83dca 100644\n--- a/src/ipa/mali-c55/mali-c55.cpp\n+++ b/src/ipa/mali-c55/mali-c55.cpp\n@@ -5,7 +5,6 @@\n * Mali-C55 ISP image processing algorithms\n */\n \n-#include <array>\n #include <map>\n #include <string.h>\n #include <vector>\n@@ -66,21 +65,11 @@ protected:\n \tstd::string logPrefix() const override;\n \n private:\n-\tvoid updateSessionConfiguration(const IPACameraSensorInfo &info,\n-\t\t\t\t\tconst ControlInfoMap &sensorControls,\n-\t\t\t\t\tBayerFormat::Order bayerOrder);\n-\tvoid updateControls(const IPACameraSensorInfo &sensorInfo,\n-\t\t\t const ControlInfoMap &sensorControls,\n-\t\t\t ControlInfoMap *ipaControls);\n-\tvoid setControls();\n+\tvoid updateControls(ControlInfoMap *ipaControls);\n+\tvoid setControls(const IPAFrameContext &frameContext);\n \n \tstd::map<unsigned int, MappedFrameBuffer> buffers_;\n \n-\tControlInfoMap sensorControls_;\n-\n-\t/* Interface to the Camera Helper */\n-\tstd::unique_ptr<CameraSensorHelper> camHelper_;\n-\n \t/* Local parameter storage */\n \tstruct IPAContext context_;\n };\n@@ -102,8 +91,8 @@ std::string IPAMaliC55::logPrefix() const\n int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig,\n \t\t ControlInfoMap *ipaControls)\n {\n-\tcamHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel);\n-\tif (!camHelper_) {\n+\tcontext_.camHelper = CameraSensorHelperFactoryBase::create(settings.sensorModel);\n+\tif (!context_.camHelper) {\n \t\tLOG(IPAMaliC55, Error)\n \t\t\t<< \"Failed to create camera sensor helper for \"\n \t\t\t<< settings.sensorModel;\n@@ -129,31 +118,23 @@ int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig\n \t\treturn -EINVAL;\n \t}\n \n+\tcontext_.sensorControls = ipaConfig.sensorControls;\n+\tcontext_.sensorInfo = ipaConfig.sensorInfo;\n+\n \tint ret = createAlgorithms(context_, (*data)[\"algorithms\"]);\n \tif (ret)\n \t\treturn ret;\n \n-\tupdateControls(ipaConfig.sensorInfo, ipaConfig.sensorControls, ipaControls);\n+\tupdateControls(ipaControls);\n \n \treturn 0;\n }\n \n-void IPAMaliC55::setControls()\n+void IPAMaliC55::setControls(const IPAFrameContext &frameContext)\n {\n-\tIPAActiveState &activeState = context_.activeState;\n-\tuint32_t exposure;\n-\tdouble gain;\n-\n-\tif (activeState.agc.autoEnabled) {\n-\t\texposure = activeState.agc.automatic.exposure;\n-\t\tgain = activeState.agc.automatic.sensorGain;\n-\t} else {\n-\t\texposure = activeState.agc.manual.exposure;\n-\t\tgain = activeState.agc.manual.sensorGain;\n-\t}\n+\tControlList ctrls(context_.sensorControls);\n+\tagc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc.exposure, frameContext.agc.gain);\n \n-\tControlList ctrls(sensorControls_);\n-\tagc::prepareControls(ctrls, camHelper_.get(), exposure, gain);\n \tsetSensorControls.emit(ctrls);\n }\n \n@@ -167,111 +148,19 @@ void IPAMaliC55::stop()\n \tcontext_.frameContexts.clear();\n }\n \n-void IPAMaliC55::updateSessionConfiguration(const IPACameraSensorInfo &info,\n-\t\t\t\t\t const ControlInfoMap &sensorControls,\n-\t\t\t\t\t BayerFormat::Order bayerOrder)\n-{\n-\tcontext_.configuration.sensor.bayerOrder = bayerOrder;\n-\n-\tconst ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;\n-\tint32_t minExposure = v4l2Exposure.min().get<int32_t>();\n-\tint32_t maxExposure = v4l2Exposure.max().get<int32_t>();\n-\tint32_t defExposure = v4l2Exposure.def().get<int32_t>();\n-\n-\tconst ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;\n-\tint32_t minGain = v4l2Gain.min().get<int32_t>();\n-\tint32_t maxGain = v4l2Gain.max().get<int32_t>();\n-\n-\t/*\n-\t * When the AGC computes the new exposure values for a frame, it needs\n-\t * to know the limits for shutter speed and analogue gain.\n-\t * As it depends on the sensor, update it with the controls.\n-\t *\n-\t * \\todo take VBLANK into account for maximum shutter speed\n-\t */\n-\tcontext_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;\n-\tcontext_.configuration.agc.minShutterSpeed = minExposure * context_.configuration.sensor.lineDuration;\n-\tcontext_.configuration.agc.maxShutterSpeed = maxExposure * context_.configuration.sensor.lineDuration;\n-\tcontext_.configuration.agc.defaultExposure = defExposure;\n-\tcontext_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain);\n-\tcontext_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain);\n-\n-\tif (camHelper_->blackLevel().has_value()) {\n-\t\t/*\n-\t\t * The black level from CameraSensorHelper is a 16-bit value.\n-\t\t * The Mali-C55 ISP expects 20-bit settings, so we shift it to\n-\t\t * the appropriate width\n-\t\t */\n-\t\tcontext_.configuration.sensor.blackLevel =\n-\t\t\tcamHelper_->blackLevel().value() << 4;\n-\t}\n-}\n-\n-void IPAMaliC55::updateControls(const IPACameraSensorInfo &sensorInfo,\n-\t\t\t\tconst ControlInfoMap &sensorControls,\n-\t\t\t\tControlInfoMap *ipaControls)\n+void IPAMaliC55::updateControls(ControlInfoMap *ipaControls)\n {\n \tControlInfoMap::Map ctrlMap;\n \n-\t/*\n-\t * Compute the frame duration limits.\n-\t *\n-\t * The frame length is computed assuming a fixed line length combined\n-\t * with the vertical frame sizes.\n-\t */\n-\tconst ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;\n-\tuint32_t hblank = v4l2HBlank.def().get<int32_t>();\n-\tuint32_t lineLength = sensorInfo.outputSize.width + hblank;\n-\n-\tconst ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;\n-\tstd::array<uint32_t, 3> frameHeights{\n-\t\tv4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,\n-\t\tv4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,\n-\t\tv4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.height,\n-\t};\n-\n-\tstd::array<int64_t, 3> frameDurations;\n-\tfor (unsigned int i = 0; i < frameHeights.size(); ++i) {\n-\t\tuint64_t frameSize = lineLength * frameHeights[i];\n-\t\tframeDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);\n-\t}\n-\n-\tctrlMap[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],\n-\t\t\t\t\t\t\t frameDurations[1],\n-\t\t\t\t\t\t\t Span<const int64_t, 2>{ { frameDurations[2], frameDurations[2] } });\n-\n-\t/*\n-\t * Compute exposure time limits from the V4L2_CID_EXPOSURE control\n-\t * limits and the line duration.\n-\t */\n-\tdouble lineDuration = sensorInfo.minLineLength / sensorInfo.pixelRate;\n-\n-\tconst ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;\n-\tint32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;\n-\tint32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;\n-\tint32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;\n-\tctrlMap[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure, defExposure);\n-\n-\t/* Compute the analogue gain limits. */\n-\tconst ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;\n-\tfloat minGain = camHelper_->gain(v4l2Gain.min().get<int32_t>());\n-\tfloat maxGain = camHelper_->gain(v4l2Gain.max().get<int32_t>());\n-\tfloat defGain = camHelper_->gain(v4l2Gain.def().get<int32_t>());\n-\tctrlMap[&controls::AnalogueGain] = ControlInfo(minGain, maxGain, defGain);\n-\n-\t/*\n-\t * Merge in any controls that we support either statically or from the\n-\t * algorithms.\n-\t */\n \tctrlMap.insert(context_.ctrlMap.begin(), context_.ctrlMap.end());\n-\n \t*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);\n }\n \n int IPAMaliC55::configure(const IPAConfigInfo &ipaConfig, uint8_t bayerOrder,\n \t\t\t ControlInfoMap *ipaControls)\n {\n-\tsensorControls_ = ipaConfig.sensorControls;\n+\tcontext_.sensorControls = ipaConfig.sensorControls;\n+\tcontext_.sensorInfo = ipaConfig.sensorInfo;\n \n \t/* Clear the IPA context before the streaming session. */\n \tcontext_.configuration = {};\n@@ -280,9 +169,16 @@ int IPAMaliC55::configure(const IPAConfigInfo &ipaConfig, uint8_t bayerOrder,\n \n \tconst IPACameraSensorInfo &info = ipaConfig.sensorInfo;\n \n-\tupdateSessionConfiguration(info, ipaConfig.sensorControls,\n-\t\t\t\t static_cast<BayerFormat::Order>(bayerOrder));\n-\tupdateControls(info, ipaConfig.sensorControls, ipaControls);\n+\tcontext_.configuration.sensor.bayerOrder = static_cast<BayerFormat::Order>(bayerOrder);\n+\n+\tif (auto bl = context_.camHelper->blackLevel()) {\n+\t\t/*\n+\t\t * The black level from CameraSensorHelper is a 16-bit value.\n+\t\t * The Mali-C55 ISP expects 20-bit settings, so we shift it to\n+\t\t * the appropriate width\n+\t\t */\n+\t\tcontext_.configuration.sensor.blackLevel = *bl << 4;\n+\t}\n \n \tfor (const auto &a : algorithms()) {\n \t\tAlgorithm *algo = static_cast<Algorithm *>(a.get());\n@@ -292,6 +188,8 @@ int IPAMaliC55::configure(const IPAConfigInfo &ipaConfig, uint8_t bayerOrder,\n \t\t\treturn ret;\n \t}\n \n+\tupdateControls(ipaControls);\n+\n \treturn 0;\n }\n \n@@ -351,8 +249,8 @@ void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,\n \tstats = reinterpret_cast<mali_c55_stats_buffer *>(\n \t\tbuffers_.at(bufferId).planes()[0].data());\n \n-\tstd::tie(frameContext.agc.exposure, frameContext.agc.sensorGain)\n-\t\t= agc::extractControls(sensorControls, camHelper_.get());\n+\tstd::tie(frameContext.sensor.exposure, frameContext.sensor.gain)\n+\t\t= agc::extractControls(sensorControls, context_.camHelper.get());\n \n \tControlList metadata(controls::controls);\n \n@@ -362,7 +260,7 @@ void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,\n \t\talgo->process(context_, request, frameContext, stats, metadata);\n \t}\n \n-\tsetControls();\n+\tsetControls(frameContext);\n \n \tstatsProcessed.emit(request, metadata);\n }\n", "prefixes": [ "RFC", "v2", "27/43" ] }