[libcamera-devel] [PATCH 05/30] libcamera: buffer: Add Dmabuf to describe a dma buffer

Niklas Söderlund niklas.soderlund at ragnatech.se
Wed Nov 27 00:35:55 CET 2019


A FrameBuffer object that holds a frame captured from a sensor consists
of one or more plane(s). The memory of each plane can be accessed by
using a dma buffer. Add a class that describes a dmabuf to make it easy
for applications and IPAs to interact with memory.

Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
 include/libcamera/buffer.h |  19 +++++++
 src/libcamera/buffer.cpp   | 113 +++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+)

diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
index 33793b4ccf881eda..3c430afbfe8e9a05 100644
--- a/include/libcamera/buffer.h
+++ b/include/libcamera/buffer.h
@@ -58,6 +58,25 @@ private:
 	int fd_;
 };
 
+class Dmabuf final
+{
+public:
+	Dmabuf(int fd, unsigned int length);
+	~Dmabuf();
+
+	int fd() const { return fd_.fd(); }
+	unsigned int length() const { return length_; }
+	void *mem();
+
+private:
+	int mmap();
+	int munmap();
+
+	FileDescriptor fd_;
+	unsigned int length_;
+	void *mem_;
+};
+
 class Plane final
 {
 public:
diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
index 0676586ae3be2a61..5516055b2ea885c2 100644
--- a/src/libcamera/buffer.cpp
+++ b/src/libcamera/buffer.cpp
@@ -177,6 +177,119 @@ FileDescriptor::~FileDescriptor()
  * an image may or may not be contiguous.
  */
 
+/**
+ * \class Dmabuf
+ * \brief A memory region to store a single plane of a frame
+ *
+ * Planar pixel formats use multiple memory regions to store planes
+ * corresponding to the different colour components of a frame. The Dmabuf class
+ * tracks the specific details of a memory region used to store a single plane
+ * for a given frame and provides the means to access the memory, both for the
+ * application and for DMA. A Buffer then contains one or multiple planes
+ * depending on its pixel format.
+ *
+ * To support DMA access, planes are associated with dmabuf objects represented
+ * by file handles. Each plane carries a dmabuf file handle and an offset within
+ * the buffer. Those file handles may refer to the same dmabuf object, depending
+ * on whether the devices accessing the memory regions composing the image
+ * support non-contiguous DMA to planes ore require DMA-contiguous memory.
+ *
+ * To support CPU access, planes carry the CPU address of their backing memory.
+ * Similarly to the dmabuf file handles, the CPU addresses for planes composing
+ * an image may or may not be contiguous.
+ */
+
+/**
+ * \brief Set the dmabuf file handle backing the buffer
+ * \param[in] fd The dmabuf file handle
+ * \param[in] length The size of the memory region
+ *
+ * The \a fd dmabuf file handle is duplicated and stored.
+ */
+Dmabuf::Dmabuf(int fd, unsigned int length)
+	: fd_(fd), length_(length), mem_(nullptr)
+{
+}
+
+Dmabuf::~Dmabuf()
+{
+	munmap();
+}
+
+/**
+ * \fn Dmabuf::fd()
+ * \brief Get the dmabuf file handle backing the buffer
+ */
+
+/**
+ * \fn Dmabuf::length()
+ * \brief Retrieve the length of the memory region
+ * \return The length of the memory region
+ */
+
+/**
+ * \fn Dmabuf::mem()
+ * \brief Retrieve the CPU accessible memory address of the Dmabuf
+ * \return The CPU accessible memory address on success or nullptr otherwise.
+ */
+void *Dmabuf::mem()
+{
+	if (!mem_)
+		mmap();
+
+	return mem_;
+}
+
+/**
+ * \brief Map the plane memory data to a CPU accessible address
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int Dmabuf::mmap()
+{
+	void *map;
+
+	if (mem_)
+		return 0;
+
+	map = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_.fd(), 0);
+	if (map == MAP_FAILED) {
+		int ret = -errno;
+		LOG(Buffer, Error)
+			<< "Failed to mmap plane: " << 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 code otherwise
+ */
+int Dmabuf::munmap()
+{
+	int ret = 0;
+
+	if (mem_)
+		ret = ::munmap(mem_, length_);
+
+	if (ret) {
+		ret = -errno;
+		LOG(Buffer, Warning)
+			<< "Failed to unmap plane: " << strerror(-ret);
+	} else {
+		mem_ = 0;
+	}
+
+	return ret;
+}
+
 Plane::Plane()
 	: fd_(-1), length_(0), mem_(0)
 {
-- 
2.24.0



More information about the libcamera-devel mailing list