[libcamera-devel] [PATCH 4/4] libcamera: buffer: Provide Buffer Planes

Laurent Pinchart laurent.pinchart at ideasonboard.com
Thu Jan 31 10:16:38 CET 2019


Hi Kieran,

Thank you for the patch.

On Tue, Jan 29, 2019 at 01:53:57PM +0000, Kieran Bingham wrote:
> Extend the Buffer management to support multi-planar formats.
> 
> An image within the system may use one or more Plane objects to track each
> plane in the case of multi-planar image formats. The Buffer class manages all
> of the data required to render or interpret the raw image data.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> ---
>  include/libcamera/buffer.h |  38 +++++++-
>  src/libcamera/buffer.cpp   | 189 +++++++++++++++++++++++++++++++++++--
>  2 files changed, 215 insertions(+), 12 deletions(-)
> 
> diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
> index dda5075f2879..08a74fb70b88 100644
> --- a/include/libcamera/buffer.h
> +++ b/include/libcamera/buffer.h
> @@ -11,20 +11,50 @@
>  
>  namespace libcamera {
>  
> -class Buffer
> +class Plane
>  {
>  public:
> -	Buffer();
> -	~Buffer();
> +	Plane();
> +	Plane(unsigned int length, unsigned int offset);
> +	~Plane();
>  
>  	int dmabuf() const { return fd_; };
>  	int setDmabuf(int fd);
>  
> +	int mmap(int fd);
>  	int mmap();
> -	void munmap();
> +	int munmap();
> +
> +	unsigned int length() const { return length_; };
> +	void *mem() const { return mem_; };
>  
>  private:
>  	int fd_;
> +	unsigned int length_;
> +	unsigned int offset_;
> +	void *mem_;
> +};
> +
> +class Buffer
> +{
> +public:
> +	Buffer();
> +	virtual ~Buffer();
> +
> +	int mmap(int fd);
> +	int munmap();
> +
> +	unsigned int index() const { return index_; };
> +	const std::vector<Plane *> &planes() { return planes_; };
> +
> +private:
> +	unsigned int index_;
> +
> +	unsigned int format_;
> +	unsigned int width_;
> +	unsigned int height_;
> +
> +	std::vector<Plane *> planes_;
>  };
>  
>  class BufferPool
> diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
> index 4a870df77e92..7b84a97dcd2b 100644
> --- a/src/libcamera/buffer.cpp
> +++ b/src/libcamera/buffer.cpp
> @@ -6,10 +6,14 @@
>   */
>  
>  #include <errno.h>
> +#include <string.h>
> +#include <sys/mman.h>
>  #include <unistd.h>
>  
>  #include <libcamera/buffer.h>
>  
> +#include "log.h"
> +
>  /**
>   * \file buffer.h
>   * \brief Buffer handling
> @@ -17,25 +21,46 @@
>  
>  namespace libcamera {
>  
> +LOG_DEFINE_CATEGORY(Buffer)
> +
>  /**
> - * \class Buffer
> - * \brief A memory buffer to store a frame
> + * \class Plane
> + * \brief A memory buffer to store a single plane of a frame

Defining Plane as a memory buffer, and Buffer as a set of Plane, is too
confusing. We need better than that.

>   *
> - * The Buffer class represents a memory buffer used to store a frame.
> + * The Plane class represents a memory region used to store a single plane. It

And here defining Plane as a plane won't really help understanding the
API. We need an overview of how the Buffer and Plane objects interact.

> + * may be backed by it's own dmaBuf handle, and represents a single plane from a

s/it's/its/

> + * Buffer. In the case of multi-planar image formats, multiple Plane objects are
> + * attached to a Buffer to manage the whole picture.

Try reading this paragraph with a newcommer's point of view and I think
you'll realize we need better :-)

>   */
> -Buffer::Buffer()
> -	: fd_(-1)
> +
> +Plane::Plane()
> +	: fd_(-1), length_(0), offset_(0), mem_(0)
>  {
>  }
>  
> -Buffer::~Buffer()
> +/**
> + * \brief Construct a Plane memory region for CPU mappings
> + * \param[in] length The size of the memory region which should be mapped
> + * \param[in] offset The offset into the file descriptor base at which the
> + * buffer commences
> + *
> + * \sa mmap(int fd)
> + */
> +Plane::Plane(unsigned int length, unsigned int offset)
> +	: fd_(-1), length_(length), offset_(offset), mem_(0)
> +{
> +}
> +
> +Plane::~Plane()
>  {
> +	munmap();
> +
>  	if (fd_ != -1)
>  		close(fd_);
>  }
>  
>  /**
> - * \fn Buffer::dmabuf()
> + * \fn Plane::dmabuf()
>   * \brief Get the dmabuf file handle backing the buffer
>   */
>  
> @@ -44,7 +69,7 @@ Buffer::~Buffer()
>   *
>   * The \a fd dmabuf file handle is duplicated and stored.
>   */
> -int Buffer::setDmabuf(int fd)
> +int Plane::setDmabuf(int fd)
>  {
>  	if (fd_ != -1) {
>  		close(fd_);
> @@ -61,6 +86,154 @@ int Buffer::setDmabuf(int fd)
>  	return 0;
>  }
>  
> +/**
> + * \brief Map the plane memory data to a CPU accessible address
> + *
> + * The \a fd specifies the file descriptor to map the memory from.
> + *
> + * \return 0 on success or a negative error value otherwise.
> + */
> +int Plane::mmap(int fd)
> +{
> +	void *map;
> +
> +	map = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
> +		     offset_);
> +	if (map == reinterpret_cast<void *>(-1)) {
> +		int ret = -errno;
> +		LOG(Buffer, Error)
> +			<< "Failed to mmap buffer: " << strerror(ret);
> +		return ret;
> +	}
> +
> +	mem_ = map;
> +
> +	return 0;
> +}
> +
> +/**
> + * \brief Map the plane memory data to a CPU accessible address
> + *
> + * The file descriptor to map the memory from must be set by a call to
> + * setDmaBuf before calling this function.
> + *
> + * \sa setDmaBuf
> + *
> + * \return 0 on success or a negative error value otherwise.

I don't understand why you need two version of mmap().

> + */
> +int Plane::mmap()
> +{
> +	return mmap(fd_);
> +}
> +
> +/**
> + * \brief Unmap any existing CPU accessible mapping
> + *
> + * Unmap the memory mapped by an earlier call to mmap.
> + *
> + * \return 0 on success or a negative error value otherwise.
> + */
> +int Plane::munmap()
> +{
> +	int ret = 0;
> +
> +	if (mem_)
> +		ret = ::munmap(mem_, length_);
> +
> +	if (ret) {
> +		ret = -errno;
> +		LOG(Buffer, Warning)
> +			<< "Failed to unmap buffer: " << strerror(ret);
> +	} else {
> +		mem_ = 0;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * \fn Plane::length()
> + * \brief Get the length of the memory buffer
> + */
> +
> +/**
> + * \fn Plane::mem()
> + * \brief Get the CPU accessible memory address if mapped
> + */
> +
> +/**
> + * \class Buffer
> + * \brief A memory buffer to store an image
> + *
> + * The Buffer class represents the memory buffers used to store a
> + * full frame image, which may contain multiple separate memory Plane
> + * objects if the image format is multi-planar.
> + */
> +
> +Buffer::Buffer()
> +	: index_(-1), format_(0), width_(0), height_(0)
> +{
> +}
> +
> +Buffer::~Buffer()
> +{
> +	for (Plane *plane : planes_)
> +		delete plane;
> +
> +	planes_.clear();
> +}
> +
> +/**
> + * \brief Map each buffer plane to a CPU accessible address
> + *
> + * Utilise the \a fd file descriptor to map each of the Buffer's planes to a CPU
> + * accessible address.
> + *
> + * \return 0 on success or a negative error value otherwise.
> + */
> +int Buffer::mmap(int fd)
> +{
> +	int ret;
> +
> +	for (Plane *plane : planes_) {
> +		ret = plane->mmap(fd);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * \brief Unmap any existing CPU accessible mapping for each plane
> + *
> + * Unmap the memory mapped by an earlier call to mmap.
> + *
> + * \return 0 on success or a negative error value otherwise.
> + */
> +int Buffer::munmap()
> +{
> +	int ret;
> +
> +	for (Plane *plane : planes_) {
> +		ret = plane->munmap();
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * \fn Buffer::index()
> + * \brief Get the Buffer index value
> + */
> +
> +/**
> + * \fn Buffer::planes()
> + * \brief Return a reference to the vector holding all Planes within the buffer
> + */
> +
>  /**
>   * \class BufferPool
>   * \brief A pool of buffers

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list