[{"id":29948,"web_url":"https://patchwork.libcamera.org/comment/29948/","msgid":"<171837197615.3835057.5806137048553091085@ping.linuxembedded.co.uk>","date":"2024-06-14T13:32:56","subject":"Re: [PATCH v4 1/2] utils: libtuning: modules: Add skeletal AGC\n\tmodule","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Paul Elder (2024-06-14 12:40:15)\n> Add a skeletal AGC module just so that we can have some AGC tuning\n> values that we can use to test during development of AGC in the IPAs. As\n> rkisp1 is the main target, we only add support for rkisp1 for now.\n> \n> The parameters are mostly copied from the hardcoded values in ctt,\n> except for the metering modes.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> \n> ---\n> Changes in v4:\n> - remove support for both v10 and v12, and only support v10\n> - remove piecewise linear function luminance targets\n> \n> Changes in v3:\n> - remove unused compatible string\n> - make gain start from 2 in the exposure modes\n> \n> Changes in v2:\n> - remove unneccessary imports\n> - add support for both v10 and v12\n> ---\n>  .../tuning/libtuning/modules/agc/__init__.py  |  6 ++\n>  utils/tuning/libtuning/modules/agc/agc.py     | 21 +++++\n>  utils/tuning/libtuning/modules/agc/rkisp1.py  | 79 +++++++++++++++++++\n>  3 files changed, 106 insertions(+)\n>  create mode 100644 utils/tuning/libtuning/modules/agc/__init__.py\n>  create mode 100644 utils/tuning/libtuning/modules/agc/agc.py\n>  create mode 100644 utils/tuning/libtuning/modules/agc/rkisp1.py\n> \n> diff --git a/utils/tuning/libtuning/modules/agc/__init__.py b/utils/tuning/libtuning/modules/agc/__init__.py\n> new file mode 100644\n> index 000000000000..4db9ca371c68\n> --- /dev/null\n> +++ b/utils/tuning/libtuning/modules/agc/__init__.py\n> @@ -0,0 +1,6 @@\n> +# SPDX-License-Identifier: GPL-2.0-or-later\n> +#\n> +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> +\n> +from libtuning.modules.agc.agc import AGC\n> +from libtuning.modules.agc.rkisp1 import AGCRkISP1\n> diff --git a/utils/tuning/libtuning/modules/agc/agc.py b/utils/tuning/libtuning/modules/agc/agc.py\n> new file mode 100644\n> index 000000000000..9c8899badc79\n> --- /dev/null\n> +++ b/utils/tuning/libtuning/modules/agc/agc.py\n> @@ -0,0 +1,21 @@\n> +# SPDX-License-Identifier: BSD-2-Clause\n> +#\n> +# Copyright (C) 2019, Raspberry Pi Ltd\n> +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> +\n> +from ..module import Module\n> +\n> +import libtuning as lt\n> +\n> +\n> +class AGC(Module):\n> +    type = 'agc'\n> +    hr_name = 'AGC (Base)'\n\nWhat's an hr_name? (hr?)\n\n> +    out_name = 'GenericAGC'\n> +\n> +    # \\todo Add sector shapes and stuff just like lsc\n> +    def __init__(self, *,\n> +                 debug: list):\n> +        super().__init__()\n> +\n> +        self.debug = debug\n> diff --git a/utils/tuning/libtuning/modules/agc/rkisp1.py b/utils/tuning/libtuning/modules/agc/rkisp1.py\n> new file mode 100644\n> index 000000000000..babb441a8300\n> --- /dev/null\n> +++ b/utils/tuning/libtuning/modules/agc/rkisp1.py\n> @@ -0,0 +1,79 @@\n> +# SPDX-License-Identifier: BSD-2-Clause\n> +#\n> +# Copyright (C) 2019, Raspberry Pi Ltd\n> +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> +#\n> +# rkisp1.py - AGC module for tuning rkisp1\n> +\n> +from .agc import AGC\n> +\n> +import libtuning as lt\n> +\n> +\n> +class AGCRkISP1(AGC):\n> +    hr_name = 'AGC (RkISP1)'\n> +    out_name = 'Agc'\n> +\n> +    def __init__(self, **kwargs):\n> +        super().__init__(**kwargs)\n> +\n> +    # We don't actually need anything from the config file\n> +    def validate_config(self, config: dict) -> bool:\n> +        return True\n\nWould you ever anticipate putting these hardcoded values into a separate\nconfig file?\n\nAnyway ... I think this gets us moving forwards so:\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> +\n> +    def _generate_metering_modes(self) -> dict:\n> +        centre_weighted = [\n> +            0, 0,  0, 0, 0,\n> +            0, 6,  8, 6, 0,\n> +            0, 8, 16, 8, 0,\n> +            0, 6,  8, 6, 0,\n> +            0, 0,  0, 0, 0\n> +        ]\n> +\n> +        spot = [\n> +            0, 0,  0, 0, 0,\n> +            0, 2,  4, 2, 0,\n> +            0, 4, 16, 4, 0,\n> +            0, 2,  4, 2, 0,\n> +            0, 0,  0, 0, 0\n> +        ]\n> +\n> +        matrix = [1 for i in range(0, 25)]\n> +\n> +        return {\n> +            'MeteringCentreWeighted': centre_weighted,\n> +            'MeteringSpot': spot,\n> +            'MeteringMatrix': matrix\n> +        }\n> +\n> +    def _generate_exposure_modes(self) -> dict:\n> +        normal = { 'shutter': [100, 10000, 30000, 60000, 120000],\n> +                   'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n> +        short = { 'shutter': [100, 5000, 10000, 20000, 120000],\n> +                  'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n> +\n> +        return { 'ExposureNormal': normal, 'ExposureShort': short }\n> +\n> +    def _generate_constraint_modes(self) -> dict:\n> +        normal = { 'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5 } }\n> +        highlight = {\n> +            'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5 },\n> +            'upper': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.8 }\n> +        }\n> +\n> +        return { 'ConstraintNormal': normal, 'ConstraintHighlight': highlight }\n> +\n> +    def _generate_y_target(self) -> list:\n> +        return 0.16\n> +\n> +    def process(self, config: dict, images: list, outputs: dict) -> dict:\n> +        output = {}\n> +\n> +        output['AeMeteringMode'] = self._generate_metering_modes()\n> +        output['AeExposureMode'] = self._generate_exposure_modes()\n> +        output['AeConstraintMode'] = self._generate_constraint_modes()\n> +        output['relativeLuminanceTarget'] = self._generate_y_target()\n> +\n> +        # \\todo Debug functionality\n> +\n> +        return output\n> -- \n> 2.39.2\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 BFDACBD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 14 Jun 2024 13:33:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EBEAE61A2A;\n\tFri, 14 Jun 2024 15:33:03 +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 ECDC461A2A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 14 Jun 2024 15:33:01 +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 0130C179;\n\tFri, 14 Jun 2024 15:32:45 +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=\"t0aAAyRI\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1718371966;\n\tbh=46IL4Q37hNQCG4/4LSULp1ymoKeEFPuPQ5awBaK3QRQ=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=t0aAAyRIuzuiU75uFg+oJPdmN4oNgzBIqHJL/Uwh8CZ+Y47IaH+zWRFoR0s+UTJ1k\n\tstjBDbxJTvLa/iMrdAxkbzTxfJwBnrY6SbuQMgwo/TRaeA5utGj7QPW6nmdiFvWMvA\n\t+fWOztZLaoqylyNzzkKX84cJjyw1GvWXt7UfrxWU=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240614114016.116620-2-paul.elder@ideasonboard.com>","References":"<20240614114016.116620-1-paul.elder@ideasonboard.com>\n\t<20240614114016.116620-2-paul.elder@ideasonboard.com>","Subject":"Re: [PATCH v4 1/2] utils: libtuning: modules: Add skeletal AGC\n\tmodule","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Paul Elder <paul.elder@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Fri, 14 Jun 2024 14:32:56 +0100","Message-ID":"<171837197615.3835057.5806137048553091085@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":29949,"web_url":"https://patchwork.libcamera.org/comment/29949/","msgid":"<ZmxReDr4SlQKWB7O@pyrite.rasen.tech>","date":"2024-06-14T14:19:36","subject":"Re: [PATCH v4 1/2] utils: libtuning: modules: Add skeletal AGC\n\tmodule","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Fri, Jun 14, 2024 at 02:32:56PM +0100, Kieran Bingham wrote:\n> Quoting Paul Elder (2024-06-14 12:40:15)\n> > Add a skeletal AGC module just so that we can have some AGC tuning\n> > values that we can use to test during development of AGC in the IPAs. As\n> > rkisp1 is the main target, we only add support for rkisp1 for now.\n> > \n> > The parameters are mostly copied from the hardcoded values in ctt,\n> > except for the metering modes.\n> > \n> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> > \n> > ---\n> > Changes in v4:\n> > - remove support for both v10 and v12, and only support v10\n> > - remove piecewise linear function luminance targets\n> > \n> > Changes in v3:\n> > - remove unused compatible string\n> > - make gain start from 2 in the exposure modes\n> > \n> > Changes in v2:\n> > - remove unneccessary imports\n> > - add support for both v10 and v12\n> > ---\n> >  .../tuning/libtuning/modules/agc/__init__.py  |  6 ++\n> >  utils/tuning/libtuning/modules/agc/agc.py     | 21 +++++\n> >  utils/tuning/libtuning/modules/agc/rkisp1.py  | 79 +++++++++++++++++++\n> >  3 files changed, 106 insertions(+)\n> >  create mode 100644 utils/tuning/libtuning/modules/agc/__init__.py\n> >  create mode 100644 utils/tuning/libtuning/modules/agc/agc.py\n> >  create mode 100644 utils/tuning/libtuning/modules/agc/rkisp1.py\n> > \n> > diff --git a/utils/tuning/libtuning/modules/agc/__init__.py b/utils/tuning/libtuning/modules/agc/__init__.py\n> > new file mode 100644\n> > index 000000000000..4db9ca371c68\n> > --- /dev/null\n> > +++ b/utils/tuning/libtuning/modules/agc/__init__.py\n> > @@ -0,0 +1,6 @@\n> > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > +#\n> > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > +\n> > +from libtuning.modules.agc.agc import AGC\n> > +from libtuning.modules.agc.rkisp1 import AGCRkISP1\n> > diff --git a/utils/tuning/libtuning/modules/agc/agc.py b/utils/tuning/libtuning/modules/agc/agc.py\n> > new file mode 100644\n> > index 000000000000..9c8899badc79\n> > --- /dev/null\n> > +++ b/utils/tuning/libtuning/modules/agc/agc.py\n> > @@ -0,0 +1,21 @@\n> > +# SPDX-License-Identifier: BSD-2-Clause\n> > +#\n> > +# Copyright (C) 2019, Raspberry Pi Ltd\n> > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > +\n> > +from ..module import Module\n> > +\n> > +import libtuning as lt\n> > +\n> > +\n> > +class AGC(Module):\n> > +    type = 'agc'\n> > +    hr_name = 'AGC (Base)'\n> \n> What's an hr_name? (hr?)\n\nhuman-readable (which ironically itself is not very human-readable but)\n\n> > +    out_name = 'GenericAGC'\n> > +\n> > +    # \\todo Add sector shapes and stuff just like lsc\n> > +    def __init__(self, *,\n> > +                 debug: list):\n> > +        super().__init__()\n> > +\n> > +        self.debug = debug\n> > diff --git a/utils/tuning/libtuning/modules/agc/rkisp1.py b/utils/tuning/libtuning/modules/agc/rkisp1.py\n> > new file mode 100644\n> > index 000000000000..babb441a8300\n> > --- /dev/null\n> > +++ b/utils/tuning/libtuning/modules/agc/rkisp1.py\n> > @@ -0,0 +1,79 @@\n> > +# SPDX-License-Identifier: BSD-2-Clause\n> > +#\n> > +# Copyright (C) 2019, Raspberry Pi Ltd\n> > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > +#\n> > +# rkisp1.py - AGC module for tuning rkisp1\n> > +\n> > +from .agc import AGC\n> > +\n> > +import libtuning as lt\n> > +\n> > +\n> > +class AGCRkISP1(AGC):\n> > +    hr_name = 'AGC (RkISP1)'\n> > +    out_name = 'Agc'\n> > +\n> > +    def __init__(self, **kwargs):\n> > +        super().__init__(**kwargs)\n> > +\n> > +    # We don't actually need anything from the config file\n> > +    def validate_config(self, config: dict) -> bool:\n> > +        return True\n> \n> Would you ever anticipate putting these hardcoded values into a separate\n> config file?\n\nOh maybe.\n\n> \n> Anyway ... I think this gets us moving forwards so:\n> \n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n\nThanks :)\n\n\nPaul\n\n> > +\n> > +    def _generate_metering_modes(self) -> dict:\n> > +        centre_weighted = [\n> > +            0, 0,  0, 0, 0,\n> > +            0, 6,  8, 6, 0,\n> > +            0, 8, 16, 8, 0,\n> > +            0, 6,  8, 6, 0,\n> > +            0, 0,  0, 0, 0\n> > +        ]\n> > +\n> > +        spot = [\n> > +            0, 0,  0, 0, 0,\n> > +            0, 2,  4, 2, 0,\n> > +            0, 4, 16, 4, 0,\n> > +            0, 2,  4, 2, 0,\n> > +            0, 0,  0, 0, 0\n> > +        ]\n> > +\n> > +        matrix = [1 for i in range(0, 25)]\n> > +\n> > +        return {\n> > +            'MeteringCentreWeighted': centre_weighted,\n> > +            'MeteringSpot': spot,\n> > +            'MeteringMatrix': matrix\n> > +        }\n> > +\n> > +    def _generate_exposure_modes(self) -> dict:\n> > +        normal = { 'shutter': [100, 10000, 30000, 60000, 120000],\n> > +                   'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n> > +        short = { 'shutter': [100, 5000, 10000, 20000, 120000],\n> > +                  'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n> > +\n> > +        return { 'ExposureNormal': normal, 'ExposureShort': short }\n> > +\n> > +    def _generate_constraint_modes(self) -> dict:\n> > +        normal = { 'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5 } }\n> > +        highlight = {\n> > +            'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5 },\n> > +            'upper': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.8 }\n> > +        }\n> > +\n> > +        return { 'ConstraintNormal': normal, 'ConstraintHighlight': highlight }\n> > +\n> > +    def _generate_y_target(self) -> list:\n> > +        return 0.16\n> > +\n> > +    def process(self, config: dict, images: list, outputs: dict) -> dict:\n> > +        output = {}\n> > +\n> > +        output['AeMeteringMode'] = self._generate_metering_modes()\n> > +        output['AeExposureMode'] = self._generate_exposure_modes()\n> > +        output['AeConstraintMode'] = self._generate_constraint_modes()\n> > +        output['relativeLuminanceTarget'] = self._generate_y_target()\n> > +\n> > +        # \\todo Debug functionality\n> > +\n> > +        return output\n> > -- \n> > 2.39.2\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 24DA6C3237\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 14 Jun 2024 14:19:47 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 08A1B6548D;\n\tFri, 14 Jun 2024 16:19:46 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D515961A2A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 14 Jun 2024 16:19:44 +0200 (CEST)","from pyrite.rasen.tech (h175-177-049-156.catv02.itscom.jp\n\t[175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id AE6A82E0;\n\tFri, 14 Jun 2024 16:19:28 +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=\"XQG3C873\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1718374770;\n\tbh=N0TdCWPh14Qt/V/9/LOtLAuz93HSUCkGHYVScLXirck=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=XQG3C873odVe8whJoz9TalfpvIcPziNFLBgYwwkZYRHXFroX5R0EAFfLRSux+Yztz\n\txOnFY2joTSEb2WaJkUHPZGI8NpnxpdetXHhJD7R8vJHdk+G3j38LyeIbqT2v9lbFNX\n\tSTSf03usU7DdN5X4KYn9Oox84doL512wei6xgsxw=","Date":"Fri, 14 Jun 2024 23:19:36 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tStefan Klug <stefan.klug@ideasonboard.com>","Subject":"Re: [PATCH v4 1/2] utils: libtuning: modules: Add skeletal AGC\n\tmodule","Message-ID":"<ZmxReDr4SlQKWB7O@pyrite.rasen.tech>","References":"<20240614114016.116620-1-paul.elder@ideasonboard.com>\n\t<20240614114016.116620-2-paul.elder@ideasonboard.com>\n\t<171837197615.3835057.5806137048553091085@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<171837197615.3835057.5806137048553091085@ping.linuxembedded.co.uk>","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":29955,"web_url":"https://patchwork.libcamera.org/comment/29955/","msgid":"<20240615174550.GK9171@pendragon.ideasonboard.com>","date":"2024-06-15T17:45:50","subject":"Re: [PATCH v4 1/2] utils: libtuning: modules: Add skeletal AGC\n\tmodule","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Paul,\n\nI know this has been merged, but I have a question.\n\nOn Fri, Jun 14, 2024 at 11:19:36PM +0900, Paul Elder wrote:\n> On Fri, Jun 14, 2024 at 02:32:56PM +0100, Kieran Bingham wrote:\n> > Quoting Paul Elder (2024-06-14 12:40:15)\n> > > Add a skeletal AGC module just so that we can have some AGC tuning\n> > > values that we can use to test during development of AGC in the IPAs. As\n> > > rkisp1 is the main target, we only add support for rkisp1 for now.\n> > > \n> > > The parameters are mostly copied from the hardcoded values in ctt,\n> > > except for the metering modes.\n> > > \n> > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > > Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> > > \n> > > ---\n> > > Changes in v4:\n> > > - remove support for both v10 and v12, and only support v10\n> > > - remove piecewise linear function luminance targets\n> > > \n> > > Changes in v3:\n> > > - remove unused compatible string\n> > > - make gain start from 2 in the exposure modes\n> > > \n> > > Changes in v2:\n> > > - remove unneccessary imports\n> > > - add support for both v10 and v12\n> > > ---\n> > >  .../tuning/libtuning/modules/agc/__init__.py  |  6 ++\n> > >  utils/tuning/libtuning/modules/agc/agc.py     | 21 +++++\n> > >  utils/tuning/libtuning/modules/agc/rkisp1.py  | 79 +++++++++++++++++++\n> > >  3 files changed, 106 insertions(+)\n> > >  create mode 100644 utils/tuning/libtuning/modules/agc/__init__.py\n> > >  create mode 100644 utils/tuning/libtuning/modules/agc/agc.py\n> > >  create mode 100644 utils/tuning/libtuning/modules/agc/rkisp1.py\n> > > \n> > > diff --git a/utils/tuning/libtuning/modules/agc/__init__.py b/utils/tuning/libtuning/modules/agc/__init__.py\n> > > new file mode 100644\n> > > index 000000000000..4db9ca371c68\n> > > --- /dev/null\n> > > +++ b/utils/tuning/libtuning/modules/agc/__init__.py\n> > > @@ -0,0 +1,6 @@\n> > > +# SPDX-License-Identifier: GPL-2.0-or-later\n> > > +#\n> > > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > > +\n> > > +from libtuning.modules.agc.agc import AGC\n> > > +from libtuning.modules.agc.rkisp1 import AGCRkISP1\n> > > diff --git a/utils/tuning/libtuning/modules/agc/agc.py b/utils/tuning/libtuning/modules/agc/agc.py\n> > > new file mode 100644\n> > > index 000000000000..9c8899badc79\n> > > --- /dev/null\n> > > +++ b/utils/tuning/libtuning/modules/agc/agc.py\n> > > @@ -0,0 +1,21 @@\n> > > +# SPDX-License-Identifier: BSD-2-Clause\n> > > +#\n> > > +# Copyright (C) 2019, Raspberry Pi Ltd\n> > > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > > +\n> > > +from ..module import Module\n> > > +\n> > > +import libtuning as lt\n> > > +\n> > > +\n> > > +class AGC(Module):\n> > > +    type = 'agc'\n> > > +    hr_name = 'AGC (Base)'\n> > \n> > What's an hr_name? (hr?)\n> \n> human-readable (which ironically itself is not very human-readable but)\n> \n> > > +    out_name = 'GenericAGC'\n> > > +\n> > > +    # \\todo Add sector shapes and stuff just like lsc\n> > > +    def __init__(self, *,\n> > > +                 debug: list):\n> > > +        super().__init__()\n> > > +\n> > > +        self.debug = debug\n> > > diff --git a/utils/tuning/libtuning/modules/agc/rkisp1.py b/utils/tuning/libtuning/modules/agc/rkisp1.py\n> > > new file mode 100644\n> > > index 000000000000..babb441a8300\n> > > --- /dev/null\n> > > +++ b/utils/tuning/libtuning/modules/agc/rkisp1.py\n> > > @@ -0,0 +1,79 @@\n> > > +# SPDX-License-Identifier: BSD-2-Clause\n> > > +#\n> > > +# Copyright (C) 2019, Raspberry Pi Ltd\n> > > +# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n> > > +#\n> > > +# rkisp1.py - AGC module for tuning rkisp1\n> > > +\n> > > +from .agc import AGC\n> > > +\n> > > +import libtuning as lt\n> > > +\n> > > +\n> > > +class AGCRkISP1(AGC):\n> > > +    hr_name = 'AGC (RkISP1)'\n> > > +    out_name = 'Agc'\n> > > +\n> > > +    def __init__(self, **kwargs):\n> > > +        super().__init__(**kwargs)\n> > > +\n> > > +    # We don't actually need anything from the config file\n> > > +    def validate_config(self, config: dict) -> bool:\n> > > +        return True\n> > \n> > Would you ever anticipate putting these hardcoded values into a separate\n> > config file?\n> \n> Oh maybe.\n> \n> > \n> > Anyway ... I think this gets us moving forwards so:\n> > \n> > \n> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> > \n> \n> Thanks :)\n> \n> \n> Paul\n> \n> > > +\n> > > +    def _generate_metering_modes(self) -> dict:\n> > > +        centre_weighted = [\n> > > +            0, 0,  0, 0, 0,\n> > > +            0, 6,  8, 6, 0,\n> > > +            0, 8, 16, 8, 0,\n> > > +            0, 6,  8, 6, 0,\n> > > +            0, 0,  0, 0, 0\n> > > +        ]\n> > > +\n> > > +        spot = [\n> > > +            0, 0,  0, 0, 0,\n> > > +            0, 2,  4, 2, 0,\n> > > +            0, 4, 16, 4, 0,\n> > > +            0, 2,  4, 2, 0,\n> > > +            0, 0,  0, 0, 0\n> > > +        ]\n\nHow did you come up with those values ? The centre weighted matrix, in\nparticular, seems quite, well, centered :-) Downsampling the rpi4 matrix\nfrom ctt I would have expected\n\n[[ 0  0  5  0  0]\n [ 0 10 10 10  0]\n [ 5 10 16 10  5]\n [ 0 10 10 10  0]\n [ 0  0  5  0  0]]\n\nSimilarly, for spot metering, the downsampled rpi4 matrix is closer to\n\n[[ 0  0  0  0  0]\n [ 0  0  1  0  0]\n [ 0  1 16  1  0]\n [ 0  0  1  0  0]\n [ 0  0  0  0  0]]\n\nWe can use other values, but I wonder where they come from.\n\n> > > +\n> > > +        matrix = [1 for i in range(0, 25)]\n\nShould this be 16, not 1, to fill up the histogram bins ? The IPA module\nassumes weights of 16 when calculating the predivider.\n\nOK, that was two questions :-)\n\n> > > +\n> > > +        return {\n> > > +            'MeteringCentreWeighted': centre_weighted,\n> > > +            'MeteringSpot': spot,\n> > > +            'MeteringMatrix': matrix\n> > > +        }\n> > > +\n> > > +    def _generate_exposure_modes(self) -> dict:\n> > > +        normal = { 'shutter': [100, 10000, 30000, 60000, 120000],\n> > > +                   'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n> > > +        short = { 'shutter': [100, 5000, 10000, 20000, 120000],\n> > > +                  'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n> > > +\n> > > +        return { 'ExposureNormal': normal, 'ExposureShort': short }\n> > > +\n> > > +    def _generate_constraint_modes(self) -> dict:\n> > > +        normal = { 'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5 } }\n> > > +        highlight = {\n> > > +            'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5 },\n> > > +            'upper': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.8 }\n> > > +        }\n> > > +\n> > > +        return { 'ConstraintNormal': normal, 'ConstraintHighlight': highlight }\n> > > +\n> > > +    def _generate_y_target(self) -> list:\n> > > +        return 0.16\n> > > +\n> > > +    def process(self, config: dict, images: list, outputs: dict) -> dict:\n> > > +        output = {}\n> > > +\n> > > +        output['AeMeteringMode'] = self._generate_metering_modes()\n> > > +        output['AeExposureMode'] = self._generate_exposure_modes()\n> > > +        output['AeConstraintMode'] = self._generate_constraint_modes()\n> > > +        output['relativeLuminanceTarget'] = self._generate_y_target()\n> > > +\n> > > +        # \\todo Debug functionality\n> > > +\n> > > +        return output","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 3EE2BBD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 15 Jun 2024 17:46:14 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1F1F56548D;\n\tSat, 15 Jun 2024 19:46:13 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9275765458\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 15 Jun 2024 19:46:11 +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 A6D232E0;\n\tSat, 15 Jun 2024 19:45:55 +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=\"hxih/qPt\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1718473555;\n\tbh=O2Sd7UoY119sWTDp++++/pSNrArgIqqylG7TIPurlx8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=hxih/qPtLALkYOiHLP03Lhj+LBPnhJPonwZvJ+ZNrHxT6nbiQYLv3PKPrTE+sDcrM\n\t0jRYElZN+lPkge3/yu1OyatWgxy7yEqG45rmxVwuYBaK+vUpwAKZ+DtPZ9g65WF+iw\n\taYt0s8zpvLn1GBRXiPXlfqloADax5Aga/nAQhaWQ=","Date":"Sat, 15 Jun 2024 20:45:50 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org,\n\tStefan Klug <stefan.klug@ideasonboard.com>","Subject":"Re: [PATCH v4 1/2] utils: libtuning: modules: Add skeletal AGC\n\tmodule","Message-ID":"<20240615174550.GK9171@pendragon.ideasonboard.com>","References":"<20240614114016.116620-1-paul.elder@ideasonboard.com>\n\t<20240614114016.116620-2-paul.elder@ideasonboard.com>\n\t<171837197615.3835057.5806137048553091085@ping.linuxembedded.co.uk>\n\t<ZmxReDr4SlQKWB7O@pyrite.rasen.tech>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<ZmxReDr4SlQKWB7O@pyrite.rasen.tech>","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>"}}]