[v2,1/7] libcamera: request: Introduce internal buffers
diff mbox series

Message ID 20240220164317.998477-2-dan.scally@ideasonboard.com
State New
Headers show
Series
  • Remove RkISP1FrameInfo and IPU3Frames classes
Related show

Commit Message

Daniel Scally Feb. 20, 2024, 4:43 p.m. UTC
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@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(-)

Patch
diff mbox series

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();