[libcamera-devel] [PATCH] pipeline: ipu3: Store requests in the case a buffer shortage
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Sat Apr 3 04:08:53 CEST 2021
Hi Hiro,
On Wed, Mar 31, 2021 at 05:51:48PM +0900, Hirokazu Honda wrote:
> I should still work for this patch series.
> The missing part is to trigger queuePendingRequests() appropriately
> when buffers are available.
> I couldn't find a good way as availableBuffers notification functions
> are separated and trying queuePendingRequests() is not likely
> successful and thus inefficient.
> I would like to ask anyone for a good idea for this.
Request queuing to the kernel can fail if we are out of either ImgU
stats/params buffers, or internal CIO2 raw buffers. New buffers become
available for the ImgU in IPU3Frames::remove(), and for the CIO2 in
CIO2Device::tryReturnBuffer(). Both could be modified to emit a signal,
which could be connected to queuePendingRequests().
> On Wed, Mar 31, 2021 at 5:45 PM Hirokazu Honda <hiroh at chromium.org> wrote:
> >
> > PipelineHandlerIPU3 returns -ENOBUFS and -ENOMEM on queueing a
> > request when there are not sufficient buffers for the request.
> > Since the request will be successful if it is queued later when
> > enough buffers are available. The requests failed due to a buffer
> > shortage should be stored and retried later in the FIFO order.
> > This introduces the queue in PipelineHandlerIPU3 to do that.
> >
> > Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
> > ---
> > src/libcamera/pipeline/ipu3/ipu3.cpp | 62 ++++++++++++++++++----------
> > 1 file changed, 41 insertions(+), 21 deletions(-)
> >
> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > index 519cad4f..71dd311f 100644
> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > @@ -153,12 +153,16 @@ private:
> > int allocateBuffers(Camera *camera);
> > int freeBuffers(Camera *camera);
> >
> > + int queuePendingRequests();
> > +
> > ImgUDevice imgu0_;
> > ImgUDevice imgu1_;
> > MediaDevice *cio2MediaDev_;
> > MediaDevice *imguMediaDev_;
> >
> > std::vector<IPABuffer> ipaBuffers_;
> > +
> > + std::queue<std::pair<IPU3CameraData *, Request *>> pendingRequests_;
As requests are per-camera, shouldn't the queue be stored in
IPU3CameraData ? queuePendingRequests() should also be moved to the
IPU3CameraData class.
> > };
> >
> > IPU3CameraConfiguration::IPU3CameraConfiguration(IPU3CameraData *data)
> > @@ -764,6 +768,8 @@ void PipelineHandlerIPU3::stop(Camera *camera)
> > IPU3CameraData *data = cameraData(camera);
> > int ret = 0;
> >
> > + pendingRequests_ = {};
> > +
> > data->ipa_->stop();
> >
> > ret |= data->imgu_->stop();
> > @@ -774,36 +780,50 @@ void PipelineHandlerIPU3::stop(Camera *camera)
> > freeBuffers(camera);
> > }
> >
> > -int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
> > +int PipelineHandlerIPU3::queuePendingRequests()
> > {
> > - IPU3CameraData *data = cameraData(camera);
> > + while (!pendingRequests_.empty()) {
> > + IPU3CameraData *data = pendingRequests_.front().first;
> > + Request *request = pendingRequests_.front().second;
> >
> > - IPU3Frames::Info *info = data->frameInfos_.create(request);
> > - if (!info)
> > - return -ENOBUFS;
> > + IPU3Frames::Info *info = data->frameInfos_.create(request);
> > + if (!info)
> > + break;
> >
> > - /*
> > - * Queue a buffer on the CIO2, using the raw stream buffer provided in
> > - * the request, if any, or a CIO2 internal buffer otherwise.
> > - */
> > - FrameBuffer *reqRawBuffer = request->findBuffer(&data->rawStream_);
> > - FrameBuffer *rawBuffer = data->cio2_.queueBuffer(request, reqRawBuffer);
> > - if (!rawBuffer) {
> > - data->frameInfos_.remove(info);
> > - return -ENOMEM;
> > - }
> > + /*
> > + * Queue a buffer on the CIO2, using the raw stream buffer
> > + * provided in the request, if any, or a CIO2 internal buffer
> > + * otherwise.
> > + */
> > + FrameBuffer *reqRawBuffer = request->findBuffer(&data->rawStream_);
> > + FrameBuffer *rawBuffer = data->cio2_.queueBuffer(request, reqRawBuffer);
> > + if (!rawBuffer) {
> > + data->frameInfos_.remove(info);
> > + break;
> > + }
> >
> > - info->rawBuffer = rawBuffer;
> > + info->rawBuffer = rawBuffer;
> >
> > - ipa::ipu3::IPU3Event ev;
> > - ev.op = ipa::ipu3::EventProcessControls;
> > - ev.frame = info->id;
> > - ev.controls = request->controls();
> > - data->ipa_->processEvent(ev);
> > + ipa::ipu3::IPU3Event ev;
> > + ev.op = ipa::ipu3::EventProcessControls;
> > + ev.frame = info->id;
> > + ev.controls = request->controls();
> > + data->ipa_->processEvent(ev);
> > +
> > + pendingRequests_.pop();
> > + }
> >
> > return 0;
> > }
> >
> > +int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
> > +{
> > + IPU3CameraData *data = cameraData(camera);
> > +
> > + pendingRequests_.emplace(data, request);
> > + return queuePendingRequests();
> > +}
> > +
> > bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
> > {
> > int ret;
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list