[libcamera-devel,v3,4/9] ipu3: Add StillCapture stream and imgu1 param buffers
diff mbox series

Message ID 20220629103018.4025635-5-chenghaoyang@google.com
State Superseded
Delegated to: Umang Jain
Headers show
Series
  • Use two imgus in ipu3 pipeline handler
Related show

Commit Message

Harvey Yang June 29, 2022, 10:30 a.m. UTC
From: Harvey Yang <chenghaoyang@chromium.org>

This patch adds the StillCapture stream and imgu1 param buffers.
The following patches will enable imgu1 to handle StillCapture stream
specifically, when the imgu0 is needed to handle video/preview streams.

Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
---
 src/libcamera/pipeline/ipu3/frames.cpp | 23 +++++++++++++++++++++--
 src/libcamera/pipeline/ipu3/frames.h   |  8 +++++++-
 src/libcamera/pipeline/ipu3/ipu3.cpp   | 20 +++++++++++++++++++-
 3 files changed, 47 insertions(+), 4 deletions(-)

Comments

Umang Jain July 27, 2022, 8:41 a.m. UTC | #1
Hi Harvey,

On 6/29/22 16:00, Harvey Yang via libcamera-devel wrote:
> From: Harvey Yang <chenghaoyang@chromium.org>
>
> This patch adds the StillCapture stream and imgu1 param buffers.


It might be worth to add that we will ignore statistics for still 
capture, as they aren't needed for 3A here, right?

> The following patches will enable imgu1 to handle StillCapture stream
> specifically, when the imgu0 is needed to handle video/preview streams.
>
> Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
> ---
>   src/libcamera/pipeline/ipu3/frames.cpp | 23 +++++++++++++++++++++--
>   src/libcamera/pipeline/ipu3/frames.h   |  8 +++++++-
>   src/libcamera/pipeline/ipu3/ipu3.cpp   | 20 +++++++++++++++++++-
>   3 files changed, 47 insertions(+), 4 deletions(-)
>
> diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp
> index a4c3477c..f9b705a5 100644
> --- a/src/libcamera/pipeline/ipu3/frames.cpp
> +++ b/src/libcamera/pipeline/ipu3/frames.cpp
> @@ -23,7 +23,8 @@ IPU3Frames::IPU3Frames()
>   }
>   
>   void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,
> -		      const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers)
> +		      const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers,
> +		      const std::vector<std::unique_ptr<FrameBuffer>> &captureParamBuffers)
>   {
>   	for (const std::unique_ptr<FrameBuffer> &buffer : paramBuffers)
>   		availableParamBuffers_.push(buffer.get());
> @@ -31,6 +32,9 @@ void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuff
>   	for (const std::unique_ptr<FrameBuffer> &buffer : statBuffers)
>   		availableStatBuffers_.push(buffer.get());
>   
> +	for (const std::unique_ptr<FrameBuffer> &buffer : captureParamBuffers)
> +		availableCaptureParamBuffers_.push(buffer.get());
> +
>   	frameInfo_.clear();
>   }
>   
> @@ -38,6 +42,7 @@ void IPU3Frames::clear()
>   {
>   	availableParamBuffers_ = {};


alternatively should we rename this to, availableVfParamBuffers_ to mark 
the distinction?

>   	availableStatBuffers_ = {};
> +	availableCaptureParamBuffers_ = {};
>   }
>   
>   IPU3Frames::Info *IPU3Frames::create(Request *request)
> @@ -54,14 +59,22 @@ IPU3Frames::Info *IPU3Frames::create(Request *request)
>   		return nullptr;
>   	}
>   
> +	if (availableCaptureParamBuffers_.empty()) {
> +		LOG(IPU3, Debug) << "Capture parameters buffer underrun";
> +		return nullptr;
> +	}
> +
>   	FrameBuffer *paramBuffer = availableParamBuffers_.front();


Ties into the earlier comment, maybe vfParamBuffer ? ... and so on below..

>   	FrameBuffer *statBuffer = availableStatBuffers_.front();
> +	FrameBuffer *captureParamBuffer = availableCaptureParamBuffers_.front();
>   
>   	paramBuffer->_d()->setRequest(request);
>   	statBuffer->_d()->setRequest(request);
> +	captureParamBuffer->_d()->setRequest(request);
>   
>   	availableParamBuffers_.pop();
>   	availableStatBuffers_.pop();
> +	availableCaptureParamBuffers_.pop();
>   
>   	/* \todo Remove the dynamic allocation of Info */
>   	std::unique_ptr<Info> info = std::make_unique<Info>();
> @@ -71,7 +84,9 @@ IPU3Frames::Info *IPU3Frames::create(Request *request)
>   	info->rawBuffer = nullptr;
>   	info->paramBuffer = paramBuffer;
>   	info->statBuffer = statBuffer;
> +	info->captureParamBuffer = captureParamBuffer;
>   	info->paramDequeued = false;
> +	info->captureParamDequeued = false;
>   	info->metadataProcessed = false;
>   
>   	frameInfo_[id] = std::move(info);
> @@ -84,6 +99,7 @@ void IPU3Frames::remove(IPU3Frames::Info *info)
>   	/* Return params and stat buffer for reuse. */
>   	availableParamBuffers_.push(info->paramBuffer);
>   	availableStatBuffers_.push(info->statBuffer);
> +	availableCaptureParamBuffers_.push(info->captureParamBuffer);
>   
>   	/* Delete the extended frame information. */
>   	frameInfo_.erase(info->id);
> @@ -102,6 +118,9 @@ bool IPU3Frames::tryComplete(IPU3Frames::Info *info)
>   	if (!info->paramDequeued)
>   		return false;
>   
> +	if (!info->captureParamDequeued)
> +		return false;
> +
>   	remove(info);
>   
>   	bufferAvailable.emit();
> @@ -131,7 +150,7 @@ IPU3Frames::Info *IPU3Frames::find(FrameBuffer *buffer)
>   				return info;
>   
>   		if (info->rawBuffer == buffer || info->paramBuffer == buffer ||
> -		    info->statBuffer == buffer)
> +		    info->statBuffer == buffer || info->captureParamBuffer == buffer)
>   			return info;
>   	}
>   
> diff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h
> index 6e3cb915..8fcb8a14 100644
> --- a/src/libcamera/pipeline/ipu3/frames.h
> +++ b/src/libcamera/pipeline/ipu3/frames.h
> @@ -36,16 +36,20 @@ public:
>   		FrameBuffer *paramBuffer;
>   		FrameBuffer *statBuffer;
>   
> +		FrameBuffer *captureParamBuffer;
> +
>   		ControlList effectiveSensorControls;
>   
>   		bool paramDequeued;
> +		bool captureParamDequeued;
>   		bool metadataProcessed;
>   	};
>   
>   	IPU3Frames();
>   
>   	void init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,
> -		  const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers);
> +		  const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers,
> +		  const std::vector<std::unique_ptr<FrameBuffer>> &captureParamBuffers);
>   	void clear();
>   
>   	Info *create(Request *request);
> @@ -61,6 +65,8 @@ private:
>   	std::queue<FrameBuffer *> availableParamBuffers_;
>   	std::queue<FrameBuffer *> availableStatBuffers_;
>   
> +	std::queue<FrameBuffer *> availableCaptureParamBuffers_;
> +
>   	std::map<unsigned int, std::unique_ptr<Info>> frameInfo_;
>   };
>   
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index e219f704..a201c5ca 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -70,6 +70,7 @@ public:
>   	Stream outStream_;
>   	Stream vfStream_;
>   	Stream rawStream_;
> +	Stream outCaptureStream_;


If there is a outCaptureStream_ now, should we be dropping outStream_ 
and associated buffer allocations for outStream_ ?

My guess is yes, let's see what happens in subsequent patches.

For this one,

Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>

>   
>   	Rectangle cropRegion_;
>   	bool supportsFlips_;
> @@ -696,6 +697,8 @@ int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,
>   		return imgu0_.viewfinder_->exportBuffers(count, buffers);
>   	else if (stream == &data->rawStream_)
>   		return data->cio2_.exportBuffers(count, buffers);
> +	else if (stream == &data->outCaptureStream_)
> +		return imgu1_.output_->exportBuffers(count, buffers);
>   
>   	return -EINVAL;
>   }
> @@ -718,11 +721,17 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera)
>   		data->outStream_.configuration().bufferCount,
>   		data->vfStream_.configuration().bufferCount,
>   		data->rawStream_.configuration().bufferCount,
> +		data->outCaptureStream_.configuration().bufferCount,
>   	});
>   
>   	ret = imgu0_.allocateBuffers(bufferCount);
>   	if (ret < 0)
>   		return ret;
> +	ret = imgu1_.allocateBuffers(bufferCount);
> +	if (ret < 0) {
> +		imgu0_.freeBuffers();
> +		return ret;
> +	}
>   
>   	/* Map buffers to the IPA. */
>   	unsigned int ipaBufferId = 1;
> @@ -737,9 +746,14 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera)
>   		ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());
>   	}
>   
> +	for (const std::unique_ptr<FrameBuffer> &buffer : imgu1_.paramBuffers_) {
> +		buffer->setCookie(ipaBufferId++);
> +		ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());
> +	}
> +
>   	data->ipa_->mapBuffers(ipaBuffers_);
>   
> -	data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_);
> +	data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_, imgu1_.paramBuffers_);
>   	data->frameInfos_.bufferAvailable.connect(
>   		data, &IPU3CameraData::queuePendingRequests);
>   
> @@ -760,6 +774,7 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera)
>   	ipaBuffers_.clear();
>   
>   	imgu0_.freeBuffers();
> +	imgu1_.freeBuffers();
>   
>   	return 0;
>   }
> @@ -1143,6 +1158,7 @@ int PipelineHandlerIPU3::registerCameras()
>   			&data->outStream_,
>   			&data->vfStream_,
>   			&data->rawStream_,
> +			&data->outCaptureStream_,
>   		};
>   		CIO2Device *cio2 = &data->cio2_;
>   
> @@ -1318,6 +1334,8 @@ void IPU3CameraData::paramsBufferReady(unsigned int id)
>   	imgu0_->param_->queueBuffer(info->paramBuffer);
>   	imgu0_->stat_->queueBuffer(info->statBuffer);
>   	imgu0_->input_->queueBuffer(info->rawBuffer);
> +
> +	info->captureParamDequeued = true;
>   }
>   
>   void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)
Harvey Yang Aug. 2, 2022, 10:30 a.m. UTC | #2
Hi Umang,

On Wed, Jul 27, 2022 at 4:41 PM Umang Jain <umang.jain@ideasonboard.com>
wrote:

> Hi Harvey,
>
> On 6/29/22 16:00, Harvey Yang via libcamera-devel wrote:
> > From: Harvey Yang <chenghaoyang@chromium.org>
> >
> > This patch adds the StillCapture stream and imgu1 param buffers.
>
>
> It might be worth to add that we will ignore statistics for still
> capture, as they aren't needed for 3A here, right?
>
>
Exactly, thanks!


> > The following patches will enable imgu1 to handle StillCapture stream
> > specifically, when the imgu0 is needed to handle video/preview streams.
> >
> > Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
> > ---
> >   src/libcamera/pipeline/ipu3/frames.cpp | 23 +++++++++++++++++++++--
> >   src/libcamera/pipeline/ipu3/frames.h   |  8 +++++++-
> >   src/libcamera/pipeline/ipu3/ipu3.cpp   | 20 +++++++++++++++++++-
> >   3 files changed, 47 insertions(+), 4 deletions(-)
> >
> > diff --git a/src/libcamera/pipeline/ipu3/frames.cpp
> b/src/libcamera/pipeline/ipu3/frames.cpp
> > index a4c3477c..f9b705a5 100644
> > --- a/src/libcamera/pipeline/ipu3/frames.cpp
> > +++ b/src/libcamera/pipeline/ipu3/frames.cpp
> > @@ -23,7 +23,8 @@ IPU3Frames::IPU3Frames()
> >   }
> >
> >   void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>>
> &paramBuffers,
> > -                   const std::vector<std::unique_ptr<FrameBuffer>>
> &statBuffers)
> > +                   const std::vector<std::unique_ptr<FrameBuffer>>
> &statBuffers,
> > +                   const std::vector<std::unique_ptr<FrameBuffer>>
> &captureParamBuffers)
> >   {
> >       for (const std::unique_ptr<FrameBuffer> &buffer : paramBuffers)
> >               availableParamBuffers_.push(buffer.get());
> > @@ -31,6 +32,9 @@ void IPU3Frames::init(const
> std::vector<std::unique_ptr<FrameBuffer>> &paramBuff
> >       for (const std::unique_ptr<FrameBuffer> &buffer : statBuffers)
> >               availableStatBuffers_.push(buffer.get());
> >
> > +     for (const std::unique_ptr<FrameBuffer> &buffer :
> captureParamBuffers)
> > +             availableCaptureParamBuffers_.push(buffer.get());
> > +
> >       frameInfo_.clear();
> >   }
> >
> > @@ -38,6 +42,7 @@ void IPU3Frames::clear()
> >   {
> >       availableParamBuffers_ = {};
>
>
> alternatively should we rename this to, availableVfParamBuffers_ to mark
> the distinction?
>
>
I'm not sure if "availableVfParamBuffers_" describes it better though...
It'll be used as ImgU0's param buffers, and ImgU0 is used for video
streams. It might not always be used for preview, especially when a JPEG
stream is not requested. IIUC "viewfinder" is mostly describing the
"preview" stream, right? (Although Han-lin told me that the viewfinder node
in ImgU might be more powerful, in terms of field of view, than the output
node, which confuses me a lot)



> >       availableStatBuffers_ = {};
> > +     availableCaptureParamBuffers_ = {};
> >   }
> >
> >   IPU3Frames::Info *IPU3Frames::create(Request *request)
> > @@ -54,14 +59,22 @@ IPU3Frames::Info *IPU3Frames::create(Request
> *request)
> >               return nullptr;
> >       }
> >
> > +     if (availableCaptureParamBuffers_.empty()) {
> > +             LOG(IPU3, Debug) << "Capture parameters buffer underrun";
> > +             return nullptr;
> > +     }
> > +
> >       FrameBuffer *paramBuffer = availableParamBuffers_.front();
>
>
> Ties into the earlier comment, maybe vfParamBuffer ? ... and so on below..
>
>
ditto


> >       FrameBuffer *statBuffer = availableStatBuffers_.front();
> > +     FrameBuffer *captureParamBuffer =
> availableCaptureParamBuffers_.front();
> >
> >       paramBuffer->_d()->setRequest(request);
> >       statBuffer->_d()->setRequest(request);
> > +     captureParamBuffer->_d()->setRequest(request);
> >
> >       availableParamBuffers_.pop();
> >       availableStatBuffers_.pop();
> > +     availableCaptureParamBuffers_.pop();
> >
> >       /* \todo Remove the dynamic allocation of Info */
> >       std::unique_ptr<Info> info = std::make_unique<Info>();
> > @@ -71,7 +84,9 @@ IPU3Frames::Info *IPU3Frames::create(Request *request)
> >       info->rawBuffer = nullptr;
> >       info->paramBuffer = paramBuffer;
> >       info->statBuffer = statBuffer;
> > +     info->captureParamBuffer = captureParamBuffer;
> >       info->paramDequeued = false;
> > +     info->captureParamDequeued = false;
> >       info->metadataProcessed = false;
> >
> >       frameInfo_[id] = std::move(info);
> > @@ -84,6 +99,7 @@ void IPU3Frames::remove(IPU3Frames::Info *info)
> >       /* Return params and stat buffer for reuse. */
> >       availableParamBuffers_.push(info->paramBuffer);
> >       availableStatBuffers_.push(info->statBuffer);
> > +     availableCaptureParamBuffers_.push(info->captureParamBuffer);
> >
> >       /* Delete the extended frame information. */
> >       frameInfo_.erase(info->id);
> > @@ -102,6 +118,9 @@ bool IPU3Frames::tryComplete(IPU3Frames::Info *info)
> >       if (!info->paramDequeued)
> >               return false;
> >
> > +     if (!info->captureParamDequeued)
> > +             return false;
> > +
> >       remove(info);
> >
> >       bufferAvailable.emit();
> > @@ -131,7 +150,7 @@ IPU3Frames::Info *IPU3Frames::find(FrameBuffer
> *buffer)
> >                               return info;
> >
> >               if (info->rawBuffer == buffer || info->paramBuffer ==
> buffer ||
> > -                 info->statBuffer == buffer)
> > +                 info->statBuffer == buffer || info->captureParamBuffer
> == buffer)
> >                       return info;
> >       }
> >
> > diff --git a/src/libcamera/pipeline/ipu3/frames.h
> b/src/libcamera/pipeline/ipu3/frames.h
> > index 6e3cb915..8fcb8a14 100644
> > --- a/src/libcamera/pipeline/ipu3/frames.h
> > +++ b/src/libcamera/pipeline/ipu3/frames.h
> > @@ -36,16 +36,20 @@ public:
> >               FrameBuffer *paramBuffer;
> >               FrameBuffer *statBuffer;
> >
> > +             FrameBuffer *captureParamBuffer;
> > +
> >               ControlList effectiveSensorControls;
> >
> >               bool paramDequeued;
> > +             bool captureParamDequeued;
> >               bool metadataProcessed;
> >       };
> >
> >       IPU3Frames();
> >
> >       void init(const std::vector<std::unique_ptr<FrameBuffer>>
> &paramBuffers,
> > -               const std::vector<std::unique_ptr<FrameBuffer>>
> &statBuffers);
> > +               const std::vector<std::unique_ptr<FrameBuffer>>
> &statBuffers,
> > +               const std::vector<std::unique_ptr<FrameBuffer>>
> &captureParamBuffers);
> >       void clear();
> >
> >       Info *create(Request *request);
> > @@ -61,6 +65,8 @@ private:
> >       std::queue<FrameBuffer *> availableParamBuffers_;
> >       std::queue<FrameBuffer *> availableStatBuffers_;
> >
> > +     std::queue<FrameBuffer *> availableCaptureParamBuffers_;
> > +
> >       std::map<unsigned int, std::unique_ptr<Info>> frameInfo_;
> >   };
> >
> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp
> b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > index e219f704..a201c5ca 100644
> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > @@ -70,6 +70,7 @@ public:
> >       Stream outStream_;
> >       Stream vfStream_;
> >       Stream rawStream_;
> > +     Stream outCaptureStream_;
>
>
> If there is a outCaptureStream_ now, should we be dropping outStream_
> and associated buffer allocations for outStream_ ?
>
> My guess is yes, let's see what happens in subsequent patches.
>
> For this one,
>
>
So |outStream_| is still in use with |outCaptureStream_| available, as it's
still the main output stream of ImgU0 (ipu3.cpp: line 380).
Unless you're suggesting that when a JPEG stream is requested, there's at
most one video stream requested (which is likely used as the Preview), and
it should be supported by ImgU0's viewfinder node.
However, The Android LIMIT-level guaranteed configuration already has a
use-case that supports two YUV/video streams and a JPEG stream [1], not to
mention the FULL-level.

[1]:
https://developer.android.com/reference/android/hardware/camera2/CameraDevice#regular-capture


> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
>
> >
> >       Rectangle cropRegion_;
> >       bool supportsFlips_;
> > @@ -696,6 +697,8 @@ int PipelineHandlerIPU3::exportFrameBuffers(Camera
> *camera, Stream *stream,
> >               return imgu0_.viewfinder_->exportBuffers(count, buffers);
> >       else if (stream == &data->rawStream_)
> >               return data->cio2_.exportBuffers(count, buffers);
> > +     else if (stream == &data->outCaptureStream_)
> > +             return imgu1_.output_->exportBuffers(count, buffers);
> >
> >       return -EINVAL;
> >   }
> > @@ -718,11 +721,17 @@ int PipelineHandlerIPU3::allocateBuffers(Camera
> *camera)
> >               data->outStream_.configuration().bufferCount,
> >               data->vfStream_.configuration().bufferCount,
> >               data->rawStream_.configuration().bufferCount,
> > +             data->outCaptureStream_.configuration().bufferCount,
> >       });
> >
> >       ret = imgu0_.allocateBuffers(bufferCount);
> >       if (ret < 0)
> >               return ret;
> > +     ret = imgu1_.allocateBuffers(bufferCount);
> > +     if (ret < 0) {
> > +             imgu0_.freeBuffers();
> > +             return ret;
> > +     }
> >
> >       /* Map buffers to the IPA. */
> >       unsigned int ipaBufferId = 1;
> > @@ -737,9 +746,14 @@ int PipelineHandlerIPU3::allocateBuffers(Camera
> *camera)
> >               ipaBuffers_.emplace_back(buffer->cookie(),
> buffer->planes());
> >       }
> >
> > +     for (const std::unique_ptr<FrameBuffer> &buffer :
> imgu1_.paramBuffers_) {
> > +             buffer->setCookie(ipaBufferId++);
> > +             ipaBuffers_.emplace_back(buffer->cookie(),
> buffer->planes());
> > +     }
> > +
> >       data->ipa_->mapBuffers(ipaBuffers_);
> >
> > -     data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_);
> > +     data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_,
> imgu1_.paramBuffers_);
> >       data->frameInfos_.bufferAvailable.connect(
> >               data, &IPU3CameraData::queuePendingRequests);
> >
> > @@ -760,6 +774,7 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera)
> >       ipaBuffers_.clear();
> >
> >       imgu0_.freeBuffers();
> > +     imgu1_.freeBuffers();
> >
> >       return 0;
> >   }
> > @@ -1143,6 +1158,7 @@ int PipelineHandlerIPU3::registerCameras()
> >                       &data->outStream_,
> >                       &data->vfStream_,
> >                       &data->rawStream_,
> > +                     &data->outCaptureStream_,
> >               };
> >               CIO2Device *cio2 = &data->cio2_;
> >
> > @@ -1318,6 +1334,8 @@ void IPU3CameraData::paramsBufferReady(unsigned
> int id)
> >       imgu0_->param_->queueBuffer(info->paramBuffer);
> >       imgu0_->stat_->queueBuffer(info->statBuffer);
> >       imgu0_->input_->queueBuffer(info->rawBuffer);
> > +
> > +     info->captureParamDequeued = true;
> >   }
> >
> >   void IPU3CameraData::metadataReady(unsigned int id, const ControlList
> &metadata)
>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp
index a4c3477c..f9b705a5 100644
--- a/src/libcamera/pipeline/ipu3/frames.cpp
+++ b/src/libcamera/pipeline/ipu3/frames.cpp
@@ -23,7 +23,8 @@  IPU3Frames::IPU3Frames()
 }
 
 void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,
-		      const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers)
+		      const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers,
+		      const std::vector<std::unique_ptr<FrameBuffer>> &captureParamBuffers)
 {
 	for (const std::unique_ptr<FrameBuffer> &buffer : paramBuffers)
 		availableParamBuffers_.push(buffer.get());
@@ -31,6 +32,9 @@  void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuff
 	for (const std::unique_ptr<FrameBuffer> &buffer : statBuffers)
 		availableStatBuffers_.push(buffer.get());
 
+	for (const std::unique_ptr<FrameBuffer> &buffer : captureParamBuffers)
+		availableCaptureParamBuffers_.push(buffer.get());
+
 	frameInfo_.clear();
 }
 
@@ -38,6 +42,7 @@  void IPU3Frames::clear()
 {
 	availableParamBuffers_ = {};
 	availableStatBuffers_ = {};
+	availableCaptureParamBuffers_ = {};
 }
 
 IPU3Frames::Info *IPU3Frames::create(Request *request)
@@ -54,14 +59,22 @@  IPU3Frames::Info *IPU3Frames::create(Request *request)
 		return nullptr;
 	}
 
+	if (availableCaptureParamBuffers_.empty()) {
+		LOG(IPU3, Debug) << "Capture parameters buffer underrun";
+		return nullptr;
+	}
+
 	FrameBuffer *paramBuffer = availableParamBuffers_.front();
 	FrameBuffer *statBuffer = availableStatBuffers_.front();
+	FrameBuffer *captureParamBuffer = availableCaptureParamBuffers_.front();
 
 	paramBuffer->_d()->setRequest(request);
 	statBuffer->_d()->setRequest(request);
+	captureParamBuffer->_d()->setRequest(request);
 
 	availableParamBuffers_.pop();
 	availableStatBuffers_.pop();
+	availableCaptureParamBuffers_.pop();
 
 	/* \todo Remove the dynamic allocation of Info */
 	std::unique_ptr<Info> info = std::make_unique<Info>();
@@ -71,7 +84,9 @@  IPU3Frames::Info *IPU3Frames::create(Request *request)
 	info->rawBuffer = nullptr;
 	info->paramBuffer = paramBuffer;
 	info->statBuffer = statBuffer;
+	info->captureParamBuffer = captureParamBuffer;
 	info->paramDequeued = false;
+	info->captureParamDequeued = false;
 	info->metadataProcessed = false;
 
 	frameInfo_[id] = std::move(info);
@@ -84,6 +99,7 @@  void IPU3Frames::remove(IPU3Frames::Info *info)
 	/* Return params and stat buffer for reuse. */
 	availableParamBuffers_.push(info->paramBuffer);
 	availableStatBuffers_.push(info->statBuffer);
+	availableCaptureParamBuffers_.push(info->captureParamBuffer);
 
 	/* Delete the extended frame information. */
 	frameInfo_.erase(info->id);
@@ -102,6 +118,9 @@  bool IPU3Frames::tryComplete(IPU3Frames::Info *info)
 	if (!info->paramDequeued)
 		return false;
 
+	if (!info->captureParamDequeued)
+		return false;
+
 	remove(info);
 
 	bufferAvailable.emit();
@@ -131,7 +150,7 @@  IPU3Frames::Info *IPU3Frames::find(FrameBuffer *buffer)
 				return info;
 
 		if (info->rawBuffer == buffer || info->paramBuffer == buffer ||
-		    info->statBuffer == buffer)
+		    info->statBuffer == buffer || info->captureParamBuffer == buffer)
 			return info;
 	}
 
diff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h
index 6e3cb915..8fcb8a14 100644
--- a/src/libcamera/pipeline/ipu3/frames.h
+++ b/src/libcamera/pipeline/ipu3/frames.h
@@ -36,16 +36,20 @@  public:
 		FrameBuffer *paramBuffer;
 		FrameBuffer *statBuffer;
 
+		FrameBuffer *captureParamBuffer;
+
 		ControlList effectiveSensorControls;
 
 		bool paramDequeued;
+		bool captureParamDequeued;
 		bool metadataProcessed;
 	};
 
 	IPU3Frames();
 
 	void init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,
-		  const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers);
+		  const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers,
+		  const std::vector<std::unique_ptr<FrameBuffer>> &captureParamBuffers);
 	void clear();
 
 	Info *create(Request *request);
@@ -61,6 +65,8 @@  private:
 	std::queue<FrameBuffer *> availableParamBuffers_;
 	std::queue<FrameBuffer *> availableStatBuffers_;
 
+	std::queue<FrameBuffer *> availableCaptureParamBuffers_;
+
 	std::map<unsigned int, std::unique_ptr<Info>> frameInfo_;
 };
 
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index e219f704..a201c5ca 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -70,6 +70,7 @@  public:
 	Stream outStream_;
 	Stream vfStream_;
 	Stream rawStream_;
+	Stream outCaptureStream_;
 
 	Rectangle cropRegion_;
 	bool supportsFlips_;
@@ -696,6 +697,8 @@  int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,
 		return imgu0_.viewfinder_->exportBuffers(count, buffers);
 	else if (stream == &data->rawStream_)
 		return data->cio2_.exportBuffers(count, buffers);
+	else if (stream == &data->outCaptureStream_)
+		return imgu1_.output_->exportBuffers(count, buffers);
 
 	return -EINVAL;
 }
@@ -718,11 +721,17 @@  int PipelineHandlerIPU3::allocateBuffers(Camera *camera)
 		data->outStream_.configuration().bufferCount,
 		data->vfStream_.configuration().bufferCount,
 		data->rawStream_.configuration().bufferCount,
+		data->outCaptureStream_.configuration().bufferCount,
 	});
 
 	ret = imgu0_.allocateBuffers(bufferCount);
 	if (ret < 0)
 		return ret;
+	ret = imgu1_.allocateBuffers(bufferCount);
+	if (ret < 0) {
+		imgu0_.freeBuffers();
+		return ret;
+	}
 
 	/* Map buffers to the IPA. */
 	unsigned int ipaBufferId = 1;
@@ -737,9 +746,14 @@  int PipelineHandlerIPU3::allocateBuffers(Camera *camera)
 		ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());
 	}
 
+	for (const std::unique_ptr<FrameBuffer> &buffer : imgu1_.paramBuffers_) {
+		buffer->setCookie(ipaBufferId++);
+		ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());
+	}
+
 	data->ipa_->mapBuffers(ipaBuffers_);
 
-	data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_);
+	data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_, imgu1_.paramBuffers_);
 	data->frameInfos_.bufferAvailable.connect(
 		data, &IPU3CameraData::queuePendingRequests);
 
@@ -760,6 +774,7 @@  int PipelineHandlerIPU3::freeBuffers(Camera *camera)
 	ipaBuffers_.clear();
 
 	imgu0_.freeBuffers();
+	imgu1_.freeBuffers();
 
 	return 0;
 }
@@ -1143,6 +1158,7 @@  int PipelineHandlerIPU3::registerCameras()
 			&data->outStream_,
 			&data->vfStream_,
 			&data->rawStream_,
+			&data->outCaptureStream_,
 		};
 		CIO2Device *cio2 = &data->cio2_;
 
@@ -1318,6 +1334,8 @@  void IPU3CameraData::paramsBufferReady(unsigned int id)
 	imgu0_->param_->queueBuffer(info->paramBuffer);
 	imgu0_->stat_->queueBuffer(info->statBuffer);
 	imgu0_->input_->queueBuffer(info->rawBuffer);
+
+	info->captureParamDequeued = true;
 }
 
 void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)