ipa: libipa: Introduce V4L2Params
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 <jacopo.mondi@ideasonboard.com> Tested-by: Antoine Bouyer <antoine.bouyer@nxp.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
@@ -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('..')
|
||||
|
||||
253
src/ipa/libipa/v4l2_params.cpp
Normal file
253
src/ipa/libipa/v4l2_params.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/* 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 an 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 allows 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<struct my_isp_awb_config_data> 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<myISPBlocks B>
|
||||
* struct block_type {
|
||||
* };
|
||||
*
|
||||
* template<>
|
||||
* struct block_type<myISPBlock::Agc> {
|
||||
* using type = struct my_isp_kernel_config_type_agc;
|
||||
* static constexpr kernel_enum_type blockType = MY_ISP_TYPE_AGC;
|
||||
* };
|
||||
*
|
||||
* template<>
|
||||
* struct block_type<myISPBlock::Awb> {
|
||||
* 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<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 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<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 */
|
||||
152
src/ipa/libipa/v4l2_params.h
Normal file
152
src/ipa/libipa/v4l2_params.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* 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/log.h>
|
||||
#include <libcamera/base/span.h>
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
namespace ipa {
|
||||
|
||||
LOG_DECLARE_CATEGORY(V4L2Params)
|
||||
|
||||
template<typename T>
|
||||
class V4L2ParamsBlock
|
||||
{
|
||||
public:
|
||||
V4L2ParamsBlock(const Span<uint8_t> data)
|
||||
: data_(data)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~V4L2ParamsBlock() {}
|
||||
|
||||
virtual void setEnabled(bool enabled)
|
||||
{
|
||||
struct v4l2_isp_params_block_header *header =
|
||||
reinterpret_cast<struct v4l2_isp_params_block_header *>(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<const T *>(data_.data());
|
||||
}
|
||||
|
||||
virtual T *operator->()
|
||||
{
|
||||
return reinterpret_cast<T *>(data_.data());
|
||||
}
|
||||
|
||||
virtual const T &operator*() const
|
||||
{
|
||||
return *reinterpret_cast<const T *>(data_.data());
|
||||
}
|
||||
|
||||
virtual T &operator*()
|
||||
{
|
||||
return *reinterpret_cast<T *>(data_.data());
|
||||
}
|
||||
|
||||
protected:
|
||||
Span<uint8_t> data_;
|
||||
};
|
||||
|
||||
template<typename Traits>
|
||||
class V4L2Params
|
||||
{
|
||||
public:
|
||||
V4L2Params(Span<uint8_t> data, unsigned int version)
|
||||
: data_(data)
|
||||
{
|
||||
struct v4l2_isp_params_buffer *params =
|
||||
reinterpret_cast<struct v4l2_isp_params_buffer *>(data_.data());
|
||||
params->data_size = 0;
|
||||
params->version = version;
|
||||
|
||||
used_ = offsetof(struct v4l2_isp_params_buffer, data);
|
||||
}
|
||||
|
||||
size_t bytesused() 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. 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<uint8_t> block = data_.subspan(used_, blockSize);
|
||||
memset(block.data(), 0, block.size());
|
||||
|
||||
struct v4l2_isp_params_block_header *header =
|
||||
reinterpret_cast<struct v4l2_isp_params_block_header *>(block.data());
|
||||
header->type = blockType;
|
||||
header->size = block.size();
|
||||
|
||||
used_ += block.size();
|
||||
|
||||
reinterpret_cast<struct v4l2_isp_params_buffer *>
|
||||
(data_.data())->data_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, \
|
||||
} }
|
||||
|
||||
@@ -79,56 +79,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);
|
||||
@@ -178,44 +128,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 {
|
||||
|
||||
@@ -49,115 +46,143 @@ 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(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<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);
|
||||
static constexpr unsigned int kVersion = RKISP1_EXT_PARAM_BUFFER_V1;
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
const Type &operator*() const &
|
||||
{
|
||||
return *reinterpret_cast<const Type *>(data().data());
|
||||
}
|
||||
|
||||
Type &operator*() &
|
||||
{
|
||||
return *reinterpret_cast<Type *>(data().data());
|
||||
}
|
||||
};
|
||||
|
||||
class RkISP1Params
|
||||
{
|
||||
public:
|
||||
RkISP1Params(uint32_t format, Span<uint8_t> data);
|
||||
|
||||
template<BlockType B>
|
||||
RkISP1ParamsBlock<B> block()
|
||||
{
|
||||
return RkISP1ParamsBlock<B>(this, block(B));
|
||||
return RkISP1ParamsBlock<Type>(this, id, block(id));
|
||||
}
|
||||
|
||||
uint32_t format() const { return format_; }
|
||||
size_t size() const { return used_; }
|
||||
|
||||
private:
|
||||
friend class RkISP1ParamsBlockBase;
|
||||
|
||||
Span<uint8_t> block(BlockType type);
|
||||
void setBlockEnabled(BlockType type, bool enabled);
|
||||
|
||||
private:
|
||||
Span<uint8_t> block(BlockType type);
|
||||
|
||||
uint32_t format_;
|
||||
};
|
||||
|
||||
Span<uint8_t> data_;
|
||||
size_t used_;
|
||||
template<typename T>
|
||||
class RkISP1ParamsBlock final : public V4L2ParamsBlock<T>
|
||||
{
|
||||
public:
|
||||
RkISP1ParamsBlock(RkISP1Params *params, BlockType type,
|
||||
const Span<uint8_t> data)
|
||||
: V4L2ParamsBlock<T>(data)
|
||||
{
|
||||
params_ = params;
|
||||
type_ = type;
|
||||
|
||||
std::map<BlockType, Span<uint8_t>> blocks_;
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
|
||||
void setEnabled(bool enabled) override
|
||||
{
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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<const T *>(cifData_.data());
|
||||
}
|
||||
|
||||
virtual T *operator->() override
|
||||
{
|
||||
return reinterpret_cast<T *>(cifData_.data());
|
||||
}
|
||||
|
||||
virtual const T &operator*() const override
|
||||
{
|
||||
return *reinterpret_cast<const T *>(cifData_.data());
|
||||
}
|
||||
|
||||
virtual T &operator*() override
|
||||
{
|
||||
return *reinterpret_cast<T *>(cifData_.data());
|
||||
}
|
||||
|
||||
private:
|
||||
RkISP1Params *params_;
|
||||
BlockType type_;
|
||||
Span<uint8_t> cifData_;
|
||||
};
|
||||
|
||||
} /* namespace ipa::rkisp1 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user