Patch Detail
Show a patch.
GET /api/patches/27464/?format=api
{ "id": 27464, "url": "https://patchwork.libcamera.org/api/patches/27464/?format=api", "web_url": "https://patchwork.libcamera.org/patch/27464/", "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-15-barnabas.pocze@ideasonboard.com>", "date": "2026-07-23T15:42:57", "name": "[RFC,v2,14/43] ipa: libipa: agc_mean_luminance: calculateNewEv(): Collect params", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "ae956217221cbb0076c6aa5e38aa7239feace6d3", "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/27464/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/27464/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/27464/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 8F16FC3301\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 23 Jul 2026 15:43:54 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 16F2267F20;\n\tThu, 23 Jul 2026 17:43:54 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 012FA67EC7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Jul 2026 17:43:33 +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 221CA1C37\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Jul 2026 17:42:33 +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=\"JgtLzCLC\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1784821353;\n\tbh=0guaNOTTnXwSaZhS+tOKH3iYPgTi94jBtetlKj0Ptcw=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=JgtLzCLCt8geo4TIbtBYLFQFumZcSjFCjinIzP9SDdxuY1ZFWYn0dm/30tw3MvABS\n\tLbN28ei/gaNdrYdyKjxge7RViT+CBdlNBjYMoxisaFwjKBTD6tgAGxAsbn+7RqnmzC\n\tMSbB483K6AED4TDIf+hGPSZumW0RKZMM5MuTCCg0=", "From": "=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Subject": "[RFC PATCH v2 14/43] ipa: libipa: agc_mean_luminance:\n\tcalculateNewEv(): Collect params", "Date": "Thu, 23 Jul 2026 17:42:57 +0200", "Message-ID": "<20260723154327.1357866-15-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": "Add a new type that contains all parameters for the `calculateNewEv()`\nfunction.\n\nSigned-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n---\n src/ipa/ipu3/algorithms/agc.cpp | 28 +++++++++--------\n src/ipa/libipa/agc_mean_luminance.cpp | 44 ++++++++++++++++-----------\n src/ipa/libipa/agc_mean_luminance.h | 12 ++++++--\n src/ipa/mali-c55/algorithms/agc.cpp | 12 +++++---\n src/ipa/rkisp1/algorithms/agc.cpp | 18 ++++++-----\n 5 files changed, 68 insertions(+), 46 deletions(-)", "diff": "diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\nindex a919418d69..ac5b6e7513 100644\n--- a/src/ipa/ipu3/algorithms/agc.cpp\n+++ b/src/ipa/ipu3/algorithms/agc.cpp\n@@ -236,22 +236,24 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n \t\t\t\t * frameContext.sensor.exposure;\n \tdouble analogueGain = frameContext.sensor.gain;\n \tutils::Duration effectiveExposureValue = exposureTime * analogueGain;\n-\tAgcTraits agcTraits{\n-\t\trgbTriples_,\n-\t\t{{\n-\t\t\tcontext.activeState.awb.gains.red,\n-\t\t\tcontext.activeState.awb.gains.blue,\n-\t\t\tcontext.activeState.awb.gains.green,\n-\t\t}},\n-\t\tbdsGrid_,\n-\t};\n \n \tutils::Duration newExposureTime;\n \tdouble aGain, qGain, dGain;\n-\tstd::tie(newExposureTime, aGain, qGain, dGain) =\n-\t\tagc_.calculateNewEv(context.activeState.agc.constraintMode,\n-\t\t\t\t context.activeState.agc.exposureMode, hist,\n-\t\t\t\t effectiveExposureValue, agcTraits);\n+\tstd::tie(newExposureTime, aGain, qGain, dGain) = agc_.calculateNewEv({\n+\t\t.traits = AgcTraits{\n+\t\t\trgbTriples_,\n+\t\t\t{{\n+\t\t\t\tcontext.activeState.awb.gains.red,\n+\t\t\t\tcontext.activeState.awb.gains.blue,\n+\t\t\t\tcontext.activeState.awb.gains.green,\n+\t\t\t}},\n+\t\t\tbdsGrid_,\n+\t\t},\n+\t\t.yHist = hist,\n+\t\t.effectiveExposureValue = effectiveExposureValue,\n+\t\t.constraintModeIndex = context.activeState.agc.constraintMode,\n+\t\t.exposureModeIndex = context.activeState.agc.exposureMode,\n+\t});\n \n \tLOG(IPU3Agc, Debug)\n \t\t<< \"Divided up exposure time, analogue gain and digital gain are \"\ndiff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp\nindex 31636159a2..083d67eb70 100644\n--- a/src/ipa/libipa/agc_mean_luminance.cpp\n+++ b/src/ipa/libipa/agc_mean_luminance.cpp\n@@ -648,16 +648,30 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue)\n \treturn filteredExposure_;\n }\n \n+/**\n+ * \\struct AgcMeanLuminance::Params\n+ * \\brief Collection of parameters for the mean luminance AGC algorithm\n+ *\n+ * \\var AgcMeanLuminance::Params::traits\n+ * \\brief The traits object implementing the necessary functions\n+ *\n+ * \\var AgcMeanLuminance::Params::yHist\n+ * \\brief A histogram from the ISP statistics to use in constraining the calculated gain\n+ *\n+ * \\var AgcMeanLuminance::Params::effectiveExposureValue\n+ * \\brief The EV applied to the frame from which the statistics in use derive\n+ *\n+ * \\var AgcMeanLuminance::Params::constraintModeIndex\n+ * \\brief The index of the constraint mode to use\n+ *\n+ * \\var AgcMeanLuminance::Params::exposureModeIndex\n+ * \\brief The index of the exposure mode to use\n+ */\n+\n /**\n * \\brief Calculate the new exposure value and split it between exposure time\n * and gain\n- * \\param[in] constraintModeIndex The index of the current constraint mode\n- * \\param[in] exposureModeIndex The index of the current exposure mode\n- * \\param[in] yHist A Histogram from the ISP statistics to use in constraining\n- * the calculated gain\n- * \\param[in] effectiveExposureValue The EV applied to the frame from which the\n- * statistics in use derive\n- * \\param[in] traits The traits object implementing the necessary functions\n+ * \\param[in] params The set of parameters for the calculation\n *\n * Calculate a new exposure value to try to obtain the target. The calculated\n * exposure value is filtered to prevent rapid changes from frame to frame, and\n@@ -667,20 +681,16 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue)\n * gain\n */\n std::tuple<utils::Duration, double, double, double>\n-AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,\n-\t\t\t\t uint32_t exposureModeIndex,\n-\t\t\t\t const Histogram &yHist,\n-\t\t\t\t utils::Duration effectiveExposureValue,\n-\t\t\t\t const Traits &traits)\n+AgcMeanLuminance::calculateNewEv(const Params ¶ms)\n {\n \t/*\n \t * The pipeline handler should validate that we have received an allowed\n \t * value for AeExposureMode.\n \t */\n \tExposureModeHelper &exposureModeHelper =\n-\t\texposureModeHelpers_.at(exposureModeIndex);\n+\t\texposureModeHelpers_.at(params.exposureModeIndex);\n \n-\tif (effectiveExposureValue == 0s) {\n+\tif (params.effectiveExposureValue == 0s) {\n \t\tLOG(AgcMeanLuminance, Error)\n \t\t\t<< \"Effective exposure value is 0. This is a bug in AGC \"\n \t\t\t \"and must be fixed for proper operation.\";\n@@ -692,8 +702,8 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,\n \t\treturn exposureModeHelper.splitExposure(10ms);\n \t}\n \n-\tdouble gain = estimateInitialGain(traits);\n-\tgain = constraintClampGain(constraintModeIndex, yHist, gain);\n+\tdouble gain = estimateInitialGain(params.traits);\n+\tgain = constraintClampGain(params.constraintModeIndex, params.yHist, gain);\n \n \t/*\n \t * We don't check whether we're already close to the target, because\n@@ -702,7 +712,7 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,\n \t * pass through the splitExposure() function.\n \t */\n \n-\tutils::Duration newExposureValue = effectiveExposureValue * gain;\n+\tutils::Duration newExposureValue = params.effectiveExposureValue * gain;\n \n \t/*\n \t * We filter the exposure value to make sure changes are not too jarring\ndiff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h\nindex d5425cd20b..eb9d6fec2b 100644\n--- a/src/ipa/libipa/agc_mean_luminance.h\n+++ b/src/ipa/libipa/agc_mean_luminance.h\n@@ -79,10 +79,16 @@ public:\n \t\treturn controls_;\n \t}\n \n+\tstruct Params {\n+\t\tconst Traits &traits;\n+\t\tconst Histogram &yHist;\n+\t\tutils::Duration effectiveExposureValue;\n+\t\tuint32_t constraintModeIndex;\n+\t\tuint32_t exposureModeIndex;\n+\t};\n+\n \tstd::tuple<utils::Duration, double, double, double>\n-\tcalculateNewEv(uint32_t constraintModeIndex, uint32_t exposureModeIndex,\n-\t\t const Histogram &yHist, utils::Duration effectiveExposureValue,\n-\t\t const Traits &traits);\n+\tcalculateNewEv(const Params ¶ms);\n \n \tdouble effectiveYTarget() const;\n \ndiff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp\nindex 29b7c66159..fb97b87c6e 100644\n--- a/src/ipa/mali-c55/algorithms/agc.cpp\n+++ b/src/ipa/mali-c55/algorithms/agc.cpp\n@@ -331,14 +331,16 @@ void Agc::process(IPAContext &context,\n \tdouble analogueGain = frameContext.agc.sensorGain;\n \tutils::Duration currentShutter = exposure * configuration.sensor.lineDuration;\n \tutils::Duration effectiveExposureValue = currentShutter * analogueGain;\n-\tAgcTraits agcTraits(statistics_);\n \n \tutils::Duration shutterTime;\n \tdouble aGain, qGain, dGain;\n-\tstd::tie(shutterTime, aGain, qGain, dGain) =\n-\t\tagc_.calculateNewEv(activeState.agc.constraintMode,\n-\t\t\t\t activeState.agc.exposureMode, statistics_.yHist,\n-\t\t\t\t effectiveExposureValue, agcTraits);\n+\tstd::tie(shutterTime, aGain, qGain, dGain) = agc_.calculateNewEv({\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 \"\ndiff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 129f5be2a5..8b4bcbd71b 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -716,20 +716,22 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n \t/* The lower 4 bits are fractional and meant to be discarded. */\n \tHistogram hist({ params->hist.hist_bins, context.hw.numHistogramBins },\n \t\t [](uint32_t x) { return x >> 4; });\n-\tAgcTraits agcTraits{\n-\t\t{ params->ae.exp_mean, context.hw.numAeCells },\n-\t\tmeteringModes_.at(frameContext.agc.meteringMode),\n-\t};\n \n \tagc_.setExposureCompensation(pow(2.0, frameContext.agc.exposureValue));\n \tagc_.setLux(frameContext.lux.lux);\n \n \tutils::Duration newExposureTime;\n \tdouble aGain, qGain, dGain;\n-\tstd::tie(newExposureTime, aGain, qGain, dGain) =\n-\t\tagc_.calculateNewEv(frameContext.agc.constraintMode,\n-\t\t\t\t frameContext.agc.exposureMode,\n-\t\t\t\t hist, effectiveExposureValue, agcTraits);\n+\tstd::tie(newExposureTime, aGain, qGain, dGain) = agc_.calculateNewEv({\n+\t\t.traits = AgcTraits{\n+\t\t\t{ params->ae.exp_mean, context.hw.numAeCells },\n+\t\t\tmeteringModes_.at(frameContext.agc.meteringMode),\n+\t\t},\n+\t\t.yHist = hist,\n+\t\t.effectiveExposureValue = effectiveExposureValue,\n+\t\t.constraintModeIndex = frameContext.agc.constraintMode,\n+\t\t.exposureModeIndex = frameContext.agc.exposureMode,\n+\t});\n \n \tLOG(RkISP1Agc, Debug)\n \t\t<< \"Divided up exposure time, analogue gain, quantization gain\"\n", "prefixes": [ "RFC", "v2", "14/43" ] }