[{"id":36595,"web_url":"https://patchwork.libcamera.org/comment/36595/","msgid":"<176201923633.3925733.16751757069202284321@ping.linuxembedded.co.uk>","date":"2025-11-01T17:47:16","subject":"Re: [PATCH v1 04/17] ipa: rkisp1: algorithms: Add YAML parsing\n\thelper utilities","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Rui,\n\nQuoting Rui Wang (2025-10-28 21:17:37)\n> Introduce yaml_helper.h with standardized functions for parsing YAML\n> configuration data in RkISP1 IPA algorithms. Provides type-safe parsing\n> for optional values, lists, enums, and specialized filter coefficients.\n\nI think this should be either part of the core Yaml helpers or there's\nsomething missing about how we can interact with reading yaml types.\n\nWe shouldn't add all of this generic type handling inside the rkisp\nalgorithm code. If the existing yaml interfaces aren't providing the\ntype handling required, then this support needs to go there (along with\ntests).\n\n\n> Key functions:\n> - opt8/16/32/bool: Type-safe optional value parsing with defaults\n> - optList8/16: List parsing with size validation\n> - optEnum: String-to-enum mapping with validation\n> - optFilterCoeffs: Specialized filter coefficient parsing\n> \n> Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>\n> ---\n>  src/ipa/rkisp1/algorithms/yaml_helper.h | 123 ++++++++++++++++++++++++\n>  1 file changed, 123 insertions(+)\n>  create mode 100644 src/ipa/rkisp1/algorithms/yaml_helper.h\n> \n> diff --git a/src/ipa/rkisp1/algorithms/yaml_helper.h b/src/ipa/rkisp1/algorithms/yaml_helper.h\n> new file mode 100644\n> index 00000000..ed2ba926\n> --- /dev/null\n> +++ b/src/ipa/rkisp1/algorithms/yaml_helper.h\n> @@ -0,0 +1,123 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2025, Ideas On Board\n> + *\n> + * RkISP1 YAML parsing helper functions\n> + */\n> +\n> +#pragma once\n> +\n> +#include <map>\n> +#include <optional>\n> +#include <vector>\n> +\n> +#include \"libcamera/internal/yaml_parser.h\"\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::rkisp1::algorithms {\n> +\n> +namespace yamlHelper {\n> +\n> +inline void opt32(const YamlObject &level, const char *key, std::optional<uint32_t> &dst)\n> +{\n> +       dst = level[key].get<uint32_t>();\n> +}\n> +\n> +inline void opt16(const YamlObject &level, const char *key, std::optional<uint16_t> &dst)\n> +{\n> +       dst = level[key].get<uint16_t>();\n> +}\n> +\n> +inline void opt8(const YamlObject &level, const char *key, std::optional<uint8_t> &dst)\n> +{\n> +       dst = level[key].get<uint8_t>();\n> +}\n> +\n> +inline void optbool(const YamlObject &level, const char *key, std::optional<bool> &dst)\n> +{\n> +       dst = level[key].get<bool>();\n> +}\n> +\n> +inline void optbool(const YamlObject &level, const char *key, bool &dst, bool defaultVal)\n> +{\n> +       std::optional<bool> val = level[key].get<bool>();\n> +       dst = val.value_or(defaultVal);\n> +}\n> +\n> +inline void opt8(const YamlObject &level, const char *key, uint8_t &dst, uint8_t defaultVal)\n> +{\n> +       std::optional<uint8_t> val = level[key].get<uint8_t>();\n> +       dst = val.value_or(defaultVal);\n> +}\n> +\n> +inline void opt16(const YamlObject &level, const char *key, uint16_t &dst, uint16_t defaultVal)\n> +{\n> +       std::optional<uint16_t> val = level[key].get<uint16_t>();\n> +       dst = val.value_or(defaultVal);\n> +}\n> +\n> +inline void opt32(const YamlObject &level, const char *key, uint32_t &dst, uint32_t defaultVal)\n> +{\n> +       std::optional<uint32_t> val = level[key].get<uint32_t>();\n> +       dst = val.value_or(defaultVal);\n> +}\n> +\n> +inline bool optList8(const YamlObject &level, const char *key, std::vector<uint8_t> &dst, size_t expectedSize)\n> +{\n> +       std::optional<std::vector<uint8_t>> val = level[key].getList<uint8_t>();\n> +       if (!val || val->size() != expectedSize)\n> +               return false;\n> +       dst = *val;\n> +       return true;\n> +}\n> +\n> +inline bool optList16(const YamlObject &level, const char *key, std::vector<uint16_t> &dst, size_t expectedSize)\n> +{\n> +       std::optional<std::vector<uint16_t>> val = level[key].getList<uint16_t>();\n> +       if (!val || val->size() != expectedSize)\n> +               return false;\n> +       dst = *val;\n> +       return true;\n> +}\n> +\n> +template<typename EnumType>\n> +inline bool optEnum(const YamlObject &level, const char *key, EnumType &dst, EnumType defaultVal,\n> +                   const std::map<std::string, EnumType> &enumMap)\n> +{\n> +       std::optional<std::string> val = level[key].get<std::string>();\n> +       if (!val) {\n> +               dst = defaultVal;\n> +               return true;\n> +       }\n> +       auto it = enumMap.find(*val);\n> +       if (it == enumMap.end())\n> +               return false;\n> +       dst = it->second;\n> +       return true;\n> +}\n> +\n> +inline bool optFilterCoeffs(const YamlObject &level, const char *key, uint8_t *coeffs, uint32_t &filterSize, size_t maxCoeffs)\n> +{\n> +       std::optional<std::vector<uint8_t>> val = level[key].getList<uint8_t>();\n> +       if (!val)\n> +               return false;\n> +\n> +       size_t size = val->size();\n> +       if (size == maxCoeffs - 1) {\n> +               filterSize = 0; // 9x9 filter\n> +       } else if (size == maxCoeffs) {\n> +               filterSize = 1; // 13x9 filter\n> +       } else {\n> +               return false; // Invalid size\n> +       }\n> +\n> +       std::copy_n(val->begin(), size, coeffs);\n> +       return true;\n> +}\n> +\n> +} /* namespace yamlHelper */\n> +\n> +} /* namespace ipa::rkisp1::algorithms */\n> +\n> +} /* namespace libcamera */\n> -- \n> 2.43.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 450B6C3241\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat,  1 Nov 2025 17:47:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 55E1A60A7B;\n\tSat,  1 Nov 2025 18:47:20 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5A1AE606D5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  1 Nov 2025 18:47:19 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BC1AC524;\n\tSat,  1 Nov 2025 18:45:27 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"oaCoaggl\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1762019127;\n\tbh=SxqSWcyz3LIcgol+yXZWELKScZ4sKapFw561EWdoctY=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=oaCoagglipLze+6oVcv2xqrRLgyNPcholuh/RUpJE8T8NNPr6Aqcku6RIxSX6lGPa\n\t91CrNHNM7DNcjK/MPwaH0adW5d40TnN+NqUAy7pa+DDMh9uNb0+8MKJUKJ1G9CQkL7\n\tw9IoNOtgvc9fs4oE5uu8zcHsJDOlK9yXMh0QKIPI=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20251028211751.2761420-4-rui.wang@ideasonboard.com>","References":"<20251028211751.2761420-1-rui.wang@ideasonboard.com>\n\t<20251028211751.2761420-4-rui.wang@ideasonboard.com>","Subject":"Re: [PATCH v1 04/17] ipa: rkisp1: algorithms: Add YAML parsing\n\thelper utilities","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Rui Wang <rui.wang@ideasonboard.com>","To":"Rui Wang <rui.wang@ideasonboard.com>, libcamera-devel@lists.libcamera.org","Date":"Sat, 01 Nov 2025 17:47:16 +0000","Message-ID":"<176201923633.3925733.16751757069202284321@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]