| Message ID | 20260810103846.1075936-21-barnabas.pocze@ideasonboard.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
Hi Barnabás On Mon, Aug 10, 2026 at 12:38:16PM +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. > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> Acked-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > --- > src/ipa/ipu3/ipu3.cpp | 13 ++++----- > src/ipa/libipa/agc.h | 52 ++++++++++++++++++++++++++++++++++ > src/ipa/libipa/meson.build | 1 + > src/ipa/mali-c55/mali-c55.cpp | 18 ++++++------ > src/ipa/rkisp1/rkisp1.cpp | 12 ++++---- > src/ipa/simple/soft_simple.cpp | 16 ++++------- > 6 files changed, 77 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..b7897269bb 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,10 @@ 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..386442bae1 > --- /dev/null > +++ b/src/ipa/libipa/agc.h > @@ -0,0 +1,52 @@ > +/* 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 { > + static_cast<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, > + static_cast<int32_t>(sensor > + ? sensor->gainCode(gain) > + : static_cast<uint32_t>(gain))); > +} > + > +} /* namespace agc */ > + > +} /* namespace ipa */ > + > +} /* namespace libcamera */ > diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build > index cbfa7cd409..d17ccf8c54 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 da0dbe4b31..a13146d8a6 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" > @@ -143,20 +144,19 @@ 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); > } > > @@ -354,10 +354,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..98ec5a5748 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,8 @@ 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..01c41e3a8c 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,8 @@ 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); > } > > -- > 2.55.0 >
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 4bdc4b7677..b7897269bb 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,10 @@ 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..386442bae1 --- /dev/null +++ b/src/ipa/libipa/agc.h @@ -0,0 +1,52 @@ +/* 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 { + static_cast<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, + static_cast<int32_t>(sensor + ? sensor->gainCode(gain) + : static_cast<uint32_t>(gain))); +} + +} /* namespace agc */ + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index cbfa7cd409..d17ccf8c54 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 da0dbe4b31..a13146d8a6 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" @@ -143,20 +144,19 @@ 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); } @@ -354,10 +354,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..98ec5a5748 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,8 @@ 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..01c41e3a8c 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,8 @@ 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 | 13 ++++----- src/ipa/libipa/agc.h | 52 ++++++++++++++++++++++++++++++++++ src/ipa/libipa/meson.build | 1 + src/ipa/mali-c55/mali-c55.cpp | 18 ++++++------ src/ipa/rkisp1/rkisp1.cpp | 12 ++++---- src/ipa/simple/soft_simple.cpp | 16 ++++------- 6 files changed, 77 insertions(+), 35 deletions(-) create mode 100644 src/ipa/libipa/agc.h