libcamera: software_isp: Add valid flag to struct SwIspStats

Generating statistics for every single frame is not really necessary.

However a roundtrip through ipa_->processStats() still need to be done
every frame, even if there are no stats to make the IPA generate metadata
for every frame.

Add a valid flag to the statistics struct to let the IPA know when there
are no statistics for the frame being processed and modify the IPA to
only generate metadata for frames without valid statistics.

This is a preparation patch for skipping statistics generation for some
frames.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Hans de Goede
2025-10-01 16:45:17 +01:00
committed by Kieran Bingham
parent b5c89375f9
commit 9b441cf198
6 changed files with 40 additions and 1 deletions
@@ -20,6 +20,11 @@ namespace libcamera {
* wrap around.
*/
struct SwIspStats {
/**
* \brief True if the statistics buffer contains valid data, false if
* no statistics were generated for this frame
*/
bool valid;
/**
* \brief Holds the sum of all sampled red pixels
*/
+23 -1
View File
@@ -91,13 +91,16 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou
again = std::clamp(again, context.configuration.agc.againMin,
context.configuration.agc.againMax);
context.activeState.agc.exposure = exposure;
context.activeState.agc.again = again;
LOG(IPASoftExposure, Debug)
<< "exposureMSV " << exposureMSV
<< " exp " << exposure << " again " << again;
}
void Agc::process(IPAContext &context,
[[maybe_unused]] const uint32_t frame,
const uint32_t frame,
IPAFrameContext &frameContext,
const SwIspStats *stats,
ControlList &metadata)
@@ -107,6 +110,25 @@ void Agc::process(IPAContext &context,
metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
if (frame == 0) {
/*
* Init active-state from sensor values in case updateExposure()
* does not run for the first frame.
*/
context.activeState.agc.exposure = frameContext.sensor.exposure;
context.activeState.agc.again = frameContext.sensor.gain;
}
if (!stats->valid) {
/*
* Use the new exposure and gain values calculated the last time
* there were valid stats.
*/
frameContext.sensor.exposure = context.activeState.agc.exposure;
frameContext.sensor.gain = context.activeState.agc.again;
return;
}
/*
* Calculate Mean Sample Value (MSV) according to formula from:
* https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
+3
View File
@@ -61,6 +61,9 @@ void Awb::process(IPAContext &context,
};
metadata.set(controls::ColourGains, mdGains);
if (!stats->valid)
return;
/*
* Black level must be subtracted to get the correct AWB ratios, they
* would be off if they were computed from the whole brightness range
+3
View File
@@ -60,6 +60,9 @@ void BlackLevel::process(IPAContext &context,
};
metadata.set(controls::SensorBlackLevels, blackLevels);
if (!stats->valid)
return;
if (context.configuration.black.level.has_value())
return;
+5
View File
@@ -37,6 +37,11 @@ struct IPASessionConfiguration {
};
struct IPAActiveState {
struct {
int32_t exposure;
double again;
} agc;
struct {
uint8_t level;
int32_t lastExposure;
@@ -318,6 +318,7 @@ void SwStatsCpu::startFrame(void)
*/
void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId)
{
stats_.valid = true;
*sharedStats_ = stats_;
statsReady.emit(frame, bufferId);
}