| Message ID | 20260827104108.1432632-6-barnabas.pocze@ideasonboard.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
Hi Barnabás, Quoting Barnabás Pőcze (2026-08-27 12:41:05) > The common `AgcAlgorithm` provides the desired vblank value the given > frame, so adjust `agc::prepareControls()` accordingly, and propagate > the vblank value to the sensors in the pipeline handlers. > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > --- > src/ipa/ipu3/ipu3.cpp | 3 +-- > src/ipa/libipa/agc.cpp | 5 ++--- > src/ipa/libipa/agc.h | 9 +++++---- > src/ipa/mali-c55/mali-c55.cpp | 3 +-- > src/ipa/rkisp1/rkisp1.cpp | 4 +--- > src/ipa/softisp/softisp.cpp | 3 +-- > src/libcamera/pipeline/ipu3/ipu3.cpp | 1 + > src/libcamera/pipeline/mali-c55/mali-c55.cpp | 1 + > src/libcamera/pipeline/simple/simple.cpp | 1 + > 9 files changed, 14 insertions(+), 16 deletions(-) > > diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp > index 031b2e4f4d..f8990e3a4b 100644 > --- a/src/ipa/ipu3/ipu3.cpp > +++ b/src/ipa/ipu3/ipu3.cpp > @@ -551,8 +551,7 @@ void IPAIPU3::setControls(unsigned int frame) > IPAFrameContext &frameContext = context_.frameContexts.get(frame); > > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - frameContext.agc.exposure, frameContext.agc.gain); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > ControlList lensCtrls(lensCtrls_); > lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, > diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp > index 34379c0d61..ce5b2ab6f6 100644 > --- a/src/ipa/libipa/agc.cpp > +++ b/src/ipa/libipa/agc.cpp > @@ -56,11 +56,10 @@ namespace agc { > > /** > * \fn prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > - * uint32_t exposure, double gain) > + * const FrameContext &frameContext) > * \param[out] controls The controls list to populate > * \param[in] sensor The CameraSensorHelper > - * \param[in] exposure The exposure (in lines) > - * \param[in] gain The analogue gain > + * \param[in] frameContext The agc frame context > * > * This function sets \a V4L2_CID_EXPOSURE and \a V4L2_CID_ANALOGUE_GAIN > * in \a controls. The gain is mapped to the gain code if \a sensor is provided, > diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h > index 9f95f23ea8..388693d21d 100644 > --- a/src/ipa/libipa/agc.h > +++ b/src/ipa/libipa/agc.h > @@ -107,13 +107,14 @@ extractControls(const ControlList &controls, const CameraSensorHelper *sensor) > > inline void > prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > - uint32_t exposure, double gain) > + const FrameContext &frameContext) > { > - controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); > + controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(frameContext.exposure)); > controls.set(V4L2_CID_ANALOGUE_GAIN, > static_cast<int32_t>(sensor > - ? sensor->gainCode(gain) > - : static_cast<uint32_t>(gain))); > + ? sensor->gainCode(frameContext.gain) > + : static_cast<uint32_t>(frameContext.gain))); > + controls.set(V4L2_CID_VBLANK, static_cast<int32_t>(frameContext.vblank)); > } I think the extractControls() and prepareControls() functions have reached a size that they could be moved to the cpp. Or is there a specific reason to keep them in the header? > > } /* namespace agc */ > diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp > index 1e7cd1995d..201225128a 100644 > --- a/src/ipa/mali-c55/mali-c55.cpp > +++ b/src/ipa/mali-c55/mali-c55.cpp > @@ -134,8 +134,7 @@ int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig > void IPAMaliC55::setControls(const IPAFrameContext &frameContext) > { > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - frameContext.agc.exposure, frameContext.agc.gain); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > setSensorControls.emit(ctrls); > } > diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp > index 79ab7338c1..cefaf40aee 100644 > --- a/src/ipa/rkisp1/rkisp1.cpp > +++ b/src/ipa/rkisp1/rkisp1.cpp > @@ -367,9 +367,7 @@ void IPARkISP1::setControls(unsigned int frame) > << ", gain " << frameContext.agc.gain << ", vblank " << vblank; What about moving that log message into prepareControls()? I think that is relevant debug information on all platforms. Best regards, Stefan > > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - exposure, frameContext.agc.gain); > - ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > setSensorControls.emit(frame, ctrls); > } > diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp > index 8acfcd1a0b..fbb3f3302f 100644 > --- a/src/ipa/softisp/softisp.cpp > +++ b/src/ipa/softisp/softisp.cpp > @@ -249,8 +249,7 @@ void IPASoftIsp::processStats(const uint32_t frame, > metadataReady.emit(frame, metadata); > > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - frameContext.agc.exposure, frameContext.agc.gain); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > setSensorControls.emit(ctrls); > } > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp > index 0f3e169d3b..4147f9475a 100644 > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp > @@ -1084,6 +1084,7 @@ int PipelineHandlerIPU3::registerCameras() > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > }; > > data->delayedCtrls_ = > diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp > index 599ff88b59..ef156d421b 100644 > --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp > +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp > @@ -1909,6 +1909,7 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera(MediaLink *link) > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > }; > > data->delayedCtrls_ = > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp > index ca98e74790..4928ef50e9 100644 > --- a/src/libcamera/pipeline/simple/simple.cpp > +++ b/src/libcamera/pipeline/simple/simple.cpp > @@ -569,6 +569,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > }; > delayedCtrls_ = std::make_unique<DelayedControls>(sensor_->device(), params); > > -- > 2.55.0 >
Hi Dan On Thu, Aug 27, 2026 at 12:41:05PM +0200, Barnabás Pőcze wrote: > The common `AgcAlgorithm` provides the desired vblank value the given > frame, so adjust `agc::prepareControls()` accordingly, and propagate > the vblank value to the sensors in the pipeline handlers. > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> Do you happen to be able to re-test this one on IPU3 ? > --- > src/ipa/ipu3/ipu3.cpp | 3 +-- > src/ipa/libipa/agc.cpp | 5 ++--- > src/ipa/libipa/agc.h | 9 +++++---- > src/ipa/mali-c55/mali-c55.cpp | 3 +-- > src/ipa/rkisp1/rkisp1.cpp | 4 +--- > src/ipa/softisp/softisp.cpp | 3 +-- > src/libcamera/pipeline/ipu3/ipu3.cpp | 1 + > src/libcamera/pipeline/mali-c55/mali-c55.cpp | 1 + > src/libcamera/pipeline/simple/simple.cpp | 1 + > 9 files changed, 14 insertions(+), 16 deletions(-) > > diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp > index 031b2e4f4d..f8990e3a4b 100644 > --- a/src/ipa/ipu3/ipu3.cpp > +++ b/src/ipa/ipu3/ipu3.cpp > @@ -551,8 +551,7 @@ void IPAIPU3::setControls(unsigned int frame) > IPAFrameContext &frameContext = context_.frameContexts.get(frame); > > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - frameContext.agc.exposure, frameContext.agc.gain); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > ControlList lensCtrls(lensCtrls_); > lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, > diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp > index 34379c0d61..ce5b2ab6f6 100644 > --- a/src/ipa/libipa/agc.cpp > +++ b/src/ipa/libipa/agc.cpp > @@ -56,11 +56,10 @@ namespace agc { > > /** > * \fn prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > - * uint32_t exposure, double gain) > + * const FrameContext &frameContext) > * \param[out] controls The controls list to populate > * \param[in] sensor The CameraSensorHelper > - * \param[in] exposure The exposure (in lines) > - * \param[in] gain The analogue gain > + * \param[in] frameContext The agc frame context > * > * This function sets \a V4L2_CID_EXPOSURE and \a V4L2_CID_ANALOGUE_GAIN > * in \a controls. The gain is mapped to the gain code if \a sensor is provided, > diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h > index 9f95f23ea8..388693d21d 100644 > --- a/src/ipa/libipa/agc.h > +++ b/src/ipa/libipa/agc.h > @@ -107,13 +107,14 @@ extractControls(const ControlList &controls, const CameraSensorHelper *sensor) > > inline void > prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > - uint32_t exposure, double gain) > + const FrameContext &frameContext) > { > - controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); > + controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(frameContext.exposure)); > controls.set(V4L2_CID_ANALOGUE_GAIN, > static_cast<int32_t>(sensor > - ? sensor->gainCode(gain) > - : static_cast<uint32_t>(gain))); > + ? sensor->gainCode(frameContext.gain) > + : static_cast<uint32_t>(frameContext.gain))); > + controls.set(V4L2_CID_VBLANK, static_cast<int32_t>(frameContext.vblank)); > } > > } /* namespace agc */ > diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp > index 1e7cd1995d..201225128a 100644 > --- a/src/ipa/mali-c55/mali-c55.cpp > +++ b/src/ipa/mali-c55/mali-c55.cpp > @@ -134,8 +134,7 @@ int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig > void IPAMaliC55::setControls(const IPAFrameContext &frameContext) > { > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - frameContext.agc.exposure, frameContext.agc.gain); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > setSensorControls.emit(ctrls); > } > diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp > index 79ab7338c1..cefaf40aee 100644 > --- a/src/ipa/rkisp1/rkisp1.cpp > +++ b/src/ipa/rkisp1/rkisp1.cpp > @@ -367,9 +367,7 @@ void IPARkISP1::setControls(unsigned int frame) > << ", gain " << frameContext.agc.gain << ", vblank " << vblank; > > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - exposure, frameContext.agc.gain); > - ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > setSensorControls.emit(frame, ctrls); > } > diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp > index 8acfcd1a0b..fbb3f3302f 100644 > --- a/src/ipa/softisp/softisp.cpp > +++ b/src/ipa/softisp/softisp.cpp > @@ -249,8 +249,7 @@ void IPASoftIsp::processStats(const uint32_t frame, > metadataReady.emit(frame, metadata); > > ControlList ctrls(context_.sensorControls); > - agc::prepareControls(ctrls, context_.camHelper.get(), > - frameContext.agc.exposure, frameContext.agc.gain); > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > setSensorControls.emit(ctrls); > } > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp > index 0f3e169d3b..4147f9475a 100644 > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp > @@ -1084,6 +1084,7 @@ int PipelineHandlerIPU3::registerCameras() > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > }; > > data->delayedCtrls_ = > diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp > index 599ff88b59..ef156d421b 100644 > --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp > +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp > @@ -1909,6 +1909,7 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera(MediaLink *link) > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > }; > > data->delayedCtrls_ = > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp > index ca98e74790..4928ef50e9 100644 > --- a/src/libcamera/pipeline/simple/simple.cpp > +++ b/src/libcamera/pipeline/simple/simple.cpp > @@ -569,6 +569,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > }; > delayedCtrls_ = std::make_unique<DelayedControls>(sensor_->device(), params); > > -- > 2.55.0 >
Hello On 27/08/2026 16:20, Jacopo Mondi wrote: > Hi Dan > > On Thu, Aug 27, 2026 at 12:41:05PM +0200, Barnabás Pőcze wrote: >> The common `AgcAlgorithm` provides the desired vblank value the given >> frame, so adjust `agc::prepareControls()` accordingly, and propagate >> the vblank value to the sensors in the pipeline handlers. >> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > > Do you happen to be able to re-test this one on IPU3 ? This v1 series you mean? Or just this patch or something? I can test anything, but possibly not until Tuesday as I was triggering the problem we saw with my lightbox before and I'm away from home until then so I don't have it (though I do have the IPU3 with me). Thanks Dan > >> --- >> src/ipa/ipu3/ipu3.cpp | 3 +-- >> src/ipa/libipa/agc.cpp | 5 ++--- >> src/ipa/libipa/agc.h | 9 +++++---- >> src/ipa/mali-c55/mali-c55.cpp | 3 +-- >> src/ipa/rkisp1/rkisp1.cpp | 4 +--- >> src/ipa/softisp/softisp.cpp | 3 +-- >> src/libcamera/pipeline/ipu3/ipu3.cpp | 1 + >> src/libcamera/pipeline/mali-c55/mali-c55.cpp | 1 + >> src/libcamera/pipeline/simple/simple.cpp | 1 + >> 9 files changed, 14 insertions(+), 16 deletions(-) >> >> diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp >> index 031b2e4f4d..f8990e3a4b 100644 >> --- a/src/ipa/ipu3/ipu3.cpp >> +++ b/src/ipa/ipu3/ipu3.cpp >> @@ -551,8 +551,7 @@ void IPAIPU3::setControls(unsigned int frame) >> IPAFrameContext &frameContext = context_.frameContexts.get(frame); >> >> ControlList ctrls(context_.sensorControls); >> - agc::prepareControls(ctrls, context_.camHelper.get(), >> - frameContext.agc.exposure, frameContext.agc.gain); >> + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); >> >> ControlList lensCtrls(lensCtrls_); >> lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, >> diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp >> index 34379c0d61..ce5b2ab6f6 100644 >> --- a/src/ipa/libipa/agc.cpp >> +++ b/src/ipa/libipa/agc.cpp >> @@ -56,11 +56,10 @@ namespace agc { >> >> /** >> * \fn prepareControls(ControlList &controls, const CameraSensorHelper *sensor, >> - * uint32_t exposure, double gain) >> + * const FrameContext &frameContext) >> * \param[out] controls The controls list to populate >> * \param[in] sensor The CameraSensorHelper >> - * \param[in] exposure The exposure (in lines) >> - * \param[in] gain The analogue gain >> + * \param[in] frameContext The agc frame context >> * >> * This function sets \a V4L2_CID_EXPOSURE and \a V4L2_CID_ANALOGUE_GAIN >> * in \a controls. The gain is mapped to the gain code if \a sensor is provided, >> diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h >> index 9f95f23ea8..388693d21d 100644 >> --- a/src/ipa/libipa/agc.h >> +++ b/src/ipa/libipa/agc.h >> @@ -107,13 +107,14 @@ extractControls(const ControlList &controls, const CameraSensorHelper *sensor) >> >> inline void >> prepareControls(ControlList &controls, const CameraSensorHelper *sensor, >> - uint32_t exposure, double gain) >> + const FrameContext &frameContext) >> { >> - controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); >> + controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(frameContext.exposure)); >> controls.set(V4L2_CID_ANALOGUE_GAIN, >> static_cast<int32_t>(sensor >> - ? sensor->gainCode(gain) >> - : static_cast<uint32_t>(gain))); >> + ? sensor->gainCode(frameContext.gain) >> + : static_cast<uint32_t>(frameContext.gain))); >> + controls.set(V4L2_CID_VBLANK, static_cast<int32_t>(frameContext.vblank)); >> } >> >> } /* namespace agc */ >> diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp >> index 1e7cd1995d..201225128a 100644 >> --- a/src/ipa/mali-c55/mali-c55.cpp >> +++ b/src/ipa/mali-c55/mali-c55.cpp >> @@ -134,8 +134,7 @@ int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig >> void IPAMaliC55::setControls(const IPAFrameContext &frameContext) >> { >> ControlList ctrls(context_.sensorControls); >> - agc::prepareControls(ctrls, context_.camHelper.get(), >> - frameContext.agc.exposure, frameContext.agc.gain); >> + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); >> >> setSensorControls.emit(ctrls); >> } >> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp >> index 79ab7338c1..cefaf40aee 100644 >> --- a/src/ipa/rkisp1/rkisp1.cpp >> +++ b/src/ipa/rkisp1/rkisp1.cpp >> @@ -367,9 +367,7 @@ void IPARkISP1::setControls(unsigned int frame) >> << ", gain " << frameContext.agc.gain << ", vblank " << vblank; >> >> ControlList ctrls(context_.sensorControls); >> - agc::prepareControls(ctrls, context_.camHelper.get(), >> - exposure, frameContext.agc.gain); >> - ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); >> + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); >> >> setSensorControls.emit(frame, ctrls); >> } >> diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp >> index 8acfcd1a0b..fbb3f3302f 100644 >> --- a/src/ipa/softisp/softisp.cpp >> +++ b/src/ipa/softisp/softisp.cpp >> @@ -249,8 +249,7 @@ void IPASoftIsp::processStats(const uint32_t frame, >> metadataReady.emit(frame, metadata); >> >> ControlList ctrls(context_.sensorControls); >> - agc::prepareControls(ctrls, context_.camHelper.get(), >> - frameContext.agc.exposure, frameContext.agc.gain); >> + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); >> setSensorControls.emit(ctrls); >> } >> >> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp >> index 0f3e169d3b..4147f9475a 100644 >> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp >> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp >> @@ -1084,6 +1084,7 @@ int PipelineHandlerIPU3::registerCameras() >> std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { >> { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, >> { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, >> + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, >> }; >> >> data->delayedCtrls_ = >> diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp >> index 599ff88b59..ef156d421b 100644 >> --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp >> +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp >> @@ -1909,6 +1909,7 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera(MediaLink *link) >> std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { >> { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, >> { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, >> + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, >> }; >> >> data->delayedCtrls_ = >> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp >> index ca98e74790..4928ef50e9 100644 >> --- a/src/libcamera/pipeline/simple/simple.cpp >> +++ b/src/libcamera/pipeline/simple/simple.cpp >> @@ -569,6 +569,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, >> std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { >> { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, >> { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, >> + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, >> }; >> delayedCtrls_ = std::make_unique<DelayedControls>(sensor_->device(), params); >> >> -- >> 2.55.0 >>
HI Dan On Thu, Aug 27, 2026 at 04:22:56PM +0100, Dan Scally wrote: > Hello > > On 27/08/2026 16:20, Jacopo Mondi wrote: > > Hi Dan > > > > On Thu, Aug 27, 2026 at 12:41:05PM +0200, Barnabás Pőcze wrote: > > > The common `AgcAlgorithm` provides the desired vblank value the given > > > frame, so adjust `agc::prepareControls()` accordingly, and propagate > > > the vblank value to the sensors in the pipeline handlers. > > > > > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > > > > Do you happen to be able to re-test this one on IPU3 ? > > This v1 series you mean? Or just this patch or something? I can test Yeah this series. I recall you reported oscillations on a version of the libIPA AGC rework that included these changes, which now have been sent as a separate series > anything, but possibly not until Tuesday as I was triggering the problem we > saw with my lightbox before and I'm away from home until then so I don't > have it (though I do have the IPU3 with me). Don't worry ;) > > Thanks > Dan > > > > > > --- > > > src/ipa/ipu3/ipu3.cpp | 3 +-- > > > src/ipa/libipa/agc.cpp | 5 ++--- > > > src/ipa/libipa/agc.h | 9 +++++---- > > > src/ipa/mali-c55/mali-c55.cpp | 3 +-- > > > src/ipa/rkisp1/rkisp1.cpp | 4 +--- > > > src/ipa/softisp/softisp.cpp | 3 +-- > > > src/libcamera/pipeline/ipu3/ipu3.cpp | 1 + > > > src/libcamera/pipeline/mali-c55/mali-c55.cpp | 1 + > > > src/libcamera/pipeline/simple/simple.cpp | 1 + > > > 9 files changed, 14 insertions(+), 16 deletions(-) > > > > > > diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp > > > index 031b2e4f4d..f8990e3a4b 100644 > > > --- a/src/ipa/ipu3/ipu3.cpp > > > +++ b/src/ipa/ipu3/ipu3.cpp > > > @@ -551,8 +551,7 @@ void IPAIPU3::setControls(unsigned int frame) > > > IPAFrameContext &frameContext = context_.frameContexts.get(frame); > > > > > > ControlList ctrls(context_.sensorControls); > > > - agc::prepareControls(ctrls, context_.camHelper.get(), > > > - frameContext.agc.exposure, frameContext.agc.gain); > > > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > > > > > ControlList lensCtrls(lensCtrls_); > > > lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, > > > diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp > > > index 34379c0d61..ce5b2ab6f6 100644 > > > --- a/src/ipa/libipa/agc.cpp > > > +++ b/src/ipa/libipa/agc.cpp > > > @@ -56,11 +56,10 @@ namespace agc { > > > > > > /** > > > * \fn prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > > > - * uint32_t exposure, double gain) > > > + * const FrameContext &frameContext) > > > * \param[out] controls The controls list to populate > > > * \param[in] sensor The CameraSensorHelper > > > - * \param[in] exposure The exposure (in lines) > > > - * \param[in] gain The analogue gain > > > + * \param[in] frameContext The agc frame context > > > * > > > * This function sets \a V4L2_CID_EXPOSURE and \a V4L2_CID_ANALOGUE_GAIN > > > * in \a controls. The gain is mapped to the gain code if \a sensor is provided, > > > diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h > > > index 9f95f23ea8..388693d21d 100644 > > > --- a/src/ipa/libipa/agc.h > > > +++ b/src/ipa/libipa/agc.h > > > @@ -107,13 +107,14 @@ extractControls(const ControlList &controls, const CameraSensorHelper *sensor) > > > > > > inline void > > > prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > > > - uint32_t exposure, double gain) > > > + const FrameContext &frameContext) > > > { > > > - controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); > > > + controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(frameContext.exposure)); > > > controls.set(V4L2_CID_ANALOGUE_GAIN, > > > static_cast<int32_t>(sensor > > > - ? sensor->gainCode(gain) > > > - : static_cast<uint32_t>(gain))); > > > + ? sensor->gainCode(frameContext.gain) > > > + : static_cast<uint32_t>(frameContext.gain))); > > > + controls.set(V4L2_CID_VBLANK, static_cast<int32_t>(frameContext.vblank)); > > > } > > > > > > } /* namespace agc */ > > > diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp > > > index 1e7cd1995d..201225128a 100644 > > > --- a/src/ipa/mali-c55/mali-c55.cpp > > > +++ b/src/ipa/mali-c55/mali-c55.cpp > > > @@ -134,8 +134,7 @@ int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig > > > void IPAMaliC55::setControls(const IPAFrameContext &frameContext) > > > { > > > ControlList ctrls(context_.sensorControls); > > > - agc::prepareControls(ctrls, context_.camHelper.get(), > > > - frameContext.agc.exposure, frameContext.agc.gain); > > > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > > > > > setSensorControls.emit(ctrls); > > > } > > > diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp > > > index 79ab7338c1..cefaf40aee 100644 > > > --- a/src/ipa/rkisp1/rkisp1.cpp > > > +++ b/src/ipa/rkisp1/rkisp1.cpp > > > @@ -367,9 +367,7 @@ void IPARkISP1::setControls(unsigned int frame) > > > << ", gain " << frameContext.agc.gain << ", vblank " << vblank; > > > > > > ControlList ctrls(context_.sensorControls); > > > - agc::prepareControls(ctrls, context_.camHelper.get(), > > > - exposure, frameContext.agc.gain); > > > - ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); > > > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > > > > > setSensorControls.emit(frame, ctrls); > > > } > > > diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp > > > index 8acfcd1a0b..fbb3f3302f 100644 > > > --- a/src/ipa/softisp/softisp.cpp > > > +++ b/src/ipa/softisp/softisp.cpp > > > @@ -249,8 +249,7 @@ void IPASoftIsp::processStats(const uint32_t frame, > > > metadataReady.emit(frame, metadata); > > > > > > ControlList ctrls(context_.sensorControls); > > > - agc::prepareControls(ctrls, context_.camHelper.get(), > > > - frameContext.agc.exposure, frameContext.agc.gain); > > > + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); > > > setSensorControls.emit(ctrls); > > > } > > > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp > > > index 0f3e169d3b..4147f9475a 100644 > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp > > > @@ -1084,6 +1084,7 @@ int PipelineHandlerIPU3::registerCameras() > > > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > > > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > > > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > > > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > > > }; > > > > > > data->delayedCtrls_ = > > > diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp > > > index 599ff88b59..ef156d421b 100644 > > > --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp > > > +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp > > > @@ -1909,6 +1909,7 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera(MediaLink *link) > > > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > > > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > > > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > > > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > > > }; > > > > > > data->delayedCtrls_ = > > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp > > > index ca98e74790..4928ef50e9 100644 > > > --- a/src/libcamera/pipeline/simple/simple.cpp > > > +++ b/src/libcamera/pipeline/simple/simple.cpp > > > @@ -569,6 +569,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, > > > std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { > > > { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, > > > { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, > > > + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, > > > }; > > > delayedCtrls_ = std::make_unique<DelayedControls>(sensor_->device(), params); > > > > > > -- > > > 2.55.0 > > > >
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 031b2e4f4d..f8990e3a4b 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -551,8 +551,7 @@ void IPAIPU3::setControls(unsigned int frame) IPAFrameContext &frameContext = context_.frameContexts.get(frame); ControlList ctrls(context_.sensorControls); - agc::prepareControls(ctrls, context_.camHelper.get(), - frameContext.agc.exposure, frameContext.agc.gain); + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); ControlList lensCtrls(lensCtrls_); lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp index 34379c0d61..ce5b2ab6f6 100644 --- a/src/ipa/libipa/agc.cpp +++ b/src/ipa/libipa/agc.cpp @@ -56,11 +56,10 @@ namespace agc { /** * \fn prepareControls(ControlList &controls, const CameraSensorHelper *sensor, - * uint32_t exposure, double gain) + * const FrameContext &frameContext) * \param[out] controls The controls list to populate * \param[in] sensor The CameraSensorHelper - * \param[in] exposure The exposure (in lines) - * \param[in] gain The analogue gain + * \param[in] frameContext The agc frame context * * This function sets \a V4L2_CID_EXPOSURE and \a V4L2_CID_ANALOGUE_GAIN * in \a controls. The gain is mapped to the gain code if \a sensor is provided, diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h index 9f95f23ea8..388693d21d 100644 --- a/src/ipa/libipa/agc.h +++ b/src/ipa/libipa/agc.h @@ -107,13 +107,14 @@ extractControls(const ControlList &controls, const CameraSensorHelper *sensor) inline void prepareControls(ControlList &controls, const CameraSensorHelper *sensor, - uint32_t exposure, double gain) + const FrameContext &frameContext) { - controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); + controls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(frameContext.exposure)); controls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(sensor - ? sensor->gainCode(gain) - : static_cast<uint32_t>(gain))); + ? sensor->gainCode(frameContext.gain) + : static_cast<uint32_t>(frameContext.gain))); + controls.set(V4L2_CID_VBLANK, static_cast<int32_t>(frameContext.vblank)); } } /* namespace agc */ diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp index 1e7cd1995d..201225128a 100644 --- a/src/ipa/mali-c55/mali-c55.cpp +++ b/src/ipa/mali-c55/mali-c55.cpp @@ -134,8 +134,7 @@ int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig void IPAMaliC55::setControls(const IPAFrameContext &frameContext) { ControlList ctrls(context_.sensorControls); - agc::prepareControls(ctrls, context_.camHelper.get(), - frameContext.agc.exposure, frameContext.agc.gain); + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); setSensorControls.emit(ctrls); } diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 79ab7338c1..cefaf40aee 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -367,9 +367,7 @@ void IPARkISP1::setControls(unsigned int frame) << ", gain " << frameContext.agc.gain << ", vblank " << vblank; ControlList ctrls(context_.sensorControls); - agc::prepareControls(ctrls, context_.camHelper.get(), - exposure, frameContext.agc.gain); - ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); setSensorControls.emit(frame, ctrls); } diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp index 8acfcd1a0b..fbb3f3302f 100644 --- a/src/ipa/softisp/softisp.cpp +++ b/src/ipa/softisp/softisp.cpp @@ -249,8 +249,7 @@ void IPASoftIsp::processStats(const uint32_t frame, metadataReady.emit(frame, metadata); ControlList ctrls(context_.sensorControls); - agc::prepareControls(ctrls, context_.camHelper.get(), - frameContext.agc.exposure, frameContext.agc.gain); + agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc); setSensorControls.emit(ctrls); } diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 0f3e169d3b..4147f9475a 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1084,6 +1084,7 @@ int PipelineHandlerIPU3::registerCameras() std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, }; data->delayedCtrls_ = diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp index 599ff88b59..ef156d421b 100644 --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp @@ -1909,6 +1909,7 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera(MediaLink *link) std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, }; data->delayedCtrls_ = diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index ca98e74790..4928ef50e9 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -569,6 +569,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, std::unordered_map<uint32_t, DelayedControls::ControlParams> params = { { V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } }, { V4L2_CID_EXPOSURE, { delays.exposureDelay, false } }, + { V4L2_CID_VBLANK, { delays.vblankDelay, true } }, }; delayedCtrls_ = std::make_unique<DelayedControls>(sensor_->device(), params);
The common `AgcAlgorithm` provides the desired vblank value the given frame, so adjust `agc::prepareControls()` accordingly, and propagate the vblank value to the sensors in the pipeline handlers. Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> --- src/ipa/ipu3/ipu3.cpp | 3 +-- src/ipa/libipa/agc.cpp | 5 ++--- src/ipa/libipa/agc.h | 9 +++++---- src/ipa/mali-c55/mali-c55.cpp | 3 +-- src/ipa/rkisp1/rkisp1.cpp | 4 +--- src/ipa/softisp/softisp.cpp | 3 +-- src/libcamera/pipeline/ipu3/ipu3.cpp | 1 + src/libcamera/pipeline/mali-c55/mali-c55.cpp | 1 + src/libcamera/pipeline/simple/simple.cpp | 1 + 9 files changed, 14 insertions(+), 16 deletions(-)