[{"id":23894,"web_url":"https://patchwork.libcamera.org/comment/23894/","msgid":"<YtCl+L8WUj7IQ36J@pendragon.ideasonboard.com>","date":"2022-07-14T23:25:44","subject":"Re: [libcamera-devel] [PATCH v5 5/8] ipa: raspberrypi: Introduce\n\tversion 2.0 format for the camera tuning file","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nThank you for the patch.\n\nOn Thu, Jul 14, 2022 at 04:24:06PM +0100, Naushir Patuck via libcamera-devel wrote:\n> The existing tuning file format (version 1.0) requires the controller algorithms\n> to run in the same order as listied in the JSON structure. The JSON\n\ns/listied/listed/\n\n> specification does not mandate any such ordering, but the Boost JSON parser\n> would maintain this order.\n> \n> In order to remove this reliance on the parser to provide ordering, introduce a\n> new version 2.0 format for the camera tuning file. In this version, the\n> algorithms are specified in a top level list node (\"algorithms\"), which does\n> require strict ordering of the elements. Additionally, a \"version\" node is added\n> to distinguish between the version 1.0 and 2.0 formats. The absence of the\n> \"version\" node implies version 1.0.\n> \n> Update the controller to support either version of the tuning file by looking\n> at the version node. CreateAlgorithm member function to now load and configure\n> each algorithm. Additionally, make CreateAlgorithm a private member, it does not\n> get called externally.\n> \n> If a version 1.0 format tuning file is used, throw a warning message indicating\n> it will be soon deprecated.\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n\nSounds like a good plan.\n\nA question on the versioning scheme though. In the rkisp1 IPA modules,\nwe use (for now) a single integer for the version. Do you see use cases\nfor a semantic versioning scheme (x.y or x.y.z) ? I'm not implying there\nare none, but we haven't really considered the versioning scheme yet,\nand it seems like a good time to discuss this.\n\nI assume major new versions of tuning files will not be backward\ncompatible with previous ones, so if an IPA module supports version\n[min, max], any tuning file with a version number outside that range\nwould be rejected.\n\nI can also imagine changes to the tuning file format that would be\nbackward-compatible (mostly adding new data, when the implementation of\nthe algorithms can use default values if the data isn't present). In\nthis case, could an IPA module benefit from knowing in advance, through\na minor version number, that additional data may be present, or would it\nonly use the major version number only and just use default values for\nabsent data ? I'm not sure if the minor version number would be useful\nfor the IPA module, but I could also imagine it may be useful to other\ntools, such as tuning tools, to know what to expect.\n\n> ---\n>  src/ipa/raspberrypi/controller/controller.cpp | 42 +++++++++++++------\n>  src/ipa/raspberrypi/controller/controller.hpp |  4 +-\n>  2 files changed, 33 insertions(+), 13 deletions(-)\n> \n> diff --git a/src/ipa/raspberrypi/controller/controller.cpp b/src/ipa/raspberrypi/controller/controller.cpp\n> index 67d650ef0c1b..9a2a3fb01793 100644\n> --- a/src/ipa/raspberrypi/controller/controller.cpp\n> +++ b/src/ipa/raspberrypi/controller/controller.cpp\n> @@ -42,22 +42,40 @@ void Controller::Read(char const *filename)\n>  \t}\n>  \n>  \tstd::unique_ptr<YamlObject> root = YamlParser::parse(file);\n> -\n> -\tfor (auto const &[key, value] : root->asDict()) {\n> -\t\tAlgorithm *algo = CreateAlgorithm(key.c_str());\n> -\t\tif (algo) {\n> -\t\t\talgo->Read(value);\n> -\t\t\talgorithms_.push_back(AlgorithmPtr(algo));\n> -\t\t} else\n> -\t\t\tLOG(RPiController, Warning)\n> -\t\t\t\t<< \"No algorithm found for \\\"\" << key << \"\\\"\";\n> +\tdouble version = (*root)[\"version\"].get<double>(1.0);\n\nInteresting idea to consider it as a duoble.\n\n> +\tif (version < 2.0) {\n> +\t\tLOG(RPiController, Warning)\n> +\t\t\t<< \"This format of the tuning file will be deprecated soon!\"\n> +\t\t\t<< \" Please use the convert_tuning.py utility to update to version 2.0.\";\n> +\t\tfor (auto const &[key, value] : root->asDict()) {\n> +\t\t\tif (!key.compare(\"version\"))\n> +\t\t\t\tcontinue;\n\nI think you can drop this check, as v1 tuning files don't specify the\nversion.\n\n> +\t\t\tCreateAlgorithm(key, value);\n> +\t\t}\n> +\t} else {\n\n\t} else if (version < 3.0) {\n\t\t...\n\t} else {\n\t\t/* error */\n\t}\n\nBut maybe a\n\n\tswitch (std::floor(version)) {\n\t\t...\n\t}\n\nwould be more readable ? Uo to you.\n\n> +\t\tif (!root->contains(\"algorithms\")) {\n> +\t\t\tLOG(RPiController, Fatal)\n> +\t\t\t\t<< \"Tuning file \" << filename\n> +\t\t\t\t<< \" does not have an \\\"algorithms\\\" list!\";\n> +\t\t\treturn;\n> +\t\t}\n> +\t\tfor (auto const &rootAlgo : (*root)[\"algorithms\"].asList())\n> +\t\t\tfor (auto const &[key, value] : rootAlgo.asDict())\n\nI'm tempted to create a asOrderedDict() function to make this easier.\n\n> +\t\t\t\tCreateAlgorithm(key, value);\n>  \t}\n>  }\n>  \n> -Algorithm *Controller::CreateAlgorithm(char const *name)\n> +void Controller::CreateAlgorithm(const std::string &name, const YamlObject &params)\n>  {\n> -\tauto it = GetAlgorithms().find(std::string(name));\n> -\treturn it != GetAlgorithms().end() ? (*it->second)(this) : nullptr;\n> +\tauto it = GetAlgorithms().find(name);\n> +\tif (it == GetAlgorithms().end()) {\n> +\t\tLOG(RPiController, Warning)\n> +\t\t\t<< \"No algorithm found for \\\"\" << name << \"\\\"\";\n> +\t\treturn;\n> +\t}\n> +\tAlgorithm *algo = (*it->second)(this);\n> +\talgo->Read(params);\n> +\talgorithms_.push_back(AlgorithmPtr(algo));\n>  }\n>  \n>  void Controller::Initialise()\n> diff --git a/src/ipa/raspberrypi/controller/controller.hpp b/src/ipa/raspberrypi/controller/controller.hpp\n> index 3b50ae770d11..9091deac5feb 100644\n> --- a/src/ipa/raspberrypi/controller/controller.hpp\n> +++ b/src/ipa/raspberrypi/controller/controller.hpp\n> @@ -15,6 +15,8 @@\n>  \n>  #include <linux/bcm2835-isp.h>\n>  \n> +#include \"libcamera/internal/yaml_parser.h\"\n\nYou can also forward-declare YamlObject, up to you.\n\n> +\n>  #include \"camera_mode.h\"\n>  #include \"device_status.h\"\n>  #include \"metadata.hpp\"\n> @@ -36,7 +38,6 @@ public:\n>  \tController();\n>  \tController(char const *json_filename);\n>  \t~Controller();\n> -\tAlgorithm *CreateAlgorithm(char const *name);\n>  \tvoid Read(char const *filename);\n>  \tvoid Initialise();\n>  \tvoid SwitchMode(CameraMode const &camera_mode, Metadata *metadata);\n> @@ -46,6 +47,7 @@ public:\n>  \tAlgorithm *GetAlgorithm(std::string const &name) const;\n>  \n>  protected:\n> +\tvoid CreateAlgorithm(const std::string &name, const libcamera::YamlObject &params);\n>  \tMetadata global_metadata_;\n>  \tstd::vector<AlgorithmPtr> algorithms_;\n>  \tbool switch_mode_called_;","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 AE67CBE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 14 Jul 2022 23:26:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0960463312;\n\tFri, 15 Jul 2022 01:26:18 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4618960489\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 15 Jul 2022 01:26:16 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C394D9DA;\n\tFri, 15 Jul 2022 01:26:15 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1657841178;\n\tbh=fBPgqItpZcPvbAKmQzxiOTrEXJXnEuC29y+Auha4NaI=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=VUyPpc32jeHdC89vDBTV3bRXvrfweD9fkz5YJemc9FSo717ai6VS0GKoRcjBEqVF2\n\tBFsb0Zv3eMOg03e7W/lFTN3cDjZXNbXsR6iSZHYon22BkkYsAz+IjVDv4GUkIELir+\n\tI2DaLSjzA+tBXi/MfCUE+EhFrsIwArLl4KoUi6qQjRUZ5CoilHt7sFiPiRM2QcszB+\n\tT25kXDpKz0x3G+VE77+smUnD9YTaBdgcA7LwbnIOJPj5WE5EZfdtMcf/X3IgG/f/cR\n\tIaB9MW4yReCLF86BKYdokUUPGl/bR2ioMSMTWoiaIh40NS4VgWbcwjGIk5LKqXwfOA\n\tFM1iotBfpCghA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1657841176;\n\tbh=fBPgqItpZcPvbAKmQzxiOTrEXJXnEuC29y+Auha4NaI=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=X5SZTOoL00bDtbuxX1K7TMJ+Lsk1VHvwyKqLqY6xgTRdIY37zylyeo/HAJd3WJDJV\n\tdpqBTPHTW8mGZR1ZqvoUrE39SHbb3HsmzjbTMkrlz5weME2vcJGus9xMdMfpI0uX9/\n\tlSFiKzUJYeLEMCPNLytJpauH/AC+rg33kShXlmdE="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"X5SZTOoL\"; dkim-atps=neutral","Date":"Fri, 15 Jul 2022 02:25:44 +0300","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<YtCl+L8WUj7IQ36J@pendragon.ideasonboard.com>","References":"<20220714152409.9780-1-naush@raspberrypi.com>\n\t<20220714152409.9780-6-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220714152409.9780-6-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v5 5/8] ipa: raspberrypi: Introduce\n\tversion 2.0 format for the camera tuning file","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":23912,"web_url":"https://patchwork.libcamera.org/comment/23912/","msgid":"<CAEmqJPqxS+nPRcS4aeu_JhocXg2H7gpbtw3ZNDVTs=x4g9aA2g@mail.gmail.com>","date":"2022-07-15T07:38:17","subject":"Re: [libcamera-devel] [PATCH v5 5/8] ipa: raspberrypi: Introduce\n\tversion 2.0 format for the camera tuning file","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Laurent,\n\nThank you for your feedback.\n\nOn Fri, 15 Jul 2022 at 00:26, Laurent Pinchart <\nlaurent.pinchart@ideasonboard.com> wrote:\n\n> Hi Naush,\n>\n> Thank you for the patch.\n>\n> On Thu, Jul 14, 2022 at 04:24:06PM +0100, Naushir Patuck via\n> libcamera-devel wrote:\n> > The existing tuning file format (version 1.0) requires the controller\n> algorithms\n> > to run in the same order as listied in the JSON structure. The JSON\n>\n> s/listied/listed/\n>\n> > specification does not mandate any such ordering, but the Boost JSON\n> parser\n> > would maintain this order.\n> >\n> > In order to remove this reliance on the parser to provide ordering,\n> introduce a\n> > new version 2.0 format for the camera tuning file. In this version, the\n> > algorithms are specified in a top level list node (\"algorithms\"), which\n> does\n> > require strict ordering of the elements. Additionally, a \"version\" node\n> is added\n> > to distinguish between the version 1.0 and 2.0 formats. The absence of\n> the\n> > \"version\" node implies version 1.0.\n> >\n> > Update the controller to support either version of the tuning file by\n> looking\n> > at the version node. CreateAlgorithm member function to now load and\n> configure\n> > each algorithm. Additionally, make CreateAlgorithm a private member, it\n> does not\n> > get called externally.\n> >\n> > If a version 1.0 format tuning file is used, throw a warning message\n> indicating\n> > it will be soon deprecated.\n> >\n> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n>\n> Sounds like a good plan.\n>\n> A question on the versioning scheme though. In the rkisp1 IPA modules,\n> we use (for now) a single integer for the version. Do you see use cases\n> for a semantic versioning scheme (x.y or x.y.z) ? I'm not implying there\n> are none, but we haven't really considered the versioning scheme yet,\n> and it seems like a good time to discuss this.\n>\n> I assume major new versions of tuning files will not be backward\n> compatible with previous ones, so if an IPA module supports version\n> [min, max], any tuning file with a version number outside that range\n> would be rejected.\n>\n> I can also imagine changes to the tuning file format that would be\n> backward-compatible (mostly adding new data, when the implementation of\n> the algorithms can use default values if the data isn't present). In\n> this case, could an IPA module benefit from knowing in advance, through\n> a minor version number, that additional data may be present, or would it\n> only use the major version number only and just use default values for\n> absent data ? I'm not sure if the minor version number would be useful\n> for the IPA module, but I could also imagine it may be useful to other\n> tools, such as tuning tools, to know what to expect.\n>\n\nAs you spotted below, I used a float type for versioning to allow x.y\nschemes.\nI never really considered a string for x.y.z to be honest, I doubt we will\nneed\nthat level of versioning.  However, I am happy to change to a string type if\nthat feels safer.  Maybe David can share his thoughts when he is back.\n\nI agree with your other points, major revisions will not be backward\ncompatible\nwith previous revisions, and if the IPA encounters a version outside of its\nrange\nit will have to reject it and fail the application.\n\nAdding new data fields to a tuning file possibly implies bumping up the\nminor\nrevision number.  In these cases, reading them through an older IPA library\nought to \"just work\" as those values will simply be ignored - and probably\nthrow\na warning message which is a good thing.\n\nRegards,\nNaush\n\n\n>\n> > ---\n> >  src/ipa/raspberrypi/controller/controller.cpp | 42 +++++++++++++------\n> >  src/ipa/raspberrypi/controller/controller.hpp |  4 +-\n> >  2 files changed, 33 insertions(+), 13 deletions(-)\n> >\n> > diff --git a/src/ipa/raspberrypi/controller/controller.cpp\n> b/src/ipa/raspberrypi/controller/controller.cpp\n> > index 67d650ef0c1b..9a2a3fb01793 100644\n> > --- a/src/ipa/raspberrypi/controller/controller.cpp\n> > +++ b/src/ipa/raspberrypi/controller/controller.cpp\n> > @@ -42,22 +42,40 @@ void Controller::Read(char const *filename)\n> >       }\n> >\n> >       std::unique_ptr<YamlObject> root = YamlParser::parse(file);\n> > -\n> > -     for (auto const &[key, value] : root->asDict()) {\n> > -             Algorithm *algo = CreateAlgorithm(key.c_str());\n> > -             if (algo) {\n> > -                     algo->Read(value);\n> > -                     algorithms_.push_back(AlgorithmPtr(algo));\n> > -             } else\n> > -                     LOG(RPiController, Warning)\n> > -                             << \"No algorithm found for \\\"\" << key <<\n> \"\\\"\";\n> > +     double version = (*root)[\"version\"].get<double>(1.0);\n>\n> Interesting idea to consider it as a duoble.\n>\n> > +     if (version < 2.0) {\n> > +             LOG(RPiController, Warning)\n> > +                     << \"This format of the tuning file will be\n> deprecated soon!\"\n> > +                     << \" Please use the convert_tuning.py utility to\n> update to version 2.0.\";\n> > +             for (auto const &[key, value] : root->asDict()) {\n> > +                     if (!key.compare(\"version\"))\n> > +                             continue;\n>\n> I think you can drop this check, as v1 tuning files don't specify the\n> version.\n>\n> > +                     CreateAlgorithm(key, value);\n> > +             }\n> > +     } else {\n>\n>         } else if (version < 3.0) {\n>                 ...\n>         } else {\n>                 /* error */\n>         }\n>\n> But maybe a\n>\n>         switch (std::floor(version)) {\n>                 ...\n>         }\n>\n> would be more readable ? Uo to you.\n>\n> > +             if (!root->contains(\"algorithms\")) {\n> > +                     LOG(RPiController, Fatal)\n> > +                             << \"Tuning file \" << filename\n> > +                             << \" does not have an \\\"algorithms\\\"\n> list!\";\n> > +                     return;\n> > +             }\n> > +             for (auto const &rootAlgo : (*root)[\"algorithms\"].asList())\n> > +                     for (auto const &[key, value] : rootAlgo.asDict())\n>\n> I'm tempted to create a asOrderedDict() function to make this easier.\n>\n> > +                             CreateAlgorithm(key, value);\n> >       }\n> >  }\n> >\n> > -Algorithm *Controller::CreateAlgorithm(char const *name)\n> > +void Controller::CreateAlgorithm(const std::string &name, const\n> YamlObject &params)\n> >  {\n> > -     auto it = GetAlgorithms().find(std::string(name));\n> > -     return it != GetAlgorithms().end() ? (*it->second)(this) : nullptr;\n> > +     auto it = GetAlgorithms().find(name);\n> > +     if (it == GetAlgorithms().end()) {\n> > +             LOG(RPiController, Warning)\n> > +                     << \"No algorithm found for \\\"\" << name << \"\\\"\";\n> > +             return;\n> > +     }\n> > +     Algorithm *algo = (*it->second)(this);\n> > +     algo->Read(params);\n> > +     algorithms_.push_back(AlgorithmPtr(algo));\n> >  }\n> >\n> >  void Controller::Initialise()\n> > diff --git a/src/ipa/raspberrypi/controller/controller.hpp\n> b/src/ipa/raspberrypi/controller/controller.hpp\n> > index 3b50ae770d11..9091deac5feb 100644\n> > --- a/src/ipa/raspberrypi/controller/controller.hpp\n> > +++ b/src/ipa/raspberrypi/controller/controller.hpp\n> > @@ -15,6 +15,8 @@\n> >\n> >  #include <linux/bcm2835-isp.h>\n> >\n> > +#include \"libcamera/internal/yaml_parser.h\"\n>\n> You can also forward-declare YamlObject, up to you.\n>\n> > +\n> >  #include \"camera_mode.h\"\n> >  #include \"device_status.h\"\n> >  #include \"metadata.hpp\"\n> > @@ -36,7 +38,6 @@ public:\n> >       Controller();\n> >       Controller(char const *json_filename);\n> >       ~Controller();\n> > -     Algorithm *CreateAlgorithm(char const *name);\n> >       void Read(char const *filename);\n> >       void Initialise();\n> >       void SwitchMode(CameraMode const &camera_mode, Metadata *metadata);\n> > @@ -46,6 +47,7 @@ public:\n> >       Algorithm *GetAlgorithm(std::string const &name) const;\n> >\n> >  protected:\n> > +     void CreateAlgorithm(const std::string &name, const\n> libcamera::YamlObject &params);\n> >       Metadata global_metadata_;\n> >       std::vector<AlgorithmPtr> algorithms_;\n> >       bool switch_mode_called_;\n>\n> --\n> Regards,\n>\n> Laurent Pinchart\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 832DFBD1F1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 15 Jul 2022 07:38:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EFFB263312;\n\tFri, 15 Jul 2022 09:38:34 +0200 (CEST)","from mail-lj1-x234.google.com (mail-lj1-x234.google.com\n\t[IPv6:2a00:1450:4864:20::234])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 79A2E6330B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 15 Jul 2022 09:38:33 +0200 (CEST)","by mail-lj1-x234.google.com with SMTP id w17so4814132ljh.6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 15 Jul 2022 00:38:33 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1657870715;\n\tbh=f+P5LkMS6usdFwg3cmWoOALc69sxokhMtViz+qDUfsE=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=2PKN19do7HwrQT+57mgSGc8E0/e8fJjt7yx4hhGknI6G2VrG9HZuiJuC7fix8lzwi\n\t6mrErlu+a0Os16xMy+fhA+4GQYxHKk2dfL6qsoO8tFcepYQLanEQujXCExoSRLRUiW\n\tfb5wjKh0MCCT9HFuq32H3oxEQb6HxMNyp+AzMF9wYPolzrd42HbyL6iM4pgBoE4MM+\n\toIWgG5XXFsW/m5215C1rL/zOz//Czp2MZ5BKeNn0zSjXiByukE5dL8pmFubMKhCCDV\n\tGC/apeNJCLPREvCX6mbl/BGmbzyJJN/kRcuvHWfz4guLMMCkkjc3A3jSJDCHe0cjsC\n\tjhbdpwXFNypBA==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=whnT2NjjHSDFrgYf1LIdt8i/yDUtj6E5JtKZ3uh5Rj0=;\n\tb=qFPuwdYRiunn9RkUNVk1OCuvuHm2Gu5pIJqc85WjkRktKY+aMyGgGu3EYK1T5KXZZw\n\te9SDpBN+/GbCDJM6fTxm6qPUo83tSACPuRumXpogOkRoa7+0t3Ervjq2m3lf3aANAKlc\n\tGCY5j2GpvlumtQy0KGpytyVGL/gdsufp0cp20vcOLV/TWT9MOJAeO0TSUCTLgkPt53dl\n\t+MwJeBow4/d0S6F43He2VlU3GCObaAYgJwu30Rp+AhEcvJbzOOIud+g/Qgo3jQKVYEuv\n\tzVb6vFwdGYQTIyoRm73UWK+ABJnD3kb2eUJ4NQD3icLtH8qo2UL0QiEjmIq2bHBsiMOz\n\tOAHQ=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"qFPuwdYR\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=whnT2NjjHSDFrgYf1LIdt8i/yDUtj6E5JtKZ3uh5Rj0=;\n\tb=Jtd9MS8DyNSgQN6WDlhN2jRhXljZrB5UE9qMGiefUARgcSBPVoY+Np/M+ddCQJf+eP\n\tnFyCzNkYfGDD590S/e6oJIwrwrQ0oyW2sHFZnwzMoD9whO4fGh+wdReXAX3ec3Gi4a4K\n\tulHKEQY7g06CIU0LoLo7Tz9BGfwYtTiY7LHlgymjMPw8UPHZE1VbglxUtVPwPYwmpcLG\n\t8zKYQGrqCMPbmo2YLC0oiWDTrUNQwVCSDnDEX76DtQ9IfhV7T9s0RlNkYSNxkUx2d4Sm\n\tVW8KSAk8UEDteh2CMJn1GRrsIT0hLboQejyBd+rBfWzM4fSYz0Hk0xVKcccyP1DIq8Mo\n\t+bmg==","X-Gm-Message-State":"AJIora+8VUFISi0DN5pTYdTnAvk3NZGSsgGgrTQHZxTRjXKl/4ZrznI8\n\tewpPyX6OmB9oBuNjgMO8NDI7fVWEdhibdkJx4PxFOadXKd1Z/w==","X-Google-Smtp-Source":"AGRyM1uqzUMf7ix43xf3MKFW+7I8DPq1xStP/k5HaTXkKpccM23qbDxFblHkh/ZUDB8KcsICwpR3IwPKMtZS9zsUUT4=","X-Received":"by 2002:a05:651c:4d1:b0:25d:794d:faf with SMTP id\n\te17-20020a05651c04d100b0025d794d0fafmr6355112lji.215.1657870712816;\n\tFri, 15 Jul 2022 00:38:32 -0700 (PDT)","MIME-Version":"1.0","References":"<20220714152409.9780-1-naush@raspberrypi.com>\n\t<20220714152409.9780-6-naush@raspberrypi.com>\n\t<YtCl+L8WUj7IQ36J@pendragon.ideasonboard.com>","In-Reply-To":"<YtCl+L8WUj7IQ36J@pendragon.ideasonboard.com>","Date":"Fri, 15 Jul 2022 08:38:17 +0100","Message-ID":"<CAEmqJPqxS+nPRcS4aeu_JhocXg2H7gpbtw3ZNDVTs=x4g9aA2g@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Content-Type":"multipart/alternative; boundary=\"000000000000ebdbbf05e3d31ab9\"","Subject":"Re: [libcamera-devel] [PATCH v5 5/8] ipa: raspberrypi: Introduce\n\tversion 2.0 format for the camera tuning file","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>","From":"Naushir Patuck via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]