Show a patch.

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

{
    "id": 2373,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/2373/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/2373/",
    "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": "<20191126233620.1695316-26-niklas.soderlund@ragnatech.se>",
    "date": "2019-11-26T23:36:15",
    "name": "[libcamera-devel,25/30] libcamera: allocator: Add BufferAllocator to help applications allocate buffers",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "a13e33db80808ece5a879fb902ac6c85bd8a74c6",
    "submitter": {
        "id": 5,
        "url": "https://patchwork.libcamera.org/api/1.1/people/5/?format=api",
        "name": "Niklas Söderlund",
        "email": "niklas.soderlund@ragnatech.se"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/2373/mbox/",
    "series": [
        {
            "id": 579,
            "url": "https://patchwork.libcamera.org/api/1.1/series/579/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=579",
            "date": "2019-11-26T23:35:50",
            "name": "libcamera: Rework buffer API",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/579/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/2373/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/2373/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<niklas.soderlund@ragnatech.se>",
        "Received": [
            "from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net\n\t[195.74.38.229])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 607CF61C59\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 27 Nov 2019 00:39:45 +0100 (CET)",
            "from bismarck.berto.se (p54ac5865.dip0.t-ipconnect.de\n\t[84.172.88.101]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA\n\tid 05b440e8-10a6-11ea-a0b9-005056917f90;\n\tWed, 27 Nov 2019 00:39:43 +0100 (CET)"
        ],
        "X-Halon-ID": "05b440e8-10a6-11ea-a0b9-005056917f90",
        "Authorized-sender": "niklas@soderlund.pp.se",
        "From": "=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 27 Nov 2019 00:36:15 +0100",
        "Message-Id": "<20191126233620.1695316-26-niklas.soderlund@ragnatech.se>",
        "X-Mailer": "git-send-email 2.24.0",
        "In-Reply-To": "<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>",
        "References": "<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 25/30] libcamera: allocator: Add\n\tBufferAllocator to help applications allocate buffers",
        "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>",
        "X-List-Received-Date": "Tue, 26 Nov 2019 23:39:45 -0000"
    },
    "content": "The FrameBuffer interface is based on the idea that all buffers are\nallocated outside libcamera and are only used by it. This is done to\nmake the API simpler and so that both internal and external buffers are\nhandled in the same way.\n\nAs V4L2 do not provide a way to allocate buffers without the help of a\nvideo device add an application facing helper which hide this. This\nallow applications to allocate buffers and then use them with cameras.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n include/libcamera/allocator.h |  39 ++++++++++\n include/libcamera/meson.build |   1 +\n include/libcamera/stream.h    |   1 +\n src/libcamera/allocator.cpp   | 141 ++++++++++++++++++++++++++++++++++\n src/libcamera/meson.build     |   1 +\n 5 files changed, 183 insertions(+)\n create mode 100644 include/libcamera/allocator.h\n create mode 100644 src/libcamera/allocator.cpp",
    "diff": "diff --git a/include/libcamera/allocator.h b/include/libcamera/allocator.h\nnew file mode 100644\nindex 0000000000000000..36fce38491b5f3ef\n--- /dev/null\n+++ b/include/libcamera/allocator.h\n@@ -0,0 +1,39 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * allocator.h - Buffer allocator\n+ */\n+#ifndef __LIBCAMERA_ALLOCATOR_H__\n+#define __LIBCAMERA_ALLOCATOR_H__\n+\n+#include <map>\n+#include <memory>\n+#include <vector>\n+\n+namespace libcamera {\n+\n+class Camera;\n+class FrameBuffer;\n+class Stream;\n+struct StreamConfiguration;\n+\n+class BufferAllocator\n+{\n+public:\n+\tBufferAllocator(std::shared_ptr<Camera> camera);\n+\t~BufferAllocator();\n+\n+\tint allocate(Stream *stream, const StreamConfiguration &config);\n+\tvoid release(Stream *stream);\n+\n+\tconst std::vector<FrameBuffer *> &buffers(Stream *stream) const;\n+\n+private:\n+\tstd::shared_ptr<Camera> camera_;\n+\tstd::map<Stream *, std::vector<FrameBuffer *>> buffers_;\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_ALLOCATOR_H__ */\ndiff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\nindex 99abf06099407c1f..0d0ba2248fd8a679 100644\n--- a/include/libcamera/meson.build\n+++ b/include/libcamera/meson.build\n@@ -1,4 +1,5 @@\n libcamera_api = files([\n+    'allocator.h',\n     'bound_method.h',\n     'buffer.h',\n     'camera.h',\ndiff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\nindex a3c692c347340382..8e653408fd54cf74 100644\n--- a/include/libcamera/stream.h\n+++ b/include/libcamera/stream.h\n@@ -85,6 +85,7 @@ public:\n \tMemoryType memoryType() const { return memoryType_; }\n \n protected:\n+\tfriend class BufferAllocator; /* To allocate and release buffers. */\n \tfriend class Camera;\n \n \tvirtual int allocateBuffers(const StreamConfiguration &config,\ndiff --git a/src/libcamera/allocator.cpp b/src/libcamera/allocator.cpp\nnew file mode 100644\nindex 0000000000000000..8b517c809c05cbcd\n--- /dev/null\n+++ b/src/libcamera/allocator.cpp\n@@ -0,0 +1,141 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * allocator.cpp - Buffer allocator\n+ */\n+\n+#include <libcamera/allocator.h>\n+\n+#include <errno.h>\n+#include <string.h>\n+#include <sys/mman.h>\n+#include <unistd.h>\n+\n+#include <libcamera/camera.h>\n+#include <libcamera/stream.h>\n+\n+#include \"log.h\"\n+\n+/**\n+ * \\file allocator.h\n+ * \\brief Buffer allocator\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(Allocator)\n+\n+/**\n+ * \\class BufferAllocator\n+ * \\brief Buffer allocator for applications\n+ *\n+ * All buffers are to be treated as if they where allocated outside of the\n+ * camera. In some situations however the only source applications can allocate\n+ * buffers from is the camera. The BufferAllocator is the interface applications\n+ * shall use in these situations.\n+ *\n+ * The buffer allocator creates buffers using resources from a camera and/or\n+ * a stream. The buffers allocated this way are owned by the application and it\n+ * is responsible for their lifetime management. But just as buffers allocated\n+ * external from cameras and streams it's not valid to free a buffer while it's\n+ * queue to a camera.\n+ *\n+ * All buffers allocator are automatically freed when the allocator object is\n+ * deleted. It is the applications responsibility to make sure this do not\n+ * happen while one or more of the buffers are queued to a camera.\n+ *\n+ * If buffers are allocated outside the scope of libcamera by the application it\n+ * do not need to interact with the buffer allocator.\n+ */\n+\n+/**\n+ * \\brief Create a BufferAllocator serving a camera\n+ * \\param[in] camera Camera the allocator shall serve\n+ */\n+\n+BufferAllocator::BufferAllocator(std::shared_ptr<Camera> camera)\n+\t: camera_(camera)\n+{\n+}\n+\n+BufferAllocator::~BufferAllocator()\n+{\n+\tfor (auto &value : buffers_) {\n+\t\tStream *stream = value.first;\n+\t\tstd::vector<FrameBuffer *> &buffers = value.second;\n+\n+\t\tfor (FrameBuffer *buffer : buffers)\n+\t\t\tdelete buffer;\n+\n+\t\tbuffers.clear();\n+\n+\t\tstream->releaseBuffers();\n+\t}\n+\n+\tbuffers_.clear();\n+}\n+\n+/**\n+ * \\brief Allocate buffers from a stream\n+ * \\param[in] stream The stream to allocate buffers from\n+ * \\param[in] config The configuration described the buffers to be allocated\n+ *\n+ * Allocate buffers matching exactly what is described in \\a config. If buffers\n+ * matching \\a config can't be allocated an error is returned and no buffers are\n+ * allocated.\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int BufferAllocator::allocate(Stream *stream, const StreamConfiguration &config)\n+{\n+\tauto iter = camera_->streams().find(stream);\n+\tif (iter != camera_->streams().end())\n+\t\treturn stream->allocateBuffers(config, &buffers_[stream]);\n+\n+\tLOG(Allocator, Error) << \"Stream do not belong to \" << camera_->name();\n+\treturn -EINVAL;\n+}\n+\n+/**\n+ * \\brief Free allocated buffers\n+ * \\param[in] stream The stream to free buffers for\n+ *\n+ * Free buffers allocated with allocate().\n+ */\n+void BufferAllocator::release(Stream *stream)\n+{\n+\tauto iter = buffers_.find(stream);\n+\tif (iter == buffers_.end())\n+\t\treturn;\n+\n+\tstd::vector<FrameBuffer *> &buffers = iter->second;\n+\n+\tfor (FrameBuffer *buffer : buffers)\n+\t\tdelete buffer;\n+\n+\tbuffers.clear();\n+\n+\tstream->releaseBuffers();\n+\n+\tbuffers_.erase(iter);\n+}\n+\n+/**\n+ * \\brief Retrive array of allocated buffers\n+ * \\param[in] stream The stream to retrive buffers for\n+ *\n+ * \\return Array of buffers\n+ */\n+const std::vector<FrameBuffer *> &BufferAllocator::buffers(Stream *stream) const\n+{\n+\tstatic std::vector<FrameBuffer *> empty;\n+\n+\tauto iter = buffers_.find(stream);\n+\tif (iter == buffers_.end())\n+\t\treturn empty;\n+\n+\treturn iter->second;\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\nindex c4f965bd7413b37e..b7041e003fdb1d49 100644\n--- a/src/libcamera/meson.build\n+++ b/src/libcamera/meson.build\n@@ -1,4 +1,5 @@\n libcamera_sources = files([\n+    'allocator.cpp',\n     'bound_method.cpp',\n     'buffer.cpp',\n     'byte_stream_buffer.cpp',\n",
    "prefixes": [
        "libcamera-devel",
        "25/30"
    ]
}