ipa: rkisp1: ccm/lsc: Fix CCM/LSC based on manual color temperature

In RkISP1Awb::process(), the color temperature in the active state is
updated every time new statistics are available.  The CCM/LSC algorithms
use that value in prepare() to update the CCM/LSC. This is not correct
if the color temperature was specified manually and leads to visible
flicker even when AwbEnable is set to false.

To fix that, track the auto and manual color temperature separately in
active state. In Awb::prepare() the current frame context is updated
with the corresponding value from active state. Change the algorithms to
fetch the color temperature from the frame context instead of the active
state in prepare().

Fixes: 0230880954 ("ipa: rkisp1: awb: Implement ColourTemperature control")
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Stefan Klug 2025-04-03 17:49:16 +02:00
parent 3fcc6b06c3
commit f1ac420eb1
5 changed files with 21 additions and 16 deletions

View file

@ -130,7 +130,8 @@ int Awb::configure(IPAContext &context,
context.activeState.awb.automatic.gains = context.activeState.awb.automatic.gains =
awbAlgo_->gainsFromColourTemperature(kDefaultColourTemperature); awbAlgo_->gainsFromColourTemperature(kDefaultColourTemperature);
context.activeState.awb.autoEnabled = true; context.activeState.awb.autoEnabled = true;
context.activeState.awb.temperatureK = kDefaultColourTemperature; context.activeState.awb.manual.temperatureK = kDefaultColourTemperature;
context.activeState.awb.automatic.temperatureK = kDefaultColourTemperature;
/* /*
* Define the measurement window for AWB as a centered rectangle * Define the measurement window for AWB as a centered rectangle
@ -187,7 +188,7 @@ void Awb::queueRequest(IPAContext &context,
const auto &gains = awbAlgo_->gainsFromColourTemperature(*colourTemperature); const auto &gains = awbAlgo_->gainsFromColourTemperature(*colourTemperature);
awb.manual.gains.r() = gains.r(); awb.manual.gains.r() = gains.r();
awb.manual.gains.b() = gains.b(); awb.manual.gains.b() = gains.b();
awb.temperatureK = *colourTemperature; awb.manual.temperatureK = *colourTemperature;
update = true; update = true;
} }
@ -196,7 +197,7 @@ void Awb::queueRequest(IPAContext &context,
<< "Set colour gains to " << awb.manual.gains; << "Set colour gains to " << awb.manual.gains;
frameContext.awb.gains = awb.manual.gains; frameContext.awb.gains = awb.manual.gains;
frameContext.awb.temperatureK = awb.temperatureK; frameContext.awb.temperatureK = awb.manual.temperatureK;
} }
/** /**
@ -210,8 +211,9 @@ void Awb::prepare(IPAContext &context, const uint32_t frame,
* most up-to-date automatic values we can read. * most up-to-date automatic values we can read.
*/ */
if (frameContext.awb.autoEnabled) { if (frameContext.awb.autoEnabled) {
frameContext.awb.gains = context.activeState.awb.automatic.gains; const auto &awb = context.activeState.awb;
frameContext.awb.temperatureK = context.activeState.awb.temperatureK; frameContext.awb.gains = awb.automatic.gains;
frameContext.awb.temperatureK = awb.automatic.temperatureK;
} }
auto gainConfig = params->block<BlockType::AwbGain>(); auto gainConfig = params->block<BlockType::AwbGain>();
@ -316,7 +318,7 @@ void Awb::process(IPAContext &context,
RkISP1AwbStats awbStats{ rgbMeans }; RkISP1AwbStats awbStats{ rgbMeans };
AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, frameContext.lux.lux); AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, frameContext.lux.lux);
activeState.awb.temperatureK = awbResult.colourTemperature; activeState.awb.automatic.temperatureK = awbResult.colourTemperature;
/* /*
* Clamp the gain values to the hardware, which expresses gains as Q2.8 * Clamp the gain values to the hardware, which expresses gains as Q2.8
@ -337,7 +339,7 @@ void Awb::process(IPAContext &context,
<< std::showpoint << std::showpoint
<< "Means " << rgbMeans << ", gains " << "Means " << rgbMeans << ", gains "
<< activeState.awb.automatic.gains << ", temp " << activeState.awb.automatic.gains << ", temp "
<< activeState.awb.temperatureK << "K"; << activeState.awb.automatic.temperatureK << "K";
} }
RGB<double> Awb::calculateRgbMeans(const IPAFrameContext &frameContext, const rkisp1_cif_isp_awb_stat *awb) const RGB<double> Awb::calculateRgbMeans(const IPAFrameContext &frameContext, const rkisp1_cif_isp_awb_stat *awb) const

View file

@ -88,7 +88,7 @@ void Ccm::setParameters(struct rkisp1_cif_isp_ctk_config &config,
void Ccm::prepare(IPAContext &context, const uint32_t frame, void Ccm::prepare(IPAContext &context, const uint32_t frame,
IPAFrameContext &frameContext, RkISP1Params *params) IPAFrameContext &frameContext, RkISP1Params *params)
{ {
uint32_t ct = context.activeState.awb.temperatureK; uint32_t ct = frameContext.awb.temperatureK;
/* /*
* \todo The colour temperature will likely be noisy, add filtering to * \todo The colour temperature will likely be noisy, add filtering to

View file

@ -404,12 +404,12 @@ void LensShadingCorrection::copyTable(rkisp1_cif_isp_lsc_config &config,
/** /**
* \copydoc libcamera::ipa::Algorithm::prepare * \copydoc libcamera::ipa::Algorithm::prepare
*/ */
void LensShadingCorrection::prepare(IPAContext &context, void LensShadingCorrection::prepare([[maybe_unused]] IPAContext &context,
[[maybe_unused]] const uint32_t frame, [[maybe_unused]] const uint32_t frame,
[[maybe_unused]] IPAFrameContext &frameContext, IPAFrameContext &frameContext,
RkISP1Params *params) RkISP1Params *params)
{ {
uint32_t ct = context.activeState.awb.temperatureK; uint32_t ct = frameContext.awb.temperatureK;
if (std::abs(static_cast<int>(ct) - static_cast<int>(lastAppliedCt_)) < if (std::abs(static_cast<int>(ct) - static_cast<int>(lastAppliedCt_)) <
kColourTemperatureChangeThreshhold) kColourTemperatureChangeThreshhold)
return; return;

View file

@ -197,15 +197,15 @@ namespace libcamera::ipa::rkisp1 {
* \var IPAActiveState::awb::AwbState.gains * \var IPAActiveState::awb::AwbState.gains
* \brief White balance gains * \brief White balance gains
* *
* \var IPAActiveState::awb::AwbState.temperatureK
* \brief Color temperature
*
* \var IPAActiveState::awb.manual * \var IPAActiveState::awb.manual
* \brief Manual regulation state (set through requests) * \brief Manual regulation state (set through requests)
* *
* \var IPAActiveState::awb.automatic * \var IPAActiveState::awb.automatic
* \brief Automatic regulation state (computed by the algorithm) * \brief Automatic regulation state (computed by the algorithm)
* *
* \var IPAActiveState::awb.temperatureK
* \brief Estimated color temperature
*
* \var IPAActiveState::awb.autoEnabled * \var IPAActiveState::awb.autoEnabled
* \brief Whether the Auto White Balance algorithm is enabled * \brief Whether the Auto White Balance algorithm is enabled
*/ */
@ -349,7 +349,10 @@ namespace libcamera::ipa::rkisp1 {
* \brief White balance gains * \brief White balance gains
* *
* \var IPAFrameContext::awb.temperatureK * \var IPAFrameContext::awb.temperatureK
* \brief Estimated color temperature * \brief Color temperature used for processing this frame
*
* This does not match the color temperature estimated for this frame as the
* measurements were taken on a previous frame.
* *
* \var IPAFrameContext::awb.autoEnabled * \var IPAFrameContext::awb.autoEnabled
* \brief Whether the Auto White Balance algorithm is enabled * \brief Whether the Auto White Balance algorithm is enabled

View file

@ -91,12 +91,12 @@ struct IPAActiveState {
struct { struct {
struct AwbState { struct AwbState {
RGB<double> gains; RGB<double> gains;
unsigned int temperatureK;
}; };
AwbState manual; AwbState manual;
AwbState automatic; AwbState automatic;
unsigned int temperatureK;
bool autoEnabled; bool autoEnabled;
} awb; } awb;