[libcamera-devel] [PATCH] libcamera: pipeline: rkisp1: Avoid race when processing parameter buffers
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Tue Jan 19 17:28:42 CET 2021
Hi Niklas,
Thank you for the patch.
On Mon, Jan 18, 2021 at 03:06:15PM +0100, Niklas Söderlund wrote:
> When moving the pipeline away from the Timeline design it was discovered
> that the design of queuing the buffers to the device as soon as possible
> was not the best idea. The parameter buffers where queued to the device
> before the IPA had processed them and this violates the V4L2 API.
>
> Fix this by waiting to queue any buffer to the device until the IPA have
> filled in the parameters buffer.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
> ---
> Hello,
>
> This patch is based on-top of '[PATCH v5 0/8] libcamera: Add helper for
> controls that take effect with a delay' as the change is much cleaner
> on-top of the removal of the Timeline.
It should probably be squashed in the appropriate patch from that
series.
> ---
> src/libcamera/pipeline/rkisp1/rkisp1.cpp | 41 ++++++++----------------
> 1 file changed, 13 insertions(+), 28 deletions(-)
>
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index 58ae8f98a5c683d5..e85979a719b7ced6 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -51,7 +51,6 @@ struct RkISP1FrameInfo {
> FrameBuffer *mainPathBuffer;
> FrameBuffer *selfPathBuffer;
>
> - bool paramFilled;
> bool paramDequeued;
> bool metadataProcessed;
> };
> @@ -219,7 +218,6 @@ RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *req
> info->mainPathBuffer = mainPathBuffer;
> info->selfPathBuffer = selfPathBuffer;
> info->statBuffer = statBuffer;
> - info->paramFilled = false;
> info->paramDequeued = false;
> info->metadataProcessed = false;
>
> @@ -322,9 +320,20 @@ void RkISP1CameraData::queueFrameAction(unsigned int frame,
> break;
> }
> case RKISP1_IPA_ACTION_PARAM_FILLED: {
> + PipelineHandlerRkISP1 *pipe = static_cast<PipelineHandlerRkISP1 *>(pipe_);
> RkISP1FrameInfo *info = frameInfo_.find(frame);
> - if (info)
> - info->paramFilled = true;
> + if (!info)
> + break;
> +
> + pipe->param_->queueBuffer(info->paramBuffer);
> + pipe->stat_->queueBuffer(info->statBuffer);
> +
> + if (info->mainPathBuffer)
> + mainPath_->queueBuffer(info->mainPathBuffer);
> +
> + if (info->selfPathBuffer)
> + selfPath_->queueBuffer(info->selfPathBuffer);
> +
The IPA generates RKISP1_IPA_ACTION_PARAM_FILLED when the request is
queued to the IPA, so the buffers will be queued early to the driver,
ensuring we won't have a queue underrun.
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
However, this means that the IPA will fill the parameters buffer with
data that is based on much earlier frames. We'll need to find a proper
middleground here, waiting as long as possible before asking the IPA for
parameters, but not too long to ensure we won't get underruns.
> break;
> }
> case RKISP1_IPA_ACTION_METADATA:
> @@ -852,15 +861,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request)
> op.controls = { request->controls() };
> data->ipa_->processEvent(op);
>
> - param_->queueBuffer(info->paramBuffer);
> - stat_->queueBuffer(info->statBuffer);
> -
> - if (info->mainPathBuffer)
> - mainPath_.queueBuffer(info->mainPathBuffer);
> -
> - if (info->selfPathBuffer)
> - selfPath_.queueBuffer(info->selfPathBuffer);
> -
> data->frame_++;
>
> return 0;
> @@ -1009,7 +1009,6 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
> mainPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady);
> selfPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady);
> stat_->bufferReady.connect(this, &PipelineHandlerRkISP1::statReady);
> - isp_->frameStart.connect(this, &PipelineHandlerRkISP1::frameStart);
> param_->bufferReady.connect(this, &PipelineHandlerRkISP1::paramReady);
>
> /*
> @@ -1097,20 +1096,6 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer)
> data->ipa_->processEvent(op);
> }
>
> -void PipelineHandlerRkISP1::frameStart(uint32_t sequence)
> -{
> - if (!activeCamera_)
> - return;
> -
> - RkISP1CameraData *data = cameraData(activeCamera_);
> -
> - RkISP1FrameInfo *info = data->frameInfo_.find(sequence);
> - if (!info || !info->paramFilled)
> - LOG(RkISP1, Info)
> - << "Parameters not ready on time for frame "
> - << sequence;
> -}
> -
> REGISTER_PIPELINE_HANDLER(PipelineHandlerRkISP1)
>
> } /* namespace libcamera */
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list