[libcamera-devel] [PATCH v3 4/8] libcamera: ipu3: Add multiple stream memory management

Niklas Söderlund niklas.soderlund at ragnatech.se
Fri Apr 5 13:30:00 CEST 2019


Hi Jacopo,

Thanks for your work.

On 2019-04-03 17:07:31 +0200, Jacopo Mondi wrote:
> Perform allocation and setup of memory sharing betweent the CIO2 output
> and the ImgU input and allocate memory for each active stream.
> ---
>  src/libcamera/pipeline/ipu3/ipu3.cpp | 78 ++++++++++++++++++++++------
>  1 file changed, 62 insertions(+), 16 deletions(-)
> 
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index a12e3f9a496d..f7e75fac1dfe 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -91,6 +91,7 @@ public:
>  
>  	BufferPool vfPool_;
>  	BufferPool statPool_;
> +	BufferPool outPool_;
>  };
>  
>  class CIO2Device
> @@ -428,13 +429,21 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,
>  	return 0;
>  }
>  
> +/**
> + * \todo Clarify if 'viewfinder' and 'stat' nodes have to be set up and
> + * started even if not in use. As of now, if not properly configured and
> + * enabled, the ImgU processing pipeline stalls.
> + *
> + * In order to be able to start the 'viewfinder' and 'stat' nodes, we need
> + * memory to be reserved.
> + */
>  int PipelineHandlerIPU3::allocateBuffers(Camera *camera,
>  					 const std::set<Stream *> &streams)
>  {
>  	IPU3CameraData *data = cameraData(camera);
> -	Stream *stream = *streams.begin();
>  	CIO2Device *cio2 = &data->cio2_;
>  	ImgUDevice *imgu = data->imgu_;
> +	unsigned int bufferCount;
>  	int ret;
>  
>  	/* Share buffers between CIO2 output and ImgU input. */
> @@ -446,28 +455,64 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera,
>  	if (ret)
>  		return ret;
>  
> -	/* Export ImgU output buffers to the stream's pool. */
> -	ret = imgu->exportBuffers(&imgu->output_, &stream->bufferPool());
> -	if (ret)
> -		return ret;
> -
>  	/*
> -	 * Reserve memory in viewfinder and stat output devices. Use the
> -	 * same number of buffers as the ones requested for the output
> -	 * stream.
> +	 * Use for internal pools the same buffer number as the input
> +	 * one: it should match the pipeline lenght.
>  	 */
> -	unsigned int bufferCount = stream->bufferPool().count();
> -
> -	imgu->viewfinder_.pool->createBuffers(bufferCount);
> -	ret = imgu->exportBuffers(&imgu->viewfinder_, imgu->viewfinder_.pool);
> -	if (ret)
> -		return ret;
> -
> +	bufferCount = pool->count();
>  	imgu->stat_.pool->createBuffers(bufferCount);
>  	ret = imgu->exportBuffers(&imgu->stat_, imgu->stat_.pool);
>  	if (ret)
>  		return ret;
>  
> +	for (Stream *stream : streams) {
> +		if (isOutput(data, stream)) {
> +			/* Export output buffers to the stream's pool. */
> +			ret = imgu->exportBuffers(&imgu->output_,
> +						  &stream->bufferPool());
> +			if (ret)
> +				return ret;
> +
> +			if (isViewfinderActive(data))
> +				continue;
> +
> +			/*
> +			 * Reserve memory in viewfinder device if it is not
> +			 * part of the active streams list. Use the same
> +			 * number of buffers as the ones requested for the
> +			 * output stream.
> +			 */
> +			bufferCount = stream->bufferPool().count();
> +			imgu->viewfinder_.pool->createBuffers(bufferCount);
> +			ret = imgu->exportBuffers(&imgu->viewfinder_,
> +						  imgu->viewfinder_.pool);
> +			if (ret)
> +				return ret;
> +		} else if (isViewfinder(data, stream)) {
> +			/* Export viewfinder buffers to the stream's pool. */
> +			ret = imgu->exportBuffers(&imgu->viewfinder_,
> +						  &stream->bufferPool());
> +			if (ret)
> +				return ret;
> +
> +			if (isOutputActive(data))
> +				continue;
> +
> +			/*
> +			 * Reserve memory in output device if it is not part
> +			 * of the active streams list. Use the same number
> +			 * of buffers as the ones requested for the viewfinder
> +			 * stream.
> +			 */
> +			bufferCount = stream->bufferPool().count();
> +			imgu->output_.pool->createBuffers(bufferCount);
> +			ret = imgu->exportBuffers(&imgu->output_,
> +						  imgu->output_.pool);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +

This change looks ok to me but I wonder about the error path here. What 
happens if exportBuffers fails for the second stream? I'm only curious 
:-)

>  	return 0;
>  }
>  
> @@ -819,6 +864,7 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index)
>  
>  	output_.pad = PAD_OUTPUT;
>  	output_.name = "output";
> +	output_.pool = &outPool_;
>  
>  	viewfinder_.dev = V4L2Device::fromEntityName(media,
>  						     name_ + " viewfinder");
> -- 
> 2.21.0
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

-- 
Regards,
Niklas Söderlund


More information about the libcamera-devel mailing list