[PATCH v2 1/7] libcamera: request: Introduce internal buffers
Daniel Scally
dan.scally at ideasonboard.com
Tue Feb 20 17:43:11 CET 2024
To simplify Pipeline Handler code designed to track whether a
Request is ready to be returned to the application or not, extend
Request::Private with the concept of internal buffers. These can
be added to a Request::Private and associated with a role, for which
a new enumeration holds descriptors. Internal buffers added to a
Request in this way count towards pending buffers and so will cause
hasPendingBuffers() to return false until they are also completed.
This necessitates a checks before emiting the bufferCompleted signal
to confirm that the buffer under consideration is associated with a
Stream rather than a purely-internal buffer.
Signed-off-by: Daniel Scally <dan.scally at ideasonboard.com>
---
Changes in v2:
- New patch, previously this was just done via the inFlightStatsBuffers
map in the RkISP1 pipeline handler.
include/libcamera/internal/request.h | 12 ++++
src/libcamera/pipeline_handler.cpp | 9 ++-
src/libcamera/request.cpp | 93 +++++++++++++++++++++++++++-
3 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h
index 3454cf5a..03ccc7e5 100644
--- a/include/libcamera/internal/request.h
+++ b/include/libcamera/internal/request.h
@@ -31,9 +31,20 @@ public:
Private(Camera *camera);
~Private();
+ enum InternalStream {
+ Parameters,
+ Statistics,
+ Mem2Mem,
+ };
+
+ using InternalBufferMap = std::map<InternalStream, FrameBuffer *>;
+
Camera *camera() const { return camera_; }
bool hasPendingBuffers() const;
+ const InternalBufferMap &internalBuffers() const { return internalBufferMap_; }
+ int addInternalBuffer(InternalStream stream, FrameBuffer *buffer);
+ FrameBuffer *findInternalBuffer(InternalStream stream);
bool completeBuffer(FrameBuffer *buffer);
void complete();
void cancel();
@@ -59,6 +70,7 @@ private:
std::unordered_set<FrameBuffer *> pending_;
std::map<FrameBuffer *, std::unique_ptr<EventNotifier>> notifiers_;
std::unique_ptr<Timer> timer_;
+ InternalBufferMap internalBufferMap_;
};
} /* namespace libcamera */
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 29e0c98a..343804e9 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -499,7 +499,14 @@ void PipelineHandler::doQueueRequests()
bool PipelineHandler::completeBuffer(Request *request, FrameBuffer *buffer)
{
Camera *camera = request->_d()->camera();
- camera->bufferCompleted.emit(request, buffer);
+
+ for (auto pair : request->buffers()) {
+ if (pair.second == buffer) {
+ camera->bufferCompleted.emit(request, buffer);
+ break;
+ }
+ }
+
return request->_d()->completeBuffer(buffer);
}
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index 949c556f..3b852f7b 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -57,6 +57,22 @@ Request::Private::~Private()
doCancelRequest();
}
+/**
+ * \enum Request::Private::InternalStream
+ * Internal stream identifiers
+ * \var Request::Private::Parameters
+ * The stream relates to ISP parameters
+ * \var Request::Private::Statistics
+ * The stream relates to ISP statistics
+ * \var Request::Private::Mem2Mem
+ * The stream relates to memory-to-memory mode operation
+ */
+
+/**
+ * \typedef Request::Private::InternalBufferMap
+ * \brief A map of InternalStream to FrameBuffer pointers
+ */
+
/**
* \fn Request::Private::camera()
* \brief Retrieve the camera this request has been queued to
@@ -75,6 +91,72 @@ bool Request::Private::hasPendingBuffers() const
return !pending_.empty();
}
+/**
+ * \fn Request::Private::internalBuffers
+ * \brief Retrieve the Request::Private's InternalStreams to buffers map
+ *
+ * Return a reference to the map that associates each InternalStream to the
+ * FrameBuffer it uses.
+ *
+ * \return The map of InternalStream to FrameBuffer
+ */
+
+/**
+ * \brief Add a FrameBuffer to a Request for an InternalStream
+ * \param[in] stream The InternalStream the buffer is used for
+ * \param[in] buffer The FrameBuffer to add to the request
+ *
+ * A reference to the buffer is stored in the request. The caller is responsible
+ * for ensuring that the buffer will remain valid until the request complete
+ * callback is called.
+ *
+ * A request can only contain one buffer per InternalStream. If a buffer has
+ * already been added to the request for the same InternalStream, this function
+ * returns -EEXIST.
+ *
+ * \return 0 on success or a negative error code otherwise
+ * \retval -EEXIST The request already contains a buffer for the stream
+ */
+int Request::Private::addInternalBuffer(InternalStream stream, FrameBuffer *buffer)
+{
+ auto it = internalBufferMap_.find(stream);
+ if (it != internalBufferMap_.end()) {
+ LOG(Request, Error)
+ << "FrameBuffer already set for internal stream";
+ return -EEXIST;
+ }
+
+ buffer->_d()->setRequest(_o<Request>());
+ pending_.insert(buffer);
+ internalBufferMap_[stream] = buffer;
+
+ return 0;
+}
+
+/**
+ * \var Request::Private::internalBufferMap_
+ * \brief Mapping of private buffer streams to buffers for this request
+ *
+ * The internalBufferMap_ tracks the buffers associated with each internal
+ * buffer stream. If a stream is not utilised in this request there will be no
+ * buffer for that stream in the map.
+ */
+
+/**
+ * \brief Return the buffer associated with a stream
+ * \param[in] stream The \ref InternalStream the buffer is associated to
+ * \return The buffer associated with the stream, or nullptr if the stream is
+ * not part of this request
+ */
+FrameBuffer *Request::Private::findInternalBuffer(InternalStream stream)
+{
+ auto it = internalBufferMap_.find(stream);
+ if (it == internalBufferMap_.end())
+ return nullptr;
+
+ return it->second;
+}
+
/**
* \brief Complete a buffer for the request
* \param[in] buffer The buffer that has completed
@@ -130,7 +212,14 @@ void Request::Private::doCancelRequest()
for (FrameBuffer *buffer : pending_) {
buffer->_d()->cancel();
- camera_->bufferCompleted.emit(request, buffer);
+
+ for (auto pair : request->bufferMap_) {
+ if (pair.second == buffer) {
+ camera_->bufferCompleted.emit(request, buffer);
+
+ break;
+ }
+ }
}
cancelled_ = true;
@@ -395,6 +484,8 @@ void Request::reuse(ReuseFlag flags)
bufferMap_.clear();
}
+ _d()->internalBufferMap_.clear();
+
status_ = RequestPending;
controls_->clear();
--
2.34.1
More information about the libcamera-devel
mailing list