From patchwork Tue Nov 26 23:36:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 2373 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 607CF61C59 for ; Wed, 27 Nov 2019 00:39:45 +0100 (CET) X-Halon-ID: 05b440e8-10a6-11ea-a0b9-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p54ac5865.dip0.t-ipconnect.de [84.172.88.101]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 05b440e8-10a6-11ea-a0b9-005056917f90; Wed, 27 Nov 2019 00:39:43 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 27 Nov 2019 00:36:15 +0100 Message-Id: <20191126233620.1695316-26-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191126233620.1695316-1-niklas.soderlund@ragnatech.se> References: <20191126233620.1695316-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 25/30] libcamera: allocator: Add BufferAllocator to help applications allocate buffers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Nov 2019 23:39:45 -0000 The FrameBuffer interface is based on the idea that all buffers are allocated outside libcamera and are only used by it. This is done to make the API simpler and so that both internal and external buffers are handled in the same way. As V4L2 do not provide a way to allocate buffers without the help of a video device add an application facing helper which hide this. This allow applications to allocate buffers and then use them with cameras. Signed-off-by: Niklas Söderlund --- include/libcamera/allocator.h | 39 ++++++++++ include/libcamera/meson.build | 1 + include/libcamera/stream.h | 1 + src/libcamera/allocator.cpp | 141 ++++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 5 files changed, 183 insertions(+) create mode 100644 include/libcamera/allocator.h create mode 100644 src/libcamera/allocator.cpp diff --git a/include/libcamera/allocator.h b/include/libcamera/allocator.h new file mode 100644 index 0000000000000000..36fce38491b5f3ef --- /dev/null +++ b/include/libcamera/allocator.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * allocator.h - Buffer allocator + */ +#ifndef __LIBCAMERA_ALLOCATOR_H__ +#define __LIBCAMERA_ALLOCATOR_H__ + +#include +#include +#include + +namespace libcamera { + +class Camera; +class FrameBuffer; +class Stream; +struct StreamConfiguration; + +class BufferAllocator +{ +public: + BufferAllocator(std::shared_ptr camera); + ~BufferAllocator(); + + int allocate(Stream *stream, const StreamConfiguration &config); + void release(Stream *stream); + + const std::vector &buffers(Stream *stream) const; + +private: + std::shared_ptr camera_; + std::map> buffers_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_ALLOCATOR_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 99abf06099407c1f..0d0ba2248fd8a679 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -1,4 +1,5 @@ libcamera_api = files([ + 'allocator.h', 'bound_method.h', 'buffer.h', 'camera.h', diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index a3c692c347340382..8e653408fd54cf74 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -85,6 +85,7 @@ public: MemoryType memoryType() const { return memoryType_; } protected: + friend class BufferAllocator; /* To allocate and release buffers. */ friend class Camera; virtual int allocateBuffers(const StreamConfiguration &config, diff --git a/src/libcamera/allocator.cpp b/src/libcamera/allocator.cpp new file mode 100644 index 0000000000000000..8b517c809c05cbcd --- /dev/null +++ b/src/libcamera/allocator.cpp @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * allocator.cpp - Buffer allocator + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "log.h" + +/** + * \file allocator.h + * \brief Buffer allocator + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Allocator) + +/** + * \class BufferAllocator + * \brief Buffer allocator for applications + * + * All buffers are to be treated as if they where allocated outside of the + * camera. In some situations however the only source applications can allocate + * buffers from is the camera. The BufferAllocator is the interface applications + * shall use in these situations. + * + * The buffer allocator creates buffers using resources from a camera and/or + * a stream. The buffers allocated this way are owned by the application and it + * is responsible for their lifetime management. But just as buffers allocated + * external from cameras and streams it's not valid to free a buffer while it's + * queue to a camera. + * + * All buffers allocator are automatically freed when the allocator object is + * deleted. It is the applications responsibility to make sure this do not + * happen while one or more of the buffers are queued to a camera. + * + * If buffers are allocated outside the scope of libcamera by the application it + * do not need to interact with the buffer allocator. + */ + +/** + * \brief Create a BufferAllocator serving a camera + * \param[in] camera Camera the allocator shall serve + */ + +BufferAllocator::BufferAllocator(std::shared_ptr camera) + : camera_(camera) +{ +} + +BufferAllocator::~BufferAllocator() +{ + for (auto &value : buffers_) { + Stream *stream = value.first; + std::vector &buffers = value.second; + + for (FrameBuffer *buffer : buffers) + delete buffer; + + buffers.clear(); + + stream->releaseBuffers(); + } + + buffers_.clear(); +} + +/** + * \brief Allocate buffers from a stream + * \param[in] stream The stream to allocate buffers from + * \param[in] config The configuration described the buffers to be allocated + * + * Allocate buffers matching exactly what is described in \a config. If buffers + * matching \a config can't be allocated an error is returned and no buffers are + * allocated. + * + * \return 0 on success or a negative error code otherwise + */ +int BufferAllocator::allocate(Stream *stream, const StreamConfiguration &config) +{ + auto iter = camera_->streams().find(stream); + if (iter != camera_->streams().end()) + return stream->allocateBuffers(config, &buffers_[stream]); + + LOG(Allocator, Error) << "Stream do not belong to " << camera_->name(); + return -EINVAL; +} + +/** + * \brief Free allocated buffers + * \param[in] stream The stream to free buffers for + * + * Free buffers allocated with allocate(). + */ +void BufferAllocator::release(Stream *stream) +{ + auto iter = buffers_.find(stream); + if (iter == buffers_.end()) + return; + + std::vector &buffers = iter->second; + + for (FrameBuffer *buffer : buffers) + delete buffer; + + buffers.clear(); + + stream->releaseBuffers(); + + buffers_.erase(iter); +} + +/** + * \brief Retrive array of allocated buffers + * \param[in] stream The stream to retrive buffers for + * + * \return Array of buffers + */ +const std::vector &BufferAllocator::buffers(Stream *stream) const +{ + static std::vector empty; + + auto iter = buffers_.find(stream); + if (iter == buffers_.end()) + return empty; + + return iter->second; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index c4f965bd7413b37e..b7041e003fdb1d49 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -1,4 +1,5 @@ libcamera_sources = files([ + 'allocator.cpp', 'bound_method.cpp', 'buffer.cpp', 'byte_stream_buffer.cpp',