Patch Detail
Show a patch.
GET /api/1.1/patches/20230/?format=api
{ "id": 20230, "url": "https://patchwork.libcamera.org/api/1.1/patches/20230/?format=api", "web_url": "https://patchwork.libcamera.org/patch/20230/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/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": "<20240607080330.2667994-2-paul.elder@ideasonboard.com>", "date": "2024-06-07T08:03:28", "name": "[v5,1/3] ipa: rkisp1: agc: Read histogram weights from tuning file", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "6f64a48e2fc219d8c0598ea046562f7e92344dab", "submitter": { "id": 17, "url": "https://patchwork.libcamera.org/api/1.1/people/17/?format=api", "name": "Paul Elder", "email": "paul.elder@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/20230/mbox/", "series": [ { "id": 4372, "url": "https://patchwork.libcamera.org/api/1.1/series/4372/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4372", "date": "2024-06-07T08:03:27", "name": "ipa: rkisp1: Improve AGC (plumbing)", "version": 5, "mbox": "https://patchwork.libcamera.org/series/4372/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/20230/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/20230/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 08115C31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 7 Jun 2024 08:03:55 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AB10665455;\n\tFri, 7 Jun 2024 10:03: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 688E66545F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 7 Jun 2024 10:03:51 +0200 (CEST)", "from neptunite.hamster-moth.ts.net\n\t(h175-177-049-156.catv02.itscom.jp [175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 282A1230;\n\tFri, 7 Jun 2024 10:03:39 +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=\"ndRq3Mlm\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1717747421;\n\tbh=WH7B0l7+0zfEg37TgUSKkXOhnrLZuKGLw8e/+jgVeJA=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=ndRq3Mlm95VPtGGnv3PVGmciDJKZx6hTmrKCJSjuhNaxw7VW08n49+VqYIR1qXFkd\n\tpwv5ojPKfzCI0+MzkTWkbpDO2Za2sjUHkdgtZ9FxXmHpBcJlUmhmMHZoB7ofQl2TJZ\n\tnFCoGo09mCPUlAQebq1QLYCZLb42Cuq2jJTFrk4A=", "From": "Paul Elder <paul.elder@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Paul Elder <paul.elder@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tDaniel Scally <dan.scally@ideasonboard.com>", "Subject": "[PATCH v5 1/3] ipa: rkisp1: agc: Read histogram weights from tuning\n\tfile", "Date": "Fri, 7 Jun 2024 17:03:28 +0900", "Message-Id": "<20240607080330.2667994-2-paul.elder@ideasonboard.com>", "X-Mailer": "git-send-email 2.39.2", "In-Reply-To": "<20240607080330.2667994-1-paul.elder@ideasonboard.com>", "References": "<20240607080330.2667994-1-paul.elder@ideasonboard.com>", "MIME-Version": "1.0", "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 support to the rkisp1 AGC to read histogram weights from the tuning\nfile. As controls for selecting the metering mode are not yet supported,\nfor now hardcode the matrix metering mode, which is the same as what the\nAGC previously hardcoded.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\nReviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\nReviewed-by: Daniel Scally <dan.scally@ideasonboard.com>\n\n---\nNo change in v5\n\nChanges in v4:\n- add debug print when parsing the yaml file\n\nChanges in v3:\n- support the new tuning file layout for interpolated matrices\n- support both v10 and v12\n\nChanges in v2:\n- add default metering mode if none are read successfully from the\n tuning file\n- compute the predivider instead of using a table\n---\n src/ipa/rkisp1/algorithms/agc.cpp | 94 ++++++++++++++++++++++++++++++-\n src/ipa/rkisp1/algorithms/agc.h | 6 ++\n 2 files changed, 97 insertions(+), 3 deletions(-)", "diff": "diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 50e0690fe..3bbafd978 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -17,6 +17,8 @@\n #include <libcamera/control_ids.h>\n #include <libcamera/ipa/core_ipa_interface.h>\n \n+#include \"libcamera/internal/yaml_parser.h\"\n+\n #include \"libipa/histogram.h\"\n \n /**\n@@ -36,6 +38,76 @@ namespace ipa::rkisp1::algorithms {\n \n LOG_DEFINE_CATEGORY(RkISP1Agc)\n \n+int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData,\n+\t\t\t const char *prop)\n+{\n+\tconst YamlObject &yamlMeteringModes = tuningData[prop];\n+\tif (!yamlMeteringModes.isDictionary()) {\n+\t\tLOG(RkISP1Agc, Error)\n+\t\t\t<< \"'\" << prop << \"' parameter not found in tuning file\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (const auto &[key, value] : yamlMeteringModes.asDict()) {\n+\t\tif (controls::AeMeteringModeNameValueMap.find(key) ==\n+\t\t controls::AeMeteringModeNameValueMap.end()) {\n+\t\t\tLOG(RkISP1Agc, Warning)\n+\t\t\t\t<< \"Skipping unknown metering mode '\" << key << \"'\";\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tfor (const auto &[version, matrix] : value.asDict()) {\n+\t\t\tstd::vector<uint8_t> weights =\n+\t\t\t\tmatrix.getList<uint8_t>().value_or(std::vector<uint8_t>{});\n+\t\t\tif (weights.size() != context.hw->numHistogramWeights)\n+\t\t\t\tcontinue;\n+\n+\t\t\tLOG(RkISP1Agc, Debug)\n+\t\t\t\t<< \"Matched metering matrix mode \"\n+\t\t\t\t<< key << \", version \" << version;\n+\n+\t\t\tmeteringModes_[controls::AeMeteringModeNameValueMap.at(key)] = weights;\n+\t\t}\n+\t}\n+\n+\tif (meteringModes_.empty()) {\n+\t\tint32_t meteringModeId = controls::AeMeteringModeNameValueMap.at(\"MeteringMatrix\");\n+\t\tstd::vector<uint8_t> weights(context.hw->numHistogramWeights, 1);\n+\n+\t\tmeteringModes_[meteringModeId] = weights;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+uint8_t Agc::predivider(Size &size)\n+{\n+\t/*\n+\t * The maximum number of pixels that could potentially be in one bin is\n+\t * if all the pixels of the image are in it, multiplied by 3 for the\n+\t * three color channels. The counter for each bin is 16 bits wide, so\n+\t * `factor` thus contains the number of times we'd wrap around. This is\n+\t * obviously the number of pixels that we need to skip to make sure\n+\t * that we don't wrap around, but we compute the square root of it\n+\t * instead, as the skip that we need to program is for both the x and y\n+\t * directions.\n+\t *\n+\t * There's a bit of extra rounding math to make sure the rounding goes\n+\t * the correct direction so that the square of the step is big enough\n+\t * to encompass the `factor` number of pixels that we need to skip.\n+\t */\n+\tdouble factor = size.width * size.height * 3 / 65535.0;\n+\tdouble root = std::sqrt(factor);\n+\tuint8_t ret;\n+\n+\tif (std::pow(std::floor(root), 2) + 0.01 < factor)\n+\t\tret = static_cast<uint8_t>(std::ceil(root));\n+\telse\n+\t\tret = static_cast<uint8_t>(std::floor(root));\n+\n+\treturn std::clamp<uint8_t>(ret, 3, 127);\n+}\n+\n Agc::Agc()\n {\n \tsupportsRaw_ = true;\n@@ -59,6 +131,10 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData)\n \tif (ret)\n \t\treturn ret;\n \n+\tret = parseMeteringModes(context, tuningData, \"AeMeteringMode\");\n+\tif (ret)\n+\t\treturn ret;\n+\n \tcontext.ctrlMap.merge(controls());\n \n \treturn 0;\n@@ -160,6 +236,7 @@ void Agc::prepare(IPAContext &context, const uint32_t frame,\n \t\tframeContext.agc.gain = context.activeState.agc.automatic.gain;\n \t}\n \n+\t/* \\todo Remove this when we can set the below with controls */\n \tif (frame > 0)\n \t\treturn;\n \n@@ -178,14 +255,25 @@ void Agc::prepare(IPAContext &context, const uint32_t frame,\n \tparams->meas.hst_config.meas_window = context.configuration.agc.measureWindow;\n \t/* Produce the luminance histogram. */\n \tparams->meas.hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM;\n+\n \t/* Set an average weighted histogram. */\n \tSpan<uint8_t> weights{\n \t\tparams->meas.hst_config.hist_weight,\n \t\tcontext.hw->numHistogramWeights\n \t};\n-\tstd::fill(weights.begin(), weights.end(), 1);\n-\t/* Step size can't be less than 3. */\n-\tparams->meas.hst_config.histogram_predivider = 4;\n+\t/* \\todo Get this from control */\n+\tstd::vector<uint8_t> &modeWeights = meteringModes_.at(controls::MeteringMatrix);\n+\tstd::copy(modeWeights.begin(), modeWeights.end(), weights.begin());\n+\n+\tstd::stringstream str;\n+\tstr << \"Histogram weights : \";\n+\tfor (size_t i = 0; i < context.hw->numHistogramWeights; i++)\n+\t\tstr << (int)params->meas.hst_config.hist_weight[i] << \" \";\n+\tLOG(RkISP1Agc, Debug) << str.str();\n+\n+\t/* \\todo Add a control for this? */\n+\tparams->meas.hst_config.histogram_predivider =\n+\t\tpredivider(context.configuration.sensor.size);\n \n \t/* Update the configuration for histogram. */\n \tparams->module_cfg_update |= RKISP1_CIF_ISP_MODULE_HST;\ndiff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h\nindex 04b3247e1..4ab56ead5 100644\n--- a/src/ipa/rkisp1/algorithms/agc.h\n+++ b/src/ipa/rkisp1/algorithms/agc.h\n@@ -44,11 +44,17 @@ public:\n \t\t ControlList &metadata) override;\n \n private:\n+\tint parseMeteringModes(IPAContext &context, const YamlObject &tuningData,\n+\t\t\t const char *prop);\n+\tuint8_t predivider(Size &size);\n+\n \tvoid fillMetadata(IPAContext &context, IPAFrameContext &frameContext,\n \t\t\t ControlList &metadata);\n \tdouble estimateLuminance(double gain) const override;\n \n \tSpan<const uint8_t> expMeans_;\n+\n+\tstd::map<int32_t, std::vector<uint8_t>> meteringModes_;\n };\n \n } /* namespace ipa::rkisp1::algorithms */\n", "prefixes": [ "v5", "1/3" ] }