[PATCH v3 1/6] libcamera: software_isp: Track frames and requests

Barnabás Pőcze pobrn at protonmail.com
Mon Jan 27 21:17:35 CET 2025


2025. január 27., hétfő 19:35 keltezéssel, Kieran Bingham <kieran.bingham at ideasonboard.com> írta:

> Quoting Laurent Pinchart (2025-01-27 06:59:36)
> > Hi Milan,
> >
> > Thank you for the patch.
> >
> > On Mon, Jan 13, 2025 at 02:34:00PM +0100, Milan Zamazal wrote:
> > > Hardware pipelines track requests and other information related to
> > > particular frames.  This hasn't been needed in software ISP so far.  But
> > > in order to be able to track metadata corresponding to a given frame,
> > > frame-request tracking mechanism starts being useful.  This patch
> > > introduces the basic tracking structure, actual metadata handling is
> > > added in the following patch.
> > >
> 
> I'm also weary that Barnabás made some fixes to other IPA 'frame
> handlers' recently.

The changes in the proposed https://patchwork.libcamera.org/patch/22610/ patch
have already been incorporated into this patch set.


> 
> I think somehow this concept needs to be templated to make sure we don't
> have different bugs and different implementation in each IPA...
> 
> Not a fault of 'this' patch, but I'm really weary about seeing multiple
> implementations of the same object.

I agree.


Regards,
Barnabás Pőcze


> 
> > > Signed-off-by: Milan Zamazal <mzamazal at redhat.com>
> > > ---
> > >  src/libcamera/pipeline/simple/simple.cpp | 81 ++++++++++++++++++++++--
> > >  1 file changed, 76 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> > > index 8ac24e6e..123179b6 100644
> > > --- a/src/libcamera/pipeline/simple/simple.cpp
> > > +++ b/src/libcamera/pipeline/simple/simple.cpp
> > > @@ -181,6 +181,64 @@ LOG_DEFINE_CATEGORY(SimplePipeline)
> > >
> > >  class SimplePipelineHandler;
> > >
> > > +struct SimpleFrameInfo {
> > > +     uint32_t frame;
> > > +     Request *request;
> > > +};
> > > +
> > > +class SimpleFrames
> > > +{
> > > +public:
> > > +     void create(Request *request);
> > > +     void destroy(uint32_t frame);
> > > +     void clear();
> > > +
> > > +     SimpleFrameInfo *find(uint32_t frame);
> > > +     SimpleFrameInfo *find(Request *request);
> > > +
> > > +private:
> > > +     std::map<uint32_t, SimpleFrameInfo> frameInfo_;
> > > +};
> > > +
> > > +void SimpleFrames::create(Request *request)
> > > +{
> > > +     uint32_t frame = request->sequence();
> > > +     auto [it, inserted] = frameInfo_.try_emplace(request->sequence());
> > > +     ASSERT(inserted);
> > > +     it->second.frame = frame;
> > > +     it->second.request = request;
> > > +}
> > > +
> > > +void SimpleFrames::destroy(uint32_t frame)
> > > +{
> > > +     frameInfo_.erase(frame);
> > > +}
> > > +
> > > +void SimpleFrames::clear()
> > > +{
> > > +     frameInfo_.clear();
> > > +}
> > > +
> > > +SimpleFrameInfo *SimpleFrames::find(uint32_t frame)
> > > +{
> > > +     auto info = frameInfo_.find(frame);
> > > +     if (info == frameInfo_.end())
> > > +             return nullptr;
> > > +     return &info->second;
> > > +}
> > > +
> > > +SimpleFrameInfo *SimpleFrames::find(Request *request)
> > > +{
> > > +     for (auto &itInfo : frameInfo_) {
> > > +             SimpleFrameInfo *info = &itInfo.second;
> > > +
> > > +             if (info->request == request)
> > > +                     return info;
> > > +     }
> > > +
> > > +     return nullptr;
> > > +}
> > > +
> > >  struct SimplePipelineInfo {
> > >       const char *driver;
> > >       /*
> > > @@ -293,11 +351,13 @@ public:
> > >
> > >       std::unique_ptr<Converter> converter_;
> > >       std::unique_ptr<SoftwareIsp> swIsp_;
> > > +     SimpleFrames frameInfo_;
> > >
> > >  private:
> > >       void tryPipeline(unsigned int code, const Size &size);
> > >       static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink);
> > >
> > > +     void completeRequest(Request *request);
> > >       void conversionInputDone(FrameBuffer *buffer);
> > >       void conversionOutputDone(FrameBuffer *buffer);
> > >
> > > @@ -799,7 +859,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
> > >                       /* No conversion, just complete the request. */
> > >                       Request *request = buffer->request();
> > >                       pipe->completeBuffer(request, buffer);
> > > -                     pipe->completeRequest(request);
> > > +                     completeRequest(request);
> > >                       return;
> > >               }
> > >
> > > @@ -817,7 +877,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
> > >               const RequestOutputs &outputs = conversionQueue_.front();
> > >               for (auto &[stream, buf] : outputs.outputs)
> > >                       pipe->completeBuffer(outputs.request, buf);
> > > -             pipe->completeRequest(outputs.request);
> > > +             completeRequest(outputs.request);
> > >               conversionQueue_.pop();
> > >
> > >               return;
> > > @@ -875,7 +935,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
> > >
> > >       /* Otherwise simply complete the request. */
> > >       pipe->completeBuffer(request, buffer);
> > > -     pipe->completeRequest(request);
> > > +     completeRequest(request);
> > >  }
> > >
> > >  void SimpleCameraData::clearIncompleteRequests()
> > > @@ -886,6 +946,14 @@ void SimpleCameraData::clearIncompleteRequests()
> > >       }
> > >  }
> > >
> > > +void SimpleCameraData::completeRequest(Request *request)
> > > +{
> > > +     SimpleFrameInfo *info = frameInfo_.find(request);
> > > +     if (info)
> >
> > If there's no frame info something is really wrong. I don't think
> > completing the request makes much sense in that case.
> >
> > > +             frameInfo_.destroy(info->frame);
> > > +     pipe()->completeRequest(request);
> > > +}
> > > +
> > >  void SimpleCameraData::conversionInputDone(FrameBuffer *buffer)
> > >  {
> > >       /* Queue the input buffer back for capture. */
> > > @@ -899,7 +967,7 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)
> > >       /* Complete the buffer and the request. */
> > >       Request *request = buffer->request();
> > >       if (pipe->completeBuffer(request, buffer))
> > > -             pipe->completeRequest(request);
> > > +             completeRequest(request);
> > >  }
> > >
> > >  void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId)
> > > @@ -1412,6 +1480,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera)
> > >
> > >       video->bufferReady.disconnect(data, &SimpleCameraData::imageBufferReady);
> > >
> > > +     data->frameInfo_.clear();
> > >       data->clearIncompleteRequests();
> > >       data->conversionBuffers_.clear();
> > >
> > > @@ -1442,8 +1511,10 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)
> > >
> > >       if (data->useConversion_) {
> > >               data->conversionQueue_.push({ request, std::move(buffers) });
> > > -             if (data->swIsp_)
> > > +             if (data->swIsp_) {
> > > +                     data->frameInfo_.create(request);
> > >                       data->swIsp_->queueRequest(request->sequence(), request->controls());
> > > +             }
> > >       }
> > >
> > >       return 0;
> >
> > --
> > Regards,
> >
> > Laurent Pinchart
> 


More information about the libcamera-devel mailing list