Patch Detail
Show a patch.
GET /api/patches/25466/?format=api
{ "id": 25466, "url": "https://patchwork.libcamera.org/api/patches/25466/?format=api", "web_url": "https://patchwork.libcamera.org/patch/25466/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20251210164055.17856-2-david.plowman@raspberrypi.com>", "date": "2025-12-10T16:15:16", "name": "[01/11] libcamera: Infrastructure to ask for \"memory\" cameras", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "4253aaaf189e9a970475719df65dfb5ad74cb925", "submitter": { "id": 42, "url": "https://patchwork.libcamera.org/api/people/42/?format=api", "name": "David Plowman", "email": "david.plowman@raspberrypi.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/25466/mbox/", "series": [ { "id": 5650, "url": "https://patchwork.libcamera.org/api/series/5650/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5650", "date": "2025-12-10T16:15:15", "name": "Bayer re-processing", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5650/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/25466/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/25466/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 4B211C3257\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 10 Dec 2025 16:41:03 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D296E614B3;\n\tWed, 10 Dec 2025 17:41:02 +0100 (CET)", "from mail-wm1-x332.google.com (mail-wm1-x332.google.com\n\t[IPv6:2a00:1450:4864:20::332])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2AA556149B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 10 Dec 2025 17:41:00 +0100 (CET)", "by mail-wm1-x332.google.com with SMTP id\n\t5b1f17b1804b1-477563e28a3so77485e9.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 10 Dec 2025 08:41:00 -0800 (PST)", "from davidp-pi5.pitowers.org\n\t([2a00:1098:3142:1f:88ea:c658:5b20:5e46])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-47a88371e13sm1270415e9.11.2025.12.10.08.40.57\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 10 Dec 2025 08:40:58 -0800 (PST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"sjRZjNZU\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1765384859; x=1765989659;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=Wtgl8b6OKI9BVILRPi19ZaWqlmqtJLVOkWTLBjKeLR0=;\n\tb=sjRZjNZU2oOh6HeNGCCIYqgu1URx9YQdn7XZX+TDndYNZrdkd6Ro2vgvBPZPhz3nYs\n\toAEYH7V/OfWnzqKHXbMP7krLoLSRr18ScJPX7SXB01VEATN0/Fc/v721X68soSfrl2pJ\n\t28ZiHVEMHxvtRbq2nJpC1QNxKkAT767U8zsC8bjc5XA/Q6IxUwr6UYzw++Mzg94Lp7EK\n\tMjIDbbvxLZXp2Ypz2zvtd8stTaJiZlIpWUFcz1aldeOnVPUffQTeNFQoeqa90Tm8DQM6\n\tGyjQxM70kaRgB7lvFQAAxUyK0YfCWkCNFZd9PQ/RmUMI8ysC+ux8bzsTq9ifO6wGMeXS\n\twTOw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1765384859; x=1765989659;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n\t:to:cc:subject:date:message-id:reply-to;\n\tbh=Wtgl8b6OKI9BVILRPi19ZaWqlmqtJLVOkWTLBjKeLR0=;\n\tb=hdDNOFuY3XbE4HU+BnjnXcg8PDPYxenzcJisR/NCafP9LOnvH4aNtD8K9yDgt0Yb2M\n\tuYtyj9GsqcPYcqOCWMVpylyZWT9P3v51eLZ1a7uT4wP7XCY7Uj938aZHKVAV+WAvOImm\n\t71HXY7Ccb/vjsNlGo/ReF/NhRxec4dgK9Ud4qWLsgDcAlPj1tc5Pop72ZGQl2Et5jyzg\n\tZGtAjhNep/Pqx1cMUySSjGGgRuVaPf5sMx9b1VuEQYYWs15cKeKmBkUwJCPbg4G2Szjy\n\t3Vd0jSVdgIaatMBm/XLDXV1DXIDxiTJA2g2Yw5Pej2NcSV/KKH2kVhXBETLQh2JXA5Vz\n\tdwBw==", "X-Gm-Message-State": "AOJu0Yyfs6JsP6mNRQlagpP2O6IRgySHZQKPK7c8LuwNue98SbpAJdqV\n\tLXq8QKp3z9sGV4J5o7l8sZlrIFUpERsfvcJTflUNNChTh3EIXzQQAbNJ3yqzU/Cr2zYO+Girpnq\n\t+AGxh", "X-Gm-Gg": "ASbGncvFn8Xk+LKrGkQQF41Yw0lkx93jDe0DCTEbImvKySQhpK9o0VU02XhAfZe2uMU\n\tbnHRz1qi5m5rumC6CvBR3iC4+G8JHemK721hSXFv2iJK5Y/wbO0Gv9iojbmtugK5xR2fMQ4X7Pd\n\tUew29gK3JWKMgIaFJ0k+Zj+OR4JxrbhDzmIFORFhrpQJV33XAJEIgaMPlbTctJfXqvoN1dOgGAY\n\tP1jTN6PhEkM15IKAN+uzsw1S7ePDy1VUZkWmYKjo2GPc0cIsl6qXFo/fKmn1jYAAeLgRlddHh83\n\tV6Pa8TOk/RvrtD60qBjWov+EosBuAsygWO6RFNfBvcqSxJTpE6ZNSWmN+OtbbMqHoxPY3BBqDbf\n\tfsfJUNL0VgmxQC8V+lE1pncYVaQ9ZBD1fTbmT3vuZQ8JMML+ICqJ+763/y73s7CFOav++7bTFTi\n\t5s5fLOnKXzQdV6XXF0AsWCCx/IA56LCGO8a4GmLUAvdXoLDjpSa1rKxEeN0cpGcxKoeosF7sPAw\n\teeRIrhN2M4VmxLCivgW0eAn3ftpSg==", "X-Google-Smtp-Source": "AGHT+IHPLrzKdRqu5yH4i1clWtwiIPDmVcjFEO46jOyHRWquJrJB76KskKEf2j/PqMGQtQ18yQtToQ==", "X-Received": "by 2002:a05:600c:4818:b0:479:3a8e:c85c with SMTP id\n\t5b1f17b1804b1-47a888ea47amr48775e9.18.1765384859249; \n\tWed, 10 Dec 2025 08:40:59 -0800 (PST)", "From": "David Plowman <david.plowman@raspberrypi.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "David Plowman <david.plowman@raspberrypi.com>", "Subject": "[PATCH 01/11] libcamera: Infrastructure to ask for \"memory\" cameras", "Date": "Wed, 10 Dec 2025 16:15:16 +0000", "Message-ID": "<20251210164055.17856-2-david.plowman@raspberrypi.com>", "X-Mailer": "git-send-email 2.47.3", "In-Reply-To": "<20251210164055.17856-1-david.plowman@raspberrypi.com>", "References": "<20251210164055.17856-1-david.plowman@raspberrypi.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "\"Memory\" cameras are used to make it easier to process raw camera\nimages that are stored in memory buffers. There may be no actual\ncamera attached to the system at all.\n\nMemory cameras are not created when the system starts. Depending on\nthe pipeline handler, it may be possible to open many memory cameras\nsimultaneously, or none at all. So any time an application requests a\nmemory camera, we check with the pipeline handler whether it can\nprovide one.\n\nSigned-off-by: David Plowman <david.plowman@raspberrypi.com>\n---\n include/libcamera/camera_manager.h | 4 ++\n include/libcamera/internal/camera_manager.h | 5 ++\n include/libcamera/internal/pipeline_handler.h | 8 +++\n src/libcamera/camera_manager.cpp | 64 +++++++++++++++++++\n src/libcamera/pipeline_handler.cpp | 23 +++++++\n 5 files changed, 104 insertions(+)", "diff": "diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h\nindex 27835500..436db409 100644\n--- a/include/libcamera/camera_manager.h\n+++ b/include/libcamera/camera_manager.h\n@@ -7,6 +7,7 @@\n \n #pragma once\n \n+#include <map>\n #include <memory>\n #include <string>\n #include <string_view>\n@@ -20,6 +21,7 @@\n namespace libcamera {\n \n class Camera;\n+class PipelineHandler;\n \n class CameraManager : public Object, public Extensible\n {\n@@ -33,6 +35,8 @@ public:\n \n \tstd::vector<std::shared_ptr<Camera>> cameras() const;\n \tstd::shared_ptr<Camera> get(std::string_view id);\n+\tstd::vector<std::string> memoryCameras() const;\n+\tstd::shared_ptr<Camera> getMemoryCamera(std::string_view id, std::string_view settings);\n \n \tstatic const std::string &version() { return version_; }\n \ndiff --git a/include/libcamera/internal/camera_manager.h b/include/libcamera/internal/camera_manager.h\nindex 755928ce..4dbc1dc8 100644\n--- a/include/libcamera/internal/camera_manager.h\n+++ b/include/libcamera/internal/camera_manager.h\n@@ -55,6 +55,9 @@ private:\n \tvoid pipelineFactoryMatch(const PipelineHandlerFactoryBase *factory);\n \tvoid cleanup() LIBCAMERA_TSA_EXCLUDES(mutex_);\n \n+\tstd::shared_ptr<Camera> getMemoryCamera(const PipelineHandlerFactoryBase *factory,\n+\t\t\t\t\t\tstd::string_view settings);\n+\n \t/*\n \t * This mutex protects\n \t *\n@@ -70,6 +73,8 @@ private:\n \n \tstd::unique_ptr<DeviceEnumerator> enumerator_;\n \n+\tstd::vector<std::string> memoryCameras_;\n+\n \tstd::unique_ptr<IPAManager> ipaManager_;\n \n \tconst GlobalConfiguration configuration_;\ndiff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h\nindex b4f97477..cb631529 100644\n--- a/include/libcamera/internal/pipeline_handler.h\n+++ b/include/libcamera/internal/pipeline_handler.h\n@@ -70,6 +70,14 @@ public:\n \n \tCameraManager *cameraManager() const { return manager_; }\n \n+\tvirtual bool supportsMemoryCamera() { return false; }\n+\n+\tvirtual std::shared_ptr<Camera> createMemoryCamera([[maybe_unused]] DeviceEnumerator *enumerator,\n+\t\t\t\t\t\t\t [[maybe_unused]] std::string_view settings)\n+\t{\n+\t\treturn nullptr;\n+\t}\n+\n protected:\n \tvoid registerCamera(std::shared_ptr<Camera> camera);\n \tvoid hotplugMediaDevice(std::shared_ptr<MediaDevice> media);\ndiff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\nindex 83510e06..734f5836 100644\n--- a/src/libcamera/camera_manager.cpp\n+++ b/src/libcamera/camera_manager.cpp\n@@ -155,6 +155,13 @@ void CameraManager::Private::pipelineFactoryMatch(const PipelineHandlerFactoryBa\n {\n \tCameraManager *const o = LIBCAMERA_O_PTR();\n \n+\t/* First check for any memory-to-memory camera pipelines. */\n+\t{\n+\t\tstd::shared_ptr<PipelineHandler> pipe = factory->create(o);\n+\t\tif (pipe->supportsMemoryCamera())\n+\t\t\tmemoryCameras_.push_back(std::string(pipe->name()));\n+\t}\n+\n \t/* Provide as many matching pipelines as possible. */\n \twhile (1) {\n \t\tstd::shared_ptr<PipelineHandler> pipe = factory->create(o);\n@@ -167,6 +174,19 @@ void CameraManager::Private::pipelineFactoryMatch(const PipelineHandlerFactoryBa\n \t}\n }\n \n+std::shared_ptr<Camera> CameraManager::Private::getMemoryCamera(const PipelineHandlerFactoryBase *factory,\n+\t\t\t\t\t\t\t\tstd::string_view settings)\n+{\n+\tCameraManager *const o = LIBCAMERA_O_PTR();\n+\n+\tstd::shared_ptr<PipelineHandler> pipe = factory->create(o);\n+\n+\tpipe->moveToThread(this);\n+\n+\treturn pipe->invokeMethod(&PipelineHandler::createMemoryCamera,\n+\t\t\t\t ConnectionTypeBlocking, enumerator_.get(), settings);\n+}\n+\n void CameraManager::Private::cleanup()\n {\n \tenumerator_->devicesAdded.disconnect(this);\n@@ -371,6 +391,9 @@ void CameraManager::stop()\n * Before calling this function the caller is responsible for ensuring that\n * the camera manager is running.\n *\n+ * This function does not list any memory cameras (for processing raw images\n+ * held in memory buffers) that may be available.\n+ *\n * \\context This function is \\threadsafe.\n *\n * \\return List of all available cameras\n@@ -409,6 +432,47 @@ std::shared_ptr<Camera> CameraManager::get(std::string_view id)\n \treturn nullptr;\n }\n \n+/**\n+ * \\brief List the pipeline handlers that support memory cameras\n+ *\n+ * Lists the pipeline handlers in the system that have indicated they\n+ * support memory cameras. Memory cameras are used for processing raw\n+ * camera images stored in memory buffers, where no corresponding\n+ * camera is available.\n+ *\n+ * \\return Vector of pipeline handler ids (strings)\n+ */\n+std::vector<std::string> CameraManager::memoryCameras() const\n+{\n+\treturn _d()->memoryCameras_;\n+}\n+\n+/**\n+ * \\brief Get a memory camera from the named pipeline handler\n+ * \\param[in] id ID of the pipeline handler that should create the memory camera\n+ *\n+ * This function causes the named pipeline handler to create and return a\n+ * memory camera to the application. Pipeline handlers may support multiple\n+ * simultaneous memory cameras, or none at all.\n+ *\n+ * \\return Shared pointer to Camera object or nullptr if no memory camera\n+ * could be provided\n+ */\n+std::shared_ptr<Camera> CameraManager::getMemoryCamera(std::string_view id,\n+\t\t\t\t\t\t std::string_view settings)\n+{\n+\tfor (const auto &name : _d()->memoryCameras_) {\n+\t\tif (name == id) {\n+\t\t\tconst PipelineHandlerFactoryBase *factory;\n+\t\t\tfactory = PipelineHandlerFactoryBase::getFactoryByName(name);\n+\n+\t\t\treturn _d()->getMemoryCamera(factory, settings);\n+\t\t}\n+\t}\n+\n+\treturn nullptr;\n+}\n+\n /**\n * \\var CameraManager::cameraAdded\n * \\brief Notify of a new camera added to the system\ndiff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\nindex 5c469e5b..c0f3c84e 100644\n--- a/src/libcamera/pipeline_handler.cpp\n+++ b/src/libcamera/pipeline_handler.cpp\n@@ -835,6 +835,29 @@ void PipelineHandler::disconnect()\n * \\return The CameraManager for this pipeline handler\n */\n \n+/**\n+ * \\fn PipelineHandler::supportsMemoryCamera()\n+ * \\brief Indicate whether this pipeline handler supports memory cameras.\n+ * \\return True if the pipeline handler supports memory cameras, otherwise false.\n+ */\n+\n+/**\n+ * \\fn PipelineHandler::createMemoryCamera()\n+ * \\brief Create a memory camera to process raw camera images from a memory buffer\n+ * \\param[in] enumerator The enumerator providing all media devices found in the\n+ * system\n+ * \\param[in] settings A string of settings that the pipeline handler should use\n+ *\n+ * The pipeline handler should create a memory camera, which an application can\n+ * use to process raw camera images that are stored in memory buffers (rather\n+ * than being delivered from a live camera).\n+ *\n+ * The settings should indicate exactly what processing the application requires\n+ * to be performed on the raw image.\n+ *\n+ * \\return Shared pointer to a camera, or a nullptr if none could be created\n+ */\n+\n /**\n * \\class PipelineHandlerFactoryBase\n * \\brief Base class for pipeline handler factories\n", "prefixes": [ "01/11" ] }