[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