[1/1] libcamera: Camera: Add signals for completion of metadata as a partial result
diff mbox series

Message ID 20240912045703.3446748-2-chenghaoyang@google.com
State New
Headers show
Series
  • Add metadataCompleted Signal in Camera
Related show

Commit Message

Harvey Yang Sept. 12, 2024, 4:52 a.m. UTC
From: Han-Lin Chen <hanlinchen@chromium.org>

Allows pipeline handler to signal metadata completion by adding the
following signals to Camera:

Signal<Request *, const ControlList &> metadataCompleted;

Together with the bufferCompleted signal, the pipeline handler is allowed to
return buffers and partial metadata at any stage of processing.

Signed-off-by: Han-Lin Chen <hanlinchen@chromium.org>
Co-developed-by: Harvey Yang <chenghaoyang@chromium.org>
---
 include/libcamera/camera.h                    |  1 +
 include/libcamera/internal/pipeline_handler.h |  1 +
 include/libcamera/request.h                   |  5 +++
 src/libcamera/camera.cpp                      |  6 +++
 src/libcamera/pipeline_handler.cpp            | 37 +++++++++++++++++++
 src/libcamera/request.cpp                     | 20 ++++++++++
 6 files changed, 70 insertions(+)

Patch
diff mbox series

diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index 94cee7bd..08c5c58c 100644
--- a/include/libcamera/camera.h
+++ b/include/libcamera/camera.h
@@ -122,6 +122,7 @@  public:
 
 	const std::string &id() const;
 
+	Signal<Request *, const ControlList &> metadataCompleted;
 	Signal<Request *, FrameBuffer *> bufferCompleted;
 	Signal<Request *> requestCompleted;
 	Signal<> disconnected;
diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index 0d380803..1af63a23 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -58,6 +58,7 @@  public:
 	void registerRequest(Request *request);
 	void queueRequest(Request *request);
 
+	void completeMetadata(Request *request, const ControlList &metadata);
 	bool completeBuffer(Request *request, FrameBuffer *buffer);
 	void completeRequest(Request *request);
 
diff --git a/include/libcamera/request.h b/include/libcamera/request.h
index e214a9d1..0200f4a1 100644
--- a/include/libcamera/request.h
+++ b/include/libcamera/request.h
@@ -12,6 +12,7 @@ 
 #include <ostream>
 #include <stdint.h>
 #include <string>
+#include <unordered_set>
 
 #include <libcamera/base/class.h>
 #include <libcamera/base/signal.h>
@@ -64,6 +65,8 @@  public:
 
 	std::string toString() const;
 
+	ControlList addCompletedMetadata(const ControlList &metadata);
+
 private:
 	LIBCAMERA_DISABLE_COPY(Request)
 
@@ -73,6 +76,8 @@  private:
 
 	const uint64_t cookie_;
 	Status status_;
+
+	std::unordered_set<unsigned int> completedMetadata_;
 };
 
 std::ostream &operator<<(std::ostream &out, const Request &r);
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index a86f552a..5ffae23e 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -892,6 +892,12 @@  const std::string &Camera::id() const
  * completed
  */
 
+/**
+ * \var Camera::metadataCompleted
+ * \brief Signal emitted when some metadata for a request is completed as a
+ * partial result
+ */
+
 /**
  * \var Camera::requestCompleted
  * \brief Signal emitted when a request queued to the camera has completed
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index e5940469..5d2999cb 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -535,6 +535,28 @@  bool PipelineHandler::completeBuffer(Request *request, FrameBuffer *buffer)
 	return request->_d()->completeBuffer(buffer);
 }
 
+/**
+ * \brief Complete part of metadata for a request
+ * \param[in] request The request the buffer belongs to
+ * \param[in] metadata The partial metadata that has completed
+ *
+ * This function could be called by pipeline handlers to signal completion of
+ * the \a metadata part of the \a request. It notifies applications of metadata
+ * completion.
+ *
+ * \context This function shall be called from the CameraManager thread.
+ */
+void PipelineHandler::completeMetadata(Request *request, const ControlList &metadata)
+{
+	const ControlList &validMetadata = request->addCompletedMetadata(metadata);
+	if (!validMetadata.empty()) {
+		request->metadata().merge(validMetadata);
+
+		Camera *camera = request->_d()->camera();
+		camera->metadataCompleted.emit(request, validMetadata);
+	}
+}
+
 /**
  * \brief Signal request completion
  * \param[in] request The request that has completed
@@ -557,6 +579,21 @@  void PipelineHandler::completeRequest(Request *request)
 
 	Camera::Private *data = camera->_d();
 
+	/*
+	 * Collect metadata which is not yet completed by the Camera, and
+	 * create one partial result to cover the missing metadata before
+	 * completing the whole request. This guarantees the aggregation of
+	 * metadata in completed partial results equals to the global metadata
+	 * in the request.
+	 *
+	 * \todo: Forbid merging metadata into request.metadata() directly and
+	 * force calling completeMetadata() to report metadata.
+	 */
+	const ControlList &validMetadata = request->addCompletedMetadata(
+		request->metadata());
+	if (!validMetadata.empty())
+		camera->metadataCompleted.emit(request, validMetadata);
+
 	while (!data->queuedRequests_.empty()) {
 		Request *req = data->queuedRequests_.front();
 		if (req->status() == Request::RequestPending)
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index 8c56ed30..3ce23a8e 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -598,6 +598,26 @@  std::string Request::toString() const
 	return ss.str();
 }
 
+/**
+ * \brief Add completed metadata, as a partial result
+ * \param[in] metadata The metadata completed
+ *
+ * Request will record the entries that has been sent to the application, to
+ * prevent duplicated controls.
+ *
+ * \return ControlList that hasn't been completed before
+ */
+ControlList Request::addCompletedMetadata(const ControlList &metadata)
+{
+	ControlList resultMetadata;
+	for (auto &[id, value] : metadata) {
+		if (!completedMetadata_.count(id))
+			resultMetadata.set(id, value);
+	}
+
+	return resultMetadata;
+}
+
 /**
  * \brief Insert a text representation of a Request into an output stream
  * \param[in] out The output stream