[PATCH] libcamera: rkisp1: Only connect delayed controls at start/stop

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Feb 14 01:09:48 CET 2025


Hi Kieran,

Thank you for the patch.

On Fri, Feb 07, 2025 at 01:37:43PM +0000, Kieran Bingham wrote:
> The RKISP1 path may potentially have multiple cameras connected through
> complex pipelines such as video multiplexors or multiple FPGA paths.
> 
> The RKISP1 pipeline handler notifies DelayedControls that a new frame is
> commencing by using the frameStart event on the ISP and using that to
> signal to DelayedControls that it is time to process the controls for
> the next frame.
> 
> When more than one camera is connected to an ISP it is important not to
> signal events to an inactive Camera.
> 
> Move the frameStart signal connection from CreateCamera() to start() and
> introduce a corresponding disconnect at stop().
> 
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> ---
> 
> When developing on an i.MX8MP, with multiple cameras connected to a
> single ISP this caused a horrible bug which I eventually found using
> UBSAN/ASAN to spot that actaully there was a use-after-free in calling
> delayedControls on a camera object that wasn't active.

I've been pondering about requiring the receiver of a signal to inherit
from the Object class. That would solve this kind of issues.

> One other alternative here, could be to move the connection of the
> signal into the setFrameStartEnabled() call, if we pass in the
> CameraData to be explicit on where we are connecting and disconnect. But
> maybe that's overkill too.

Conceptually, the isp_->frameStart signal is emitted by a resource
shared by multiple cameras. It would make sense to model this with a
slot in the PipelineHandlerRkISP1 class instead of the RkISP1CameraData
class, and relay it to the delayed controls class through activeCamera_.
Would that be a better model ?

>  src/libcamera/pipeline/rkisp1/rkisp1.cpp | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index 1ac8d8ae7ed9..b1b0bde7fd00 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -1071,6 +1071,11 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL
>  	utils::ScopeExitActions actions;
>  	int ret;
>  
> +	isp_->frameStart.connect(data->delayedCtrls_.get(),
> +				 &DelayedControls::applyControls);
> +
> +	actions += [&]() { isp_->frameStart.disconnect(data->delayedCtrls_.get()); };
> +
>  	/* Allocate buffers for internal pipeline usage. */
>  	ret = allocateBuffers(camera);
>  	if (ret)
> @@ -1142,6 +1147,8 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera)
>  
>  	isp_->setFrameStartEnabled(false);
>  
> +	isp_->frameStart.disconnect(data->delayedCtrls_.get());
> +
>  	data->ipa_->stop();
>  
>  	if (hasSelfPath_)
> @@ -1330,8 +1337,6 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)
>  	data->delayedCtrls_ =
>  		std::make_unique<DelayedControls>(data->sensor_->device(),
>  						  params);
> -	isp_->frameStart.connect(data->delayedCtrls_.get(),
> -				 &DelayedControls::applyControls);
>  
>  	ret = data->loadIPA(media_->hwRevision());
>  	if (ret)

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list