diff options
-rw-r--r-- | include/libcamera/buffer.h | 74 | ||||
-rw-r--r-- | include/libcamera/libcamera.h | 1 | ||||
-rw-r--r-- | include/libcamera/meson.build | 1 | ||||
-rw-r--r-- | src/libcamera/buffer.cpp | 253 | ||||
-rw-r--r-- | src/libcamera/meson.build | 1 |
5 files changed, 330 insertions, 0 deletions
diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h new file mode 100644 index 00000000..21a1ec4c --- /dev/null +++ b/include/libcamera/buffer.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * buffer.h - Buffer handling + */ +#ifndef __LIBCAMERA_BUFFER_H__ +#define __LIBCAMERA_BUFFER_H__ + +#include <vector> + +#include <libcamera/signal.h> + +namespace libcamera { + +class BufferPool; + +class Plane final +{ +public: + Plane(); + ~Plane(); + + int dmabuf() const { return fd_; } + int setDmabuf(int fd, unsigned int length); + + void *mem(); + unsigned int length() const { return length_; } + +private: + int mmap(); + int munmap(); + + int fd_; + unsigned int length_; + void *mem_; +}; + +class Buffer final +{ +public: + Buffer(); + + unsigned int index() const { return index_; } + std::vector<Plane> &planes() { return planes_; } + + Signal<Buffer *> completed; + +private: + friend class BufferPool; + + unsigned int index_; + + std::vector<Plane> planes_; +}; + +class BufferPool final +{ +public: + ~BufferPool(); + + void createBuffers(unsigned int count); + void destroyBuffers(); + + unsigned int count() const { return buffers_.size(); } + std::vector<Buffer> &buffers() { return buffers_; } + +private: + std::vector<Buffer> buffers_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_BUFFER_H__ */ diff --git a/include/libcamera/libcamera.h b/include/libcamera/libcamera.h index 272dfd5e..8167e809 100644 --- a/include/libcamera/libcamera.h +++ b/include/libcamera/libcamera.h @@ -7,6 +7,7 @@ #ifndef __LIBCAMERA_LIBCAMERA_H__ #define __LIBCAMERA_LIBCAMERA_H__ +#include <libcamera/buffer.h> #include <libcamera/camera.h> #include <libcamera/camera_manager.h> #include <libcamera/event_dispatcher.h> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 54a68078..8c14423b 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -1,4 +1,5 @@ libcamera_api = files([ + 'buffer.h', 'camera.h', 'camera_manager.h', 'event_dispatcher.h', diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp new file mode 100644 index 00000000..5f6114cf --- /dev/null +++ b/src/libcamera/buffer.cpp @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * buffer.cpp - Buffer handling + */ + +#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 + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Buffer) + +/** + * \class Plane + * \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 Plane 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. + */ + +Plane::Plane() + : fd_(-1), length_(0), mem_(0) +{ +} + +Plane::~Plane() +{ + munmap(); + + if (fd_ != -1) + close(fd_); +} + +/** + * \fn Plane::dmabuf() + * \brief Get the dmabuf file handle backing the buffer + */ + +/** + * \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. The caller may close + * the original file handle. + * + * \return 0 on success or a negative error value otherwise. + */ +int Plane::setDmabuf(int fd, unsigned int length) +{ + if (fd < 0) { + LOG(Buffer, Error) << "Invalid dmabuf fd provided"; + return -EINVAL; + } + + if (fd_ != -1) { + close(fd_); + fd_ = -1; + } + + fd_ = dup(fd); + if (fd_ == -1) { + int ret = -errno; + LOG(Buffer, Error) + << "Failed to duplicate dmabuf: " << strerror(-ret); + return ret; + } + + length_ = length; + + 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_, 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 value otherwise. + */ +int Plane::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; +} + +/** + * \fn Plane::mem() + * \brief Retrieve the CPU accessible memory address of the Plane + * \return The CPU accessible memory address on success or nullptr otherwise. + */ +void *Plane::mem() +{ + if (!mem_) + mmap(); + + return mem_; +} + +/** + * \fn Plane::length() + * \brief Retrieve the length of the memory region + * \return The length of the memory region + */ + +/** + * \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) +{ +} + +/** + * \fn Buffer::index() + * \brief Retrieve the Buffer index + * \return The buffer index + */ + +/** + * \fn Buffer::planes() + * \brief Retrieve the planes within the buffer + * \return A reference to a vector holding all Planes within the buffer + */ + +/** + * \var Buffer::completed + * \brief A Signal to provide notifications that the specific Buffer is ready + */ + +/** + * \class BufferPool + * \brief A pool of buffers + * + * The BufferPool class groups together a collection of Buffers to store frames. + * The buffers must be exported by a device before they can be imported into + * another device for further use. + */ + +BufferPool::~BufferPool() +{ + destroyBuffers(); +} + +/** + * \brief Create buffers in the Pool + * \param[in] count The number of buffers to create + */ +void BufferPool::createBuffers(unsigned int count) +{ + unsigned int index = 0; + + buffers_.resize(count); + for (Buffer &buffer : buffers_) + buffer.index_ = index++; +} + +/** + * \brief Release all buffers from pool + */ +void BufferPool::destroyBuffers() +{ + buffers_.resize(0); +} + +/** + * \fn BufferPool::count() + * \brief Retrieve the number of buffers contained within the pool + * \return The number of buffers contained in the pool + */ + +/** + * \fn BufferPool::buffers() + * \brief Retrieve all the buffers in the pool + * \return A vector containing all the buffers in the pool. + */ + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 9f6ff99e..a4e9cc8f 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -1,4 +1,5 @@ libcamera_sources = files([ + 'buffer.cpp', 'camera.cpp', 'camera_manager.cpp', 'device_enumerator.cpp', |