[libcamera-devel] [PATCH v5 1/2] pipeline: ipu3: Store requests in the case a buffer shortage
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon May 24 04:52:23 CEST 2021
Hi Hiro,
Thank you for the patch.
On Thu, May 13, 2021 at 11:29:45AM +0900, Hirokazu Honda 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 IPU3CameraData to do that.
>
> Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
> Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> src/libcamera/pipeline/ipu3/cio2.cpp | 2 +-
> src/libcamera/pipeline/ipu3/frames.cpp | 4 +-
> src/libcamera/pipeline/ipu3/ipu3.cpp | 80 +++++++++++++++++++-------
> 3 files changed, 63 insertions(+), 23 deletions(-)
>
> diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
> index 3cd777d1..8bbef174 100644
> --- a/src/libcamera/pipeline/ipu3/cio2.cpp
> +++ b/src/libcamera/pipeline/ipu3/cio2.cpp
> @@ -272,7 +272,7 @@ FrameBuffer *CIO2Device::queueBuffer(Request *request, FrameBuffer *rawBuffer)
> /* If no buffer is provided in the request, use an internal one. */
> if (!buffer) {
> if (availableBuffers_.empty()) {
> - LOG(IPU3, Error) << "CIO2 buffer underrun";
> + LOG(IPU3, Debug) << "CIO2 buffer underrun";
> return nullptr;
> }
>
> diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp
> index d0f55ab9..29d9aafc 100644
> --- a/src/libcamera/pipeline/ipu3/frames.cpp
> +++ b/src/libcamera/pipeline/ipu3/frames.cpp
> @@ -44,12 +44,12 @@ IPU3Frames::Info *IPU3Frames::create(Request *request)
> unsigned int id = request->sequence();
>
> if (availableParamBuffers_.empty()) {
> - LOG(IPU3, Error) << "Parameters buffer underrun";
> + LOG(IPU3, Debug) << "Parameters buffer underrun";
> return nullptr;
> }
>
> if (availableStatBuffers_.empty()) {
> - LOG(IPU3, Error) << "Statistics buffer underrun";
> + LOG(IPU3, Debug) << "Statistics buffer underrun";
> return nullptr;
> }
>
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index ade8ffbd..6961d498 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -66,6 +66,8 @@ public:
> void cio2BufferReady(FrameBuffer *buffer);
> void paramBufferReady(FrameBuffer *buffer);
> void statBufferReady(FrameBuffer *buffer);
> + void queuePendingRequests();
> + void cancelPendingRequests();
>
> CIO2Device cio2_;
> ImgUDevice *imgu_;
> @@ -84,6 +86,8 @@ public:
>
> std::unique_ptr<ipa::ipu3::IPAProxyIPU3> ipa_;
>
> + std::queue<Request *> pendingRequests_;
> +
> private:
> void queueFrameAction(unsigned int id,
> const ipa::ipu3::IPU3Action &action);
> @@ -764,6 +768,8 @@ void PipelineHandlerIPU3::stop(Camera *camera)
> IPU3CameraData *data = cameraData(camera);
> int ret = 0;
>
> + data->cancelPendingRequests();
> +
> data->ipa_->stop();
>
> ret |= data->imgu_->stop();
> @@ -774,32 +780,66 @@ void PipelineHandlerIPU3::stop(Camera *camera)
> freeBuffers(camera);
> }
>
> -int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
> +void IPU3CameraData::cancelPendingRequests()
> {
> - IPU3CameraData *data = cameraData(camera);
> + while (!pendingRequests_.empty()) {
> + Request *request = pendingRequests_.front();
>
> - IPU3Frames::Info *info = data->frameInfos_.create(request);
> - if (!info)
> - return -ENOBUFS;
> + for (auto it : request->buffers()) {
> + FrameBuffer *buffer = it.second;
> + buffer->cancel();
> + pipe_->completeBuffer(request, buffer);
> + }
>
> - /*
> - * 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;
> + pipe_->completeRequest(request);
> + pendingRequests_.pop();
> }
> +}
>
> - info->rawBuffer = rawBuffer;
> +void IPU3CameraData::queuePendingRequests()
> +{
> + while (!pendingRequests_.empty()) {
> + Request *request = pendingRequests_.front();
>
> - ipa::ipu3::IPU3Event ev;
> - ev.op = ipa::ipu3::EventProcessControls;
> - ev.frame = info->id;
> - ev.controls = request->controls();
> - data->ipa_->processEvent(ev);
> + IPU3Frames::Info *info = 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(&rawStream_);
> + FrameBuffer *rawBuffer = cio2_.queueBuffer(request, reqRawBuffer);
> + /*
> + * \todo If queueBuffer fails in queuing a buffer to the device,
> + * report the request as error by cancelling the request and
> + * calling PipelineHandler::completeRequest().
> + */
> + if (!rawBuffer) {
> + frameInfos_.remove(info);
> + break;
> + }
> +
> + info->rawBuffer = rawBuffer;
> +
> + ipa::ipu3::IPU3Event ev;
> + ev.op = ipa::ipu3::EventProcessControls;
> + ev.frame = info->id;
> + ev.controls = request->controls();
> + ipa_->processEvent(ev);
> +
> + pendingRequests_.pop();
> + }
> +}
> +
> +int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
> +{
> + IPU3CameraData *data = cameraData(camera);
> +
> + data->pendingRequests_.push(request);
> + data->queuePendingRequests();
>
> return 0;
> }
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list