From patchwork Mon Oct 7 09:54:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21524 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 97507C3264 for ; Mon, 7 Oct 2024 09:54:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6700063536; Mon, 7 Oct 2024 11:54:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ksQtZfvu"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 64B736352D for ; Mon, 7 Oct 2024 11:54:33 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 859AE55; Mon, 7 Oct 2024 11:52:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294777; bh=mwTbDvgj9NfE8vYX85KBZNJCWGr2we9pfCBV7XsWqCs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ksQtZfvu1LUeR918Gu81QJNux6JntuOV+AleXAQ1F9hOL7tXLCxDwzIdGoW4DNCSO b5ixyReBAnPqY8ImduSJorlWTTiUwJNxqlO3KUVc+EzMdAfLjWImxNz2OU9pHbC85Z 7Ng4P0otn/GCpjep1dvvJNxGGLumkd7amdhY7+mA= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Laurent Pinchart Subject: [PATCH v2 1/7] libcamera: Add debug control space Date: Mon, 7 Oct 2024 11:54:05 +0200 Message-ID: <20241007095425.211158-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a new 'debug' controls namespace for the upcoming implementation of debug metadata. While at it, sort the entries alphabetically. Signed-off-by: Stefan Klug Reviewed-by: Laurent Pinchart --- Changes in v2: - Order lists in meson file alphabetically - Fix wording in control-ranges --- include/libcamera/meson.build | 5 +++-- src/libcamera/control_ids_debug.yaml | 7 +++++++ src/libcamera/control_ranges.yaml | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 src/libcamera/control_ids_debug.yaml diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index a969a95dbf7a..fd69a5172b6a 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -34,8 +34,9 @@ libcamera_headers_install_dir = get_option('includedir') / libcamera_include_dir controls_map = { 'controls': { - 'draft': 'control_ids_draft.yaml', 'core': 'control_ids_core.yaml', + 'debug': 'control_ids_debug.yaml', + 'draft': 'control_ids_draft.yaml', 'rpi/vc4': 'control_ids_rpi.yaml', }, @@ -55,7 +56,7 @@ foreach mode, entry : controls_map files_list = [] input_files = [] foreach vendor, header : entry - if vendor != 'core' and vendor != 'draft' + if vendor not in ['core', 'debug', 'draft'] if vendor not in pipelines continue endif diff --git a/src/libcamera/control_ids_debug.yaml b/src/libcamera/control_ids_debug.yaml new file mode 100644 index 000000000000..62f742c58129 --- /dev/null +++ b/src/libcamera/control_ids_debug.yaml @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +%YAML 1.1 +--- +vendor: debug +controls: + diff --git a/src/libcamera/control_ranges.yaml b/src/libcamera/control_ranges.yaml index d42447d04647..6752eb986ac6 100644 --- a/src/libcamera/control_ranges.yaml +++ b/src/libcamera/control_ranges.yaml @@ -13,6 +13,8 @@ ranges: draft: 10000 # Raspberry Pi vendor controls rpi: 20000 - # Next range starts at 30000 + # Controls for debug metadata + debug: 30000 + # Next range starts at 40000 ... From patchwork Mon Oct 7 09:54:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21525 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 8FADCBD80A for ; Mon, 7 Oct 2024 09:54:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6503B63535; Mon, 7 Oct 2024 11:54:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="TfksGh/e"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 61CB16352D for ; Mon, 7 Oct 2024 11:54:36 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8D32C49E; Mon, 7 Oct 2024 11:53:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294780; bh=eh7WhZirsJVemqom/sbb5vduqK8tqmE9IEIX1lhhN0Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TfksGh/eQAHtbNnWGWuonTUhnaAnG080mqd6tX9gLmI+Au02+rMbORowDK6htKpSz VGRJnrLsP/BE23cdVgpZnSgVHKJjKRpT+xV8gfce0rmQlgr96QDt8jfgOzrcUWlbth 85S2e3QOWxMt6ShaRBPEp3EdIFdVh7dDYwbAVh4M= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v2 2/7] libcamera: Add a DebugMetadata helper Date: Mon, 7 Oct 2024 11:54:06 +0200 Message-ID: <20241007095425.211158-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Debug metadata often occurs in places where the metadata control list is not available e.g. in queueRequest() or processStatsBuffer() or even in a class far away from the metadata handling code. It is therefore difficult to add debug metadata without adding lots of boilerplate code. This can be mitigated by recording the metadata and forwarding it to the metadata control list when it becomes available. To solve the issue of code that is far away from the metadata context, add a chaining mechanism to allow loose coupling at runtime. Signed-off-by: Stefan Klug --- Changes in v2: - Replace assignments of ControlList by a moveEntries function - Replace assignUpstream by setParent - Improve documentation --- include/libcamera/internal/debug_controls.h | 46 +++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/control_ids_core.yaml | 5 + src/libcamera/control_ids_debug.yaml | 3 +- src/libcamera/debug_controls.cpp | 145 ++++++++++++++++++++ src/libcamera/meson.build | 1 + 6 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 include/libcamera/internal/debug_controls.h create mode 100644 src/libcamera/debug_controls.cpp diff --git a/include/libcamera/internal/debug_controls.h b/include/libcamera/internal/debug_controls.h new file mode 100644 index 000000000000..00457d60b1a2 --- /dev/null +++ b/include/libcamera/internal/debug_controls.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * Debug metadata helpers + */ + +#pragma once + +#include + +namespace libcamera { + +class DebugMetadata +{ +public: + DebugMetadata() = default; + + void checkForEnable(const ControlList &controls); + void enable(bool enable = true); + void setParent(DebugMetadata *parent); + void moveEntries(ControlList &list); + + template + void set(const Control &ctrl, const V &value) + { + if (parent_) { + parent_->set(ctrl, value); + return; + } + + if (!enabled_) + return; + + cache_.set(ctrl, value); + } + + void set(unsigned int id, const ControlValue &value); + +private: + bool enabled_ = false; + DebugMetadata *parent_ = nullptr; + ControlList cache_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 1c5eef9cab80..1dddcd50c90b 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -14,6 +14,7 @@ libcamera_internal_headers = files([ 'control_serializer.h', 'control_validator.h', 'converter.h', + 'debug_controls.h', 'delayed_controls.h', 'device_enumerator.h', 'device_enumerator_sysfs.h', diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index 1b1bd9507d25..d34a2d068b60 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -968,4 +968,9 @@ controls: The default gamma value must be 2.2 which closely mimics sRGB gamma. Note that this is camera gamma, so it is applied as 1.0/gamma. + - DebugMetadataEnable: + type: bool + description: | + Enable or disable the debug metadata. + ... diff --git a/src/libcamera/control_ids_debug.yaml b/src/libcamera/control_ids_debug.yaml index 62f742c58129..797532712099 100644 --- a/src/libcamera/control_ids_debug.yaml +++ b/src/libcamera/control_ids_debug.yaml @@ -3,5 +3,4 @@ %YAML 1.1 --- vendor: debug -controls: - +controls: [] diff --git a/src/libcamera/debug_controls.cpp b/src/libcamera/debug_controls.cpp new file mode 100644 index 000000000000..84157aca5a74 --- /dev/null +++ b/src/libcamera/debug_controls.cpp @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * Helper to easily record debug metadata inside libcamera. + */ + +#include "libcamera/internal/debug_controls.h" + +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(DebugControls) + +/** + * \file debug_controls.h + * \brief Helper to easily record debug metadata inside libcamera + */ + +/** + * \class DebugMetadata + * \brief Helper to record metadata for later use + * + * When one wants to record debug metadata, the metadata list is often not + * directly available (either because we are inside process() of an IPA or + * because we are in a closed module). This class allows to record the data and + * at a later point in time forward it either to another DebugMetadata instance + * or to a ControlList. + */ + +/** + * \fn DebugMetadata::checkForEnable + * \brief Check for DebugMetadataEnable in the supplied ControlList + * \param[in] controls The supplied ControlList + * + * Looks for controls::DebugMetadataEnable and enables or disables debug + * metadata handling accordingly. + */ +void DebugMetadata::checkForEnable(const ControlList &controls) +{ + const auto &ctrl = controls.get(controls::DebugMetadataEnable); + if (ctrl) + enable(*ctrl); +} + +/** + * \fn DebugMetadata::enable + * \brief Enables or disabled metadata handling + * \param[in] enable The enable state + * + * Enables or disables metadata handling according to \a enable. When \a enable + * is true, all calls to set() get cached and can later be retrieved using \a + * DebugMetadata::moveEntries(). When \a enable is false, the cache gets cleared + * and no further metadata is recorded. + * + * Forwarding to a parent is independent of the enabled state. + */ +void DebugMetadata::enable(bool enable) +{ + enabled_ = enable; + if (!enabled_) + cache_.clear(); +} + +/** + * \fn DebugMetadata::setParent + * \brief Assign a parent metadata handler + * \param[in] parent Pointer to the parent handler + * + * When a \a parent gets set, all further calls to DebugMetadata::set are + * forwarded to that instance. It is not allowed to enable a DebugMetadata + * object, log entries to it and later set the parent. This is done to keep a + * path open for switching to tracing infrastructure later. For tracing one + * would need some kind of "context" identifier that needs to be available on + * set() time. The parent can be treated as such. The top level object + * (the one where enable() get's called) lives in a place where that information + * is also available. + * + * The parent can be reset by passing a nullptr. + */ +void DebugMetadata::setParent(DebugMetadata *parent) +{ + parent_ = parent; + + if (!parent_) + return; + + if (!cache_.empty()) + LOG(DebugControls, Error) + << "Controls were recorded before setting a parent." + << " These are dropped."; + + cache_.clear(); +} + +/** + * \fn DebugMetadata::moveEntries + * \brief Move all cached entries into a list + * \param[in] list The list + * + * Moves all entries into the list specified by \a list. Duplicate entries in + * \a list get overwritten. + */ +void DebugMetadata::moveEntries(ControlList &list) +{ + list.merge(std::move(cache_), ControlList::MergePolicy::OverwriteExisting); + cache_.clear(); +} + +/** + * \fn DebugMetadata::set(const Control &ctrl, const V &value) + * \brief Set a value + * \param[in] ctrl The ctrl to set + * \param[in] value The control value + * + * Sets the debug metadata for \a ctrl to value \a value. If a parent is set, + * the value gets passed there unconditionally. Otherwise it gets cached if the + * instance is enabled or dropped silently when disabled. + */ + +/** + * \fn DebugMetadata::set(unsigned int id, const ControlValue &value) + * \brief Set a value + * \param[in] id The id of the control + * \param[in] value The control value + * + * Sets the debug metadata for \a id to value \a value. If a parent is set, + * the value gets passed there unconditionally. Otherwise it gets cached if the + * instance is enabled or dropped silently when disabled. + */ +void DebugMetadata::set(unsigned int id, const ControlValue &value) +{ + if (parent_) { + parent_->set(id, value); + return; + } + + if (!enabled_) + return; + + cache_.set(id, value); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index aa9ab0291854..f7b5ee8dcc34 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -25,6 +25,7 @@ libcamera_internal_sources = files([ 'control_validator.cpp', 'converter.cpp', 'delayed_controls.cpp', + 'debug_controls.cpp', 'device_enumerator.cpp', 'device_enumerator_sysfs.cpp', 'dma_buf_allocator.cpp', From patchwork Mon Oct 7 09:54:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21526 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 554B2C32DD for ; Mon, 7 Oct 2024 09:54:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DAEAD63539; Mon, 7 Oct 2024 11:54:44 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BIjfnJiF"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BE63E63532 for ; Mon, 7 Oct 2024 11:54:40 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A77911111; Mon, 7 Oct 2024 11:53:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294783; bh=n4SLJwD6XK6lTuOS7gyxMQ7vQzP/IusI2D3c6pPxqr0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BIjfnJiFJ1YdYVpq+6d6gmG/LH6sx2LFYBdamU3j3iIsyNMQzwdMjTFlrT0K8sgna bOX/8FojuL4S9aynQw0ZSRFS9oWGp1fWUhZHSIT5kxr6aUpsXl96ojy2hiS0ITGOPT QmGVAYLk8yddWcyTkammTgrQ4c+LfolAr+E+98O8= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v2 3/7] utils: Add script to generate control_ids_debug.yaml Date: Mon, 7 Oct 2024 11:54:07 +0200 Message-ID: <20241007095425.211158-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" For flexible debugging it is helpful to minimize the roundtrip time. This script parses the sourcetree and looks for usages of set(controls::debug::Something, and adds (or removes) the controls as necessary from the yaml description. It is meant to be used during development to ease the creation of the correct yaml entries. Signed-off-by: Stefan Klug --- Changes in v2: - Search only until the first comma of the set() call, to allow linebreaks there. - Support ruamel.yaml as fallback - Rename output to ctrl_file - Add "generated by" comment in yaml file --- utils/gen-debug-controls.py | 165 ++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100755 utils/gen-debug-controls.py diff --git a/utils/gen-debug-controls.py b/utils/gen-debug-controls.py new file mode 100755 index 000000000000..c5c4570ffd00 --- /dev/null +++ b/utils/gen-debug-controls.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024, Ideas on Board Inc. +# +# Author: Stefan Klug +# +# This script looks for occurrences of the debug metadata controls in the source +# tree and updates src/libcamera/control_ids_debug.yaml accordingly. It is meant +# to be used during development to ease updating of the yaml file while +# debugging. + +import argparse +import logging +import os +import re +import sys +from dataclasses import dataclass +from pathlib import Path + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') + +try: + import ruyaml +except: + try: + import ruamel.yaml as ruyaml + except: + logger.error( + f'Failed to import ruyaml. Please install the ruyaml or the ruamel.yaml package.') + sys.exit(1) + +@dataclass +class FoundMatch: + file: os.PathLike + whole_match: str + line: int + type: str + name: str + size: str = None + + +def get_control_name(control): + k = list(control.keys()) + if len(k) != 1: + raise Exception(f"Can't handle control entry with {len(k)} keys") + return k[0] + + +def find_debug_controls(dir): + extensions = ['.cpp', '.h'] + files = [p for p in dir.rglob('*') if p.suffix in extensions] + + # The following regex was tested on + # set>( controls::debug::something , static_cast(var) ) + # set<>( controls::debug::something , static_cast(var) ) + # set( controls::debug::something , static_cast (var) ) + exp = re.compile(r'set' # set function + # possibly followed by template param + r'(?:\<((?:[^)(])*)\>)?' + # referencing a debug control + r'\(\s*controls::debug::(\w+)\s*,' + ) + matches = [] + for p in files: + with p.open('r') as f: + for idx, line in enumerate(f): + match = exp.search(line) + if match: + m = FoundMatch(file=p, line=idx, type=match.group(1), + name=match.group(2), whole_match=match.group(0)) + if m.type is not None and m.type.startswith('Span'): + # simple span type detection treating the last word inside <> as type + r = re.match(r'Span<(?:.*\s+)(.*)>', m.type) + m.type = r.group(1) + m.size = '[n]' + matches.append(m) + return matches + + +def main(argv): + parser = argparse.ArgumentParser( + description='Automatically updates control_ids_debug.yaml',) + args = parser.parse_args(argv[1:]) + + yaml = ruyaml.YAML() + root_dir = Path(__file__).resolve().parent.parent + ctrl_file = root_dir.joinpath('src/libcamera/control_ids_debug.yaml') + + matches = find_debug_controls(root_dir.joinpath('src')) + + doc = yaml.load(ctrl_file) + + controls = doc['controls'] + + # create a map of names in the existing yaml for easier updating + controls_map = {} + for control in controls: + for k, v in control.items(): + controls_map[k] = v + + obsolete_names = list(controls_map.keys()) + + for m in matches: + if not m.type: + p = m.file.relative_to(Path.cwd(), walk_up=True) + logger.warning( + f'{p}:{m.line + 1}: Failed to deduce type from {m.whole_match} ... skipping') + continue + + p = m.file.relative_to(root_dir) + desc = {'type': m.type, + 'description': f'Debug control {m.name} found in {p}:{m.line}'} + if m.size is not None: + desc['size'] = m.size + + if m.name in controls_map: + # Can't use == for modified check because of the special yaml dicts. + update_needed = False + if list(controls_map[m.name].keys()) != list(desc.keys()): + update_needed = True + else: + for k, v in controls_map[m.name].items(): + if v != desc[k]: + update_needed = True + break + + if update_needed: + logger.info(f"Update control '{m.name}'") + controls_map[m.name].clear() + controls_map[m.name].update(desc) + + obsolete_names.remove(m.name) + else: + logger.info(f"Add control '{m.name}'") + insert_before = len(controls) + for idx, control in enumerate(controls): + if get_control_name(control).lower() > m.name.lower(): + insert_before = idx + break + controls.insert(insert_before, {m.name: desc}) + + # Remove elements from controls without recreating the list (to keep comments etc.) + idx = 0 + while idx < len(controls): + name = get_control_name(controls[idx]) + if name in obsolete_names: + logger.info(f"Remove control '{name}'") + controls.pop(idx) + else: + idx += 1 + + with ctrl_file.open('w') as f: + # ruyaml looses the copyright header + f.write(("# SPDX-License-Identifier: LGPL-2.1-or-later\n" + "#\n" + "# This file is generated by utils/gen-debug-controls.py\n" + "#\n")) + yaml.dump(doc, f) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) From patchwork Mon Oct 7 09:54:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21527 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 C6C31C3264 for ; Mon, 7 Oct 2024 09:54:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 32F636353A; Mon, 7 Oct 2024 11:54:46 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="akvc92Xy"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 77F0A63535 for ; Mon, 7 Oct 2024 11:54:42 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8F03A1111; Mon, 7 Oct 2024 11:53:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294786; bh=FGj48CRnmw837TOdKjFASRFcdEff4M7K5Azl/VJ6KuU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=akvc92XyQWpnl30PdEW1ownc13N3Ih7Ijt6zmlMwtdXPDU9oc/cHCb6MZDKHOwb4H TLP7rMFBEPP9+R0A+bUOiJ1yxj5dDM/8hkHJ58B/A0mgQd+ebkSoCmNIurJE3E2+Fh NOw4mXtS3orL0x63ILuQfKn+9hWYzkgtpYSMRz7A= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Laurent Pinchart , Kieran Bingham Subject: [PATCH v2 4/7] ipa: rkisp1: Add constructor to the ipa context Date: Mon, 7 Oct 2024 11:54:08 +0200 Message-ID: <20241007095425.211158-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Initialization using the initializer list is cumbersome and requires modifications to the list whenever the context is modified. Fix that by adding a proper constructor to the context. Signed-off-by: Stefan Klug Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/ipa/rkisp1/ipa_context.h | 5 +++++ src/ipa/rkisp1/rkisp1.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index e274d9b01e1c..d52e73ad2503 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -180,6 +180,11 @@ struct IPAFrameContext : public FrameContext { }; struct IPAContext { + IPAContext(unsigned int frameContextSize) + : hw(nullptr), frameContexts(frameContextSize) + { + } + const IPAHwSettings *hw; IPACameraSensorInfo sensorInfo; IPASessionConfiguration configuration; diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 9e161cabdea4..a579f21de56f 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -124,7 +124,7 @@ const ControlInfoMap::Map rkisp1Controls{ } /* namespace */ IPARkISP1::IPARkISP1() - : context_({ {}, {}, {}, {}, { kMaxFrameContexts }, {}, {} }) + : context_(kMaxFrameContexts) { } From patchwork Mon Oct 7 09:54:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21528 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 D36EDC32DE for ; Mon, 7 Oct 2024 09:54:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 563D965369; Mon, 7 Oct 2024 11:54:49 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="glVFO+vM"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 54E3F63535 for ; Mon, 7 Oct 2024 11:54:45 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6E25915EE; Mon, 7 Oct 2024 11:53:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294789; bh=RWLslE+nEKrMmRrdopi/a+SQk3O4hbiE3plewPKBxKQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=glVFO+vM9C78cOTAaCRCU0qsD3MkPtFkbslVRo1zxye6Fp/xTBOG2yfC0BuabJrIh RXu6Vj3QGxsM4AQixXRwD8t3uUspoylDyBetInAtM8rqXQ6KM32JJTm+yvXypvVk4U mzSpzc30TfTrUc8pIFMPJwybOCZHNyyfWJA72+Oo= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v2 5/7] ipa: rkisp1: Add debug metadata support to the rkisp1 Date: Mon, 7 Oct 2024 11:54:09 +0200 Message-ID: <20241007095425.211158-6-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a DebugMetadata helper to the context and add the corresponding plumbing. This is all that is needed to support debug metadata in an IPA. Signed-off-by: Stefan Klug Reviewed-by: Laurent Pinchart --- Changes in v2: - Replace DebugMetadata::assignList by DebugMetadata::moveEntries --- src/ipa/rkisp1/ipa_context.h | 5 +++++ src/ipa/rkisp1/rkisp1.cpp | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index d52e73ad2503..7b93a9e9461d 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -17,8 +17,11 @@ #include #include #include + #include +#include "libcamera/internal/debug_controls.h" + #include #include #include @@ -194,6 +197,8 @@ struct IPAContext { ControlInfoMap::Map ctrlMap; + DebugMetadata debugMetadata; + /* Interface to the Camera Helper */ std::unique_ptr camHelper; }; diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index a579f21de56f..b96141aabf0f 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -117,6 +117,7 @@ const IPAHwSettings ipaHwSettingsV12{ const ControlInfoMap::Map rkisp1Controls{ { &controls::AwbEnable, ControlInfo(false, true) }, { &controls::ColourGains, ControlInfo(0.0f, 3.996f, 1.0f) }, + { &controls::DebugMetadataEnable, ControlInfo(false, true, false) }, { &controls::Sharpness, ControlInfo(0.0f, 10.0f, 1.0f) }, { &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) }, }; @@ -326,6 +327,7 @@ void IPARkISP1::unmapBuffers(const std::vector &ids) void IPARkISP1::queueRequest(const uint32_t frame, const ControlList &controls) { IPAFrameContext &frameContext = context_.frameContexts.alloc(frame); + context_.debugMetadata.checkForEnable(controls); for (auto const &a : algorithms()) { Algorithm *algo = static_cast(a.get()); @@ -377,6 +379,7 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId } setControls(frame); + context_.debugMetadata.moveEntries(metadata); metadataReady.emit(frame, metadata); } From patchwork Mon Oct 7 09:54:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21529 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 4481EC32DF for ; Mon, 7 Oct 2024 09:54:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 541C86536A; Mon, 7 Oct 2024 11:54:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WGXzmpdR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 00BAB6353B for ; Mon, 7 Oct 2024 11:54:49 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1F9A41667; Mon, 7 Oct 2024 11:53:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294793; bh=LWH0Fjvo2R3wNXd0L9iqL8mPrb5JPIZ/8rxsFKxYbeA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WGXzmpdR3j1quCFFGWcnJgz9FuY1EZ29GgOrjiR1v+W2KHSgJ62VUfX30+5em+ZO2 g6As9uhf4R9fWlqDngEBgdBtFPY0lAhXifvql0HwJaAcMhp8+Fcb69s3HrPG8dMICH fz6v58zr2NfEb6n3fQi6m5Oy5BYu+FfqxRcL7m2o= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Laurent Pinchart Subject: [PATCH v2 6/7] ipa: libipa: Add data accessor to Histogram Date: Mon, 7 Oct 2024 11:54:10 +0200 Message-ID: <20241007095425.211158-7-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" For debugging purposes it is helpful to access the internal data of the histogram. Add an accessor for that. Signed-off-by: Stefan Klug Reviewed-by: Laurent Pinchart --- Changes in v2: - return Span instead of reference to std::vector --- src/ipa/libipa/histogram.cpp | 6 ++++++ src/ipa/libipa/histogram.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/ipa/libipa/histogram.cpp b/src/ipa/libipa/histogram.cpp index 5fbfadf5e4e1..10e44b54a0cf 100644 --- a/src/ipa/libipa/histogram.cpp +++ b/src/ipa/libipa/histogram.cpp @@ -62,6 +62,12 @@ Histogram::Histogram(Span data) * \return Number of bins */ +/** + * \fn Histogram::data() + * \brief Retrieve the internal data + * \return The data + */ + /** * \fn Histogram::total() * \brief Retrieve the total number of values in the data set diff --git a/src/ipa/libipa/histogram.h b/src/ipa/libipa/histogram.h index 6fd641683694..a926002c8cf0 100644 --- a/src/ipa/libipa/histogram.h +++ b/src/ipa/libipa/histogram.h @@ -36,6 +36,7 @@ public: } size_t bins() const { return cumulative_.size() - 1; } + const Span data() const { return cumulative_; } uint64_t total() const { return cumulative_[cumulative_.size() - 1]; } uint64_t cumulativeFrequency(double bin) const; double quantile(double q, uint32_t first = 0, uint32_t last = UINT_MAX) const; From patchwork Mon Oct 7 09:54:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21530 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 5B53DC32E0 for ; Mon, 7 Oct 2024 09:54:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 704416536B; Mon, 7 Oct 2024 11:54:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Hy+KnJ9w"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3012F6353A for ; Mon, 7 Oct 2024 11:54:52 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:ba12:1296:516b:1122]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4EB8F152D; Mon, 7 Oct 2024 11:53:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728294796; bh=Kmp6hb9ta58J+9nDgsycbnef6xSPpW1OuToVI6pvP8w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hy+KnJ9wM1l+DCGZUys8omX+DxspS7SIUysg4z7hCNe8APlH8tqMx1ywASOcpnrXi cq683lMsiej4cMhp4sPDz1dz1B0KKzjhRmSgh8iu5O7DP7/N7D855DkeOum/ONjyG5 BPrv38vJuc54dbgxOK63zeU5XtjGf6o4ehf8aw/c= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v2 7/7] [DNI] ipa: Add debug controls to the agc algorithm Date: Mon, 7 Oct 2024 11:54:11 +0200 Message-ID: <20241007095425.211158-8-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241007095425.211158-1-stefan.klug@ideasonboard.com> References: <20241007095425.211158-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a few (arbitrary) debug metadata to the agc algorithm. This shows how easy it is to add debug metadata to an ipa even for classes that don't have direct access to the metadata list or the context like AgcMeanLuminance. The control_ids_debug.yaml was autogenerated by calling utils/gen-debug-controls.py Signed-off-by: Stefan Klug --- Update in v2: - Break too long line in agc.cpp --- src/ipa/libipa/agc_mean_luminance.cpp | 8 ++++++++ src/ipa/libipa/agc_mean_luminance.h | 4 ++++ src/ipa/rkisp1/algorithms/agc.cpp | 10 ++++++++++ src/libcamera/control_ids_debug.yaml | 21 ++++++++++++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index f97ef11771c4..bd0f85afcd2e 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -133,6 +133,11 @@ static constexpr double kDefaultRelativeLuminanceTarget = 0.16; * values. */ +/** + * \var AgcMeanLuminance::debugMeta_ + * \brief DebugMetadata helper + */ + AgcMeanLuminance::AgcMeanLuminance() : frameCount_(0), filteredExposure_(0s), relativeLuminanceTarget_(0) { @@ -541,8 +546,11 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, exposureModeHelpers_.at(exposureModeIndex); double gain = estimateInitialGain(); + debugMeta_.set(controls::debug::AgcInitialGain, static_cast(gain)); gain = constraintClampGain(constraintModeIndex, yHist, gain); + debugMeta_.set(controls::debug::AgcNewGain, static_cast(gain)); + /* * We don't check whether we're already close to the target, because * even if the effective exposure value is the same as the last frame's diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 576d28be8eb0..428465a11a36 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -16,6 +16,7 @@ #include +#include "libcamera/internal/debug_controls.h" #include "libcamera/internal/yaml_parser.h" #include "exposure_mode_helper.h" @@ -71,6 +72,9 @@ public: frameCount_ = 0; } +protected: + DebugMetadata debugMeta_; + private: virtual double estimateLuminance(const double gain) const = 0; diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 17d074d9c03e..6668db942042 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -139,6 +139,8 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData) { int ret; + debugMeta_.setParent(&context.debugMetadata); + ret = parseTuningData(tuningData); if (ret) return ret; @@ -444,6 +446,14 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, frameContext.agc.exposureMode, hist, effectiveExposureValue); + debugMeta_.set(controls::debug::AgcAnalogGain, aGain); + debugMeta_.set(controls::debug::AgcDigitalGain, dGain); + + const Span orig = hist.data(); + const Span data{ reinterpret_cast(&orig[0]), + orig.size() }; + debugMeta_.set>(controls::debug::AgcHistogram, data); + LOG(RkISP1Agc, Debug) << "Divided up shutter, analogue gain and digital gain are " << shutterTime << ", " << aGain << " and " << dGain; diff --git a/src/libcamera/control_ids_debug.yaml b/src/libcamera/control_ids_debug.yaml index 797532712099..61ea2d17b553 100644 --- a/src/libcamera/control_ids_debug.yaml +++ b/src/libcamera/control_ids_debug.yaml @@ -1,6 +1,25 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # +# This file is generated by utils/gen-debug-controls.py +# %YAML 1.1 --- vendor: debug -controls: [] +controls: +- AgcAnalogGain: + type: float + description: Debug control AgcAnalogGain found in src/ipa/rkisp1/algorithms/agc.cpp:448 +- AgcDigitalGain: + type: float + description: Debug control AgcDigitalGain found in src/ipa/rkisp1/algorithms/agc.cpp:449 +- AgcHistogram: + type: int64_t + description: Debug control AgcHistogram found in src/ipa/rkisp1/algorithms/agc.cpp:454 + size: '[n]' +- AgcInitialGain: + type: float + description: Debug control AgcInitialGain found in src/ipa/libipa/agc_mean_luminance.cpp:548 +- AgcNewGain: + type: float + description: Debug control AgcNewGain found in src/ipa/libipa/agc_mean_luminance.cpp:551 +