[libcamera-devel] [PATCH v2 06/11] ipa: rkisp1: Pass requests setting AF controls to the AF algorithm
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Fri Jul 15 02:38:50 CEST 2022
Hello,
On Thu, Jul 14, 2022 at 09:47:55PM +0100, Kieran Bingham via libcamera-devel wrote:
> Quoting Jacopo Mondi via libcamera-devel (2022-07-14 19:46:52)
> > On Wed, Jul 13, 2022 at 10:43:12AM +0200, Daniel Semkowicz via libcamera-devel wrote:
> > > Pass the controls set by top level API to the AF algorithm if it
> > > was enabled.
> > >
> > > Signed-off-by: Daniel Semkowicz <dse at thaumatec.com>
> > > ---
> > > src/ipa/rkisp1/rkisp1.cpp | 52 +++++++++++++++++++++++++++++++++++++--
> > > 1 file changed, 50 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> > > index 01bb54fb..53b53f12 100644
> > > --- a/src/ipa/rkisp1/rkisp1.cpp
> > > +++ b/src/ipa/rkisp1/rkisp1.cpp
> > > @@ -28,6 +28,7 @@
> > > #include "libcamera/internal/mapped_framebuffer.h"
> > > #include "libcamera/internal/yaml_parser.h"
> > >
> > > +#include "algorithms/af.h"
> > > #include "algorithms/agc.h"
> > > #include "algorithms/algorithm.h"
> > > #include "algorithms/awb.h"
> > > @@ -295,9 +296,56 @@ void IPARkISP1::unmapBuffers(const std::vector<unsigned int> &ids)
> > > }
> > >
> > > void IPARkISP1::queueRequest([[maybe_unused]] const uint32_t frame,
> > > - [[maybe_unused]] const ControlList &controls)
> > > + const ControlList &controls)
> > > {
> > > - /* \todo Start processing for 'frame' based on 'controls'. */
> > > + using namespace algorithms;
> > > +
> > > + for (auto const &ctrl : controls) {
> >
> > You can use structured bindings, they're nicer :)
> >
> > for (auto const &[id, val] : controls) {
> >
> > }
> >
> > > + unsigned int ctrlEnum = ctrl.first;
> > > + const ControlValue &ctrlValue = ctrl.second;
> >
> > And drop these
> > > +
> > > + LOG(IPARkISP1, Debug) << "Request ctrl: "
> > > + << controls::controls.at(ctrlEnum)->name()
> > > + << " = " << ctrlValue.toString();
> > > +
> > > + switch (ctrlEnum) {
> > > + case controls::AF_MODE: {
> > > + Af *af = getAlgorithm<Af>();
> > > + if (!af) {
> > > + LOG(IPARkISP1, Warning) << "Could not set AF_MODE - no AF algorithm";
> > > + break;
> > > + }
> >
> > You can get *af once outside of the switch.
> >
> > Also, as the failure in getting *af is not related to the control,
> > there's not much value in duplicating the error message, should
> > getAlgorithm<>() be made loud on failure so that the caller can skip
> > doing the same, if not required ?
>
> I had actually envisaged handling controls differently, adding a hook to
> each algorithm called either queueRequest() or processControls() or
> such, and let each algorithm handle only the controls it uses.
Do you mean https://lists.libcamera.org/pipermail/libcamera-devel/2022-July/031931.html
and https://lists.libcamera.org/pipermail/libcamera-devel/2022-July/031932.html ? :-)
> The drawback there is that if a control goes unhandled, it would be
> difficult for us to detect or report that, so I think I like this
> approach too.
We could let the Algorithm::queueRequest() function indicate which
control(s) it has handled, and verify at the end that all controls have
been handled.
> Especially as you cover that exact condition in the default case below!
>
> My only worry is that switch table could get really large though, and
> the algorithms will have to have a public API to handle all each control
> specifically which could get extensive.
That's what the RPi IPA module does, and I'm not a big fan of the end
result.
> The only alternative I can think of off the top of my head to consider
> could be:
>
> ControlList afControls;
> ControlList agcControls;
>
> for (auto const control : controls) {
> case controls::AF_TRIGGER:
> case controls::AF_PAUSE:
> afControls.emplace(control);
> break;
>
> case controls::AE_ENABLE:
> case controls::AE_METERING_MODE:
> agcControls.emplace(control);
> break;
>
> default:
> // unhandled control error
> break;
> }
>
>
> if (afControls.size()) {
> // I would probably store all the instantiated algorithms
> // as a named private pointer variable in the IPARkISP1 class.
>
> if (!af_) {
> LOG(IPARkISP1, Warning) << "Unhandled AF controls";
> } else {
> af_->setControls(afControls);
> }
> }
>
> if (agcControls.size()) {
>
> if (!agc_) {
> LOG(IPARkISP1, Warning) << "Unhandled AGC controls";
> } else {
> agc_->setControls(agcControls);
> }
> }
>
> Perhaps some of that boilerplate for each algorithm could get mapped
> down in a template. And also perhaps this introduces more iteration and
> copying than would be desired too - it's only sketching out an idea to
> see if it's easier to keep the definition of how controls are handled by
> algorithms managed by the algorithms themselves.
>
> > > +
> > > + af->setMode(static_cast<controls::AfModeEnum>(ctrlValue.get<int32_t>()));
> > > + break;
> > > + }
> > > + case controls::AF_TRIGGER: {
> > > + Af *af = getAlgorithm<Af>();
> > > + if (!af) {
> > > + LOG(IPARkISP1, Warning) << "Could not set AF_TRIGGER - no AF algorithm";
> > > + break;
> > > + }
> > > +
> > > + af->setTrigger(static_cast<controls::AfTriggerEnum>(ctrlValue.get<int32_t>()));
> > > + break;
> > > + }
> > > + case controls::AF_PAUSE: {
> > > + Af *af = getAlgorithm<Af>();
> > > + if (!af) {
> > > + LOG(IPARkISP1, Warning) << "Could not set AF_TRIGGER - no AF algorithm";
> > > + break;
> > > + }
> > > +
> > > + af->setPause(static_cast<controls::AfPauseEnum>(ctrlValue.get<int32_t>()));
> > > + break;
> > > + }
> > > + default:
> > > + LOG(IPARkISP1, Warning)
> > > + << "Ctrl " << controls::controls.at(ctrlEnum)->name()
> > > + << " is not handled.";
> > > + break;
> > > + }
> > > + }
> > > }
> > >
> > > void IPARkISP1::fillParamsBuffer(const uint32_t frame, const uint32_t bufferId)
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list