diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h index ae11f112..3c986018 100644 --- a/include/libcamera/internal/software_isp/swisp_stats.h +++ b/include/libcamera/internal/software_isp/swisp_stats.h @@ -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 */ diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp index 3471cc88..e0447cbd 100644 --- a/src/ipa/simple/algorithms/agc.cpp +++ b/src/ipa/simple/algorithms/agc.cpp @@ -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()); 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 diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index cf567e89..ddd0b791 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -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 diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp index 8c1e9ed0..616da0ee 100644 --- a/src/ipa/simple/algorithms/blc.cpp +++ b/src/ipa/simple/algorithms/blc.cpp @@ -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; diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 468fccab..c3081e30 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -37,6 +37,11 @@ struct IPASessionConfiguration { }; struct IPAActiveState { + struct { + int32_t exposure; + double again; + } agc; + struct { uint8_t level; int32_t lastExposure; diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 4b77b360..eb416dfd 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -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); }