The terms "shutter" and "shutter speed" are used through libcamera to mean "exposure time". This is confusing, both due to "speed" being used as "time" while it should be the inverse (i.e. a maximum speed should correspond to the minimum time), and due to "shutter speed" and "exposure time" being used in different places with the same meaning. To improve clarity of the code base and the documentation, use "exposure time" consistently to replace "shutter speed". This rename highlighted another vocabulary issue in libcamera. The ExposureModeHelper::splitExposure() function used to document that it splits "exposure time into shutter time and gain". It has been reworded to "split exposure into exposure time and gain". That is not entirely satisfactory, as "exposure" has a defined meaning in photography (see https://en.wikipedia.org/wiki/Exposure_(photography)) that is not expressed as a duration. This issue if left to be addressed separately. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Naushir Patuck <naush@raspberrypi.com> Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
79 lines
2.3 KiB
Python
79 lines
2.3 KiB
Python
# SPDX-License-Identifier: BSD-2-Clause
|
|
#
|
|
# Copyright (C) 2019, Raspberry Pi Ltd
|
|
# Copyright (C) 2024, Paul Elder <paul.elder@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 = [
|
|
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
|
|
]
|
|
|
|
spot = [
|
|
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
|
|
]
|
|
|
|
matrix = [1 for i in range(0, 25)]
|
|
|
|
return {
|
|
'MeteringCentreWeighted': centre_weighted,
|
|
'MeteringSpot': spot,
|
|
'MeteringMatrix': matrix
|
|
}
|
|
|
|
def _generate_exposure_modes(self) -> dict:
|
|
normal = {'exposure-time': [100, 10000, 30000, 60000, 120000],
|
|
'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}
|
|
short = {'exposure-time': [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.5}}
|
|
highlight = {
|
|
'lower': {'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.5},
|
|
'upper': {'qLo': 0.98, 'qHi': 1.0, 'yTarget': 0.8}
|
|
}
|
|
|
|
return {'ConstraintNormal': normal, 'ConstraintHighlight': highlight}
|
|
|
|
def _generate_y_target(self) -> list:
|
|
return 0.5
|
|
|
|
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
|