From patchwork Mon Apr 28 09:02:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Sven_P=C3=BCschel?= X-Patchwork-Id: 23274 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 89556C32A2 for ; Mon, 28 Apr 2025 09:05:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B7DB168AD5; Mon, 28 Apr 2025 11:05:12 +0200 (CEST) Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [IPv6:2a0a:edc0:2:b01:1d::104]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 45B9168AD0 for ; Mon, 28 Apr 2025 11:05:06 +0200 (CEST) Received: from ptz.office.stw.pengutronix.de ([2a0a:edc0:0:900:1d::77] helo=peter.guest.stw.pengutronix.de) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1u9KQD-0001au-UX; Mon, 28 Apr 2025 11:05:06 +0200 From: =?utf-8?q?Sven_P=C3=BCschel?= To: libcamera-devel@lists.libcamera.org Cc: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= , Kieran Bingham , Laurent Pinchart , Paul Elder , Jacopo Mondi , =?utf-8?q?Sven_P=C3=BCschel?= Subject: [PATCH v11 02/19] libcamera: framebuffer_allocator: Make allocate() require count Date: Mon, 28 Apr 2025 11:02:27 +0200 Message-ID: <20250428090413.38234-3-s.pueschel@pengutronix.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250428090413.38234-1-s.pueschel@pengutronix.de> References: <20250428090413.38234-1-s.pueschel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:900:1d::77 X-SA-Exim-Mail-From: s.pueschel@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: libcamera-devel@lists.libcamera.org X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Nícolas F. R. A. Prado Make FrameBufferAllocator::allocate() require a 'count' argument for the number of buffers to be allocated. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Reviewed-by: Paul Elder Signed-off-by: Paul Elder Reviewed-by: Jacopo Mondi Signed-off-by: Sven Püschel --- Changes in v11: - add mali-c55 and virtual - adapt python binding Changes in v10: - add imx8-isi Changes in v9: - rebased - notably, ControlList::get() returns a std::optional, and since the MinimumRequests property is a required property, we can simply get it via .value() - this will be enforced by lc-compliance in a later patch 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/apps/cam/camera_session.cpp | 13 +++++++++---- src/apps/lc-compliance/helpers/capture.cpp | 5 +++-- src/apps/qcam/main_window.cpp | 10 +++++++++- src/gstreamer/gstlibcameraallocator.cpp | 6 +++++- src/libcamera/camera.cpp | 4 ++-- src/libcamera/framebuffer_allocator.cpp | 9 +++++++-- src/libcamera/pipeline/imx8-isi/imx8-isi.cpp | 5 ++--- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 ++-- src/libcamera/pipeline/mali-c55/mali-c55.cpp | 3 ++- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 4 ++-- src/libcamera/pipeline/rpi/common/pipeline_base.cpp | 2 +- src/libcamera/pipeline/rpi/common/pipeline_base.h | 2 +- src/libcamera/pipeline/simple/simple.cpp | 4 ++-- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 7 ++++--- src/libcamera/pipeline/vimc/vimc.cpp | 7 ++++--- src/libcamera/pipeline/virtual/virtual.cpp | 5 +++-- src/libcamera/pipeline_handler.cpp | 1 + src/py/libcamera/py_main.cpp | 4 ++-- src/v4l2/v4l2_camera.cpp | 2 +- test/camera/camera_reconfigure.cpp | 5 ++++- test/camera/capture.cpp | 11 +++++++---- test/camera/statemachine.cpp | 5 ++++- test/fence.cpp | 6 +++++- test/mapped-buffer.cpp | 5 ++++- 29 files changed, 97 insertions(+), 50 deletions(-) diff --git a/Documentation/guides/application-developer.rst b/Documentation/guides/application-developer.rst index f3798d17..dbd2bfc6 100644 --- a/Documentation/guides/application-developer.rst +++ b/Documentation/guides/application-developer.rst @@ -32,6 +32,7 @@ defined names and types without the need of prefixing them. #include #include + #include using namespace libcamera; using namespace std::chrono_literals; @@ -276,7 +277,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. @@ -284,9 +288,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 1079d998..2e9825dc 100644 --- a/Documentation/guides/pipeline-handler.rst +++ b/Documentation/guides/pipeline-handler.rst @@ -209,7 +209,7 @@ implementations for the overridden class members. Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -1242,7 +1242,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 94cee7bd..ce9d8812 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -163,7 +163,7 @@ private: void requestComplete(Request *request); friend class FrameBufferAllocator; - int exportFrameBuffers(Stream *stream, + int exportFrameBuffers(Stream *stream, unsigned int count, std::vector> *buffers); }; diff --git a/include/libcamera/framebuffer_allocator.h b/include/libcamera/framebuffer_allocator.h index f3896bf2..1568c55d 100644 --- a/include/libcamera/framebuffer_allocator.h +++ b/include/libcamera/framebuffer_allocator.h @@ -25,7 +25,7 @@ public: FrameBufferAllocator(std::shared_ptr 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 972a2fa6..0e9fe23e 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -48,7 +48,7 @@ public: Span 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> *buffers) = 0; virtual int start(Camera *camera, const ControlList *controls) = 0; diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 97c1ae44..f50108f3 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -326,17 +326,22 @@ 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).value(); + 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/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp index 2a3fa3b6..690de005 100644 --- a/src/apps/lc-compliance/helpers/capture.cpp +++ b/src/apps/lc-compliance/helpers/capture.cpp @@ -120,7 +120,8 @@ void Capture::start() assert(!allocator_.allocated()); assert(requests_.empty()); - const auto bufferCount = config_->at(0).bufferCount; + unsigned int bufferCount = + camera_->properties().get(properties::MinimumRequests).value(); /* No point in testing less requests then the camera depth. */ if (queueLimit_ && *queueLimit_ < bufferCount) { @@ -137,7 +138,7 @@ void Capture::start() for (const auto &cfg : *config_) { Stream *stream = cfg.stream(); - int count = allocator_.allocate(stream); + int count = allocator_.allocate(stream, bufferCount); ASSERT_GE(count, 0) << "Failed to allocate buffers"; const auto &buffers = allocator_.buffers(stream); diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp index d2ccbd23..9a9b7fa9 100644 --- a/src/apps/qcam/main_window.cpp +++ b/src/apps/qcam/main_window.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -447,7 +448,14 @@ 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).value() + 1; + + ret = allocator_->allocate(stream, bufferCount); if (ret < 0) { qWarning() << "Failed to allocate capture buffers"; goto error; diff --git a/src/gstreamer/gstlibcameraallocator.cpp b/src/gstreamer/gstlibcameraallocator.cpp index d4492d99..0d8e4c40 100644 --- a/src/gstreamer/gstlibcameraallocator.cpp +++ b/src/gstreamer/gstlibcameraallocator.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include "gstlibcamera-utils.h" @@ -209,11 +210,14 @@ gst_libcamera_allocator_new(std::shared_ptr camera, if (ret) return nullptr; + unsigned int bufferCount = + camera->properties().get(properties::MinimumRequests).value(); + self->fb_allocator = new FrameBufferAllocator(camera); for (StreamConfiguration &streamCfg : *config_) { Stream *stream = streamCfg.stream(); - ret = self->fb_allocator->allocate(stream); + ret = self->fb_allocator->allocate(stream, bufferCount); if (ret <= 0) return nullptr; diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index c180a5fd..33e928b9 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -950,7 +950,7 @@ void Camera::disconnect() disconnected.emit(); } -int Camera::exportFrameBuffers(Stream *stream, +int Camera::exportFrameBuffers(Stream *stream, unsigned int count, std::vector> *buffers) { Private *const d = _d(); @@ -967,7 +967,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 3d53bde2..c522f479 100644 --- a/src/libcamera/framebuffer_allocator.cpp +++ b/src/libcamera/framebuffer_allocator.cpp @@ -68,6 +68,7 @@ FrameBufferAllocator::~FrameBufferAllocator() = default; /** * \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 @@ -76,6 +77,10 @@ FrameBufferAllocator::~FrameBufferAllocator() = default; * 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 @@ -83,7 +88,7 @@ FrameBufferAllocator::~FrameBufferAllocator() = default; * 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) { const auto &[it, inserted] = buffers_.try_emplace(stream); @@ -92,7 +97,7 @@ int FrameBufferAllocator::allocate(Stream *stream) return -EBUSY; } - int ret = camera_->exportFrameBuffers(stream, &it->second); + int ret = camera_->exportFrameBuffers(stream, count, &it->second); if (ret == -EINVAL) LOG(Allocator, Error) << "Stream is not part of " << camera_->id() diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp index 2b8a583e..21f44424 100644 --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp @@ -108,7 +108,7 @@ public: generateConfiguration(Camera *camera, Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -908,10 +908,9 @@ int PipelineHandlerISI::configure(Camera *camera, CameraConfiguration *c) return 0; } -int PipelineHandlerISI::exportFrameBuffers(Camera *camera, Stream *stream, +int PipelineHandlerISI::exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count, std::vector> *buffers) { - unsigned int count = stream->configuration().bufferCount; Pipe *pipe = pipeFromStream(camera, stream); return pipe->capture->exportBuffers(count, buffers); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 356ca2e1..30b74d4e 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -139,7 +139,7 @@ public: Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -637,10 +637,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) } int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream, + unsigned int count, std::vector> *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/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp index f0ab3d2e..9df1622e 100644 --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp @@ -608,6 +608,7 @@ public: int configure(Camera *camera, CameraConfiguration *config) override; int exportFrameBuffers(Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) override; int allocateBuffers(Camera *camera); void freeBuffers(Camera *camera); @@ -1087,10 +1088,10 @@ int PipelineHandlerMaliC55::configure(Camera *camera, } int PipelineHandlerMaliC55::exportFrameBuffers(Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { MaliC55Pipe *pipe = pipeFromStream(cameraData(camera), stream); - unsigned int count = stream->configuration().bufferCount; return pipe->cap->exportBuffers(count, buffers); } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 5e3a4dba..4e8eff70 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -158,7 +158,7 @@ public: Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -953,10 +953,10 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) } int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { RkISP1CameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; if (stream == &data->mainPathStream_) { /* diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp index ef51d530..dc1e0a2e 100644 --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp @@ -630,10 +630,10 @@ int PipelineHandlerBase::configure(Camera *camera, CameraConfiguration *config) } int PipelineHandlerBase::exportFrameBuffers([[maybe_unused]] Camera *camera, libcamera::Stream *stream, + unsigned int count, std::vector> *buffers) { RPi::Stream *s = static_cast(stream); - unsigned int count = stream->configuration().bufferCount; int ret = s->dev()->exportBuffers(count, buffers); s->setExportedBuffers(buffers); diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h index aae0c2f3..e73d6f18 100644 --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h @@ -218,7 +218,7 @@ public: generateConfiguration(Camera *camera, Span roles) override; int configure(Camera *camera, CameraConfiguration *config) override; - int exportFrameBuffers(Camera *camera, libcamera::Stream *stream, + int exportFrameBuffers(Camera *camera, libcamera::Stream *stream, unsigned int count, std::vector> *buffers) override; int start(Camera *camera, const ControlList *controls) override; diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 7abf0fc9..1e77ccdc 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -404,7 +404,7 @@ public: Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -1434,10 +1434,10 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) } int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, + unsigned int count, std::vector> *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 31951a12..60c82364 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -87,7 +87,7 @@ public: Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -278,11 +278,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> *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 01685a64..8833647a 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -92,7 +92,7 @@ public: Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -343,11 +343,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> *buffers) { VimcCameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; return data->video_->exportBuffers(count, buffers); } diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp index c33f1a5e..ad2bdb57 100644 --- a/src/libcamera/pipeline/virtual/virtual.cpp +++ b/src/libcamera/pipeline/virtual/virtual.cpp @@ -87,7 +87,7 @@ public: Span 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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -269,6 +269,7 @@ int PipelineHandlerVirtual::configure(Camera *camera, int PipelineHandlerVirtual::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { if (!dmaBufAllocator_.isValid()) @@ -281,7 +282,7 @@ int PipelineHandlerVirtual::exportFrameBuffers([[maybe_unused]] Camera *camera, for (size_t i = 0; i < info.numPlanes(); ++i) planeSizes.push_back(info.planeSize(config.size, i)); - return dmaBufAllocator_.exportBuffers(config.bufferCount, planeSizes, buffers); + return dmaBufAllocator_.exportBuffers(count, planeSizes, buffers); } int PipelineHandlerVirtual::start([[maybe_unused]] Camera *camera, diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index d84dff3c..3211256c 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -314,6 +314,7 @@ void PipelineHandler::unlockMediaDevices() * \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/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp index 441a70ab..f75450ee 100644 --- a/src/py/libcamera/py_main.cpp +++ b/src/py/libcamera/py_main.cpp @@ -349,8 +349,8 @@ PYBIND11_MODULE(_libcamera, m) pyFrameBufferAllocator .def(py::init>(), py::keep_alive<1, 2>()) - .def("allocate", [](FrameBufferAllocator &self, Stream *stream) { - int ret = self.allocate(stream); + .def("allocate", [](FrameBufferAllocator &self, Stream *stream, unsigned int count) { + int ret = self.allocate(stream, count); if (ret < 0) throw std::system_error(-ret, std::generic_category(), "Failed to allocate buffers"); diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 94d138cd..a4b0e562 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -162,7 +162,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 06c87730..63a97863 100644 --- a/test/camera/camera_reconfigure.cpp +++ b/test/camera/camera_reconfigure.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "camera_test.h" #include "test.h" @@ -78,7 +79,9 @@ private: * same buffer allocation for each run. */ if (!allocated_) { - int ret = allocator_->allocate(stream); + unsigned int bufferCount = + camera_->properties().get(properties::MinimumRequests).value(); + 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 8766fb19..05f4a1e3 100644 --- a/test/camera/capture.cpp +++ b/test/camera/capture.cpp @@ -7,12 +7,13 @@ #include -#include - #include #include #include +#include +#include + #include "camera_test.h" #include "test.h" @@ -101,8 +102,10 @@ protected: Stream *stream = cfg.stream(); - int ret = allocator_->allocate(stream); - if (ret < 0) + unsigned int bufferCount = + camera_->properties().get(properties::MinimumRequests).value(); + int ret = allocator_->allocate(stream, bufferCount); + if (ret < static_cast(bufferCount)) return TestFail; for (const std::unique_ptr &buffer : allocator_->buffers(stream)) { diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp index 9c2b0c6a..a9ddb323 100644 --- a/test/camera/statemachine.cpp +++ b/test/camera/statemachine.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "camera_test.h" #include "test.h" @@ -120,7 +121,9 @@ 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).value(); + if (allocator_->allocate(stream, bufferCount) < 0) return TestFail; if (camera_->start()) diff --git a/test/fence.cpp b/test/fence.cpp index 8095b228..eb6c8b54 100644 --- a/test/fence.cpp +++ b/test/fence.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "camera_test.h" #include "test.h" @@ -119,8 +120,11 @@ int FenceTest::init() StreamConfiguration &cfg = config_->at(0); stream_ = cfg.stream(); + unsigned int bufferCount = + camera_->properties().get(properties::MinimumRequests).value(); + allocator_ = std::make_unique(camera_); - if (allocator_->allocate(stream_) < 0) + if (allocator_->allocate(stream_, bufferCount) < 0) return TestFail; nbuffers_ = allocator_->buffers(stream_).size(); diff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp index b4422f7d..1b98feea 100644 --- a/test/mapped-buffer.cpp +++ b/test/mapped-buffer.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "libcamera/internal/mapped_framebuffer.h" @@ -55,7 +56,9 @@ protected: stream_ = cfg.stream(); - int ret = allocator_->allocate(stream_); + unsigned int bufferCount = + camera_->properties().get(properties::MinimumRequests).value(); + int ret = allocator_->allocate(stream_, bufferCount); if (ret < 0) return TestFail;