@@ -11,20 +11,49 @@
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();
- 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 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
@@ -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,52 @@
namespace libcamera {
+LOG_DEFINE_CATEGORY(Buffer)
+
/**
- * \class Buffer
- * \brief A memory buffer to store a frame
+ * \class Plane
+ * \brief A memory region to store a single plane of a frame
+ *
+ * Image pixel formats may require more than one memory region to store separate
+ * planar data. These memory regions may be different sizes depending upon the
+ * pixel formats, and may be backed against different dmabuf handles when
+ * working with the V4L2 MPLANE api.
*
- * The Buffer class represents a memory buffer used to store a frame.
+ * The Plane class tracks the specific details of a memory region used to store
+ * a single plane for a given image and provides the means to map and access the
+ * data from an application.
+ *
+ * A Buffer may contain multiple Plane instances for multi-planar image formats.
*/
-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()
+ */
+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
*/
@@ -46,7 +77,7 @@ Buffer::~Buffer()
*
* \return 0 on success or a negative error value otherwise.
*/
-int Buffer::setDmabuf(int fd)
+int Plane::setDmabuf(int fd)
{
if (fd_ != -1) {
close(fd_);
@@ -70,6 +101,146 @@ int Buffer::setDmabuf(int fd)
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.
+ */
+int Plane::mmap()
+{
+ void *map;
+
+ if (mem_)
+ return 0;
+
+ 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 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
+ *
+ * Each buffer plane must have had it's dmabuf handle set before attempting to
+ * mmap.
+ *
+ * \return 0 on success or a negative error value otherwise.
+ */
+int Buffer::mmap()
+{
+ int ret;
+
+ for (Plane *plane : planes_) {
+ ret = plane->mmap();
+ 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
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@ideasonboard.com> --- include/libcamera/buffer.h | 37 +++++++- src/libcamera/buffer.cpp | 187 +++++++++++++++++++++++++++++++++++-- 2 files changed, 212 insertions(+), 12 deletions(-)