ipa: mali-c55: Add BLC Algorithm
Add a Black Level Correction algorithm. Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Acked-by: Nayden Kanchev <nayden.kanchev@arm.com> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
This commit is contained in:
parent
e8cae247e8
commit
fbea6a4c02
5 changed files with 194 additions and 0 deletions
140
src/ipa/mali-c55/algorithms/blc.cpp
Normal file
140
src/ipa/mali-c55/algorithms/blc.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, Ideas On Board
|
||||||
|
*
|
||||||
|
* Mali-C55 sensor offset (black level) correction
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blc.h"
|
||||||
|
|
||||||
|
#include <libcamera/base/log.h>
|
||||||
|
#include <libcamera/control_ids.h>
|
||||||
|
|
||||||
|
#include "libcamera/internal/yaml_parser.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file blc.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
namespace ipa::mali_c55::algorithms {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class BlackLevelCorrection
|
||||||
|
* \brief MaliC55 Black Level Correction control
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOG_DEFINE_CATEGORY(MaliC55Blc)
|
||||||
|
|
||||||
|
BlackLevelCorrection::BlackLevelCorrection()
|
||||||
|
: tuningParameters_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \copydoc libcamera::ipa::Algorithm::init
|
||||||
|
*/
|
||||||
|
int BlackLevelCorrection::init([[maybe_unused]] IPAContext &context,
|
||||||
|
const YamlObject &tuningData)
|
||||||
|
{
|
||||||
|
offset00 = tuningData["offset00"].get<uint32_t>(0);
|
||||||
|
offset01 = tuningData["offset01"].get<uint32_t>(0);
|
||||||
|
offset10 = tuningData["offset10"].get<uint32_t>(0);
|
||||||
|
offset11 = tuningData["offset11"].get<uint32_t>(0);
|
||||||
|
|
||||||
|
if (offset00 > kMaxOffset || offset01 > kMaxOffset ||
|
||||||
|
offset10 > kMaxOffset || offset11 > kMaxOffset) {
|
||||||
|
LOG(MaliC55Blc, Error) << "Invalid black level offsets";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tuningParameters_ = true;
|
||||||
|
|
||||||
|
LOG(MaliC55Blc, Debug)
|
||||||
|
<< "Black levels: 00 " << offset00 << ", 01 " << offset01
|
||||||
|
<< ", 10 " << offset10 << ", 11 " << offset11;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \copydoc libcamera::ipa::Algorithm::configure
|
||||||
|
*/
|
||||||
|
int BlackLevelCorrection::configure(IPAContext &context,
|
||||||
|
[[maybe_unused]] const IPACameraSensorInfo &configInfo)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If no Black Levels were passed in through tuning data then we could
|
||||||
|
* use the value from the CameraSensorHelper if one is available.
|
||||||
|
*/
|
||||||
|
if (context.configuration.sensor.blackLevel &&
|
||||||
|
!(offset00 + offset01 + offset10 + offset11)) {
|
||||||
|
offset00 = context.configuration.sensor.blackLevel;
|
||||||
|
offset01 = context.configuration.sensor.blackLevel;
|
||||||
|
offset10 = context.configuration.sensor.blackLevel;
|
||||||
|
offset11 = context.configuration.sensor.blackLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \copydoc libcamera::ipa::Algorithm::prepare
|
||||||
|
*/
|
||||||
|
void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context,
|
||||||
|
const uint32_t frame,
|
||||||
|
[[maybe_unused]] IPAFrameContext &frameContext,
|
||||||
|
mali_c55_params_buffer *params)
|
||||||
|
{
|
||||||
|
mali_c55_params_block block;
|
||||||
|
block.data = ¶ms->data[params->total_size];
|
||||||
|
|
||||||
|
if (frame > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!tuningParameters_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
block.header->type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS;
|
||||||
|
block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE;
|
||||||
|
block.header->size = sizeof(mali_c55_params_sensor_off_preshading);
|
||||||
|
|
||||||
|
block.sensor_offs->chan00 = offset00;
|
||||||
|
block.sensor_offs->chan01 = offset01;
|
||||||
|
block.sensor_offs->chan10 = offset10;
|
||||||
|
block.sensor_offs->chan11 = offset11;
|
||||||
|
|
||||||
|
params->total_size += block.header->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlackLevelCorrection::process([[maybe_unused]] IPAContext &context,
|
||||||
|
[[maybe_unused]] const uint32_t frame,
|
||||||
|
[[maybe_unused]] IPAFrameContext &frameContext,
|
||||||
|
[[maybe_unused]] const mali_c55_stats_buffer *stats,
|
||||||
|
ControlList &metadata)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Black Level Offsets in tuning data need to be 20-bit, whereas the
|
||||||
|
* metadata expects values from a 16-bit range. Right-shift to remove
|
||||||
|
* the 4 least significant bits.
|
||||||
|
*
|
||||||
|
* The black levels should be reported in the order R, Gr, Gb, B. We
|
||||||
|
* ignore that here given we're using matching values so far, but it
|
||||||
|
* would be safer to check the sensor's bayer order.
|
||||||
|
*
|
||||||
|
* \todo Account for bayer order.
|
||||||
|
*/
|
||||||
|
metadata.set(controls::SensorBlackLevels, {
|
||||||
|
static_cast<int32_t>(offset00 >> 4),
|
||||||
|
static_cast<int32_t>(offset01 >> 4),
|
||||||
|
static_cast<int32_t>(offset10 >> 4),
|
||||||
|
static_cast<int32_t>(offset11 >> 4),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_IPA_ALGORITHM(BlackLevelCorrection, "BlackLevelCorrection")
|
||||||
|
|
||||||
|
} /* namespace ipa::mali_c55::algorithms */
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
42
src/ipa/mali-c55/algorithms/blc.h
Normal file
42
src/ipa/mali-c55/algorithms/blc.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, Ideas On Board
|
||||||
|
*
|
||||||
|
* Mali-C55 sensor offset (black level) correction
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "algorithm.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
namespace ipa::mali_c55::algorithms {
|
||||||
|
|
||||||
|
class BlackLevelCorrection : public Algorithm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlackLevelCorrection();
|
||||||
|
~BlackLevelCorrection() = default;
|
||||||
|
|
||||||
|
int init(IPAContext &context, const YamlObject &tuningData) override;
|
||||||
|
int configure(IPAContext &context,
|
||||||
|
const IPACameraSensorInfo &configInfo) override;
|
||||||
|
void prepare(IPAContext &context, const uint32_t frame,
|
||||||
|
IPAFrameContext &frameContext,
|
||||||
|
mali_c55_params_buffer *params) override;
|
||||||
|
void process(IPAContext &context, const uint32_t frame,
|
||||||
|
IPAFrameContext &frameContext,
|
||||||
|
const mali_c55_stats_buffer *stats,
|
||||||
|
ControlList &metadata) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr uint32_t kMaxOffset = 0xfffff;
|
||||||
|
|
||||||
|
bool tuningParameters_;
|
||||||
|
uint32_t offset00;
|
||||||
|
uint32_t offset01;
|
||||||
|
uint32_t offset10;
|
||||||
|
uint32_t offset11;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace ipa::mali_c55::algorithms */
|
||||||
|
} /* namespace libcamera */
|
|
@ -2,4 +2,5 @@
|
||||||
|
|
||||||
mali_c55_ipa_algorithms = files([
|
mali_c55_ipa_algorithms = files([
|
||||||
'agc.cpp',
|
'agc.cpp',
|
||||||
|
'blc.cpp',
|
||||||
])
|
])
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct IPASessionConfiguration {
|
||||||
struct {
|
struct {
|
||||||
BayerFormat::Order bayerOrder;
|
BayerFormat::Order bayerOrder;
|
||||||
utils::Duration lineDuration;
|
utils::Duration lineDuration;
|
||||||
|
uint32_t blackLevel;
|
||||||
} sensor;
|
} sensor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,16 @@ void IPAMaliC55::updateSessionConfiguration(const IPACameraSensorInfo &info,
|
||||||
context_.configuration.agc.defaultExposure = defExposure;
|
context_.configuration.agc.defaultExposure = defExposure;
|
||||||
context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain);
|
context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain);
|
||||||
context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain);
|
context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain);
|
||||||
|
|
||||||
|
if (camHelper_->blackLevel().has_value()) {
|
||||||
|
/*
|
||||||
|
* The black level from CameraSensorHelper is a 16-bit value.
|
||||||
|
* The Mali-C55 ISP expects 20-bit settings, so we shift it to
|
||||||
|
* the appropriate width
|
||||||
|
*/
|
||||||
|
context_.configuration.sensor.blackLevel =
|
||||||
|
camHelper_->blackLevel().value() << 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPAMaliC55::updateControls(const IPACameraSensorInfo &sensorInfo,
|
void IPAMaliC55::updateControls(const IPACameraSensorInfo &sensorInfo,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue