From patchwork Sun Feb 3 10:55:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 486 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6440D60DB5 for ; Sun, 3 Feb 2019 11:55:22 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1118A41; Sun, 3 Feb 2019 11:55:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191322; bh=ucXzhou69UrroknYx5pOV3IP4jtEFpQzVog2HmdzNFk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qxXEyG4/0sg0qWLjBvRB6Pbe0dYnSZ+3l906m2jicvV4JPr0RcwXR/nqbzG4Xcx8z RFSOnMIIrSoRFAqk3XFbn3f2qyKpLX+6xubzwCFM3lXHbs4eYejFX5O5UZHPN3ByHB 3dOMCkPVoih1LF97qcCcIZgmxJ/dNN9zq/SQdH5Y= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 11:55:17 +0100 Message-Id: <20190203105517.5355-6-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203105517.5355-1-kieran.bingham@ideasonboard.com> References: <20190203105517.5355-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/5] libcamera: buffer: Provide Buffer Planes X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 10:55:22 -0000 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 --- include/libcamera/buffer.h | 37 +++++++- src/libcamera/buffer.cpp | 187 +++++++++++++++++++++++++++++++++++-- 2 files changed, 212 insertions(+), 12 deletions(-) diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h index dda5075f2879..afe99d5c4ab0 100644 --- a/include/libcamera/buffer.h +++ b/include/libcamera/buffer.h @@ -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 &planes() { return planes_; }; + +private: + unsigned int index_; + + unsigned int format_; + unsigned int width_; + unsigned int height_; + + std::vector planes_; }; class BufferPool diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp index 08deaa97e4af..887863b2af2e 100644 --- a/src/libcamera/buffer.cpp +++ b/src/libcamera/buffer.cpp @@ -6,10 +6,14 @@ */ #include +#include +#include #include #include +#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(-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