[PATCH v3 1/4] utils: libtuning: modules: Add skeletal AGC module

Paul Elder paul.elder at ideasonboard.com
Wed May 29 21:42:48 CEST 2024


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 <paul.elder at ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug at ideasonboard.com>

---
Changes in v3:
- remove unused compatible string
- make gain start from 2 in the exposure modes

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  | 110 ++++++++++++++++++
 3 files changed, 137 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 <paul.elder at ideasonboard.com>
+
+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 <paul.elder at ideasonboard.com>
+
+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..02feb10e0
--- /dev/null
+++ b/utils/tuning/libtuning/modules/agc/rkisp1.py
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (C) 2019, Raspberry Pi Ltd
+# Copyright (C) 2024, Paul Elder <paul.elder at ideasonboard.com>
+#
+# 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'
+
+    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': [2.0, 4.0, 6.0, 6.0, 6.0]}
+        short = { 'shutter': [100, 5000, 10000, 20000, 120000],
+                  'gain': [2.0, 4.0, 6.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
-- 
2.39.2



More information about the libcamera-devel mailing list