@@ -16,6 +16,7 @@ libipa_headers = files([
'lsc_polynomial.h',
'lux.h',
'module.h',
+ 'v4l2_params.h',
'pwl.h',
])
@@ -35,6 +36,7 @@ libipa_sources = files([
'lsc_polynomial.cpp',
'lux.cpp',
'module.cpp',
+ 'v4l2_params.cpp',
'pwl.cpp',
])
new file mode 100644
@@ -0,0 +1,269 @@
+/* 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 extensible format
+ *
+ * The Linux kernel defines a generic buffer format for configuring ISP devices
+ * through a set of parameters in the form of V4L2 extensible parameters. The
+ * V4L2 extensible parameters define a serialization format for ISP parameters
+ * that allows userspace to populate a buffer of configuration data by appending
+ * them one after the other in a binary buffer.
+ *
+ * Each ISP driver compatible with the v4l2-isp format will define its own
+ * meta-output format identifier and defines the types of the configuration data
+ * of each ISP block that usually match the registers layout.
+ *
+ * The V4L2Params class represent the V4L2 extensible parameters buffer and
+ * allows users to populate the ISP configuration blocks, represented by the
+ * V4L2ParamBlock class instances.
+ *
+ * IPA implementations using this helpers should define an enumeration of ISP
+ * blocks the IPA module supports 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 A view on 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::header()
+ * \brief Retrieve a reference to the header (struct v4l2_params_block_header)
+ * \return The block header
+ */
+
+/**
+ * \fn V4L2ParamsBlock::data()
+ * \brief Retrieve a reference to block configuration data memory area
+ * \return The block data
+ */
+
+/**
+ * \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<struct my_isp_awb_config_data> awbBlock
+ *
+ * awbBlock->gain_ch00 = ...;
+ * awbBlock->gain_ch01 = ...;
+ * awbBlock->gain_ch10 = ...;
+ * awbBlock->gain_ch11 = ...;
+ *
+ * \endcode
+ *
+ * Users of this class are not expected to create a V4L2ParamsBlock manually but
+ * should rather use V4L2Params::block() to retrieve a reference to the memory
+ * area used to construct a V4L2ParamsBlock<T> in their overloaded
+ * implementation of V4L2Params::block().
+ */
+
+/**
+ * \fn V4L2ParamsBlock::operator->() const
+ * \copydoc V4L2ParamsBlock::operator->()
+ */
+
+/**
+ * \fn V4L2ParamsBlock::operator*() const
+ * \copydoc V4L2ParamsBlock::operator->()
+ */
+
+/**
+ * \fn V4L2ParamsBlock::operator*()
+ * \copydoc V4L2ParamsBlock::operator->()
+ */
+
+ /**
+ * \class V4L2Params
+ * \brief Helper class that represent an ISP configuration buffer
+ *
+ * ISP implementation compatible with v4l2-isp define their ISP configuration
+ * buffer types compatible with the struct v4l2_params_buffer type.
+ *
+ * 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.
+ *
+ * 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 the 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,
+ * ...
+ * };
+ *
+ * // Associated to the ISP blocks the kernel types
+ * template<myISPBlocks B>
+ * struct block_type {
+ * };
+ *
+ * template<>
+ * struct block_type<myISPBlock::Agc> {
+ * using type = struct my_isp_kernel_config_type_agc;
+ * static constextpr struct my_isp_kernel_block_type MY_ISP_TYPE_AGC;
+ * };
+ *
+ * template<>
+ * struct block_type<myISPBlock::Awb> {
+ * using type = struct my_isp_kernel_config_type_awb;
+ * static constextpr struct my_isp_kernel_block_type MY_ISP_TYPE_AWB;
+ * };
+ *
+ *
+ * // Convenience type to associated a block id to the 'block_type' overload
+ * struct params_traits {
+ * using id_type = myISPBlocks;
+ * template<id_type Id> using id_to_details = block_type<Id>;
+ * };
+ *
+ * ...
+ *
+ * // Derive the V4L2Params class by providing params_traits
+ * class MyISPParams : public V4L2Params<params_traits>
+ * {
+ * public:
+ * MyISPParams::MyISPParams(Span<uint8_t> 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<myISPBlocks::AWB>();
+ * awb->gain00 = ...;
+ * awb->gain01 = ...;
+ * awb->gain10 = ...;
+ * awb->gain11 = ...;
+ * \endcode
+ */
+
+/**
+ * \fn V4L2Params::V4L2Params()
+ * \brief Construct a V4L2Params
+ * \param[in] data Reference to the v4l2-buffer memory mapped area
+ * \param[in] version The ISP parameters version the implementation supports
+ */
+
+/**
+ * \fn V4L2Params::size()
+ * \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 returns 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<T>
+ * 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 */
new file mode 100644
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * V4L2 Parameters
+ */
+
+#pragma once
+
+#include <map>
+#include <stdint.h>
+#include <string.h>
+
+#include <linux/media/v4l2-isp.h>
+
+#include <libcamera/base/span.h>
+
+namespace libcamera {
+
+namespace ipa {
+
+template<typename T>
+class V4L2ParamsBlock
+{
+public:
+ V4L2ParamsBlock(const Span<uint8_t> data)
+ : header_(data.subspan(0, sizeof(v4l2_params_block_header))),
+ data_(data.subspan(sizeof(v4l2_params_block_header)))
+ {
+ }
+
+ void setEnabled(bool enabled)
+ {
+ struct v4l2_params_block_header *header =
+ reinterpret_cast<struct v4l2_params_block_header *>(header_.data());
+
+ header->flags &= ~(V4L2_PARAMS_FL_BLOCK_ENABLE |
+ V4L2_PARAMS_FL_BLOCK_DISABLE);
+ header->flags |= enabled ? V4L2_PARAMS_FL_BLOCK_ENABLE
+ : V4L2_PARAMS_FL_BLOCK_DISABLE;
+ }
+
+ Span<uint8_t> header() const { return header_; }
+ Span<uint8_t> data() const { return data_; }
+
+ const T *operator->() const
+ {
+ return reinterpret_cast<const T *>(data().data());
+ }
+
+ T *operator->()
+ {
+ return reinterpret_cast<T *>(data().data());
+ }
+
+ const T &operator*() const
+ {
+ return *reinterpret_cast<const T *>(data().data());
+ }
+
+ T &operator*()
+ {
+ return *reinterpret_cast<T *>(data().data());
+ }
+
+private:
+ Span<uint8_t> header_;
+ Span<uint8_t> data_;
+};
+
+template<typename Traits>
+class V4L2Params
+{
+public:
+ V4L2Params(Span<uint8_t> data, unsigned int version)
+ : data_(data)
+ {
+ struct v4l2_params_buffer *cfg =
+ reinterpret_cast<struct v4l2_params_buffer *>(data_.data());
+ cfg->data_size = 0;
+ cfg->version = version;
+ used_ = offsetof(struct v4l2_params_buffer, data);
+ }
+
+ size_t size() const { return used_; }
+
+ template<typename Traits::id_type Id>
+ auto block()
+ {
+ using Details = typename Traits::template id_to_details<Id>;
+
+ using Type = typename Details::type;
+ constexpr auto kernelId = Details::blockType;
+
+ auto data = block(Id, kernelId, sizeof(Type));
+ return V4L2ParamsBlock<Type>(data);
+ }
+
+protected:
+ Span<uint8_t> 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. */
+ if (blockSize > data_.size() - used_)
+ return {};
+
+ /* Allocate a new block, clear its memory, and initialize its header. */
+ Span<uint8_t> block = data_.subspan(used_, blockSize);
+ used_ += blockSize;
+
+ struct v4l2_params_buffer *cfg =
+ reinterpret_cast<struct v4l2_params_buffer *>(data_.data());
+ cfg->data_size += blockSize;
+
+ memset(block.data(), 0, block.size());
+
+ struct v4l2_params_block_header *header =
+ reinterpret_cast<struct v4l2_params_block_header *>(block.data());
+ header->type = blockType;
+ header->size = block.size();
+
+ /* Update the cache. */
+ blocks_[type] = block;
+
+ return block;
+ }
+
+ Span<uint8_t> data_;
+ size_t used_;
+
+ std::map<typename Traits::id_type, Span<uint8_t>> blocks_;
+};
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
@@ -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, \
} }
@@ -78,56 +78,6 @@ const std::map<BlockType, BlockTypeInfo> kBlockTypeInfo = {
} /* namespace */
-RkISP1ParamsBlockBase::RkISP1ParamsBlockBase(RkISP1Params *params, BlockType type,
- const Span<uint8_t> &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<struct rkisp1_ext_params_block_header *>(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<uint8_t> data)
- : format_(format), data_(data), used_(0)
-{
- if (format_ == V4L2_META_FMT_RK_ISP1_EXT_PARAMS) {
- struct rkisp1_ext_params_cfg *cfg =
- reinterpret_cast<struct rkisp1_ext_params_cfg *>(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);
@@ -177,44 +127,7 @@ Span<uint8_t> 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<uint8_t> block = data_.subspan(used_, size);
- used_ += size;
-
- struct rkisp1_ext_params_cfg *cfg =
- reinterpret_cast<struct rkisp1_ext_params_cfg *>(data_.data());
- cfg->data_size += size;
-
- memset(block.data(), 0, block.size());
-
- struct rkisp1_ext_params_block_header *header =
- reinterpret_cast<struct rkisp1_ext_params_block_header *>(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 */
@@ -7,13 +7,10 @@
#pragma once
-#include <map>
-#include <stdint.h>
-
#include <linux/rkisp1-config.h>
+#include <linux/videodev2.h>
-#include <libcamera/base/class.h>
-#include <libcamera/base/span.h>
+#include <libipa/v4l2_params.h>
namespace libcamera {
@@ -48,114 +45,110 @@ template<BlockType B>
struct block_type {
};
-#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct) \
+#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct, id) \
template<> \
struct block_type<BlockType::blockType> { \
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(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)
+
+struct params_traits {
+ using id_type = BlockType;
+
+ template<id_type Id>
+ using id_to_details = block_type<Id>;
+};
} /* namespace details */
-class RkISP1Params;
+template<typename T>
+class RkISP1ParamsBlock;
-class RkISP1ParamsBlockBase
+class RkISP1Params : public V4L2Params<details::params_traits>
{
public:
- RkISP1ParamsBlockBase(RkISP1Params *params, BlockType type,
- const Span<uint8_t> &data);
-
- Span<uint8_t> data() const { return data_; }
-
- void setEnabled(bool enabled);
-
-private:
- LIBCAMERA_DISABLE_COPY(RkISP1ParamsBlockBase)
-
- RkISP1Params *params_;
- BlockType type_;
- Span<uint8_t> header_;
- Span<uint8_t> data_;
-};
+ static constexpr unsigned int kVersion = RKISP1_EXT_PARAM_BUFFER_V1;
-template<BlockType B>
-class RkISP1ParamsBlock : public RkISP1ParamsBlockBase
-{
-public:
- using Type = typename details::block_type<B>::type;
-
- RkISP1ParamsBlock(RkISP1Params *params, const Span<uint8_t> &data)
- : RkISP1ParamsBlockBase(params, B, data)
+ RkISP1Params(uint32_t format, Span<uint8_t> 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);
+ }
}
- const Type *operator->() const
+ template<details::params_traits::id_type id>
+ auto block()
{
- return reinterpret_cast<const Type *>(data().data());
- }
+ using Type = typename details::block_type<id>::type;
- Type *operator->()
- {
- return reinterpret_cast<Type *>(data().data());
+ return RkISP1ParamsBlock<Type>(this, id, block(id));
}
- const Type &operator*() const &
- {
- return *reinterpret_cast<const Type *>(data().data());
- }
+ uint32_t format() const { return format_; }
+ void setBlockEnabled(BlockType type, bool enabled);
- Type &operator*() &
- {
- return *reinterpret_cast<Type *>(data().data());
- }
+private:
+ Span<uint8_t> block(BlockType type);
+
+ uint32_t format_;
};
-class RkISP1Params
+template<typename T>
+class RkISP1ParamsBlock : public V4L2ParamsBlock<T>
{
public:
- RkISP1Params(uint32_t format, Span<uint8_t> data);
-
- template<BlockType B>
- RkISP1ParamsBlock<B> block()
+ RkISP1ParamsBlock(RkISP1Params *params, BlockType type,
+ const Span<uint8_t> &data)
+ : V4L2ParamsBlock<T>(data)
{
- return RkISP1ParamsBlock<B>(this, block(B));
+ params_ = params;
+ type_ = type;
+
+ /* Legacy param format has no header */
+ if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS)
+ data_ = data;
}
- uint32_t format() const { return format_; }
- size_t size() const { return used_; }
+ void 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);
+
+ return V4L2ParamsBlock<T>::setEnabled(enabled);
+ }
private:
- friend class RkISP1ParamsBlockBase;
-
- Span<uint8_t> block(BlockType type);
- void setBlockEnabled(BlockType type, bool enabled);
-
- uint32_t format_;
-
+ RkISP1Params *params_;
+ BlockType type_;
Span<uint8_t> data_;
- size_t used_;
-
- std::map<BlockType, Span<uint8_t>> blocks_;
};
} /* namespace ipa::rkisp1 */