libcamera: buffer: Create a MappedBuffer

Provide a MappedFrameBuffer helper class which will map
all of the Planes within a FrameBuffer and provide CPU addressable
pointers for those planes.

The MappedFrameBuffer implements the interface of the MappedBuffer
allowing other buffer types to be constructed of the same form, with a
common interface and cleanup.

This allows MappedBuffer instances to be created from Camera3Buffer types.

Mappings are removed upon destruction.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Kieran Bingham 2020-07-17 16:55:59 +01:00
parent 38ca814e97
commit b3383da79f
2 changed files with 197 additions and 1 deletions

View file

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2020, Google Inc.
*
* buffer.h - Internal buffer handling
*/
#ifndef __LIBCAMERA_INTERNAL_BUFFER_H__
#define __LIBCAMERA_INTERNAL_BUFFER_H__
#include <sys/mman.h>
#include <vector>
#include <libcamera/buffer.h>
#include <libcamera/span.h>
namespace libcamera {
class MappedBuffer
{
public:
using Plane = Span<uint8_t>;
~MappedBuffer();
MappedBuffer(MappedBuffer &&other);
MappedBuffer &operator=(MappedBuffer &&other);
bool isValid() const { return error_ == 0; }
int error() const { return error_; }
const std::vector<Plane> &maps() const { return maps_; }
protected:
MappedBuffer();
int error_;
std::vector<Plane> maps_;
};
class MappedFrameBuffer : public MappedBuffer
{
public:
MappedFrameBuffer(const FrameBuffer *buffer, int flags);
};
} /* namespace libcamera */
#endif /* __LIBCAMERA_INTERNAL_BUFFER_H__ */

View file

@ -6,6 +6,7 @@
*/ */
#include <libcamera/buffer.h> #include <libcamera/buffer.h>
#include "libcamera/internal/buffer.h"
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
@ -15,8 +16,11 @@
#include "libcamera/internal/log.h" #include "libcamera/internal/log.h"
/** /**
* \file buffer.h * \file libcamera/buffer.h
* \brief Buffer handling * \brief Buffer handling
*
* \file libcamera/internal/buffer.h
* \brief Internal buffer handling support
*/ */
namespace libcamera { namespace libcamera {
@ -290,4 +294,149 @@ int FrameBuffer::copyFrom(const FrameBuffer *src)
return 0; return 0;
} }
/**
* \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
*
* 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 */ } /* namespace libcamera */