[libcamera-devel] [PATCH v8 02/17] libcamera: framebuffer_allocator: Make allocate() require count

Paul Elder paul.elder at ideasonboard.com
Wed Nov 30 12:19:16 CET 2022


On Tue, Aug 24, 2021 at 04:56:21PM -0300, Nícolas F. R. A. Prado wrote:
> Make FrameBufferAllocator::allocate() require a 'count' argument for the
> number of buffers to be allocated.
> 
> Signed-off-by: Nícolas F. R. A. Prado <nfraprado at collabora.com>
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>

> 
> ---
> 
> Changes in v8:
> - Updated application-developer and pipeline-handler guides with new allocate()
>   API and MinimumRequests property
> - Added handling for when allocate() returns less buffers than needed in cam and
>   the capture unit test
> - Improved FrameBufferAllocator::allocate() description
> 
> Changes in v6:
> - Changed static_cast to convert 'count' to unsigned int instead of
>   'bufferCount' to int when comparing
> 
> Changes in v5:
> - Made sure that qcam allocates at least 2 buffers
> 
>  Documentation/guides/application-developer.rst     |  9 +++++++--
>  Documentation/guides/pipeline-handler.rst          |  3 +--
>  include/libcamera/camera.h                         |  2 +-
>  include/libcamera/framebuffer_allocator.h          |  2 +-
>  include/libcamera/internal/pipeline_handler.h      |  2 +-
>  src/android/camera_stream.cpp                      |  5 ++++-
>  src/cam/camera_session.cpp                         | 12 ++++++++----
>  src/gstreamer/gstlibcameraallocator.cpp            |  4 +++-
>  src/lc-compliance/simple_capture.cpp               |  7 +++++--
>  src/libcamera/camera.cpp                           |  4 ++--
>  src/libcamera/framebuffer_allocator.cpp            |  9 +++++++--
>  src/libcamera/pipeline/ipu3/ipu3.cpp               |  4 ++--
>  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  4 ++--
>  src/libcamera/pipeline/rkisp1/rkisp1.cpp           |  4 ++--
>  src/libcamera/pipeline/simple/simple.cpp           |  4 ++--
>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  7 ++++---
>  src/libcamera/pipeline/vimc/vimc.cpp               |  7 ++++---
>  src/libcamera/pipeline_handler.cpp                 |  1 +
>  src/qcam/main_window.cpp                           |  9 ++++++++-
>  src/v4l2/v4l2_camera.cpp                           |  2 +-
>  test/camera/camera_reconfigure.cpp                 |  4 +++-
>  test/camera/capture.cpp                            |  6 ++++--
>  test/camera/statemachine.cpp                       |  4 +++-
>  test/mapped-buffer.cpp                             |  4 +++-
>  24 files changed, 79 insertions(+), 40 deletions(-)
> 
> diff --git a/Documentation/guides/application-developer.rst b/Documentation/guides/application-developer.rst
> index fb6a80a57eb7..4dc8ac402ec6 100644
> --- a/Documentation/guides/application-developer.rst
> +++ b/Documentation/guides/application-developer.rst
> @@ -31,6 +31,7 @@ defined names and types without the need of prefixing them.
>     #include <memory>
>  
>     #include <libcamera/libcamera.h>
> +   #include <libcamera/property_ids.h>
>  
>     using namespace libcamera;
>  
> @@ -260,7 +261,10 @@ Using the libcamera ``FrameBufferAllocator``
>  
>  Applications create a ``FrameBufferAllocator`` for a Camera and use it
>  to allocate buffers for streams of a ``CameraConfiguration`` with the
> -``allocate()`` function.
> +``allocate()`` function. The number of buffers to be allocated needs to be
> +specified, and should be at least equal to the value of the ``MinimumRequests``
> +property in order for the pipeline to have enough requests to be able to
> +capture without frame drops.
>  
>  The list of allocated buffers can be retrieved using the ``Stream`` instance
>  as the parameter of the ``FrameBufferAllocator::buffers()`` function.
> @@ -268,9 +272,10 @@ as the parameter of the ``FrameBufferAllocator::buffers()`` function.
>  .. code:: cpp
>  
>     FrameBufferAllocator *allocator = new FrameBufferAllocator(camera);
> +   unsigned int bufferCount = camera->properties().get(properties::MinimumRequests);
>  
>     for (StreamConfiguration &cfg : *config) {
> -       int ret = allocator->allocate(cfg.stream());
> +       int ret = allocator->allocate(cfg.stream(), bufferCount);
>         if (ret < 0) {
>             std::cerr << "Can't allocate buffers" << std::endl;
>             return -ENOMEM;
> diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst
> index 32e3fc518d91..2a69ef7d7461 100644
> --- a/Documentation/guides/pipeline-handler.rst
> +++ b/Documentation/guides/pipeline-handler.rst
> @@ -206,7 +206,7 @@ implementations for the overridden class members.
>            const StreamRoles &roles) override;
>            int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -          int exportFrameBuffers(Camera *camera, Stream *stream,
> +          int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>            std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>            int start(Camera *camera, const ControlList *controls) override;
> @@ -1186,7 +1186,6 @@ handle this:
>  
>  .. code-block:: cpp
>  
> -   unsigned int count = stream->configuration().bufferCount;
>     VividCameraData *data = cameraData(camera);
>  
>     return data->video_->exportBuffers(count, buffers);
> diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
> index 05cdab724b10..d52867db5137 100644
> --- a/include/libcamera/camera.h
> +++ b/include/libcamera/camera.h
> @@ -116,7 +116,7 @@ private:
>  	void requestComplete(Request *request);
>  
>  	friend class FrameBufferAllocator;
> -	int exportFrameBuffers(Stream *stream,
> +	int exportFrameBuffers(Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers);
>  };
>  
> diff --git a/include/libcamera/framebuffer_allocator.h b/include/libcamera/framebuffer_allocator.h
> index cbc9ce101889..2d5a6e98e10c 100644
> --- a/include/libcamera/framebuffer_allocator.h
> +++ b/include/libcamera/framebuffer_allocator.h
> @@ -25,7 +25,7 @@ public:
>  	FrameBufferAllocator(std::shared_ptr<Camera> camera);
>  	~FrameBufferAllocator();
>  
> -	int allocate(Stream *stream);
> +	int allocate(Stream *stream, unsigned int count);
>  	int free(Stream *stream);
>  
>  	bool allocated() const { return !buffers_.empty(); }
> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> index 41cba44d990f..c6b3af18b1d3 100644
> --- a/include/libcamera/internal/pipeline_handler.h
> +++ b/include/libcamera/internal/pipeline_handler.h
> @@ -50,7 +50,7 @@ public:
>  		const StreamRoles &roles) = 0;
>  	virtual int configure(Camera *camera, CameraConfiguration *config) = 0;
>  
> -	virtual int exportFrameBuffers(Camera *camera, Stream *stream,
> +	virtual int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  				       std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
>  
>  	virtual int start(Camera *camera, const ControlList *controls) = 0;
> diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp
> index 61b441830e18..29be1ac5ca4f 100644
> --- a/src/android/camera_stream.cpp
> +++ b/src/android/camera_stream.cpp
> @@ -15,6 +15,7 @@
>  #include "jpeg/post_processor_jpeg.h"
>  
>  #include <libcamera/formats.h>
> +#include <libcamera/property_ids.h>
>  
>  using namespace libcamera;
>  
> @@ -83,8 +84,10 @@ int CameraStream::configure()
>  			return ret;
>  	}
>  
> +	unsigned int bufferCount = cameraDevice_->camera()->properties().get(properties::MinimumRequests);
> +
>  	if (allocator_) {
> -		int ret = allocator_->allocate(stream());
> +		int ret = allocator_->allocate(stream(), bufferCount);
>  		if (ret < 0)
>  			return ret;
>  
> diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp
> index 60d640f2b15c..d9a8500f390f 100644
> --- a/src/cam/camera_session.cpp
> +++ b/src/cam/camera_session.cpp
> @@ -237,17 +237,21 @@ int CameraSession::startCapture()
>  {
>  	int ret;
>  
> -	/* Identify the stream with the least number of buffers. */
> -	unsigned int nbuffers = UINT_MAX;
> +	unsigned int nbuffers = camera_->properties().get(properties::MinimumRequests);
> +
>  	for (StreamConfiguration &cfg : *config_) {
> -		ret = allocator_->allocate(cfg.stream());
> +		ret = allocator_->allocate(cfg.stream(), nbuffers);
>  		if (ret < 0) {
>  			std::cerr << "Can't allocate buffers" << std::endl;
>  			return -ENOMEM;
>  		}
>  
>  		unsigned int allocated = allocator_->buffers(cfg.stream()).size();
> -		nbuffers = std::min(nbuffers, allocated);
> +		if (allocated < nbuffers) {
> +			std::cerr << "Unable to allocate enough buffers"
> +				  << std::endl;
> +			return -ENOMEM;
> +		}
>  	}
>  
>  	/*
> diff --git a/src/gstreamer/gstlibcameraallocator.cpp b/src/gstreamer/gstlibcameraallocator.cpp
> index 7bd8ba2db71d..8cc42edfaf61 100644
> --- a/src/gstreamer/gstlibcameraallocator.cpp
> +++ b/src/gstreamer/gstlibcameraallocator.cpp
> @@ -10,6 +10,7 @@
>  
>  #include <libcamera/camera.h>
>  #include <libcamera/framebuffer_allocator.h>
> +#include <libcamera/property_ids.h>
>  #include <libcamera/stream.h>
>  
>  #include "gstlibcamera-utils.h"
> @@ -188,13 +189,14 @@ gst_libcamera_allocator_new(std::shared_ptr<Camera> camera,
>  {
>  	auto *self = GST_LIBCAMERA_ALLOCATOR(g_object_new(GST_TYPE_LIBCAMERA_ALLOCATOR,
>  							  nullptr));
> +	unsigned int bufferCount = camera->properties().get(properties::MinimumRequests);
>  
>  	self->fb_allocator = new FrameBufferAllocator(camera);
>  	for (StreamConfiguration &streamCfg : *config_) {
>  		Stream *stream = streamCfg.stream();
>  		gint ret;
>  
> -		ret = self->fb_allocator->allocate(stream);
> +		ret = self->fb_allocator->allocate(stream, bufferCount);
>  		if (ret == 0)
>  			return nullptr;
>  
> diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp
> index 25097f28a603..d87f30cbeb1b 100644
> --- a/src/lc-compliance/simple_capture.cpp
> +++ b/src/lc-compliance/simple_capture.cpp
> @@ -7,6 +7,8 @@
>  
>  #include <gtest/gtest.h>
>  
> +#include <libcamera/property_ids.h>
> +
>  #include "simple_capture.h"
>  
>  using namespace libcamera;
> @@ -44,11 +46,12 @@ void SimpleCapture::configure(StreamRole role)
>  
>  void SimpleCapture::start()
>  {
> +	unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);
>  	Stream *stream = config_->at(0).stream();
> -	int count = allocator_->allocate(stream);
> +	int count = allocator_->allocate(stream, bufferCount);
>  
>  	ASSERT_GE(count, 0) << "Failed to allocate buffers";
> -	EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected";
> +	EXPECT_EQ(count, bufferCount) << "Allocated less buffers than expected";
>  
>  	camera_->requestCompleted.connect(this, &SimpleCapture::requestComplete);
>  
> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
> index c20e05014fb9..bea0d04ebd4e 100644
> --- a/src/libcamera/camera.cpp
> +++ b/src/libcamera/camera.cpp
> @@ -691,7 +691,7 @@ void Camera::disconnect()
>  	disconnected.emit(this);
>  }
>  
> -int Camera::exportFrameBuffers(Stream *stream,
> +int Camera::exportFrameBuffers(Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	Private *const d = _d();
> @@ -708,7 +708,7 @@ int Camera::exportFrameBuffers(Stream *stream,
>  
>  	return d->pipe_->invokeMethod(&PipelineHandler::exportFrameBuffers,
>  				      ConnectionTypeBlocking, this, stream,
> -				      buffers);
> +				      count, buffers);
>  }
>  
>  /**
> diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp
> index 4df27cac0e94..8538240b4ae6 100644
> --- a/src/libcamera/framebuffer_allocator.cpp
> +++ b/src/libcamera/framebuffer_allocator.cpp
> @@ -71,6 +71,7 @@ FrameBufferAllocator::~FrameBufferAllocator()
>  /**
>   * \brief Allocate buffers for a configured stream
>   * \param[in] stream The stream to allocate buffers for
> + * \param[in] count The number of buffers to allocate
>   *
>   * Allocate buffers suitable for capturing frames from the \a stream. The Camera
>   * shall have been previously configured with Camera::configure() and shall be
> @@ -79,6 +80,10 @@ FrameBufferAllocator::~FrameBufferAllocator()
>   * Upon successful allocation, the allocated buffers can be retrieved with the
>   * buffers() function.
>   *
> + * This function may allocate less buffers than requested, due to memory and
> + * other system constraints. The caller shall always check the return value to
> + * verify if the number of allocate buffers matches its needs.
> + *
>   * \return The number of allocated buffers on success or a negative error code
>   * otherwise
>   * \retval -EACCES The camera is not in a state where buffers can be allocated
> @@ -86,14 +91,14 @@ FrameBufferAllocator::~FrameBufferAllocator()
>   * not part of the active camera configuration
>   * \retval -EBUSY Buffers are already allocated for the \a stream
>   */
> -int FrameBufferAllocator::allocate(Stream *stream)
> +int FrameBufferAllocator::allocate(Stream *stream, unsigned int count)
>  {
>  	if (buffers_.count(stream)) {
>  		LOG(Allocator, Error) << "Buffers already allocated for stream";
>  		return -EBUSY;
>  	}
>  
> -	int ret = camera_->exportFrameBuffers(stream, &buffers_[stream]);
> +	int ret = camera_->exportFrameBuffers(stream, count, &buffers_[stream]);
>  	if (ret == -EINVAL)
>  		LOG(Allocator, Error)
>  			<< "Stream is not part of " << camera_->id()
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index 2309609093cc..eaa503a33208 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -137,7 +137,7 @@ public:
>  		const StreamRoles &roles) override;
>  	int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -	int exportFrameBuffers(Camera *camera, Stream *stream,
> +	int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>  	int start(Camera *camera, const ControlList *controls) override;
> @@ -670,10 +670,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
>  }
>  
>  int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,
> +					    unsigned int count,
>  					    std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	IPU3CameraData *data = cameraData(camera);
> -	unsigned int count = stream->configuration().bufferCount;
>  
>  	if (stream == &data->outStream_)
>  		return data->imgu_->output_->exportBuffers(count, buffers);
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> index d35b9714f0c3..8a1040aa46be 100644
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> @@ -251,7 +251,7 @@ public:
>  	CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override;
>  	int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -	int exportFrameBuffers(Camera *camera, Stream *stream,
> +	int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>  	int start(Camera *camera, const ControlList *controls) override;
> @@ -795,10 +795,10 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)
>  }
>  
>  int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,
> +					   unsigned int count,
>  					   std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	RPi::Stream *s = static_cast<RPi::Stream *>(stream);
> -	unsigned int count = stream->configuration().bufferCount;
>  	int ret = s->dev()->exportBuffers(count, buffers);
>  
>  	s->setExportedBuffers(buffers);
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index cc663c983b3b..853a0ef42ba3 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -143,7 +143,7 @@ public:
>  		const StreamRoles &roles) override;
>  	int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -	int exportFrameBuffers(Camera *camera, Stream *stream,
> +	int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>  	int start(Camera *camera, const ControlList *controls) override;
> @@ -674,10 +674,10 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
>  }
>  
>  int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,
> +					      unsigned int count,
>  					      std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	RkISP1CameraData *data = cameraData(camera);
> -	unsigned int count = stream->configuration().bufferCount;
>  
>  	if (stream == &data->mainPathStream_)
>  		return mainPath_.exportBuffers(count, buffers);
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index 26c59e601a76..737815452bae 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -236,7 +236,7 @@ public:
>  						   const StreamRoles &roles) override;
>  	int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -	int exportFrameBuffers(Camera *camera, Stream *stream,
> +	int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>  	int start(Camera *camera, const ControlList *controls) override;
> @@ -808,10 +808,10 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
>  }
>  
>  int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
> +					      unsigned int count,
>  					      std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	SimpleCameraData *data = cameraData(camera);
> -	unsigned int count = stream->configuration().bufferCount;
>  
>  	/*
>  	 * Export buffers on the converter or capture video node, depending on
> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> index 75d57300555c..7821cacfa883 100644
> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> @@ -70,7 +70,7 @@ public:
>  		const StreamRoles &roles) override;
>  	int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -	int exportFrameBuffers(Camera *camera, Stream *stream,
> +	int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>  	int start(Camera *camera, const ControlList *controls) override;
> @@ -223,11 +223,12 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)
>  	return 0;
>  }
>  
> -int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, Stream *stream,
> +int PipelineHandlerUVC::exportFrameBuffers(Camera *camera,
> +					   [[maybe_unused]] Stream *stream,
> +					   unsigned int count,
>  					   std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	UVCCameraData *data = cameraData(camera);
> -	unsigned int count = stream->configuration().bufferCount;
>  
>  	return data->video_->exportBuffers(count, buffers);
>  }
> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> index a0d8fd6c48c3..eebdfd1a4c01 100644
> --- a/src/libcamera/pipeline/vimc/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> @@ -88,7 +88,7 @@ public:
>  		const StreamRoles &roles) override;
>  	int configure(Camera *camera, CameraConfiguration *config) override;
>  
> -	int exportFrameBuffers(Camera *camera, Stream *stream,
> +	int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
>  			       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
>  
>  	int start(Camera *camera, const ControlList *controls) override;
> @@ -318,11 +318,12 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
>  	return 0;
>  }
>  
> -int PipelineHandlerVimc::exportFrameBuffers(Camera *camera, Stream *stream,
> +int PipelineHandlerVimc::exportFrameBuffers(Camera *camera,
> +					    [[maybe_unused]] Stream *stream,
> +					    unsigned int count,
>  					    std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
>  	VimcCameraData *data = cameraData(camera);
> -	unsigned int count = stream->configuration().bufferCount;
>  
>  	return data->video_->exportBuffers(count, buffers);
>  }
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 597d4c6a578a..ed4d62ae5c34 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -230,6 +230,7 @@ void PipelineHandler::unlock()
>   * \brief Allocate and export buffers for \a stream
>   * \param[in] camera The camera
>   * \param[in] stream The stream to allocate buffers for
> + * \param[in] count The number of buffers to allocate
>   * \param[out] buffers Array of buffers successfully allocated
>   *
>   * This function allocates buffers for the \a stream from the devices associated
> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
> index 1adaae60d83b..4089e47269a4 100644
> --- a/src/qcam/main_window.cpp
> +++ b/src/qcam/main_window.cpp
> @@ -25,6 +25,7 @@
>  #include <QtDebug>
>  
>  #include <libcamera/camera_manager.h>
> +#include <libcamera/property_ids.h>
>  #include <libcamera/version.h>
>  
>  #include "dng_writer.h"
> @@ -463,7 +464,13 @@ int MainWindow::startCapture()
>  	for (StreamConfiguration &config : *config_) {
>  		Stream *stream = config.stream();
>  
> -		ret = allocator_->allocate(stream);
> +		/*
> +		 * We hold on to a buffer for display, so need one extra from
> +		 * the minimum required for capture.
> +		 */
> +		unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests) + 1;
> +
> +		ret = allocator_->allocate(stream, bufferCount);
>  		if (ret < 0) {
>  			qWarning() << "Failed to allocate capture buffers";
>  			goto error;
> diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp
> index 157ab94e0544..d01eacfa2b84 100644
> --- a/src/v4l2/v4l2_camera.cpp
> +++ b/src/v4l2/v4l2_camera.cpp
> @@ -161,7 +161,7 @@ int V4L2Camera::allocBuffers(unsigned int count)
>  {
>  	Stream *stream = config_->at(0).stream();
>  
> -	int ret = bufferAllocator_->allocate(stream);
> +	int ret = bufferAllocator_->allocate(stream, count);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/test/camera/camera_reconfigure.cpp b/test/camera/camera_reconfigure.cpp
> index 5adef16e1c9e..00e6b113341b 100644
> --- a/test/camera/camera_reconfigure.cpp
> +++ b/test/camera/camera_reconfigure.cpp
> @@ -17,6 +17,7 @@
>  #include <libcamera/base/timer.h>
>  
>  #include <libcamera/framebuffer_allocator.h>
> +#include <libcamera/property_ids.h>
>  
>  #include "camera_test.h"
>  #include "test.h"
> @@ -76,7 +77,8 @@ private:
>  		 * same buffer allocation for each run.
>  		 */
>  		if (!allocated_) {
> -			int ret = allocator_->allocate(stream);
> +			unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);
> +			int ret = allocator_->allocate(stream, bufferCount);
>  			if (ret < 0) {
>  				cerr << "Failed to allocate buffers" << endl;
>  				return TestFail;
> diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
> index 238d98dbba16..8d921fcb38f6 100644
> --- a/test/camera/capture.cpp
> +++ b/test/camera/capture.cpp
> @@ -8,6 +8,7 @@
>  #include <iostream>
>  
>  #include <libcamera/framebuffer_allocator.h>
> +#include <libcamera/property_ids.h>
>  
>  #include <libcamera/base/event_dispatcher.h>
>  #include <libcamera/base/thread.h>
> @@ -96,8 +97,9 @@ protected:
>  
>  		Stream *stream = cfg.stream();
>  
> -		int ret = allocator_->allocate(stream);
> -		if (ret < 0)
> +		unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);
> +		int ret = allocator_->allocate(stream, bufferCount);
> +		if (ret < static_cast<int>(bufferCount))
>  			return TestFail;
>  
>  		for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) {
> diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp
> index 26fb5ca17139..70015bb56c74 100644
> --- a/test/camera/statemachine.cpp
> +++ b/test/camera/statemachine.cpp
> @@ -8,6 +8,7 @@
>  #include <iostream>
>  
>  #include <libcamera/framebuffer_allocator.h>
> +#include <libcamera/property_ids.h>
>  
>  #include "camera_test.h"
>  #include "test.h"
> @@ -119,7 +120,8 @@ protected:
>  		/* Use internally allocated buffers. */
>  		allocator_ = new FrameBufferAllocator(camera_);
>  		Stream *stream = *camera_->streams().begin();
> -		if (allocator_->allocate(stream) < 0)
> +		unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);
> +		if (allocator_->allocate(stream, bufferCount) < 0)
>  			return TestFail;
>  
>  		if (camera_->start())
> diff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp
> index 97571945cbca..a5c56715a169 100644
> --- a/test/mapped-buffer.cpp
> +++ b/test/mapped-buffer.cpp
> @@ -8,6 +8,7 @@
>  #include <iostream>
>  
>  #include <libcamera/framebuffer_allocator.h>
> +#include <libcamera/property_ids.h>
>  
>  #include "libcamera/internal/mapped_framebuffer.h"
>  
> @@ -54,7 +55,8 @@ protected:
>  
>  		stream_ = cfg.stream();
>  
> -		int ret = allocator_->allocate(stream_);
> +		unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);
> +		int ret = allocator_->allocate(stream_, bufferCount);
>  		if (ret < 0)
>  			return TestFail;
>  
> -- 
> 2.33.0
> 


More information about the libcamera-devel mailing list