From patchwork Tue Oct 14 10:55:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 24633 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 06790C3331 for ; Tue, 14 Oct 2025 10:55:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B0427605FA; Tue, 14 Oct 2025 12:55:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rLiBppzK"; 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 2FB27605DE for ; Tue, 14 Oct 2025 12:55:53 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 39644F09; Tue, 14 Oct 2025 12:54:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760439253; bh=3oRwtQJD4vEwVmVb78GMsM6rxq7l9LRAJcwS3WSN9TI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rLiBppzKvE/iAuZGvBdVEai4itOjUacDbvTCdUnIp0AXBBE1xullU8Trdcb7VHoj8 oFYdVZ9E4hkRDlTPF5YGrvbSIeVGxpCdfX9aPBfeYAsCGFul2qxl8NcWyh7zryW7NT /rcz5iSrISmgvMBF69Ur+dg626sImc6eVqDyscw8= From: Jacopo Mondi Date: Tue, 14 Oct 2025 12:55:39 +0200 Subject: [PATCH v6 4/5] ipa: libipa: Introduce V4L2Params MIME-Version: 1.0 Message-Id: <20251014-v4l2-params-v6-4-caf5fa69eb29@ideasonboard.com> References: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> In-Reply-To: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Antoine Bouyer X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=26276; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=3oRwtQJD4vEwVmVb78GMsM6rxq7l9LRAJcwS3WSN9TI=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBo7iw1pEUvAreMYegG6d5iE4ChWDccqrL+kp0Sd KcQrLM/4YGJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaO4sNQAKCRByNAaPFqFW PDBiD/wLmYw3LEdN1ZGZ82U6hnNVazgW6HirqTXr2EYwibxDChBgPRQELt3YcSKV30CxUGTWASE +Q0h7KRFT1YVkVplJDEsvTbo2vBItnls5lkDBtlDW6Sk5bD3fGRXAOMpcvHBp1cRHLgtwzPLyDk o0pOcopLC3URDlcagCM9kAr4lVwOgy1Eo+evLzqs7dEA0hWyfn1PMWHp3uF724/9ZweMADAM90F 9w7Y9YMBHVVyMVtdUCUkVPjMxFqQqkIxIM/f8mXPT7lrwO2Zsp8dg5XTlRpwyYi/ucV1KW9vOVJ dl6Vgt8uHJUhvhPQzN8619/qAzxD9E3tIb5iq9w/QLwLGz60XE4c616pITZTf5t+2daY9UVJb+w tyiyzsFMVjQPMhCGejF18+8dosIYxeop2h7JHStNih8+Soq2xDA+i5td4sz5rLSHUYaEeCPUUrf kNsn4mo3LVoUl+4Zcu5NUFuNbXWcvqndgcj6wNtMiBNxUhufchHyuiGs+mgfEnenO16TaNwp3yl boODcenRuacFT/CDbyzHvicgY5zPKayLq2aw4zFNF01xDh2vsbZkOeVuVP4ldJvk6LEtJL+dCWQ LxMUV4ea/TOefenNsjLASJonX2gVgR8hgXeOUqtkcatt/w4FyZyjO+ClkFw1wg/2eFd5teFE/BV /bF1/JF1UZIGoQw== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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" The existing RkISP1Params helper class allows the RkISP1 IPA to handle both the extensible parameters format and the legacy fixed-size format. With the introduction of v4l2-isp.h in the Linux kernel the part of the RkISP1Params helper class that handles extensible parameters can be generalized so that other IPA modules can use the same helpers to populate a parameters buffer compatible with v4l2-isp.h. Generalize the RkISP1Params class to a new libipa component named V4L2Params and derive the existing RkISP1Params from it, leaving in the RkISP1-specific implementation the handling of the legacy format. Deriving RkISP1Params from V4L2Params requires changing the size associated to each block to include the size of v4l2_params_block_header in the ipa:rkisp1::kBlockTypeInfo map as the V4L2Params::block() implementation doesn't account for that as RkIS1Params::block() implementation did. Signed-off-by: Jacopo Mondi Tested-by: Antoine Bouyer --- src/ipa/libipa/meson.build | 2 + src/ipa/libipa/v4l2_params.cpp | 254 +++++++++++++++++++++++++++++++++++++++++ src/ipa/libipa/v4l2_params.h | 152 ++++++++++++++++++++++++ src/ipa/rkisp1/params.cpp | 93 +-------------- src/ipa/rkisp1/params.h | 175 ++++++++++++++++------------ src/ipa/rkisp1/rkisp1.cpp | 2 +- 6 files changed, 512 insertions(+), 166 deletions(-) diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index 660be94054fa98b714b6bc586039081e45a6b4bc..7202df869c2fe4d58586f72f0c3d7c9fb1472d23 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -17,6 +17,7 @@ libipa_headers = files([ 'lux.h', 'module.h', 'pwl.h', + 'v4l2_params.h', ]) libipa_sources = files([ @@ -36,6 +37,7 @@ libipa_sources = files([ 'lux.cpp', 'module.cpp', 'pwl.cpp', + 'v4l2_params.cpp', ]) libipa_includes = include_directories('..') diff --git a/src/ipa/libipa/v4l2_params.cpp b/src/ipa/libipa/v4l2_params.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea0cc85471f1289ecd227d9833ed20d5851d404e --- /dev/null +++ b/src/ipa/libipa/v4l2_params.cpp @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Ideas On Board + * + * V4L2 Parameters + */ + +#include "v4l2_params.h" + +namespace libcamera { + +namespace ipa { + +/** + * \file v4l2_params.cpp + * \brief Helper class to populate an ISP configuration buffer compatible with + * the generic V4L2 ISP format + * + * The Linux kernel defines a generic buffer format for configuring ISP devices. + * The format describes a serialisation method for ISP parameters that allows + * userspace to populate a buffer of configuration data by appending blocks to + * the buffer with common headers but device-specific contents one after the + * other. + * + * The V4L2Params class implements support the V4L2 ISP parameters buffer format + * and allows users to populate the ISP configuration blocks, represented as + * V4L2ParamBlock class instances. + * + * IPA implementations using this helpers should define an enumeration of ISP + * blocks supported by the IPA module and use a set of common abstraction to + * help their derived implementation of V4L2Params translate the enumerated ISP + * block identifier to the actual type of the configuration data as defined by + * the kernel interface. + * + * As an example of this see the RkISP1 and Mali-C55 implementations. + */ + +/** + * \class V4L2ParamsBlock + * \brief Helper class that represents a ISP configuration block + * + * Each ISP function is associated with a set of configuration parameters + * defined by the kernel interface. + * + * This class represents an ISP block configuration entry. It is constructed + * with a reference to the memory area where the block configuration will be + * stored in the parameters buffer. The template parameter represents + * the underlying kernel-defined ISP block configuration type and allow its + * user to easily cast it to said type to populate and read the configuration + * parameters. + * + * \sa V4L2Params::block() + */ + +/** + * \fn V4L2ParamsBlock::V4L2ParamsBlock() + * \brief Construct a V4L2ParamsBlock with memory represented by \a data + * \param[in] data The memory area where the ISP block is located + */ + +/** + * \fn V4L2ParamsBlock::setEnabled() + * \brief Enable/disable an ISP configuration block + * \param[in] enabled The enable flag + */ + +/** + * \fn V4L2ParamsBlock::operator->() + * \brief Access the ISP configuration block casting it to the kernel-defined + * ISP configuration type + * + * The V4L2ParamsBlock is templated with the kernel defined ISP configuration + * block type. This function allows users to easily cast a V4L2ParamsBlock to + * the underlying kernel-defined type in order to easily populate or read + * the ISP configuration data. + * + * \code{.cpp} + * + * // The kernel header defines the ISP configuration types, in example + * // struct my_isp_awb_config_data { + * // u16 gain_ch00; + * // u16 gain_ch01; + * // u16 gain_ch10; + * // u16 gain_ch11; + * // + * // } + * + * template<> V4L2ParamsBlock awbBlock = ... + * + * awbBlock->gain_ch00 = ...; + * awbBlock->gain_ch01 = ...; + * awbBlock->gain_ch10 = ...; + * awbBlock->gain_ch11 = ...; + * + * \endcode + * + * Users of this class shall not create a V4L2ParamsBlock manually but should + * use V4L2Params::block(). + */ + +/** + * \fn V4L2ParamsBlock::operator->() const + * \copydoc V4L2ParamsBlock::operator->() + */ + +/** + * \fn V4L2ParamsBlock::operator*() const + * \copydoc V4L2ParamsBlock::operator->() + */ + +/** + * \fn V4L2ParamsBlock::operator*() + * \copydoc V4L2ParamsBlock::operator->() + */ + +/** + * \var V4L2ParamsBlock::data_ + * \brief Memory area reserved for the ISP configuration block + */ + + /** + * \class V4L2Params + * \brief Helper class that represent an ISP configuration buffer + * + * This class represents an ISP configuration buffer. It is constructed + * with a reference to the memory mapped buffer that will be queued to the ISP + * driver. + * + * This class is templated with the type of the enumeration of ISP blocks that + * each IPA module is expected to support. IPA modules are expected to derive + * this class by providing a 'param_traits' type that helps the class associate + * a block type with the actual memory area that represents the ISP + * configuration block. + * + * \code{.cpp} + * + * // Define the supported ISP blocks + * enum class myISPBlocks { + * Agc, + * Awb, + * ... + * }; + * + * // Maps the C++ enum type to the kernel enum type and concrete parameter type + * template + * struct block_type { + * }; + * + * template<> + * struct block_type { + * using type = struct my_isp_kernel_config_type_agc; + * static constexpr kernel_enum_type blockType = MY_ISP_TYPE_AGC; + * }; + * + * template<> + * struct block_type { + * using type = struct my_isp_kernel_config_type_awb; + * static constexpr kernel_enum_type blockType = MY_ISP_TYPE_AWB; + * }; + * + * + * // Convenience type to associate a block id to the 'block_type' overload + * struct params_traits { + * using id_type = myISPBlocks; + * template using id_to_details = block_type; + * }; + * + * ... + * + * // Derive the V4L2Params class by providing params_traits + * class MyISPParams : public V4L2Params + * { + * public: + * MyISPParams::MyISPParams(Span data) + * : V4L2Params(data, kVersion) + * { + * } + * }; + * + * \endcode + * + * Users of this class can then easily access an ISP configuration block as a + * V4L2ParamsBlock instance. + * + * \code{.cpp} + * + * MyISPParams params(data); + * + * auto awb = params.block(); + * awb->gain00 = ...; + * awb->gain01 = ...; + * awb->gain10 = ...; + * awb->gain11 = ...; + * \endcode + */ + +/** + * \fn V4L2Params::V4L2Params() + * \brief Construct an instance of V4L2Params + * \param[in] data Reference to the v4l2-buffer memory mapped area + * \param[in] version The ISP parameters version the implementation supports + */ + +/** + * \fn V4L2Params::bytesused() + * \brief Retrieve the used size of the parameters buffer (in bytes) + * + * The parameters buffer size is mostly used to populate the v4l2_buffer + * bytesused field before queueing the buffer to the ISP. + * + * \return The number of bytes occupied by the ISP configuration parameters + */ + +/** + * \fn V4L2Params::block() + * \brief Retrieve the location of an ISP configuration block a return it + * \return A V4L2ParamsBlock instance that points to the ISP configuration block + */ + +/** + * \fn V4L2Params::block(typename Traits::id_type type, unsigned int blockType, size_t blockSize) + * \brief Populate an ISP configuration block a returns a reference to its + * memory + * \param[in] type The ISP block identifier enumerated by the IPA module + * \param[in] blockType The kernel-defined ISP block identifier, used to + * populate the block header + * \param[in] blockSize The ISP block size, used to populate the block header + * + * Initialize the block header with \a blockType and \a blockSize and + * returns a reference to the memory used to store an ISP configuration block. + * + * IPA modules that derive the V4L2Params class shall use this function to + * retrieve the memory area that will be used to construct a V4L2ParamsBlock + * before returning it to the caller. + */ + +/** + * \var V4L2Params::data_ + * \brief The ISP parameters buffer memory + */ + +/** + * \var V4L2Params::used_ + * \brief The number of bytes used in the parameters buffer + */ + +/** + * \var V4L2Params::blocks_ + * \brief Cache of ISP configuration blocks + */ + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/v4l2_params.h b/src/ipa/libipa/v4l2_params.h new file mode 100644 index 0000000000000000000000000000000000000000..728305c5b7b859815bee6da62ce35c44dd1ec41a --- /dev/null +++ b/src/ipa/libipa/v4l2_params.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Ideas On Board + * + * V4L2 Parameters + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +namespace libcamera { + +namespace ipa { + +LOG_DECLARE_CATEGORY(V4L2Params) + +template +class V4L2ParamsBlock +{ +public: + V4L2ParamsBlock(const Span data) + : data_(data) + { + } + + virtual ~V4L2ParamsBlock() {} + + virtual void setEnabled(bool enabled) + { + struct v4l2_isp_params_block_header *header = + reinterpret_cast(data_.data()); + + header->flags &= ~(V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | + V4L2_ISP_PARAMS_FL_BLOCK_DISABLE); + header->flags |= enabled ? V4L2_ISP_PARAMS_FL_BLOCK_ENABLE + : V4L2_ISP_PARAMS_FL_BLOCK_DISABLE; + } + + virtual const T *operator->() const + { + return reinterpret_cast(data_.data()); + } + + virtual T *operator->() + { + return reinterpret_cast(data_.data()); + } + + virtual const T &operator*() const + { + return *reinterpret_cast(data_.data()); + } + + virtual T &operator*() + { + return *reinterpret_cast(data_.data()); + } + +protected: + Span data_; +}; + +template +class V4L2Params +{ +public: + V4L2Params(Span data, unsigned int version) + : data_(data) + { + struct v4l2_isp_params_buffer *params = + reinterpret_cast(data_.data()); + params->data_size = 0; + params->version = version; + + used_ = offsetof(struct v4l2_isp_params_buffer, data); + } + + size_t bytesused() const { return used_; } + + template + auto block() + { + using Details = typename Traits::template id_to_details; + + using Type = typename Details::type; + constexpr auto kernelId = Details::blockType; + + auto data = block(Id, kernelId, sizeof(Type)); + return V4L2ParamsBlock(data); + } + +protected: + Span block(typename Traits::id_type type, + unsigned int blockType, size_t blockSize) + { + /* + * Look up the block in the cache first. If an algorithm + * requests the same block type twice, it should get the same + * block. + */ + auto cacheIt = blocks_.find(type); + if (cacheIt != blocks_.end()) + return cacheIt->second; + + /* + * Make sure we don't run out of space. Assert as otherwise + * we get a segfault as soon as someone tries to access the + * empty Span<> returned from here. + */ + if (blockSize > data_.size() - used_) { + LOG(Fatal) << + "Parameters buffer out of space; potential version mismatch between driver and libcamera"; + return {}; + } + + /* Allocate a new block, clear its memory, and initialize its header. */ + Span block = data_.subspan(used_, blockSize); + memset(block.data(), 0, block.size()); + + struct v4l2_isp_params_block_header *header = + reinterpret_cast(block.data()); + header->type = blockType; + header->size = block.size(); + + used_ += block.size(); + + reinterpret_cast + (data_.data())->data_size += block.size(); + + /* Update the cache. */ + blocks_[type] = block; + + return block; + } + + Span data_; + size_t used_; + + std::map> blocks_; +}; + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/params.cpp b/src/ipa/rkisp1/params.cpp index 5edb36c91b87859d02c0a8b41efe977ff048def5..7040207c26557aa278050a1f7232cc6c380505b1 100644 --- a/src/ipa/rkisp1/params.cpp +++ b/src/ipa/rkisp1/params.cpp @@ -35,7 +35,7 @@ struct BlockTypeInfo { #define RKISP1_BLOCK_TYPE_ENTRY(block, id, type, category, bit) \ { BlockType::block, { \ RKISP1_EXT_PARAMS_BLOCK_TYPE_##id, \ - sizeof(struct rkisp1_cif_isp_##type##_config), \ + sizeof(struct rkisp1_ext_params_##type##_config), \ offsetof(struct rkisp1_params_cfg, category.type##_config), \ RKISP1_CIF_ISP_MODULE_##bit, \ } } @@ -49,7 +49,7 @@ struct BlockTypeInfo { #define RKISP1_BLOCK_TYPE_ENTRY_EXT(block, id, type) \ { BlockType::block, { \ RKISP1_EXT_PARAMS_BLOCK_TYPE_##id, \ - sizeof(struct rkisp1_cif_isp_##type##_config), \ + sizeof(struct rkisp1_ext_params_##type##_config), \ 0, 0, \ } } @@ -79,56 +79,6 @@ const std::map kBlockTypeInfo = { } /* namespace */ -RkISP1ParamsBlockBase::RkISP1ParamsBlockBase(RkISP1Params *params, BlockType type, - const Span &data) - : params_(params), type_(type) -{ - if (params_->format() == V4L2_META_FMT_RK_ISP1_EXT_PARAMS) { - header_ = data.subspan(0, sizeof(rkisp1_ext_params_block_header)); - data_ = data.subspan(sizeof(rkisp1_ext_params_block_header)); - } else { - data_ = data; - } -} - -void RkISP1ParamsBlockBase::setEnabled(bool enabled) -{ - /* - * For the legacy fixed format, blocks are enabled in the top-level - * header. Delegate to the RkISP1Params class. - */ - if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS) - return params_->setBlockEnabled(type_, enabled); - - /* - * For the extensible format, set the enable and disable flags in the - * block header directly. - */ - struct rkisp1_ext_params_block_header *header = - reinterpret_cast(header_.data()); - header->flags &= ~(RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE | - RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE); - header->flags |= enabled ? RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE - : RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE; -} - -RkISP1Params::RkISP1Params(uint32_t format, Span data) - : format_(format), data_(data), used_(0) -{ - if (format_ == V4L2_META_FMT_RK_ISP1_EXT_PARAMS) { - struct rkisp1_ext_params_cfg *cfg = - reinterpret_cast(data.data()); - - cfg->version = RKISP1_EXT_PARAM_BUFFER_V1; - cfg->data_size = 0; - - used_ += offsetof(struct rkisp1_ext_params_cfg, data); - } else { - memset(data.data(), 0, data.size()); - used_ = sizeof(struct rkisp1_params_cfg); - } -} - void RkISP1Params::setBlockEnabled(BlockType type, bool enabled) { const BlockTypeInfo &info = kBlockTypeInfo.at(type); @@ -178,44 +128,7 @@ Span RkISP1Params::block(BlockType type) return data_.subspan(info.offset, info.size); } - /* - * For the extensible format, allocate memory for the block, including - * the header. Look up the block in the cache first. If an algorithm - * requests the same block type twice, it should get the same block. - */ - auto cacheIt = blocks_.find(type); - if (cacheIt != blocks_.end()) - return cacheIt->second; - - /* Make sure we don't run out of space. */ - size_t size = sizeof(struct rkisp1_ext_params_block_header) - + ((info.size + 7) & ~7); - if (size > data_.size() - used_) { - LOG(RkISP1Params, Error) - << "Out of memory to allocate block type " - << utils::to_underlying(type); - return {}; - } - - /* Allocate a new block, clear its memory, and initialize its header. */ - Span block = data_.subspan(used_, size); - used_ += size; - - struct rkisp1_ext_params_cfg *cfg = - reinterpret_cast(data_.data()); - cfg->data_size += size; - - memset(block.data(), 0, block.size()); - - struct rkisp1_ext_params_block_header *header = - reinterpret_cast(block.data()); - header->type = info.type; - header->size = block.size(); - - /* Update the cache. */ - blocks_[type] = block; - - return block; + return V4L2Params::block(type, info.type, info.size); } } /* namespace ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/params.h b/src/ipa/rkisp1/params.h index 2e60528d102ec44a31417d4b146e74cace363efa..eddb37d5c000b6b1de1c698ad915f2b42da58b81 100644 --- a/src/ipa/rkisp1/params.h +++ b/src/ipa/rkisp1/params.h @@ -7,13 +7,10 @@ #pragma once -#include -#include - #include +#include -#include -#include +#include namespace libcamera { @@ -49,115 +46,143 @@ template struct block_type { }; -#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct) \ +#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct, id) \ template<> \ struct block_type { \ using type = struct rkisp1_cif_isp_##blockStruct##_config; \ + static constexpr rkisp1_ext_params_block_type blockType = \ + RKISP1_EXT_PARAMS_BLOCK_TYPE_##id; \ }; -RKISP1_DEFINE_BLOCK_TYPE(Bls, bls) -RKISP1_DEFINE_BLOCK_TYPE(Dpcc, dpcc) -RKISP1_DEFINE_BLOCK_TYPE(Sdg, sdg) -RKISP1_DEFINE_BLOCK_TYPE(AwbGain, awb_gain) -RKISP1_DEFINE_BLOCK_TYPE(Flt, flt) -RKISP1_DEFINE_BLOCK_TYPE(Bdm, bdm) -RKISP1_DEFINE_BLOCK_TYPE(Ctk, ctk) -RKISP1_DEFINE_BLOCK_TYPE(Goc, goc) -RKISP1_DEFINE_BLOCK_TYPE(Dpf, dpf) -RKISP1_DEFINE_BLOCK_TYPE(DpfStrength, dpf_strength) -RKISP1_DEFINE_BLOCK_TYPE(Cproc, cproc) -RKISP1_DEFINE_BLOCK_TYPE(Ie, ie) -RKISP1_DEFINE_BLOCK_TYPE(Lsc, lsc) -RKISP1_DEFINE_BLOCK_TYPE(Awb, awb_meas) -RKISP1_DEFINE_BLOCK_TYPE(Hst, hst) -RKISP1_DEFINE_BLOCK_TYPE(Aec, aec) -RKISP1_DEFINE_BLOCK_TYPE(Afc, afc) -RKISP1_DEFINE_BLOCK_TYPE(CompandBls, compand_bls) -RKISP1_DEFINE_BLOCK_TYPE(CompandExpand, compand_curve) -RKISP1_DEFINE_BLOCK_TYPE(CompandCompress, compand_curve) -RKISP1_DEFINE_BLOCK_TYPE(Wdr, wdr) +RKISP1_DEFINE_BLOCK_TYPE(Bls, bls, BLS) +RKISP1_DEFINE_BLOCK_TYPE(Dpcc, dpcc, DPCC) +RKISP1_DEFINE_BLOCK_TYPE(Sdg, sdg, SDG) +RKISP1_DEFINE_BLOCK_TYPE(AwbGain, awb_gain, AWB_GAIN) +RKISP1_DEFINE_BLOCK_TYPE(Flt, flt, FLT) +RKISP1_DEFINE_BLOCK_TYPE(Bdm, bdm, BDM) +RKISP1_DEFINE_BLOCK_TYPE(Ctk, ctk, CTK) +RKISP1_DEFINE_BLOCK_TYPE(Goc, goc, GOC) +RKISP1_DEFINE_BLOCK_TYPE(Dpf, dpf, DPF) +RKISP1_DEFINE_BLOCK_TYPE(DpfStrength, dpf_strength, DPF_STRENGTH) +RKISP1_DEFINE_BLOCK_TYPE(Cproc, cproc, CPROC) +RKISP1_DEFINE_BLOCK_TYPE(Ie, ie, IE) +RKISP1_DEFINE_BLOCK_TYPE(Lsc, lsc, LSC) +RKISP1_DEFINE_BLOCK_TYPE(Awb, awb_meas, AWB_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(Hst, hst, HST_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(Aec, aec, AEC_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(Afc, afc, AFC_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(CompandBls, compand_bls, COMPAND_BLS) +RKISP1_DEFINE_BLOCK_TYPE(CompandExpand, compand_curve, COMPAND_EXPAND) +RKISP1_DEFINE_BLOCK_TYPE(CompandCompress, compand_curve, COMPAND_COMPRESS) +RKISP1_DEFINE_BLOCK_TYPE(Wdr, wdr, WDR) + +struct params_traits { + using id_type = BlockType; + + template + using id_to_details = block_type; +}; } /* namespace details */ -class RkISP1Params; +template +class RkISP1ParamsBlock; -class RkISP1ParamsBlockBase +class RkISP1Params : public V4L2Params { public: - RkISP1ParamsBlockBase(RkISP1Params *params, BlockType type, - const Span &data); + static constexpr unsigned int kVersion = RKISP1_EXT_PARAM_BUFFER_V1; + + RkISP1Params(uint32_t format, Span data) + : V4L2Params(data, kVersion), format_(format) + { + if (format_ == V4L2_META_FMT_RK_ISP1_PARAMS) { + memset(data.data(), 0, data.size()); + used_ = sizeof(struct rkisp1_params_cfg); + } + } + + template + auto block() + { + using Type = typename details::block_type::type; - Span data() const { return data_; } + return RkISP1ParamsBlock(this, id, block(id)); + } - void setEnabled(bool enabled); + uint32_t format() const { return format_; } + void setBlockEnabled(BlockType type, bool enabled); private: - LIBCAMERA_DISABLE_COPY(RkISP1ParamsBlockBase) + Span block(BlockType type); - RkISP1Params *params_; - BlockType type_; - Span header_; - Span data_; + uint32_t format_; }; -template -class RkISP1ParamsBlock : public RkISP1ParamsBlockBase +template +class RkISP1ParamsBlock final : public V4L2ParamsBlock { public: - using Type = typename details::block_type::type; - - RkISP1ParamsBlock(RkISP1Params *params, const Span &data) - : RkISP1ParamsBlockBase(params, B, data) + RkISP1ParamsBlock(RkISP1Params *params, BlockType type, + const Span data) + : V4L2ParamsBlock(data) { + params_ = params; + type_ = type; + + /* + * cifData_ points to the actual configuration data + * (struct rkisp1_cif_isp_*) which is not prefixed by any header, + * for the legacy fixed format. + */ + if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS) + cifData_ = data; + else + cifData_ = data.subspan(sizeof(v4l2_isp_params_block_header)); } - const Type *operator->() const + void setEnabled(bool enabled) override { - return reinterpret_cast(data().data()); + /* + * For the legacy fixed format, blocks are enabled in the + * top-level header. Delegate to the RkISP1Params class. + */ + if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS) + return params_->setBlockEnabled(type_, enabled); + + return V4L2ParamsBlock::setEnabled(enabled); } - Type *operator->() + /* + * Override the dereference operators to return a reference to the + * actual configuration data (struct rkisp1_cif_isp_*) skipping the + * 'v4l2_isp_params_block_header' header. + */ + + virtual const T *operator->() const override { - return reinterpret_cast(data().data()); + return reinterpret_cast(cifData_.data()); } - const Type &operator*() const & + virtual T *operator->() override { - return *reinterpret_cast(data().data()); + return reinterpret_cast(cifData_.data()); } - Type &operator*() & + virtual const T &operator*() const override { - return *reinterpret_cast(data().data()); + return *reinterpret_cast(cifData_.data()); } -}; - -class RkISP1Params -{ -public: - RkISP1Params(uint32_t format, Span data); - template - RkISP1ParamsBlock block() + virtual T &operator*() override { - return RkISP1ParamsBlock(this, block(B)); + return *reinterpret_cast(cifData_.data()); } - uint32_t format() const { return format_; } - size_t size() const { return used_; } - private: - friend class RkISP1ParamsBlockBase; - - Span block(BlockType type); - void setBlockEnabled(BlockType type, bool enabled); - - uint32_t format_; - - Span data_; - size_t used_; - - std::map> blocks_; + RkISP1Params *params_; + BlockType type_; + Span cifData_; }; } /* namespace ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index fa22bfc349043002345d275b11a60ac983e329d7..f5f7377b63d21af11473ccc4ab18ab45294743cb 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -349,7 +349,7 @@ void IPARkISP1::computeParams(const uint32_t frame, const uint32_t bufferId) for (auto const &algo : algorithms()) algo->prepare(context_, frame, frameContext, ¶ms); - paramsComputed.emit(frame, params.size()); + paramsComputed.emit(frame, params.bytesused()); } void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId,