From patchwork Fri May 17 07:57:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 20052 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 47155BD78E for ; Fri, 17 May 2024 07:58:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E7B9F63484; Fri, 17 May 2024 09:58:05 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="HjHpiMVh"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8CAB763481 for ; Fri, 17 May 2024 09:58:03 +0200 (CEST) Received: from neptunite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2BFA1475; Fri, 17 May 2024 09:57:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1715932674; bh=uQAAhPHRSkT6vozENsAzY206n6/5tHmSzqUufcIoPU8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HjHpiMVh5txRbbZ1xb+5SRECUG7ust64NtyqLo8ht7f9a7uVEKwrT7Q9+QSK7Vb97 AVrKuXHCtQ2orKFtGiXOOAHayILiJEuI5ptaMpsYez1pmL0nViGQpM/+6ptlzsTJVu vpvf6aNIFAlXeN/rLFHxY/Jg1X+GmAijySP8vXEw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder , Stefan Klug Subject: [PATCH v2 1/5] utils: libtuning: modules: Add skeletal AGC module Date: Fri, 17 May 2024 16:57:47 +0900 Message-Id: <20240517075751.3866269-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240517075751.3866269-1-paul.elder@ideasonboard.com> References: <20240517075751.3866269-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a skeletal AGC module just so that we can have some AGC tuning values that we can use to test during development of AGC in the IPAs. As rkisp1 is the main target, we only add support for rkisp1 for now. The parameters are mostly copied from the hardcoded values in ctt, except for the metering modes. Signed-off-by: Paul Elder Reviewed-by: Stefan Klug --- Changes in v2: - remove unneccessary imports - add support for both v10 and v12 --- .../tuning/libtuning/modules/agc/__init__.py | 6 + utils/tuning/libtuning/modules/agc/agc.py | 21 ++++ utils/tuning/libtuning/modules/agc/rkisp1.py | 112 ++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 utils/tuning/libtuning/modules/agc/__init__.py create mode 100644 utils/tuning/libtuning/modules/agc/agc.py create mode 100644 utils/tuning/libtuning/modules/agc/rkisp1.py diff --git a/utils/tuning/libtuning/modules/agc/__init__.py b/utils/tuning/libtuning/modules/agc/__init__.py new file mode 100644 index 000000000..4db9ca371 --- /dev/null +++ b/utils/tuning/libtuning/modules/agc/__init__.py @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2024, Paul Elder + +from libtuning.modules.agc.agc import AGC +from libtuning.modules.agc.rkisp1 import AGCRkISP1 diff --git a/utils/tuning/libtuning/modules/agc/agc.py b/utils/tuning/libtuning/modules/agc/agc.py new file mode 100644 index 000000000..9c8899bad --- /dev/null +++ b/utils/tuning/libtuning/modules/agc/agc.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2019, Raspberry Pi Ltd +# Copyright (C) 2024, Paul Elder + +from ..module import Module + +import libtuning as lt + + +class AGC(Module): + type = 'agc' + hr_name = 'AGC (Base)' + out_name = 'GenericAGC' + + # \todo Add sector shapes and stuff just like lsc + def __init__(self, *, + debug: list): + super().__init__() + + self.debug = debug diff --git a/utils/tuning/libtuning/modules/agc/rkisp1.py b/utils/tuning/libtuning/modules/agc/rkisp1.py new file mode 100644 index 000000000..4ac4d8ce7 --- /dev/null +++ b/utils/tuning/libtuning/modules/agc/rkisp1.py @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2019, Raspberry Pi Ltd +# Copyright (C) 2024, Paul Elder +# +# rkisp1.py - AGC module for tuning rkisp1 + +from .agc import AGC + +import libtuning as lt + + +class AGCRkISP1(AGC): + hr_name = 'AGC (RkISP1)' + out_name = 'Agc' + # \todo Not sure if this is useful. Probably will remove later. + compatible = ['rkisp1'] + + def __init__(self, *, **kwargs): + super().__init__(**kwargs) + + # We don't actually need anything from the config file + def validate_config(self, config: dict) -> bool: + return True + + def _generate_metering_modes(self) -> dict: + centre_weighted = { + 'v10': [ + 0, 0, 0, 0, 0, + 0, 6, 8, 6, 0, + 0, 8, 16, 8, 0, + 0, 6, 8, 6, 0, + 0, 0, 0, 0, 0 + ], + + 'v12': [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 4, 3, 0, 0, 0, + 0, 0, 3, 6, 8, 6, 3, 0, 0, + 0, 0, 4, 8, 16, 8, 4, 0, 0, + 0, 0, 3, 6, 8, 6, 3, 0, 0, + 0, 0, 0, 3, 4, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + ] + } + + spot = { + 'v10': [ + 0, 0, 0, 0, 0, + 0, 2, 4, 2, 0, + 0, 4, 16, 4, 0, + 0, 2, 4, 2, 0, + 0, 0, 0, 0, 0 + ], + + 'v12': [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 2, 1, 0, 0, 0, + 0, 0, 1, 2, 4, 2, 1, 0, 0, + 0, 0, 2, 4, 16, 4, 2, 0, 0, + 0, 0, 1, 2, 4, 2, 1, 0, 0, + 0, 0, 0, 1, 2, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + ] + } + + matrix = { + 'v10': [1 for i in range(0, 25)], + 'v12': [1 for i in range(0, 81)] + } + + return { + 'MeteringCentreWeighted': centre_weighted, + 'MeteringSpot': spot, + 'MeteringMatrix': matrix + } + + def _generate_exposure_modes(self) -> dict: + normal = { 'shutter': [100, 10000, 30000, 60000, 120000], + 'gain': [1.0, 2.0, 4.0, 6.0, 6.0] } + short = { 'shutter': [100, 5000, 10000, 20000, 120000], + 'gain': [1.0, 2.0, 4.0, 6.0, 6.0]} + + return { 'ExposureNormal': normal, 'ExposureShort': short } + + def _generate_constraint_modes(self) -> dict: + normal = { 'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': [ 0, 0.5, 1000, 0.5 ] } } + highlight = { + 'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': [ 0, 0.5, 1000, 0.5 ] }, + 'upper': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': [ 0, 0.8, 1000, 0.5 ] } + } + + return { 'ConstraintNormal': normal, 'ConstraintHighlight': highlight } + + def _generate_y_target(self) -> list: + return [0, 0.16, 1000, 0.165, 10000, 0.17] + + def process(self, config: dict, images: list, outputs: dict) -> dict: + output = {} + + output['AeMeteringMode'] = self._generate_metering_modes() + output['AeExposureMode'] = self._generate_exposure_modes() + output['AeConstraintMode'] = self._generate_constraint_modes() + output['relativeLuminanceTarget'] = self._generate_y_target() + + # \todo Debug functionality + + return output