Show a patch.

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

{
    "id": 12622,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/12622/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/12622/",
    "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": "<20210616151152.3856595-7-kieran.bingham@ideasonboard.com>",
    "date": "2021-06-16T15:11:52",
    "name": "[libcamera-devel,6/6] libcamera-helpers: Provide helper library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "516517c8ac151f0bfab8c38ca50b2ab601f31876",
    "submitter": {
        "id": 4,
        "url": "https://patchwork.libcamera.org/api/1.1/people/4/?format=api",
        "name": "Kieran Bingham",
        "email": "kieran.bingham@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/12622/mbox/",
    "series": [
        {
            "id": 2143,
            "url": "https://patchwork.libcamera.org/api/1.1/series/2143/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2143",
            "date": "2021-06-16T15:11:46",
            "name": "libcamera-platform: Split library functionality",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/2143/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/12622/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/12622/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 5BD98C321C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 16 Jun 2021 15:12:04 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1054068960;\n\tWed, 16 Jun 2021 17:12:04 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E056E68950\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 16 Jun 2021 17:11:58 +0200 (CEST)",
            "from Monstersaurus.local\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 90B1F1163;\n\tWed, 16 Jun 2021 17:11:58 +0200 (CEST)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"VGea3kIc\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1623856318;\n\tbh=xWzfC5Z7o3yRsI69gSMa/oqEWXIs8ZupRDeD3MS8xjw=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=VGea3kIcFQjp7Ob2XNoxq69c2MVLGmSMMqpT/5YQbiTiGwRTpCBaG9IHzQG5NmG+l\n\tm05451OSYhD+/WryNjSAgtpfx66UR86sqmDhN2NjRG0I4tHxiQMEf/urBjeBAKep7f\n\tFR0DApu4jAZntb+rvlHr9xl9QQNnMsVJPBhQ6DFU=",
        "From": "Kieran Bingham <kieran.bingham@ideasonboard.com>",
        "To": "libcamera devel <libcamera-devel@lists.libcamera.org>",
        "Date": "Wed, 16 Jun 2021 16:11:52 +0100",
        "Message-Id": "<20210616151152.3856595-7-kieran.bingham@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20210616151152.3856595-1-kieran.bingham@ideasonboard.com>",
        "References": "<20210616151152.3856595-1-kieran.bingham@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 6/6] libcamera-helpers: Provide helper\n\tlibrary",
        "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": "Provide a library which build support on top of the libcamera API.\n\nThis currently implements the MappedBuffer and MappedFrameBuffer classes\nwhich help with lifetime management of mmapping libcamera buffers.\n\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n---\n Documentation/Doxyfile.in                     |   2 +\n .../buffer.h => helpers/mapped_buffer.h}      |  10 +-\n include/libcamera/helpers/meson.build         |  10 +\n include/libcamera/internal/meson.build        |   1 -\n include/libcamera/meson.build                 |   1 +\n src/android/camera_device.h                   |   2 +-\n src/android/camera_stream.h                   |   2 +-\n src/android/jpeg/encoder_libjpeg.h            |   3 +-\n src/android/jpeg/post_processor_jpeg.h        |   2 +-\n src/android/jpeg/thumbnailer.h                |   3 +-\n src/android/meson.build                       |   1 +\n src/android/mm/generic_camera_buffer.cpp      |   2 +-\n src/android/post_processor.h                  |   2 +-\n src/ipa/ipu3/ipu3.cpp                         |   2 +-\n src/ipa/ipu3/meson.build                      |   2 +-\n src/ipa/raspberrypi/meson.build               |   1 +\n src/ipa/raspberrypi/raspberrypi.cpp           |   2 +-\n src/libcamera-helpers/mapped_buffer.cpp       | 171 ++++++++++++++++++\n src/libcamera/buffer.cpp                      | 149 ---------------\n .../pipeline/raspberrypi/raspberrypi.cpp      |   3 +-\n src/meson.build                               |   1 +\n test/mapped-buffer.cpp                        |   3 +-\n test/meson.build                              |  14 +-\n 23 files changed, 220 insertions(+), 169 deletions(-)\n rename include/libcamera/{internal/buffer.h => helpers/mapped_buffer.h} (81%)\n create mode 100644 include/libcamera/helpers/meson.build\n create mode 100644 src/libcamera-helpers/mapped_buffer.cpp",
    "diff": "diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\nindex c1b395bf0b83..e67775b99d26 100644\n--- a/Documentation/Doxyfile.in\n+++ b/Documentation/Doxyfile.in\n@@ -791,9 +791,11 @@ WARN_LOGFILE           =\n INPUT                  = \"@TOP_SRCDIR@/include/libcamera\" \\\n \t\t\t \"@TOP_SRCDIR@/src/ipa/libipa\" \\\n \t\t\t \"@TOP_SRCDIR@/src/libcamera\" \\\n+\t\t\t \"@TOP_SRCDIR@/src/libcamera-helpers\" \\\n \t\t\t \"@TOP_SRCDIR@/src/libcamera-platform\" \\\n \t\t\t \"@TOP_BUILDDIR@/include/libcamera\" \\\n \t\t\t \"@TOP_BUILDDIR@/src/libcamera\" \\\n+\t\t\t \"@TOP_BUILDDIR@/src/libcamera-helpers\" \\\n \t\t\t \"@TOP_BUILDDIR@/src/libcamera-platform\"\n \n # This tag can be used to specify the character encoding of the source files\ndiff --git a/include/libcamera/internal/buffer.h b/include/libcamera/helpers/mapped_buffer.h\nsimilarity index 81%\nrename from include/libcamera/internal/buffer.h\nrename to include/libcamera/helpers/mapped_buffer.h\nindex 9da1fbd12c27..ece24f2ddd2c 100644\n--- a/include/libcamera/internal/buffer.h\n+++ b/include/libcamera/helpers/mapped_buffer.h\n@@ -2,16 +2,16 @@\n /*\n  * Copyright (C) 2020, Google Inc.\n  *\n- * buffer.h - Internal buffer handling\n+ * mapped_buffer.h - Mapped Buffer handling\n  */\n-#ifndef __LIBCAMERA_INTERNAL_BUFFER_H__\n-#define __LIBCAMERA_INTERNAL_BUFFER_H__\n+#ifndef __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__\n+#define __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__\n \n #include <sys/mman.h>\n #include <vector>\n \n-#include <libcamera/class.h>\n #include <libcamera/buffer.h>\n+#include <libcamera/class.h>\n #include <libcamera/span.h>\n \n namespace libcamera {\n@@ -48,4 +48,4 @@ public:\n \n } /* namespace libcamera */\n \n-#endif /* __LIBCAMERA_INTERNAL_BUFFER_H__ */\n+#endif /* __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__ */\ndiff --git a/include/libcamera/helpers/meson.build b/include/libcamera/helpers/meson.build\nnew file mode 100644\nindex 000000000000..c025eb930600\n--- /dev/null\n+++ b/include/libcamera/helpers/meson.build\n@@ -0,0 +1,10 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+libcamera_helpers_include_dir = libcamera_include_dir / 'helpers'\n+\n+libcamera_helpers_headers = files([\n+    'mapped_buffer.h',\n+])\n+\n+install_headers(libcamera_helpers_headers,\n+                subdir: libcamera_helpers_include_dir)\ndiff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build\nindex 1187cc1f63e4..ecd0c8ba183e 100644\n--- a/include/libcamera/internal/meson.build\n+++ b/include/libcamera/internal/meson.build\n@@ -11,7 +11,6 @@ libcamera_tracepoint_header = custom_target(\n \n libcamera_internal_headers = files([\n     'bayer_format.h',\n-    'buffer.h',\n     'byte_stream_buffer.h',\n     'camera_controls.h',\n     'camera_sensor.h',\ndiff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\nindex 7bfcebc79c86..7c98d8744ec2 100644\n--- a/include/libcamera/meson.build\n+++ b/include/libcamera/meson.build\n@@ -20,6 +20,7 @@ libcamera_public_headers = files([\n \n include_dir = libcamera_include_dir / 'libcamera'\n \n+subdir('helpers')\n subdir('internal')\n subdir('ipa')\n subdir('platform')\ndiff --git a/src/android/camera_device.h b/src/android/camera_device.h\nindex b9be3df58084..26e5bbc0c26c 100644\n--- a/src/android/camera_device.h\n+++ b/src/android/camera_device.h\n@@ -25,7 +25,7 @@\n #include <libcamera/platform/message.h>\n #include <libcamera/platform/thread.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n #include \"camera_metadata.h\"\n #include \"camera_stream.h\"\ndiff --git a/src/android/camera_stream.h b/src/android/camera_stream.h\nindex 3401672233ca..12484cb607ed 100644\n--- a/src/android/camera_stream.h\n+++ b/src/android/camera_stream.h\n@@ -19,7 +19,7 @@\n #include <libcamera/geometry.h>\n #include <libcamera/pixel_format.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n class CameraDevice;\n class CameraMetadata;\ndiff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h\nindex 838da7728382..ca7c1958e20e 100644\n--- a/src/android/jpeg/encoder_libjpeg.h\n+++ b/src/android/jpeg/encoder_libjpeg.h\n@@ -9,7 +9,8 @@\n \n #include \"encoder.h\"\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n+\n #include \"libcamera/internal/formats.h\"\n \n #include <jpeglib.h>\ndiff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h\nindex 5d2d4ab224b1..4700a7f562a2 100644\n--- a/src/android/jpeg/post_processor_jpeg.h\n+++ b/src/android/jpeg/post_processor_jpeg.h\n@@ -13,7 +13,7 @@\n \n #include <libcamera/geometry.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n class CameraDevice;\n \ndiff --git a/src/android/jpeg/thumbnailer.h b/src/android/jpeg/thumbnailer.h\nindex 4e9226c34104..483b41dfe47d 100644\n--- a/src/android/jpeg/thumbnailer.h\n+++ b/src/android/jpeg/thumbnailer.h\n@@ -9,7 +9,8 @@\n \n #include <libcamera/geometry.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n+\n #include \"libcamera/internal/formats.h\"\n \n class Thumbnailer\ndiff --git a/src/android/meson.build b/src/android/meson.build\nindex 6edaa1185905..abde9fd2def0 100644\n--- a/src/android/meson.build\n+++ b/src/android/meson.build\n@@ -5,6 +5,7 @@ android_deps = [\n     dependency('libjpeg', required : get_option('android')),\n     dependency('yaml-0.1', required : get_option('android')),\n     libcamera_dep,\n+    libcamera_helpers,\n ]\n \n android_enabled = true\ndiff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp\nindex f138ada14964..64c73c5716ad 100644\n--- a/src/android/mm/generic_camera_buffer.cpp\n+++ b/src/android/mm/generic_camera_buffer.cpp\n@@ -11,7 +11,7 @@\n \n #include <libcamera/platform/log.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n using namespace libcamera;\n \ndiff --git a/src/android/post_processor.h b/src/android/post_processor.h\nindex 547fda379ed8..53220edaf24d 100644\n--- a/src/android/post_processor.h\n+++ b/src/android/post_processor.h\n@@ -10,7 +10,7 @@\n #include <libcamera/buffer.h>\n #include <libcamera/stream.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n #include \"camera_buffer.h\"\n \ndiff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp\nindex ca1ce4dc96d0..158eb3bc49e5 100644\n--- a/src/ipa/ipu3/ipu3.cpp\n+++ b/src/ipa/ipu3/ipu3.cpp\n@@ -20,7 +20,7 @@\n \n #include <libcamera/platform/log.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n #include \"ipu3_agc.h\"\n #include \"ipu3_awb.h\"\ndiff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build\nindex 0d843846acde..34620024def7 100644\n--- a/src/ipa/ipu3/meson.build\n+++ b/src/ipa/ipu3/meson.build\n@@ -12,7 +12,7 @@ mod = shared_module(ipa_name,\n                     [ipu3_ipa_sources, libcamera_generated_ipa_headers],\n                     name_prefix : '',\n                     include_directories : [ipa_includes, libipa_includes],\n-                    dependencies : libcamera_dep,\n+                    dependencies : [libcamera_dep, libcamera_helpers],\n                     link_with : libipa,\n                     install : true,\n                     install_dir : ipa_install_dir)\ndiff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build\nindex 230356d3ce3a..b2ce6f3e8618 100644\n--- a/src/ipa/raspberrypi/meson.build\n+++ b/src/ipa/raspberrypi/meson.build\n@@ -4,6 +4,7 @@ ipa_name = 'ipa_rpi'\n \n rpi_ipa_deps = [\n     libcamera_dep,\n+    libcamera_helpers,\n     dependency('boost'),\n     libatomic,\n ]\ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex 90f35d970fd0..b85a1e51d757 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -26,7 +26,7 @@\n \n #include <libcamera/platform/log.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n #include <linux/bcm2835-isp.h>\n \ndiff --git a/src/libcamera-helpers/mapped_buffer.cpp b/src/libcamera-helpers/mapped_buffer.cpp\nnew file mode 100644\nindex 000000000000..0d4517b62f65\n--- /dev/null\n+++ b/src/libcamera-helpers/mapped_buffer.cpp\n@@ -0,0 +1,171 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2021, Google Inc.\n+ *\n+ * mapped_buffer.cpp - Mapped Buffer handling\n+ */\n+\n+#include <libcamera/helpers/mapped_buffer.h>\n+\n+#include <errno.h>\n+#include <string.h>\n+#include <sys/mman.h>\n+#include <unistd.h>\n+\n+#include <libcamera/platform/log.h>\n+\n+/**\n+ * \\file libcamera/helpers/mapped_buffer.h\n+ * \\brief Mapped Buffer handling\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(MappedBuffer)\n+\n+/**\n+ * \\class MappedBuffer\n+ * \\brief Provide an interface to support managing memory mapped buffers\n+ *\n+ * The MappedBuffer interface provides access to a set of MappedPlanes which\n+ * are available for access by the CPU.\n+ *\n+ * This class is not meant to be constructed directly, but instead derived\n+ * classes should be used to implement the correct mapping of a source buffer.\n+ *\n+ * This allows treating CPU accessible memory through a generic interface\n+ * regardless of whether it originates from a libcamera FrameBuffer or other\n+ * source.\n+ */\n+\n+/**\n+ * \\typedef MappedBuffer::Plane\n+ * \\brief A mapped region of memory accessible to the CPU\n+ *\n+ * The MappedBuffer::Plane uses the Span interface to describe the mapped memory\n+ * region.\n+ */\n+\n+/**\n+ * \\brief Construct an empty MappedBuffer\n+ */\n+MappedBuffer::MappedBuffer()\n+\t: error_(0)\n+{\n+}\n+\n+/**\n+ * \\brief Move constructor, construct the MappedBuffer with the contents of \\a\n+ * other using move semantics\n+ * \\param[in] other The other MappedBuffer\n+ *\n+ * Moving a MappedBuffer moves the mappings contained in the \\a other to the new\n+ * MappedBuffer and invalidates the \\a other.\n+ *\n+ * No mappings are unmapped or destroyed in this process.\n+ */\n+MappedBuffer::MappedBuffer(MappedBuffer &&other)\n+{\n+\t*this = std::move(other);\n+}\n+\n+/**\n+ * \\brief Move assignment operator, replace the mappings with those of \\a other\n+* \\param[in] other The other MappedBuffer\n+ *\n+ * Moving a MappedBuffer moves the mappings contained in the \\a other to the new\n+ * MappedBuffer and invalidates the \\a other.\n+ *\n+ * No mappings are unmapped or destroyed in this process.\n+ */\n+MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)\n+{\n+\terror_ = other.error_;\n+\tmaps_ = std::move(other.maps_);\n+\tother.error_ = -ENOENT;\n+\n+\treturn *this;\n+}\n+\n+MappedBuffer::~MappedBuffer()\n+{\n+\tfor (Plane &map : maps_)\n+\t\tmunmap(map.data(), map.size());\n+}\n+\n+/**\n+ * \\fn MappedBuffer::isValid()\n+ * \\brief Check if the MappedBuffer instance is valid\n+ * \\return True if the MappedBuffer has valid mappings, false otherwise\n+ */\n+\n+/**\n+ * \\fn MappedBuffer::error()\n+ * \\brief Retrieve the map error status\n+ *\n+ * This function retrieves the error status from the MappedBuffer.\n+ * The error status is a negative number as defined by errno.h. If\n+ * no error occurred, this function returns 0.\n+ *\n+ * \\return The map error code\n+ */\n+\n+/**\n+ * \\fn MappedBuffer::maps()\n+ * \\brief Retrieve the mapped planes\n+ *\n+ * This function retrieves the successfully mapped planes stored as a vector\n+ * of Span<uint8_t> to provide access to the mapped memory.\n+ *\n+ * \\return A vector of the mapped planes\n+ */\n+\n+/**\n+ * \\var MappedBuffer::error_\n+ * \\brief Stores the error value if present\n+ *\n+ * MappedBuffer derived classes shall set this to a negative value as defined\n+ * by errno.h if an error occured during the mapping process.\n+ */\n+\n+/**\n+ * \\var MappedBuffer::maps_\n+ * \\brief Stores the internal mapped planes\n+ *\n+ * MappedBuffer derived classes shall store the mappings they create in this\n+ * vector which is parsed during destruct to unmap any memory mappings which\n+ * completed successfully.\n+ */\n+\n+/**\n+ * \\class MappedFrameBuffer\n+ * \\brief Map a FrameBuffer using the MappedBuffer interface\n+ */\n+\n+/**\n+ * \\brief Map all planes of a FrameBuffer\n+ * \\param[in] buffer FrameBuffer to be mapped\n+ * \\param[in] flags Protection flags to apply to map\n+ *\n+ * Construct an object to map a frame buffer for CPU access.\n+ * The flags are passed directly to mmap and should be either PROT_READ,\n+ * PROT_WRITE, or a bitwise-or combination of both.\n+ */\n+MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)\n+{\n+\tmaps_.reserve(buffer->planes().size());\n+\n+\tfor (const FrameBuffer::Plane &plane : buffer->planes()) {\n+\t\tvoid *address = mmap(nullptr, plane.length, flags,\n+\t\t\t\t     MAP_SHARED, plane.fd.fd(), 0);\n+\t\tif (address == MAP_FAILED) {\n+\t\t\terror_ = -errno;\n+\t\t\tLOG(MappedBuffer, Error) << \"Failed to mmap plane\";\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tmaps_.emplace_back(static_cast<uint8_t *>(address), plane.length);\n+\t}\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp\nindex 3c862820e6e1..0a232d791fcd 100644\n--- a/src/libcamera/buffer.cpp\n+++ b/src/libcamera/buffer.cpp\n@@ -6,7 +6,6 @@\n  */\n \n #include <libcamera/buffer.h>\n-#include \"libcamera/internal/buffer.h\"\n \n #include <errno.h>\n #include <string.h>\n@@ -18,9 +17,6 @@\n /**\n  * \\file libcamera/buffer.h\n  * \\brief Buffer handling\n- *\n- * \\file libcamera/internal/buffer.h\n- * \\brief Internal buffer handling support\n  */\n \n namespace libcamera {\n@@ -235,149 +231,4 @@ FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)\n  * indicate that the metadata is invalid.\n  */\n \n-/**\n- * \\class MappedBuffer\n- * \\brief Provide an interface to support managing memory mapped buffers\n- *\n- * The MappedBuffer interface provides access to a set of MappedPlanes which\n- * are available for access by the CPU.\n- *\n- * This class is not meant to be constructed directly, but instead derived\n- * classes should be used to implement the correct mapping of a source buffer.\n- *\n- * This allows treating CPU accessible memory through a generic interface\n- * regardless of whether it originates from a libcamera FrameBuffer or other\n- * source.\n- */\n-\n-/**\n- * \\typedef MappedBuffer::Plane\n- * \\brief A mapped region of memory accessible to the CPU\n- *\n- * The MappedBuffer::Plane uses the Span interface to describe the mapped memory\n- * region.\n- */\n-\n-/**\n- * \\brief Construct an empty MappedBuffer\n- */\n-MappedBuffer::MappedBuffer()\n-\t: error_(0)\n-{\n-}\n-\n-/**\n- * \\brief Move constructor, construct the MappedBuffer with the contents of \\a\n- * other using move semantics\n- * \\param[in] other The other MappedBuffer\n- *\n- * Moving a MappedBuffer moves the mappings contained in the \\a other to the new\n- * MappedBuffer and invalidates the \\a other.\n- *\n- * No mappings are unmapped or destroyed in this process.\n- */\n-MappedBuffer::MappedBuffer(MappedBuffer &&other)\n-{\n-\t*this = std::move(other);\n-}\n-\n-/**\n- * \\brief Move assignment operator, replace the mappings with those of \\a other\n-* \\param[in] other The other MappedBuffer\n- *\n- * Moving a MappedBuffer moves the mappings contained in the \\a other to the new\n- * MappedBuffer and invalidates the \\a other.\n- *\n- * No mappings are unmapped or destroyed in this process.\n- */\n-MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)\n-{\n-\terror_ = other.error_;\n-\tmaps_ = std::move(other.maps_);\n-\tother.error_ = -ENOENT;\n-\n-\treturn *this;\n-}\n-\n-MappedBuffer::~MappedBuffer()\n-{\n-\tfor (Plane &map : maps_)\n-\t\tmunmap(map.data(), map.size());\n-}\n-\n-/**\n- * \\fn MappedBuffer::isValid()\n- * \\brief Check if the MappedBuffer instance is valid\n- * \\return True if the MappedBuffer has valid mappings, false otherwise\n- */\n-\n-/**\n- * \\fn MappedBuffer::error()\n- * \\brief Retrieve the map error status\n- *\n- * This function retrieves the error status from the MappedBuffer.\n- * The error status is a negative number as defined by errno.h. If\n- * no error occurred, this function returns 0.\n- *\n- * \\return The map error code\n- */\n-\n-/**\n- * \\fn MappedBuffer::maps()\n- * \\brief Retrieve the mapped planes\n- *\n- * This function retrieves the successfully mapped planes stored as a vector\n- * of Span<uint8_t> to provide access to the mapped memory.\n- *\n- * \\return A vector of the mapped planes\n- */\n-\n-/**\n- * \\var MappedBuffer::error_\n- * \\brief Stores the error value if present\n- *\n- * MappedBuffer derived classes shall set this to a negative value as defined\n- * by errno.h if an error occured during the mapping process.\n- */\n-\n-/**\n- * \\var MappedBuffer::maps_\n- * \\brief Stores the internal mapped planes\n- *\n- * MappedBuffer derived classes shall store the mappings they create in this\n- * vector which is parsed during destruct to unmap any memory mappings which\n- * completed successfully.\n- */\n-\n-/**\n- * \\class MappedFrameBuffer\n- * \\brief Map a FrameBuffer using the MappedBuffer interface\n- */\n-\n-/**\n- * \\brief Map all planes of a FrameBuffer\n- * \\param[in] buffer FrameBuffer to be mapped\n- * \\param[in] flags Protection flags to apply to map\n- *\n- * Construct an object to map a frame buffer for CPU access.\n- * The flags are passed directly to mmap and should be either PROT_READ,\n- * PROT_WRITE, or a bitwise-or combination of both.\n- */\n-MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)\n-{\n-\tmaps_.reserve(buffer->planes().size());\n-\n-\tfor (const FrameBuffer::Plane &plane : buffer->planes()) {\n-\t\tvoid *address = mmap(nullptr, plane.length, flags,\n-\t\t\t\t     MAP_SHARED, plane.fd.fd(), 0);\n-\t\tif (address == MAP_FAILED) {\n-\t\t\terror_ = -errno;\n-\t\t\tLOG(Buffer, Error) << \"Failed to mmap plane\";\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tmaps_.emplace_back(static_cast<uint8_t *>(address), plane.length);\n-\t}\n-}\n-\n } /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex dc3fe63112d4..e6849733f979 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -29,8 +29,9 @@\n #include <linux/bcm2835-isp.h>\n #include <linux/videodev2.h>\n \n+#include <libcamera/helpers/mapped_buffer.h>\n+\n #include \"libcamera/internal/bayer_format.h\"\n-#include \"libcamera/internal/buffer.h\"\n #include \"libcamera/internal/camera_sensor.h\"\n #include \"libcamera/internal/delayed_controls.h\"\n #include \"libcamera/internal/device_enumerator.h\"\ndiff --git a/src/meson.build b/src/meson.build\nindex 70e1a4618a0f..380de28d0f7a 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -31,6 +31,7 @@ libcamera_objects = []\n # libcamera must be built first as a dependency to the other components.\n subdir('libcamera-platform')\n subdir('libcamera')\n+subdir('libcamera-helpers')\n \n subdir('android')\n subdir('ipa')\ndiff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp\nindex 5de8201e45f6..218d700f40da 100644\n--- a/test/mapped-buffer.cpp\n+++ b/test/mapped-buffer.cpp\n@@ -4,12 +4,11 @@\n  *\n  * libcamera internal MappedBuffer tests\n  */\n-\n #include <iostream>\n \n #include <libcamera/framebuffer_allocator.h>\n \n-#include \"libcamera/internal/buffer.h\"\n+#include <libcamera/helpers/mapped_buffer.h>\n \n #include \"camera_test.h\"\n #include \"test.h\"\ndiff --git a/test/meson.build b/test/meson.build\nindex 045ad2a2d7c9..ee0d127cf1ec 100644\n--- a/test/meson.build\n+++ b/test/meson.build\n@@ -40,7 +40,6 @@ internal_tests = [\n     ['file',                            'file.cpp'],\n     ['file-descriptor',                 'file-descriptor.cpp'],\n     ['hotplug-cameras',                 'hotplug-cameras.cpp'],\n-    ['mapped-buffer',                   'mapped-buffer.cpp'],\n     ['message',                         'message.cpp'],\n     ['object',                          'object.cpp'],\n     ['object-delete',                   'object-delete.cpp'],\n@@ -53,6 +52,10 @@ internal_tests = [\n     ['utils',                           'utils.cpp'],\n ]\n \n+helpers_tests = [\n+    ['mapped-buffer',                   'mapped-buffer.cpp'],\n+]\n+\n foreach t : public_tests\n     exe = executable(t[0], t[1],\n                      dependencies : libcamera_dep,\n@@ -70,3 +73,12 @@ foreach t : internal_tests\n \n     test(t[0], exe)\n endforeach\n+\n+foreach t : helpers_tests\n+    exe = executable(t[0], t[1],\n+                     dependencies : [libcamera_dep, libcamera_helpers],\n+                     link_with : test_libraries,\n+                     include_directories : test_includes_internal)\n+\n+    test(t[0], exe)\n+endforeach\n",
    "prefixes": [
        "libcamera-devel",
        "6/6"
    ]
}