[{"id":31291,"web_url":"https://patchwork.libcamera.org/comment/31291/","msgid":"<172692336014.2374548.13436357637822329976@ping.linuxembedded.co.uk>","date":"2024-09-21T12:56:00","subject":"Re: [PATCH v3 9/9] ipa: rkisp1: Add polynomial LSC loader","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Stefan Klug (2024-09-20 14:39:24)\n> Add a loader that is capable of loading polynomial coefficients from the\n> tuning files. The polynomial is sampled at load time to reduce the\n> computational overhead at runtime.\n> \n> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> \n> ---\n> Changes in v3:\n> - Fixes bug with lsc table beeing rotated by 90 degrees\n\nThat was just a minor bug right ;-)\n\n> - Added documentation on sizesListToPositions()\n> - Refactored loader selection code\n> ---\n>  src/ipa/rkisp1/algorithms/lsc.cpp | 147 +++++++++++++++++++++++++++++-\n>  1 file changed, 145 insertions(+), 2 deletions(-)\n> \n> diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp\n> index 44c97f0e1a10..e210b32ff380 100644\n> --- a/src/ipa/rkisp1/algorithms/lsc.cpp\n> +++ b/src/ipa/rkisp1/algorithms/lsc.cpp\n> @@ -16,6 +16,7 @@\n>  \n>  #include \"libcamera/internal/yaml_parser.h\"\n>  \n> +#include \"libipa/lsc_polynomial.h\"\n>  #include \"linux/rkisp1-config.h\"\n>  \n>  /**\n> @@ -70,6 +71,132 @@ namespace ipa::rkisp1::algorithms {\n>  \n>  LOG_DEFINE_CATEGORY(RkISP1Lsc)\n>  \n> +class LscPolynomialLoader\n> +{\n> +public:\n> +       LscPolynomialLoader(const Size &sensorSize,\n> +                           const Rectangle &cropRectangle,\n> +                           const std::vector<double> &xSizes,\n> +                           const std::vector<double> &ySizes)\n> +               : sensorSize_(sensorSize),\n> +                 cropRectangle_(cropRectangle),\n> +                 xSizes_(xSizes),\n> +                 ySizes_(ySizes)\n> +       {\n> +       }\n> +\n> +       int parseLscData(const YamlObject &yamlSets,\n> +                        std::map<unsigned int, LensShadingCorrection::Components> &lscData)\n> +       {\n> +               const auto &sets = yamlSets.asList();\n> +               for (const auto &yamlSet : sets) {\n> +                       std::optional<LscPolynomial> pr, pgr, pgb, pb;\n> +                       uint32_t ct = yamlSet[\"ct\"].get<uint32_t>(0);\n> +\n> +                       if (lscData.count(ct)) {\n> +                               LOG(RkISP1Lsc, Error)\n> +                                       << \"Multiple sets found for \"\n> +                                       << \"color temperature \" << ct;\n> +                               return -EINVAL;\n> +                       }\n> +\n> +                       LensShadingCorrection::Components &set = lscData[ct];\n> +                       pr = yamlSet[\"r\"].get<LscPolynomial>();\n> +                       pgr = yamlSet[\"gr\"].get<LscPolynomial>();\n> +                       pgb = yamlSet[\"gb\"].get<LscPolynomial>();\n> +                       pb = yamlSet[\"b\"].get<LscPolynomial>();\n> +\n> +                       if (!(pr || pgr || pgb || pb)) {\n> +                               LOG(RkISP1Lsc, Error)\n> +                                       << \"Failed to parse polynomial for \"\n> +                                       << \"colour temperature \" << ct;\n> +                               return -EINVAL;\n> +                       }\n> +\n> +                       set.ct = ct;\n> +                       pr->setReferenceImageSize(sensorSize_);\n> +                       pgr->setReferenceImageSize(sensorSize_);\n> +                       pgb->setReferenceImageSize(sensorSize_);\n> +                       pb->setReferenceImageSize(sensorSize_);\n> +                       set.r = samplePolynomial(*pr);\n> +                       set.gr = samplePolynomial(*pgr);\n> +                       set.gb = samplePolynomial(*pgb);\n> +                       set.b = samplePolynomial(*pb);\n> +               }\n> +\n> +               if (lscData.empty()) {\n> +                       LOG(RkISP1Lsc, Error) << \"Failed to load any sets\";\n> +                       return -EINVAL;\n> +               }\n> +\n> +               return 0;\n> +       }\n> +\n> +private:\n> +       /*\n> +        * The lsc grid has custom spacing defined on half the range (see\n> +        * parseSizes() for details). For easier handling this function converts\n> +        * the spaces vector to positions and mirrors them. E.g.:\n> +        *\n> +        * input:   | 0.2 | 0.3 |\n> +        * output: 0.0   0.2   0.5   0.8   1.0\n> +        */\n> +       std::vector<double> sizesListToPositions(const std::vector<double> &sizes)\n> +       {\n> +               const int half = sizes.size();\n> +               std::vector<double> res(half * 2 + 1);\n> +               double x = 0.0;\n> +\n> +               res[half] = 0.5;\n> +               for (int i = 1; i <= half; i++) {\n> +                       x += sizes[half - i];\n> +                       res[half - i] = 0.5 - x;\n> +                       res[half + i] = 0.5 + x;\n> +               }\n> +\n> +               return res;\n> +       }\n> +\n> +       std::vector<uint16_t> samplePolynomial(const LscPolynomial &poly)\n> +       {\n> +               constexpr int k = RKISP1_CIF_ISP_LSC_SAMPLES_MAX;\n> +\n> +               double m = poly.getM();\n> +               double x0 = cropRectangle_.x / m;\n> +               double y0 = cropRectangle_.y / m;\n> +               double w = cropRectangle_.width / m;\n> +               double h = cropRectangle_.height / m;\n> +               std::vector<uint16_t> res;\n> +\n> +               assert(xSizes_.size() * 2 + 1 == k);\n> +               assert(ySizes_.size() * 2 + 1 == k);\n> +\n> +               res.reserve(k * k);\n> +\n> +               std::vector<double> xPos(sizesListToPositions(xSizes_));\n> +               std::vector<double> yPos(sizesListToPositions(ySizes_));\n> +\n> +               for (int y = 0; y < k; y++) {\n> +                       for (int x = 0; x < k; x++) {\n> +                               double xp = x0 + xPos[x] * w;\n> +                               double yp = y0 + yPos[y] * h;\n> +                               int v = static_cast<int>(\n> +                                       poly.sampleAtNormalizedPixelPos(xp, yp) *\n> +                                       1024);\n> +\n> +                               v = std::min(std::max(v, 1024), 4095);\n\n\nIt's not immediately obvious why we're using values of 1024 and 4095\nhere ... or why we're clamping between v (above 1024) and 4095. I can\nmake guesses, but acomment above would be helpful to any reader to clear\nit up.\n\n> +                               res.push_back(v);\n> +                       }\n> +               }\n> +               return res;\n> +       }\n> +\n> +       Size sensorSize_;\n> +       Rectangle cropRectangle_;\n> +       const std::vector<double> &xSizes_;\n> +       const std::vector<double> &ySizes_;\n> +};\n> +\n>  class LscTableLoader\n>  {\n>  public:\n> @@ -192,8 +319,24 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n>  \n>         std::map<unsigned int, Components> lscData;\n>         int res = 0;\n> -       auto loader = LscTableLoader();\n> -       res = loader.parseLscData(yamlSets, lscData);\n> +       std::string type = tuningData[\"type\"].get<std::string>(\"table\");\n> +       if (type == \"table\") {\n> +               LOG(RkISP1Lsc, Debug) << \"Loading tabular LSC data.\";\n> +               auto loader = LscTableLoader();\n> +               res = loader.parseLscData(yamlSets, lscData);\n> +       } else if (type == \"polynomial\") {\n> +               LOG(RkISP1Lsc, Debug) << \"Loading polynomial LSC data.\";\n> +               auto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize,\n> +                                                 context.sensorInfo.analogCrop,\n> +                                                 xSize_,\n> +                                                 ySize_);\n> +               res = loader.parseLscData(yamlSets, lscData);\n> +       } else {\n> +               LOG(RkISP1Lsc, Error) << \"Unsupported LSC data type '\"\n> +                                     << type << \"'\";\n\nI like the syntax and expressiveness on the default values here - so we\nknow type is set to something else in this block.\n\nWith comments above handled anyway you see fit...\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> +               res = -EINVAL;\n> +       }\n> +\n>         if (res)\n>                 return res;\n>  \n> -- \n> 2.43.0\n>","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 E24DEC3257\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 21 Sep 2024 12:56:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E067C634FC;\n\tSat, 21 Sep 2024 14:56:03 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 187DE618E4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 21 Sep 2024 14:56:03 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 59D4A890;\n\tSat, 21 Sep 2024 14:54:38 +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=\"sk8FJmHJ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1726923278;\n\tbh=t4j5vh9TqiMDeopBDM/AxzDqF4bKVJDJ6uxklA8hris=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=sk8FJmHJXLU79rL3dFx5MKawKhqMAGiHMgkae9r0mmSE5ILJ6x/HDXdlCnWU4oHgv\n\tmWHRaYpzje+/SboC7soAF6OHkoCx4zF4o0K6FhWcH7/dZx2cibPn+to7j2FtkfjgBw\n\tZg0aQnvIjmaE/hjIc/M5YfLKoItqHoTuzxwWPCfg=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240920133941.90629-10-stefan.klug@ideasonboard.com>","References":"<20240920133941.90629-1-stefan.klug@ideasonboard.com>\n\t<20240920133941.90629-10-stefan.klug@ideasonboard.com>","Subject":"Re: [PATCH v3 9/9] ipa: rkisp1: Add polynomial LSC loader","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Stefan Klug <stefan.klug@ideasonboard.com>","To":"Stefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Sat, 21 Sep 2024 13:56:00 +0100","Message-ID":"<172692336014.2374548.13436357637822329976@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>"}},{"id":31320,"web_url":"https://patchwork.libcamera.org/comment/31320/","msgid":"<20240923201741.GA7165@pendragon.ideasonboard.com>","date":"2024-09-23T20:17:41","subject":"Re: [PATCH v3 9/9] ipa: rkisp1: Add polynomial LSC loader","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Stefan,\n\nThank you for the patch.\n\nOn Fri, Sep 20, 2024 at 03:39:24PM +0200, Stefan Klug wrote:\n> Add a loader that is capable of loading polynomial coefficients from the\n> tuning files. The polynomial is sampled at load time to reduce the\n> computational overhead at runtime.\n> \n> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> \n> ---\n> Changes in v3:\n> - Fixes bug with lsc table beeing rotated by 90 degrees\n> - Added documentation on sizesListToPositions()\n> - Refactored loader selection code\n> ---\n>  src/ipa/rkisp1/algorithms/lsc.cpp | 147 +++++++++++++++++++++++++++++-\n>  1 file changed, 145 insertions(+), 2 deletions(-)\n> \n> diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp\n> index 44c97f0e1a10..e210b32ff380 100644\n> --- a/src/ipa/rkisp1/algorithms/lsc.cpp\n> +++ b/src/ipa/rkisp1/algorithms/lsc.cpp\n> @@ -16,6 +16,7 @@\n>  \n>  #include \"libcamera/internal/yaml_parser.h\"\n>  \n> +#include \"libipa/lsc_polynomial.h\"\n>  #include \"linux/rkisp1-config.h\"\n>  \n>  /**\n> @@ -70,6 +71,132 @@ namespace ipa::rkisp1::algorithms {\n>  \n>  LOG_DEFINE_CATEGORY(RkISP1Lsc)\n>  \n> +class LscPolynomialLoader\n> +{\n> +public:\n> +\tLscPolynomialLoader(const Size &sensorSize,\n> +\t\t\t    const Rectangle &cropRectangle,\n> +\t\t\t    const std::vector<double> &xSizes,\n> +\t\t\t    const std::vector<double> &ySizes)\n> +\t\t: sensorSize_(sensorSize),\n> +\t\t  cropRectangle_(cropRectangle),\n> +\t\t  xSizes_(xSizes),\n> +\t\t  ySizes_(ySizes)\n> +\t{\n> +\t}\n> +\n> +\tint parseLscData(const YamlObject &yamlSets,\n> +\t\t\t std::map<unsigned int, LensShadingCorrection::Components> &lscData)\n> +\t{\n> +\t\tconst auto &sets = yamlSets.asList();\n> +\t\tfor (const auto &yamlSet : sets) {\n> +\t\t\tstd::optional<LscPolynomial> pr, pgr, pgb, pb;\n> +\t\t\tuint32_t ct = yamlSet[\"ct\"].get<uint32_t>(0);\n> +\n> +\t\t\tif (lscData.count(ct)) {\n> +\t\t\t\tLOG(RkISP1Lsc, Error)\n> +\t\t\t\t\t<< \"Multiple sets found for \"\n> +\t\t\t\t\t<< \"color temperature \" << ct;\n> +\t\t\t\treturn -EINVAL;\n> +\t\t\t}\n> +\n> +\t\t\tLensShadingCorrection::Components &set = lscData[ct];\n> +\t\t\tpr = yamlSet[\"r\"].get<LscPolynomial>();\n> +\t\t\tpgr = yamlSet[\"gr\"].get<LscPolynomial>();\n> +\t\t\tpgb = yamlSet[\"gb\"].get<LscPolynomial>();\n> +\t\t\tpb = yamlSet[\"b\"].get<LscPolynomial>();\n> +\n> +\t\t\tif (!(pr || pgr || pgb || pb)) {\n> +\t\t\t\tLOG(RkISP1Lsc, Error)\n> +\t\t\t\t\t<< \"Failed to parse polynomial for \"\n> +\t\t\t\t\t<< \"colour temperature \" << ct;\n> +\t\t\t\treturn -EINVAL;\n> +\t\t\t}\n> +\n> +\t\t\tset.ct = ct;\n> +\t\t\tpr->setReferenceImageSize(sensorSize_);\n> +\t\t\tpgr->setReferenceImageSize(sensorSize_);\n> +\t\t\tpgb->setReferenceImageSize(sensorSize_);\n> +\t\t\tpb->setReferenceImageSize(sensorSize_);\n> +\t\t\tset.r = samplePolynomial(*pr);\n> +\t\t\tset.gr = samplePolynomial(*pgr);\n> +\t\t\tset.gb = samplePolynomial(*pgb);\n> +\t\t\tset.b = samplePolynomial(*pb);\n> +\t\t}\n> +\n> +\t\tif (lscData.empty()) {\n> +\t\t\tLOG(RkISP1Lsc, Error) << \"Failed to load any sets\";\n> +\t\t\treturn -EINVAL;\n> +\t\t}\n> +\n> +\t\treturn 0;\n> +\t}\n\nDon't make the functions inline.\n\nclass LscPolynomialLoader\n{\npublic:\n\tLscPolynomialLoader(const Size &sensorSize,\n\t\t\t    const Rectangle &cropRectangle,\n\t\t\t    const std::vector<double> &xSizes,\n\t\t\t    const std::vector<double> &ySizes);\n\t\n\tint parseLscData(const YamlObject &yamlSets,\n\t\t\t std::map<unsigned int, LensShadingCorrection::Components> &lscData);\n\n...\n};\n\nLscPolynomialLoader::LscPolynomialLoader(const Size &sensorSize,\n\t\t\t\t\t const Rectangle &cropRectangle,\n\t\t\t\t\t const std::vector<double> &xSizes,\n\t\t\t\t\t const std::vector<double> &ySizes)\n{\n\t...\n}\n\n...\n\nThat will reduce indentation.\n\n> +\n> +private:\n> +\t/*\n> +\t * The lsc grid has custom spacing defined on half the range (see\n\ns/lsc/LSC/\n\n> +\t * parseSizes() for details). For easier handling this function converts\n> +\t * the spaces vector to positions and mirrors them. E.g.:\n> +\t *\n> +\t * input:   | 0.2 | 0.3 |\n> +\t * output: 0.0   0.2   0.5   0.8   1.0\n> +\t */\n> +\tstd::vector<double> sizesListToPositions(const std::vector<double> &sizes)\n> +\t{\n> +\t\tconst int half = sizes.size();\n> +\t\tstd::vector<double> res(half * 2 + 1);\n\ns/res/pos/ (or positions)\n\n\"res\" (I assume it stands for result) is a bit like \"tmp\", it doesn't\ndescribe very well what the variable contains.\n\nSame below.\n\n> +\t\tdouble x = 0.0;\n> +\n> +\t\tres[half] = 0.5;\n> +\t\tfor (int i = 1; i <= half; i++) {\n> +\t\t\tx += sizes[half - i];\n> +\t\t\tres[half - i] = 0.5 - x;\n> +\t\t\tres[half + i] = 0.5 + x;\n> +\t\t}\n> +\n> +\t\treturn res;\n> +\t}\n> +\n> +\tstd::vector<uint16_t> samplePolynomial(const LscPolynomial &poly)\n> +\t{\n> +\t\tconstexpr int k = RKISP1_CIF_ISP_LSC_SAMPLES_MAX;\n> +\n> +\t\tdouble m = poly.getM();\n> +\t\tdouble x0 = cropRectangle_.x / m;\n> +\t\tdouble y0 = cropRectangle_.y / m;\n> +\t\tdouble w = cropRectangle_.width / m;\n> +\t\tdouble h = cropRectangle_.height / m;\n> +\t\tstd::vector<uint16_t> res;\n> +\n> +\t\tassert(xSizes_.size() * 2 + 1 == k);\n> +\t\tassert(ySizes_.size() * 2 + 1 == k);\n\nI think the belongs to the constructor. But better, you shouldn't assert\nlike this. If the tuning file contains a wrong size, you'll crash. This\nshould be handled gracefully, with a check in\nLensShadingCorrection::init, and the 'k' constant above moved to the\nbeginning of the file.\n\nFurthermore, does this class actually depend on the number of samples\nthe hardware expects ?\n\n> +\n> +\t\tres.reserve(k * k);\n> +\n> +\t\tstd::vector<double> xPos(sizesListToPositions(xSizes_));\n> +\t\tstd::vector<double> yPos(sizesListToPositions(ySizes_));\n> +\n> +\t\tfor (int y = 0; y < k; y++) {\n> +\t\t\tfor (int x = 0; x < k; x++) {\n> +\t\t\t\tdouble xp = x0 + xPos[x] * w;\n> +\t\t\t\tdouble yp = y0 + yPos[y] * h;\n> +\t\t\t\tint v = static_cast<int>(\n> +\t\t\t\t\tpoly.sampleAtNormalizedPixelPos(xp, yp) *\n> +\t\t\t\t\t1024);\n> +\n> +\t\t\t\tv = std::min(std::max(v, 1024), 4095);\n> +\t\t\t\tres.push_back(v);\n> +\t\t\t}\n> +\t\t}\n> +\t\treturn res;\n> +\t}\n> +\n> +\tSize sensorSize_;\n> +\tRectangle cropRectangle_;\n> +\tconst std::vector<double> &xSizes_;\n> +\tconst std::vector<double> &ySizes_;\n> +};\n> +\n>  class LscTableLoader\n>  {\n>  public:\n> @@ -192,8 +319,24 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,\n>  \n>  \tstd::map<unsigned int, Components> lscData;\n>  \tint res = 0;\n\nFor error codes we use \"ret\".\n\n> -\tauto loader = LscTableLoader();\n> -\tres = loader.parseLscData(yamlSets, lscData);\n> +\tstd::string type = tuningData[\"type\"].get<std::string>(\"table\");\n> +\tif (type == \"table\") {\n> +\t\tLOG(RkISP1Lsc, Debug) << \"Loading tabular LSC data.\";\n> +\t\tauto loader = LscTableLoader();\n> +\t\tres = loader.parseLscData(yamlSets, lscData);\n> +\t} else if (type == \"polynomial\") {\n> +\t\tLOG(RkISP1Lsc, Debug) << \"Loading polynomial LSC data.\";\n> +\t\tauto loader = LscPolynomialLoader(context.sensorInfo.activeAreaSize,\n> +\t\t\t\t\t\t  context.sensorInfo.analogCrop,\n> +\t\t\t\t\t\t  xSize_,\n> +\t\t\t\t\t\t  ySize_);\n> +\t\tres = loader.parseLscData(yamlSets, lscData);\n> +\t} else {\n> +\t\tLOG(RkISP1Lsc, Error) << \"Unsupported LSC data type '\"\n> +\t\t\t\t      << type << \"'\";\n> +\t\tres = -EINVAL;\n> +\t}\n> +\n>  \tif (res)\n>  \t\treturn res;\n>","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 12B71C0F1B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 23 Sep 2024 20:18:17 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 215286350B;\n\tMon, 23 Sep 2024 22:18:16 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 590526037E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 23 Sep 2024 22:18:14 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BA62863D;\n\tMon, 23 Sep 2024 22:16:47 +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=\"Xdhtbmmd\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1727122608;\n\tbh=vfDDtdmdtGg5E6Nrf9QfUIz5F8R4oP9Gojev7GxsXUk=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=XdhtbmmdPe1QmG5ebUMuh35jS0Bsm4OniaFBL50SfmIegjQAUXloaa7gTw+TRYJ7x\n\tHujRxGmdEQBEHZ+PvtjaWqeeio13aRChL7096pNPFq/Fqf//odF5ckEtyVVyE/HbD1\n\t9t0ok3uRkOBy3oJHf/m7gkQSAdTy/LeP31fZ2KI8=","Date":"Mon, 23 Sep 2024 23:17:41 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v3 9/9] ipa: rkisp1: Add polynomial LSC loader","Message-ID":"<20240923201741.GA7165@pendragon.ideasonboard.com>","References":"<20240920133941.90629-1-stefan.klug@ideasonboard.com>\n\t<20240920133941.90629-10-stefan.klug@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20240920133941.90629-10-stefan.klug@ideasonboard.com>","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>"}}]