From patchwork Sun Jun 30 18:10:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1539 Return-Path: Received: from relay12.mail.gandi.net (relay12.mail.gandi.net [217.70.178.232]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C362D61F28 for ; Sun, 30 Jun 2019 20:09:40 +0200 (CEST) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 67D77200004; Sun, 30 Jun 2019 18:09:40 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Sun, 30 Jun 2019 20:10:47 +0200 Message-Id: <20190630181049.9548-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190630181049.9548-1-jacopo@jmondi.org> References: <20190630181049.9548-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC 6/8] libcamera: stream: Add operation to map buffers 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, 30 Jun 2019 18:09:40 -0000 Add and operation to map external buffers provided by applications in a Request to the Stream's internal buffers used by the pipeline handlers to interact with the video device. For streams using internal memory allocation, the two buffers are the same as applications effectively use Buffers from the Stream's pool where the video device memory has been exported to. Signed-off-by: Jacopo Mondi --- include/libcamera/buffer.h | 1 + include/libcamera/stream.h | 5 +++ src/libcamera/stream.cpp | 66 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h index 260a62e9e77e..d5d3dc90a096 100644 --- a/include/libcamera/buffer.h +++ b/include/libcamera/buffer.h @@ -59,6 +59,7 @@ private: friend class BufferPool; friend class PipelineHandler; friend class Request; + friend class Stream; friend class V4L2VideoDevice; void cancel(); diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index 796f1aff2602..4c034c113ddb 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -85,6 +85,8 @@ public: const StreamConfiguration &configuration() const { return configuration_; } MemoryType memoryType() const { return memoryType_; } + Buffer *mapBuffer(Buffer *requestBuffer); + protected: friend class Camera; @@ -94,6 +96,9 @@ protected: BufferPool bufferPool_; StreamConfiguration configuration_; MemoryType memoryType_; + + std::vector mappableBuffers_; + std::map bufferMaps_; }; } /* namespace libcamera */ diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index b6292427d3a2..f36336857ad6 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include "log.h" /** @@ -445,6 +447,26 @@ void Stream::createBuffers(unsigned int count) return; bufferPool_.createBuffers(count); + + /* Streams with internal memory usage do not need buffer mapping. */ + if (memoryType_ == InternalMemory) + return; + + /* + * Prepare for buffer mapping by queuing all buffers from the internal + * pool. Each external buffer presented by application will be mapped + * on an internal one. + */ + mappableBuffers_.clear(); + for (Buffer &buffer : bufferPool_.buffers()) { + /* Reserve all planes to support mapping multiplanar buffers. */ + buffer.planes().clear(); + /* \todo: I would use VIDEO_MAX_PLANES but that's V4L2 stuff.. */ + for (unsigned int i = 0; i < 3; ++i) + buffer.planes().emplace_back(); + + mappableBuffers_.push_back(&buffer); + } } /** @@ -457,6 +479,50 @@ void Stream::destroyBuffers() createBuffers(0); } +/** + * \brief Map the buffer an application has associated with a Request to an + * internl one + * + * \todo Rewrite documentation + * If the Stream uses external memory, we need to map the externally + * provided buffer to an internal one, trying to keep a best effort + * association based on the Buffer's last usage time. + * External and internal buffers are associated by using the dmabuf + * fds as key. + */ +Buffer *Stream::mapBuffer(Buffer *requestBuffer) +{ + /* + * \todo Multiplane APIs have one fd per plane, the key should be + * hashed using all the planes fds. + */ + unsigned int key = requestBuffer->planes()[0].dmabuf(); + + /* If the buffer has already been mapped, just return it. */ + auto mapped = bufferMaps_.find(key); + if (mapped != bufferMaps_.end()) + return mapped->second; + + /* + * Remove the last recently used buffer from the circular list and + * use it for mapping. + */ + auto mappable = mappableBuffers_.begin(); + Buffer *buffer = *mappable; + mappableBuffers_.erase(mappable); + mappableBuffers_.push_back(buffer); + + /* \todo: Support multiplanar external buffers. */ + buffer->planes()[0].setDmabuf(key, 0); + + /* Pipeline handlers use request_ at buffer completion time. */ + buffer->request_ = requestBuffer->request(); + + bufferMaps_[key] = buffer; + + return buffer; +} + /** * \var Stream::bufferPool_ * \brief The pool of buffers associated with the stream