ipa: simple: awb: Keep the gains across a reconfiguration Awb::configure() resets the colour gains to 1.0, so every reconfiguration throws away the white balance the previous one had converged on and the first frames of the new configuration are rendered with the sensor's raw white balance. An application that reconfigures the camera and captures immediately therefore gets a tinted image, which is what taking a still picture with GNOME Snapshot does on the Surface Pro 12in: its preview is correctly balanced, and the picture it writes is heavily green, because the still is captured at a different resolution than the preview and the frame it keeps is the first one after the reconfiguration. Captured through PipeWire, the front camera needs two frames to converge: frame R/G B/G 0 0.709 0.805 1 0.516 0.734 2 1.045 0.920 44 1.044 0.905 The gains describe the scene in front of the sensor, not the stream configuration, so keep them and only initialise them once. --- a/src/ipa/simple/algorithms/awb.h +++ b/src/ipa/simple/algorithms/awb.h @@ -29,6 +29,9 @@ IPAFrameContext &frameContext, const SwIspStats *stats, ControlList &metadata) override; + +private: + bool initialised_ = false; }; } /* namespace ipa::soft::algorithms */ --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -26,8 +26,24 @@ int Awb::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { + /* + * Initialise the gains on the first configuration only. + * + * A camera can be reconfigured while it keeps looking at the same + * scene, which is what an application does when it captures a still + * picture at a different resolution than the one its preview runs at. + * Discarding the gains that the previous configuration converged on + * then paints the first frames of the new one with the sensor's raw + * white balance, and an application that captures straight away gets a + * tinted picture. The gains are a property of the scene rather than of + * the stream configuration, so carry them over. + */ + if (initialised_) + return 0; + auto &gains = context.activeState.awb.gains; gains = { { 1.0, 1.0, 1.0 } }; + initialised_ = true; return 0; }