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

Kieran Bingham kieran.bingham at ideasonboard.com
Mon Jan 27 19:35:37 CET 2025


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.

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.

> > 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