From patchwork Thu Jun 30 13:38:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16459 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 0EAA8C3273 for ; Thu, 30 Jun 2022 13:39:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A45F065633; Thu, 30 Jun 2022 15:39:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596361; bh=BQg10bEAKgUSKfipvpBAEs5RYtA/MK+zNLgmgMgBYV0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=GSFMcdTJJnite90BeW9bFFHkunf1o7BnoUnFub//y/AXAIGPieoDfdKdnitVdNvU7 +L9coIOb6bsE7CtXaz0I8cVw9ev3oXp/+Z/lhAalksVTrbOLEC820WApt+sf6sZULS /PRpPlZM6549v2Z/KLX2qMWQJjojKDHH66bZ3KfYzFGu3PKVCgmVGBRseyR21uwYTC tgFLGVWBK6srTOFtCDTPlKFVSV+MaSx29oyw2vXjfbNVHJQR+VMwR7tp8Sl67K4bRY TZADGpBtNGdUo/+UveSocpq2TxgDBAOLP1axBdmBsKgxMfD5XL5RgVq5kD9tkIBrE5 uXqr+Tkr7pxQQ== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9ABF46564C for ; Thu, 30 Jun 2022 15:39:18 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 7C224240003; Thu, 30 Jun 2022 13:39:17 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:40 +0200 Message-Id: <20220630133902.321099-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 01/23] libcamera: control_ids: Add 'internal' argument 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add to the gen-controls.py script an optional argument '--internal' that allows to specify if the generated file targets public or internal controls. Add two new tags to the .cpp.in and .h.in templates to specify the correct inclusion path and the correct namespace. Internal controls will be introduced in the next patch. Signed-off-by: Jacopo Mondi --- include/libcamera/control_ids.h.in | 6 +++--- src/libcamera/control_ids.cpp.in | 12 ++++++------ utils/gen-controls.py | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in index 0718a8886f6c..410cfb643a0b 100644 --- a/include/libcamera/control_ids.h.in +++ b/include/libcamera/control_ids.h.in @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * control_ids.h - Control ID list + * ${include_prefix}control_ids.h - Control ID list * * This file is auto-generated. Do not edit. */ @@ -16,7 +16,7 @@ namespace libcamera { -namespace controls { +namespace controls${namespace_extension} { enum { ${ids} @@ -32,6 +32,6 @@ ${draft_controls} } /* namespace draft */ -} /* namespace controls */ +} /* namespace controls${namespace_extension} */ } /* namespace libcamera */ diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index 5fb1c2c30558..e7e1080e9324 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -2,17 +2,17 @@ /* * Copyright (C) 2019, Google Inc. * - * control_ids.cpp : Control ID list + * ${include_prefix}control_ids.cpp : Control ID list * * This file is auto-generated. Do not edit. */ -#include +#include #include /** - * \file control_ids.h - * \brief Camera control identifiers + * \file libcamera/${include_prefix}control_ids.h + * \brief Control identifiers */ namespace libcamera { @@ -20,7 +20,7 @@ namespace libcamera { /** * \brief Namespace for libcamera controls */ -namespace controls { +namespace controls${namespace_extension} { ${controls_doc} @@ -57,6 +57,6 @@ extern const ControlIdMap controls { ${controls_map} }; -} /* namespace controls */ +} /* namespace controls${namespace_extension} */ } /* namespace libcamera */ diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 3f99b5e2ba7d..978179f63858 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -188,6 +188,17 @@ def fill_template(template, data): return template.substitute(data) +def handle_internal_arg(internal, data): + + if internal: + data["namespace_extension"] = "::internal" + data["include_prefix"] = "internal/" + return + + data["namespace_extension"] = "" + data["include_prefix"] = "" + + def main(argv): # Parse command line arguments @@ -198,6 +209,7 @@ def main(argv): help='Input file name.') parser.add_argument('template', type=str, help='Template file name.') + parser.add_argument('--internal', type=bool, default=False) args = parser.parse_args(argv[1:]) data = open(args.input, 'rb').read() @@ -210,6 +222,8 @@ def main(argv): else: raise RuntimeError('Unknown template type') + handle_internal_arg(args.internal, data) + data = fill_template(args.template, data) if args.output: From patchwork Thu Jun 30 13:38:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16460 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 BF240BE173 for ; Thu, 30 Jun 2022 13:39:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7255065658; Thu, 30 Jun 2022 15:39:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596363; bh=Td3krTJJg9DQJdNUDwUHGq6oqQPqRHLo3sYlLNOUw9g=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=xnBfj316wqFZ9D23vNWrKXeFjkGFWCMEG8GFElK+zK9rPYAVdfNN8ahv4QyhAnnKD B95Wae9Zk1gkUmKnNsTZs2+x6xAxu4n9x2qZlosmAhH/QgAa7npmaewvRSaN9Pfe41 K6PCV3i8PeimVF+BcC04DE3mbpGODXq8od2ENwpPNpDnKHvNMQOZykyUMyZz7MDYIx +SJt2olrGajM3enCUOO7U5CxYoNDhaAyDo88WTHI79fpGQPzpK6S9bOy3FzzcCYsck XZ+MOhYtbSjybKjlY5km5JaPIhVVtZSXGJmTPNARtWXZp5i7iKeIwsypCQo0ZYIF0u C/G1pyGOa3jlw== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 328156559A for ; Thu, 30 Jun 2022 15:39:20 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 3A2FF240004; Thu, 30 Jun 2022 13:39:18 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:41 +0200 Message-Id: <20220630133902.321099-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 02/23] libcamera: control_ids: Separate the id numerical space 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Separate the internal and public control id numerical space by placing the internal controls at offset 0x1000. Signed-off-by: Jacopo Mondi Reviewed-by: Jean-Michel Hautbois --- utils/gen-controls.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 978179f63858..63e888546277 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -118,7 +118,7 @@ ${description} } -def generate_h(controls): +def generate_h(internal, controls): enum_template_start = string.Template('''enum ${name}Enum {''') enum_value_template = string.Template('''\t${name} = ${value},''') enum_values_template = string.Template('''extern const std::array ${name}Values;''') @@ -133,7 +133,11 @@ def generate_h(controls): name, ctrl = ctrl.popitem() id_name = snake_case(name).upper() - ids.append('\t' + id_name + ' = ' + str(id_value) + ',') + # Separate the internal and public controls id space + if internal: + ids.append('\t' + id_name + ' = ' + "0x1000 | " + str(id_value) + ',') + else: + ids.append('\t' + id_name + ' = ' + str(id_value) + ',') ctrl_type = ctrl['type'] if ctrl_type == 'string': @@ -218,7 +222,7 @@ def main(argv): if args.template.endswith('.cpp.in'): data = generate_cpp(controls) elif args.template.endswith('.h.in'): - data = generate_h(controls) + data = generate_h(args.internal, controls) else: raise RuntimeError('Unknown template type') From patchwork Thu Jun 30 13:38:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16461 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 B22C7C3274 for ; Thu, 30 Jun 2022 13:39:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6770765656; Thu, 30 Jun 2022 15:39:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596364; bh=zPR0ZoqDhUm2TMeYw2bRw8+KOUOJGkyz5Mn+49FkRO8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=PP1zBMEWQrNXw4ky0CJ6hzIbzXkerKZv7b7ie6syOXsPM5OWhbqcdgRTEj7g1NIMa Pr0x3tIQTrboMz5RTgWWlW/hMPaurWTbvzn0mQchwYKkkbUHcIQO8JZ/5id8LP3Y6g MnyfZChHPstlE+9HWDdpV+cNjsyfmn3xBBaByQnuLnrfO3tbZrFAD/UTs+p72n+/NA 47N7wDHJAEbKWOgvG9p4Lodjo6USeRcYGtZZmdKwcyBuQlPNQ+5dVmk1Ij0SQmGjEb wGxmyduFtjrTRn0fwkXuXT018KwMx/h3d+7xqBAVws8NrY7Jt4Sailq8bdVqaMNBcv SZLdtT6bY6uLg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 11ED165633 for ; Thu, 30 Jun 2022 15:39:21 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 7676F240004; Thu, 30 Jun 2022 13:39:20 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:42 +0200 Message-Id: <20220630133902.321099-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 03/23] libcamera: Introduce internal controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Introduce the enumeration of internal controls in internal_control_ids.yaml. Plumb in the build system the command to generate the definition of internal controls by re-using the same mechanism used for public controls to make it easy to extend it to also handle internal properties in future. Signed-off-by: Jacopo Mondi Reviewed-by: Jean-Michel Hautbois --- include/libcamera/internal/meson.build | 15 ++++++++++++++ src/libcamera/internal_control_ids.yaml | 27 +++++++++++++++++++++++++ src/libcamera/meson.build | 17 ++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/libcamera/internal_control_ids.yaml diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 7a780d48ee57..1559c3c368c4 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -9,6 +9,21 @@ libcamera_tracepoint_header = custom_target( command: [gen_tracepoints_header, '@OUTPUT@', '@INPUT@'], ) +# Generate the list of internal controls identifiers +internal_control_source_files = ['control_ids'] + +libcamera_internal_control_headers = [] + +foreach header : internal_control_source_files + input_files = files('../../../src/libcamera/internal_' + header +'.yaml',\ + '../' + header + '.h.in') + libcamera_internal_control_headers += custom_target( + 'internal_' + header + '_h', + input : input_files, + output : header + '.h', + command : [gen_controls, '--internal=True','-o', '@OUTPUT@', '@INPUT@']) +endforeach + libcamera_internal_headers = files([ 'bayer_format.h', 'byte_stream_buffer.h', diff --git a/src/libcamera/internal_control_ids.yaml b/src/libcamera/internal_control_ids.yaml new file mode 100644 index 000000000000..6d3775afcf67 --- /dev/null +++ b/src/libcamera/internal_control_ids.yaml @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2022, Google Inc. +# +%YAML 1.2 +--- +# Enumeration of internal libcamera controls +# Not exposed to application, for library use only + +controls: + + - ExposureTime: + type: int32_t + description: | + The sensor exposure time in milliseconds. + + - FrameDuration: + type: int64_t + description: | + The sensor frame duration time in milliseconds. + + - AnalogueGain: + type: float + description: | + The sensor analogue gain value. + +... diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index b57bee7ef6ca..89fdf347c708 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -52,6 +52,7 @@ libcamera_sources = files([ libcamera_sources += libcamera_public_headers libcamera_sources += libcamera_generated_ipa_headers libcamera_sources += libcamera_tracepoint_header +libcamera_sources += libcamera_internal_control_headers includes = [ libcamera_includes, @@ -99,6 +100,7 @@ if not libyaml.found() libyaml = libyaml_wrap.dependency('yaml') endif +# Generate control_ids.cpp and property_ids.cpp control_sources = [] foreach source : control_source_files @@ -111,6 +113,21 @@ endforeach libcamera_sources += control_sources +# Generate internal_control_ids.cpp +internal_control_source_files = ['control_ids'] +internal_control_sources = [] + +foreach source : internal_control_source_files + input_files = files('internal_' + source +'.yaml', source + '.cpp.in') + internal_control_sources += custom_target('internal_' + source + '_cpp', + input : input_files, + output : 'internal_' + source + '.cpp', + command : [gen_controls, '--internal=True',\ + '-o', '@OUTPUT@',\ + '@INPUT@']) +endforeach +libcamera_sources += internal_control_sources + gen_version = meson.project_source_root() / 'utils' / 'gen-version.sh' # Use vcs_tag() and not configure_file() or run_command(), to ensure that the From patchwork Thu Jun 30 13:38:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16463 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 553FAC3275 for ; Thu, 30 Jun 2022 13:39:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 941A16565E; Thu, 30 Jun 2022 15:39:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596367; bh=YRcrjHMXZIwdFvwX6ssq+Ra4PbFZJC596koAMpw3dT8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=AdfxTYI1rQgEAiHf32vDLfhhaz/IKo07wuWyieilKBMMHb0ar78MAAyzsiEnXiwt4 ENhfcgrTh90EBjI7KGzZxDrnw6JgpkDP1y7Tsxdy2LhD25qRMISEjlFWyVkdFpsblz No2SS78eIp/N1xQZRuyChe+gZ+tuQF3cOgFihMVoPRE/r6fUpfXI1XMKes0Mq2Beys pDB0EdogBtIFaXqFDp6wLDxM9smlaa7aw9efIXlh5tq5Z/LzFkfLmNDEljWahbg9LP AedC+7WpnkMDFLjV/s4ZdR+yNdw/R9f7PeHfYb5VLMnnNRh6E8V7VgN7O4MHeadta4 XrzIfuTj22oWw== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 12AF565653 for ; Thu, 30 Jun 2022 15:39:22 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 4C327240003; Thu, 30 Jun 2022 13:39:21 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:43 +0200 Message-Id: <20220630133902.321099-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 04/23] libcamera: control_serializer: Support internal controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The control serializer class uses tags to identify which ControlIdMap to use to de-serialize a ControlList. Add a value for internal controls to the ipa_controls_id_map_type enumeration and use it to identify lists of internal controls. Signed-off-by: Jacopo Mondi --- include/libcamera/ipa/ipa_controls.h | 1 + src/libcamera/control_serializer.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/libcamera/ipa/ipa_controls.h b/include/libcamera/ipa/ipa_controls.h index e5da1946ce1d..609e28197f50 100644 --- a/include/libcamera/ipa/ipa_controls.h +++ b/include/libcamera/ipa/ipa_controls.h @@ -20,6 +20,7 @@ extern "C" { enum ipa_controls_id_map_type { IPA_CONTROL_ID_MAP_CONTROLS, IPA_CONTROL_ID_MAP_PROPERTIES, + IPA_CONTROL_ID_MAP_INTERNAL_CONTROLS, IPA_CONTROL_ID_MAP_V4L2, }; diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index e87d23625ed2..c5b691a981a2 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -21,6 +21,7 @@ #include #include "libcamera/internal/byte_stream_buffer.h" +#include "libcamera/internal/control_ids.h" /** * \file control_serializer.h @@ -335,6 +336,8 @@ int ControlSerializer::serialize(const ControlList &list, idMapType = IPA_CONTROL_ID_MAP_CONTROLS; else if (idmap == &properties::properties) idMapType = IPA_CONTROL_ID_MAP_PROPERTIES; + else if (idmap == &controls::internal::controls) + idMapType = IPA_CONTROL_ID_MAP_INTERNAL_CONTROLS; else idMapType = IPA_CONTROL_ID_MAP_V4L2; @@ -461,6 +464,9 @@ ControlInfoMap ControlSerializer::deserialize(ByteStreamBuffer & case IPA_CONTROL_ID_MAP_PROPERTIES: idMap = &properties::properties; break; + case IPA_CONTROL_ID_MAP_INTERNAL_CONTROLS: + idMap = &controls::internal::controls; + break; case IPA_CONTROL_ID_MAP_V4L2: controlIdMaps_.emplace_back(std::make_unique()); localIdMap = controlIdMaps_.back().get(); From patchwork Thu Jun 30 13:38:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16462 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 4A33FC3276 for ; Thu, 30 Jun 2022 13:39:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CF74265662; Thu, 30 Jun 2022 15:39:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596369; bh=g4xH56Lmmaf+Kq/Tr6zXns9LdEvX6pqKSBSV+1ov2P0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Xml5AMQrYEBnDay3aJWSeGfKQhOk10ig4szzqsRyylFHwmjKNmpixvzJZNAsKNPXO 42RCy4D7LakkmoMAriaE27nHTzyqnHZRCUi7IF81PHCu6ixtJVugOR4QBtB8YkVcRQ 8gls8BZEK1IKmZhxTjggonw954vZmlXbKn7EYZSAKihybHdUuUhEBXObPAKalUGQuK d65zV2J/uRUd2uUtGGWBdOfxliaU389m1QOZ6XocF1YP5e7K6Te/unuL7BxPdLMOdZ FGsZM5Ra7M3ZRGxNwnnxpgCX1TQSHSEabdT3TYwzQ29T4xn0kHlTt2yjwq15sYSKcz 3xdl1SNfIINDg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B871F65651 for ; Thu, 30 Jun 2022 15:39:22 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 0CB22240004; Thu, 30 Jun 2022 13:39:21 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:44 +0200 Message-Id: <20220630133902.321099-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 05/23] libcamera: Add src/libcamera/camera_sensor directory 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The camera sensor related files are growing in number. As we prepare to add camera sensor helpers there too, create a directory to contain all camera sensor related classes. Signed-off-by: Jacopo Mondi --- src/libcamera/{ => camera_sensor}/camera_sensor.cpp | 0 .../{ => camera_sensor}/camera_sensor_properties.cpp | 0 src/libcamera/camera_sensor/meson.build | 6 ++++++ src/libcamera/meson.build | 3 +-- 4 files changed, 7 insertions(+), 2 deletions(-) rename src/libcamera/{ => camera_sensor}/camera_sensor.cpp (100%) rename src/libcamera/{ => camera_sensor}/camera_sensor_properties.cpp (100%) create mode 100644 src/libcamera/camera_sensor/meson.build diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp similarity index 100% rename from src/libcamera/camera_sensor.cpp rename to src/libcamera/camera_sensor/camera_sensor.cpp diff --git a/src/libcamera/camera_sensor_properties.cpp b/src/libcamera/camera_sensor/camera_sensor_properties.cpp similarity index 100% rename from src/libcamera/camera_sensor_properties.cpp rename to src/libcamera/camera_sensor/camera_sensor_properties.cpp diff --git a/src/libcamera/camera_sensor/meson.build b/src/libcamera/camera_sensor/meson.build new file mode 100644 index 000000000000..bf4b131a94b1 --- /dev/null +++ b/src/libcamera/camera_sensor/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_sources += files([ + 'camera_sensor.cpp', + 'camera_sensor_properties.cpp', +]) diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 89fdf347c708..897fb259a894 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -7,8 +7,6 @@ libcamera_sources = files([ 'camera_controls.cpp', 'camera_lens.cpp', 'camera_manager.cpp', - 'camera_sensor.cpp', - 'camera_sensor_properties.cpp', 'color_space.cpp', 'controls.cpp', 'control_serializer.cpp', @@ -61,6 +59,7 @@ includes = [ libatomic = cc.find_library('atomic', required : false) subdir('base') +subdir('camera_sensor') subdir('ipa') subdir('pipeline') subdir('proxy') From patchwork Thu Jun 30 13:38:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16465 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 E25EFC3277 for ; Thu, 30 Jun 2022 13:39:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 38A7C6565C; Thu, 30 Jun 2022 15:39:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596370; bh=0oOj00cS5wce6+BqgTEqwBLXunBSwT4HDzu4liBJrFk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Gbzyb7ZGyGqwFbalzVnJ5Ka0W4xgwOSu6zLVgjIhRRYh97XAAzSS9ToQCXMuJunky +rg/P2qJvbTJxMvCs+KtTGZR3KvBzM8wPKeX2AI0jpWeUQw3KorE3KbzQo+/WuYfLq nGlp4vDeH+DWD0UuQUpIvFE6L1XekWKXTshW7MjUUjLyAPmz9P8R3bPrCcEjQhA+f2 vGAHq3rC7m9XMHqeN+fXgTXurwkRH+O3NfEguBqRznv8CIhLHHHj5CBkjibu+RNWAQ oD4bvmq+Y3Z1at9vgsm2k4mvr4fw6w4v6nbVcpznPLGfWfAJsm8o+tSegSJHx4CxzN VGCWQ4qy+vsIQ== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 885AC65657 for ; Thu, 30 Jun 2022 15:39:25 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 81C5C24000B; Thu, 30 Jun 2022 13:39:22 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:45 +0200 Message-Id: <20220630133902.321099-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 06/23] libcamera: camera_sensor: Copy CameraSensorHelper 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Copy from libipa the CameraSensorHelper class into the libcamera/camera_sensor/ directory. The CameraSensorHelper class will be used by the CameraSensor class to translate the sensor gain codes to the actual gain values. Do not remove the original files from libipa to maintain compatibility with the existing IPAs. Signed-off-by: Jacopo Mondi --- include/libcamera/internal/camera_sensor.h | 2 + .../libcamera/internal/camera_sensor_helper.h | 93 ++++ include/libcamera/internal/meson.build | 1 + src/libcamera/camera_sensor/camera_sensor.cpp | 8 + .../camera_sensor/camera_sensor_helper.cpp | 487 ++++++++++++++++++ src/libcamera/camera_sensor/meson.build | 1 + 6 files changed, 592 insertions(+) create mode 100644 include/libcamera/internal/camera_sensor_helper.h create mode 100644 src/libcamera/camera_sensor/camera_sensor_helper.cpp diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index b9f4d7867854..43b035b77f2b 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -20,6 +20,7 @@ #include +#include "libcamera/internal/camera_sensor_helper.h" #include "libcamera/internal/formats.h" #include "libcamera/internal/v4l2_subdevice.h" @@ -105,6 +106,7 @@ private: ControlList properties_; std::unique_ptr focusLens_; + std::unique_ptr helper_; }; } /* namespace libcamera */ diff --git a/include/libcamera/internal/camera_sensor_helper.h b/include/libcamera/internal/camera_sensor_helper.h new file mode 100644 index 000000000000..929d417c4e4f --- /dev/null +++ b/include/libcamera/internal/camera_sensor_helper.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * camera_sensor_helper.h - Helper class that performs sensor-specific parameter computations + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace libcamera { + +class CameraSensorHelper +{ +public: + CameraSensorHelper() = default; + virtual ~CameraSensorHelper() = default; + + virtual uint32_t gainCode(double gain) const; + virtual double gain(uint32_t gainCode) const; + +protected: + enum AnalogueGainType { + AnalogueGainLinear, + AnalogueGainExponential, + }; + + struct AnalogueGainLinearConstants { + int16_t m0; + int16_t c0; + int16_t m1; + int16_t c1; + }; + + struct AnalogueGainExpConstants { + double a; + double m; + }; + + union AnalogueGainConstants { + AnalogueGainLinearConstants linear; + AnalogueGainExpConstants exp; + }; + + AnalogueGainType gainType_; + AnalogueGainConstants gainConstants_; + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelper) +}; + +class CameraSensorHelperFactory +{ +public: + CameraSensorHelperFactory(const std::string name); + virtual ~CameraSensorHelperFactory() = default; + + static std::unique_ptr create(const std::string &name); + + static void registerType(CameraSensorHelperFactory *factory); + static std::vector &factories(); + +protected: + virtual CameraSensorHelper *createInstance() = 0; + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelperFactory) + + std::string name_; +}; + +#define REGISTER_CAMERA_SENSOR_HELPER(name, helper) \ +class helper##Factory final : public CameraSensorHelperFactory \ +{ \ +public: \ + helper##Factory() : CameraSensorHelperFactory(name) {} \ + \ +private: \ + CameraSensorHelper *createInstance() \ + { \ + return new helper(); \ + } \ +}; \ +static helper##Factory global_##helper##Factory; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 1559c3c368c4..615be538386a 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -31,6 +31,7 @@ libcamera_internal_headers = files([ 'camera_controls.h', 'camera_lens.h', 'camera_sensor.h', + 'camera_sensor_helper.h', 'camera_sensor_properties.h', 'control_serializer.h', 'control_validator.h', diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index d055c16a4885..59b956e40803 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -172,6 +172,14 @@ int CameraSensor::init() if (ret) return ret; + helper_ = CameraSensorHelperFactory::create(model_); + if (!helper_) { + LOG(CameraSensor, Error) + << "Unable to create helper class for camera sensor " + << model_; + return -ENODEV; + } + ret = discoverAncillaryDevices(); if (ret) return ret; diff --git a/src/libcamera/camera_sensor/camera_sensor_helper.cpp b/src/libcamera/camera_sensor/camera_sensor_helper.cpp new file mode 100644 index 000000000000..bb1e3a6fd0ec --- /dev/null +++ b/src/libcamera/camera_sensor/camera_sensor_helper.cpp @@ -0,0 +1,487 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * camera_sensor_helper.cpp - Helper class that performs sensor-specific + * parameter computations + */ +#include "libcamera/internal/camera_sensor_helper.h" + +#include + +#include + +/** + * \file libcamera/internal/camera_sensor_helper.h + * \brief Helper class that performs sensor-specific parameter computations + * + * Computation of sensor configuration parameters is a sensor specific + * operation. Each CameraHelper derived class computes the value of + * configuration parameters, for example the analogue gain value, using + * sensor-specific functions and constants. + * + * Every subclass of CameraSensorHelper shall be registered with using + * the REGISTER_CAMERA_SENSOR_HELPER() macro. + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(CameraSensorHelper) + +/** + * \class CameraSensorHelper + * \brief Base class for computing sensor tuning parameters using + * sensor-specific constants + * + * Instances derived from CameraSensorHelper class are sensor-specific. + * Each supported sensor will have an associated base class defined. + */ + +/** + * \brief Construct a CameraSensorHelper instance + * + * CameraSensorHelper derived class instances shall never be constructed + * manually but always through the CameraSensorHelperFactory::create() function. + */ + +/** + * \brief Compute gain code from the analogue gain absolute value + * \param[in] gain The real gain to pass + * + * This function aims to abstract the calculation of the gain to allow + * algorithms use the real gain for its estimations. + * + * \return The gain code to pass to V4L2 + */ +uint32_t CameraSensorHelper::gainCode(double gain) const +{ + const AnalogueGainConstants &k = gainConstants_; + + switch (gainType_) { + case AnalogueGainLinear: + ASSERT(k.linear.m0 == 0 || k.linear.m1 == 0); + + return (k.linear.c0 - k.linear.c1 * gain) / + (k.linear.m1 * gain - k.linear.m0); + + case AnalogueGainExponential: + ASSERT(k.exp.a != 0 && k.exp.m != 0); + + return std::log2(gain / k.exp.a) / k.exp.m; + + default: + ASSERT(false); + return 0; + } +} + +/** + * \brief Compute the real gain from the V4L2 subdev control gain code + * \param[in] gainCode The V4L2 subdev control gain + * + * This function aims to abstract the calculation of the gain letting the + * algorithms use the real gain for its estimations. It is the counterpart of + * the function CameraSensorHelper::gainCode. + * + * \return The real gain + */ +double CameraSensorHelper::gain(uint32_t gainCode) const +{ + const AnalogueGainConstants &k = gainConstants_; + double gain = static_cast(gainCode); + + switch (gainType_) { + case AnalogueGainLinear: + ASSERT(k.linear.m0 == 0 || k.linear.m1 == 0); + + return (k.linear.m0 * gain + k.linear.c0) / + (k.linear.m1 * gain + k.linear.c1); + + case AnalogueGainExponential: + ASSERT(k.exp.a != 0 && k.exp.m != 0); + + return k.exp.a * std::exp2(k.exp.m * gain); + + default: + ASSERT(false); + return 0.0; + } +} + +/** + * \enum CameraSensorHelper::AnalogueGainType + * \brief The gain calculation modes as defined by the MIPI CCS + * + * Describes the image sensor analogue gain capabilities. + * Two modes are possible, depending on the sensor: Linear and Exponential. + */ + +/** + * \var CameraSensorHelper::AnalogueGainLinear + * \brief Gain is computed using linear gain estimation + * + * The relationship between the integer gain parameter and the resulting gain + * multiplier is given by the following equation: + * + * \f$gain=\frac{m0x+c0}{m1x+c1}\f$ + * + * Where 'x' is the gain control parameter, and m0, m1, c0 and c1 are + * image-sensor-specific constants of the sensor. + * These constants are static parameters, and for any given image sensor either + * m0 or m1 shall be zero. + * + * The full Gain equation therefore reduces to either: + * + * \f$gain=\frac{c0}{m1x+c1}\f$ or \f$\frac{m0x+c0}{c1}\f$ + */ + +/** + * \var CameraSensorHelper::AnalogueGainExponential + * \brief Gain is expressed using an exponential model + * + * The relationship between the integer gain parameter and the resulting gain + * multiplier is given by the following equation: + * + * \f$gain = a \cdot 2^{m \cdot x}\f$ + * + * Where 'x' is the gain control parameter, and 'a' and 'm' are image + * sensor-specific constants. + * + * This is a subset of the MIPI CCS exponential gain model with the linear + * factor 'a' being a constant, but with the exponent being configurable + * through the 'm' coefficient. + * + * When the gain is expressed in dB, 'a' is equal to 1 and 'm' to + * \f$log_{2}{10^{\frac{1}{20}}}\f$. + */ + +/** + * \struct CameraSensorHelper::AnalogueGainLinearConstants + * \brief Analogue gain constants for the linear gain model + * + * \var CameraSensorHelper::AnalogueGainLinearConstants::m0 + * \brief Constant used in the linear gain coding/decoding + * + * \note Either m0 or m1 shall be zero. + * + * \var CameraSensorHelper::AnalogueGainLinearConstants::c0 + * \brief Constant used in the linear gain coding/decoding + * + * \var CameraSensorHelper::AnalogueGainLinearConstants::m1 + * \brief Constant used in the linear gain coding/decoding + * + * \note Either m0 or m1 shall be zero. + * + * \var CameraSensorHelper::AnalogueGainLinearConstants::c1 + * \brief Constant used in the linear gain coding/decoding + */ + +/** + * \struct CameraSensorHelper::AnalogueGainExpConstants + * \brief Analogue gain constants for the exponential gain model + * + * \var CameraSensorHelper::AnalogueGainExpConstants::a + * \brief Constant used in the exponential gain coding/decoding + * + * \var CameraSensorHelper::AnalogueGainExpConstants::m + * \brief Constant used in the exponential gain coding/decoding + */ + +/** + * \struct CameraSensorHelper::AnalogueGainConstants + * \brief Analogue gain model constants + * + * This union stores the constants used to calculate the analogue gain. The + * CameraSensorHelper::gainType_ variable selects which union member is valid. + * + * \var CameraSensorHelper::AnalogueGainConstants::linear + * \brief Constants for the linear gain model + * + * \var CameraSensorHelper::AnalogueGainConstants::exp + * \brief Constants for the exponential gain model + */ + +/** + * \var CameraSensorHelper::gainType_ + * \brief The analogue gain model type + */ + +/** + * \var CameraSensorHelper::gainConstants_ + * \brief The analogue gain parameters used for calculation + * + * The analogue gain is calculated through a formula, and its parameters are + * sensor specific. Use this variable to store the values at init time. + */ + +/** + * \class CameraSensorHelperFactory + * \brief Registration of CameraSensorHelperFactory classes and creation of instances + * + * To facilitate discovery and instantiation of CameraSensorHelper classes, the + * CameraSensorHelperFactory class maintains a registry of camera sensor helper + * sub-classes. Each CameraSensorHelper subclass shall register itself using the + * REGISTER_CAMERA_SENSOR_HELPER() macro, which will create a corresponding + * instance of a CameraSensorHelperFactory subclass and register it with the + * static list of factories. + */ + +/** + * \brief Construct a camera sensor helper factory + * \param[in] name Name of the camera sensor helper class + * + * Creating an instance of the factory registers it with the global list of + * factories, accessible through the factories() function. + * + * The factory \a name is used for debug purpose and shall be unique. + */ +CameraSensorHelperFactory::CameraSensorHelperFactory(const std::string name) + : name_(name) +{ + registerType(this); +} + +/** + * \brief Create an instance of the CameraSensorHelper corresponding to + * a named factory + * \param[in] name Name of the factory + * + * \return A unique pointer to a new instance of the CameraSensorHelper subclass + * corresponding to the named factory or a null pointer if no such factory + * exists + */ +std::unique_ptr CameraSensorHelperFactory::create(const std::string &name) +{ + std::vector &factories = + CameraSensorHelperFactory::factories(); + + for (CameraSensorHelperFactory *factory : factories) { + if (name != factory->name_) + continue; + + CameraSensorHelper *helper = factory->createInstance(); + return std::unique_ptr(helper); + } + + return nullptr; +} + +/** + * \brief Add a camera sensor helper class to the registry + * \param[in] factory Factory to use to construct the camera sensor helper + * + * The caller is responsible to guarantee the uniqueness of the camera sensor + * helper name. + */ +void CameraSensorHelperFactory::registerType(CameraSensorHelperFactory *factory) +{ + std::vector &factories = + CameraSensorHelperFactory::factories(); + + factories.push_back(factory); +} + +/** + * \brief Retrieve the list of all camera sensor helper factories + * \return The list of camera sensor helper factories + */ +std::vector &CameraSensorHelperFactory::factories() +{ + /* + * The static factories map is defined inside the function to ensure + * it gets initialized on first use, without any dependency on link + * order. + */ + static std::vector factories; + return factories; +} + +/** + * \fn CameraSensorHelperFactory::createInstance() + * \brief Create an instance of the CameraSensorHelper corresponding to the + * factory + * + * This virtual function is implemented by the REGISTER_CAMERA_SENSOR_HELPER() + * macro. It creates a camera sensor helper instance associated with the camera + * sensor model. + * + * \return A pointer to a newly constructed instance of the CameraSensorHelper + * subclass corresponding to the factory + */ + +/** + * \var CameraSensorHelperFactory::name_ + * \brief The name of the factory + */ + +/** + * \def REGISTER_CAMERA_SENSOR_HELPER(name, helper) + * \brief Register a camera sensor helper with the camera sensor helper factory + * \param[in] name Sensor model name used to register the class + * \param[in] helper Class name of CameraSensorHelper derived class to register + * + * Register a CameraSensorHelper subclass with the factory and make it available + * to try and match sensors. + */ + +/* ----------------------------------------------------------------------------- + * Sensor-specific subclasses + */ + +#ifndef __DOXYGEN__ + +/* + * Helper function to compute the m parameter of the exponential gain model + * when the gain code is expressed in dB. + */ +static constexpr double expGainDb(double step) +{ + constexpr double log2_10 = 3.321928094887362; + + /* + * The gain code is expressed in step * dB (e.g. in 0.1 dB steps): + * + * G_code = G_dB/step = 20/step*log10(G_linear) + * + * Inverting the formula, we get + * + * G_linear = 10^(step/20*G_code) = 2^(log2(10)*step/20*G_code) + */ + return log2_10 * step / 20; +} + +class CameraSensorHelperImx219 : public CameraSensorHelper +{ +public: + CameraSensorHelperImx219() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 0, 256, -1, 256 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219) + +class CameraSensorHelperImx258 : public CameraSensorHelper +{ +public: + CameraSensorHelperImx258() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 0, 512, -1, 512 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258) + +class CameraSensorHelperImx290 : public CameraSensorHelper +{ +public: + CameraSensorHelperImx290() + { + gainType_ = AnalogueGainExponential; + gainConstants_.exp = { 1.0, expGainDb(0.3) }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("imx290", CameraSensorHelperImx290) + +class CameraSensorHelperImx296 : public CameraSensorHelper +{ +public: + CameraSensorHelperImx296() + { + gainType_ = AnalogueGainExponential; + gainConstants_.exp = { 1.0, expGainDb(0.1) }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("imx296", CameraSensorHelperImx296) + +class CameraSensorHelperImx477 : public CameraSensorHelper +{ +public: + CameraSensorHelperImx477() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 0, 1024, -1, 1024 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477) + +class CameraSensorHelperOv2740 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv2740() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 128 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740) + +class CameraSensorHelperOv5640 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv5640() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 16 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov5640", CameraSensorHelperOv5640) + +class CameraSensorHelperOv5670 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv5670() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 128 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670) + +class CameraSensorHelperOv5675 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv5675() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 128 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov5675", CameraSensorHelperOv5675) + +class CameraSensorHelperOv5693 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv5693() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 16 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693) + +class CameraSensorHelperOv8865 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv8865() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 128 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865) + +class CameraSensorHelperOv13858 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv13858() + { + gainType_ = AnalogueGainLinear; + gainConstants_.linear = { 1, 0, 0, 128 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858) + +#endif /* __DOXYGEN__ */ + +} /* namespace libcamera */ diff --git a/src/libcamera/camera_sensor/meson.build b/src/libcamera/camera_sensor/meson.build index bf4b131a94b1..991eeeeee29e 100644 --- a/src/libcamera/camera_sensor/meson.build +++ b/src/libcamera/camera_sensor/meson.build @@ -2,5 +2,6 @@ libcamera_sources += files([ 'camera_sensor.cpp', + 'camera_sensor_helper.cpp', 'camera_sensor_properties.cpp', ]) From patchwork Thu Jun 30 13:38:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16464 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 E339CC3278 for ; Thu, 30 Jun 2022 13:39:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 33A4A6569C; Thu, 30 Jun 2022 15:39:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596372; bh=Wze/zWdkmyZCcAc3Lfnv2bHGjZUXn9zlfAP79PKvJcs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=EN0HTxzYu+xXEMoDTEZd7KnEq2U0YHFYK45Wfr+V0nFX/zOGlQcXcT94t5/cMlytu 9jlnKd2lspkbP+TAYXJZded6nN6aeZu9YGdKKnKzo9Pn4x8rKG+v4qUQs7MJCRi/Rr IyuzSQP4+PTTFF0d1rBtShGUCpq5zH1jRANdalrFuk3t+eWk0Hda9CJ9JdigZ5zQLa 2UUuf281jsGuNuXL2gGm3iVqqzdlYkgNY4QfoE9wscXCblcqiyP9W00PJCoLtn0U/F JJTDD36pbX4ulXBbSN35LrAiQhw8uTeBC2dgADmQLoPfwqxd9wfkoG3vUQp6+I5+6L vc6v2GMctvrFA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 42D956564C for ; Thu, 30 Jun 2022 15:39:27 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id DEEAC24000B; Thu, 30 Jun 2022 13:39:25 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:46 +0200 Message-Id: <20220630133902.321099-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 07/23] libcamera: camera_sensor: Rename the control interface 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The control interface of the CameraSensor class operates on V4L2 controls. To prepare to move the CameraSensor interface to use libcamera::internal controls, rename the existing interface to be the 'v4l2' control interface, to allow users to transition to the new interface gradually. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/internal/camera_sensor.h | 6 +++--- src/libcamera/camera_sensor/camera_sensor.cpp | 14 +++++++------- src/libcamera/pipeline/ipu3/ipu3.cpp | 10 +++++----- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 14 +++++++------- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 +- src/libcamera/pipeline/vimc/vimc.cpp | 8 ++++---- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index 43b035b77f2b..2a850dedc0aa 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -56,9 +56,9 @@ public: const Size &size) const; int setFormat(V4L2SubdeviceFormat *format); - const ControlInfoMap &controls() const; - ControlList getControls(const std::vector &ids); - int setControls(ControlList *ctrls); + const ControlInfoMap &v4l2Controls() const; + ControlList getV4L2Controls(const std::vector &ids); + int setV4L2Controls(ControlList *ctrls); V4L2Subdevice *device() { return subdev_.get(); } diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index 59b956e40803..26cfa7d0f65a 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -335,8 +335,8 @@ void CameraSensor::initStaticProperties() void CameraSensor::initTestPatternModes() { - const auto &v4l2TestPattern = controls().find(V4L2_CID_TEST_PATTERN); - if (v4l2TestPattern == controls().end()) { + const auto &v4l2TestPattern = v4l2Controls().find(V4L2_CID_TEST_PATTERN); + if (v4l2TestPattern == v4l2Controls().end()) { LOG(CameraSensor, Debug) << "V4L2_CID_TEST_PATTERN is not supported"; return; } @@ -615,10 +615,10 @@ int CameraSensor::applyTestPatternMode(controls::draft::TestPatternModeEnum mode LOG(CameraSensor, Debug) << "Apply test pattern mode " << mode; int32_t index = staticProps_->testPatternModes.at(mode); - ControlList ctrls{ controls() }; + ControlList ctrls{ v4l2Controls() }; ctrls.set(V4L2_CID_TEST_PATTERN, index); - int ret = setControls(&ctrls); + int ret = setV4L2Controls(&ctrls); if (ret) return ret; @@ -744,7 +744,7 @@ int CameraSensor::setFormat(V4L2SubdeviceFormat *format) * * \return A map of the V4L2 controls supported by the sensor */ -const ControlInfoMap &CameraSensor::controls() const +const ControlInfoMap &CameraSensor::v4l2Controls() const { return subdev_->controls(); } @@ -767,7 +767,7 @@ const ControlInfoMap &CameraSensor::controls() const * \return The control values in a ControlList on success, or an empty list on * error */ -ControlList CameraSensor::getControls(const std::vector &ids) +ControlList CameraSensor::getV4L2Controls(const std::vector &ids) { return subdev_->getControls(ids); } @@ -797,7 +797,7 @@ ControlList CameraSensor::getControls(const std::vector &ids) * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ -int CameraSensor::setControls(ControlList *ctrls) +int CameraSensor::setV4L2Controls(ControlList *ctrls) { return subdev_->setControls(ctrls); } diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index b7dda282faab..85e5f8a70408 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -581,7 +581,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) * the sensor and user transform. */ if (data->supportsFlips_) { - ControlList sensorCtrls(cio2->sensor()->controls()); + ControlList sensorCtrls(cio2->sensor()->v4l2Controls()); sensorCtrls.set(V4L2_CID_HFLIP, static_cast(!!(config->combinedTransform_ & Transform::HFlip))); @@ -589,7 +589,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) static_cast(!!(config->combinedTransform_ & Transform::VFlip))); - ret = cio2->sensor()->setControls(&sensorCtrls); + ret = cio2->sensor()->setV4L2Controls(&sensorCtrls); if (ret) return ret; } @@ -662,7 +662,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) } ipa::ipu3::IPAConfigInfo configInfo; - configInfo.sensorControls = data->cio2_.sensor()->controls(); + configInfo.sensorControls = data->cio2_.sensor()->v4l2Controls(); CameraLens *lens = data->cio2_.sensor()->focusLens(); if (lens) @@ -1157,7 +1157,7 @@ int PipelineHandlerIPU3::registerCameras() LOG(IPU3, Warning) << "Invalid rotation of " << rotation << " degrees: ignoring"; - ControlList ctrls = cio2->sensor()->getControls({ V4L2_CID_HFLIP }); + ControlList ctrls = cio2->sensor()->getV4L2Controls({ V4L2_CID_HFLIP }); if (!ctrls.empty()) /* We assume the sensor supports VFLIP too. */ data->supportsFlips_ = true; @@ -1245,7 +1245,7 @@ int IPU3CameraData::loadIPA() return ret; ret = ipa_->init(IPASettings{ "", sensor->model() }, sensorInfo, - sensor->controls(), &ipaControls_); + sensor->v4l2Controls(), &ipaControls_); if (ret) { LOG(IPU3, Error) << "Failed to initialise the IPU3 IPA"; return ret; diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 66a84b1dfb97..f0013d3a1485 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -1303,8 +1303,8 @@ int PipelineHandlerRPi::registerCamera(MediaDevice *unicam, MediaDevice *isp, Me * sensor of the colour gains. It is defined to be a linear gain where * the default value represents a gain of exactly one. */ - auto it = data->sensor_->controls().find(V4L2_CID_NOTIFY_GAINS); - if (it != data->sensor_->controls().end()) + auto it = data->sensor_->v4l2Controls().find(V4L2_CID_NOTIFY_GAINS); + if (it != data->sensor_->v4l2Controls().end()) data->notifyGainsUnity_ = it->second.def().get(); /* @@ -1565,7 +1565,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config, ipa::RPi::IPA } } - entityControls.emplace(0, sensor_->controls()); + entityControls.emplace(0, sensor_->v4l2Controls()); entityControls.emplace(1, isp_[Isp::Input].dev()->controls()); /* Always send the user transform to the IPA. */ @@ -1719,7 +1719,7 @@ void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList & if (notifyGainsUnity_ && controls.contains(libcamera::controls::ColourGains)) { libcamera::Span colourGains = controls.get(libcamera::controls::ColourGains); /* The control wants linear gains in the order B, Gb, Gr, R. */ - ControlList ctrls(sensor_->controls()); + ControlList ctrls(sensor_->v4l2Controls()); std::array gains{ static_cast(colourGains[1] * *notifyGainsUnity_), *notifyGainsUnity_, @@ -1728,7 +1728,7 @@ void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList & }; ctrls.set(V4L2_CID_NOTIFY_GAINS, Span{ gains }); - sensor_->setControls(&ctrls); + sensor_->setV4L2Controls(&ctrls); } state_ = State::IpaComplete; @@ -1800,10 +1800,10 @@ void RPiCameraData::setSensorControls(ControlList &controls) ControlList vblank_ctrl; vblank_ctrl.set(V4L2_CID_VBLANK, controls.get(V4L2_CID_VBLANK)); - sensor_->setControls(&vblank_ctrl); + sensor_->setV4L2Controls(&vblank_ctrl); } - sensor_->setControls(&controls); + sensor_->setV4L2Controls(&controls); } void RPiCameraData::unicamTimeout() diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 3dc0850c7c89..83b67a8205f5 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -670,7 +670,7 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) } std::map entityControls; - entityControls.emplace(0, data->sensor_->controls()); + entityControls.emplace(0, data->sensor_->v4l2Controls()); ret = data->ipa_->configure(sensorInfo, streamConfig, entityControls); if (ret) { diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index 3379ac5cd47d..2991306ca9d8 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -307,7 +307,7 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config) std::forward_as_tuple(cfg.pixelFormat, cfg.size)); std::map entityControls; - entityControls.emplace(0, data->sensor_->controls()); + entityControls.emplace(0, data->sensor_->v4l2Controls()); IPACameraSensorInfo sensorInfo; data->sensor_->sensorInfo(&sensorInfo); @@ -376,7 +376,7 @@ void PipelineHandlerVimc::stopDevice(Camera *camera) int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request) { - ControlList controls(data->sensor_->controls()); + ControlList controls(data->sensor_->v4l2Controls()); for (auto it : request->controls()) { unsigned int id = it.first; @@ -405,7 +405,7 @@ int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request) << "Setting control " << utils::hex(ctrl.first) << " to " << ctrl.second.toString(); - int ret = data->sensor_->setControls(&controls); + int ret = data->sensor_->setV4L2Controls(&controls); if (ret) { LOG(VIMC, Error) << "Failed to set controls: " << ret; return ret < 0 ? ret : -EINVAL; @@ -530,7 +530,7 @@ int VimcCameraData::init() } /* Initialise the supported controls. */ - const ControlInfoMap &controls = sensor_->controls(); + const ControlInfoMap &controls = sensor_->v4l2Controls(); ControlInfoMap::Map ctrls; for (const auto &ctrl : controls) { From patchwork Thu Jun 30 13:38:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16466 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 C6B2CC3279 for ; Thu, 30 Jun 2022 13:39:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B38116569F; Thu, 30 Jun 2022 15:39:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596372; bh=D4LZqFIaG7h5yKFiw2jMPZjigf1V/xSbPCU74OIl17I=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=e9AaHM0wf+KNb/1RxUSkPgxKf1kaJHLwMmSWLzsvGIbEF1KMMiXfVOoJaRTv4AHvo pSzIBSFYyJ4JgppWfoP+fbwyiFEw3JIRF6zmyM7hrDrgU7/ZyE2JrWh7oV/i6LFbJu 6WZ7nPnGmICMUgvyAPJ+YgblMQ5LDV3mzvPIMwqGnjD0wvqIfTOe/8d4wm4wpcgVR1 xVGyZnHgFF20aXyYqS5CRTH7YiDpNRQQwCgl/bCYDrnFvScTgqsG2rzYEzrJyD9uDp DrdGj6NUkCE6uXiKD0XidpY0iDPzgy9QckELT1wUkjpM8i/4+RWgfaYJu3eK4R5gUR 1bG8ST3im/5qg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 91EC465657 for ; Thu, 30 Jun 2022 15:39:28 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id A59BA24000E; Thu, 30 Jun 2022 13:39:27 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:47 +0200 Message-Id: <20220630133902.321099-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 08/23] libcamera: camera_sensor: Initialize controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Initialize the control interface of the CameraSensor class by registering the control limits for controls::internal::ExposureTime, controls::internal::FrameDuration and controls::internal::AnalogueGain. Update the CameraSensor controls in the CameraSensor::updateControlInfo() function after having updated the subdevice V4L2 controls. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/internal/camera_sensor.h | 3 + src/libcamera/camera_sensor/camera_sensor.cpp | 90 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index 2a850dedc0aa..1eab5e9d53f0 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -63,6 +63,7 @@ public: V4L2Subdevice *device() { return subdev_.get(); } const ControlList &properties() const { return properties_; } + const ControlInfoMap &controls() const { return controls_; } int sensorInfo(IPACameraSensorInfo *info) const; void updateControlInfo(); @@ -81,6 +82,7 @@ private: void initStaticProperties(); void initTestPatternModes(); int initProperties(); + int updateControls(); int applyTestPatternMode(controls::draft::TestPatternModeEnum mode); int discoverAncillaryDevices(); @@ -104,6 +106,7 @@ private: const BayerFormat *bayerFormat_; ControlList properties_; + ControlInfoMap controls_; std::unique_ptr focusLens_; std::unique_ptr helper_; diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index 26cfa7d0f65a..976d34aaf876 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -22,6 +22,7 @@ #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/camera_lens.h" #include "libcamera/internal/camera_sensor_properties.h" +#include "libcamera/internal/control_ids.h" #include "libcamera/internal/formats.h" #include "libcamera/internal/sysfs.h" @@ -180,6 +181,10 @@ int CameraSensor::init() return -ENODEV; } + ret = updateControls(); + if (ret) + return ret; + ret = discoverAncillaryDevices(); if (ret) return ret; @@ -455,6 +460,84 @@ int CameraSensor::initProperties() return 0; } +int CameraSensor::updateControls() +{ + if (!bayerFormat_) + return 0; + + ControlInfoMap::Map controlsMap; + + /* The subdev driver has been validate already, the controls are there! */ + ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE, + V4L2_CID_HBLANK }); + uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get(); + uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get(); + + /* Assume the sensor has a single source pad #0. */ + V4L2SubdeviceFormat subdevFormat; + subdev_->getFormat(0, &subdevFormat); + + const ControlInfoMap &subdevControlsInfo = subdev_->controls(); + + /* + * Compute controls::ExposureTime limits by using line length and pixel + * rate converted to microseconds. Use the V4L2_CID_EXPOSURE control to + * get exposure min, max and default and convert it from lines to + * microseconds. + */ + uint32_t lineLength = subdevFormat.size.width + hblank; + double lineDuration = lineLength / (pixelRate / 1000000.0F); + const ControlInfo &v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE); + int32_t minExposure = v4l2Exposure.min().get() * lineDuration; + int32_t maxExposure = v4l2Exposure.max().get() * lineDuration; + int32_t defExposure = v4l2Exposure.def().get() * lineDuration; + + controlsMap[&controls::internal::ExposureTime] = + ControlInfo(minExposure, maxExposure, defExposure); + + /* + * Compute the frame duration limits. + * + * The frame length is computed assuming a fixed line length combined + * with the vertical frame sizes. + */ + const ControlInfo &v4l2VBlank = subdevControlsInfo.at(V4L2_CID_VBLANK); + std::array frameHeights{ + v4l2VBlank.min().get() + subdevFormat.size.height, + v4l2VBlank.max().get() + subdevFormat.size.height, + v4l2VBlank.def().get() + subdevFormat.size.height, + }; + + std::array frameDurations; + for (unsigned int i = 0; i < frameHeights.size(); ++i) { + uint64_t frameSize = lineLength * frameHeights[i]; + frameDurations[i] = frameSize / (pixelRate / 1000000.0F); + } + + controlsMap[&controls::internal::FrameDuration] = + ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]); + + /* + * Analogue gain values. + * + * Translate the V4L2 analogue gain, expressed in sensor-specific + * gain codes, and translate them to analogue gain values. + * + * \todo: CameraSensorHelper returns a double; there's no ControlValue + * overload for the double type. + */ + const ControlInfo &v4l2AGain = subdevControlsInfo.at(V4L2_CID_ANALOGUE_GAIN); + controlsMap[&controls::internal::AnalogueGain] = + ControlInfo(static_cast(helper_->gain(v4l2AGain.min().get())), + static_cast(helper_->gain(v4l2AGain.max().get())), + static_cast(helper_->gain(v4l2AGain.def().get()))); + + controls_ = ControlInfoMap(std::move(controlsMap), + controls::internal::controls); + + return 0; +} + /** * \brief Check for and initialise any ancillary devices * @@ -815,6 +898,12 @@ int CameraSensor::setV4L2Controls(ControlList *ctrls) * \return The list of camera sensor properties */ +/** + * \fn CameraSensor::controls() + * \brief Retrieve the map of the camera sensor controls limits + * \return The map of camera sensor control information + */ + /** * \brief Assemble and return the camera sensor info * \param[out] info The camera sensor info @@ -910,6 +999,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const void CameraSensor::updateControlInfo() { subdev_->updateControlInfo(); + updateControls(); } /** From patchwork Thu Jun 30 13:38:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16467 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 3078CC327A for ; Thu, 30 Jun 2022 13:39:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B5542656A1; Thu, 30 Jun 2022 15:39:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596373; bh=qfkbTfnrg4/rHiitqO5pfDyHxnXcXfcTXHBeAKyDSns=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=3CPjN0H1DAV39gwhDxMH0CN2EpjuyyJOKwSzoaTQLg0hoQcmMDs0AyBs6oNhkZz0D X1QowD0ngDSvxiwwMCMTEhyBwRW6ZAZEkBMSPdyQh1n3OSUzyLT85tu9RC87AGyqg/ qN6BkVbI+fmkGwuKpaEO/5i59gh9e8BAAIrYg0d1Sm9JiuOzQEmizCBZMudMAWlyXk lVOP9RNSObHSmFDMLj3uVqdAjwEgxT5MLFh01mD3896a0B6JOi7qfSz7aksYhJBrC5 gtKz4bTzgpvfvLHay4ybjlzvYxbyufTqrav0OeyfCTZ6chgVAJGZTm/mdTQLZYEnIX 5B/Bu0ussFkFA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B3C9E65697 for ; Thu, 30 Jun 2022 15:39:29 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id E8AF424000E; Thu, 30 Jun 2022 13:39:28 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:48 +0200 Message-Id: <20220630133902.321099-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 09/23] libcamera: camera_sensor_properties: Add sensor delays 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add to the camera sensor properties a map of control identifiers to their latencies. Some camera sensor controls take a variable number of frames to take effect, hence they should be set in advance. The newly introduced map records that information as a property of the camera sensor class. Signed-off-by: Jacopo Mondi --- .../internal/camera_sensor_properties.h | 4 ++ .../camera_sensor_properties.cpp | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/libcamera/internal/camera_sensor_properties.h b/include/libcamera/internal/camera_sensor_properties.h index 1ee3cb994106..2404b0674323 100644 --- a/include/libcamera/internal/camera_sensor_properties.h +++ b/include/libcamera/internal/camera_sensor_properties.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -16,10 +17,13 @@ namespace libcamera { struct CameraSensorProperties { + using SensorDelays = std::unordered_map; + static const CameraSensorProperties *get(const std::string &sensor); Size unitCellSize; std::map testPatternModes; + SensorDelays sensorDelays; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera_sensor/camera_sensor_properties.cpp b/src/libcamera/camera_sensor/camera_sensor_properties.cpp index e5f27f06eb1d..4b5ab716abe2 100644 --- a/src/libcamera/camera_sensor/camera_sensor_properties.cpp +++ b/src/libcamera/camera_sensor/camera_sensor_properties.cpp @@ -13,6 +13,8 @@ #include +#include + /** * \file camera_sensor_properties.h * \brief Database of camera sensor properties @@ -41,6 +43,18 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties) * \brief Map that associates the TestPattern control value with the indexes of * the corresponding sensor test pattern modes as returned by * V4L2_CID_TEST_PATTERN. + * + * \var CameraSensorProperties::sensorDelays + * \brief Map that associates control identifiers with their latencies, + * expressed in frame periods. + */ + +/** + * \typedef CameraSensorProperties::SensorDelays + * \brief Camera sensor controls delays + * + * Type to represent a map of camera sensor controls associated with their + * latencies, expressed in frame periods. */ /** @@ -69,6 +83,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen * 9: "Resolution Pattern" */ }, + .sensorDelays = { }, } }, { "imx219", { .unitCellSize = { 1120, 1120 }, @@ -79,6 +94,11 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeColorBarsFadeToGray, 3 }, { controls::draft::TestPatternModePn9, 4 }, }, + .sensorDelays = { + { &controls::internal::FrameDuration, 2 }, + { &controls::internal::ExposureTime, 2 }, + { &controls::internal::AnalogueGain, 1 }, + }, } }, { "imx258", { .unitCellSize = { 1120, 1120 }, @@ -89,18 +109,26 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeColorBarsFadeToGray, 3 }, { controls::draft::TestPatternModePn9, 4 }, }, + .sensorDelays = { }, } }, { "imx290", { .unitCellSize = { 2900, 2900 }, .testPatternModes = {}, + .sensorDelays = { + { &controls::internal::FrameDuration, 2 }, + { &controls::internal::ExposureTime, 2 }, + { &controls::internal::AnalogueGain, 2 }, + }, } }, { "imx296", { .unitCellSize = { 3450, 3450 }, .testPatternModes = {}, + .sensorDelays = { }, } }, { "imx477", { .unitCellSize = { 1550, 1550 }, .testPatternModes = {}, + .sensorDelays = { }, } }, { "ov2740", { .unitCellSize = { 1400, 1400 }, @@ -108,6 +136,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeOff, 0 }, { controls::draft::TestPatternModeColorBars, 1}, }, + .sensorDelays = { }, } }, { "ov5640", { .unitCellSize = { 1400, 1400 }, @@ -115,10 +144,16 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeOff, 0 }, { controls::draft::TestPatternModeColorBars, 1 }, }, + .sensorDelays = { }, } }, { "ov5647", { .unitCellSize = { 1400, 1400 }, .testPatternModes = {}, + .sensorDelays = { + { &controls::internal::FrameDuration, 2 }, + { &controls::internal::ExposureTime, 2 }, + { &controls::internal::AnalogueGain, 2 }, + }, } }, { "ov5670", { .unitCellSize = { 1120, 1120 }, @@ -126,6 +161,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeOff, 0 }, { controls::draft::TestPatternModeColorBars, 1 }, }, + .sensorDelays = { }, } }, { "ov5675", { .unitCellSize = { 1120, 1120 }, @@ -133,6 +169,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeOff, 0 }, { controls::draft::TestPatternModeColorBars, 1 }, }, + .sensorDelays = { }, } }, { "ov5693", { .unitCellSize = { 1400, 1400 }, @@ -145,6 +182,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen * Rolling Bar". */ }, + .sensorDelays = { }, } }, { "ov8865", { .unitCellSize = { 1400, 1400 }, @@ -159,6 +197,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen * 5: "Color squares with rolling bar" */ }, + .sensorDelays = { }, } }, { "ov13858", { .unitCellSize = { 1120, 1120 }, @@ -166,6 +205,7 @@ const CameraSensorProperties *CameraSensorProperties::get(const std::string &sen { controls::draft::TestPatternModeOff, 0 }, { controls::draft::TestPatternModeColorBars, 1 }, }, + .sensorDelays = { }, } }, }; From patchwork Thu Jun 30 13:38:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16468 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 838A1BE173 for ; Thu, 30 Jun 2022 13:39:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0C87A6569A; Thu, 30 Jun 2022 15:39:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596375; bh=ENxgh+HpD1p1yd5Rr9RIkQiW7aCtBzXEuxUFTVVDPp0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ZkmVlCNUuxvWBoVIOswc0R7Cw9o/VgA2cCRRzAYsTev70HjBiZXGDNedwHpRcH0Qn y802fXqYbhUxpSXFE96DVDtqqcE1ZFAehYk6SjXHxU9xIeuxchApO5MByS6SDYRTts Tpb2HxjDRgWYzZRejQst6DK3xs8cO6rTsAbYHdOuRQtmporCRpqXDL35t321uDJ4L2 8z/N+sGzRB9fpF6RCBvFAU0uRT8IdI2kYCNqjF3+LwqL+xzupYH8JM1Ehkz0I0z9cf 3uXL/Vnh8kNlAQoVYpO34iJhfJmaVWsmK7728ckGcBR/fFXKRwf0KFz7FBkhWI2U0K Bkb7M6OzeeRdg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A3E1865633 for ; Thu, 30 Jun 2022 15:39:30 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id DA3EB240005; Thu, 30 Jun 2022 13:39:29 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:49 +0200 Message-Id: <20220630133902.321099-11-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 10/23] libcamera: camera_sensor: Initialize delayed controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add to the CameraSensor class an instance of the DelayedControls class and initialize it using the sensor delays registered in camera sensor static properties. Signed-off-by: Jacopo Mondi --- include/libcamera/internal/camera_sensor.h | 3 ++ src/libcamera/camera_sensor/camera_sensor.cpp | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index 1eab5e9d53f0..bd5aa0dbc27d 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -21,6 +21,7 @@ #include #include "libcamera/internal/camera_sensor_helper.h" +#include "libcamera/internal/delayed_controls.h" #include "libcamera/internal/formats.h" #include "libcamera/internal/v4l2_subdevice.h" @@ -82,6 +83,7 @@ private: void initStaticProperties(); void initTestPatternModes(); int initProperties(); + int initDelayedControls(); int updateControls(); int applyTestPatternMode(controls::draft::TestPatternModeEnum mode); int discoverAncillaryDevices(); @@ -110,6 +112,7 @@ private: std::unique_ptr focusLens_; std::unique_ptr helper_; + std::unique_ptr delayedCtrls_; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index 976d34aaf876..211c7461f5c6 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -189,6 +189,10 @@ int CameraSensor::init() if (ret) return ret; + ret = initDelayedControls(); + if (ret) + return ret; + return applyTestPatternMode(controls::draft::TestPatternModeEnum::TestPatternModeOff); } @@ -460,6 +464,43 @@ int CameraSensor::initProperties() return 0; } +int CameraSensor::initDelayedControls() +{ + /* If no static priorities are available, all controls have delay 0. */ + static const CameraSensorProperties::SensorDelays noDelays{}; + const CameraSensorProperties::SensorDelays *delays = staticProps_ + ? &staticProps_->sensorDelays + : &noDelays; + + const std::map controlsMap{ + { V4L2_CID_ANALOGUE_GAIN, &controls::internal::AnalogueGain }, + { V4L2_CID_EXPOSURE, &controls::internal::ExposureTime }, + { V4L2_CID_VBLANK, &controls::internal::FrameDuration }, + }; + + std::unordered_map params; + for (const auto &[v4l2Ctrl, ctrl] : controlsMap) { + uint32_t delay = 0; + + /* + * If the control is not registered in the delays map, assume 0 + * as delay. + */ + auto it = delays->find(ctrl); + if (it != delays->end()) + delay = it->second; + + /* VBLANK needs the priority flag set. */ + bool priority = v4l2Ctrl == V4L2_CID_VBLANK ? true : false; + + params[v4l2Ctrl] = { delay, priority }; + } + + delayedCtrls_ = std::make_unique(device(), params); + + return 0; +} + int CameraSensor::updateControls() { if (!bayerFormat_) From patchwork Thu Jun 30 13:38:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16470 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 9ED01BE173 for ; Thu, 30 Jun 2022 13:39:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4A56E65654; Thu, 30 Jun 2022 15:39:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596379; bh=e6CA81XgDG0jDFZRuz9A0qOZSqW4ZunScIBZranHz68=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=pN7+FEk54iuBCiJG0FTqbC0kYyItI6scp546Vucuy0qSWrS0bCGeye2t+JUao8AsE hed4cjqwevePfzLyx/9W45M1JbKhjkqm5ziTRriCyeFl+d4BnNxtbzhG0fj2JLnJyk snDOq55pIQVruGfIjkpw3P23l/Q651ZcRyk7YoyXb0JviamY4z6WTc+MHH0onRYovv Cg1arSh2/femxPuYDx4DclGByZsfzIO1BFGehtxgbmcL/fHNp/TWexfVmGC7mAazDr vtjvylG0mZooSWgBXem5mylHMxNMfT7QsBBnQynu9/XQrKybsaxzACtQH/PejLey4a ux0CsrvSpiovg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A901365698 for ; Thu, 30 Jun 2022 15:39:32 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 5245524000E; Thu, 30 Jun 2022 13:39:30 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:50 +0200 Message-Id: <20220630133902.321099-12-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 11/23] libcamera: camera_sensor: Expose DelayedControls interface 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that the CameraSensor class has an instance of delayed controls expose its interface for pipeline handlers to use it. The interface towards DelayedControls still operates on lists of V4L2 controls. Signed-off-by: Jacopo Mondi --- include/libcamera/internal/camera_sensor.h | 4 +++ src/libcamera/camera_sensor/camera_sensor.cpp | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index bd5aa0dbc27d..a606bc5d1cb5 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -71,6 +71,10 @@ public: CameraLens *focusLens() { return focusLens_.get(); } + void frameStart(uint32_t sequence); + void pushControls(const ControlList &ctrls); + ControlList getControls(uint32_t sequence); + protected: std::string logPrefix() const override; diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index 211c7461f5c6..e1770e8fa130 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -1043,6 +1043,37 @@ void CameraSensor::updateControlInfo() updateControls(); } +/** + * \brief Signal to the camera sensor class that a new frame has start exposing + * \param[in] sequence The frame sequence number + */ +void CameraSensor::frameStart(uint32_t sequence) +{ + /* A new capture session requires to start in a clean state. */ + if (sequence == 0) + delayedCtrls_->reset(); + + delayedCtrls_->applyControls(sequence); +} + +/** + * \brief Push a new set of controls to the CameraSensor + * \param[in] ctrls The list of controls to push to the sensor + */ +void CameraSensor::pushControls(const ControlList &ctrls) +{ + delayedCtrls_->push(ctrls); +} + +/** + * \brief Get the list of controls applied at frame \a sequence + * \param[in] sequence The frame sequence number + */ +ControlList CameraSensor::getControls(uint32_t sequence) +{ + return delayedCtrls_->get(sequence); +} + /** * \fn CameraSensor::focusLens() * \brief Retrieve the focus lens controller From patchwork Thu Jun 30 13:38:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16469 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 9FCAFC3273 for ; Thu, 30 Jun 2022 13:39:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 59BD3656A8; Thu, 30 Jun 2022 15:39:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596380; bh=n67kfmPtKbblafw6iA5kXJUSwapYI5FBnoFF2b5ESug=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=JqRoca3wxQfkWeQDn5JJTnJR5gXzGe1MnbJPRoaNgEhwspcoPWolUFo26xWA9QtbP U1LJSYaPakQ8gaShQlhF2zyysXKnF57eKFt2C0OnstqjSTik6VVLyWdGKk9tVQ3aBs 2v/HKi3myAgsndFJU/IOClVq0nr/K/NZqnidqUr5XEY4Hg+j0eUidOIerviklqbOU1 KWl0CqBASYNtvF32qOwBs4HaaQbGSp5G1t+ZpLiVXV01IQWMH1QjYy6SBnb1hZEXum 3Ue2iQfMBF7L3jiiNK4I0B/0q/dZDrHjUnh8NAGHeIsKHmdXJ8oRr42q/m0tLn4gHn 6RAr3RqxltOeA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 332BD65699 for ; Thu, 30 Jun 2022 15:39:34 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id DCA2F240015; Thu, 30 Jun 2022 13:39:32 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:51 +0200 Message-Id: <20220630133902.321099-13-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 12/23] libcamera: ipu3: Drop DelayedControls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that the CameraSensor class exposes the DelayedControl interface use the sensor to operate controls. Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 85e5f8a70408..a5a35b6585c6 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -26,7 +26,6 @@ #include "libcamera/internal/camera.h" #include "libcamera/internal/camera_lens.h" #include "libcamera/internal/camera_sensor.h" -#include "libcamera/internal/delayed_controls.h" #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/framebuffer.h" #include "libcamera/internal/ipa_manager.h" @@ -74,7 +73,6 @@ public: bool supportsFlips_; Transform rotationTransform_; - std::unique_ptr delayedCtrls_; IPU3Frames frameInfos_; std::unique_ptr ipa_; @@ -785,8 +783,6 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] const ControlLis if (ret) goto error; - data->delayedCtrls_->reset(); - /* * Start the ImgU video devices, buffers will be queued to the * ImgU output and viewfinder when requests will be queued. @@ -1136,9 +1132,6 @@ int PipelineHandlerIPU3::registerCameras() { V4L2_CID_EXPOSURE, { 2, false } }, }; - data->delayedCtrls_ = - std::make_unique(cio2->sensor()->device(), - params); data->cio2_.frameStart().connect(data.get(), &IPU3CameraData::frameStart); @@ -1258,9 +1251,11 @@ void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id, const ControlList &sensorControls, const ControlList &lensControls) { - delayedCtrls_->push(sensorControls); + CameraSensor *sensor = cio2_.sensor(); + + sensor->pushControls(sensorControls); - CameraLens *focusLens = cio2_.sensor()->focusLens(); + CameraLens *focusLens = sensor->focusLens(); if (!focusLens) return; @@ -1375,7 +1370,7 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer) request->metadata().set(controls::SensorTimestamp, buffer->metadata().timestamp); - info->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence); + info->effectiveSensorControls = cio2_.sensor()->getControls(buffer->metadata().sequence); if (request->findBuffer(&rawStream_)) pipe()->completeBuffer(request, buffer); @@ -1441,7 +1436,7 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer) */ void IPU3CameraData::frameStart(uint32_t sequence) { - delayedCtrls_->applyControls(sequence); + cio2_.sensor()->frameStart(sequence); if (processingRequests_.empty()) return; From patchwork Thu Jun 30 13:38:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16472 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 3D6DCC3275 for ; Thu, 30 Jun 2022 13:39:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DFA3E656AA; Thu, 30 Jun 2022 15:39:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596382; bh=9E+htababTQRwiAXk97E3/6MTUzUihKkQXjRjDhKrec=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=AhMLkuOJPozAg16ySDICfLdpz1j/9MG8FkBmCDxwaXaqWCPfStL0DG1T6p6BZJHi9 D+5Cp2NOaT3MbJ9y02nypCBJex2l37b0AJEykPiD9DnK6VfCA+Zqd+tDj3D4ed+CEP XJRkZDYoPTDOl3jEINOocKCupCNLg8urAk1mldfd6aSj/sN3+6kmNAQTNvWPAcQoTd nUPTNhDlLflnW15IX7GL6oshrot6DPbbsuj4mjbFWQ0Ln2KMoocdxf3yjMhkMssiho sScFU1NibWlT13m/QW3wKlEhtwONwqz1sjLndh960FQFNp5JgDkYv4HvfOLNl1E1R5 yP4akI2OP8bTA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CB7BB65658 for ; Thu, 30 Jun 2022 15:39:35 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id CBFA2240010; Thu, 30 Jun 2022 13:39:34 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:52 +0200 Message-Id: <20220630133902.321099-14-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 13/23] libcamera: camera_sensor: Cache the sensor configuration 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The sensor configuration parameters, which include the output format the blanking lengths and the current pixel rate, are updated everytime a new format is set on the sensor. The sensor configuration parameters will be used in order to translate libcamera controls in the corresponding V4L2 control values (and vice-versa). The same parameters are also used to populate the CameraSensorInfo to pass it to IPA modules. In order to avoid re-querying the V4L2 subdevice for the control values and the output format everytime, cache the current sensor configuration in a class member field, updated when a new format is set on the sensor and at initialization time. As the function that updates the configuration was originally only meant to update the CameraSensor ControlInfoMap limits, rename it from updateControls() to updateConfiguration(). Signed-off-by: Jacopo Mondi --- include/libcamera/internal/camera_sensor.h | 9 ++- src/libcamera/camera_sensor/camera_sensor.cpp | 69 +++++++------------ 2 files changed, 32 insertions(+), 46 deletions(-) diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index a606bc5d1cb5..bb9327646bc1 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -81,6 +81,13 @@ protected: private: LIBCAMERA_DISABLE_COPY(CameraSensor) + struct { + V4L2SubdeviceFormat outputFormat; + uint64_t pixelRate; + uint32_t hblank; + double lineDuration; + } config_; + int generateId(); int validateSensorDriver(); void initVimcDefaultProperties(); @@ -88,7 +95,7 @@ private: void initTestPatternModes(); int initProperties(); int initDelayedControls(); - int updateControls(); + int updateConfiguration(); int applyTestPatternMode(controls::draft::TestPatternModeEnum mode); int discoverAncillaryDevices(); diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index e1770e8fa130..cc4cbd4ad509 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -181,7 +181,7 @@ int CameraSensor::init() return -ENODEV; } - ret = updateControls(); + ret = updateConfiguration(); if (ret) return ret; @@ -501,7 +501,7 @@ int CameraSensor::initDelayedControls() return 0; } -int CameraSensor::updateControls() +int CameraSensor::updateConfiguration() { if (!bayerFormat_) return 0; @@ -511,12 +511,11 @@ int CameraSensor::updateControls() /* The subdev driver has been validate already, the controls are there! */ ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE, V4L2_CID_HBLANK }); - uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get(); - uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get(); + config_.pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get(); + config_.hblank = subdevControls.get(V4L2_CID_HBLANK).get(); /* Assume the sensor has a single source pad #0. */ - V4L2SubdeviceFormat subdevFormat; - subdev_->getFormat(0, &subdevFormat); + subdev_->getFormat(0, &config_.outputFormat); const ControlInfoMap &subdevControlsInfo = subdev_->controls(); @@ -526,12 +525,14 @@ int CameraSensor::updateControls() * get exposure min, max and default and convert it from lines to * microseconds. */ - uint32_t lineLength = subdevFormat.size.width + hblank; - double lineDuration = lineLength / (pixelRate / 1000000.0F); - const ControlInfo &v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE); - int32_t minExposure = v4l2Exposure.min().get() * lineDuration; - int32_t maxExposure = v4l2Exposure.max().get() * lineDuration; - int32_t defExposure = v4l2Exposure.def().get() * lineDuration; + const Size &outputSize = config_.outputFormat.size; + uint32_t lineLength = outputSize.width + config_.hblank; + config_.lineDuration = lineLength / (config_.pixelRate / 1000000.0F); + + ControlInfo v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE); + int32_t minExposure = v4l2Exposure.min().get() * config_.lineDuration; + int32_t maxExposure = v4l2Exposure.max().get() * config_.lineDuration; + int32_t defExposure = v4l2Exposure.def().get() * config_.lineDuration; controlsMap[&controls::internal::ExposureTime] = ControlInfo(minExposure, maxExposure, defExposure); @@ -544,15 +545,15 @@ int CameraSensor::updateControls() */ const ControlInfo &v4l2VBlank = subdevControlsInfo.at(V4L2_CID_VBLANK); std::array frameHeights{ - v4l2VBlank.min().get() + subdevFormat.size.height, - v4l2VBlank.max().get() + subdevFormat.size.height, - v4l2VBlank.def().get() + subdevFormat.size.height, + v4l2VBlank.min().get() + outputSize.height, + v4l2VBlank.max().get() + outputSize.height, + v4l2VBlank.def().get() + outputSize.height, }; std::array frameDurations; for (unsigned int i = 0; i < frameHeights.size(); ++i) { uint64_t frameSize = lineLength * frameHeights[i]; - frameDurations[i] = frameSize / (pixelRate / 1000000.0F); + frameDurations[i] = frameSize / (config_.pixelRate / 1000000.0F); } controlsMap[&controls::internal::FrameDuration] = @@ -989,6 +990,8 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const << "The analogue crop rectangle has been defaulted to the active area size"; } + const ControlInfo vblank = subdev_->controls().at(V4L2_CID_VBLANK); + /* * IPACameraSensorInfo::analogCrop::x and IPACameraSensorInfo::analogCrop::y * are defined relatively to the active pixel area, while V4L2's @@ -998,34 +1001,10 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const */ info->analogCrop.x -= activeArea_.x; info->analogCrop.y -= activeArea_.y; - - /* The bit depth and image size depend on the currently applied format. */ - V4L2SubdeviceFormat format{}; - ret = subdev_->getFormat(pad_, &format); - if (ret) - return ret; - info->bitsPerPixel = format.bitsPerPixel(); - info->outputSize = format.size; - - /* - * Retrieve the pixel rate, line length and minimum/maximum frame - * duration through V4L2 controls. Support for the V4L2_CID_PIXEL_RATE, - * V4L2_CID_HBLANK and V4L2_CID_VBLANK controls is mandatory. - */ - ControlList ctrls = subdev_->getControls({ V4L2_CID_PIXEL_RATE, - V4L2_CID_HBLANK, - V4L2_CID_VBLANK }); - if (ctrls.empty()) { - LOG(CameraSensor, Error) - << "Failed to retrieve camera info controls"; - return -EINVAL; - } - - int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get(); - info->lineLength = info->outputSize.width + hblank; - info->pixelRate = ctrls.get(V4L2_CID_PIXEL_RATE).get(); - - const ControlInfo vblank = ctrls.infoMap()->at(V4L2_CID_VBLANK); + info->bitsPerPixel = config_.outputFormat.bitsPerPixel(); + info->outputSize = config_.outputFormat.size; + info->lineLength = info->outputSize.width + config_.hblank; + info->pixelRate = config_.pixelRate; info->minFrameLength = info->outputSize.height + vblank.min().get(); info->maxFrameLength = info->outputSize.height + vblank.max().get(); @@ -1040,7 +1019,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const void CameraSensor::updateControlInfo() { subdev_->updateControlInfo(); - updateControls(); + updateConfiguration(); } /** From patchwork Thu Jun 30 13:38:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16471 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 38F72C3274 for ; Thu, 30 Jun 2022 13:39:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 650EB6564E; Thu, 30 Jun 2022 15:39:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596383; bh=9ySY97JDsTSmnDSL7AIXOmHeC6+kW/Mb73b7umzzwqs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=pkAn96Ad3BRrJDKlRqIPqbBlIE8hSVfXoghd4FxVk71+QECN0KN4Gl0/7W2f1kbhp J6rcUH8w8yvr/l+kV/jPiuJ/xd5DU+/wqPEdQ8Mx7ffs2VEWqf5azLQxXM3oAiphep cY4GNuP/Dj4X/lXaDdWLzLWM4qARvfHd4qEIP6+j/WMJnO8QNqmdMS4ory9VnwReeR SSmlZuwlR8kZzNkUW0Y0Fp5ERi3mmspvr/lH4mn/U2UuPWGCTO2UohmhAtPQkxSGsL 8RHxOIaEYwBSKHf3VvsFjg7jC84KE9Yg22o1cf73Ia6zROoKwRdtKmra31sQxnfxFo m5UwliY40KbcA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BDA4665699 for ; Thu, 30 Jun 2022 15:39:36 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 074B8240007; Thu, 30 Jun 2022 13:39:35 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:53 +0200 Message-Id: <20220630133902.321099-15-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 14/23] libcamera: camera_sensor: Translate libcamera/V4L2 controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In the process of moving the CameraSensor class control interface to use libcamera::internal controls modify the CameraSensor::pushControls() and CameraSensor::getControls() to use lists of libcamera controls and translate to and from V4L2 controls to interface with DelayedControls, which will actually take care of applying controls to the V4L2 subdevice. Signed-off-by: Jacopo Mondi --- src/libcamera/camera_sensor/camera_sensor.cpp | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index cc4cbd4ad509..02810c7c5ad0 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -1038,19 +1038,82 @@ void CameraSensor::frameStart(uint32_t sequence) /** * \brief Push a new set of controls to the CameraSensor * \param[in] ctrls The list of controls to push to the sensor + * + * \a ctrls contains a list of libcamera::controls::internal controls */ void CameraSensor::pushControls(const ControlList &ctrls) { - delayedCtrls_->push(ctrls); + ControlList v4l2Ctrls(subdev_->controls()); + + /* + * DelayedControls applies V4L2 controls for us to the subdevice. + * Translate here between libcamera controls and V4L2 controls. + * + * The currently supported controls are V4L2_CID_VBLANK, + * V4L2_CID_EXPOSURE and V4L2_CID_ANALOGUE_GAIN. + */ + + if (ctrls.contains(controls::internal::AnalogueGain)) { + float gain = ctrls.get(controls::internal::AnalogueGain); + int32_t gainCode = helper_->gainCode(gain); + + v4l2Ctrls.set(V4L2_CID_ANALOGUE_GAIN, ControlValue(gainCode)); + } + + if (ctrls.contains(controls::internal::ExposureTime)) { + uint32_t exposureTime = ctrls.get(controls::internal::ExposureTime); + int32_t exposure = exposureTime / config_.lineDuration; + + v4l2Ctrls.set(V4L2_CID_EXPOSURE, ControlValue(exposure)); + } + + if (ctrls.contains(controls::internal::FrameDuration)) { + uint64_t duration = ctrls.get(controls::internal::FrameDuration); + uint32_t frameSize = duration / (1000000.0F / config_.pixelRate); + uint32_t lineLength = config_.outputFormat.size.width + config_.hblank; + int32_t vblank = frameSize / lineLength - config_.outputFormat.size.height; + + v4l2Ctrls.set(V4L2_CID_VBLANK, vblank); + } + + delayedCtrls_->push(v4l2Ctrls); } /** * \brief Get the list of controls applied at frame \a sequence * \param[in] sequence The frame sequence number + * + * The returned controls list contains libcamera::controls::internal controls */ ControlList CameraSensor::getControls(uint32_t sequence) { - return delayedCtrls_->get(sequence); + ControlList ctrls(controls::internal::controls); + ControlList v4l2Ctrls = delayedCtrls_->get(sequence); + + if (v4l2Ctrls.contains(V4L2_CID_ANALOGUE_GAIN)) { + uint32_t gainCode = v4l2Ctrls.get(V4L2_CID_ANALOGUE_GAIN).get(); + float gain = static_cast(helper_->gain(gainCode)); + + ctrls.set(controls::internal::AnalogueGain, gain); + } + + if (v4l2Ctrls.contains(V4L2_CID_EXPOSURE)) { + uint32_t exposure = v4l2Ctrls.get(V4L2_CID_EXPOSURE).get(); + uint32_t exposureTime = exposure * config_.lineDuration; + + ctrls.set(controls::internal::ExposureTime, exposureTime); + } + + if (v4l2Ctrls.contains(V4L2_CID_VBLANK)) { + uint32_t vblank = v4l2Ctrls.get(V4L2_CID_VBLANK).get(); + uint32_t frameSize = (config_.outputFormat.size.width + config_.hblank) + * (config_.outputFormat.size.height + vblank); + uint64_t duration = frameSize / (config_.pixelRate / 1000000.0F); + + ctrls.set(controls::internal::FrameDuration, duration); + } + + return ctrls; } /** From patchwork Thu Jun 30 13:38:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16473 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 5520AC3273 for ; Thu, 30 Jun 2022 13:39:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E068E656AC; Thu, 30 Jun 2022 15:39:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596385; bh=jpm1bAu1PHHZy4fnkMag/Lb87tUq5kBmNOIsvRnDuMg=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=OEW+q2Qrm38sR5rhoAVPdDy33r+gd11tEhcmVD0AIPXXh18Ix7QhQCnOyzGJsuKqQ 9TI7vrhT3SMGyYF3xxcKBAjp8afxGSDqm6/+wo0r0cMOp0TsTi9XI42wG8X/lXwqsu lhYHYi2aXw5FVMLkBSOmE7sWM8tTHtG3IbB3dxe7l3GNzMtI9kdQxM/PoBLzYPerwJ 4iEopbYXh4LSuBEDtwdIsujD89vY3oTColNVCV8zyILJbd5wBeeyursgLUslxJO4A5 w1Lh1cIsT6cB9v3utcIwjGURjFAyBQzE5+MzGdjAE1VuQsrHfbrjUQRnjQeOB/KlkC kiiqqZy6j4EFQ== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 21AAC65656 for ; Thu, 30 Jun 2022 15:39:38 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 10A0024000A; Thu, 30 Jun 2022 13:39:36 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:54 +0200 Message-Id: <20220630133902.321099-16-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 15/23] libcamera: ipu3: Initialize controls in the pipeline 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Currently the map of V4L2 controls collected from the sensor is passed to the IPA module which initializes Camera controls by inspecting the sensor control values. As the CameraSensor class translates V4L2 controls into libcamera::internal controls, the Camera controls can be initialized directly in the pipeline handler, without sending them to the IPA which receives all the information it needs using the CameraSensorInfo. Remove from the IPA interface the list of V4L2 controls from the sensor sent to the IPA as it is not used anymore and initialize Camera controls in the pipeline directly. Signed-off-by: Jacopo Mondi --- include/libcamera/ipa/ipu3.mojom | 7 +-- src/ipa/ipu3/ipu3.cpp | 86 ++-------------------------- src/libcamera/pipeline/ipu3/ipu3.cpp | 32 ++++++----- 3 files changed, 25 insertions(+), 100 deletions(-) diff --git a/include/libcamera/ipa/ipu3.mojom b/include/libcamera/ipa/ipu3.mojom index d1b1c6b867da..5818cd3a6846 100644 --- a/include/libcamera/ipa/ipu3.mojom +++ b/include/libcamera/ipa/ipu3.mojom @@ -18,14 +18,13 @@ struct IPAConfigInfo { interface IPAIPU3Interface { init(libcamera.IPASettings settings, - libcamera.IPACameraSensorInfo sensorInfo, - libcamera.ControlInfoMap sensorControls) - => (int32 ret, libcamera.ControlInfoMap ipaControls); + libcamera.IPACameraSensorInfo sensorInfo) + => (int32 ret); start() => (int32 ret); stop(); configure(IPAConfigInfo configInfo) - => (int32 ret, libcamera.ControlInfoMap ipaControls); + => (int32 ret); mapBuffers(array buffers); unmapBuffers(array ids); diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 2f6bb672f7bb..a6e5dcbaada9 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -132,15 +132,12 @@ class IPAIPU3 : public IPAIPU3Interface { public: int init(const IPASettings &settings, - const IPACameraSensorInfo &sensorInfo, - const ControlInfoMap &sensorControls, - ControlInfoMap *ipaControls) override; + const IPACameraSensorInfo &sensorInfo) override; int start() override; void stop() override; - int configure(const IPAConfigInfo &configInfo, - ControlInfoMap *ipaControls) override; + int configure(const IPAConfigInfo &configInfo) override; void mapBuffers(const std::vector &buffers) override; void unmapBuffers(const std::vector &ids) override; @@ -151,9 +148,6 @@ public: const uint32_t bufferId, const ControlList &sensorControls) override; private: - void updateControls(const IPACameraSensorInfo &sensorInfo, - const ControlInfoMap &sensorControls, - ControlInfoMap *ipaControls); void updateSessionConfiguration(const ControlInfoMap &sensorControls); bool validateSensorControls(); @@ -208,68 +202,6 @@ void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain); } -/** - * \brief Compute camera controls using the sensor information and the sensor - * V4L2 controls - * - * Some of the camera controls are computed by the pipeline handler, some others - * by the IPA module which is in charge of handling, for example, the exposure - * time and the frame duration. - * - * This function computes: - * - controls::ExposureTime - * - controls::FrameDurationLimits - */ -void IPAIPU3::updateControls(const IPACameraSensorInfo &sensorInfo, - const ControlInfoMap &sensorControls, - ControlInfoMap *ipaControls) -{ - ControlInfoMap::Map controls{}; - double lineDuration = context_.configuration.sensor.lineDuration.get(); - - /* - * Compute exposure time limits by using line length and pixel rate - * converted to microseconds. Use the V4L2_CID_EXPOSURE control to get - * exposure min, max and default and convert it from lines to - * microseconds. - */ - const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second; - int32_t minExposure = v4l2Exposure.min().get() * lineDuration; - int32_t maxExposure = v4l2Exposure.max().get() * lineDuration; - int32_t defExposure = v4l2Exposure.def().get() * lineDuration; - controls[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure, - defExposure); - - /* - * Compute the frame duration limits. - * - * The frame length is computed assuming a fixed line length combined - * with the vertical frame sizes. - */ - const ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second; - uint32_t hblank = v4l2HBlank.def().get(); - uint32_t lineLength = sensorInfo.outputSize.width + hblank; - - const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second; - std::array frameHeights{ - v4l2VBlank.min().get() + sensorInfo.outputSize.height, - v4l2VBlank.max().get() + sensorInfo.outputSize.height, - v4l2VBlank.def().get() + sensorInfo.outputSize.height, - }; - - std::array frameDurations; - for (unsigned int i = 0; i < frameHeights.size(); ++i) { - uint64_t frameSize = lineLength * frameHeights[i]; - frameDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U); - } - - controls[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0], - frameDurations[1], - frameDurations[2]); - - *ipaControls = ControlInfoMap(std::move(controls), controls::controls); -} - /** * \brief Validate that the sensor controls mandatory for the IPA exists */ @@ -300,9 +232,7 @@ bool IPAIPU3::validateSensorControls() * them in the \a ipaControls output parameter. */ int IPAIPU3::init(const IPASettings &settings, - const IPACameraSensorInfo &sensorInfo, - const ControlInfoMap &sensorControls, - ControlInfoMap *ipaControls) + const IPACameraSensorInfo &sensorInfo) { camHelper_ = CameraSensorHelperFactory::create(settings.sensorModel); if (camHelper_ == nullptr) { @@ -323,9 +253,6 @@ int IPAIPU3::init(const IPASettings &settings, algorithms_.push_back(std::make_unique()); algorithms_.push_back(std::make_unique()); - /* Initialize controls. */ - updateControls(sensorInfo, sensorControls, ipaControls); - return 0; } @@ -423,7 +350,6 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) * \brief Configure the IPU3 IPA * \param[in] configInfo The IPA configuration data, received from the pipeline * handler - * \param[in] ipaControls The IPA controls to update * * Calculate the best grid for the statistics based on the pipeline handler BDS * output, and parse the minimum and maximum exposure and analogue gain control @@ -434,8 +360,7 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) * All algorithm modules are called to allow them to prepare the * \a IPASessionConfiguration structure for the \a IPAContext. */ -int IPAIPU3::configure(const IPAConfigInfo &configInfo, - ControlInfoMap *ipaControls) +int IPAIPU3::configure(const IPAConfigInfo &configInfo) { if (configInfo.sensorControls.empty()) { LOG(IPAIPU3, Error) << "No sensor controls provided"; @@ -464,9 +389,6 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo, return -EINVAL; } - /* Update the camera controls using the new sensor settings. */ - updateControls(sensorInfo_, sensorCtrls_, ipaControls); - /* Update the IPASessionConfiguration using the sensor settings. */ updateSessionConfiguration(sensorCtrls_); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index a5a35b6585c6..8c5b6c36ae0b 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -26,6 +26,7 @@ #include "libcamera/internal/camera.h" #include "libcamera/internal/camera_lens.h" #include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/control_ids.h" #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/framebuffer.h" #include "libcamera/internal/ipa_manager.h" @@ -82,8 +83,6 @@ public: /* Requests queued to the CIO2 device but not yet processed by the ImgU. */ std::queue processingRequests_; - ControlInfoMap ipaControls_; - private: void metadataReady(unsigned int id, const ControlList &metadata); void paramsBufferReady(unsigned int id); @@ -670,7 +669,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) configInfo.bdsOutputSize = config->imguConfig().bds; configInfo.iif = config->imguConfig().iif; - ret = data->ipa_->configure(configInfo, &data->ipaControls_); + ret = data->ipa_->configure(configInfo); if (ret) { LOG(IPU3, Error) << "Failed to configure IPA: " << strerror(-ret); @@ -946,9 +945,6 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) * Initialize the camera controls by calculating controls which the pipeline * is reponsible for and merge them with the controls computed by the IPA. * - * This function needs data->ipaControls_ to be initialized by the IPA init() - * function at camera creation time. Always call this function after IPA init(). - * * \return 0 on success or a negative error code otherwise */ int PipelineHandlerIPU3::initControls(IPU3CameraData *data) @@ -978,9 +974,6 @@ int PipelineHandlerIPU3::initControls(IPU3CameraData *data) * Compute the camera controls by calculating controls which the pipeline * is reponsible for and merge them with the controls computed by the IPA. * - * This function needs data->ipaControls_ to be refreshed when a new - * configuration is applied to the camera by the IPA configure() function. - * * Always call this function after IPA configure() to make sure to have a * properly refreshed IPA controls list. * @@ -1059,9 +1052,21 @@ int PipelineHandlerIPU3::updateControls(IPU3CameraData *data) controls[&controls::ScalerCrop] = ControlInfo(minCrop, maxCrop, maxCrop); - /* Add the IPA registered controls to list of camera controls. */ - for (const auto &ipaControl : data->ipaControls_) - controls[ipaControl.first] = ipaControl.second; + /* + * Translate the sensor controls to Camera controls. + * + * Exposure time and the frame duration limits are reported directly + * from the sensor. + */ + const ControlInfoMap &sensorControls = sensor->controls(); + + if (sensorControls.count(&controls::internal::ExposureTime)) + controls[&controls::ExposureTime] = + sensorControls.at(&controls::internal::ExposureTime); + + if (sensorControls.count(&controls::internal::FrameDuration)) + controls[&controls::FrameDurationLimits] = + sensorControls.at(&controls::internal::FrameDuration); data->controlInfo_ = ControlInfoMap(std::move(controls), controls::controls); @@ -1237,8 +1242,7 @@ int IPU3CameraData::loadIPA() if (ret) return ret; - ret = ipa_->init(IPASettings{ "", sensor->model() }, sensorInfo, - sensor->v4l2Controls(), &ipaControls_); + ret = ipa_->init(IPASettings{ "", sensor->model() }, sensorInfo); if (ret) { LOG(IPU3, Error) << "Failed to initialise the IPU3 IPA"; return ret; From patchwork Thu Jun 30 13:38:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16474 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 B4FF3BE173 for ; Thu, 30 Jun 2022 13:39:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 568C7656B0; Thu, 30 Jun 2022 15:39:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596388; bh=foCxZ0go4cL640cwJ1RY+DLYNuS4Pp9tGf3lwEIiy6U=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=dmJZSZ+hQsVDRp0DKDQ7za2us2BXYgAzcA9Ix5paFb1g+Axna4/2xfUBmlSkunJ9j n8o/h9pP8q7CPH2eyNLn+xMjelgBCXWZt1l/OWmW4iRd851bQd4Mc4Vae6agCeu6TC sk+cm2ii/pJFnXqukKeiXF0d5AC4bCOU0wlc14iinG4CEV6UaDDcz2tMDWTAQri5Mo Zb+Jw61tiHliopN/iEQV4wQ0n1CQE4JfxXRFi5g8EmYoTKjFaVVrFlViPGAlFHN0Re 7T6k0P2JTXcVNymJwfAuEhTRr1Xh55SYdDCLP/oI2Hy86AlHezZkmTvbCWvTuO7BSL TsX7Pe/KXIwlQ== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C914D6564F for ; Thu, 30 Jun 2022 15:39:39 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 7E23A24000A; Thu, 30 Jun 2022 13:39:38 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:55 +0200 Message-Id: <20220630133902.321099-17-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 16/23] libcamera: IPACameraSensorInfo: Add VBLANK 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The IPA module needs the vertical blanking value to calculate the total frame size. In order to prepare removing usage of V4L2_CID_VBLANK in IPA modules, add the vblank value to the IPACameraSensorInfo structure. Signed-off-by: Jacopo Mondi --- include/libcamera/ipa/core.mojom | 6 ++++++ src/libcamera/camera_sensor/camera_sensor.cpp | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom index 74f3339e56f2..d122fb7add4d 100644 --- a/include/libcamera/ipa/core.mojom +++ b/include/libcamera/ipa/core.mojom @@ -178,6 +178,11 @@ module libcamera; * The total line length in pixel clock periods, including blanking. */ +/** + * \var IPACameraSensorInfo::vblank + * \brief The vertical blanking, expressed in number of lines + */ + /** * \var IPACameraSensorInfo::minFrameLength * \brief The minimum allowable frame length in units of lines @@ -218,6 +223,7 @@ struct IPACameraSensorInfo { uint64 pixelRate; uint32 lineLength; + uint32 vblank; uint32 minFrameLength; uint32 maxFrameLength; diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp index 02810c7c5ad0..08b96b9c3b40 100644 --- a/src/libcamera/camera_sensor/camera_sensor.cpp +++ b/src/libcamera/camera_sensor/camera_sensor.cpp @@ -1008,6 +1008,21 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const info->minFrameLength = info->outputSize.height + vblank.min().get(); info->maxFrameLength = info->outputSize.height + vblank.max().get(); + /* + * Retrieve the vertical blanking. + * + * We can't rely on the valued cached as vblank can be modified while + * streaming to adjust the frame rate. + */ + ControlList ctrls = subdev_->getControls({ V4L2_CID_VBLANK }); + if (ctrls.empty()) { + LOG(CameraSensor, Error) + << "Failed to retrieve camera info controls"; + return -EINVAL; + } + + info->vblank = ctrls.get(V4L2_CID_VBLANK).get(); + return 0; } From patchwork Thu Jun 30 13:38:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16475 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 2429DBE173 for ; Thu, 30 Jun 2022 13:39:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B43BC65696; Thu, 30 Jun 2022 15:39:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596389; bh=4rac9Rtmiyxlxc19x7gSaPtGSORbrQUteRJ1HerjVew=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=iPo78SBra71VkV0QZEhIdu3HFYlQAUCuEt2MLNSlV50p9yOF5yU2CNbrG1U/hnx6b QUcvU03xAZ/k3VI+6/Pd+q0DrSg3wjpdt2K+WeoU4npG8now5ydCBf3PKpdIqnNEJn 8Ujfy1ccjDJBVa6PvM56SpJ7PHNgdMZZwLHYAdMRRFBUEwGdVVT99NtxErdU1qAsnY BS1KkUe3RWJn8YdpwQLDwtplb4ACkHhJilNlKNr3Q1Q6UypQVfc5FGyWbSqCozdZKO JjHN5+lxAK5gAcmBeaXZy9axIhQfT7Xf+UA2WPSkKu81ifb6ELGXnbG0tFGlDyo5TA gb6nh2SY0TnIw== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D0BD96569B for ; Thu, 30 Jun 2022 15:39:41 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id B402924000F; Thu, 30 Jun 2022 13:39:39 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:56 +0200 Message-Id: <20220630133902.321099-18-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 17/23] ipa: ipu3: Configure IPA with libcamera controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Pass to the IPA configure() function the list of libcamera controls::internal controls in place of sending to the IPA the raw V4L2 control values. As V4L2 controls are removed from the list of arguments passed to IPA::configure(), fetch the vertical blanking value from the CameraSensorInfo now that it is available there. While at it, rationalize the sequence of operations IPA::configure() to: - check the validity of the configuration - update the session configuration - configure algorithm - assign class member variables Signed-off-by: Jacopo Mondi --- src/ipa/ipu3/ipa_context.cpp | 4 +- src/ipa/ipu3/ipa_context.h | 2 +- src/ipa/ipu3/ipu3.cpp | 79 +++++++++++----------------- src/libcamera/pipeline/ipu3/ipu3.cpp | 2 +- 4 files changed, 36 insertions(+), 51 deletions(-) diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp index 13cdb835ef7f..06fdf2a1efc7 100644 --- a/src/ipa/ipu3/ipa_context.cpp +++ b/src/ipa/ipu3/ipa_context.cpp @@ -126,8 +126,8 @@ namespace libcamera::ipa::ipu3 { * \var IPASessionConfiguration::sensor.lineDuration * \brief Line duration in microseconds * - * \var IPASessionConfiguration::sensor.defVBlank - * \brief The default vblank value of the sensor + * \var IPASessionConfiguration::sensor.vBlank + * \brief The vertical blanking expressed in number of lines */ /** diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index 42e11141d3a1..a5b878ab7792 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -43,7 +43,7 @@ struct IPASessionConfiguration { } agc; struct { - int32_t defVBlank; + int32_t vBlank; utils::Duration lineDuration; } sensor; }; diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index a6e5dcbaada9..44a7d13225df 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -28,6 +28,7 @@ #include #include +#include "libcamera/internal/control_ids.h" #include "libcamera/internal/mapped_framebuffer.h" #include "algorithms/af.h" @@ -148,9 +149,9 @@ public: const uint32_t bufferId, const ControlList &sensorControls) override; private: - void updateSessionConfiguration(const ControlInfoMap &sensorControls); + void updateSessionConfiguration(const IPAConfigInfo &info); - bool validateSensorControls(); + bool validateSensorControls(const ControlInfoMap &sensorControls); void setControls(unsigned int frame); void calculateBdsGrid(const Size &bdsOutputSize); @@ -176,18 +177,12 @@ private: * \brief Compute IPASessionConfiguration using the sensor information and the * sensor V4L2 controls */ -void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) +void IPAIPU3::updateSessionConfiguration(const IPAConfigInfo &info) { - const ControlInfo vBlank = sensorControls.find(V4L2_CID_VBLANK)->second; - context_.configuration.sensor.defVBlank = vBlank.def().get(); + const IPACameraSensorInfo &sensorInfo = info.sensorInfo; + context_.configuration.sensor.vBlank = sensorInfo.vblank; - const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second; - int32_t minExposure = v4l2Exposure.min().get(); - int32_t maxExposure = v4l2Exposure.max().get(); - - const ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second; - int32_t minGain = v4l2Gain.min().get(); - int32_t maxGain = v4l2Gain.max().get(); + const ControlInfoMap &sensorControls = info.sensorControls; /* * When the AGC computes the new exposure values for a frame, it needs @@ -196,27 +191,30 @@ void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) * * \todo take VBLANK into account for maximum shutter speed */ - context_.configuration.agc.minShutterSpeed = minExposure * context_.configuration.sensor.lineDuration; - context_.configuration.agc.maxShutterSpeed = maxExposure * context_.configuration.sensor.lineDuration; - context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain); - context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain); + const ControlInfo &exposure = sensorControls.at(&controls::internal::ExposureTime); + context_.configuration.agc.minShutterSpeed = exposure.min().get() * 1.0us; + context_.configuration.agc.maxShutterSpeed = exposure.max().get() * 1.0us; + + const ControlInfo &gain = sensorControls.at(&controls::internal::AnalogueGain); + context_.configuration.agc.minAnalogueGain = gain.min().get(); + context_.configuration.agc.maxAnalogueGain = gain.max().get(); } /** * \brief Validate that the sensor controls mandatory for the IPA exists */ -bool IPAIPU3::validateSensorControls() +bool IPAIPU3::validateSensorControls(const ControlInfoMap &sensorControls) { - static const uint32_t ctrls[] = { - V4L2_CID_ANALOGUE_GAIN, - V4L2_CID_EXPOSURE, - V4L2_CID_VBLANK, + static constexpr std::array ctrls = { + &controls::internal::ExposureTime, + &controls::internal::FrameDuration, + &controls::internal::AnalogueGain, }; - for (auto c : ctrls) { - if (sensorCtrls_.find(c) == sensorCtrls_.end()) { + for (const ControlId *c : ctrls) { + if (sensorControls.find(c) == sensorControls.end()) { LOG(IPAIPU3, Error) << "Unable to find sensor control " - << utils::hex(c); + << c->name(); return false; } } @@ -362,35 +360,19 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) */ int IPAIPU3::configure(const IPAConfigInfo &configInfo) { - if (configInfo.sensorControls.empty()) { - LOG(IPAIPU3, Error) << "No sensor controls provided"; - return -ENODATA; + if (!validateSensorControls(configInfo.sensorControls)) { + LOG(IPAIPU3, Error) << "Sensor control validation failed."; + return -EINVAL; } - sensorInfo_ = configInfo.sensorInfo; - - lensCtrls_ = configInfo.lensControls; - - /* - * Compute the sensor V4L2 controls to be used by the algorithms and - * to be set on the sensor. - */ - sensorCtrls_ = configInfo.sensorControls; - - calculateBdsGrid(configInfo.bdsOutputSize); - /* Clean IPAActiveState at each reconfiguration. */ context_.activeState = {}; IPAFrameContext initFrameContext; context_.frameContexts.fill(initFrameContext); - if (!validateSensorControls()) { - LOG(IPAIPU3, Error) << "Sensor control validation failed."; - return -EINVAL; - } - /* Update the IPASessionConfiguration using the sensor settings. */ - updateSessionConfiguration(sensorCtrls_); + updateSessionConfiguration(configInfo); + calculateBdsGrid(configInfo.bdsOutputSize); for (auto const &algo : algorithms_) { int ret = algo->configure(context_, configInfo); @@ -398,6 +380,10 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) return ret; } + sensorInfo_ = configInfo.sensorInfo; + lensCtrls_ = configInfo.lensControls; + sensorCtrls_ = configInfo.sensorControls; + return 0; } @@ -500,7 +486,7 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get()); double lineDuration = context_.configuration.sensor.lineDuration.get(); - int32_t vBlank = context_.configuration.sensor.defVBlank; + int32_t vBlank = context_.configuration.sensor.vBlank; ControlList ctrls(controls::controls); for (auto const &algo : algorithms_) @@ -508,7 +494,6 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, setControls(frame); - /* \todo Use VBlank value calculated from each frame exposure. */ int64_t frameDuration = (vBlank + sensorInfo_.outputSize.height) * lineDuration; ctrls.set(controls::FrameDuration, frameDuration); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 8c5b6c36ae0b..ce207c968075 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -659,7 +659,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) } ipa::ipu3::IPAConfigInfo configInfo; - configInfo.sensorControls = data->cio2_.sensor()->v4l2Controls(); + configInfo.sensorControls = data->cio2_.sensor()->controls(); CameraLens *lens = data->cio2_.sensor()->focusLens(); if (lens) From patchwork Thu Jun 30 13:38:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16476 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 BFB86BE173 for ; Thu, 30 Jun 2022 13:39:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 37DB9656A5; Thu, 30 Jun 2022 15:39:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596391; bh=OV37ZwdCo/y5iOkMfZufy1rAHArxcLauP5pn50vF+QY=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=c/lunPlTt8xmw1tCdTKZNPt8yvnJO4rYcmq5smBy7rV82H3aFkfK6wj8evU27Puqf TNsKiu+ZDmrVhNZd6b3mtLYdF2vG2nvcKQegc+GpRKhDTJ57aICsQboEUp8PM9kach sx40sUuKpAso5wyEl/KBe1KpMBJ9L/Imfj8xA1ta0ulGjXV4CyWr5CP8TAPSnVjhQ4 +tcOq/tA5oOSYjOVxr0BsHOh5mUCV9AMSu/1tDsoqjmty4q6vt2BXKcKuSrqxxvnVz pzsBAKIuhvI4MuuS6EIAHMe+6FsA+rpWEtF9WMuNevyg+kRYmKHlooOhRJq2tVyXAH 5k4bkQYlhLd5w== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8A1F5656A5 for ; Thu, 30 Jun 2022 15:39:43 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 75DC4240005; Thu, 30 Jun 2022 13:39:41 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:57 +0200 Message-Id: <20220630133902.321099-19-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 18/23] ipa: ipu3: Use an up to date lineDuration 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The IPA module computes the lineDuration value in the init() function only, and uses it when processing statistics to recompute the shutter duration. As the lineDuration varies when a new mode is applied to the sensor, computing it once at IPA initialization time is not enough. Re-calculate the line duration value at IPA configure() time to make sure the module always uses an updated value. Signed-off-by: Jacopo Mondi --- include/libcamera/ipa/ipu3.mojom | 3 +-- src/ipa/ipu3/ipu3.cpp | 9 ++++----- src/libcamera/pipeline/ipu3/ipu3.cpp | 7 +------ 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/include/libcamera/ipa/ipu3.mojom b/include/libcamera/ipa/ipu3.mojom index 5818cd3a6846..64fe65fdd5fc 100644 --- a/include/libcamera/ipa/ipu3.mojom +++ b/include/libcamera/ipa/ipu3.mojom @@ -17,8 +17,7 @@ struct IPAConfigInfo { }; interface IPAIPU3Interface { - init(libcamera.IPASettings settings, - libcamera.IPACameraSensorInfo sensorInfo) + init(libcamera.IPASettings settings) => (int32 ret); start() => (int32 ret); stop(); diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 44a7d13225df..eb97c8be5431 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -132,8 +132,7 @@ namespace ipa::ipu3 { class IPAIPU3 : public IPAIPU3Interface { public: - int init(const IPASettings &settings, - const IPACameraSensorInfo &sensorInfo) override; + int init(const IPASettings &settings) override; int start() override; void stop() override; @@ -181,6 +180,8 @@ void IPAIPU3::updateSessionConfiguration(const IPAConfigInfo &info) { const IPACameraSensorInfo &sensorInfo = info.sensorInfo; context_.configuration.sensor.vBlank = sensorInfo.vblank; + context_.configuration.sensor.lineDuration = sensorInfo.lineLength * 1.0s + / sensorInfo.pixelRate; const ControlInfoMap &sensorControls = info.sensorControls; @@ -229,8 +230,7 @@ bool IPAIPU3::validateSensorControls(const ControlInfoMap &sensorControls) * handler, computes the limits of the controls it handles and returns * them in the \a ipaControls output parameter. */ -int IPAIPU3::init(const IPASettings &settings, - const IPACameraSensorInfo &sensorInfo) +int IPAIPU3::init(const IPASettings &settings) { camHelper_ = CameraSensorHelperFactory::create(settings.sensorModel); if (camHelper_ == nullptr) { @@ -242,7 +242,6 @@ int IPAIPU3::init(const IPASettings &settings, /* Clean context */ context_.configuration = {}; - context_.configuration.sensor.lineDuration = sensorInfo.lineLength * 1.0s / sensorInfo.pixelRate; /* Construct our Algorithms */ algorithms_.push_back(std::make_unique()); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index ce207c968075..55b96137f065 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1237,12 +1237,7 @@ int IPU3CameraData::loadIPA() if (ret) return ret; - IPACameraSensorInfo sensorInfo{}; - ret = sensor->sensorInfo(&sensorInfo); - if (ret) - return ret; - - ret = ipa_->init(IPASettings{ "", sensor->model() }, sensorInfo); + ret = ipa_->init(IPASettings{ "", sensor->model() }); if (ret) { LOG(IPU3, Error) << "Failed to initialise the IPU3 IPA"; return ret; From patchwork Thu Jun 30 13:38:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16477 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 4F663BE173 for ; Thu, 30 Jun 2022 13:39:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CA231656B1; Thu, 30 Jun 2022 15:39:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596393; bh=oK0Vulz7dFwEAwnbt3WG2svQdV6Rb+H55QXELyLuJ7Q=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=iQOqFhY7M3ts1YoqBicY1CRsYb0uHbnxxqa7z1R16LGFo8wtwQLuHVpLHBx74Gwpo dci+IwjXdbBY6jgeYXpEg8kjDCqMwVSfGjEbOIYoBqLOJC5kkpYmAa/8yBDZPA5dLb 2MZF62/FVAF1KNc6YqvIpwqe0bPrQu0x/xR8kFnc1wKvWnW84kocgmpjUeVQL63xNV NI6RtkZOaEy93mKkO0ukwBc6GPoTMlhdN+NSoBTKbVK4TU0pslqibrtBxSxYlfqSv0 QYFpn8hkXZs15jHFZglI56AQZKNop1qEMWyIMNW1ManF6o9w8aOrsuV37ylQvwAHwn RfK1s78+RNLjg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DD3F9656AD for ; Thu, 30 Jun 2022 15:39:45 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id E1F5B240005; Thu, 30 Jun 2022 13:39:43 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:58 +0200 Message-Id: <20220630133902.321099-20-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 19/23] ipa: ipu3: Rework IPAIPU3::processStatsBuffer() 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Before removing V4L2 controls from the IPAIPU3::processStatsBuffer() interface, rationalize the existing code a bit. 1) we have a context_.configuration which collects the per-capture session configuration data. At the same time the sensor and lens controls info are kept in class member variables. Move all per-capture session parameters to context_.configuration. 2) IPAIPU3::setControls() operates on the active state, which is implicitly retrieved from the global context. Pass it explicitly to make it clear. 3) Now that we have the full IPACameraSensorInfo in the current context remove vblank from IPASessionConfiguration::sensor as it can be retrieved from IPASessionConfiguration::sensor.info. 4) Rationalize the code of IPAIPU3::processStatsBuffer() to organize it in a logical flow of operations: - Update the per-frame context with the sensor's controls values - Map the stats buffer - Run algorithms with the per-frame context and stats - setControls() using the active state as computed by algorithms - Populate the metadata buffer Signed-off-by: Jacopo Mondi --- src/ipa/ipu3/ipa_context.cpp | 14 ++++++-- src/ipa/ipu3/ipa_context.h | 9 ++++- src/ipa/ipu3/ipu3.cpp | 68 +++++++++++++++++++----------------- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp index 06fdf2a1efc7..f09d061e2d19 100644 --- a/src/ipa/ipu3/ipa_context.cpp +++ b/src/ipa/ipu3/ipa_context.cpp @@ -126,8 +126,18 @@ namespace libcamera::ipa::ipu3 { * \var IPASessionConfiguration::sensor.lineDuration * \brief Line duration in microseconds * - * \var IPASessionConfiguration::sensor.vBlank - * \brief The vertical blanking expressed in number of lines + * \var IPASessionConfiguration::sensor.info + * \brief The IPACameraSensorInfo valid for the session + * + * \var IPASessionConfiguration::sensor.controls + * \brief The ControlInfoMap of camera sensor control limits valid for the + * session + * + * \var IPASessionConfiguration::lens + * \brief Lens-specific configuration of the IPA + * + * \var IPASessionConfiguration::lens.controls + * \brief The ControlInfoMap of lens control limits valid for the session */ /** diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index a5b878ab7792..35baa17e8708 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -17,6 +17,8 @@ #include #include +#include + namespace libcamera { namespace ipa::ipu3 { @@ -43,9 +45,14 @@ struct IPASessionConfiguration { } agc; struct { - int32_t vBlank; utils::Duration lineDuration; + ControlInfoMap controls; + IPACameraSensorInfo info; } sensor; + + struct { + ControlInfoMap controls; + } lens; }; struct IPAActiveState { diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index eb97c8be5431..f2e28c06a2c2 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -152,16 +152,11 @@ private: bool validateSensorControls(const ControlInfoMap &sensorControls); - void setControls(unsigned int frame); + void setControls(unsigned int frame, const IPAActiveState &state); void calculateBdsGrid(const Size &bdsOutputSize); std::map buffers_; - ControlInfoMap sensorCtrls_; - ControlInfoMap lensCtrls_; - - IPACameraSensorInfo sensorInfo_; - /* Interface to the Camera Helper */ std::unique_ptr camHelper_; @@ -179,7 +174,6 @@ private: void IPAIPU3::updateSessionConfiguration(const IPAConfigInfo &info) { const IPACameraSensorInfo &sensorInfo = info.sensorInfo; - context_.configuration.sensor.vBlank = sensorInfo.vblank; context_.configuration.sensor.lineDuration = sensorInfo.lineLength * 1.0s / sensorInfo.pixelRate; @@ -199,6 +193,11 @@ void IPAIPU3::updateSessionConfiguration(const IPAConfigInfo &info) const ControlInfo &gain = sensorControls.at(&controls::internal::AnalogueGain); context_.configuration.agc.minAnalogueGain = gain.min().get(); context_.configuration.agc.maxAnalogueGain = gain.max().get(); + + /* Store the sensor and lens configuration in the current session. */ + context_.configuration.sensor.info = info.sensorInfo; + context_.configuration.sensor.controls = info.sensorControls; + context_.configuration.lens.controls = info.lensControls; } /** @@ -262,7 +261,7 @@ int IPAIPU3::start() * Set the sensors V4L2 controls before the first frame to ensure that * we have an expected and known configuration from the start. */ - setControls(0); + setControls(0, context_.activeState); return 0; } @@ -379,10 +378,6 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) return ret; } - sensorInfo_ = configInfo.sensorInfo; - lensCtrls_ = configInfo.lensControls; - sensorCtrls_ = configInfo.sensorControls; - return 0; } @@ -472,10 +467,10 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, return; } - Span mem = it->second.planes()[0]; - const ipu3_uapi_stats_3a *stats = - reinterpret_cast(mem.data()); - + /* + * Update the per-frame context storing the sensor exposure and + * gain for later use by algorithms. + */ IPAFrameContext &frameContext = context_.frameContexts[frame % kMaxFrameContexts]; if (frameContext.frame != frame) @@ -484,23 +479,28 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get(); frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get()); - double lineDuration = context_.configuration.sensor.lineDuration.get(); - int32_t vBlank = context_.configuration.sensor.vBlank; - ControlList ctrls(controls::controls); + /* Run algorithms on the statistics and per-frame context. */ + Span mem = it->second.planes()[0]; + const ipu3_uapi_stats_3a *stats = reinterpret_cast(mem.data()); for (auto const &algo : algorithms_) algo->process(context_, &frameContext, stats); - setControls(frame); - - int64_t frameDuration = (vBlank + sensorInfo_.outputSize.height) * lineDuration; - ctrls.set(controls::FrameDuration, frameDuration); + /* Set sensor controls using the newly computed values. */ + setControls(frame, context_.activeState); - ctrls.set(controls::AnalogueGain, frameContext.sensor.gain); + /* Prepare metadata for the frame. */ + const IPASessionConfiguration &ipaConfig = context_.configuration; + const IPACameraSensorInfo &sensorInfo = ipaConfig.sensor.info; + double lineDuration = ipaConfig.sensor.lineDuration.get(); + int64_t frameDuration = (sensorInfo.vblank + sensorInfo.outputSize.height) * lineDuration; - ctrls.set(controls::ColourTemperature, context_.activeState.awb.temperatureK); + ControlList metadata(controls::controls); - ctrls.set(controls::ExposureTime, frameContext.sensor.exposure * lineDuration); + metadata.set(controls::FrameDuration, frameDuration); + metadata.set(controls::AnalogueGain, frameContext.sensor.gain); + metadata.set(controls::ColourTemperature, context_.activeState.awb.temperatureK); + metadata.set(controls::ExposureTime, frameContext.sensor.exposure * lineDuration); /* * \todo The Metadata provides a path to getting extended data @@ -510,7 +510,7 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, * likely want to avoid putting platform specific metadata in. */ - metadataReady.emit(frame, ctrls); + metadataReady.emit(frame, metadata); } /** @@ -530,22 +530,24 @@ void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls) /** * \brief Handle sensor controls for a given \a frame number * \param[in] frame The frame on which the sensor controls should be set + * \param[in] state The IPA active state which contains the control values as + * computed by the algorithms * * Send the desired sensor control values to the pipeline handler to request * that they are applied on the camera sensor. */ -void IPAIPU3::setControls(unsigned int frame) +void IPAIPU3::setControls(unsigned int frame, const IPAActiveState &state) { - int32_t exposure = context_.activeState.agc.exposure; - int32_t gain = camHelper_->gainCode(context_.activeState.agc.gain); + int32_t exposure = state.agc.exposure; + int32_t gain = camHelper_->gainCode(state.agc.gain); - ControlList ctrls(sensorCtrls_); + ControlList ctrls(controls::controls); ctrls.set(V4L2_CID_EXPOSURE, exposure); ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain); - ControlList lensCtrls(lensCtrls_); + ControlList lensCtrls(controls::controls); lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, - static_cast(context_.activeState.af.focus)); + static_cast(state.af.focus)); setSensorControls.emit(frame, ctrls, lensCtrls); } From patchwork Thu Jun 30 13:38:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16478 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 B17C8BE173 for ; Thu, 30 Jun 2022 13:39:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5DE2F656B5; Thu, 30 Jun 2022 15:39:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596395; bh=McMzxIfktJ6BpbvEaIQ6eK0gr6MearwMemeQxYmrzYk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=jAGIT4XFkICFJPSpSp+439Nn0ddHJUAgOG/jUYn2atGeOmC5hWL4lWzmO+ecClHEd qcm4UQwzok7Iua/AFqRwzs+PHoaO29lCCdDAzGl9HDG/SFlI0RmN55Hf5NihZALIp5 ZJoZ9WUNA4GiAlrQH0vwoADiOdN+4zkNepExMxdrZf6KqHp9pFIUAPBneub8zHzqje CctLrwyLyx7NBAxxDIXQYFa5o91Xkxzc2zhZ+TZHYf/EHKr0eYofdkPD9qlrS0hzKz TnZKf3ihkNQLSiRyXuNFPJiSbvAKnKPqfB5h9muW5uK0bCu1Zzt8npa4MAXLXHNrjK DYusbTSKOEThA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 72B75656B1 for ; Thu, 30 Jun 2022 15:39:48 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 412D3240003; Thu, 30 Jun 2022 13:39:45 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:38:59 +0200 Message-Id: <20220630133902.321099-21-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 20/23] ipa: ipu3: Make algorithms use libcamera controls 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move the IPU3 IPA module and the AGC algorithm to use libcamera controls instead of computing V4L2 control values. Signed-off-by: Jacopo Mondi --- src/ipa/ipu3/algorithms/agc.cpp | 12 +++--------- src/ipa/ipu3/ipu3.cpp | 15 ++++++--------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index f16be534dd71..d1bbf2a753e9 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -186,11 +186,6 @@ utils::Duration Agc::filterExposure(utils::Duration exposureValue) void Agc::computeExposure(IPAContext &context, IPAFrameContext *frameContext, double yGain, double iqMeanGain) { - const IPASessionConfiguration &configuration = context.configuration; - /* Get the effective exposure and gain applied on the sensor. */ - uint32_t exposure = frameContext->sensor.exposure; - double analogueGain = frameContext->sensor.gain; - /* Use the highest of the two gain estimates. */ double evGain = std::max(yGain, iqMeanGain); @@ -201,13 +196,12 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext *frameContext, /* extracted from Rpi::Agc::computeTargetExposure */ - /* Calculate the shutter time in seconds */ - utils::Duration currentShutter = exposure * configuration.sensor.lineDuration; - /* * Update the exposure value for the next computation using the values * of exposure and gain really used by the sensor. */ + double analogueGain = frameContext->sensor.gain; + utils::Duration currentShutter = frameContext->sensor.exposure * 1.0us; utils::Duration effectiveExposureValue = currentShutter * analogueGain; LOG(IPU3Agc, Debug) << "Actual total exposure " << currentShutter * analogueGain @@ -250,7 +244,7 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext *frameContext, IPAActiveState &activeState = context.activeState; /* Update the estimated exposure and gain. */ - activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration; + activeState.agc.exposure = shutterTime.get(); activeState.agc.gain = stepGain; } diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index f2e28c06a2c2..6d622b4c290b 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -476,8 +476,8 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, if (frameContext.frame != frame) LOG(IPAIPU3, Warning) << "Frame " << frame << " does not match its frame context"; - frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get(); - frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get()); + frameContext.sensor.exposure = sensorControls.get(controls::internal::ExposureTime); + frameContext.sensor.gain = sensorControls.get(controls::internal::AnalogueGain); /* Run algorithms on the statistics and per-frame context. */ Span mem = it->second.planes()[0]; @@ -500,7 +500,7 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame, metadata.set(controls::FrameDuration, frameDuration); metadata.set(controls::AnalogueGain, frameContext.sensor.gain); metadata.set(controls::ColourTemperature, context_.activeState.awb.temperatureK); - metadata.set(controls::ExposureTime, frameContext.sensor.exposure * lineDuration); + metadata.set(controls::ExposureTime, frameContext.sensor.exposure); /* * \todo The Metadata provides a path to getting extended data @@ -538,12 +538,9 @@ void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls) */ void IPAIPU3::setControls(unsigned int frame, const IPAActiveState &state) { - int32_t exposure = state.agc.exposure; - int32_t gain = camHelper_->gainCode(state.agc.gain); - - ControlList ctrls(controls::controls); - ctrls.set(V4L2_CID_EXPOSURE, exposure); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain); + ControlList ctrls(controls::internal::controls); + ctrls.set(controls::internal::ExposureTime, state.agc.exposure); + ctrls.set(controls::internal::AnalogueGain, static_cast(state.agc.gain)); ControlList lensCtrls(controls::controls); lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, From patchwork Thu Jun 30 13:39:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16479 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 983F3C3273 for ; Thu, 30 Jun 2022 13:39:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F336F656AF; Thu, 30 Jun 2022 15:39:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596396; bh=oJGDA59ynjCnTwfOvPazRfGrA9ltGSrJ9yJbKPytX8c=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=1bjVYOHCdrDMKvKx9jG6cswhvcRf+8nZK4XnGAF0cia+dEA9ArdcbeadPjGsW/xZW DExEIB/77m349MbFHuGwDH1kkXpPt9NrR8FCTxOQm1wjP173t+tTXGxK8qFbQsKtWS P2/tN9xf91+8kKrfIfBb04+gfHuq24mfgtRg/sQod325NO6iVcyPM8qniS0St1Wbzg tW5d3KDnaUJLq/HKdtfwfCGup+cUaavHJzzlNA//lPiT9Gand4JA/tOomwr9hfBJKX 76Srqi9Yewd33PUcovpMKdym+mB4lPiGRjg5amc/5052SjkM1tnjOp9uSuymAkBe4+ ZcTpDagdmwZwA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F223E65650 for ; Thu, 30 Jun 2022 15:39:50 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 01590240007; Thu, 30 Jun 2022 13:39:48 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:39:00 +0200 Message-Id: <20220630133902.321099-22-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 21/23] ipa: ipu3: Add and use LensFocusAbsolute control 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add to the internal controls LensFocusAbsolute as a draft control as it is currently identical to V4L2_CID_FOCUS_ABSOLUTE. Use the newly introduced control in the IPU3 pipeline handler and IPA module. Signed-off-by: Jacopo Mondi --- include/libcamera/ipa/ipu3.mojom | 3 +-- src/ipa/ipu3/ipu3.cpp | 7 ++----- src/libcamera/internal_control_ids.yaml | 13 +++++++++++++ src/libcamera/pipeline/ipu3/ipu3.cpp | 13 +++++-------- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/libcamera/ipa/ipu3.mojom b/include/libcamera/ipa/ipu3.mojom index 64fe65fdd5fc..bfeadc58c52a 100644 --- a/include/libcamera/ipa/ipu3.mojom +++ b/include/libcamera/ipa/ipu3.mojom @@ -35,8 +35,7 @@ interface IPAIPU3Interface { }; interface IPAIPU3EventInterface { - setSensorControls(uint32 frame, libcamera.ControlList sensorControls, - libcamera.ControlList lensControls); + setSensorControls(uint32 frame, libcamera.ControlList sensorControls); paramsBufferReady(uint32 frame); metadataReady(uint32 frame, libcamera.ControlList metadata); }; diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 6d622b4c290b..2f158df367a8 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -541,12 +541,9 @@ void IPAIPU3::setControls(unsigned int frame, const IPAActiveState &state) ControlList ctrls(controls::internal::controls); ctrls.set(controls::internal::ExposureTime, state.agc.exposure); ctrls.set(controls::internal::AnalogueGain, static_cast(state.agc.gain)); + ctrls.set(controls::internal::draft::LensFocusAbsolute, state.af.focus); - ControlList lensCtrls(controls::controls); - lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, - static_cast(state.af.focus)); - - setSensorControls.emit(frame, ctrls, lensCtrls); + setSensorControls.emit(frame, ctrls); } } /* namespace ipa::ipu3 */ diff --git a/src/libcamera/internal_control_ids.yaml b/src/libcamera/internal_control_ids.yaml index 6d3775afcf67..804c227213a7 100644 --- a/src/libcamera/internal_control_ids.yaml +++ b/src/libcamera/internal_control_ids.yaml @@ -24,4 +24,17 @@ controls: description: | The sensor analogue gain value. + # ---------------------------------------------------------------------------- + # Draft controls section + + - LensFocusAbsolute: + type: int32_t + draft: true + description: | + This control sets the focal point of the camera to the specified + position. The unit is undefined. Positive values set the focus closer to + the camera, negative values towards infinity. + + Currently identical to V4L2_CID_FOCUS_ABSOLUTE. + ... diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 55b96137f065..1dbcdd0b56e6 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -86,8 +86,7 @@ public: private: void metadataReady(unsigned int id, const ControlList &metadata); void paramsBufferReady(unsigned int id); - void setSensorControls(unsigned int id, const ControlList &sensorControls, - const ControlList &lensControls); + void setSensorControls(unsigned int id, const ControlList &sensorControls); }; class IPU3CameraConfiguration : public CameraConfiguration @@ -1247,8 +1246,7 @@ int IPU3CameraData::loadIPA() } void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id, - const ControlList &sensorControls, - const ControlList &lensControls) + const ControlList &sensorControls) { CameraSensor *sensor = cio2_.sensor(); @@ -1258,12 +1256,11 @@ void IPU3CameraData::setSensorControls([[maybe_unused]] unsigned int id, if (!focusLens) return; - if (!lensControls.contains(V4L2_CID_FOCUS_ABSOLUTE)) + if (!sensorControls.contains(controls::internal::draft::LensFocusAbsolute)) return; - const ControlValue &focusValue = lensControls.get(V4L2_CID_FOCUS_ABSOLUTE); - - focusLens->setFocusPosition(focusValue.get()); + int32_t focusAbsolute = sensorControls.get(controls::internal::draft::LensFocusAbsolute); + focusLens->setFocusPosition(focusAbsolute); } void IPU3CameraData::paramsBufferReady(unsigned int id) From patchwork Thu Jun 30 13:39:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16480 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 A3605C3274 for ; Thu, 30 Jun 2022 13:39:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5A75F656B7; Thu, 30 Jun 2022 15:39:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596399; bh=ppR811V+Kq0f8c46mGFUwZj89Mn6DI0vaywGAE1speA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=T0l+oC+Cr683r1bwG3ftUIZFu3tghf6KOUxJaGWICt8aDeZ+A8UmRKT2gd0Zq7fMA 3o1GtWVeuI5RcEyAPWzthj1jKERA+1VH5nhV4byZcHfzEdxzkNFwuO7c+tBAZWS+6m Wik+L4w/qKIYsxo1g5jl7UzsuGxWDslLy1OXw288Rf7fwNRHRfY2UlqPwDknsh0wb3 IEj5q6THzVlVcpRocm65F6Ubxc5NIAxfol9JAb3WG2X4Eft4DnhIdUThXFXt4lBXZG MoABI+J9pLii5m7K2F9SbmybEQfVfDejQmC7Vs8fMghAL2wR3Wqiqj+CSBhJNSrcw/ sJo8BB6pWlPTA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 17879656A7 for ; Thu, 30 Jun 2022 15:39:53 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 7D859240005; Thu, 30 Jun 2022 13:39:50 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:39:01 +0200 Message-Id: <20220630133902.321099-23-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 22/23] libcamera: camera_lens: Expose libcamera control limits 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The CameraLens class exposes the list of V4L2 controls through the CameraLens::controls() function. Modify the implementation to expose the newly introduced LensFocusAbsolute control limits. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/internal/camera_lens.h | 5 +++- src/libcamera/camera_lens.cpp | 33 ++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/include/libcamera/internal/camera_lens.h b/include/libcamera/internal/camera_lens.h index 277417daffed..ea98379ecc62 100644 --- a/include/libcamera/internal/camera_lens.h +++ b/include/libcamera/internal/camera_lens.h @@ -30,7 +30,7 @@ public: const std::string &model() const { return model_; } - const ControlInfoMap &controls() const; + const ControlInfoMap &controls() const { return controls_; } protected: std::string logPrefix() const override; @@ -39,11 +39,14 @@ private: LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraLens) int validateLensDriver(); + void updateControls(); const MediaEntity *entity_; std::unique_ptr subdev_; std::string model_; + + ControlInfoMap controls_; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera_lens.cpp b/src/libcamera/camera_lens.cpp index b3d48199ec3b..08c2c42a9cfa 100644 --- a/src/libcamera/camera_lens.cpp +++ b/src/libcamera/camera_lens.cpp @@ -9,6 +9,7 @@ #include +#include "libcamera/internal/control_ids.h" #include "libcamera/internal/v4l2_subdevice.h" /** @@ -73,6 +74,9 @@ int CameraLens::init() return ret; model_ = subdev_->model(); + + updateControls(); + return 0; } @@ -124,6 +128,13 @@ int CameraLens::validateLensDriver() return ret; } +/** + * \fn CameraLens::controls() + * \brief Retrieve the CameraLens controls limits + * + * \return The ControlInfoMap with the CameraLens controls limits + */ + /** * \fn CameraLens::model() * \brief Retrieve the lens model name @@ -139,15 +150,21 @@ std::string CameraLens::logPrefix() const return "'" + entity_->name() + "'"; } -/** - * \fn CameraLens::controls() - * \brief Retrieve the V4L2 controls of the lens' subdev - * - * \return A map of the V4L2 controls supported by the lens' driver - */ -const ControlInfoMap &CameraLens::controls() const +void CameraLens::updateControls() { - return subdev_->controls(); + ControlInfoMap::Map controls; + + /* The lens driver has been validate, the control is there. */ + const ControlInfoMap &lensControls = subdev_->controls(); + const ControlInfo &focusAbsolute = lensControls.at(V4L2_CID_FOCUS_ABSOLUTE); + + controls[&controls::internal::draft::LensFocusAbsolute] = + ControlInfo(focusAbsolute.min().get(), + focusAbsolute.max().get(), + focusAbsolute.def().get()); + + controls_ = ControlInfoMap(std::move(controls), + controls::internal::controls); } } /* namespace libcamera */ From patchwork Thu Jun 30 13:39:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 16481 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 99C0BBE173 for ; Thu, 30 Jun 2022 13:40:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 401CB656B9; Thu, 30 Jun 2022 15:40:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656596400; bh=XlMMPMSdM90NzYaaefA2qyMuByeK/vS93wawPT3IY5E=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=reGVuwkGsPyCZv3LRq2thwLPFOFf9XXQUNMBdfEqSl21h4UIR4db9IZ0WWqmim0Dx qQT03LzpGhe/r7gt1xak/7JcgP1URpJpgKuzjp20VeKpz9PA0kVtQkex5AnO3eWEWv wQ+u1WvDHsnooGS8AUbr0eb6U0b5J23EG9B3vLIeCxgiawMCx/fUakQFUp3RyAm2bZ Kyrbx7oKvGnB3bsNpd2/hMJ/E2/6l3QQEqo8bWXkzcgTxVFPTtS96rWMUnftsjO5Xl YyZHd3VPDsvNCwV9JRxy1gVtC7gYM0PlWgq2s+oUBAZdCp+lvpO5vieyVLdXHCFB4Z OjvXKPZME/2Qg== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6A802656AE for ; Thu, 30 Jun 2022 15:39:54 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 955A9240005; Thu, 30 Jun 2022 13:39:53 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 15:39:02 +0200 Message-Id: <20220630133902.321099-24-jacopo@jmondi.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220630133902.321099-1-jacopo@jmondi.org> References: <20220630133902.321099-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 23/23] libcamera: Move camera_lens.cpp in src/libcamera/camera_sensor 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: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The CameraLens class is tighly copuled with the camera sensor classes. Move the camera_lens.cpp file in src/libcamera/camera_sensor. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/{ => camera_sensor}/camera_lens.cpp | 0 src/libcamera/camera_sensor/meson.build | 1 + src/libcamera/meson.build | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename src/libcamera/{ => camera_sensor}/camera_lens.cpp (100%) diff --git a/src/libcamera/camera_lens.cpp b/src/libcamera/camera_sensor/camera_lens.cpp similarity index 100% rename from src/libcamera/camera_lens.cpp rename to src/libcamera/camera_sensor/camera_lens.cpp diff --git a/src/libcamera/camera_sensor/meson.build b/src/libcamera/camera_sensor/meson.build index 991eeeeee29e..b38e3551f644 100644 --- a/src/libcamera/camera_sensor/meson.build +++ b/src/libcamera/camera_sensor/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_sources += files([ + 'camera_lens.cpp', 'camera_sensor.cpp', 'camera_sensor_helper.cpp', 'camera_sensor_properties.cpp', diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 897fb259a894..dc8f55cf5057 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -5,7 +5,6 @@ libcamera_sources = files([ 'byte_stream_buffer.cpp', 'camera.cpp', 'camera_controls.cpp', - 'camera_lens.cpp', 'camera_manager.cpp', 'color_space.cpp', 'controls.cpp',