[libcamera-devel] [PATCH v3 9/9] ipu3: Fixes frame delay
Umang Jain
umang.jain at ideasonboard.com
Wed Jul 27 15:24:59 CEST 2022
Hello,
On 6/29/22 16:00, Harvey Yang via libcamera-devel wrote:
> Like the shipped ipu3 HAL, handle the frame delay with one extra input,
Can you point to the shipped ipu3 HAL frame delay handling code here for
reference?
> needed for the first frame and StillCapture's non-sequential frame
> requests.
>
> Signed-off-by: Harvey Yang <chenghaoyang at chromium.org>
> ---
> src/libcamera/pipeline/ipu3/ipu3.cpp | 73 +++++++++++++++++++++++-----
> 1 file changed, 62 insertions(+), 11 deletions(-)
>
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index e26c2736..8689cf8b 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -90,6 +90,9 @@ public:
>
> ControlInfoMap ipaControls_;
>
> + bool firstRequest_ = true;
> + int lastRequestSequence_ = -1;
this is only used under hasCapture so maybe lastCaptureRequestSeq_ is
more appropriate?
> +
> private:
> void metadataReady(unsigned int id, const ControlList &metadata);
> void paramsBufferReady(unsigned int id);
> @@ -565,6 +568,9 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
> CIO2Device *cio2 = &data->cio2_;
> V4L2DeviceFormat outputFormat;
>
> + data->firstRequest_ = true;
> + data->lastRequestSequence_ = -1;
> +
Does this needs to be reset on every start()/stop() cycles?
> ImgUDevice::PipeConfig imguConfig1 = config->imguConfig1();
> useImgu1_ = !imguConfig1.isNull();
>
> @@ -1427,6 +1433,11 @@ void IPU3CameraData::paramsBufferReady(unsigned int id)
> if (!info)
> return;
>
> + int yuvCount = firstRequest_ ? 2 : 1;
> + int stillCount = firstRequest_ || (lastRequestSequence_ + 1) != static_cast<int>(info->request->sequence()) ? 2 : 1;
> +
This is getting a bit non-trivial to follow. Can you probably include a
brief comment here to explain some rationale?
As per my understanding, if the lastRequestSequence_ was a StillCapture,
stillCount will be 1 for current request capture, and it will 2 for all
other cases?
We need stillCount to be 2 (usually) because .... ?
> + firstRequest_ = false;
> +
> bool hasYuv = false;
> bool hasCapture = false;
> /* Queue all buffers from the request aimed for the ImgU. */
> @@ -1436,33 +1447,53 @@ void IPU3CameraData::paramsBufferReady(unsigned int id)
>
> if (stream == &outStream_) {
> hasYuv = true;
> - imgu0_->output_->queueBuffer(outbuffer);
> +
> + for (int i = 0; i < yuvCount; ++i) {
> + bufferReturnCounters[outbuffer] += 1;
> + imgu0_->output_->queueBuffer(outbuffer);
Have you checked / discussed what happens if you re-queue the same
buffer on videodevice twice (before even dequeuing it)? I am not sure,
because the current documentation doesn't specify this case I think.
I've asked around.
> + }
> } else if (stream == &vfStream_) {
> hasYuv = true;
> - imgu0_->viewfinder_->queueBuffer(outbuffer);
> +
> + for (int i = 0; i < yuvCount; ++i) {
> + bufferReturnCounters[outbuffer] += 1;
> + imgu0_->viewfinder_->queueBuffer(outbuffer);
> + }
> } else if (stream == &outCaptureStream_) {
> hasCapture = true;
>
> - imgu1_->output_->queueBuffer(outbuffer);
> + for (int i = 0; i < stillCount; ++i) {
> + bufferReturnCounters[outbuffer] += 1;
> + imgu1_->output_->queueBuffer(outbuffer);
> + }
> }
> }
>
> if (hasYuv) {
> - bufferReturnCounters[info->rawBuffer] += 1;
> -
> - imgu0_->param_->queueBuffer(info->paramBuffer);
> - imgu0_->stat_->queueBuffer(info->statBuffer);
> - imgu0_->input_->queueBuffer(info->rawBuffer);
> + for (int i = 0; i < yuvCount; ++i) {
> + bufferReturnCounters[info->paramBuffer] += 1;
> + bufferReturnCounters[info->statBuffer] += 1;
> + bufferReturnCounters[info->rawBuffer] += 1;
> +
> + imgu0_->param_->queueBuffer(info->paramBuffer);
> + imgu0_->stat_->queueBuffer(info->statBuffer);
> + imgu0_->input_->queueBuffer(info->rawBuffer);
> + }
> } else {
> info->paramDequeued = true;
> info->metadataProcessed = true;
> }
>
> if (hasCapture) {
> - bufferReturnCounters[info->rawBuffer] += 1;
> + lastRequestSequence_ = info->request->sequence();
>
> - imgu1_->param_->queueBuffer(info->captureParamBuffer);
> - imgu1_->input_->queueBuffer(info->rawBuffer);
> + for (int i = 0; i < stillCount; ++i) {
> + bufferReturnCounters[info->captureParamBuffer] += 1;
> + bufferReturnCounters[info->rawBuffer] += 1;
> +
> + imgu1_->param_->queueBuffer(info->captureParamBuffer);
> + imgu1_->input_->queueBuffer(info->rawBuffer);
> + }
> } else {
> info->captureParamDequeued = true;
> }
> @@ -1503,6 +1534,11 @@ void IPU3CameraData::tryReturnBuffer(FrameBuffer *buffer)
> */
> void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
> {
> + if (--bufferReturnCounters[buffer] > 0)
> + return;
> +
> + bufferReturnCounters.erase(buffer);
> +
> IPU3Frames::Info *info = frameInfos_.find(buffer);
> if (!info)
> return;
> @@ -1569,6 +1605,11 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
>
> void IPU3CameraData::paramBufferReady(FrameBuffer *buffer)
> {
> + if (--bufferReturnCounters[buffer] > 0)
> + return;
> +
> + bufferReturnCounters.erase(buffer);
> +
> IPU3Frames::Info *info = frameInfos_.find(buffer);
> if (!info)
> return;
> @@ -1589,6 +1630,11 @@ void IPU3CameraData::paramBufferReady(FrameBuffer *buffer)
>
> void IPU3CameraData::captureParamBufferReady(FrameBuffer *buffer)
> {
> + if (--bufferReturnCounters[buffer] > 0)
> + return;
> +
> + bufferReturnCounters.erase(buffer);
> +
> IPU3Frames::Info *info = frameInfos_.find(buffer);
> if (!info)
> return;
> @@ -1609,6 +1655,11 @@ void IPU3CameraData::captureParamBufferReady(FrameBuffer *buffer)
>
> void IPU3CameraData::statBufferReady(FrameBuffer *buffer)
> {
> + if (--bufferReturnCounters[buffer] > 0)
> + return;
> +
> + bufferReturnCounters.erase(buffer);
> +
> IPU3Frames::Info *info = frameInfos_.find(buffer);
> if (!info)
> return;
More information about the libcamera-devel
mailing list