| Message ID | 20260803131435.153927-21-barnabas.pocze@ideasonboard.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Hi Barnabás On Mon, Aug 03, 2026 at 03:14:05PM +0200, Barnabás Pőcze wrote: > Move the extraction and preparation of `V4L2_CID_{EXPOSURE,ANALOGUE_GAIN}` > into separate functions. This also implements support for not having a > a camera sensor helper. not a fan, but I won't bother you > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > --- > src/ipa/ipu3/ipu3.cpp | 14 +++++----- > src/ipa/libipa/agc.h | 49 ++++++++++++++++++++++++++++++++++ > src/ipa/libipa/meson.build | 1 + > src/ipa/mali-c55/mali-c55.cpp | 17 +++++------- > src/ipa/rkisp1/rkisp1.cpp | 11 +++----- > src/ipa/simple/soft_simple.cpp | 15 +++-------- > 6 files changed, 72 insertions(+), 35 deletions(-) > create mode 100644 src/ipa/libipa/agc.h > > diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp > index 4bdc4b7677..51379808cd 100644 > --- a/src/ipa/ipu3/ipu3.cpp > +++ b/src/ipa/ipu3/ipu3.cpp > @@ -36,6 +36,7 @@ > #include "libcamera/internal/mapped_framebuffer.h" > #include "libcamera/internal/yaml_parser.h" > > +#include "libipa/agc.h" > #include "libipa/camera_sensor_helper.h" > > #include "ipa_context.h" > @@ -596,8 +597,8 @@ void IPAIPU3::processStats(const uint32_t frame, > > IPAFrameContext &frameContext = context_.frameContexts.get(frame); > > - frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); > - frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); > + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) > + = agc::extractControls(sensorControls, camHelper_.get()); > > ControlList metadata(controls::controls); > > @@ -642,12 +643,11 @@ void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls) > */ > void IPAIPU3::setControls(unsigned int frame) > { > - int32_t exposure = context_.activeState.agc.exposure; > - int32_t gain = camHelper_->gainCode(context_.activeState.agc.gain); > - > ControlList ctrls(sensorCtrls_); > - ctrls.set(V4L2_CID_EXPOSURE, exposure); > - ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain); > + agc::prepareControls( > + ctrls, camHelper_.get(), > + context_.activeState.agc.exposure, context_.activeState.agc.gain > + ); Looks a bit weird with the ); on a different line, for a function call. Why not simply agc::prepareControls(ctrls, camHelper_.get(), context_.activeState.agc.exposure, context_.activeState.agc.gain); > > ControlList lensCtrls(lensCtrls_); > lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, > diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h > new file mode 100644 > index 0000000000..5247425952 > --- /dev/null > +++ b/src/ipa/libipa/agc.h > @@ -0,0 +1,49 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2026 Ideas on Board Oy > + * > + * AGC-related functionality > + */ > + > +#pragma once > + > +#include <utility> > + > +#include <linux/v4l2-controls.h> > + > +#include <libcamera/controls.h> > + > +#include "camera_sensor_helper.h" > + > +namespace libcamera { > + > +namespace ipa { > + > +namespace agc { > + > +[[nodiscard]] > +inline std::pair<uint32_t, double> https://en.cppreference.com/cpp/language/inline suggests me that inline (as a hint to the compiler) might not be necessary. Unless this is for the "multiple definitions are permitted" rule. > +extractControls(const ControlList &controls, const CameraSensorHelper *sensor) > +{ > + auto exposure = controls.get(V4L2_CID_EXPOSURE).get<int32_t>(); > + auto gainCode = controls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); > + > + return { > + uint32_t(exposure), I think we generally try to avoid plain old C-style casts and prefer static_cast<> ? > + sensor ? sensor->gain(gainCode) : gainCode, > + }; > +} > + > +inline void > +prepareControls(ControlList &controls, const CameraSensorHelper *sensor, > + int32_t exposure, double gain) > +{ > + controls.set(V4L2_CID_EXPOSURE, exposure); > + controls.set(V4L2_CID_ANALOGUE_GAIN, int32_t(sensor ? sensor->gainCode(gain) : gain)); > +} > + > +} /* namespace agc */ > + > +} /* namespace ipa */ > + > +} /* namespace libcamera */ > diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build > index 963c5ee730..05f1a8749c 100644 > --- a/src/ipa/libipa/meson.build > +++ b/src/ipa/libipa/meson.build > @@ -1,6 +1,7 @@ > # SPDX-License-Identifier: CC0-1.0 > > libipa_headers = files([ > + 'agc.h', > 'agc_mean_luminance.h', > 'algorithm.h', > 'awb_bayes.h', > diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp > index 1d3af0627f..65e5297766 100644 > --- a/src/ipa/mali-c55/mali-c55.cpp > +++ b/src/ipa/mali-c55/mali-c55.cpp > @@ -27,6 +27,7 @@ > #include "libcamera/internal/yaml_parser.h" > > #include "algorithms/algorithm.h" > +#include "libipa/agc.h" > #include "libipa/camera_sensor_helper.h" > > #include "ipa_context.h" > @@ -141,20 +142,18 @@ void IPAMaliC55::setControls() > { > IPAActiveState &activeState = context_.activeState; > uint32_t exposure; > - uint32_t gain; > + double gain; > > if (activeState.agc.autoEnabled) { > exposure = activeState.agc.automatic.exposure; > - gain = camHelper_->gainCode(activeState.agc.automatic.sensorGain); > + gain = activeState.agc.automatic.sensorGain; > } else { > exposure = activeState.agc.manual.exposure; > - gain = camHelper_->gainCode(activeState.agc.manual.sensorGain); > + gain = activeState.agc.manual.sensorGain; > } > > ControlList ctrls(sensorControls_); > - ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); > - ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain)); > - > + agc::prepareControls(ctrls, camHelper_.get(), exposure, gain); > setSensorControls.emit(ctrls); > } > > @@ -352,10 +351,8 @@ void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId, > stats = reinterpret_cast<mali_c55_stats_buffer *>( > buffers_.at(bufferId).planes()[0].data()); > > - frameContext.agc.exposure = > - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); > - frameContext.agc.sensorGain = > - camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); > + std::tie(frameContext.agc.exposure, frameContext.agc.sensorGain) > + = agc::extractControls(sensorControls, camHelper_.get()); > > ControlList metadata(controls::controls); > > diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp > index 38f55b1d86..acb878d814 100644 > --- a/src/ipa/rkisp1/rkisp1.cpp > +++ b/src/ipa/rkisp1/rkisp1.cpp > @@ -31,6 +31,7 @@ > #include "libcamera/internal/yaml_parser.h" > > #include "algorithms/algorithm.h" > +#include "libipa/agc.h" > > #include "ipa_context.h" > #include "params.h" > @@ -328,10 +329,8 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, > stats = reinterpret_cast<rkisp1_stat_buffer *>( > mappedBuffers_.at(bufferId).planes()[0].data()); > > - frameContext.sensor.exposure = > - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); > - frameContext.sensor.gain = > - context_.camHelper->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); > + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) > + = agc::extractControls(sensorControls, context_.camHelper.get()); > > ControlList metadata(controls::controls); > > @@ -365,7 +364,6 @@ void IPARkISP1::setControls(unsigned int frame) > > IPAFrameContext &frameContext = context_.frameContexts.get(frame); > uint32_t exposure = frameContext.agc.exposure; > - uint32_t gain = context_.camHelper->gainCode(frameContext.agc.gain); > uint32_t vblank = frameContext.agc.vblank; > > LOG(IPARkISP1, Debug) > @@ -373,8 +371,7 @@ void IPARkISP1::setControls(unsigned int frame) > << ", gain " << frameContext.agc.gain << ", vblank " << vblank; > > ControlList ctrls(context_.sensorControls); > - ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); > - ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain)); > + agc::prepareControls(ctrls, context_.camHelper.get(), exposure, frameContext.agc.gain); > ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); > > setSensorControls.emit(frame, ctrls); > diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp > index 3932daaa1f..a38fcff7d8 100644 > --- a/src/ipa/simple/soft_simple.cpp > +++ b/src/ipa/simple/soft_simple.cpp > @@ -27,6 +27,7 @@ > #include "libcamera/internal/yaml_parser.h" > > #include "algorithms/adjust.h" > +#include "libipa/agc.h" > #include "libipa/camera_sensor_helper.h" > > #include "module.h" > @@ -301,10 +302,8 @@ void IPASoftSimple::processStats(const uint32_t frame, > { > IPAFrameContext &frameContext = context_.frameContexts.get(frame); > > - frameContext.sensor.exposure = > - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); > - int32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); > - frameContext.sensor.gain = camHelper_ ? camHelper_->gain(again) : again; > + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) > + = agc::extractControls(sensorControls, camHelper_.get()); > > ControlList metadata(controls::controls); > for (const auto &algo : algorithms()) > @@ -312,13 +311,7 @@ void IPASoftSimple::processStats(const uint32_t frame, > metadataReady.emit(frame, metadata); > > ControlList ctrls(sensorInfoMap_); > - > - int32_t againNew = camHelper_ > - ? camHelper_->gainCode(frameContext.agc.gain) > - : static_cast<int32_t>(frameContext.agc.gain); > - ctrls.set(V4L2_CID_EXPOSURE, frameContext.agc.exposure); > - ctrls.set(V4L2_CID_ANALOGUE_GAIN, againNew); > - > + agc::prepareControls(ctrls, camHelper_.get(), frameContext.agc.exposure, frameContext.agc.gain); You can eaisly break this line > setSensorControls.emit(ctrls); > } > > -- > 2.55.0 >
2026. 08. 05. 16:09 keltezéssel, Jacopo Mondi írta: > Hi Barnabás > > On Mon, Aug 03, 2026 at 03:14:05PM +0200, Barnabás Pőcze wrote: >> Move the extraction and preparation of `V4L2_CID_{EXPOSURE,ANALOGUE_GAIN}` >> into separate functions. This also implements support for not having a >> a camera sensor helper. > > not a fan, but I won't bother you I don't know. I still feel like this is easier to get the types right and all. If there were `Control<>` definitions for v4l2 controls as well, I would probably have a different opinion. > >> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> >> --- >> src/ipa/ipu3/ipu3.cpp | 14 +++++----- >> src/ipa/libipa/agc.h | 49 ++++++++++++++++++++++++++++++++++ >> src/ipa/libipa/meson.build | 1 + >> src/ipa/mali-c55/mali-c55.cpp | 17 +++++------- >> src/ipa/rkisp1/rkisp1.cpp | 11 +++----- >> src/ipa/simple/soft_simple.cpp | 15 +++-------- >> 6 files changed, 72 insertions(+), 35 deletions(-) >> create mode 100644 src/ipa/libipa/agc.h >> >> diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp >> index 4bdc4b7677..51379808cd 100644 >> --- a/src/ipa/ipu3/ipu3.cpp >> +++ b/src/ipa/ipu3/ipu3.cpp >> @@ -36,6 +36,7 @@ >> #include "libcamera/internal/mapped_framebuffer.h" >> #include "libcamera/internal/yaml_parser.h" >> >> +#include "libipa/agc.h" >> #include "libipa/camera_sensor_helper.h" >> >> #include "ipa_context.h" >> @@ -596,8 +597,8 @@ void IPAIPU3::processStats(const uint32_t frame, >> >> IPAFrameContext &frameContext = context_.frameContexts.get(frame); >> >> - frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); >> - frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); >> + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) >> + = agc::extractControls(sensorControls, camHelper_.get()); >> >> ControlList metadata(controls::controls); >> >> @@ -642,12 +643,11 @@ void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls) >> */ >> void IPAIPU3::setControls(unsigned int frame) >> { >> - int32_t exposure = context_.activeState.agc.exposure; >> - int32_t gain = camHelper_->gainCode(context_.activeState.agc.gain); >> - >> ControlList ctrls(sensorCtrls_); >> - ctrls.set(V4L2_CID_EXPOSURE, exposure); >> - ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain); >> + agc::prepareControls( >> + ctrls, camHelper_.get(), >> + context_.activeState.agc.exposure, context_.activeState.agc.gain >> + ); > > Looks a bit weird with the ); on a different line, for a function > call. > > Why not simply > > agc::prepareControls(ctrls, camHelper_.get(), > context_.activeState.agc.exposure, > context_.activeState.agc.gain); > > Done. >> >> ControlList lensCtrls(lensCtrls_); >> lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, >> diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h >> new file mode 100644 >> index 0000000000..5247425952 >> --- /dev/null >> +++ b/src/ipa/libipa/agc.h >> @@ -0,0 +1,49 @@ >> +/* SPDX-License-Identifier: LGPL-2.1-or-later */ >> +/* >> + * Copyright (C) 2026 Ideas on Board Oy >> + * >> + * AGC-related functionality >> + */ >> + >> +#pragma once >> + >> +#include <utility> >> + >> +#include <linux/v4l2-controls.h> >> + >> +#include <libcamera/controls.h> >> + >> +#include "camera_sensor_helper.h" >> + >> +namespace libcamera { >> + >> +namespace ipa { >> + >> +namespace agc { >> + >> +[[nodiscard]] >> +inline std::pair<uint32_t, double> > > https://en.cppreference.com/cpp/language/inline > suggests me that inline (as a hint to the compiler) might not be > necessary. Unless this is for the "multiple definitions are > permitted" rule. It is indeed for the latter. > >> +extractControls(const ControlList &controls, const CameraSensorHelper *sensor) >> +{ >> + auto exposure = controls.get(V4L2_CID_EXPOSURE).get<int32_t>(); >> + auto gainCode = controls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); >> + >> + return { >> + uint32_t(exposure), > > I think we generally try to avoid plain old C-style casts and prefer > static_cast<> ? Done > >> + sensor ? sensor->gain(gainCode) : gainCode, >> + }; >> +} >> + >> +inline void >> +prepareControls(ControlList &controls, const CameraSensorHelper *sensor, >> + int32_t exposure, double gain) >> +{ >> + controls.set(V4L2_CID_EXPOSURE, exposure); >> + controls.set(V4L2_CID_ANALOGUE_GAIN, int32_t(sensor ? sensor->gainCode(gain) : gain)); >> +} >> + >> +} /* namespace agc */ >> + >> +} /* namespace ipa */ >> + >> +} /* namespace libcamera */ >> diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build >> index 963c5ee730..05f1a8749c 100644 >> --- a/src/ipa/libipa/meson.build >> +++ b/src/ipa/libipa/meson.build >> @@ -1,6 +1,7 @@ >> # SPDX-License-Identifier: CC0-1.0 >> >> libipa_headers = files([ >> + 'agc.h', >> 'agc_mean_luminance.h', >> 'algorithm.h', >> 'awb_bayes.h', >> diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp >> index 1d3af0627f..65e5297766 100644 >> --- a/src/ipa/mali-c55/mali-c55.cpp >> +++ b/src/ipa/mali-c55/mali-c55.cpp >> @@ -27,6 +27,7 @@ >> #include "libcamera/internal/yaml_parser.h" >> >> #include "algorithms/algorithm.h" >> +#include "libipa/agc.h" >> #include "libipa/camera_sensor_helper.h" >> >> #include "ipa_context.h" >> @@ -141,20 +142,18 @@ void IPAMaliC55::setControls() >> { >> IPAActiveState &activeState = context_.activeState; >> uint32_t exposure; >> - uint32_t gain; >> + double gain; >> >> if (activeState.agc.autoEnabled) { >> exposure = activeState.agc.automatic.exposure; >> - gain = camHelper_->gainCode(activeState.agc.automatic.sensorGain); >> + gain = activeState.agc.automatic.sensorGain; >> } else { >> exposure = activeState.agc.manual.exposure; >> - gain = camHelper_->gainCode(activeState.agc.manual.sensorGain); >> + gain = activeState.agc.manual.sensorGain; >> } >> >> ControlList ctrls(sensorControls_); >> - ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); >> - ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain)); >> - >> + agc::prepareControls(ctrls, camHelper_.get(), exposure, gain); >> setSensorControls.emit(ctrls); >> } >> >> @@ -352,10 +351,8 @@ void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId, >> stats = reinterpret_cast<mali_c55_stats_buffer *>( >> buffers_.at(bufferId).planes()[0].data()); >> >> - frameContext.agc.exposure = >> - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); >> - frameContext.agc.sensorGain = >> - camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); >> + std::tie(frameContext.agc.exposure, frameContext.agc.sensorGain) >> + = agc::extractControls(sensorControls, camHelper_.get()); >> >> ControlList metadata(controls::controls); >> >> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp >> index 38f55b1d86..acb878d814 100644 >> --- a/src/ipa/rkisp1/rkisp1.cpp >> +++ b/src/ipa/rkisp1/rkisp1.cpp >> @@ -31,6 +31,7 @@ >> #include "libcamera/internal/yaml_parser.h" >> >> #include "algorithms/algorithm.h" >> +#include "libipa/agc.h" >> >> #include "ipa_context.h" >> #include "params.h" >> @@ -328,10 +329,8 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, >> stats = reinterpret_cast<rkisp1_stat_buffer *>( >> mappedBuffers_.at(bufferId).planes()[0].data()); >> >> - frameContext.sensor.exposure = >> - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); >> - frameContext.sensor.gain = >> - context_.camHelper->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); >> + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) >> + = agc::extractControls(sensorControls, context_.camHelper.get()); >> >> ControlList metadata(controls::controls); >> >> @@ -365,7 +364,6 @@ void IPARkISP1::setControls(unsigned int frame) >> >> IPAFrameContext &frameContext = context_.frameContexts.get(frame); >> uint32_t exposure = frameContext.agc.exposure; >> - uint32_t gain = context_.camHelper->gainCode(frameContext.agc.gain); >> uint32_t vblank = frameContext.agc.vblank; >> >> LOG(IPARkISP1, Debug) >> @@ -373,8 +371,7 @@ void IPARkISP1::setControls(unsigned int frame) >> << ", gain " << frameContext.agc.gain << ", vblank " << vblank; >> >> ControlList ctrls(context_.sensorControls); >> - ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); >> - ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain)); >> + agc::prepareControls(ctrls, context_.camHelper.get(), exposure, frameContext.agc.gain); >> ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); >> >> setSensorControls.emit(frame, ctrls); >> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp >> index 3932daaa1f..a38fcff7d8 100644 >> --- a/src/ipa/simple/soft_simple.cpp >> +++ b/src/ipa/simple/soft_simple.cpp >> @@ -27,6 +27,7 @@ >> #include "libcamera/internal/yaml_parser.h" >> >> #include "algorithms/adjust.h" >> +#include "libipa/agc.h" >> #include "libipa/camera_sensor_helper.h" >> >> #include "module.h" >> @@ -301,10 +302,8 @@ void IPASoftSimple::processStats(const uint32_t frame, >> { >> IPAFrameContext &frameContext = context_.frameContexts.get(frame); >> >> - frameContext.sensor.exposure = >> - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); >> - int32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); >> - frameContext.sensor.gain = camHelper_ ? camHelper_->gain(again) : again; >> + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) >> + = agc::extractControls(sensorControls, camHelper_.get()); >> >> ControlList metadata(controls::controls); >> for (const auto &algo : algorithms()) >> @@ -312,13 +311,7 @@ void IPASoftSimple::processStats(const uint32_t frame, >> metadataReady.emit(frame, metadata); >> >> ControlList ctrls(sensorInfoMap_); >> - >> - int32_t againNew = camHelper_ >> - ? camHelper_->gainCode(frameContext.agc.gain) >> - : static_cast<int32_t>(frameContext.agc.gain); >> - ctrls.set(V4L2_CID_EXPOSURE, frameContext.agc.exposure); >> - ctrls.set(V4L2_CID_ANALOGUE_GAIN, againNew); >> - >> + agc::prepareControls(ctrls, camHelper_.get(), frameContext.agc.exposure, frameContext.agc.gain); > > You can eaisly break this line Done > >> setSensorControls.emit(ctrls); >> } >> >> -- >> 2.55.0 >>
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 4bdc4b7677..51379808cd 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -36,6 +36,7 @@ #include "libcamera/internal/mapped_framebuffer.h" #include "libcamera/internal/yaml_parser.h" +#include "libipa/agc.h" #include "libipa/camera_sensor_helper.h" #include "ipa_context.h" @@ -596,8 +597,8 @@ void IPAIPU3::processStats(const uint32_t frame, IPAFrameContext &frameContext = context_.frameContexts.get(frame); - frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); - frameContext.sensor.gain = camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) + = agc::extractControls(sensorControls, camHelper_.get()); ControlList metadata(controls::controls); @@ -642,12 +643,11 @@ void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls) */ void IPAIPU3::setControls(unsigned int frame) { - int32_t exposure = context_.activeState.agc.exposure; - int32_t gain = camHelper_->gainCode(context_.activeState.agc.gain); - ControlList ctrls(sensorCtrls_); - ctrls.set(V4L2_CID_EXPOSURE, exposure); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain); + agc::prepareControls( + ctrls, camHelper_.get(), + context_.activeState.agc.exposure, context_.activeState.agc.gain + ); ControlList lensCtrls(lensCtrls_); lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h new file mode 100644 index 0000000000..5247425952 --- /dev/null +++ b/src/ipa/libipa/agc.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026 Ideas on Board Oy + * + * AGC-related functionality + */ + +#pragma once + +#include <utility> + +#include <linux/v4l2-controls.h> + +#include <libcamera/controls.h> + +#include "camera_sensor_helper.h" + +namespace libcamera { + +namespace ipa { + +namespace agc { + +[[nodiscard]] +inline std::pair<uint32_t, double> +extractControls(const ControlList &controls, const CameraSensorHelper *sensor) +{ + auto exposure = controls.get(V4L2_CID_EXPOSURE).get<int32_t>(); + auto gainCode = controls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); + + return { + uint32_t(exposure), + sensor ? sensor->gain(gainCode) : gainCode, + }; +} + +inline void +prepareControls(ControlList &controls, const CameraSensorHelper *sensor, + int32_t exposure, double gain) +{ + controls.set(V4L2_CID_EXPOSURE, exposure); + controls.set(V4L2_CID_ANALOGUE_GAIN, int32_t(sensor ? sensor->gainCode(gain) : gain)); +} + +} /* namespace agc */ + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index 963c5ee730..05f1a8749c 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 libipa_headers = files([ + 'agc.h', 'agc_mean_luminance.h', 'algorithm.h', 'awb_bayes.h', diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp index 1d3af0627f..65e5297766 100644 --- a/src/ipa/mali-c55/mali-c55.cpp +++ b/src/ipa/mali-c55/mali-c55.cpp @@ -27,6 +27,7 @@ #include "libcamera/internal/yaml_parser.h" #include "algorithms/algorithm.h" +#include "libipa/agc.h" #include "libipa/camera_sensor_helper.h" #include "ipa_context.h" @@ -141,20 +142,18 @@ void IPAMaliC55::setControls() { IPAActiveState &activeState = context_.activeState; uint32_t exposure; - uint32_t gain; + double gain; if (activeState.agc.autoEnabled) { exposure = activeState.agc.automatic.exposure; - gain = camHelper_->gainCode(activeState.agc.automatic.sensorGain); + gain = activeState.agc.automatic.sensorGain; } else { exposure = activeState.agc.manual.exposure; - gain = camHelper_->gainCode(activeState.agc.manual.sensorGain); + gain = activeState.agc.manual.sensorGain; } ControlList ctrls(sensorControls_); - ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain)); - + agc::prepareControls(ctrls, camHelper_.get(), exposure, gain); setSensorControls.emit(ctrls); } @@ -352,10 +351,8 @@ void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId, stats = reinterpret_cast<mali_c55_stats_buffer *>( buffers_.at(bufferId).planes()[0].data()); - frameContext.agc.exposure = - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); - frameContext.agc.sensorGain = - camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); + std::tie(frameContext.agc.exposure, frameContext.agc.sensorGain) + = agc::extractControls(sensorControls, camHelper_.get()); ControlList metadata(controls::controls); diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 38f55b1d86..acb878d814 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -31,6 +31,7 @@ #include "libcamera/internal/yaml_parser.h" #include "algorithms/algorithm.h" +#include "libipa/agc.h" #include "ipa_context.h" #include "params.h" @@ -328,10 +329,8 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, stats = reinterpret_cast<rkisp1_stat_buffer *>( mappedBuffers_.at(bufferId).planes()[0].data()); - frameContext.sensor.exposure = - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); - frameContext.sensor.gain = - context_.camHelper->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>()); + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) + = agc::extractControls(sensorControls, context_.camHelper.get()); ControlList metadata(controls::controls); @@ -365,7 +364,6 @@ void IPARkISP1::setControls(unsigned int frame) IPAFrameContext &frameContext = context_.frameContexts.get(frame); uint32_t exposure = frameContext.agc.exposure; - uint32_t gain = context_.camHelper->gainCode(frameContext.agc.gain); uint32_t vblank = frameContext.agc.vblank; LOG(IPARkISP1, Debug) @@ -373,8 +371,7 @@ void IPARkISP1::setControls(unsigned int frame) << ", gain " << frameContext.agc.gain << ", vblank " << vblank; ControlList ctrls(context_.sensorControls); - ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure)); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain)); + agc::prepareControls(ctrls, context_.camHelper.get(), exposure, frameContext.agc.gain); ctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank)); setSensorControls.emit(frame, ctrls); diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index 3932daaa1f..a38fcff7d8 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -27,6 +27,7 @@ #include "libcamera/internal/yaml_parser.h" #include "algorithms/adjust.h" +#include "libipa/agc.h" #include "libipa/camera_sensor_helper.h" #include "module.h" @@ -301,10 +302,8 @@ void IPASoftSimple::processStats(const uint32_t frame, { IPAFrameContext &frameContext = context_.frameContexts.get(frame); - frameContext.sensor.exposure = - sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); - int32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); - frameContext.sensor.gain = camHelper_ ? camHelper_->gain(again) : again; + std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) + = agc::extractControls(sensorControls, camHelper_.get()); ControlList metadata(controls::controls); for (const auto &algo : algorithms()) @@ -312,13 +311,7 @@ void IPASoftSimple::processStats(const uint32_t frame, metadataReady.emit(frame, metadata); ControlList ctrls(sensorInfoMap_); - - int32_t againNew = camHelper_ - ? camHelper_->gainCode(frameContext.agc.gain) - : static_cast<int32_t>(frameContext.agc.gain); - ctrls.set(V4L2_CID_EXPOSURE, frameContext.agc.exposure); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, againNew); - + agc::prepareControls(ctrls, camHelper_.get(), frameContext.agc.exposure, frameContext.agc.gain); setSensorControls.emit(ctrls); }
Move the extraction and preparation of `V4L2_CID_{EXPOSURE,ANALOGUE_GAIN}` into separate functions. This also implements support for not having a a camera sensor helper. Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> --- src/ipa/ipu3/ipu3.cpp | 14 +++++----- src/ipa/libipa/agc.h | 49 ++++++++++++++++++++++++++++++++++ src/ipa/libipa/meson.build | 1 + src/ipa/mali-c55/mali-c55.cpp | 17 +++++------- src/ipa/rkisp1/rkisp1.cpp | 11 +++----- src/ipa/simple/soft_simple.cpp | 15 +++-------- 6 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 src/ipa/libipa/agc.h