@@ -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
*/
@@ -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
@@ -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
@@ -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;
@@ -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);
}