[libcamera-devel,6/6] libcamera-helpers: Provide helper library
diff mbox series

Message ID 20210616151152.3856595-7-kieran.bingham@ideasonboard.com
State Superseded
Headers show
Series
  • libcamera-platform: Split library functionality
Related show

Commit Message

Kieran Bingham June 16, 2021, 3:11 p.m. UTC
Provide a library which build support on top of the libcamera API.

This currently implements the MappedBuffer and MappedFrameBuffer classes
which help with lifetime management of mmapping libcamera buffers.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 Documentation/Doxyfile.in                     |   2 +
 .../buffer.h => helpers/mapped_buffer.h}      |  10 +-
 include/libcamera/helpers/meson.build         |  10 +
 include/libcamera/internal/meson.build        |   1 -
 include/libcamera/meson.build                 |   1 +
 src/android/camera_device.h                   |   2 +-
 src/android/camera_stream.h                   |   2 +-
 src/android/jpeg/encoder_libjpeg.h            |   3 +-
 src/android/jpeg/post_processor_jpeg.h        |   2 +-
 src/android/jpeg/thumbnailer.h                |   3 +-
 src/android/meson.build                       |   1 +
 src/android/mm/generic_camera_buffer.cpp      |   2 +-
 src/android/post_processor.h                  |   2 +-
 src/ipa/ipu3/ipu3.cpp                         |   2 +-
 src/ipa/ipu3/meson.build                      |   2 +-
 src/ipa/raspberrypi/meson.build               |   1 +
 src/ipa/raspberrypi/raspberrypi.cpp           |   2 +-
 src/libcamera-helpers/mapped_buffer.cpp       | 171 ++++++++++++++++++
 src/libcamera/buffer.cpp                      | 149 ---------------
 .../pipeline/raspberrypi/raspberrypi.cpp      |   3 +-
 src/meson.build                               |   1 +
 test/mapped-buffer.cpp                        |   3 +-
 test/meson.build                              |  14 +-
 23 files changed, 220 insertions(+), 169 deletions(-)
 rename include/libcamera/{internal/buffer.h => helpers/mapped_buffer.h} (81%)
 create mode 100644 include/libcamera/helpers/meson.build
 create mode 100644 src/libcamera-helpers/mapped_buffer.cpp

Comments

Umang Jain June 17, 2021, 7:24 a.m. UTC | #1
Hi Kieran,

I cannot compile this series with this patch, due to missing 
src/libcamera-helpers/meson.build

src/meson.build:34:0: ERROR: Non-existent build file 
'src/libcamera-helpers/meson.build'

On 6/16/21 8:41 PM, Kieran Bingham wrote:
> Provide a library which build support on top of the libcamera API.
>
> This currently implements the MappedBuffer and MappedFrameBuffer classes
> which help with lifetime management of mmapping libcamera buffers.
>
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> ---
>   Documentation/Doxyfile.in                     |   2 +
>   .../buffer.h => helpers/mapped_buffer.h}      |  10 +-
>   include/libcamera/helpers/meson.build         |  10 +
>   include/libcamera/internal/meson.build        |   1 -
>   include/libcamera/meson.build                 |   1 +
>   src/android/camera_device.h                   |   2 +-
>   src/android/camera_stream.h                   |   2 +-
>   src/android/jpeg/encoder_libjpeg.h            |   3 +-
>   src/android/jpeg/post_processor_jpeg.h        |   2 +-
>   src/android/jpeg/thumbnailer.h                |   3 +-
>   src/android/meson.build                       |   1 +
>   src/android/mm/generic_camera_buffer.cpp      |   2 +-
>   src/android/post_processor.h                  |   2 +-
>   src/ipa/ipu3/ipu3.cpp                         |   2 +-
>   src/ipa/ipu3/meson.build                      |   2 +-
>   src/ipa/raspberrypi/meson.build               |   1 +
>   src/ipa/raspberrypi/raspberrypi.cpp           |   2 +-
>   src/libcamera-helpers/mapped_buffer.cpp       | 171 ++++++++++++++++++
>   src/libcamera/buffer.cpp                      | 149 ---------------
>   .../pipeline/raspberrypi/raspberrypi.cpp      |   3 +-
>   src/meson.build                               |   1 +
>   test/mapped-buffer.cpp                        |   3 +-
>   test/meson.build                              |  14 +-
>   23 files changed, 220 insertions(+), 169 deletions(-)
>   rename include/libcamera/{internal/buffer.h => helpers/mapped_buffer.h} (81%)
>   create mode 100644 include/libcamera/helpers/meson.build
>   create mode 100644 src/libcamera-helpers/mapped_buffer.cpp
> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
> index c1b395bf0b83..e67775b99d26 100644
> --- a/Documentation/Doxyfile.in
> +++ b/Documentation/Doxyfile.in
> @@ -791,9 +791,11 @@ WARN_LOGFILE           =
>   INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
>   			 "@TOP_SRCDIR@/src/ipa/libipa" \
>   			 "@TOP_SRCDIR@/src/libcamera" \
> +			 "@TOP_SRCDIR@/src/libcamera-helpers" \
>   			 "@TOP_SRCDIR@/src/libcamera-platform" \
>   			 "@TOP_BUILDDIR@/include/libcamera" \
>   			 "@TOP_BUILDDIR@/src/libcamera" \
> +			 "@TOP_BUILDDIR@/src/libcamera-helpers" \
>   			 "@TOP_BUILDDIR@/src/libcamera-platform"
>   
>   # This tag can be used to specify the character encoding of the source files
> diff --git a/include/libcamera/internal/buffer.h b/include/libcamera/helpers/mapped_buffer.h
> similarity index 81%
> rename from include/libcamera/internal/buffer.h
> rename to include/libcamera/helpers/mapped_buffer.h
> index 9da1fbd12c27..ece24f2ddd2c 100644
> --- a/include/libcamera/internal/buffer.h
> +++ b/include/libcamera/helpers/mapped_buffer.h
> @@ -2,16 +2,16 @@
>   /*
>    * Copyright (C) 2020, Google Inc.
>    *
> - * buffer.h - Internal buffer handling
> + * mapped_buffer.h - Mapped Buffer handling
>    */
> -#ifndef __LIBCAMERA_INTERNAL_BUFFER_H__
> -#define __LIBCAMERA_INTERNAL_BUFFER_H__
> +#ifndef __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__
> +#define __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__
>   
>   #include <sys/mman.h>
>   #include <vector>
>   
> -#include <libcamera/class.h>
>   #include <libcamera/buffer.h>
> +#include <libcamera/class.h>
>   #include <libcamera/span.h>
>   
>   namespace libcamera {
> @@ -48,4 +48,4 @@ public:
>   
>   } /* namespace libcamera */
>   
> -#endif /* __LIBCAMERA_INTERNAL_BUFFER_H__ */
> +#endif /* __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__ */
> diff --git a/include/libcamera/helpers/meson.build b/include/libcamera/helpers/meson.build
> new file mode 100644
> index 000000000000..c025eb930600
> --- /dev/null
> +++ b/include/libcamera/helpers/meson.build
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: CC0-1.0
> +
> +libcamera_helpers_include_dir = libcamera_include_dir / 'helpers'
> +
> +libcamera_helpers_headers = files([
> +    'mapped_buffer.h',
> +])
> +
> +install_headers(libcamera_helpers_headers,
> +                subdir: libcamera_helpers_include_dir)
> diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
> index 1187cc1f63e4..ecd0c8ba183e 100644
> --- a/include/libcamera/internal/meson.build
> +++ b/include/libcamera/internal/meson.build
> @@ -11,7 +11,6 @@ libcamera_tracepoint_header = custom_target(
>   
>   libcamera_internal_headers = files([
>       'bayer_format.h',
> -    'buffer.h',
>       'byte_stream_buffer.h',
>       'camera_controls.h',
>       'camera_sensor.h',
> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
> index 7bfcebc79c86..7c98d8744ec2 100644
> --- a/include/libcamera/meson.build
> +++ b/include/libcamera/meson.build
> @@ -20,6 +20,7 @@ libcamera_public_headers = files([
>   
>   include_dir = libcamera_include_dir / 'libcamera'
>   
> +subdir('helpers')
>   subdir('internal')
>   subdir('ipa')
>   subdir('platform')
> diff --git a/src/android/camera_device.h b/src/android/camera_device.h
> index b9be3df58084..26e5bbc0c26c 100644
> --- a/src/android/camera_device.h
> +++ b/src/android/camera_device.h
> @@ -25,7 +25,7 @@
>   #include <libcamera/platform/message.h>
>   #include <libcamera/platform/thread.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   #include "camera_metadata.h"
>   #include "camera_stream.h"
> diff --git a/src/android/camera_stream.h b/src/android/camera_stream.h
> index 3401672233ca..12484cb607ed 100644
> --- a/src/android/camera_stream.h
> +++ b/src/android/camera_stream.h
> @@ -19,7 +19,7 @@
>   #include <libcamera/geometry.h>
>   #include <libcamera/pixel_format.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   class CameraDevice;
>   class CameraMetadata;
> diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
> index 838da7728382..ca7c1958e20e 100644
> --- a/src/android/jpeg/encoder_libjpeg.h
> +++ b/src/android/jpeg/encoder_libjpeg.h
> @@ -9,7 +9,8 @@
>   
>   #include "encoder.h"
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
> +
>   #include "libcamera/internal/formats.h"
>   
>   #include <jpeglib.h>
> diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h
> index 5d2d4ab224b1..4700a7f562a2 100644
> --- a/src/android/jpeg/post_processor_jpeg.h
> +++ b/src/android/jpeg/post_processor_jpeg.h
> @@ -13,7 +13,7 @@
>   
>   #include <libcamera/geometry.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   class CameraDevice;
>   
> diff --git a/src/android/jpeg/thumbnailer.h b/src/android/jpeg/thumbnailer.h
> index 4e9226c34104..483b41dfe47d 100644
> --- a/src/android/jpeg/thumbnailer.h
> +++ b/src/android/jpeg/thumbnailer.h
> @@ -9,7 +9,8 @@
>   
>   #include <libcamera/geometry.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
> +
>   #include "libcamera/internal/formats.h"
>   
>   class Thumbnailer
> diff --git a/src/android/meson.build b/src/android/meson.build
> index 6edaa1185905..abde9fd2def0 100644
> --- a/src/android/meson.build
> +++ b/src/android/meson.build
> @@ -5,6 +5,7 @@ android_deps = [
>       dependency('libjpeg', required : get_option('android')),
>       dependency('yaml-0.1', required : get_option('android')),
>       libcamera_dep,
> +    libcamera_helpers,
>   ]
>   
>   android_enabled = true
> diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp
> index f138ada14964..64c73c5716ad 100644
> --- a/src/android/mm/generic_camera_buffer.cpp
> +++ b/src/android/mm/generic_camera_buffer.cpp
> @@ -11,7 +11,7 @@
>   
>   #include <libcamera/platform/log.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   using namespace libcamera;
>   
> diff --git a/src/android/post_processor.h b/src/android/post_processor.h
> index 547fda379ed8..53220edaf24d 100644
> --- a/src/android/post_processor.h
> +++ b/src/android/post_processor.h
> @@ -10,7 +10,7 @@
>   #include <libcamera/buffer.h>
>   #include <libcamera/stream.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   #include "camera_buffer.h"
>   
> diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
> index ca1ce4dc96d0..158eb3bc49e5 100644
> --- a/src/ipa/ipu3/ipu3.cpp
> +++ b/src/ipa/ipu3/ipu3.cpp
> @@ -20,7 +20,7 @@
>   
>   #include <libcamera/platform/log.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   #include "ipu3_agc.h"
>   #include "ipu3_awb.h"
> diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build
> index 0d843846acde..34620024def7 100644
> --- a/src/ipa/ipu3/meson.build
> +++ b/src/ipa/ipu3/meson.build
> @@ -12,7 +12,7 @@ mod = shared_module(ipa_name,
>                       [ipu3_ipa_sources, libcamera_generated_ipa_headers],
>                       name_prefix : '',
>                       include_directories : [ipa_includes, libipa_includes],
> -                    dependencies : libcamera_dep,
> +                    dependencies : [libcamera_dep, libcamera_helpers],
>                       link_with : libipa,
>                       install : true,
>                       install_dir : ipa_install_dir)
> diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build
> index 230356d3ce3a..b2ce6f3e8618 100644
> --- a/src/ipa/raspberrypi/meson.build
> +++ b/src/ipa/raspberrypi/meson.build
> @@ -4,6 +4,7 @@ ipa_name = 'ipa_rpi'
>   
>   rpi_ipa_deps = [
>       libcamera_dep,
> +    libcamera_helpers,
>       dependency('boost'),
>       libatomic,
>   ]
> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
> index 90f35d970fd0..b85a1e51d757 100644
> --- a/src/ipa/raspberrypi/raspberrypi.cpp
> +++ b/src/ipa/raspberrypi/raspberrypi.cpp
> @@ -26,7 +26,7 @@
>   
>   #include <libcamera/platform/log.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   #include <linux/bcm2835-isp.h>
>   
> diff --git a/src/libcamera-helpers/mapped_buffer.cpp b/src/libcamera-helpers/mapped_buffer.cpp
> new file mode 100644
> index 000000000000..0d4517b62f65
> --- /dev/null
> +++ b/src/libcamera-helpers/mapped_buffer.cpp
> @@ -0,0 +1,171 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2021, Google Inc.
> + *
> + * mapped_buffer.cpp - Mapped Buffer handling
> + */
> +
> +#include <libcamera/helpers/mapped_buffer.h>
> +
> +#include <errno.h>
> +#include <string.h>
> +#include <sys/mman.h>
> +#include <unistd.h>
> +
> +#include <libcamera/platform/log.h>
> +
> +/**
> + * \file libcamera/helpers/mapped_buffer.h
> + * \brief Mapped Buffer handling
> + */
> +
> +namespace libcamera {
> +
> +LOG_DEFINE_CATEGORY(MappedBuffer)
> +
> +/**
> + * \class MappedBuffer
> + * \brief Provide an interface to support managing memory mapped buffers
> + *
> + * The MappedBuffer interface provides access to a set of MappedPlanes which
> + * are available for access by the CPU.
> + *
> + * This class is not meant to be constructed directly, but instead derived
> + * classes should be used to implement the correct mapping of a source buffer.
> + *
> + * This allows treating CPU accessible memory through a generic interface
> + * regardless of whether it originates from a libcamera FrameBuffer or other
> + * source.
> + */
> +
> +/**
> + * \typedef MappedBuffer::Plane
> + * \brief A mapped region of memory accessible to the CPU
> + *
> + * The MappedBuffer::Plane uses the Span interface to describe the mapped memory
> + * region.
> + */
> +
> +/**
> + * \brief Construct an empty MappedBuffer
> + */
> +MappedBuffer::MappedBuffer()
> +	: error_(0)
> +{
> +}
> +
> +/**
> + * \brief Move constructor, construct the MappedBuffer with the contents of \a
> + * other using move semantics
> + * \param[in] other The other MappedBuffer
> + *
> + * Moving a MappedBuffer moves the mappings contained in the \a other to the new
> + * MappedBuffer and invalidates the \a other.
> + *
> + * No mappings are unmapped or destroyed in this process.
> + */
> +MappedBuffer::MappedBuffer(MappedBuffer &&other)
> +{
> +	*this = std::move(other);
> +}
> +
> +/**
> + * \brief Move assignment operator, replace the mappings with those of \a other
> +* \param[in] other The other MappedBuffer
> + *
> + * Moving a MappedBuffer moves the mappings contained in the \a other to the new
> + * MappedBuffer and invalidates the \a other.
> + *
> + * No mappings are unmapped or destroyed in this process.
> + */
> +MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
> +{
> +	error_ = other.error_;
> +	maps_ = std::move(other.maps_);
> +	other.error_ = -ENOENT;
> +
> +	return *this;
> +}
> +
> +MappedBuffer::~MappedBuffer()
> +{
> +	for (Plane &map : maps_)
> +		munmap(map.data(), map.size());
> +}
> +
> +/**
> + * \fn MappedBuffer::isValid()
> + * \brief Check if the MappedBuffer instance is valid
> + * \return True if the MappedBuffer has valid mappings, false otherwise
> + */
> +
> +/**
> + * \fn MappedBuffer::error()
> + * \brief Retrieve the map error status
> + *
> + * This function retrieves the error status from the MappedBuffer.
> + * The error status is a negative number as defined by errno.h. If
> + * no error occurred, this function returns 0.
> + *
> + * \return The map error code
> + */
> +
> +/**
> + * \fn MappedBuffer::maps()
> + * \brief Retrieve the mapped planes
> + *
> + * This function retrieves the successfully mapped planes stored as a vector
> + * of Span<uint8_t> to provide access to the mapped memory.
> + *
> + * \return A vector of the mapped planes
> + */
> +
> +/**
> + * \var MappedBuffer::error_
> + * \brief Stores the error value if present
> + *
> + * MappedBuffer derived classes shall set this to a negative value as defined
> + * by errno.h if an error occured during the mapping process.
> + */
> +
> +/**
> + * \var MappedBuffer::maps_
> + * \brief Stores the internal mapped planes
> + *
> + * MappedBuffer derived classes shall store the mappings they create in this
> + * vector which is parsed during destruct to unmap any memory mappings which
> + * completed successfully.
> + */
> +
> +/**
> + * \class MappedFrameBuffer
> + * \brief Map a FrameBuffer using the MappedBuffer interface
> + */
> +
> +/**
> + * \brief Map all planes of a FrameBuffer
> + * \param[in] buffer FrameBuffer to be mapped
> + * \param[in] flags Protection flags to apply to map
> + *
> + * Construct an object to map a frame buffer for CPU access.
> + * The flags are passed directly to mmap and should be either PROT_READ,
> + * PROT_WRITE, or a bitwise-or combination of both.
> + */
> +MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)
> +{
> +	maps_.reserve(buffer->planes().size());
> +
> +	for (const FrameBuffer::Plane &plane : buffer->planes()) {
> +		void *address = mmap(nullptr, plane.length, flags,
> +				     MAP_SHARED, plane.fd.fd(), 0);
> +		if (address == MAP_FAILED) {
> +			error_ = -errno;
> +			LOG(MappedBuffer, Error) << "Failed to mmap plane";
> +			break;
> +		}
> +
> +		maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
> +	}
> +}
> +
> +} /* namespace libcamera */
> diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
> index 3c862820e6e1..0a232d791fcd 100644
> --- a/src/libcamera/buffer.cpp
> +++ b/src/libcamera/buffer.cpp
> @@ -6,7 +6,6 @@
>    */
>   
>   #include <libcamera/buffer.h>
> -#include "libcamera/internal/buffer.h"
>   
>   #include <errno.h>
>   #include <string.h>
> @@ -18,9 +17,6 @@
>   /**
>    * \file libcamera/buffer.h
>    * \brief Buffer handling
> - *
> - * \file libcamera/internal/buffer.h
> - * \brief Internal buffer handling support
>    */
>   
>   namespace libcamera {
> @@ -235,149 +231,4 @@ FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)
>    * indicate that the metadata is invalid.
>    */
>   
> -/**
> - * \class MappedBuffer
> - * \brief Provide an interface to support managing memory mapped buffers
> - *
> - * The MappedBuffer interface provides access to a set of MappedPlanes which
> - * are available for access by the CPU.
> - *
> - * This class is not meant to be constructed directly, but instead derived
> - * classes should be used to implement the correct mapping of a source buffer.
> - *
> - * This allows treating CPU accessible memory through a generic interface
> - * regardless of whether it originates from a libcamera FrameBuffer or other
> - * source.
> - */
> -
> -/**
> - * \typedef MappedBuffer::Plane
> - * \brief A mapped region of memory accessible to the CPU
> - *
> - * The MappedBuffer::Plane uses the Span interface to describe the mapped memory
> - * region.
> - */
> -
> -/**
> - * \brief Construct an empty MappedBuffer
> - */
> -MappedBuffer::MappedBuffer()
> -	: error_(0)
> -{
> -}
> -
> -/**
> - * \brief Move constructor, construct the MappedBuffer with the contents of \a
> - * other using move semantics
> - * \param[in] other The other MappedBuffer
> - *
> - * Moving a MappedBuffer moves the mappings contained in the \a other to the new
> - * MappedBuffer and invalidates the \a other.
> - *
> - * No mappings are unmapped or destroyed in this process.
> - */
> -MappedBuffer::MappedBuffer(MappedBuffer &&other)
> -{
> -	*this = std::move(other);
> -}
> -
> -/**
> - * \brief Move assignment operator, replace the mappings with those of \a other
> -* \param[in] other The other MappedBuffer
> - *
> - * Moving a MappedBuffer moves the mappings contained in the \a other to the new
> - * MappedBuffer and invalidates the \a other.
> - *
> - * No mappings are unmapped or destroyed in this process.
> - */
> -MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
> -{
> -	error_ = other.error_;
> -	maps_ = std::move(other.maps_);
> -	other.error_ = -ENOENT;
> -
> -	return *this;
> -}
> -
> -MappedBuffer::~MappedBuffer()
> -{
> -	for (Plane &map : maps_)
> -		munmap(map.data(), map.size());
> -}
> -
> -/**
> - * \fn MappedBuffer::isValid()
> - * \brief Check if the MappedBuffer instance is valid
> - * \return True if the MappedBuffer has valid mappings, false otherwise
> - */
> -
> -/**
> - * \fn MappedBuffer::error()
> - * \brief Retrieve the map error status
> - *
> - * This function retrieves the error status from the MappedBuffer.
> - * The error status is a negative number as defined by errno.h. If
> - * no error occurred, this function returns 0.
> - *
> - * \return The map error code
> - */
> -
> -/**
> - * \fn MappedBuffer::maps()
> - * \brief Retrieve the mapped planes
> - *
> - * This function retrieves the successfully mapped planes stored as a vector
> - * of Span<uint8_t> to provide access to the mapped memory.
> - *
> - * \return A vector of the mapped planes
> - */
> -
> -/**
> - * \var MappedBuffer::error_
> - * \brief Stores the error value if present
> - *
> - * MappedBuffer derived classes shall set this to a negative value as defined
> - * by errno.h if an error occured during the mapping process.
> - */
> -
> -/**
> - * \var MappedBuffer::maps_
> - * \brief Stores the internal mapped planes
> - *
> - * MappedBuffer derived classes shall store the mappings they create in this
> - * vector which is parsed during destruct to unmap any memory mappings which
> - * completed successfully.
> - */
> -
> -/**
> - * \class MappedFrameBuffer
> - * \brief Map a FrameBuffer using the MappedBuffer interface
> - */
> -
> -/**
> - * \brief Map all planes of a FrameBuffer
> - * \param[in] buffer FrameBuffer to be mapped
> - * \param[in] flags Protection flags to apply to map
> - *
> - * Construct an object to map a frame buffer for CPU access.
> - * The flags are passed directly to mmap and should be either PROT_READ,
> - * PROT_WRITE, or a bitwise-or combination of both.
> - */
> -MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)
> -{
> -	maps_.reserve(buffer->planes().size());
> -
> -	for (const FrameBuffer::Plane &plane : buffer->planes()) {
> -		void *address = mmap(nullptr, plane.length, flags,
> -				     MAP_SHARED, plane.fd.fd(), 0);
> -		if (address == MAP_FAILED) {
> -			error_ = -errno;
> -			LOG(Buffer, Error) << "Failed to mmap plane";
> -			break;
> -		}
> -
> -		maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
> -	}
> -}
> -
>   } /* namespace libcamera */
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> index dc3fe63112d4..e6849733f979 100644
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> @@ -29,8 +29,9 @@
>   #include <linux/bcm2835-isp.h>
>   #include <linux/videodev2.h>
>   
> +#include <libcamera/helpers/mapped_buffer.h>
> +
>   #include "libcamera/internal/bayer_format.h"
> -#include "libcamera/internal/buffer.h"
>   #include "libcamera/internal/camera_sensor.h"
>   #include "libcamera/internal/delayed_controls.h"
>   #include "libcamera/internal/device_enumerator.h"
> diff --git a/src/meson.build b/src/meson.build
> index 70e1a4618a0f..380de28d0f7a 100644
> --- a/src/meson.build
> +++ b/src/meson.build
> @@ -31,6 +31,7 @@ libcamera_objects = []
>   # libcamera must be built first as a dependency to the other components.
>   subdir('libcamera-platform')
>   subdir('libcamera')
> +subdir('libcamera-helpers')
>   
>   subdir('android')
>   subdir('ipa')
> diff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp
> index 5de8201e45f6..218d700f40da 100644
> --- a/test/mapped-buffer.cpp
> +++ b/test/mapped-buffer.cpp
> @@ -4,12 +4,11 @@
>    *
>    * libcamera internal MappedBuffer tests
>    */
> -
>   #include <iostream>
>   
>   #include <libcamera/framebuffer_allocator.h>
>   
> -#include "libcamera/internal/buffer.h"
> +#include <libcamera/helpers/mapped_buffer.h>
>   
>   #include "camera_test.h"
>   #include "test.h"
> diff --git a/test/meson.build b/test/meson.build
> index 045ad2a2d7c9..ee0d127cf1ec 100644
> --- a/test/meson.build
> +++ b/test/meson.build
> @@ -40,7 +40,6 @@ internal_tests = [
>       ['file',                            'file.cpp'],
>       ['file-descriptor',                 'file-descriptor.cpp'],
>       ['hotplug-cameras',                 'hotplug-cameras.cpp'],
> -    ['mapped-buffer',                   'mapped-buffer.cpp'],
>       ['message',                         'message.cpp'],
>       ['object',                          'object.cpp'],
>       ['object-delete',                   'object-delete.cpp'],
> @@ -53,6 +52,10 @@ internal_tests = [
>       ['utils',                           'utils.cpp'],
>   ]
>   
> +helpers_tests = [
> +    ['mapped-buffer',                   'mapped-buffer.cpp'],
> +]
> +
>   foreach t : public_tests
>       exe = executable(t[0], t[1],
>                        dependencies : libcamera_dep,
> @@ -70,3 +73,12 @@ foreach t : internal_tests
>   
>       test(t[0], exe)
>   endforeach
> +
> +foreach t : helpers_tests
> +    exe = executable(t[0], t[1],
> +                     dependencies : [libcamera_dep, libcamera_helpers],
> +                     link_with : test_libraries,
> +                     include_directories : test_includes_internal)
> +
> +    test(t[0], exe)
> +endforeach
Kieran Bingham June 17, 2021, 7:30 a.m. UTC | #2
Hi Umang,

Oh dear - I'm sorry I slipped on this.

Here is the diff which introduces the meson.build


diff --git a/src/libcamera-helpers/meson.build
b/src/libcamera-helpers/meson.build
new file mode 100644
index 000000000000..53e6d91554f7
--- /dev/null
+++ b/src/libcamera-helpers/meson.build
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: CC0-1.0
+
+libcamera_helpers_sources = files([
+    'mapped_buffer.cpp',
+])
+
+libcamera_helpers_deps = [
+    libcamera_dep,
+]
+
+libcamera_helpers_lib = shared_library('libcamera-helpers',
+                                       [libcamera_helpers_sources,
libcamera_helpers_headers],
+                                       name_prefix : '',
+                                       install : true,
+                                       cpp_args : libcamera_cpp_args,
+                                       include_directories :
libcamera_includes,
+                                       dependencies :
libcamera_helpers_deps)
+
+libcamera_helpers = declare_dependency(sources: libcamera_helpers_headers,
+                                       include_directories :
libcamera_includes,
+                                       link_with : libcamera_helpers_lib)
+
+pkg_mod = import('pkgconfig')
+pkg_mod.generate(libraries : libcamera_helpers_lib,
+                 version : '1.0',
+                 name : 'libcamera-helpers',
+                 filebase : 'camera-helpers',
+                 description : 'Complex Camera Support Library helpers',
+                 subdirs : 'libcamera')


which will of course be in any v2 ;-)

--
Kieran



On 17/06/2021 08:24, Umang Jain wrote:
> Hi Kieran,
> 
> I cannot compile this series with this patch, due to missing
> src/libcamera-helpers/meson.build
> 
> src/meson.build:34:0: ERROR: Non-existent build file
> 'src/libcamera-helpers/meson.build'
> 
> On 6/16/21 8:41 PM, Kieran Bingham wrote:
>> Provide a library which build support on top of the libcamera API.
>>
>> This currently implements the MappedBuffer and MappedFrameBuffer classes
>> which help with lifetime management of mmapping libcamera buffers.
>>
>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>> ---
>>   Documentation/Doxyfile.in                     |   2 +
>>   .../buffer.h => helpers/mapped_buffer.h}      |  10 +-
>>   include/libcamera/helpers/meson.build         |  10 +
>>   include/libcamera/internal/meson.build        |   1 -
>>   include/libcamera/meson.build                 |   1 +
>>   src/android/camera_device.h                   |   2 +-
>>   src/android/camera_stream.h                   |   2 +-
>>   src/android/jpeg/encoder_libjpeg.h            |   3 +-
>>   src/android/jpeg/post_processor_jpeg.h        |   2 +-
>>   src/android/jpeg/thumbnailer.h                |   3 +-
>>   src/android/meson.build                       |   1 +
>>   src/android/mm/generic_camera_buffer.cpp      |   2 +-
>>   src/android/post_processor.h                  |   2 +-
>>   src/ipa/ipu3/ipu3.cpp                         |   2 +-
>>   src/ipa/ipu3/meson.build                      |   2 +-
>>   src/ipa/raspberrypi/meson.build               |   1 +
>>   src/ipa/raspberrypi/raspberrypi.cpp           |   2 +-
>>   src/libcamera-helpers/mapped_buffer.cpp       | 171 ++++++++++++++++++
>>   src/libcamera/buffer.cpp                      | 149 ---------------
>>   .../pipeline/raspberrypi/raspberrypi.cpp      |   3 +-
>>   src/meson.build                               |   1 +
>>   test/mapped-buffer.cpp                        |   3 +-
>>   test/meson.build                              |  14 +-
>>   23 files changed, 220 insertions(+), 169 deletions(-)
>>   rename include/libcamera/{internal/buffer.h =>
>> helpers/mapped_buffer.h} (81%)
>>   create mode 100644 include/libcamera/helpers/meson.build
>>   create mode 100644 src/libcamera-helpers/mapped_buffer.cpp
>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
>> index c1b395bf0b83..e67775b99d26 100644
>> --- a/Documentation/Doxyfile.in
>> +++ b/Documentation/Doxyfile.in
>> @@ -791,9 +791,11 @@ WARN_LOGFILE           =
>>   INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
>>                "@TOP_SRCDIR@/src/ipa/libipa" \
>>                "@TOP_SRCDIR@/src/libcamera" \
>> +             "@TOP_SRCDIR@/src/libcamera-helpers" \
>>                "@TOP_SRCDIR@/src/libcamera-platform" \
>>                "@TOP_BUILDDIR@/include/libcamera" \
>>                "@TOP_BUILDDIR@/src/libcamera" \
>> +             "@TOP_BUILDDIR@/src/libcamera-helpers" \
>>                "@TOP_BUILDDIR@/src/libcamera-platform"
>>     # This tag can be used to specify the character encoding of the
>> source files
>> diff --git a/include/libcamera/internal/buffer.h
>> b/include/libcamera/helpers/mapped_buffer.h
>> similarity index 81%
>> rename from include/libcamera/internal/buffer.h
>> rename to include/libcamera/helpers/mapped_buffer.h
>> index 9da1fbd12c27..ece24f2ddd2c 100644
>> --- a/include/libcamera/internal/buffer.h
>> +++ b/include/libcamera/helpers/mapped_buffer.h
>> @@ -2,16 +2,16 @@
>>   /*
>>    * Copyright (C) 2020, Google Inc.
>>    *
>> - * buffer.h - Internal buffer handling
>> + * mapped_buffer.h - Mapped Buffer handling
>>    */
>> -#ifndef __LIBCAMERA_INTERNAL_BUFFER_H__
>> -#define __LIBCAMERA_INTERNAL_BUFFER_H__
>> +#ifndef __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__
>> +#define __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__
>>     #include <sys/mman.h>
>>   #include <vector>
>>   -#include <libcamera/class.h>
>>   #include <libcamera/buffer.h>
>> +#include <libcamera/class.h>
>>   #include <libcamera/span.h>
>>     namespace libcamera {
>> @@ -48,4 +48,4 @@ public:
>>     } /* namespace libcamera */
>>   -#endif /* __LIBCAMERA_INTERNAL_BUFFER_H__ */
>> +#endif /* __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__ */
>> diff --git a/include/libcamera/helpers/meson.build
>> b/include/libcamera/helpers/meson.build
>> new file mode 100644
>> index 000000000000..c025eb930600
>> --- /dev/null
>> +++ b/include/libcamera/helpers/meson.build
>> @@ -0,0 +1,10 @@
>> +# SPDX-License-Identifier: CC0-1.0
>> +
>> +libcamera_helpers_include_dir = libcamera_include_dir / 'helpers'
>> +
>> +libcamera_helpers_headers = files([
>> +    'mapped_buffer.h',
>> +])
>> +
>> +install_headers(libcamera_helpers_headers,
>> +                subdir: libcamera_helpers_include_dir)
>> diff --git a/include/libcamera/internal/meson.build
>> b/include/libcamera/internal/meson.build
>> index 1187cc1f63e4..ecd0c8ba183e 100644
>> --- a/include/libcamera/internal/meson.build
>> +++ b/include/libcamera/internal/meson.build
>> @@ -11,7 +11,6 @@ libcamera_tracepoint_header = custom_target(
>>     libcamera_internal_headers = files([
>>       'bayer_format.h',
>> -    'buffer.h',
>>       'byte_stream_buffer.h',
>>       'camera_controls.h',
>>       'camera_sensor.h',
>> diff --git a/include/libcamera/meson.build
>> b/include/libcamera/meson.build
>> index 7bfcebc79c86..7c98d8744ec2 100644
>> --- a/include/libcamera/meson.build
>> +++ b/include/libcamera/meson.build
>> @@ -20,6 +20,7 @@ libcamera_public_headers = files([
>>     include_dir = libcamera_include_dir / 'libcamera'
>>   +subdir('helpers')
>>   subdir('internal')
>>   subdir('ipa')
>>   subdir('platform')
>> diff --git a/src/android/camera_device.h b/src/android/camera_device.h
>> index b9be3df58084..26e5bbc0c26c 100644
>> --- a/src/android/camera_device.h
>> +++ b/src/android/camera_device.h
>> @@ -25,7 +25,7 @@
>>   #include <libcamera/platform/message.h>
>>   #include <libcamera/platform/thread.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     #include "camera_metadata.h"
>>   #include "camera_stream.h"
>> diff --git a/src/android/camera_stream.h b/src/android/camera_stream.h
>> index 3401672233ca..12484cb607ed 100644
>> --- a/src/android/camera_stream.h
>> +++ b/src/android/camera_stream.h
>> @@ -19,7 +19,7 @@
>>   #include <libcamera/geometry.h>
>>   #include <libcamera/pixel_format.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     class CameraDevice;
>>   class CameraMetadata;
>> diff --git a/src/android/jpeg/encoder_libjpeg.h
>> b/src/android/jpeg/encoder_libjpeg.h
>> index 838da7728382..ca7c1958e20e 100644
>> --- a/src/android/jpeg/encoder_libjpeg.h
>> +++ b/src/android/jpeg/encoder_libjpeg.h
>> @@ -9,7 +9,8 @@
>>     #include "encoder.h"
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>> +
>>   #include "libcamera/internal/formats.h"
>>     #include <jpeglib.h>
>> diff --git a/src/android/jpeg/post_processor_jpeg.h
>> b/src/android/jpeg/post_processor_jpeg.h
>> index 5d2d4ab224b1..4700a7f562a2 100644
>> --- a/src/android/jpeg/post_processor_jpeg.h
>> +++ b/src/android/jpeg/post_processor_jpeg.h
>> @@ -13,7 +13,7 @@
>>     #include <libcamera/geometry.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     class CameraDevice;
>>   diff --git a/src/android/jpeg/thumbnailer.h
>> b/src/android/jpeg/thumbnailer.h
>> index 4e9226c34104..483b41dfe47d 100644
>> --- a/src/android/jpeg/thumbnailer.h
>> +++ b/src/android/jpeg/thumbnailer.h
>> @@ -9,7 +9,8 @@
>>     #include <libcamera/geometry.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>> +
>>   #include "libcamera/internal/formats.h"
>>     class Thumbnailer
>> diff --git a/src/android/meson.build b/src/android/meson.build
>> index 6edaa1185905..abde9fd2def0 100644
>> --- a/src/android/meson.build
>> +++ b/src/android/meson.build
>> @@ -5,6 +5,7 @@ android_deps = [
>>       dependency('libjpeg', required : get_option('android')),
>>       dependency('yaml-0.1', required : get_option('android')),
>>       libcamera_dep,
>> +    libcamera_helpers,
>>   ]
>>     android_enabled = true
>> diff --git a/src/android/mm/generic_camera_buffer.cpp
>> b/src/android/mm/generic_camera_buffer.cpp
>> index f138ada14964..64c73c5716ad 100644
>> --- a/src/android/mm/generic_camera_buffer.cpp
>> +++ b/src/android/mm/generic_camera_buffer.cpp
>> @@ -11,7 +11,7 @@
>>     #include <libcamera/platform/log.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     using namespace libcamera;
>>   diff --git a/src/android/post_processor.h
>> b/src/android/post_processor.h
>> index 547fda379ed8..53220edaf24d 100644
>> --- a/src/android/post_processor.h
>> +++ b/src/android/post_processor.h
>> @@ -10,7 +10,7 @@
>>   #include <libcamera/buffer.h>
>>   #include <libcamera/stream.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     #include "camera_buffer.h"
>>   diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
>> index ca1ce4dc96d0..158eb3bc49e5 100644
>> --- a/src/ipa/ipu3/ipu3.cpp
>> +++ b/src/ipa/ipu3/ipu3.cpp
>> @@ -20,7 +20,7 @@
>>     #include <libcamera/platform/log.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     #include "ipu3_agc.h"
>>   #include "ipu3_awb.h"
>> diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build
>> index 0d843846acde..34620024def7 100644
>> --- a/src/ipa/ipu3/meson.build
>> +++ b/src/ipa/ipu3/meson.build
>> @@ -12,7 +12,7 @@ mod = shared_module(ipa_name,
>>                       [ipu3_ipa_sources,
>> libcamera_generated_ipa_headers],
>>                       name_prefix : '',
>>                       include_directories : [ipa_includes,
>> libipa_includes],
>> -                    dependencies : libcamera_dep,
>> +                    dependencies : [libcamera_dep, libcamera_helpers],
>>                       link_with : libipa,
>>                       install : true,
>>                       install_dir : ipa_install_dir)
>> diff --git a/src/ipa/raspberrypi/meson.build
>> b/src/ipa/raspberrypi/meson.build
>> index 230356d3ce3a..b2ce6f3e8618 100644
>> --- a/src/ipa/raspberrypi/meson.build
>> +++ b/src/ipa/raspberrypi/meson.build
>> @@ -4,6 +4,7 @@ ipa_name = 'ipa_rpi'
>>     rpi_ipa_deps = [
>>       libcamera_dep,
>> +    libcamera_helpers,
>>       dependency('boost'),
>>       libatomic,
>>   ]
>> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp
>> b/src/ipa/raspberrypi/raspberrypi.cpp
>> index 90f35d970fd0..b85a1e51d757 100644
>> --- a/src/ipa/raspberrypi/raspberrypi.cpp
>> +++ b/src/ipa/raspberrypi/raspberrypi.cpp
>> @@ -26,7 +26,7 @@
>>     #include <libcamera/platform/log.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     #include <linux/bcm2835-isp.h>
>>   diff --git a/src/libcamera-helpers/mapped_buffer.cpp
>> b/src/libcamera-helpers/mapped_buffer.cpp
>> new file mode 100644
>> index 000000000000..0d4517b62f65
>> --- /dev/null
>> +++ b/src/libcamera-helpers/mapped_buffer.cpp
>> @@ -0,0 +1,171 @@
>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
>> +/*
>> + * Copyright (C) 2021, Google Inc.
>> + *
>> + * mapped_buffer.cpp - Mapped Buffer handling
>> + */
>> +
>> +#include <libcamera/helpers/mapped_buffer.h>
>> +
>> +#include <errno.h>
>> +#include <string.h>
>> +#include <sys/mman.h>
>> +#include <unistd.h>
>> +
>> +#include <libcamera/platform/log.h>
>> +
>> +/**
>> + * \file libcamera/helpers/mapped_buffer.h
>> + * \brief Mapped Buffer handling
>> + */
>> +
>> +namespace libcamera {
>> +
>> +LOG_DEFINE_CATEGORY(MappedBuffer)
>> +
>> +/**
>> + * \class MappedBuffer
>> + * \brief Provide an interface to support managing memory mapped buffers
>> + *
>> + * The MappedBuffer interface provides access to a set of
>> MappedPlanes which
>> + * are available for access by the CPU.
>> + *
>> + * This class is not meant to be constructed directly, but instead
>> derived
>> + * classes should be used to implement the correct mapping of a
>> source buffer.
>> + *
>> + * This allows treating CPU accessible memory through a generic
>> interface
>> + * regardless of whether it originates from a libcamera FrameBuffer
>> or other
>> + * source.
>> + */
>> +
>> +/**
>> + * \typedef MappedBuffer::Plane
>> + * \brief A mapped region of memory accessible to the CPU
>> + *
>> + * The MappedBuffer::Plane uses the Span interface to describe the
>> mapped memory
>> + * region.
>> + */
>> +
>> +/**
>> + * \brief Construct an empty MappedBuffer
>> + */
>> +MappedBuffer::MappedBuffer()
>> +    : error_(0)
>> +{
>> +}
>> +
>> +/**
>> + * \brief Move constructor, construct the MappedBuffer with the
>> contents of \a
>> + * other using move semantics
>> + * \param[in] other The other MappedBuffer
>> + *
>> + * Moving a MappedBuffer moves the mappings contained in the \a other
>> to the new
>> + * MappedBuffer and invalidates the \a other.
>> + *
>> + * No mappings are unmapped or destroyed in this process.
>> + */
>> +MappedBuffer::MappedBuffer(MappedBuffer &&other)
>> +{
>> +    *this = std::move(other);
>> +}
>> +
>> +/**
>> + * \brief Move assignment operator, replace the mappings with those
>> of \a other
>> +* \param[in] other The other MappedBuffer
>> + *
>> + * Moving a MappedBuffer moves the mappings contained in the \a other
>> to the new
>> + * MappedBuffer and invalidates the \a other.
>> + *
>> + * No mappings are unmapped or destroyed in this process.
>> + */
>> +MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
>> +{
>> +    error_ = other.error_;
>> +    maps_ = std::move(other.maps_);
>> +    other.error_ = -ENOENT;
>> +
>> +    return *this;
>> +}
>> +
>> +MappedBuffer::~MappedBuffer()
>> +{
>> +    for (Plane &map : maps_)
>> +        munmap(map.data(), map.size());
>> +}
>> +
>> +/**
>> + * \fn MappedBuffer::isValid()
>> + * \brief Check if the MappedBuffer instance is valid
>> + * \return True if the MappedBuffer has valid mappings, false otherwise
>> + */
>> +
>> +/**
>> + * \fn MappedBuffer::error()
>> + * \brief Retrieve the map error status
>> + *
>> + * This function retrieves the error status from the MappedBuffer.
>> + * The error status is a negative number as defined by errno.h. If
>> + * no error occurred, this function returns 0.
>> + *
>> + * \return The map error code
>> + */
>> +
>> +/**
>> + * \fn MappedBuffer::maps()
>> + * \brief Retrieve the mapped planes
>> + *
>> + * This function retrieves the successfully mapped planes stored as a
>> vector
>> + * of Span<uint8_t> to provide access to the mapped memory.
>> + *
>> + * \return A vector of the mapped planes
>> + */
>> +
>> +/**
>> + * \var MappedBuffer::error_
>> + * \brief Stores the error value if present
>> + *
>> + * MappedBuffer derived classes shall set this to a negative value as
>> defined
>> + * by errno.h if an error occured during the mapping process.
>> + */
>> +
>> +/**
>> + * \var MappedBuffer::maps_
>> + * \brief Stores the internal mapped planes
>> + *
>> + * MappedBuffer derived classes shall store the mappings they create
>> in this
>> + * vector which is parsed during destruct to unmap any memory
>> mappings which
>> + * completed successfully.
>> + */
>> +
>> +/**
>> + * \class MappedFrameBuffer
>> + * \brief Map a FrameBuffer using the MappedBuffer interface
>> + */
>> +
>> +/**
>> + * \brief Map all planes of a FrameBuffer
>> + * \param[in] buffer FrameBuffer to be mapped
>> + * \param[in] flags Protection flags to apply to map
>> + *
>> + * Construct an object to map a frame buffer for CPU access.
>> + * The flags are passed directly to mmap and should be either PROT_READ,
>> + * PROT_WRITE, or a bitwise-or combination of both.
>> + */
>> +MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int
>> flags)
>> +{
>> +    maps_.reserve(buffer->planes().size());
>> +
>> +    for (const FrameBuffer::Plane &plane : buffer->planes()) {
>> +        void *address = mmap(nullptr, plane.length, flags,
>> +                     MAP_SHARED, plane.fd.fd(), 0);
>> +        if (address == MAP_FAILED) {
>> +            error_ = -errno;
>> +            LOG(MappedBuffer, Error) << "Failed to mmap plane";
>> +            break;
>> +        }
>> +
>> +        maps_.emplace_back(static_cast<uint8_t *>(address),
>> plane.length);
>> +    }
>> +}
>> +
>> +} /* namespace libcamera */
>> diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
>> index 3c862820e6e1..0a232d791fcd 100644
>> --- a/src/libcamera/buffer.cpp
>> +++ b/src/libcamera/buffer.cpp
>> @@ -6,7 +6,6 @@
>>    */
>>     #include <libcamera/buffer.h>
>> -#include "libcamera/internal/buffer.h"
>>     #include <errno.h>
>>   #include <string.h>
>> @@ -18,9 +17,6 @@
>>   /**
>>    * \file libcamera/buffer.h
>>    * \brief Buffer handling
>> - *
>> - * \file libcamera/internal/buffer.h
>> - * \brief Internal buffer handling support
>>    */
>>     namespace libcamera {
>> @@ -235,149 +231,4 @@ FrameBuffer::FrameBuffer(const
>> std::vector<Plane> &planes, unsigned int cookie)
>>    * indicate that the metadata is invalid.
>>    */
>>   -/**
>> - * \class MappedBuffer
>> - * \brief Provide an interface to support managing memory mapped buffers
>> - *
>> - * The MappedBuffer interface provides access to a set of
>> MappedPlanes which
>> - * are available for access by the CPU.
>> - *
>> - * This class is not meant to be constructed directly, but instead
>> derived
>> - * classes should be used to implement the correct mapping of a
>> source buffer.
>> - *
>> - * This allows treating CPU accessible memory through a generic
>> interface
>> - * regardless of whether it originates from a libcamera FrameBuffer
>> or other
>> - * source.
>> - */
>> -
>> -/**
>> - * \typedef MappedBuffer::Plane
>> - * \brief A mapped region of memory accessible to the CPU
>> - *
>> - * The MappedBuffer::Plane uses the Span interface to describe the
>> mapped memory
>> - * region.
>> - */
>> -
>> -/**
>> - * \brief Construct an empty MappedBuffer
>> - */
>> -MappedBuffer::MappedBuffer()
>> -    : error_(0)
>> -{
>> -}
>> -
>> -/**
>> - * \brief Move constructor, construct the MappedBuffer with the
>> contents of \a
>> - * other using move semantics
>> - * \param[in] other The other MappedBuffer
>> - *
>> - * Moving a MappedBuffer moves the mappings contained in the \a other
>> to the new
>> - * MappedBuffer and invalidates the \a other.
>> - *
>> - * No mappings are unmapped or destroyed in this process.
>> - */
>> -MappedBuffer::MappedBuffer(MappedBuffer &&other)
>> -{
>> -    *this = std::move(other);
>> -}
>> -
>> -/**
>> - * \brief Move assignment operator, replace the mappings with those
>> of \a other
>> -* \param[in] other The other MappedBuffer
>> - *
>> - * Moving a MappedBuffer moves the mappings contained in the \a other
>> to the new
>> - * MappedBuffer and invalidates the \a other.
>> - *
>> - * No mappings are unmapped or destroyed in this process.
>> - */
>> -MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
>> -{
>> -    error_ = other.error_;
>> -    maps_ = std::move(other.maps_);
>> -    other.error_ = -ENOENT;
>> -
>> -    return *this;
>> -}
>> -
>> -MappedBuffer::~MappedBuffer()
>> -{
>> -    for (Plane &map : maps_)
>> -        munmap(map.data(), map.size());
>> -}
>> -
>> -/**
>> - * \fn MappedBuffer::isValid()
>> - * \brief Check if the MappedBuffer instance is valid
>> - * \return True if the MappedBuffer has valid mappings, false otherwise
>> - */
>> -
>> -/**
>> - * \fn MappedBuffer::error()
>> - * \brief Retrieve the map error status
>> - *
>> - * This function retrieves the error status from the MappedBuffer.
>> - * The error status is a negative number as defined by errno.h. If
>> - * no error occurred, this function returns 0.
>> - *
>> - * \return The map error code
>> - */
>> -
>> -/**
>> - * \fn MappedBuffer::maps()
>> - * \brief Retrieve the mapped planes
>> - *
>> - * This function retrieves the successfully mapped planes stored as a
>> vector
>> - * of Span<uint8_t> to provide access to the mapped memory.
>> - *
>> - * \return A vector of the mapped planes
>> - */
>> -
>> -/**
>> - * \var MappedBuffer::error_
>> - * \brief Stores the error value if present
>> - *
>> - * MappedBuffer derived classes shall set this to a negative value as
>> defined
>> - * by errno.h if an error occured during the mapping process.
>> - */
>> -
>> -/**
>> - * \var MappedBuffer::maps_
>> - * \brief Stores the internal mapped planes
>> - *
>> - * MappedBuffer derived classes shall store the mappings they create
>> in this
>> - * vector which is parsed during destruct to unmap any memory
>> mappings which
>> - * completed successfully.
>> - */
>> -
>> -/**
>> - * \class MappedFrameBuffer
>> - * \brief Map a FrameBuffer using the MappedBuffer interface
>> - */
>> -
>> -/**
>> - * \brief Map all planes of a FrameBuffer
>> - * \param[in] buffer FrameBuffer to be mapped
>> - * \param[in] flags Protection flags to apply to map
>> - *
>> - * Construct an object to map a frame buffer for CPU access.
>> - * The flags are passed directly to mmap and should be either PROT_READ,
>> - * PROT_WRITE, or a bitwise-or combination of both.
>> - */
>> -MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int
>> flags)
>> -{
>> -    maps_.reserve(buffer->planes().size());
>> -
>> -    for (const FrameBuffer::Plane &plane : buffer->planes()) {
>> -        void *address = mmap(nullptr, plane.length, flags,
>> -                     MAP_SHARED, plane.fd.fd(), 0);
>> -        if (address == MAP_FAILED) {
>> -            error_ = -errno;
>> -            LOG(Buffer, Error) << "Failed to mmap plane";
>> -            break;
>> -        }
>> -
>> -        maps_.emplace_back(static_cast<uint8_t *>(address),
>> plane.length);
>> -    }
>> -}
>> -
>>   } /* namespace libcamera */
>> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
>> b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
>> index dc3fe63112d4..e6849733f979 100644
>> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
>> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
>> @@ -29,8 +29,9 @@
>>   #include <linux/bcm2835-isp.h>
>>   #include <linux/videodev2.h>
>>   +#include <libcamera/helpers/mapped_buffer.h>
>> +
>>   #include "libcamera/internal/bayer_format.h"
>> -#include "libcamera/internal/buffer.h"
>>   #include "libcamera/internal/camera_sensor.h"
>>   #include "libcamera/internal/delayed_controls.h"
>>   #include "libcamera/internal/device_enumerator.h"
>> diff --git a/src/meson.build b/src/meson.build
>> index 70e1a4618a0f..380de28d0f7a 100644
>> --- a/src/meson.build
>> +++ b/src/meson.build
>> @@ -31,6 +31,7 @@ libcamera_objects = []
>>   # libcamera must be built first as a dependency to the other
>> components.
>>   subdir('libcamera-platform')
>>   subdir('libcamera')
>> +subdir('libcamera-helpers')
>>     subdir('android')
>>   subdir('ipa')
>> diff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp
>> index 5de8201e45f6..218d700f40da 100644
>> --- a/test/mapped-buffer.cpp
>> +++ b/test/mapped-buffer.cpp
>> @@ -4,12 +4,11 @@
>>    *
>>    * libcamera internal MappedBuffer tests
>>    */
>> -
>>   #include <iostream>
>>     #include <libcamera/framebuffer_allocator.h>
>>   -#include "libcamera/internal/buffer.h"
>> +#include <libcamera/helpers/mapped_buffer.h>
>>     #include "camera_test.h"
>>   #include "test.h"
>> diff --git a/test/meson.build b/test/meson.build
>> index 045ad2a2d7c9..ee0d127cf1ec 100644
>> --- a/test/meson.build
>> +++ b/test/meson.build
>> @@ -40,7 +40,6 @@ internal_tests = [
>>       ['file',                            'file.cpp'],
>>       ['file-descriptor',                 'file-descriptor.cpp'],
>>       ['hotplug-cameras',                 'hotplug-cameras.cpp'],
>> -    ['mapped-buffer',                   'mapped-buffer.cpp'],
>>       ['message',                         'message.cpp'],
>>       ['object',                          'object.cpp'],
>>       ['object-delete',                   'object-delete.cpp'],
>> @@ -53,6 +52,10 @@ internal_tests = [
>>       ['utils',                           'utils.cpp'],
>>   ]
>>   +helpers_tests = [
>> +    ['mapped-buffer',                   'mapped-buffer.cpp'],
>> +]
>> +
>>   foreach t : public_tests
>>       exe = executable(t[0], t[1],
>>                        dependencies : libcamera_dep,
>> @@ -70,3 +73,12 @@ foreach t : internal_tests
>>         test(t[0], exe)
>>   endforeach
>> +
>> +foreach t : helpers_tests
>> +    exe = executable(t[0], t[1],
>> +                     dependencies : [libcamera_dep, libcamera_helpers],
>> +                     link_with : test_libraries,
>> +                     include_directories : test_includes_internal)
>> +
>> +    test(t[0], exe)
>> +endforeach

Patch
diff mbox series

diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
index c1b395bf0b83..e67775b99d26 100644
--- a/Documentation/Doxyfile.in
+++ b/Documentation/Doxyfile.in
@@ -791,9 +791,11 @@  WARN_LOGFILE           =
 INPUT                  = "@TOP_SRCDIR@/include/libcamera" \
 			 "@TOP_SRCDIR@/src/ipa/libipa" \
 			 "@TOP_SRCDIR@/src/libcamera" \
+			 "@TOP_SRCDIR@/src/libcamera-helpers" \
 			 "@TOP_SRCDIR@/src/libcamera-platform" \
 			 "@TOP_BUILDDIR@/include/libcamera" \
 			 "@TOP_BUILDDIR@/src/libcamera" \
+			 "@TOP_BUILDDIR@/src/libcamera-helpers" \
 			 "@TOP_BUILDDIR@/src/libcamera-platform"
 
 # This tag can be used to specify the character encoding of the source files
diff --git a/include/libcamera/internal/buffer.h b/include/libcamera/helpers/mapped_buffer.h
similarity index 81%
rename from include/libcamera/internal/buffer.h
rename to include/libcamera/helpers/mapped_buffer.h
index 9da1fbd12c27..ece24f2ddd2c 100644
--- a/include/libcamera/internal/buffer.h
+++ b/include/libcamera/helpers/mapped_buffer.h
@@ -2,16 +2,16 @@ 
 /*
  * Copyright (C) 2020, Google Inc.
  *
- * buffer.h - Internal buffer handling
+ * mapped_buffer.h - Mapped Buffer handling
  */
-#ifndef __LIBCAMERA_INTERNAL_BUFFER_H__
-#define __LIBCAMERA_INTERNAL_BUFFER_H__
+#ifndef __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__
+#define __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__
 
 #include <sys/mman.h>
 #include <vector>
 
-#include <libcamera/class.h>
 #include <libcamera/buffer.h>
+#include <libcamera/class.h>
 #include <libcamera/span.h>
 
 namespace libcamera {
@@ -48,4 +48,4 @@  public:
 
 } /* namespace libcamera */
 
-#endif /* __LIBCAMERA_INTERNAL_BUFFER_H__ */
+#endif /* __LIBCAMERA_HELPERS_MAPPED_BUFFER_H__ */
diff --git a/include/libcamera/helpers/meson.build b/include/libcamera/helpers/meson.build
new file mode 100644
index 000000000000..c025eb930600
--- /dev/null
+++ b/include/libcamera/helpers/meson.build
@@ -0,0 +1,10 @@ 
+# SPDX-License-Identifier: CC0-1.0
+
+libcamera_helpers_include_dir = libcamera_include_dir / 'helpers'
+
+libcamera_helpers_headers = files([
+    'mapped_buffer.h',
+])
+
+install_headers(libcamera_helpers_headers,
+                subdir: libcamera_helpers_include_dir)
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index 1187cc1f63e4..ecd0c8ba183e 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -11,7 +11,6 @@  libcamera_tracepoint_header = custom_target(
 
 libcamera_internal_headers = files([
     'bayer_format.h',
-    'buffer.h',
     'byte_stream_buffer.h',
     'camera_controls.h',
     'camera_sensor.h',
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index 7bfcebc79c86..7c98d8744ec2 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -20,6 +20,7 @@  libcamera_public_headers = files([
 
 include_dir = libcamera_include_dir / 'libcamera'
 
+subdir('helpers')
 subdir('internal')
 subdir('ipa')
 subdir('platform')
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index b9be3df58084..26e5bbc0c26c 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -25,7 +25,7 @@ 
 #include <libcamera/platform/message.h>
 #include <libcamera/platform/thread.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 #include "camera_metadata.h"
 #include "camera_stream.h"
diff --git a/src/android/camera_stream.h b/src/android/camera_stream.h
index 3401672233ca..12484cb607ed 100644
--- a/src/android/camera_stream.h
+++ b/src/android/camera_stream.h
@@ -19,7 +19,7 @@ 
 #include <libcamera/geometry.h>
 #include <libcamera/pixel_format.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 class CameraDevice;
 class CameraMetadata;
diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
index 838da7728382..ca7c1958e20e 100644
--- a/src/android/jpeg/encoder_libjpeg.h
+++ b/src/android/jpeg/encoder_libjpeg.h
@@ -9,7 +9,8 @@ 
 
 #include "encoder.h"
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
+
 #include "libcamera/internal/formats.h"
 
 #include <jpeglib.h>
diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h
index 5d2d4ab224b1..4700a7f562a2 100644
--- a/src/android/jpeg/post_processor_jpeg.h
+++ b/src/android/jpeg/post_processor_jpeg.h
@@ -13,7 +13,7 @@ 
 
 #include <libcamera/geometry.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 class CameraDevice;
 
diff --git a/src/android/jpeg/thumbnailer.h b/src/android/jpeg/thumbnailer.h
index 4e9226c34104..483b41dfe47d 100644
--- a/src/android/jpeg/thumbnailer.h
+++ b/src/android/jpeg/thumbnailer.h
@@ -9,7 +9,8 @@ 
 
 #include <libcamera/geometry.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
+
 #include "libcamera/internal/formats.h"
 
 class Thumbnailer
diff --git a/src/android/meson.build b/src/android/meson.build
index 6edaa1185905..abde9fd2def0 100644
--- a/src/android/meson.build
+++ b/src/android/meson.build
@@ -5,6 +5,7 @@  android_deps = [
     dependency('libjpeg', required : get_option('android')),
     dependency('yaml-0.1', required : get_option('android')),
     libcamera_dep,
+    libcamera_helpers,
 ]
 
 android_enabled = true
diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp
index f138ada14964..64c73c5716ad 100644
--- a/src/android/mm/generic_camera_buffer.cpp
+++ b/src/android/mm/generic_camera_buffer.cpp
@@ -11,7 +11,7 @@ 
 
 #include <libcamera/platform/log.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 using namespace libcamera;
 
diff --git a/src/android/post_processor.h b/src/android/post_processor.h
index 547fda379ed8..53220edaf24d 100644
--- a/src/android/post_processor.h
+++ b/src/android/post_processor.h
@@ -10,7 +10,7 @@ 
 #include <libcamera/buffer.h>
 #include <libcamera/stream.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 #include "camera_buffer.h"
 
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index ca1ce4dc96d0..158eb3bc49e5 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -20,7 +20,7 @@ 
 
 #include <libcamera/platform/log.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 #include "ipu3_agc.h"
 #include "ipu3_awb.h"
diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build
index 0d843846acde..34620024def7 100644
--- a/src/ipa/ipu3/meson.build
+++ b/src/ipa/ipu3/meson.build
@@ -12,7 +12,7 @@  mod = shared_module(ipa_name,
                     [ipu3_ipa_sources, libcamera_generated_ipa_headers],
                     name_prefix : '',
                     include_directories : [ipa_includes, libipa_includes],
-                    dependencies : libcamera_dep,
+                    dependencies : [libcamera_dep, libcamera_helpers],
                     link_with : libipa,
                     install : true,
                     install_dir : ipa_install_dir)
diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build
index 230356d3ce3a..b2ce6f3e8618 100644
--- a/src/ipa/raspberrypi/meson.build
+++ b/src/ipa/raspberrypi/meson.build
@@ -4,6 +4,7 @@  ipa_name = 'ipa_rpi'
 
 rpi_ipa_deps = [
     libcamera_dep,
+    libcamera_helpers,
     dependency('boost'),
     libatomic,
 ]
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
index 90f35d970fd0..b85a1e51d757 100644
--- a/src/ipa/raspberrypi/raspberrypi.cpp
+++ b/src/ipa/raspberrypi/raspberrypi.cpp
@@ -26,7 +26,7 @@ 
 
 #include <libcamera/platform/log.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 #include <linux/bcm2835-isp.h>
 
diff --git a/src/libcamera-helpers/mapped_buffer.cpp b/src/libcamera-helpers/mapped_buffer.cpp
new file mode 100644
index 000000000000..0d4517b62f65
--- /dev/null
+++ b/src/libcamera-helpers/mapped_buffer.cpp
@@ -0,0 +1,171 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * mapped_buffer.cpp - Mapped Buffer handling
+ */
+
+#include <libcamera/helpers/mapped_buffer.h>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <libcamera/platform/log.h>
+
+/**
+ * \file libcamera/helpers/mapped_buffer.h
+ * \brief Mapped Buffer handling
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(MappedBuffer)
+
+/**
+ * \class MappedBuffer
+ * \brief Provide an interface to support managing memory mapped buffers
+ *
+ * The MappedBuffer interface provides access to a set of MappedPlanes which
+ * are available for access by the CPU.
+ *
+ * This class is not meant to be constructed directly, but instead derived
+ * classes should be used to implement the correct mapping of a source buffer.
+ *
+ * This allows treating CPU accessible memory through a generic interface
+ * regardless of whether it originates from a libcamera FrameBuffer or other
+ * source.
+ */
+
+/**
+ * \typedef MappedBuffer::Plane
+ * \brief A mapped region of memory accessible to the CPU
+ *
+ * The MappedBuffer::Plane uses the Span interface to describe the mapped memory
+ * region.
+ */
+
+/**
+ * \brief Construct an empty MappedBuffer
+ */
+MappedBuffer::MappedBuffer()
+	: error_(0)
+{
+}
+
+/**
+ * \brief Move constructor, construct the MappedBuffer with the contents of \a
+ * other using move semantics
+ * \param[in] other The other MappedBuffer
+ *
+ * Moving a MappedBuffer moves the mappings contained in the \a other to the new
+ * MappedBuffer and invalidates the \a other.
+ *
+ * No mappings are unmapped or destroyed in this process.
+ */
+MappedBuffer::MappedBuffer(MappedBuffer &&other)
+{
+	*this = std::move(other);
+}
+
+/**
+ * \brief Move assignment operator, replace the mappings with those of \a other
+* \param[in] other The other MappedBuffer
+ *
+ * Moving a MappedBuffer moves the mappings contained in the \a other to the new
+ * MappedBuffer and invalidates the \a other.
+ *
+ * No mappings are unmapped or destroyed in this process.
+ */
+MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
+{
+	error_ = other.error_;
+	maps_ = std::move(other.maps_);
+	other.error_ = -ENOENT;
+
+	return *this;
+}
+
+MappedBuffer::~MappedBuffer()
+{
+	for (Plane &map : maps_)
+		munmap(map.data(), map.size());
+}
+
+/**
+ * \fn MappedBuffer::isValid()
+ * \brief Check if the MappedBuffer instance is valid
+ * \return True if the MappedBuffer has valid mappings, false otherwise
+ */
+
+/**
+ * \fn MappedBuffer::error()
+ * \brief Retrieve the map error status
+ *
+ * This function retrieves the error status from the MappedBuffer.
+ * The error status is a negative number as defined by errno.h. If
+ * no error occurred, this function returns 0.
+ *
+ * \return The map error code
+ */
+
+/**
+ * \fn MappedBuffer::maps()
+ * \brief Retrieve the mapped planes
+ *
+ * This function retrieves the successfully mapped planes stored as a vector
+ * of Span<uint8_t> to provide access to the mapped memory.
+ *
+ * \return A vector of the mapped planes
+ */
+
+/**
+ * \var MappedBuffer::error_
+ * \brief Stores the error value if present
+ *
+ * MappedBuffer derived classes shall set this to a negative value as defined
+ * by errno.h if an error occured during the mapping process.
+ */
+
+/**
+ * \var MappedBuffer::maps_
+ * \brief Stores the internal mapped planes
+ *
+ * MappedBuffer derived classes shall store the mappings they create in this
+ * vector which is parsed during destruct to unmap any memory mappings which
+ * completed successfully.
+ */
+
+/**
+ * \class MappedFrameBuffer
+ * \brief Map a FrameBuffer using the MappedBuffer interface
+ */
+
+/**
+ * \brief Map all planes of a FrameBuffer
+ * \param[in] buffer FrameBuffer to be mapped
+ * \param[in] flags Protection flags to apply to map
+ *
+ * Construct an object to map a frame buffer for CPU access.
+ * The flags are passed directly to mmap and should be either PROT_READ,
+ * PROT_WRITE, or a bitwise-or combination of both.
+ */
+MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)
+{
+	maps_.reserve(buffer->planes().size());
+
+	for (const FrameBuffer::Plane &plane : buffer->planes()) {
+		void *address = mmap(nullptr, plane.length, flags,
+				     MAP_SHARED, plane.fd.fd(), 0);
+		if (address == MAP_FAILED) {
+			error_ = -errno;
+			LOG(MappedBuffer, Error) << "Failed to mmap plane";
+			break;
+		}
+
+		maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
+	}
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
index 3c862820e6e1..0a232d791fcd 100644
--- a/src/libcamera/buffer.cpp
+++ b/src/libcamera/buffer.cpp
@@ -6,7 +6,6 @@ 
  */
 
 #include <libcamera/buffer.h>
-#include "libcamera/internal/buffer.h"
 
 #include <errno.h>
 #include <string.h>
@@ -18,9 +17,6 @@ 
 /**
  * \file libcamera/buffer.h
  * \brief Buffer handling
- *
- * \file libcamera/internal/buffer.h
- * \brief Internal buffer handling support
  */
 
 namespace libcamera {
@@ -235,149 +231,4 @@  FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)
  * indicate that the metadata is invalid.
  */
 
-/**
- * \class MappedBuffer
- * \brief Provide an interface to support managing memory mapped buffers
- *
- * The MappedBuffer interface provides access to a set of MappedPlanes which
- * are available for access by the CPU.
- *
- * This class is not meant to be constructed directly, but instead derived
- * classes should be used to implement the correct mapping of a source buffer.
- *
- * This allows treating CPU accessible memory through a generic interface
- * regardless of whether it originates from a libcamera FrameBuffer or other
- * source.
- */
-
-/**
- * \typedef MappedBuffer::Plane
- * \brief A mapped region of memory accessible to the CPU
- *
- * The MappedBuffer::Plane uses the Span interface to describe the mapped memory
- * region.
- */
-
-/**
- * \brief Construct an empty MappedBuffer
- */
-MappedBuffer::MappedBuffer()
-	: error_(0)
-{
-}
-
-/**
- * \brief Move constructor, construct the MappedBuffer with the contents of \a
- * other using move semantics
- * \param[in] other The other MappedBuffer
- *
- * Moving a MappedBuffer moves the mappings contained in the \a other to the new
- * MappedBuffer and invalidates the \a other.
- *
- * No mappings are unmapped or destroyed in this process.
- */
-MappedBuffer::MappedBuffer(MappedBuffer &&other)
-{
-	*this = std::move(other);
-}
-
-/**
- * \brief Move assignment operator, replace the mappings with those of \a other
-* \param[in] other The other MappedBuffer
- *
- * Moving a MappedBuffer moves the mappings contained in the \a other to the new
- * MappedBuffer and invalidates the \a other.
- *
- * No mappings are unmapped or destroyed in this process.
- */
-MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
-{
-	error_ = other.error_;
-	maps_ = std::move(other.maps_);
-	other.error_ = -ENOENT;
-
-	return *this;
-}
-
-MappedBuffer::~MappedBuffer()
-{
-	for (Plane &map : maps_)
-		munmap(map.data(), map.size());
-}
-
-/**
- * \fn MappedBuffer::isValid()
- * \brief Check if the MappedBuffer instance is valid
- * \return True if the MappedBuffer has valid mappings, false otherwise
- */
-
-/**
- * \fn MappedBuffer::error()
- * \brief Retrieve the map error status
- *
- * This function retrieves the error status from the MappedBuffer.
- * The error status is a negative number as defined by errno.h. If
- * no error occurred, this function returns 0.
- *
- * \return The map error code
- */
-
-/**
- * \fn MappedBuffer::maps()
- * \brief Retrieve the mapped planes
- *
- * This function retrieves the successfully mapped planes stored as a vector
- * of Span<uint8_t> to provide access to the mapped memory.
- *
- * \return A vector of the mapped planes
- */
-
-/**
- * \var MappedBuffer::error_
- * \brief Stores the error value if present
- *
- * MappedBuffer derived classes shall set this to a negative value as defined
- * by errno.h if an error occured during the mapping process.
- */
-
-/**
- * \var MappedBuffer::maps_
- * \brief Stores the internal mapped planes
- *
- * MappedBuffer derived classes shall store the mappings they create in this
- * vector which is parsed during destruct to unmap any memory mappings which
- * completed successfully.
- */
-
-/**
- * \class MappedFrameBuffer
- * \brief Map a FrameBuffer using the MappedBuffer interface
- */
-
-/**
- * \brief Map all planes of a FrameBuffer
- * \param[in] buffer FrameBuffer to be mapped
- * \param[in] flags Protection flags to apply to map
- *
- * Construct an object to map a frame buffer for CPU access.
- * The flags are passed directly to mmap and should be either PROT_READ,
- * PROT_WRITE, or a bitwise-or combination of both.
- */
-MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)
-{
-	maps_.reserve(buffer->planes().size());
-
-	for (const FrameBuffer::Plane &plane : buffer->planes()) {
-		void *address = mmap(nullptr, plane.length, flags,
-				     MAP_SHARED, plane.fd.fd(), 0);
-		if (address == MAP_FAILED) {
-			error_ = -errno;
-			LOG(Buffer, Error) << "Failed to mmap plane";
-			break;
-		}
-
-		maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
-	}
-}
-
 } /* namespace libcamera */
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index dc3fe63112d4..e6849733f979 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -29,8 +29,9 @@ 
 #include <linux/bcm2835-isp.h>
 #include <linux/videodev2.h>
 
+#include <libcamera/helpers/mapped_buffer.h>
+
 #include "libcamera/internal/bayer_format.h"
-#include "libcamera/internal/buffer.h"
 #include "libcamera/internal/camera_sensor.h"
 #include "libcamera/internal/delayed_controls.h"
 #include "libcamera/internal/device_enumerator.h"
diff --git a/src/meson.build b/src/meson.build
index 70e1a4618a0f..380de28d0f7a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -31,6 +31,7 @@  libcamera_objects = []
 # libcamera must be built first as a dependency to the other components.
 subdir('libcamera-platform')
 subdir('libcamera')
+subdir('libcamera-helpers')
 
 subdir('android')
 subdir('ipa')
diff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp
index 5de8201e45f6..218d700f40da 100644
--- a/test/mapped-buffer.cpp
+++ b/test/mapped-buffer.cpp
@@ -4,12 +4,11 @@ 
  *
  * libcamera internal MappedBuffer tests
  */
-
 #include <iostream>
 
 #include <libcamera/framebuffer_allocator.h>
 
-#include "libcamera/internal/buffer.h"
+#include <libcamera/helpers/mapped_buffer.h>
 
 #include "camera_test.h"
 #include "test.h"
diff --git a/test/meson.build b/test/meson.build
index 045ad2a2d7c9..ee0d127cf1ec 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -40,7 +40,6 @@  internal_tests = [
     ['file',                            'file.cpp'],
     ['file-descriptor',                 'file-descriptor.cpp'],
     ['hotplug-cameras',                 'hotplug-cameras.cpp'],
-    ['mapped-buffer',                   'mapped-buffer.cpp'],
     ['message',                         'message.cpp'],
     ['object',                          'object.cpp'],
     ['object-delete',                   'object-delete.cpp'],
@@ -53,6 +52,10 @@  internal_tests = [
     ['utils',                           'utils.cpp'],
 ]
 
+helpers_tests = [
+    ['mapped-buffer',                   'mapped-buffer.cpp'],
+]
+
 foreach t : public_tests
     exe = executable(t[0], t[1],
                      dependencies : libcamera_dep,
@@ -70,3 +73,12 @@  foreach t : internal_tests
 
     test(t[0], exe)
 endforeach
+
+foreach t : helpers_tests
+    exe = executable(t[0], t[1],
+                     dependencies : [libcamera_dep, libcamera_helpers],
+                     link_with : test_libraries,
+                     include_directories : test_includes_internal)
+
+    test(t[0], exe)
+endforeach