Show a patch.

GET /api/1.1/patches/18059/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 18059,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/18059/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/18059/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20221228223003.2265712-4-paul.elder@ideasonboard.com>",
    "date": "2022-12-28T22:29:47",
    "name": "[libcamera-devel,v10,03/19] libcamera: framebuffer_allocator: Make allocate() require count",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "65c329559da678930cb98b53b0a072d49f11ec96",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/1.1/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/18059/mbox/",
    "series": [
        {
            "id": 3691,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3691/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3691",
            "date": "2022-12-28T22:29:44",
            "name": "lc-compliance: Add test to queue more requests than hardware depth",
            "version": 10,
            "mbox": "https://patchwork.libcamera.org/series/3691/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/18059/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/18059/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 72EF2C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Dec 2022 22:30:24 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 37424625D4;\n\tWed, 28 Dec 2022 23:30:23 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A4DBB61F13\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Dec 2022 23:30:20 +0100 (CET)",
            "from pyrite.mediacom.info (unknown\n\t[IPv6:2604:2d80:ad8a:9000:1bf9:855b:22de:3645])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1142A25B;\n\tWed, 28 Dec 2022 23:30:18 +0100 (CET)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1672266623;\n\tbh=U+/lU1UnnktP+kK6HCvIaqzQLxWxQ+b6CSm+Q/Np/1A=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=UX7vx873XTtPNrvpPixiR628LG4fiQlJFUr7WF5C/YpyrXK9rs/IxiSsdR2CKvgGU\n\tVvQ67jO70R1UmuA7qlXKecAreS+0RKzz+Lc9Or0Qa65VFo3xfy1B3BjdpqhZIVwBxG\n\tAQKW0DEwLkISRag4Qu5Kzd1ysuemnHMxL3ymDzZA6rhDkxvNSo9EhcV0VtAWq8mY56\n\tnAYMCBEwLRrm9i5jAmbB7lc5wXTcFWCNBGwPctbol6+JhjFoILk4WHxe5yF8wp2hvU\n\tUYixOnn0WBoXjx8WNRTmhm2md/N6ZCld/BoVoIy6r4uu50sem1Neg96xtQZRHcrTTV\n\tSzVs1neVsZOSw==",
            "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1672266620;\n\tbh=U+/lU1UnnktP+kK6HCvIaqzQLxWxQ+b6CSm+Q/Np/1A=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=aZYB8qe5pUM2YOZHnWbFPLeagxn67KKGN60hlYhHA6zPNpRiOSviLAE+qltCPGwNs\n\tptXMy0vZgFwQx57sDvOwV+tTf1cFPnAL+aTOMAF6n3RczRHk3iWvShP0vo35+3bkc6\n\typ5HFq2qi5Vk1B1Nk+uVUKxqEIWlR0ESDCooaBQQ="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"aZYB8qe5\"; dkim-atps=neutral",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 28 Dec 2022 16:29:47 -0600",
        "Message-Id": "<20221228223003.2265712-4-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.35.1",
        "In-Reply-To": "<20221228223003.2265712-1-paul.elder@ideasonboard.com>",
        "References": "<20221228223003.2265712-1-paul.elder@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v10 03/19] libcamera:\n\tframebuffer_allocator: Make allocate() require count",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<libcamera-devel.lists.libcamera.org>",
        "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>",
        "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>",
        "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>",
        "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>",
        "From": "Paul Elder via libcamera-devel <libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Paul Elder <paul.elder@ideasonboard.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "From: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n\nMake FrameBufferAllocator::allocate() require a 'count' argument for the\nnumber of buffers to be allocated.\n\nSigned-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\n---\nChanges in v10:\n- add imx8-isi\n\nChanges in v9:\n- rebased\n- notably, ControlList::get() returns a std::optional, and since the\n  MinimumRequests property is a required property, we can simply\n  get it via .value()\n  - this will be enforced by lc-compliance in a later patch\n\nChanges in v8:\n- Updated application-developer and pipeline-handler guides with new allocate()\n  API and MinimumRequests property\n- Added handling for when allocate() returns less buffers than needed in cam and\n  the capture unit test\n- Improved FrameBufferAllocator::allocate() description\n\nChanges in v6:\n- Changed static_cast to convert 'count' to unsigned int instead of\n  'bufferCount' to int when comparing\n\nChanges in v5:\n- Made sure that qcam allocates at least 2 buffers\n---\n Documentation/guides/application-developer.rst     |  9 +++++++--\n Documentation/guides/pipeline-handler.rst          |  3 +--\n include/libcamera/camera.h                         |  2 +-\n include/libcamera/framebuffer_allocator.h          |  2 +-\n include/libcamera/internal/pipeline_handler.h      |  2 +-\n src/apps/cam/camera_session.cpp                    | 13 +++++++++----\n src/apps/lc-compliance/simple_capture.cpp          |  8 ++++++--\n src/apps/qcam/main_window.cpp                      | 10 +++++++++-\n src/gstreamer/gstlibcameraallocator.cpp            |  5 ++++-\n src/libcamera/camera.cpp                           |  4 ++--\n src/libcamera/framebuffer_allocator.cpp            |  9 +++++++--\n src/libcamera/pipeline/imx8-isi/imx8-isi.cpp       |  5 ++---\n src/libcamera/pipeline/ipu3/ipu3.cpp               |  4 ++--\n src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  4 ++--\n src/libcamera/pipeline/rkisp1/rkisp1.cpp           |  4 ++--\n src/libcamera/pipeline/simple/simple.cpp           |  4 ++--\n src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  7 ++++---\n src/libcamera/pipeline/vimc/vimc.cpp               |  7 ++++---\n src/libcamera/pipeline_handler.cpp                 |  1 +\n src/v4l2/v4l2_camera.cpp                           |  2 +-\n test/camera/camera_reconfigure.cpp                 |  5 ++++-\n test/camera/capture.cpp                            | 11 +++++++----\n test/camera/statemachine.cpp                       |  5 ++++-\n test/fence.cpp                                     |  6 +++++-\n test/mapped-buffer.cpp                             |  5 ++++-\n 25 files changed, 92 insertions(+), 45 deletions(-)",
    "diff": "diff --git a/Documentation/guides/application-developer.rst b/Documentation/guides/application-developer.rst\nindex 1b2d7727..40bcf67a 100644\n--- a/Documentation/guides/application-developer.rst\n+++ b/Documentation/guides/application-developer.rst\n@@ -30,6 +30,7 @@ defined names and types without the need of prefixing them.\n    #include <thread>\n \n    #include <libcamera/libcamera.h>\n+   #include <libcamera/property_ids.h>\n \n    using namespace libcamera;\n    using namespace std::chrono_literals;\n@@ -272,7 +273,10 @@ Using the libcamera ``FrameBufferAllocator``\n \n Applications create a ``FrameBufferAllocator`` for a Camera and use it\n to allocate buffers for streams of a ``CameraConfiguration`` with the\n-``allocate()`` function.\n+``allocate()`` function. The number of buffers to be allocated needs to be\n+specified, and should be at least equal to the value of the ``MinimumRequests``\n+property in order for the pipeline to have enough requests to be able to\n+capture without frame drops.\n \n The list of allocated buffers can be retrieved using the ``Stream`` instance\n as the parameter of the ``FrameBufferAllocator::buffers()`` function.\n@@ -280,9 +284,10 @@ as the parameter of the ``FrameBufferAllocator::buffers()`` function.\n .. code:: cpp\n \n    FrameBufferAllocator *allocator = new FrameBufferAllocator(camera);\n+   unsigned int bufferCount = camera->properties().get(properties::MinimumRequests);\n \n    for (StreamConfiguration &cfg : *config) {\n-       int ret = allocator->allocate(cfg.stream());\n+       int ret = allocator->allocate(cfg.stream(), bufferCount);\n        if (ret < 0) {\n            std::cerr << \"Can't allocate buffers\" << std::endl;\n            return -ENOMEM;\ndiff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst\nindex bfa87faa..c0890bc2 100644\n--- a/Documentation/guides/pipeline-handler.rst\n+++ b/Documentation/guides/pipeline-handler.rst\n@@ -206,7 +206,7 @@ implementations for the overridden class members.\n           const StreamRoles &roles) override;\n           int configure(Camera *camera, CameraConfiguration *config) override;\n \n-          int exportFrameBuffers(Camera *camera, Stream *stream,\n+          int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n           std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n           int start(Camera *camera, const ControlList *controls) override;\n@@ -1185,7 +1185,6 @@ handle this:\n \n .. code-block:: cpp\n \n-   unsigned int count = stream->configuration().bufferCount;\n    VividCameraData *data = cameraData(camera);\n \n    return data->video_->exportBuffers(count, buffers);\ndiff --git a/include/libcamera/camera.h b/include/libcamera/camera.h\nindex 5bb06584..4d32d16b 100644\n--- a/include/libcamera/camera.h\n+++ b/include/libcamera/camera.h\n@@ -126,7 +126,7 @@ private:\n \tvoid requestComplete(Request *request);\n \n \tfriend class FrameBufferAllocator;\n-\tint exportFrameBuffers(Stream *stream,\n+\tint exportFrameBuffers(Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n };\n \ndiff --git a/include/libcamera/framebuffer_allocator.h b/include/libcamera/framebuffer_allocator.h\nindex 45ff232b..7a0bf1a0 100644\n--- a/include/libcamera/framebuffer_allocator.h\n+++ b/include/libcamera/framebuffer_allocator.h\n@@ -25,7 +25,7 @@ public:\n \tFrameBufferAllocator(std::shared_ptr<Camera> camera);\n \t~FrameBufferAllocator();\n \n-\tint allocate(Stream *stream);\n+\tint allocate(Stream *stream, unsigned int count);\n \tint free(Stream *stream);\n \n \tbool allocated() const { return !buffers_.empty(); }\ndiff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h\nindex ec4f662d..8af165a3 100644\n--- a/include/libcamera/internal/pipeline_handler.h\n+++ b/include/libcamera/internal/pipeline_handler.h\n@@ -52,7 +52,7 @@ public:\n \t\tconst StreamRoles &roles) = 0;\n \tvirtual int configure(Camera *camera, CameraConfiguration *config) = 0;\n \n-\tvirtual int exportFrameBuffers(Camera *camera, Stream *stream,\n+\tvirtual int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;\n \n \tvirtual int start(Camera *camera, const ControlList *controls) = 0;\ndiff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp\nindex 8fcec630..b2f64e39 100644\n--- a/src/apps/cam/camera_session.cpp\n+++ b/src/apps/cam/camera_session.cpp\n@@ -253,17 +253,22 @@ int CameraSession::startCapture()\n {\n \tint ret;\n \n-\t/* Identify the stream with the least number of buffers. */\n-\tunsigned int nbuffers = UINT_MAX;\n+\tunsigned int nbuffers =\n+\t\tcamera_->properties().get(properties::MinimumRequests).value();\n+\n \tfor (StreamConfiguration &cfg : *config_) {\n-\t\tret = allocator_->allocate(cfg.stream());\n+\t\tret = allocator_->allocate(cfg.stream(), nbuffers);\n \t\tif (ret < 0) {\n \t\t\tstd::cerr << \"Can't allocate buffers\" << std::endl;\n \t\t\treturn -ENOMEM;\n \t\t}\n \n \t\tunsigned int allocated = allocator_->buffers(cfg.stream()).size();\n-\t\tnbuffers = std::min(nbuffers, allocated);\n+\t\tif (allocated < nbuffers) {\n+\t\t\tstd::cerr << \"Unable to allocate enough buffers\"\n+\t\t\t\t  << std::endl;\n+\t\t\treturn -ENOMEM;\n+\t\t}\n \t}\n \n \t/*\ndiff --git a/src/apps/lc-compliance/simple_capture.cpp b/src/apps/lc-compliance/simple_capture.cpp\nindex cf4d7cf3..be495986 100644\n--- a/src/apps/lc-compliance/simple_capture.cpp\n+++ b/src/apps/lc-compliance/simple_capture.cpp\n@@ -7,6 +7,8 @@\n \n #include <gtest/gtest.h>\n \n+#include <libcamera/property_ids.h>\n+\n #include \"simple_capture.h\"\n \n using namespace libcamera;\n@@ -44,11 +46,13 @@ void SimpleCapture::configure(StreamRole role)\n \n void SimpleCapture::start()\n {\n+\tunsigned int bufferCount =\n+\t\tcamera_->properties().get(properties::MinimumRequests).value();\n \tStream *stream = config_->at(0).stream();\n-\tint count = allocator_->allocate(stream);\n+\tint count = allocator_->allocate(stream, bufferCount);\n \n \tASSERT_GE(count, 0) << \"Failed to allocate buffers\";\n-\tEXPECT_EQ(count, config_->at(0).bufferCount) << \"Allocated less buffers than expected\";\n+\tEXPECT_EQ(count, bufferCount) << \"Allocated less buffers than expected\";\n \n \tcamera_->requestCompleted.connect(this, &SimpleCapture::requestComplete);\n \ndiff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\nindex fb2db4aa..85b696fe 100644\n--- a/src/apps/qcam/main_window.cpp\n+++ b/src/apps/qcam/main_window.cpp\n@@ -12,6 +12,7 @@\n #include <string>\n \n #include <libcamera/camera_manager.h>\n+#include <libcamera/property_ids.h>\n #include <libcamera/version.h>\n \n #include <QCoreApplication>\n@@ -464,7 +465,14 @@ int MainWindow::startCapture()\n \tfor (StreamConfiguration &config : *config_) {\n \t\tStream *stream = config.stream();\n \n-\t\tret = allocator_->allocate(stream);\n+\t\t/*\n+\t\t * We hold on to a buffer for display, so need one extra from\n+\t\t * the minimum required for capture.\n+\t\t */\n+\t\tunsigned int bufferCount =\n+\t\t\tcamera_->properties().get(properties::MinimumRequests).value() + 1;\n+\n+\t\tret = allocator_->allocate(stream, bufferCount);\n \t\tif (ret < 0) {\n \t\t\tqWarning() << \"Failed to allocate capture buffers\";\n \t\t\tgoto error;\ndiff --git a/src/gstreamer/gstlibcameraallocator.cpp b/src/gstreamer/gstlibcameraallocator.cpp\nindex c740b8fc..5f9b96ad 100644\n--- a/src/gstreamer/gstlibcameraallocator.cpp\n+++ b/src/gstreamer/gstlibcameraallocator.cpp\n@@ -10,6 +10,7 @@\n \n #include <libcamera/camera.h>\n #include <libcamera/framebuffer_allocator.h>\n+#include <libcamera/property_ids.h>\n #include <libcamera/stream.h>\n \n #include \"gstlibcamera-utils.h\"\n@@ -193,13 +194,15 @@ gst_libcamera_allocator_new(std::shared_ptr<Camera> camera,\n {\n \tauto *self = GST_LIBCAMERA_ALLOCATOR(g_object_new(GST_TYPE_LIBCAMERA_ALLOCATOR,\n \t\t\t\t\t\t\t  nullptr));\n+\tunsigned int bufferCount =\n+\t\tcamera->properties().get(properties::MinimumRequests).value();\n \n \tself->fb_allocator = new FrameBufferAllocator(camera);\n \tfor (StreamConfiguration &streamCfg : *config_) {\n \t\tStream *stream = streamCfg.stream();\n \t\tgint ret;\n \n-\t\tret = self->fb_allocator->allocate(stream);\n+\t\tret = self->fb_allocator->allocate(stream, bufferCount);\n \t\tif (ret == 0)\n \t\t\treturn nullptr;\n \ndiff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\nindex 2d947a44..ad289b28 100644\n--- a/src/libcamera/camera.cpp\n+++ b/src/libcamera/camera.cpp\n@@ -779,7 +779,7 @@ void Camera::disconnect()\n \tdisconnected.emit();\n }\n \n-int Camera::exportFrameBuffers(Stream *stream,\n+int Camera::exportFrameBuffers(Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tPrivate *const d = _d();\n@@ -796,7 +796,7 @@ int Camera::exportFrameBuffers(Stream *stream,\n \n \treturn d->pipe_->invokeMethod(&PipelineHandler::exportFrameBuffers,\n \t\t\t\t      ConnectionTypeBlocking, this, stream,\n-\t\t\t\t      buffers);\n+\t\t\t\t      count, buffers);\n }\n \n /**\ndiff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp\nindex dabd9219..6a0bb8df 100644\n--- a/src/libcamera/framebuffer_allocator.cpp\n+++ b/src/libcamera/framebuffer_allocator.cpp\n@@ -71,6 +71,7 @@ FrameBufferAllocator::~FrameBufferAllocator()\n /**\n  * \\brief Allocate buffers for a configured stream\n  * \\param[in] stream The stream to allocate buffers for\n+ * \\param[in] count The number of buffers to allocate\n  *\n  * Allocate buffers suitable for capturing frames from the \\a stream. The Camera\n  * shall have been previously configured with Camera::configure() and shall be\n@@ -79,6 +80,10 @@ FrameBufferAllocator::~FrameBufferAllocator()\n  * Upon successful allocation, the allocated buffers can be retrieved with the\n  * buffers() function.\n  *\n+ * This function may allocate less buffers than requested, due to memory and\n+ * other system constraints. The caller shall always check the return value to\n+ * verify if the number of allocate buffers matches its needs.\n+ *\n  * \\return The number of allocated buffers on success or a negative error code\n  * otherwise\n  * \\retval -EACCES The camera is not in a state where buffers can be allocated\n@@ -86,7 +91,7 @@ FrameBufferAllocator::~FrameBufferAllocator()\n  * not part of the active camera configuration\n  * \\retval -EBUSY Buffers are already allocated for the \\a stream\n  */\n-int FrameBufferAllocator::allocate(Stream *stream)\n+int FrameBufferAllocator::allocate(Stream *stream, unsigned int count)\n {\n \tconst auto &[it, inserted] = buffers_.try_emplace(stream);\n \n@@ -95,7 +100,7 @@ int FrameBufferAllocator::allocate(Stream *stream)\n \t\treturn -EBUSY;\n \t}\n \n-\tint ret = camera_->exportFrameBuffers(stream, &it->second);\n+\tint ret = camera_->exportFrameBuffers(stream, count, &it->second);\n \tif (ret == -EINVAL)\n \t\tLOG(Allocator, Error)\n \t\t\t<< \"Stream is not part of \" << camera_->id()\ndiff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\nindex 9e1063d0..434fbd63 100644\n--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n@@ -116,7 +116,7 @@ public:\n \tgenerateConfiguration(Camera *camera, const StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -805,10 +805,9 @@ int PipelineHandlerISI::configure(Camera *camera, CameraConfiguration *c)\n \treturn 0;\n }\n \n-int PipelineHandlerISI::exportFrameBuffers(Camera *camera, Stream *stream,\n+int PipelineHandlerISI::exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n-\tunsigned int count = stream->configuration().bufferCount;\n \tPipe *pipe = pipeFromStream(camera, stream);\n \n \treturn pipe->capture->exportBuffers(count, buffers);\ndiff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex dd7df136..f4cc2467 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -140,7 +140,7 @@ public:\n \t\tconst StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -689,10 +689,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)\n }\n \n int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,\n+\t\t\t\t\t    unsigned int count,\n \t\t\t\t\t    std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tIPU3CameraData *data = cameraData(camera);\n-\tunsigned int count = stream->configuration().bufferCount;\n \n \tif (stream == &data->outStream_)\n \t\treturn data->imgu_->output_->exportBuffers(count, buffers);\ndiff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 4a08d01e..4641c76f 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -328,7 +328,7 @@ public:\n \t\tconst StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -1005,10 +1005,10 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n }\n \n int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,\n+\t\t\t\t\t   unsigned int count,\n \t\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tRPi::Stream *s = static_cast<RPi::Stream *>(stream);\n-\tunsigned int count = stream->configuration().bufferCount;\n \tint ret = s->dev()->exportBuffers(count, buffers);\n \n \ts->setExportedBuffers(buffers);\ndiff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\nindex 76f59f2e..5994b974 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n@@ -149,7 +149,7 @@ public:\n \t\tconst StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -817,10 +817,10 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)\n }\n \n int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,\n+\t\t\t\t\t      unsigned int count,\n \t\t\t\t\t      std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tRkISP1CameraData *data = cameraData(camera);\n-\tunsigned int count = stream->configuration().bufferCount;\n \n \tif (stream == &data->mainPathStream_)\n \t\treturn mainPath_.exportBuffers(count, buffers);\ndiff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex 8ed983fe..6b7c6d5c 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -322,7 +322,7 @@ public:\n \t\tconst StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -1202,10 +1202,10 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n }\n \n int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n+\t\t\t\t\t      unsigned int count,\n \t\t\t\t\t      std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tSimpleCameraData *data = cameraData(camera);\n-\tunsigned int count = stream->configuration().bufferCount;\n \n \t/*\n \t * Export buffers on the converter or capture video node, depending on\ndiff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\nindex 7f580955..4ce240a4 100644\n--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n@@ -78,7 +78,7 @@ public:\n \t\tconst StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -226,11 +226,12 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)\n \treturn 0;\n }\n \n-int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, Stream *stream,\n+int PipelineHandlerUVC::exportFrameBuffers(Camera *camera,\n+\t\t\t\t\t   [[maybe_unused]] Stream *stream,\n+\t\t\t\t\t   unsigned int count,\n \t\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tUVCCameraData *data = cameraData(camera);\n-\tunsigned int count = stream->configuration().bufferCount;\n \n \treturn data->video_->exportBuffers(count, buffers);\n }\ndiff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\nindex d2633be4..e58caf99 100644\n--- a/src/libcamera/pipeline/vimc/vimc.cpp\n+++ b/src/libcamera/pipeline/vimc/vimc.cpp\n@@ -89,7 +89,7 @@ public:\n \t\tconst StreamRoles &roles) override;\n \tint configure(Camera *camera, CameraConfiguration *config) override;\n \n-\tint exportFrameBuffers(Camera *camera, Stream *stream,\n+\tint exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,\n \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n \n \tint start(Camera *camera, const ControlList *controls) override;\n@@ -321,11 +321,12 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)\n \treturn 0;\n }\n \n-int PipelineHandlerVimc::exportFrameBuffers(Camera *camera, Stream *stream,\n+int PipelineHandlerVimc::exportFrameBuffers(Camera *camera,\n+\t\t\t\t\t    [[maybe_unused]] Stream *stream,\n+\t\t\t\t\t    unsigned int count,\n \t\t\t\t\t    std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tVimcCameraData *data = cameraData(camera);\n-\tunsigned int count = stream->configuration().bufferCount;\n \n \treturn data->video_->exportBuffers(count, buffers);\n }\ndiff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\nindex cfade490..fffbd51b 100644\n--- a/src/libcamera/pipeline_handler.cpp\n+++ b/src/libcamera/pipeline_handler.cpp\n@@ -280,6 +280,7 @@ void PipelineHandler::unlockMediaDevices()\n  * \\brief Allocate and export buffers for \\a stream\n  * \\param[in] camera The camera\n  * \\param[in] stream The stream to allocate buffers for\n+ * \\param[in] count The number of buffers to allocate\n  * \\param[out] buffers Array of buffers successfully allocated\n  *\n  * This function allocates buffers for the \\a stream from the devices associated\ndiff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\nindex 7b97c2d5..1c5fab64 100644\n--- a/src/v4l2/v4l2_camera.cpp\n+++ b/src/v4l2/v4l2_camera.cpp\n@@ -160,7 +160,7 @@ int V4L2Camera::allocBuffers(unsigned int count)\n {\n \tStream *stream = config_->at(0).stream();\n \n-\tint ret = bufferAllocator_->allocate(stream);\n+\tint ret = bufferAllocator_->allocate(stream, count);\n \tif (ret < 0)\n \t\treturn ret;\n \ndiff --git a/test/camera/camera_reconfigure.cpp b/test/camera/camera_reconfigure.cpp\nindex 06c87730..63a97863 100644\n--- a/test/camera/camera_reconfigure.cpp\n+++ b/test/camera/camera_reconfigure.cpp\n@@ -17,6 +17,7 @@\n #include <libcamera/base/timer.h>\n \n #include <libcamera/framebuffer_allocator.h>\n+#include <libcamera/property_ids.h>\n \n #include \"camera_test.h\"\n #include \"test.h\"\n@@ -78,7 +79,9 @@ private:\n \t\t * same buffer allocation for each run.\n \t\t */\n \t\tif (!allocated_) {\n-\t\t\tint ret = allocator_->allocate(stream);\n+\t\t\tunsigned int bufferCount =\n+\t\t\t\tcamera_->properties().get(properties::MinimumRequests).value();\n+\t\t\tint ret = allocator_->allocate(stream, bufferCount);\n \t\t\tif (ret < 0) {\n \t\t\t\tcerr << \"Failed to allocate buffers\" << endl;\n \t\t\t\treturn TestFail;\ndiff --git a/test/camera/capture.cpp b/test/camera/capture.cpp\nindex de824083..64d3a8e7 100644\n--- a/test/camera/capture.cpp\n+++ b/test/camera/capture.cpp\n@@ -7,12 +7,13 @@\n \n #include <iostream>\n \n-#include <libcamera/framebuffer_allocator.h>\n-\n #include <libcamera/base/event_dispatcher.h>\n #include <libcamera/base/thread.h>\n #include <libcamera/base/timer.h>\n \n+#include <libcamera/framebuffer_allocator.h>\n+#include <libcamera/property_ids.h>\n+\n #include \"camera_test.h\"\n #include \"test.h\"\n \n@@ -98,8 +99,10 @@ protected:\n \n \t\tStream *stream = cfg.stream();\n \n-\t\tint ret = allocator_->allocate(stream);\n-\t\tif (ret < 0)\n+\t\tunsigned int bufferCount =\n+\t\t\tcamera_->properties().get(properties::MinimumRequests).value();\n+\t\tint ret = allocator_->allocate(stream, bufferCount);\n+\t\tif (ret < static_cast<int>(bufferCount))\n \t\t\treturn TestFail;\n \n \t\tfor (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) {\ndiff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp\nindex 9c2b0c6a..a9ddb323 100644\n--- a/test/camera/statemachine.cpp\n+++ b/test/camera/statemachine.cpp\n@@ -8,6 +8,7 @@\n #include <iostream>\n \n #include <libcamera/framebuffer_allocator.h>\n+#include <libcamera/property_ids.h>\n \n #include \"camera_test.h\"\n #include \"test.h\"\n@@ -120,7 +121,9 @@ protected:\n \t\t/* Use internally allocated buffers. */\n \t\tallocator_ = new FrameBufferAllocator(camera_);\n \t\tStream *stream = *camera_->streams().begin();\n-\t\tif (allocator_->allocate(stream) < 0)\n+\t\tunsigned int bufferCount =\n+\t\t\tcamera_->properties().get(properties::MinimumRequests).value();\n+\t\tif (allocator_->allocate(stream, bufferCount) < 0)\n \t\t\treturn TestFail;\n \n \t\tif (camera_->start())\ndiff --git a/test/fence.cpp b/test/fence.cpp\nindex 1e38bc2f..88ce2857 100644\n--- a/test/fence.cpp\n+++ b/test/fence.cpp\n@@ -18,6 +18,7 @@\n \n #include <libcamera/fence.h>\n #include <libcamera/framebuffer_allocator.h>\n+#include <libcamera/property_ids.h>\n \n #include \"camera_test.h\"\n #include \"test.h\"\n@@ -117,8 +118,11 @@ int FenceTest::init()\n \tStreamConfiguration &cfg = config_->at(0);\n \tstream_ = cfg.stream();\n \n+\tunsigned int bufferCount =\n+\t\tcamera_->properties().get(properties::MinimumRequests).value();\n+\n \tallocator_ = std::make_unique<FrameBufferAllocator>(camera_);\n-\tif (allocator_->allocate(stream_) < 0)\n+\tif (allocator_->allocate(stream_, bufferCount) < 0)\n \t\treturn TestFail;\n \n \tnbuffers_ = allocator_->buffers(stream_).size();\ndiff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp\nindex b4422f7d..1b98feea 100644\n--- a/test/mapped-buffer.cpp\n+++ b/test/mapped-buffer.cpp\n@@ -8,6 +8,7 @@\n #include <iostream>\n \n #include <libcamera/framebuffer_allocator.h>\n+#include <libcamera/property_ids.h>\n \n #include \"libcamera/internal/mapped_framebuffer.h\"\n \n@@ -55,7 +56,9 @@ protected:\n \n \t\tstream_ = cfg.stream();\n \n-\t\tint ret = allocator_->allocate(stream_);\n+\t\tunsigned int bufferCount =\n+\t\t\tcamera_->properties().get(properties::MinimumRequests).value();\n+\t\tint ret = allocator_->allocate(stream_, bufferCount);\n \t\tif (ret < 0)\n \t\t\treturn TestFail;\n \n",
    "prefixes": [
        "libcamera-devel",
        "v10",
        "03/19"
    ]
}