From patchwork Wed Apr 30 12:14:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23309 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 96AA4BE08B for ; Wed, 30 Apr 2025 12:15:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5179068AD8; Wed, 30 Apr 2025 14:15:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bq/jO3bR"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AA49068ADB for ; Wed, 30 Apr 2025 14:15:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015302; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6nojKMgyAr1J7Kg+cw5+5LA/MAeA+yK1yKIX+m6UGFQ=; b=bq/jO3bRMdA7EkzEVG3Htgvw/WmVPg8Vb0rwOvz6bay42l+8V6gY1V9L78TMnt8mRzOhE6 LdkdZFjvgQYn7vtDN8lFW7QlG8aZTVNEAC322hDI0YdEuH53iLK2xCn7wTa8lkov9uOnNB zUKLoRxVhkgi9EYFWrYLWk489TTlS7Q= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-332-r2fsM4BEPny_lhqXHQfADQ-1; Wed, 30 Apr 2025 08:15:01 -0400 X-MC-Unique: r2fsM4BEPny_lhqXHQfADQ-1 X-Mimecast-MFC-AGG-ID: r2fsM4BEPny_lhqXHQfADQ_1746015299 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A673A19560A0; Wed, 30 Apr 2025 12:14:59 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E3BF718001D5; Wed, 30 Apr 2025 12:14:57 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 01/15] yaml: Move yaml_parser.cpp to base Date: Wed, 30 Apr 2025 14:14:34 +0200 Message-ID: <20250430121449.39910-2-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: _aO8puuxZZ6wIPZ2PnxSXytIhP8VhRDkb2y9r-7oK9o_1746015299 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Global configuration, which uses the YAML parser, will be in base. Thus YAML parser must be moved to base too. Indentation is changed in one place of the moved file to make the autoformatter and checkstyle.py happy. Signed-off-by: Milan Zamazal --- src/libcamera/base/meson.build | 14 ++++++++++++++ src/libcamera/{ => base}/yaml_parser.cpp | 13 ++++++------- src/libcamera/meson.build | 14 -------------- 3 files changed, 20 insertions(+), 21 deletions(-) rename src/libcamera/{ => base}/yaml_parser.cpp (98%) diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build index a742dfdf..94843eb9 100644 --- a/src/libcamera/base/meson.build +++ b/src/libcamera/base/meson.build @@ -24,10 +24,12 @@ libcamera_base_internal_sources = files([ 'thread.cpp', 'timer.cpp', 'utils.cpp', + 'yaml_parser.cpp', ]) libdw = dependency('libdw', required : false) libunwind = dependency('libunwind', required : false) +libyaml = dependency('yaml-0.1', required : false) if cc.has_header_symbol('execinfo.h', 'backtrace') config_h.set('HAVE_BACKTRACE', 1) @@ -41,11 +43,23 @@ if libunwind.found() config_h.set('HAVE_UNWIND', 1) endif +# Fallback to a subproject if libyaml isn't found, as it's not packaged in AOSP. +if not libyaml.found() + cmake = import('cmake') + + libyaml_vars = cmake.subproject_options() + libyaml_vars.add_cmake_defines({'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'}) + libyaml_vars.append_compile_args('c', '-Wno-unused-value') + libyaml_wrap = cmake.subproject('libyaml', options : libyaml_vars) + libyaml = libyaml_wrap.dependency('yaml') +endif + libcamera_base_deps = [ libatomic, libdw, libthreads, libunwind, + libyaml, ] # Internal components must use the libcamera_base_private dependency to enable diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/base/yaml_parser.cpp similarity index 98% rename from src/libcamera/yaml_parser.cpp rename to src/libcamera/base/yaml_parser.cpp index a5e42461..13111faa 100644 --- a/src/libcamera/yaml_parser.cpp +++ b/src/libcamera/base/yaml_parser.cpp @@ -149,13 +149,12 @@ YamlObject::Getter::get(const YamlObject &obj) const template struct YamlObject::Getter || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v>> -{ + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v>> { std::optional get(const YamlObject &obj) const { if (obj.type_ != Type::Value) diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 800d4080..e3f382fa 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -55,7 +55,6 @@ libcamera_internal_sources = files([ 'v4l2_subdevice.cpp', 'v4l2_videodevice.cpp', 'vector.cpp', - 'yaml_parser.cpp', ]) includes = [ @@ -83,7 +82,6 @@ if not cc.has_function('dlopen') libdl = cc.find_library('dl') endif libudev = dependency('libudev', required : get_option('udev')) -libyaml = dependency('yaml-0.1', required : false) # Use one of gnutls or libcrypto (provided by OpenSSL), trying gnutls first. libcrypto = dependency('gnutls', required : false) @@ -119,17 +117,6 @@ if libudev.found() ]) endif -# Fallback to a subproject if libyaml isn't found, as it's not packaged in AOSP. -if not libyaml.found() - cmake = import('cmake') - - libyaml_vars = cmake.subproject_options() - libyaml_vars.add_cmake_defines({'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'}) - libyaml_vars.append_compile_args('c', '-Wno-unused-value') - libyaml_wrap = cmake.subproject('libyaml', options : libyaml_vars) - libyaml = libyaml_wrap.dependency('yaml') -endif - control_sources = [] controls_mode_files = { @@ -189,7 +176,6 @@ libcamera_deps += [ libdl, liblttng, libudev, - libyaml, ] # We add '/' to the build_rpath as a 'safe' path to act as a boolean flag. From patchwork Wed Apr 30 12:14:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23310 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 449ECBE08B for ; Wed, 30 Apr 2025 12:15:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F071268B29; Wed, 30 Apr 2025 14:15:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="gM1qBtjG"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2663F68ADB for ; Wed, 30 Apr 2025 14:15:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015308; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0bXRIdxP/mCiD4+mKKX3pKGTb3lz0anjYl35dcGzug4=; b=gM1qBtjG9kfjGJViXn/MSwRCG6HU/nYZXQu2X7RCh8iMR92ueuSVT/sHJFZn1yhc0vBDUp AM+rl3EzDHML3f3sGTt76No7JcnY2mWwCAl0bdhQwfZTHCgkrFt7Dl0NBRqF3GmFPiic2j ESqmMxrf/1WtcykMUBPtSwLxTX60FmQ= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-31-mBFMWKMIPuy4P6ImbpH8mg-1; Wed, 30 Apr 2025 08:15:03 -0400 X-MC-Unique: mBFMWKMIPuy4P6ImbpH8mg-1 X-Mimecast-MFC-AGG-ID: mBFMWKMIPuy4P6ImbpH8mg_1746015302 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4D2351800877; Wed, 30 Apr 2025 12:15:02 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2EF8E180047F; Wed, 30 Apr 2025 12:14:59 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 02/15] config: Introduce global runtime configuration Date: Wed, 30 Apr 2025 14:14:35 +0200 Message-ID: <20250430121449.39910-3-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: E3bBXb10sKyzQgTwIP-MSV6XhlNr0ktwiHulBoQgxyQ_1746015302 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Currently, libcamera can be configured in runtime using several environment variables. With introducing more and more variables, this mechanism reaches its limits. It would be simpler and more flexible if it was possible to configure libcamera in a single file. For example, there have been a request for defining pipeline precedence in runtime. We want to compile in multiple pipelines, in order to have them accessible within single packages in distributions. And then being able to select among the pipelines manually as needed based on the particular hardware or operating system environment. Having the configuration file then allows easy switching between hardware, GPU or CPU IPAs. Another possible use case is tuning image output, especially with software ISP, to user liking. For example, some users may prefer higher contrast without the need to use the corresponding knobs, if present at all, in every application. The configuration file can also be used to enable or disable experimental features and avoid the need to track local patches changing configuration options hard-wired in the code when working on new features. This patch introduces basic support for configuration files. It reads, stores and accesses the configuration. The configuration is meant to use as a hidden singleton with public access methods. It is implemented as GlobalConfiguration namespace exposing the public functions, with private functions and the configuration data hidden in an anonymous namespace. This model suits well the purpose of having a hidden singleton wrapped by public access functions. libcamera configuration can be specified using a system-wide configuration file or a user configuration file. The user configuration file takes precedence if present. There is currently no way to merge multiple configuration files, the one found is used as the only configuration file. If no configuration file is present, nothing changes to the current libcamera behavior (except for some log messages related to configuration file lookup). The configuration file is a YAML file. We already have a mechanism for handling YAML configuration files in libcamera and the given infrastructure can be reused for the purpose. However, the configuration type is abstracted to make contingent future change of the underlying class easier while retaining (most of) the original API. The configuration is versioned. This has currently no particular meaning but is likely to have its purpose in future, especially once configuration validation is introduced. The configuration YAML file looks as follows: --- version: 1 configuration: WHATEVER CONFIGURATION NEEDED There is no logging about reading the configuration file and contingent errors. This is on purpose because logging will query configuration, which can lead to various problems when done during configuration initialization. Reporting the errors will be added later. A complication arises from the fact that when the configuration is loaded, logging may be called and logging will ask for the configuration. This is error-prone and may lead to subtle problems. For this reason, the global configuration is instantiated to a pointer, with an empty configuration initially. The real configuration will be created through initialize() method. It will be clearer how it helps in the followup patch introducing logging configuration. Logging is also the most notable component from base that uses global configuration. In order to be able to do it, the global configuration must be put to base. This patch introduces just the basic idea. Actually using the configuration in the corresponding places (everything what is currently configurable via environment variables should be configurable in the file configuration) and other enhancements are implemented in the followup patches. Signed-off-by: Milan Zamazal --- .../libcamera/internal/global_configuration.h | 25 +++ include/libcamera/internal/meson.build | 1 + src/libcamera/base/global_configuration.cpp | 153 ++++++++++++++++++ src/libcamera/base/meson.build | 1 + 4 files changed, 180 insertions(+) create mode 100644 include/libcamera/internal/global_configuration.h create mode 100644 src/libcamera/base/global_configuration.cpp diff --git a/include/libcamera/internal/global_configuration.h b/include/libcamera/internal/global_configuration.h new file mode 100644 index 00000000..bed88279 --- /dev/null +++ b/include/libcamera/internal/global_configuration.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Red Hat, inc. + * + * Global configuration handling + */ + +#pragma once + +#include "libcamera/internal/yaml_parser.h" + +namespace libcamera { + +namespace GlobalConfiguration { + +using Configuration = const YamlObject &; + +void initialize(); + +unsigned int version(); +Configuration configuration(); + +} /* namespace GlobalConfiguration */ + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 33f318b2..951bfee4 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -22,6 +22,7 @@ libcamera_internal_headers = files([ 'dma_buf_allocator.h', 'formats.h', 'framebuffer.h', + 'global_configuration.h', 'ipa_data_serializer.h', 'ipa_manager.h', 'ipa_module.h', diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp new file mode 100644 index 00000000..3350a26a --- /dev/null +++ b/src/libcamera/base/global_configuration.cpp @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Red Hat, inc. + * + * Global configuration handling + */ + +#include "libcamera/internal/global_configuration.h" + +#include +#include + +#include +#include +#include + +#include "libcamera/internal/yaml_parser.h" + +namespace libcamera { + +namespace GlobalConfiguration { + +namespace { + +std::unique_ptr yamlConfiguration = std::make_unique(); + +bool loadFile(const std::filesystem::path &fileName) +{ + File file(fileName); + if (!file.exists()) { + return false; + } + + if (!file.open(File::OpenModeFlag::ReadOnly)) + return true; + + auto root = YamlParser::parse(file); + if (!root) + return true; + yamlConfiguration = std::move(root); + + return true; +} + +const std::vector + globalConfigurationFiles = { + std::filesystem::path(LIBCAMERA_SYSCONF_DIR) / "configuration.yaml", + std::filesystem::path("/etc/libcamera/configuration.yaml"), + }; + +void load() +{ + std::filesystem::path userConfigurationDirectory; + char *xdgConfigHome = utils::secure_getenv("XDG_CONFIG_HOME"); + if (xdgConfigHome) { + userConfigurationDirectory = xdgConfigHome; + } else { + const char *home = utils::secure_getenv("HOME"); + if (home) + userConfigurationDirectory = + std::filesystem::path(home) / ".config"; + } + + if (!userConfigurationDirectory.empty()) { + std::filesystem::path user_configuration_file = + userConfigurationDirectory / "libcamera" / "configuration.yaml"; + if (loadFile(user_configuration_file)) + return; + } + + for (const auto &path : globalConfigurationFiles) + if (loadFile(path)) + return; +} + +Configuration get() +{ + return *yamlConfiguration; +} + +} /* namespace */ + +/** + * \brief Initialize the global configuration + * + * This must be called before global configuration is accessed. + */ +void initialize() +{ + load(); +} + +/** + * \namespace GlobalConfiguration + * \brief Support for global libcamera configuration + * + * The configuration file is a YAML file and the configuration itself is stored + * under `configuration' top-level item. + * + * The configuration file is looked up in user's home directory first and if it + * is not found then in system-wide configuration directories. If multiple + * configuration files exist then only the first one found is used and no + * configuration merging is performed. + * + * The configuration can be accessed using GlobalConfiguration::configuration(). + */ + +/** + * \typedef GlobalConfiguration::Configuration + * \brief Type representing global libcamera configuration + * + * All code outside GlobalConfiguration must use this type declaration and not + * the underlying type. + */ + +/** + * \brief Return configuration version + * + * The version is (optionally) declared in the configuration file in the + * top-level section `version', alongside `configuration'. This has currently no + * real use but may be needed in future if configuration incompatibilities + * occur. + * + * \return Configuration version as declared in the configuration file or 0 if + * no version is declared there + */ +unsigned int version() +{ + return get()["version"].get().value_or(0); +} + +/** + * \brief Return libcamera global configuration + * + * This returns the whole configuration stored in the top-level section + * `configuration' of the YAML configuration file. + * + * The requested part of the configuration can be accessed using \a YamlObject + * methods. + * + * \note \a YamlObject type itself shouldn't be used in type declarations to + * avoid trouble if we decide to change the underlying data objects in future. + * + * \return The whole configuration section + */ +Configuration configuration() +{ + return get()["configuration"]; +} + +} /* namespace GlobalConfiguration */ + +} /* namespace libcamera */ diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build index 94843eb9..4c003284 100644 --- a/src/libcamera/base/meson.build +++ b/src/libcamera/base/meson.build @@ -16,6 +16,7 @@ libcamera_base_internal_sources = files([ 'event_dispatcher_poll.cpp', 'event_notifier.cpp', 'file.cpp', + 'global_configuration.cpp', 'log.cpp', 'memfd.cpp', 'message.cpp', From patchwork Wed Apr 30 12:14:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23311 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 9983ABE08B for ; Wed, 30 Apr 2025 12:15:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 481A568B2D; Wed, 30 Apr 2025 14:15:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="BcGG48bE"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 76F8868B26 for ; Wed, 30 Apr 2025 14:15:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015309; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MZahhlnFn2YyYQybrHFbq9BB4Ijfz/5yM6URBkHdkfM=; b=BcGG48bEFKwyo3nqgJ27fdgMNWPgYk/+tWBUve2cuaBzsKlqc/nXy5ygAfctxw2smtOwLL v0/cQlyiqWflTvrVYtkOjJicuMSSkJaFWHPR7xeHkDkeJ0YcODS1vIQ/9nXCUcZJUYhU6N l1KkOSG15Mk8VTwpdBKnL+eE11cSSgk= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-58-vveXiH1cPR2wWgNMO13rtg-1; Wed, 30 Apr 2025 08:15:06 -0400 X-MC-Unique: vveXiH1cPR2wWgNMO13rtg-1 X-Mimecast-MFC-AGG-ID: vveXiH1cPR2wWgNMO13rtg_1746015305 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DCB1D19560BB; Wed, 30 Apr 2025 12:15:04 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C3F3418001D5; Wed, 30 Apr 2025 12:15:02 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 03/15] config: Look up logging levels in the configuration file Date: Wed, 30 Apr 2025 14:14:36 +0200 Message-ID: <20250430121449.39910-4-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: vudk1kCO3aKJ_fxD6vuLiLQ_XxvzqVLKVmqChtEFZos_1746015305 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In addition to LIBCAMERA_LOG_LEVELS environment variable, expose the same configuration in the configuration file. Because logging asks for configuration and configuration loading uses logging, extra care is needed. We must prevent calling any log function before configuration is loaded. Otherwise the log function would ask for configuration, it would load the configuration files and would try to log the results. Which can lead to various breakages, even quite subtle; this has been demonstrated in camera_reconfigure test when trying to make the configuration initialization more transparent, as a static variable instance with automatic initialization rather than a pointer with manual initialization() invocation. But we must log at least errors when reading the configuration. Especially, we cannot prevent logging in configuration initialization entirely because the YAML parser may log errors. But in case of an error during configuration initialization, the configuration cannot be read anyway and the statically created initial global configuration instance serves the purpose of providing some, empty configuration. Then the errors from the YAML parser can be logged. We cannot use the same mechanism for other logging in configuration initialization because then logging would read and use the empty configuration, which is not a valid configuration this time, for the whole run of libcamera. The configuration must be initialized, which is done by calling initialize() method in IPAManager constructor. A more suitable place would be CameraManager constructor but it would be too late there, the IPAManager constructor is called earlier. The configuration snippet for logging looks as follows: configuration: log: levels: LIBCAMERA_LOG_LEVELS Signed-off-by: Milan Zamazal --- src/libcamera/base/global_configuration.cpp | 30 ++++++++++++++++++--- src/libcamera/base/log.cpp | 28 ++++++++++--------- src/libcamera/ipa_manager.cpp | 3 +++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index 3350a26a..8d823b98 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -22,8 +22,15 @@ namespace GlobalConfiguration { namespace { +LOG_DEFINE_CATEGORY(Configuration) + std::unique_ptr yamlConfiguration = std::make_unique(); +/* + * Care is needed here to not log anything before the configuration is + * loaded otherwise the logger would be initialized with empty configuration. + */ + bool loadFile(const std::filesystem::path &fileName) { File file(fileName); @@ -31,12 +38,18 @@ bool loadFile(const std::filesystem::path &fileName) return false; } - if (!file.open(File::OpenModeFlag::ReadOnly)) + if (!file.open(File::OpenModeFlag::ReadOnly)) { + LOG(Configuration, Warning) + << "Failed to open configuration file " << fileName; return true; + } auto root = YamlParser::parse(file); - if (!root) + if (!root) { + LOG(Configuration, Warning) + << "Failed to parse configuration file " << fileName; return true; + } yamlConfiguration = std::move(root); return true; @@ -83,7 +96,11 @@ Configuration get() /** * \brief Initialize the global configuration * - * This must be called before global configuration is accessed. + * This function is expected to be called only once, before the configuration is + * queried for the first time. + * + * \note Most notably, the function must be called before any logging, because + * logging queries the configuration. */ void initialize() { @@ -97,6 +114,13 @@ void initialize() * The configuration file is a YAML file and the configuration itself is stored * under `configuration' top-level item. * + * Example configuration file content: + * \code{.yaml} + * configuration: + * log: + * levels: 'IPAManager:DEBUG' + * \endcode + * * The configuration file is looked up in user's home directory first and if it * is not found then in system-wide configuration directories. If multiple * configuration files exist then only the first one found is used and no diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 8bf3e1da..4b287af0 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -5,8 +5,6 @@ * Logging infrastructure */ -#include - #include #include #include @@ -16,18 +14,22 @@ #include #include #include +#include #include #include #include #include -#include - #include +#include #include #include #include +#include + +#include "libcamera/internal/global_configuration.h" + /** * \file base/log.h * \brief Logging infrastructure @@ -235,8 +237,7 @@ void LogOutput::write(const LogMessage &msg) switch (target_) { case LoggingTargetSyslog: - str = std::string(log_severity_name(severity)) + " " - + msg.category().name() + " " + msg.fileInfo() + " "; + str = std::string(log_severity_name(severity)) + " " + msg.category().name() + " " + msg.fileInfo() + " "; if (!msg.prefix().empty()) str += msg.prefix() + ": "; str += msg.msg(); @@ -244,11 +245,7 @@ void LogOutput::write(const LogMessage &msg) break; case LoggingTargetStream: case LoggingTargetFile: - str = "[" + utils::time_point_to_string(msg.timestamp()) + "] [" - + std::to_string(Thread::currentId()) + "] " - + severityColor + log_severity_name(severity) + " " - + categoryColor + msg.category().name() + " " - + fileColor + msg.fileInfo() + " "; + str = "[" + utils::time_point_to_string(msg.timestamp()) + "] [" + std::to_string(Thread::currentId()) + "] " + severityColor + log_severity_name(severity) + " " + categoryColor + msg.category().name() + " " + fileColor + msg.fileInfo() + " "; if (!msg.prefix().empty()) str += prefixColor + msg.prefix() + ": "; str += resetColor + msg.msg(); @@ -628,8 +625,13 @@ void Logger::parseLogFile() void Logger::parseLogLevels() { const char *debug = utils::secure_getenv("LIBCAMERA_LOG_LEVELS"); - if (!debug) - return; + if (!debug) { + const std::optional confDebug = + GlobalConfiguration::configuration()["log"]["levels"].get(); + if (!confDebug.has_value()) + return; + debug = confDebug.value().c_str(); + } for (const char *pair = debug; *debug != '\0'; pair = debug) { const char *comma = strchrnul(debug, ','); diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp index 830750dc..7b4b2946 100644 --- a/src/libcamera/ipa_manager.cpp +++ b/src/libcamera/ipa_manager.cpp @@ -16,6 +16,7 @@ #include #include +#include "libcamera/internal/global_configuration.h" #include "libcamera/internal/ipa_module.h" #include "libcamera/internal/ipa_proxy.h" #include "libcamera/internal/pipeline_handler.h" @@ -103,6 +104,8 @@ LOG_DEFINE_CATEGORY(IPAManager) */ IPAManager::IPAManager() { + GlobalConfiguration::initialize(); + #if HAVE_IPA_PUBKEY if (!pubKey_.isValid()) LOG(IPAManager, Warning) << "Public key not valid"; From patchwork Wed Apr 30 12:14:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23312 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 56D38BE08B for ; Wed, 30 Apr 2025 12:15:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DA19068B31; Wed, 30 Apr 2025 14:15:16 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="MWqBwU/+"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 153A468B2B for ; Wed, 30 Apr 2025 14:15:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015312; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MEtJ2CtjD2VcvcPVZilYKbxVAks0RybmyFHYAgXCuC0=; b=MWqBwU/+K1PfanoB/KjyjtVod8oX2J170K2XSWzSmCJIxtJtU7F39msUx3l7Dq8L37+OxB p7Fuv9XOnDohcQuiQJZw9MlWXygeiESuwUuv73wypTRcu2zcFffYzV/Q7x9bla66bByb9L 11DqxYE8ojGQnrc4j1udRIYYAYPae5U= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-339-J6-mHiy4O8-zZH7aS82odw-1; Wed, 30 Apr 2025 08:15:08 -0400 X-MC-Unique: J6-mHiy4O8-zZH7aS82odw-1 X-Mimecast-MFC-AGG-ID: J6-mHiy4O8-zZH7aS82odw_1746015307 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 105951956078; Wed, 30 Apr 2025 12:15:07 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5A11418001DA; Wed, 30 Apr 2025 12:15:05 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 04/15] config: Add configuration retrieval helpers Date: Wed, 30 Apr 2025 14:14:37 +0200 Message-ID: <20250430121449.39910-5-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: VrTGCVYm4d4gq0FqQ9hSW26iq_KecYSDAZBAPFHxWtM_1746015307 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Let's add some helpers to make accessing simple configuration values simpler. GlobalConfiguration::option must check for the key presence before retrieving the value using operator[] because if the key is not present then YamlObject::empty may be returned as a regular value. Signed-off-by: Milan Zamazal --- .../libcamera/internal/global_configuration.h | 6 +++ src/libcamera/base/global_configuration.cpp | 52 ++++++++++++++++++- src/libcamera/base/log.cpp | 13 ++--- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/include/libcamera/internal/global_configuration.h b/include/libcamera/internal/global_configuration.h index bed88279..07062145 100644 --- a/include/libcamera/internal/global_configuration.h +++ b/include/libcamera/internal/global_configuration.h @@ -7,6 +7,9 @@ #pragma once +#include +#include + #include "libcamera/internal/yaml_parser.h" namespace libcamera { @@ -19,6 +22,9 @@ void initialize(); unsigned int version(); Configuration configuration(); +std::optional option(const std::string &confPath); +std::optional envOption(const char *const envVariable, + const std::string &confPath); } /* namespace GlobalConfiguration */ diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index 8d823b98..84821f26 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -8,6 +8,8 @@ #include "libcamera/internal/global_configuration.h" #include +#include +#include #include #include @@ -126,7 +128,10 @@ void initialize() * configuration files exist then only the first one found is used and no * configuration merging is performed. * - * The configuration can be accessed using GlobalConfiguration::configuration(). + * The configuration can be accessed using the provided helpers. Namely + * GlobalConfiguration::option() or GlobalConfiguration::envOption() to access + * individual options or GlobalConfiguration::configuration() to access the + * whole configuration. */ /** @@ -137,6 +142,51 @@ void initialize() * the underlying type. */ +/** + * \brief Return value of the configuration option identified by \a confPath + * \param[in] confPath Sequence of the YAML section names (excluding + * `configuration') leading to the requested option separated by dots + * \return A value if an item corresponding to \a confPath exists in the + * configuration file, no value otherwise + */ +std::optional option(const std::string &confPath) +{ + const YamlObject *c = &configuration(); + for (auto part : utils::split(confPath, ".")) { + c = &(*c)[part]; + if (!*c) + return {}; + } + return c->get(); +} + +/** + * \brief Return value of the configuration option from a file or environment + * \param[in] envVariable Environment variable to get the value from + * \param[in] confPath The same as in GlobalConfiguration::option + * + * This helper looks first at the given environment variable and if it is + * defined then it returns its value (even if it is empty). Otherwise it looks + * for \a confPath the same way as in GlobalConfiguration::option. Only string + * values are supported. + * + * \note Support for using environment variables to configure libcamera behavior + * is provided here mostly for backward compatibility reasons. Introducing new + * configuration environment variables is discouraged. + * + * \return A value retrieved from the given environment option or configuration + * file or no value if not found + */ +std::optional envOption( + const char *const envVariable, + const std::string &confPath) +{ + const char *envValue = utils::secure_getenv(envVariable); + if (envValue) + return std::optional{ std::string{ envValue } }; + return option(confPath); +} + /** * \brief Return configuration version * diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 4b287af0..3cda7c57 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -624,14 +624,11 @@ void Logger::parseLogFile() */ void Logger::parseLogLevels() { - const char *debug = utils::secure_getenv("LIBCAMERA_LOG_LEVELS"); - if (!debug) { - const std::optional confDebug = - GlobalConfiguration::configuration()["log"]["levels"].get(); - if (!confDebug.has_value()) - return; - debug = confDebug.value().c_str(); - } + const std::optional confDebug = + GlobalConfiguration::envOption("LIBCAMERA_LOG_LEVELS", "log.levels"); + if (!confDebug.has_value()) + return; + const char *debug = confDebug.value().c_str(); for (const char *pair = debug; *debug != '\0'; pair = debug) { const char *comma = strchrnul(debug, ','); From patchwork Wed Apr 30 12:14:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23313 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 6AC9BBE08B for ; Wed, 30 Apr 2025 12:15:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BF98668B2F; Wed, 30 Apr 2025 14:15:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="BAtKO/IL"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0F4C568B28 for ; Wed, 30 Apr 2025 14:15:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015312; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=x0cfFdTQyu63X5WoQ6TH5TRwtGKd63Yf8qz/8DXGMsk=; b=BAtKO/ILXo7CTKJPoEdyK8dJoJpFLcrNZkBxamejGlKnkz+k/0Zg4bk9MOOMQb6Ywyp9dL yqIYlkKavT/6Wc2ThUbVg5VYBsGY1iAGztDoFRag+FWYKE3wmodcbx+eZvSktA71ll6sGu 6qkych1ma4bVY0GVjaSCuJmWJK6CcgU= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-455-qZLJRIKtM8O-V6LNn1RAsg-1; Wed, 30 Apr 2025 08:15:10 -0400 X-MC-Unique: qZLJRIKtM8O-V6LNn1RAsg-1 X-Mimecast-MFC-AGG-ID: qZLJRIKtM8O-V6LNn1RAsg_1746015309 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7B5521955E79; Wed, 30 Apr 2025 12:15:09 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7626818001DA; Wed, 30 Apr 2025 12:15:07 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 05/15] config: Look up log file in configuration file Date: Wed, 30 Apr 2025 14:14:38 +0200 Message-ID: <20250430121449.39910-6-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: ru1kjWb-Ein8PV4H5Xv5luMyoAVNSpoMMIHQrWn2NDI_1746015309 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Let's allow specifying the log file in the configuration file. This requires change in LIBCAMERA_LOG_FILE interpretation so that we can disable the log file in isolated processes. If LIBCAMERA_LOG_FILE is defined but empty, it means there is no log file, even if defined in the configuration file. This should cause no compatibility trouble since opening a file with an empty name makes little sense. The configuration snippet: configuration: log: file: FILENAME Signed-off-by: Milan Zamazal --- src/libcamera/base/global_configuration.cpp | 1 + src/libcamera/base/log.cpp | 13 +++++++++---- src/libcamera/process.cpp | 11 ++++++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index 84821f26..073096b5 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -120,6 +120,7 @@ void initialize() * \code{.yaml} * configuration: * log: + * file: syslog * levels: 'IPAManager:DEBUG' * \endcode * diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 3cda7c57..c702b825 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -603,16 +603,21 @@ Logger::Logger() */ void Logger::parseLogFile() { - const char *file = utils::secure_getenv("LIBCAMERA_LOG_FILE"); - if (!file) + std::optional file = + GlobalConfiguration::envOption("LIBCAMERA_LOG_FILE", "log.file"); + if (!file.has_value()) return; - if (!strcmp(file, "syslog")) { + auto fileValue = file.value(); + if (fileValue == "") + return; + + if (fileValue == "syslog") { logSetTarget(LoggingTargetSyslog); return; } - logSetFile(file, false); + logSetFile(fileValue.c_str(), false); } /** diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp index 68fad327..c606164a 100644 --- a/src/libcamera/process.cpp +++ b/src/libcamera/process.cpp @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -23,6 +25,8 @@ #include #include +#include "libcamera/internal/global_configuration.h" + /** * \file process.h * \brief Process object @@ -261,9 +265,10 @@ int Process::start(const std::string &path, closeAllFdsExcept(fds); - const char *file = utils::secure_getenv("LIBCAMERA_LOG_FILE"); - if (file && strcmp(file, "syslog")) - unsetenv("LIBCAMERA_LOG_FILE"); + std::optional file = + GlobalConfiguration::envOption("LIBCAMERA_LOG_FILE", "log.file"); + if (file.has_value() && file.value() != "syslog") + setenv("LIBCAMERA_LOG_FILE", "", 1); const char **argv = new const char *[args.size() + 2]; unsigned int len = args.size(); From patchwork Wed Apr 30 12:14:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23314 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 195ADBE08B for ; Wed, 30 Apr 2025 12:15:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CD22068B35; Wed, 30 Apr 2025 14:15:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="fyFDednn"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AED2F68B27 for ; Wed, 30 Apr 2025 14:15:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015318; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AhiCSXXN1JT2fUfZHTcuwk7q1S2uxOJgEb0jc1qDws8=; b=fyFDednno5+fp+rUQfPaXuW+RGTbsD10cAMse5Q0eM7CXfrTIP5v0zHeSgihX9bVlebX2K GRqcfFk83es15MbWzuldTiRZMNvfHQB/yT/3Va/PF//O/XC3NvYnf453XhGhJfEvi9ie2F +9hR0Gztzl4V5kJqyj80nAA4QLIq5CM= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-561-EQ6CmXZzNI2Ke0UtDOzAug-1; Wed, 30 Apr 2025 08:15:14 -0400 X-MC-Unique: EQ6CmXZzNI2Ke0UtDOzAug-1 X-Mimecast-MFC-AGG-ID: EQ6CmXZzNI2Ke0UtDOzAug_1746015311 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AB4751955DC6; Wed, 30 Apr 2025 12:15:11 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E178B180010A; Wed, 30 Apr 2025 12:15:09 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 06/15] config: Look up log color configuration in configuration file Date: Wed, 30 Apr 2025 14:14:39 +0200 Message-ID: <20250430121449.39910-7-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: yd_1VKHqtk7cQvKeUIH6t-YKj5KQA-OdnIkH1SmZ6sM_1746015311 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Let's add a configuration file item for logging in color. The configuration snippet: configuration: log: color: BOOL In order to use the global configuration access helper for a boolean value, we must make a template from it. To make the template visible, we must implement it in the header file, otherwise undefined reference error would be reported when linking. We don't implement envOption helper for boolean here, because we would have to deal with a specific value interpretation in this particular case. Signed-off-by: Milan Zamazal --- .../libcamera/internal/global_configuration.h | 27 ++++++++++++++++++- src/libcamera/base/global_configuration.cpp | 19 ++++--------- src/libcamera/base/log.cpp | 2 ++ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/include/libcamera/internal/global_configuration.h b/include/libcamera/internal/global_configuration.h index 07062145..a6e21a2d 100644 --- a/include/libcamera/internal/global_configuration.h +++ b/include/libcamera/internal/global_configuration.h @@ -10,6 +10,8 @@ #include #include +#include + #include "libcamera/internal/yaml_parser.h" namespace libcamera { @@ -22,7 +24,30 @@ void initialize(); unsigned int version(); Configuration configuration(); -std::optional option(const std::string &confPath); + +template || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v> * = nullptr> +std::optional option(const std::string &confPath) +{ + const YamlObject *c = &configuration(); + for (auto part : utils::split(confPath, ".")) { + c = &(*c)[part]; + if (!*c) + return {}; + } + return c->get(); +} + std::optional envOption(const char *const envVariable, const std::string &confPath); diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index 073096b5..3dc31c48 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -14,7 +14,6 @@ #include #include -#include #include "libcamera/internal/yaml_parser.h" @@ -144,22 +143,14 @@ void initialize() */ /** + * \fn std::optional GlobalConfiguration::option(const char *const confPath) * \brief Return value of the configuration option identified by \a confPath + * \tparam T The type of the retrieved configuration value * \param[in] confPath Sequence of the YAML section names (excluding * `configuration') leading to the requested option separated by dots - * \return A value if an item corresponding to \a confPath exists in the - * configuration file, no value otherwise + * \return A value of type \a T if an item corresponding to \a confPath exists + * in the configuration file and matches type \a T, no value otherwise */ -std::optional option(const std::string &confPath) -{ - const YamlObject *c = &configuration(); - for (auto part : utils::split(confPath, ".")) { - c = &(*c)[part]; - if (!*c) - return {}; - } - return c->get(); -} /** * \brief Return value of the configuration option from a file or environment @@ -185,7 +176,7 @@ std::optional envOption( const char *envValue = utils::secure_getenv(envVariable); if (envValue) return std::optional{ std::string{ envValue } }; - return option(confPath); + return option(confPath); } /** diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index c702b825..d8cffbca 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -586,6 +586,8 @@ void Logger::logSetLevel(const char *category, const char *level) Logger::Logger() { bool color = !utils::secure_getenv("LIBCAMERA_LOG_NO_COLOR"); + if (color) + color = GlobalConfiguration::option("log.color").value_or(true); logSetStream(&std::cerr, color); parseLogFile(); From patchwork Wed Apr 30 12:14:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23323 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 515BCBE08B for ; Wed, 30 Apr 2025 12:16:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1272268B37; Wed, 30 Apr 2025 14:16:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="NFpIas6K"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CE01168AD7 for ; Wed, 30 Apr 2025 14:16:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015363; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Y78vWsfDj/uLIEKeU3KpUfoJLVyImkf83i0TuEbV1pk=; b=NFpIas6Kfj3SQBGTXVoRqkLD8Mj/2OUlKmkHRQSbilkajPhLrl5+Pe1/BHKPirz/wZalHK NOXKVMiL8Ibp8kNlRfRQrmEiuNKGkOgnjU3jaGrkXWzkm5sfeCUzwZUpvMDb0FCR9V4XdT qRBhGjq5mM0bF8zvwIKm9WCMi5kZhSA= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-634-GhwiUJMXMKaYmQcbyjY8Hw-1; Wed, 30 Apr 2025 08:15:15 -0400 X-MC-Unique: GhwiUJMXMKaYmQcbyjY8Hw-1 X-Mimecast-MFC-AGG-ID: GhwiUJMXMKaYmQcbyjY8Hw_1746015314 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DB2EF19560AA; Wed, 30 Apr 2025 12:15:13 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 21E2118001D5; Wed, 30 Apr 2025 12:15:11 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 07/15] config: Look up rpi config path in configuration file Date: Wed, 30 Apr 2025 14:14:40 +0200 Message-ID: <20250430121449.39910-8-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Ca1zs0887B3ZlwM1FVr9SvEAqkay6uMrAiKpXHtSJo4_1746015314 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Let's introduce a configuration option for rpi configuration file path. It may be arguable whether pipeline specific configurations belong to the global configuration file. But: - Having a single configuration file is generally easier for the user. - The original configuration via environment variables can be already considered global. - This option points to other configuration files and it makes little sense to add another configuration file to the chain. The configuration snippet: configuration: pipeline: rpi: config_file: FILENAME Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/rpi/common/pipeline_base.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp index 1f13e523..739dc61a 100644 --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp @@ -20,6 +20,7 @@ #include #include "libcamera/internal/camera_lens.h" +#include "libcamera/internal/global_configuration.h" #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/v4l2_subdevice.h" @@ -1102,7 +1103,12 @@ int CameraData::loadPipelineConfiguration() /* Initial configuration of the platform, in case no config file is present */ platformPipelineConfigure({}); - char const *configFromEnv = utils::secure_getenv("LIBCAMERA_RPI_CONFIG_FILE"); + std::optional configFile = + GlobalConfiguration::envOption("LIBCAMERA_RPI_CONFIG_FILE", + "pipelines.rpi.config_file"); + if (!configFile.has_value()) + return 0; + char const *configFromEnv = configFile.value().c_str(); if (!configFromEnv || *configFromEnv == '\0') return 0; From patchwork Wed Apr 30 12:14:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23315 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 24A5BBE08B for ; Wed, 30 Apr 2025 12:15:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B830B68B37; Wed, 30 Apr 2025 14:15:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Shy3Czd9"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 947BF68B27 for ; Wed, 30 Apr 2025 14:15:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015320; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MR6QI2o8el3O9A+3Hd1wZiU8/e1IUDsFxyQF8sv/CEk=; b=Shy3Czd9OCPQ58zBuCtmq6Xt+T3y6o26MJPv/B9447ZdT8QBBSsfuO7ank/O94iAwgQ8V/ C+vd+hZV0XCbpIWvDuOTub7fIhaoS6AYi64IgdV/6SJXTgZHS2MffQd1VB4Fu5hNMZuYod uORXCr0+XmB6S8bXHkSFROh/W5DzgPM= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-610-fbV0eImiOzWi7yVNWlBFGg-1; Wed, 30 Apr 2025 08:15:17 -0400 X-MC-Unique: fbV0eImiOzWi7yVNWlBFGg-1 X-Mimecast-MFC-AGG-ID: fbV0eImiOzWi7yVNWlBFGg_1746015316 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 529141801A18; Wed, 30 Apr 2025 12:15:16 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 596F7180047F; Wed, 30 Apr 2025 12:15:14 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 08/15] config: Look up IPA configurables in configuration file Date: Wed, 30 Apr 2025 14:14:41 +0200 Message-ID: <20250430121449.39910-9-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 1TlGyEKaMqd6m6ahZP7awFwVj4mj_4NXL62CrEDoyRQ_1746015316 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This patch adds configuration options for environment variables used in the IPA proxy. Two utility functions configuration retrieval functions are added, to retrieve lists of values. The configuration snippet: configuration: ipa: config_paths: - config path 1 - config path 2 - ... module_paths: - module path 1 - module path 2 - ... proxy_paths: - proxy path 1 - proxy path 2 - ... force_isolation: BOOL ipas: IPA_NAME: tuning_file: TUNING FILE Signed-off-by: Milan Zamazal --- .../libcamera/internal/global_configuration.h | 4 ++ src/libcamera/base/global_configuration.cpp | 51 +++++++++++++++ src/libcamera/ipa_manager.cpp | 32 +++++---- src/libcamera/ipa_proxy.cpp | 65 ++++++++++--------- 4 files changed, 109 insertions(+), 43 deletions(-) diff --git a/include/libcamera/internal/global_configuration.h b/include/libcamera/internal/global_configuration.h index a6e21a2d..ffa6454c 100644 --- a/include/libcamera/internal/global_configuration.h +++ b/include/libcamera/internal/global_configuration.h @@ -48,8 +48,12 @@ std::optional option(const std::string &confPath) return c->get(); } +std::vector listOption(const std::string &confPath); std::optional envOption(const char *const envVariable, const std::string &confPath); +std::vector envListOption( + const char *const envVariable, + const std::string &confPath); } /* namespace GlobalConfiguration */ diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index 3dc31c48..e69951b4 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -9,11 +9,14 @@ #include #include +#include #include #include +#include #include #include +#include #include "libcamera/internal/yaml_parser.h" @@ -152,6 +155,24 @@ void initialize() * in the configuration file and matches type \a T, no value otherwise */ +/** + * \brief Return values of the configuration option identified by \a confPath + * \tparam T The type of the retrieved configuration value + * \param[in] confPath Sequence of the YAML section names (excluding + * `configuration') leading to the requested list option, separated by dots + * \return A vector of strings (empty one if the option is not found) + */ +std::vector listOption(const std::string &confPath) +{ + const YamlObject *c = &configuration(); + for (auto part : utils::split(confPath, ".")) { + c = &(*c)[part]; + if (!*c) + return {}; + } + return c->getList().value_or(std::vector()); +} + /** * \brief Return value of the configuration option from a file or environment * \param[in] envVariable Environment variable to get the value from @@ -179,6 +200,36 @@ std::optional envOption( return option(confPath); } +/** + * \brief Return values of the configuration option from a file or environment + * \param[in] envVariable Environment variable to get the value from + * \param[in] confPath The same as in GlobalConfiguration::option + * + * This helper looks first at the given environment variable and if it is + * defined (even if it is empty) then it splits its value by semicolons and + * returns the resulting list of strings. Otherwise it looks for \a confPath the + * same way as in GlobalConfiguration::option, value of which must be a list of + * strings. + * + * \note Support for using environment variables to configure libcamera behavior + * is provided here mostly for backward compatibility reasons. Introducing new + * configuration environment variables is discouraged. + * + * \return A vector of strings retrieved from the given environment option or + * configuration file (an empty vector is returned if nothing is found) + */ +std::vector envListOption( + const char *const envVariable, + const std::string &confPath) +{ + const char *envValue = utils::secure_getenv(envVariable); + if (envValue) { + auto items = utils::split(envValue, ":"); + return std::vector(items.begin(), items.end()); + } + return listOption(confPath); +} + /** * \brief Return configuration version * diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp index 7b4b2946..7b082a3b 100644 --- a/src/libcamera/ipa_manager.cpp +++ b/src/libcamera/ipa_manager.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -114,18 +115,25 @@ IPAManager::IPAManager() unsigned int ipaCount = 0; /* User-specified paths take precedence. */ - const char *modulePaths = utils::secure_getenv("LIBCAMERA_IPA_MODULE_PATH"); - if (modulePaths) { - for (const auto &dir : utils::split(modulePaths, ":")) { - if (dir.empty()) - continue; + const auto modulePaths = + GlobalConfiguration::envListOption( + "LIBCAMERA_IPA_MODULE_PATH", "ipa.module_paths"); + for (const auto &dir : modulePaths) { + if (dir.empty()) + continue; - ipaCount += addDir(dir.c_str()); - } + ipaCount += addDir(dir.c_str()); + } - if (!ipaCount) - LOG(IPAManager, Warning) - << "No IPA found in '" << modulePaths << "'"; + if (!ipaCount) { + std::string paths; + if (!modulePaths.empty()) { + paths = std::accumulate(std::next(modulePaths.begin()), + modulePaths.end(), + modulePaths[0], + [](std::string s1, std::string s2) { return s1 + ":" + s2; }); + } + LOG(IPAManager, Warning) << "No IPA found in '" << paths << "'"; } /* @@ -283,7 +291,9 @@ bool IPAManager::isSignatureValid([[maybe_unused]] IPAModule *ipa) const { #if HAVE_IPA_PUBKEY char *force = utils::secure_getenv("LIBCAMERA_IPA_FORCE_ISOLATION"); - if (force && force[0] != '\0') { + if ((force && force[0] != '\0') || + (!force && GlobalConfiguration::option("ipa.force_isolation") + .value_or(false))) { LOG(IPAManager, Debug) << "Isolation of IPA module " << ipa->path() << " forced through environment variable"; diff --git a/src/libcamera/ipa_proxy.cpp b/src/libcamera/ipa_proxy.cpp index 9907b961..10c6ff8e 100644 --- a/src/libcamera/ipa_proxy.cpp +++ b/src/libcamera/ipa_proxy.cpp @@ -14,6 +14,7 @@ #include #include +#include "libcamera/internal/global_configuration.h" #include "libcamera/internal/ipa_module.h" /** @@ -105,37 +106,37 @@ std::string IPAProxy::configurationFile(const std::string &name, const std::string ipaName = ipam_->info().name; /* - * Start with any user override through the module-specific environment - * variable. Use the name of the IPA module up to the first '/' to - * construct the variable name. + * Start with any user override through the module-specific configuration or + * environment variable. Use the name of the IPA module up to the first '/' + * to construct the configuration and variable names. */ - std::string ipaEnvName = ipaName.substr(0, ipaName.find('/')); + std::string ipaBaseName = ipaName.substr(0, ipaName.find('/')); + std::string ipaConfigName = "ipa.ipas." + ipaBaseName + ".tuning_file"; + std::string ipaEnvName = ipaBaseName; std::transform(ipaEnvName.begin(), ipaEnvName.end(), ipaEnvName.begin(), [](unsigned char c) { return std::toupper(c); }); ipaEnvName = "LIBCAMERA_" + ipaEnvName + "_TUNING_FILE"; - char const *configFromEnv = utils::secure_getenv(ipaEnvName.c_str()); - if (configFromEnv && *configFromEnv != '\0') - return { configFromEnv }; + auto config = GlobalConfiguration::envOption(ipaEnvName.c_str(), ipaConfigName); + if (config) + return { config.value() }; struct stat statbuf; int ret; /* - * Check the directory pointed to by the IPA config path environment - * variable next. + * Check the directory pointed to by the IPA config path next. */ - const char *confPaths = utils::secure_getenv("LIBCAMERA_IPA_CONFIG_PATH"); - if (confPaths) { - for (const auto &dir : utils::split(confPaths, ":")) { - if (dir.empty()) - continue; - - std::string confPath = dir + "/" + ipaName + "/" + name; - ret = stat(confPath.c_str(), &statbuf); - if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) - return confPath; - } + auto confPaths = + GlobalConfiguration::envListOption( + "LIBCAMERA_IPA_CONFIG_PATH", "ipa.config_paths"); + for (const auto &dir : confPaths) { + if (dir.empty()) + continue; + std::string confPath = dir + "/" + ipaName + "/" + name; + ret = stat(confPath.c_str(), &statbuf); + if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) + return confPath; } std::string root = utils::libcameraSourcePath(); @@ -199,18 +200,18 @@ std::string IPAProxy::resolvePath(const std::string &file) const { std::string proxyFile = "/" + file; - /* Check env variable first. */ - const char *execPaths = utils::secure_getenv("LIBCAMERA_IPA_PROXY_PATH"); - if (execPaths) { - for (const auto &dir : utils::split(execPaths, ":")) { - if (dir.empty()) - continue; - - std::string proxyPath = dir; - proxyPath += proxyFile; - if (!access(proxyPath.c_str(), X_OK)) - return proxyPath; - } + /* Check the configuration first. */ + const auto execPaths = + GlobalConfiguration::envListOption( + "LIBCAMERA_IPA_PROXY_PATH", "ipa.proxy_paths"); + for (const auto &dir : execPaths) { + if (dir.empty()) + continue; + + std::string proxyPath = dir; + proxyPath += proxyFile; + if (!access(proxyPath.c_str(), X_OK)) + return proxyPath; } /* From patchwork Wed Apr 30 12:14:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23316 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 808D7BE08B for ; Wed, 30 Apr 2025 12:15:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2D5D768B2C; Wed, 30 Apr 2025 14:15:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="QZMSkhYB"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 16A2A68AD8 for ; Wed, 30 Apr 2025 14:15:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015321; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9cqF9s48TA+gD/ht0A94fLLKMU5KTF6yiJ9i5QNojIc=; b=QZMSkhYBVS27rYx5Xu+b10tBRgdoZ5ECYsvrTqsgOdancaBXECBKrPTpWae+sZNAYd4I2v q5V7oOVQhV//NjEJRiiPH82tLllTFWAw22d/Joqgmm6H29j5OwQYY6Ax5/nwCc0smrIfAj onGEZ9hctXjVbK+w9cPuXXVuh9JPH3Y= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-533-gsAGiN3xO7iHGhegZXUZAQ-1; Wed, 30 Apr 2025 08:15:19 -0400 X-MC-Unique: gsAGiN3xO7iHGhegZXUZAQ-1 X-Mimecast-MFC-AGG-ID: gsAGiN3xO7iHGhegZXUZAQ_1746015318 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 93FB719560BC; Wed, 30 Apr 2025 12:15:18 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CB0E3180047F; Wed, 30 Apr 2025 12:15:16 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 09/15] config: Look up pipelines match list in configuration file Date: Wed, 30 Apr 2025 14:14:42 +0200 Message-ID: <20250430121449.39910-10-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: FtH_Ca4qoP0uGRBhcm6mfk7V5ar-KbwhynQvCTAbpKU_1746015318 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Let's add a configuration file item for the pipelines match list. Signed-off-by: Milan Zamazal --- src/libcamera/camera_manager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index e62e7193..3cbffdbd 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -15,6 +15,7 @@ #include "libcamera/internal/camera.h" #include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/global_configuration.h" #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/pipeline_handler.h" @@ -110,14 +111,15 @@ void CameraManager::Private::createPipelineHandlers() * file and only fallback on environment variable or all handlers, if * there is no configuration file. */ - const char *pipesList = - utils::secure_getenv("LIBCAMERA_PIPELINES_MATCH_LIST"); - if (pipesList) { + std::optional pipesList = + GlobalConfiguration::envOption("LIBCAMERA_PIPELINES_MATCH_LIST", + "pipelines_match_list"); + if (pipesList.has_value()) { /* * When a list of preferred pipelines is defined, iterate * through the ordered list to match the enumerated devices. */ - for (const auto &pipeName : utils::split(pipesList, ",")) { + for (const auto &pipeName : utils::split(pipesList.value(), ",")) { const PipelineHandlerFactoryBase *factory; factory = PipelineHandlerFactoryBase::getFactoryByName(pipeName); if (!factory) From patchwork Wed Apr 30 12:14:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23317 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 2F287BE08B for ; Wed, 30 Apr 2025 12:15:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DE03068B33; Wed, 30 Apr 2025 14:15:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="R3xy3ELY"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7D0CE68B30 for ; Wed, 30 Apr 2025 14:15:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015325; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RUIMJmlpVxvDNFshIdsFAdREvh8X/UHoiUNka+Tq46M=; b=R3xy3ELY8vcWXNjKfhCtDBxK2ngpbGUzF4/yfS0bb6zIXCqLuQeta61uEfpQsj/Rl361gF qN1IDcWVymUbR8msjRcNmQDwN+n+7r9zwPMBf2u9aPHXSHreYOyVOn0xBiXd0++KpHDfOm V2U2vVhQUahQjutgAoElZ/+Z7wDEnDE= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-498-BsQjlcoeO6-gykif80CpjQ-1; Wed, 30 Apr 2025 08:15:21 -0400 X-MC-Unique: BsQjlcoeO6-gykif80CpjQ-1 X-Mimecast-MFC-AGG-ID: BsQjlcoeO6-gykif80CpjQ_1746015320 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A8B7719560AE; Wed, 30 Apr 2025 12:15:20 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 17BE9180047F; Wed, 30 Apr 2025 12:15:18 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 10/15] config: Allow enabling software ISP in runtime Date: Wed, 30 Apr 2025 14:14:43 +0200 Message-ID: <20250430121449.39910-11-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: TzDVG3peELNxWt0mV1Q-07VdzkMGZLFMsctFI6IkjJ8_1746015320 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This patch allows enabling or disabling software ISP in runtime in addition to compile time. This can be useful for software ISP testing on various platforms as well as for overriding the defaults in case the defaults don't work well (e.g. hardware ISP may or may not work on i.MX8MP depending on the kernel and libcamera patches present in the given system). The configuration is specified as follows: configuration: pipelines: simple: supported_devices: - driver: DRIVER-NAME software_isp: BOOLEAN - ... For example: configuration: pipelines: simple: supported_devices: - driver: mxc-isi software_isp: true The overall configuration of enabling or disabling software ISP may get dropped in future but this patch is still useful in the meantime. Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index efb07051..dbe8bee4 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -35,6 +35,7 @@ #include "libcamera/internal/converter.h" #include "libcamera/internal/delayed_controls.h" #include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/global_configuration.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/software_isp/software_isp.h" @@ -1688,6 +1689,17 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) } swIspEnabled_ = info->swIspEnabled; + for (GlobalConfiguration::Configuration entry : + GlobalConfiguration::configuration() + ["pipelines"]["simple"]["supported_devices"] + .asList()) { + auto name = entry["driver"].get(); + if (name == info->driver) { + swIspEnabled_ = entry["software_isp"].get().value_or(swIspEnabled_); + LOG(SimplePipeline, Debug) << "Overriding software ISP to " << swIspEnabled_; + break; + } + } /* Locate the sensors. */ std::vector sensors = locateSensors(media); From patchwork Wed Apr 30 12:14:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23318 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 2EDD5BE08B for ; Wed, 30 Apr 2025 12:15:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8585568B3C; Wed, 30 Apr 2025 14:15:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="FAfyOAmr"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BBCD168B35 for ; Wed, 30 Apr 2025 14:15:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015327; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hHY10QrVBpz8NlVXI9Au1VyV8E/7oHTf8qjLwCyd+vk=; b=FAfyOAmrWgbUN/KF6p0/FAxjm6RCURHCA5fG2Lx3tPhN8zGON8ogaUBcZ5H9Qfp4VFXeiL sfzikAbW4Pwbn5fpzK5IFDp8TyEr239CvdGmpk6LYvNHhYaKIxBKMZjLyZba3D+IxecGyu M6UXV1E91EOB6NsNByuW/ACYJHYAhms= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-158-Z0PfZjIuPAKpVExsbvBevw-1; Wed, 30 Apr 2025 08:15:24 -0400 X-MC-Unique: Z0PfZjIuPAKpVExsbvBevw-1 X-Mimecast-MFC-AGG-ID: Z0PfZjIuPAKpVExsbvBevw_1746015322 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C39951800446; Wed, 30 Apr 2025 12:15:22 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 19D2418001DA; Wed, 30 Apr 2025 12:15:20 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 11/15] config: Add global configuration file documentation Date: Wed, 30 Apr 2025 14:14:44 +0200 Message-ID: <20250430121449.39910-12-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: i-LhhKhsvyJDks9aBMZZkpDDgv1r1ZsNJxkjohDZQ9k_1746015322 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend (and rename) the documentation of environment variables with information about the configuration file. Signed-off-by: Milan Zamazal --- Documentation/documentation-contents.rst | 2 +- Documentation/index.rst | 2 +- Documentation/meson.build | 2 +- ...ariables.rst => runtime_configuration.rst} | 112 ++++++++++++++++-- 4 files changed, 102 insertions(+), 16 deletions(-) rename Documentation/{environment_variables.rst => runtime_configuration.rst} (65%) diff --git a/Documentation/documentation-contents.rst b/Documentation/documentation-contents.rst index 5c111849..4be3729c 100644 --- a/Documentation/documentation-contents.rst +++ b/Documentation/documentation-contents.rst @@ -7,7 +7,7 @@ * :doc:`/feature_requirements` * :doc:`/guides/application-developer` * :doc:`/python-bindings` - * :doc:`/environment_variables` + * :doc:`/runtime_configuration` * :doc:`/api-html/index` * :doc:`/code-of-conduct` * | diff --git a/Documentation/index.rst b/Documentation/index.rst index 251112fb..200de6f6 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -12,13 +12,13 @@ Application Writer's Guide Camera Sensor Model - Environment variables Feature Requirements IPA Writer's guide Lens driver requirements libcamera Architecture Pipeline Handler Writer's Guide Python Bindings + Runtime configuration Sensor driver requirements SoftwareISP Benchmarking Tracing guide diff --git a/Documentation/meson.build b/Documentation/meson.build index 0fc5909d..6d5af0f6 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -128,7 +128,6 @@ if sphinx.found() 'contributing.rst', 'design/ae.rst', 'documentation-contents.rst', - 'environment_variables.rst', 'feature_requirements.rst', 'guides/application-developer.rst', 'guides/ipa.rst', @@ -140,6 +139,7 @@ if sphinx.found() 'libcamera_architecture.rst', 'mali-c55.dot', 'python-bindings.rst', + 'runtime_configuration.rst', 'sensor_driver_requirements.rst', 'software-isp-benchmarking.rst', '../README.rst', diff --git a/Documentation/environment_variables.rst b/Documentation/runtime_configuration.rst similarity index 65% rename from Documentation/environment_variables.rst rename to Documentation/runtime_configuration.rst index 6f123558..a3812d44 100644 --- a/Documentation/environment_variables.rst +++ b/Documentation/runtime_configuration.rst @@ -2,49 +2,135 @@ .. include:: documentation-contents.rst -Environment variables +Runtime configuration ===================== -The libcamera behaviour can be tuned through environment variables. This -document lists all the available variables and describes their usage. +The libcamera behaviour can be tuned through a configuration file or +environment variables. This document lists all the configuration options +and describes their usage. + +General rules +------------- + +The configuration file is looked up in the following locations, in this +order: + +- $XDG_CONFIG_HOME/libcamera/configuration.yaml +- LIBCAMERA_SYSCONF_DIR/configuration.yaml +- /etc/libcamera/configuration.yaml + +The first configuration file found wins, contingent configuration files +in other locations are ignored. + +Settings in environment variables take precedence over settings in +configuration files. This allows overriding behaviour temporarily +without the need to modify configuration files. + +Configuration options +--------------------- + +Here is an overview of the available configuration options, in the YAML +file structure: + +:: + + configuration: + ipa: + config_paths: # full paths to directories, separated by colons + force_isolation: # true/false + module_paths: # full paths to directories, separated by colons + ipas: + rkisp1: + tuning_file: # full path + rpi: + tuning_file: # full path + log: + color: # true/false for color/no-color + file: # either `syslog` or a full path + levels: # see Log levels + pipelines_match_list: # pipeline names, separated by commas + pipelines: + rpi: + config_file: # full path + simple: + supported_devices: + - driver: # driver name, e.g. `mxc-isi` + software_isp: # true/false + +Configuration file example +-------------------------- + +:: + + --- + version: 1 + configuration: + ipa: + config_paths: + - /home/user/.libcamera/share/ipa + - /opt/libcamera/vendor/share/ipa + module_paths: + - /home/user/.libcamera/lib + - /opt/libcamera/vendor/lib + proxy_paths: + - /home/user/.libcamera/proxy/worker + - /opt/libcamera/vendor/proxy/worker + force_isolation: true + ipas: + rpi: + tuning_file: /home/pi/imx283.json + log: + color: false + file: syslog + levels: 'IPAManager:DEBUG' + pipelines_match_list: rkisp1,simple + pipelines: + rpi: + config_file: /usr/local/share/libcamera/pipeline/rpi/vc4/minimal_mem.yaml + simple: + supported_devices: + - driver: mxc-isi + software_isp: true List of variables ----------------- -LIBCAMERA_LOG_FILE +The corresponding configuration file paths are listed in parentheses. + +LIBCAMERA_LOG_FILE (log.file) The custom destination for log output. Example value: ``/home/{user}/camera_log.log`` -LIBCAMERA_LOG_LEVELS +LIBCAMERA_LOG_LEVELS (log.levels) Configure the verbosity of log messages for different categories (`more `__). Example value: ``*:DEBUG`` -LIBCAMERA_LOG_NO_COLOR +LIBCAMERA_LOG_NO_COLOR (log.color) Disable coloring of log messages (`more `__). -LIBCAMERA_IPA_CONFIG_PATH +LIBCAMERA_IPA_CONFIG_PATH (ipa.config_paths) Define custom search locations for IPA configurations (`more `__). Example value: ``${HOME}/.libcamera/share/ipa:/opt/libcamera/vendor/share/ipa`` -LIBCAMERA_IPA_FORCE_ISOLATION +LIBCAMERA_IPA_FORCE_ISOLATION (ipa.force_isolation) When set to a non-empty string, force process isolation of all IPA modules. Example value: ``1`` -LIBCAMERA_IPA_MODULE_PATH +LIBCAMERA_IPA_MODULE_PATH (ipa.module_paths) Define custom search locations for IPA modules (`more `__). Example value: ``${HOME}/.libcamera/lib:/opt/libcamera/vendor/lib`` -LIBCAMERA_IPA_PROXY_PATH +LIBCAMERA_IPA_PROXY_PATH (ipa.proxy_paths) Define custom full path for a proxy worker for a given executable name. Example value: ``${HOME}/.libcamera/proxy/worker:/opt/libcamera/vendor/proxy/worker`` -LIBCAMERA_PIPELINES_MATCH_LIST +LIBCAMERA_PIPELINES_MATCH_LIST (pipelines_match_list) Define an ordered list of pipeline names to be used to match the media devices in the system. The pipeline handler names used to populate the variable are the ones passed to the REGISTER_PIPELINE_HANDLER() macro in the @@ -52,7 +138,7 @@ LIBCAMERA_PIPELINES_MATCH_LIST Example value: ``rkisp1,simple`` -LIBCAMERA_RPI_CONFIG_FILE +LIBCAMERA_RPI_CONFIG_FILE (pipelines.rpi.config_file) Define a custom configuration file to use in the Raspberry Pi pipeline handler. Example value: ``/usr/local/share/libcamera/pipeline/rpi/vc4/minimal_mem.yaml`` @@ -156,7 +242,7 @@ code. IPA configuration ~~~~~~~~~~~~~~~~~ -IPA modules use configuration files to store parameters. The format and +IPA modules use their own configuration files to store parameters. The format and contents of the configuration files is specific to the IPA module. They usually contain tuning parameters for the algorithms, in JSON format. From patchwork Wed Apr 30 12:14:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23319 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 E1AE2BE08B for ; Wed, 30 Apr 2025 12:15:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9694668B3E; Wed, 30 Apr 2025 14:15:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Txj1IZJN"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6CA6F68B3C for ; Wed, 30 Apr 2025 14:15:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015329; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xuUa1oqsfSt8W+p75/DmvlqSj23hOoo6x+Y+y8IATyU=; b=Txj1IZJNMrI5ofQZ+4iL8OBhSY0ROxya9Qh1dNKxYtRSjpB1IbcvhccPUkt97v8PAKDle7 d+0mdyuTR6AHm3gr35Rcmc+4dDrMWXvpmWXY+/rqPFAEAterMM+xe7clrDvUh+d2nj6u4Q nHAO9y3KOqz5WUvOS+NAIMQzr4qmKUE= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-617-9eZ0B1EiPZCuHE6NkzJiDw-1; Wed, 30 Apr 2025 08:15:26 -0400 X-MC-Unique: 9eZ0B1EiPZCuHE6NkzJiDw-1 X-Mimecast-MFC-AGG-ID: 9eZ0B1EiPZCuHE6NkzJiDw_1746015325 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0A0E11800873; Wed, 30 Apr 2025 12:15:25 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4850E180047F; Wed, 30 Apr 2025 12:15:23 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 12/15] libcamera: software_isp: Make input buffer copying configurable Date: Wed, 30 Apr 2025 14:14:45 +0200 Message-ID: <20250430121449.39910-13-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: x9jlZHsqo8vjbkGdHZuMdkRY3XyXo1h-LMQQV8RjiHw_1746015325 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" On some platforms, working directly on the input buffer is very slow due to disabled caching. This is why we copy the input buffer into standard (cached) memory. This is an unnecessary overhead on platforms with cached buffers. Let's make input buffer copying configurable. The default is still copying, as it's overhead is much lower than contingent operations on non-cached memory. Ideally, we should improve this in future to set the default to non-copying if we can be sure under observable circumstances that we are working with cached buffers. Completes software ISP TODO #6. Signed-off-by: Milan Zamazal --- Documentation/runtime_configuration.rst | 2 ++ src/libcamera/software_isp/TODO | 11 ----------- src/libcamera/software_isp/debayer_cpu.cpp | 5 ++++- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Documentation/runtime_configuration.rst b/Documentation/runtime_configuration.rst index a3812d44..d439fa21 100644 --- a/Documentation/runtime_configuration.rst +++ b/Documentation/runtime_configuration.rst @@ -53,6 +53,7 @@ file structure: rpi: config_file: # full path simple: + copy_input_buffer: # true/false supported_devices: - driver: # driver name, e.g. `mxc-isi` software_isp: # true/false @@ -88,6 +89,7 @@ Configuration file example rpi: config_file: /usr/local/share/libcamera/pipeline/rpi/vc4/minimal_mem.yaml simple: + copy_input_buffer: false supported_devices: - driver: mxc-isi software_isp: true diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO index a50db668..2c919f44 100644 --- a/src/libcamera/software_isp/TODO +++ b/src/libcamera/software_isp/TODO @@ -71,17 +71,6 @@ per-frame buffers like we do for hardware ISPs. --- -6. Input buffer copying configuration - -> DebayerCpu::DebayerCpu(std::unique_ptr stats) -> : stats_(std::move(stats)), gammaCorrection_(1.0) -> { -> enableInputMemcpy_ = true; - -Set this appropriately and/or make it configurable. - ---- - 7. Performance measurement configuration > void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 66f6038c..2c8faa22 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -24,6 +24,7 @@ #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/dma_buf_allocator.h" #include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/global_configuration.h" #include "libcamera/internal/mapped_framebuffer.h" namespace libcamera { @@ -50,7 +51,9 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats) * always set it to true as the safer choice but this should be changed in * future. */ - enableInputMemcpy_ = true; + enableInputMemcpy_ = GlobalConfiguration::option( + "pipelines.simple.copy_input_buffer") + .value_or(true); /* Initialize color lookup tables */ for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { From patchwork Wed Apr 30 12:14:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23320 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 0BC9BBE08B for ; Wed, 30 Apr 2025 12:15:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B4F5468B41; Wed, 30 Apr 2025 14:15:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="DvTpuEaT"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C913168B2D for ; Wed, 30 Apr 2025 14:15:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015331; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0+XK7b9tV2OtwxbUreMwjcKDQTNLBCfAPpCL6mZxlKY=; b=DvTpuEaTxcEjRBFju4GRQWxI+t/tcnP8s+dpKMzfat6xO4fjA8b0wz6pddeJszxbogxy8q ztMAPhStc6RzZ+gTgu6KYlKfZrUAXVB+yv9sET3jSv5yLbbxMrvKtWBYojltnCTYLFS0w5 a+N4QyOpfxr5iHTy/1Q6YTlssQ940Vs= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-340-t9J-f8zmOoGS_UIn_vM3gw-1; Wed, 30 Apr 2025 08:15:28 -0400 X-MC-Unique: t9J-f8zmOoGS_UIn_vM3gw-1 X-Mimecast-MFC-AGG-ID: t9J-f8zmOoGS_UIn_vM3gw_1746015327 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3B0591956096; Wed, 30 Apr 2025 12:15:27 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7191F180047F; Wed, 30 Apr 2025 12:15:25 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 13/15] libcamera: software_isp: Make measurement configurable Date: Wed, 30 Apr 2025 14:14:46 +0200 Message-ID: <20250430121449.39910-14-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: yYbGNKHc3lbUo1gsIANvaLaza4MtxCcLgYShZzyio5g_1746015327 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Software ISP performs performance measurement on certain part of initial frames. Let's make this range configurable. For this purpose, this patch introduces new configuration options pipelines.simple.measure.skip and pipelines.simple.measure.number. Setting the latter one to 0 disables the measurement. Instead of the last frame, the class member and its configuration specify the number of frames to measure. This is easier to use for users and doesn't require to adjust two configuration parameters when the number of the initially skipped frames is changed. The patch also changes the names of the class members to make them more accurate. Completes software ISP TODO #7. Signed-off-by: Milan Zamazal --- Documentation/runtime_configuration.rst | 6 ++++++ src/libcamera/software_isp/TODO | 25 ---------------------- src/libcamera/software_isp/debayer_cpu.cpp | 25 ++++++++++++++-------- src/libcamera/software_isp/debayer_cpu.h | 7 +++--- 4 files changed, 25 insertions(+), 38 deletions(-) diff --git a/Documentation/runtime_configuration.rst b/Documentation/runtime_configuration.rst index d439fa21..943f8876 100644 --- a/Documentation/runtime_configuration.rst +++ b/Documentation/runtime_configuration.rst @@ -54,6 +54,9 @@ file structure: config_file: # full path simple: copy_input_buffer: # true/false + measure: + skip: # non-negative integer, frames to skip initially + number: # non-negative integer, frames to measure supported_devices: - driver: # driver name, e.g. `mxc-isi` software_isp: # true/false @@ -90,6 +93,9 @@ Configuration file example config_file: /usr/local/share/libcamera/pipeline/rpi/vc4/minimal_mem.yaml simple: copy_input_buffer: false + measure: + skip: 50 + number: 30 supported_devices: - driver: mxc-isi software_isp: true diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO index 2c919f44..f19e15ae 100644 --- a/src/libcamera/software_isp/TODO +++ b/src/libcamera/software_isp/TODO @@ -71,31 +71,6 @@ per-frame buffers like we do for hardware ISPs. --- -7. Performance measurement configuration - -> void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) -> /* Measure before emitting signals */ -> if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure && -> ++measuredFrames_ > DebayerCpu::kFramesToSkip) { -> timespec frameEndTime = {}; -> clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime); -> frameProcessTime_ += timeDiff(frameEndTime, frameStartTime); -> if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) { -> const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure - -> DebayerCpu::kFramesToSkip; -> LOG(Debayer, Info) -> << "Processed " << measuredFrames -> << " frames in " << frameProcessTime_ / 1000 << "us, " -> << frameProcessTime_ / (1000 * measuredFrames) -> << " us/frame"; -> } -> } - -I wonder if there would be a way to control at runtime when/how to -perform those measurements. Maybe that's a bit overkill. - ---- - 8. DebayerCpu cleanups > >> class DebayerCpu : public Debayer, public Object diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 2c8faa22..f8893332 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -55,6 +55,13 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats) "pipelines.simple.copy_input_buffer") .value_or(true); + skipBeforeMeasure_ = GlobalConfiguration::option( + "pipelines.simple.measure.skip") + .value_or(skipBeforeMeasure_); + framesToMeasure_ = GlobalConfiguration::option( + "pipelines.simple.measure.number") + .value_or(framesToMeasure_); + /* Initialize color lookup tables */ for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { red_[i] = green_[i] = blue_[i] = i; @@ -557,7 +564,7 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, lineBuffers_[i].resize(lineBufferLength_); } - measuredFrames_ = 0; + encounteredFrames_ = 0; frameProcessTime_ = 0; return 0; @@ -763,7 +770,10 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output { timespec frameStartTime; - if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) { + bool measure = framesToMeasure_ > 0 && + encounteredFrames_ < skipBeforeMeasure_ + framesToMeasure_ && + ++encounteredFrames_ > skipBeforeMeasure_; + if (measure) { frameStartTime = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime); } @@ -820,18 +830,15 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output dmaSyncers.clear(); /* Measure before emitting signals */ - if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure && - ++measuredFrames_ > DebayerCpu::kFramesToSkip) { + if (measure) { timespec frameEndTime = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime); frameProcessTime_ += timeDiff(frameEndTime, frameStartTime); - if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) { - const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure - - DebayerCpu::kFramesToSkip; + if (encounteredFrames_ == skipBeforeMeasure_ + framesToMeasure_) { LOG(Debayer, Info) - << "Processed " << measuredFrames + << "Processed " << framesToMeasure_ << " frames in " << frameProcessTime_ / 1000 << "us, " - << frameProcessTime_ / (1000 * measuredFrames) + << frameProcessTime_ / (1000 * framesToMeasure_) << " us/frame"; } } diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 926195e9..dc52a0a8 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -160,11 +160,10 @@ private: unsigned int xShift_; /* Offset of 0/1 applied to window_.x */ bool enableInputMemcpy_; bool swapRedBlueGains_; - unsigned int measuredFrames_; + unsigned int encounteredFrames_; int64_t frameProcessTime_; - /* Skip 30 frames for things to stabilize then measure 30 frames */ - static constexpr unsigned int kFramesToSkip = 30; - static constexpr unsigned int kLastFrameToMeasure = 60; + unsigned int skipBeforeMeasure_ = 30; + unsigned int framesToMeasure_ = 30; }; } /* namespace libcamera */ From patchwork Wed Apr 30 12:14:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23321 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 067E4BE08B for ; Wed, 30 Apr 2025 12:15:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9A82568B3A; Wed, 30 Apr 2025 14:15:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="f9Mm4hx0"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 81E7768B2F for ; Wed, 30 Apr 2025 14:15:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015332; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hVuXi6WG1+MdwXG+EfcioXkGugI3ds305bJq0tPbPuU=; b=f9Mm4hx0Wq8xdcyggRkywPmBxm6eoNJ4uENp0t5Jyi5NJRJiXrlWaigONBw4jlF5aZgOAj Z1wcykoOTQhf5/kq++no33FiG4tw2J7pB5qNxoPmTaXeUl/fTJaFCrmfeMCaJKePMQa/zS 2MTWkw3kLETzzfAJHAfXCxKgrPESS4c= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-439-HBMBaN51MbOJne_lUMbKlA-1; Wed, 30 Apr 2025 08:15:30 -0400 X-MC-Unique: HBMBaN51MbOJne_lUMbKlA-1 X-Mimecast-MFC-AGG-ID: HBMBaN51MbOJne_lUMbKlA_1746015329 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9B385180034E; Wed, 30 Apr 2025 12:15:29 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A7373180047F; Wed, 30 Apr 2025 12:15:27 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 14/15] config: Make configuration file configurable Date: Wed, 30 Apr 2025 14:14:47 +0200 Message-ID: <20250430121449.39910-15-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: FMAZDEzxHAb0VQW1QxiLtr1NGrX1AmgqPKOevWE7WYI_1746015329 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" To support easy switching of configurations, let's introduce LIBCAMERA_CONFIG_NAME environment variable, which denotes: - The path of the configuration file to load if it is an absolute path; or - the path of the configuration file to load, relative to the configuration directories. If such a configuration file doesn't exist, no custom configuration is loaded. Signed-off-by: Milan Zamazal --- Documentation/runtime_configuration.rst | 8 +++++++ src/libcamera/base/global_configuration.cpp | 26 ++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Documentation/runtime_configuration.rst b/Documentation/runtime_configuration.rst index 943f8876..f0ad349b 100644 --- a/Documentation/runtime_configuration.rst +++ b/Documentation/runtime_configuration.rst @@ -19,6 +19,14 @@ order: - LIBCAMERA_SYSCONF_DIR/configuration.yaml - /etc/libcamera/configuration.yaml +The default name of the configuration file, configuration.yaml, can be +overridden in LIBCAMERA_CONFIG_NAME environment variable. The variable +can specify just an alternative configuration file name to be looked up +in the locations above, or it can contain a whole relative or absolute +path. If an absolute path is specified then it is the only location that +is used; if the given file doesn't exist then no configuration file is +read. + The first configuration file found wins, contingent configuration files in other locations are ignored. diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index e69951b4..f35b3dae 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -60,13 +60,27 @@ bool loadFile(const std::filesystem::path &fileName) } const std::vector - globalConfigurationFiles = { - std::filesystem::path(LIBCAMERA_SYSCONF_DIR) / "configuration.yaml", - std::filesystem::path("/etc/libcamera/configuration.yaml"), + globalConfigurationDirectories = { + std::filesystem::path(LIBCAMERA_SYSCONF_DIR), + std::filesystem::path("/etc/libcamera"), }; void load() { + const char *libcameraConfigName = + utils::secure_getenv("LIBCAMERA_CONFIG_NAME"); + if (!libcameraConfigName) + libcameraConfigName = ""; + std::filesystem::path configName(libcameraConfigName); + + if (configName.is_absolute()) { + loadFile(configName); + return; + } + + if (configName.empty()) + configName = std::filesystem::path("configuration.yaml"); + std::filesystem::path userConfigurationDirectory; char *xdgConfigHome = utils::secure_getenv("XDG_CONFIG_HOME"); if (xdgConfigHome) { @@ -80,13 +94,13 @@ void load() if (!userConfigurationDirectory.empty()) { std::filesystem::path user_configuration_file = - userConfigurationDirectory / "libcamera" / "configuration.yaml"; + userConfigurationDirectory / "libcamera" / configName; if (loadFile(user_configuration_file)) return; } - for (const auto &path : globalConfigurationFiles) - if (loadFile(path)) + for (const auto &path : globalConfigurationDirectories) + if (loadFile(path / configName)) return; } From patchwork Wed Apr 30 12:14:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 23322 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 AAA87BE08B for ; Wed, 30 Apr 2025 12:15:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 12D6668B45; Wed, 30 Apr 2025 14:15:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Xk8t7xBN"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F1A3168B2D for ; Wed, 30 Apr 2025 14:15:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746015336; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cn+M7TwClTPf1UO1H4rcv+z5fIdIv4yASiLTQvTDZew=; b=Xk8t7xBNqwDh1XzZKpLCx/m8C4fBtvN/sKsmLyTtjzS4O1gbllRsxkujxSa450FdchmCkT i2UAj6PnIX8CqnCRde0JvnpC1pulomkknkGRx07a6lK+a+zL3tqnVZvPIje6lRIZZBtQTR p0C9V150Xhev4etka/A06xxrysTEtBk= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-421-ab4FXDXOPCaHEnpEErzLHw-1; Wed, 30 Apr 2025 08:15:32 -0400 X-MC-Unique: ab4FXDXOPCaHEnpEErzLHw-1 X-Mimecast-MFC-AGG-ID: ab4FXDXOPCaHEnpEErzLHw_1746015331 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CA7091956096; Wed, 30 Apr 2025 12:15:31 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.120]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0E138180047F; Wed, 30 Apr 2025 12:15:29 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Laurent Pinchart Subject: [PATCH v8 15/15] config: Make configuration directories configurable Date: Wed, 30 Apr 2025 14:14:48 +0200 Message-ID: <20250430121449.39910-16-mzamazal@redhat.com> In-Reply-To: <20250430121449.39910-1-mzamazal@redhat.com> References: <20250430121449.39910-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: h9kO1LZ0SuYLtsQsxzlibC1YED_oIWPiBKSScuSSIJs_1746015331 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A newly introduced LIBCAMERA_CONFIG_DIR environment variable specifies a directory or a list of directories separated by colons where to look for the libcamera configuration file before trying the standard locations. Signed-off-by: Milan Zamazal --- Documentation/runtime_configuration.rst | 5 +++++ src/libcamera/base/global_configuration.cpp | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Documentation/runtime_configuration.rst b/Documentation/runtime_configuration.rst index f0ad349b..19d1824f 100644 --- a/Documentation/runtime_configuration.rst +++ b/Documentation/runtime_configuration.rst @@ -19,6 +19,11 @@ order: - LIBCAMERA_SYSCONF_DIR/configuration.yaml - /etc/libcamera/configuration.yaml +If LIBCAMERA_CONFIG_DIR environment variable is non-empty then it +specifies additional directories where to look for the configuration +file, before looking at the standard locations. It can be a single +directory or multiple directories separated by colons. + The default name of the configuration file, configuration.yaml, can be overridden in LIBCAMERA_CONFIG_NAME environment variable. The variable can specify just an alternative configuration file name to be looked up diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp index f35b3dae..315ea7ad 100644 --- a/src/libcamera/base/global_configuration.cpp +++ b/src/libcamera/base/global_configuration.cpp @@ -59,12 +59,6 @@ bool loadFile(const std::filesystem::path &fileName) return true; } -const std::vector - globalConfigurationDirectories = { - std::filesystem::path(LIBCAMERA_SYSCONF_DIR), - std::filesystem::path("/etc/libcamera"), - }; - void load() { const char *libcameraConfigName = @@ -81,6 +75,17 @@ void load() if (configName.empty()) configName = std::filesystem::path("configuration.yaml"); + const char *const configDir = utils::secure_getenv("LIBCAMERA_CONFIG_DIR"); + std::vector globalConfigurationDirectories; + if (configDir) + for (auto const &path : utils::split(configDir, ":")) + if (!path.empty()) + globalConfigurationDirectories.push_back(path); + globalConfigurationDirectories.push_back( + std::filesystem::path(LIBCAMERA_SYSCONF_DIR)); + globalConfigurationDirectories.push_back( + std::filesystem::path("/etc/libcamera")); + std::filesystem::path userConfigurationDirectory; char *xdgConfigHome = utils::secure_getenv("XDG_CONFIG_HOME"); if (xdgConfigHome) {