[PATCH v2 2/2] ipa: rkisp1: Have algos initialize FrameContext
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Wed Nov 13 08:35:24 CET 2024
Hi Stefan
thanks for the review
On Tue, Nov 12, 2024 at 05:35:52PM +0100, Stefan Klug wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Wed, Oct 30, 2024 at 05:48:52PM +0100, Jacopo Mondi wrote:
> > The RkISP1 AGC algorithms assumes the metering mode to be
> > "MeteringMatrix" and pre-fill an array of weights associated
> > with it stored in meteringModes_[MeteringMatrix] when intializing
> > the algorithm in parseMeteringModes().
> >
> > It laters fetches the weights when computing parameters using the
> > FrameContext.agc.meteringMode as index of the meteringModes_ array.
> >
> > When a Request gets queued to the algorithm, the
> > FrameContext.agc.meteringMode index is populated from the algorithm's
> > active state, and optionally updated if the application has specified
> > a different metering mode.
> >
> > In case of Request underrun however, a non-initialized FrameContext
> > gets provided to the algorithm, causing an (unhandled) exception when
> > accessing the meteringModes_ array.
> >
> > To handle the situation when a Request underrun occours and let
> > algorithms initialize a FrameContext to safe defaults:
> >
> > - Add an 'underrun' flag to FrameContext
> > - Add an 'initFrameContext()' function to RkISP1 algorithms
> > - If a FrameContext is get() before being allocated, pass it through
> > the algorithms' initFrameContext() to safely initialize it
> >
> > Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
> > ---
> > src/ipa/libipa/fc_queue.cpp | 6 ++++++
> > src/ipa/libipa/fc_queue.h | 5 +++++
> > src/ipa/rkisp1/algorithms/agc.cpp | 8 ++++++++
> > src/ipa/rkisp1/algorithms/agc.h | 4 ++++
> > src/ipa/rkisp1/algorithms/algorithm.h | 5 +++++
> > src/ipa/rkisp1/rkisp1.cpp | 9 +++++++++
> > 6 files changed, 37 insertions(+)
> >
> > diff --git a/src/ipa/libipa/fc_queue.cpp b/src/ipa/libipa/fc_queue.cpp
> > index 0365e9197748..44f9d866ad1b 100644
> > --- a/src/ipa/libipa/fc_queue.cpp
> > +++ b/src/ipa/libipa/fc_queue.cpp
> > @@ -36,6 +36,12 @@ namespace ipa {
> > *
> > * \var FrameContext::frame
> > * \brief The frame number
> > + *
> > + * \var FrameContext::underrun
> > + * \brief Boolean flag that reports if the FrameContext has been accessed with
> > + * a FCQeueu::get() call before being FCQueue::alloc()-ated. If the flag is set
> > + * to True then the frame context needs to be initialized by algorithms to safe
> > + * defaults as it won't be initialized with any non-user provided control.
> > */
> >
> > /**
> > diff --git a/src/ipa/libipa/fc_queue.h b/src/ipa/libipa/fc_queue.h
> > index a1d136521107..d70ca9601bd7 100644
> > --- a/src/ipa/libipa/fc_queue.h
> > +++ b/src/ipa/libipa/fc_queue.h
> > @@ -22,6 +22,9 @@ template<typename FrameContext>
> > class FCQueue;
> >
> > struct FrameContext {
> > +public:
> > + bool underrun = false;
> > +
> > private:
> > template<typename T> friend class FCQueue;
> > uint32_t frame;
> > @@ -97,6 +100,7 @@ public:
> > * is called before alloc() by the IPA for frame#0.
> > */
> > init(frameContext, frame);
> > + frameContext.underrun = true;
>
> I can't find the place where the flag is reset to false (In case there
> are temporary underruns).
It happens in init()
void init(FrameContext &frameContext, const uint32_t frame)
{
frameContext = {};
and 'underrun' gets set to true only in the case get(x) is called
before alloc(x)
I should probably reset it in clear() too though
>
> >
> > return frameContext;
> > }
> > @@ -117,6 +121,7 @@ public:
> > << "Obtained an uninitialised FrameContext for " << frame;
> >
> > init(frameContext, frame);
> > + frameContext.underrun = true;
> >
> > return frameContext;
> > }
> > diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
> > index 301b7ec26508..4122f665b3ee 100644
> > --- a/src/ipa/rkisp1/algorithms/agc.cpp
> > +++ b/src/ipa/rkisp1/algorithms/agc.cpp
> > @@ -204,6 +204,14 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
> > return 0;
> > }
> >
> > +void Agc::initFrameContext(IPAContext &context,
> > + IPAFrameContext &frameContext)
> > +{
> > + auto &agc = context.activeState.agc;
> > +
> > + frameContext.agc.meteringMode = agc.meteringMode;
> > +}
> > +
>
> I'm unsure if we really need the separate function.
>
> From an algorithm point of view, I can't see the difference between
> calling
>
> initFrameContext(ipaContext, frameContext)
>
> and
>
> queueRequest(ipaContext, frameContext.frame, frameContext, {})
I like this way of thinking about it
>
> Couldn't we just rename queueRequest to initFrameContext, so that we
> don't have to implement two separate functions?
>
I like this ideas as well
Let's bikeshed the names a bit
we have
init()
configure()
queueRequest()
prepare()
process()
with the last three operations being called repetidly in a streaming
session.
I was never in love with the "prepare()" and "process()" names, and I
would rather use "prepare()" for queueRequest(), but that's what we
have right now.
The idea is that queueRequest actually initializes a frame context,
optionally with user provided controls. So I think that using
initFrameContext() is actually a good suggestion.
<End of bikeshedding>
> > /**
> > * \copydoc libcamera::ipa::Algorithm::queueRequest
> > */
> > diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h
> > index aa86f2c5bc21..c1adf91bbc4e 100644
> > --- a/src/ipa/rkisp1/algorithms/agc.h
> > +++ b/src/ipa/rkisp1/algorithms/agc.h
> > @@ -30,6 +30,10 @@ public:
> >
> > int init(IPAContext &context, const YamlObject &tuningData) override;
> > int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override;
> > +
> > + void initFrameContext(IPAContext &context,
> > + IPAFrameContext &frameContext) override;
> > +
> > void queueRequest(IPAContext &context,
> > const uint32_t frame,
> > IPAFrameContext &frameContext,
> > diff --git a/src/ipa/rkisp1/algorithms/algorithm.h b/src/ipa/rkisp1/algorithms/algorithm.h
> > index 715cfcd8298b..82603b7b372d 100644
> > --- a/src/ipa/rkisp1/algorithms/algorithm.h
> > +++ b/src/ipa/rkisp1/algorithms/algorithm.h
> > @@ -23,6 +23,11 @@ public:
> > {
> > }
> >
> > + virtual void initFrameContext([[maybe_unused]] IPAContext &context,
> > + [[maybe_unused]] IPAFrameContext &frameContext)
> > + {
> > + }
> > +
> > bool disabled_;
> > bool supportsRaw_;
> > };
> > diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> > index 9e161cabdea4..b743de9ff6af 100644
> > --- a/src/ipa/rkisp1/rkisp1.cpp
> > +++ b/src/ipa/rkisp1/rkisp1.cpp
> > @@ -353,6 +353,15 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId
> > {
> > IPAFrameContext &frameContext = context_.frameContexts.get(frame);
> >
> > + if (frameContext.underrun) {
> > + for (auto const &a : algorithms()) {
> > + Algorithm *algo = static_cast<Algorithm *>(a.get());
> > + if (algo->disabled_)
> > + continue;
> > + algo->initFrameContext(context_, frameContext);
> > + }
>
> Maybe that would be the place for frameContext.underrun = false?
I don't think the FrameContext status flags should be handled outside
of the FCQ implementation, otherwise each algo implementation would
have to do that correctly by its own.
Thanks
j
>
> Best regards,
> Stefan
>
> > + }
> > +
> > /*
> > * In raw capture mode, the ISP is bypassed and no statistics buffer is
> > * provided.
> > --
> > 2.47.0
> >
More information about the libcamera-devel
mailing list