[PATCH v2 1/9] libcamera: Camera: Add signals for completion of metadata as a partial result
Harvey Yang
chenghaoyang at chromium.org
Wed Nov 27 10:25:51 CET 2024
From: Han-Lin Chen <hanlinchen at chromium.org>
Allows pipeline handler to signal metadata completion by adding the
following signals to Camera:
Signal<Request *, const ControlList &> metadataAvailable;
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 at chromium.org>
Co-developed-by: Harvey Yang <chenghaoyang at chromium.org>
---
include/libcamera/camera.h | 1 +
include/libcamera/internal/pipeline_handler.h | 1 +
include/libcamera/internal/request.h | 4 ++
include/libcamera/request.h | 1 +
src/libcamera/camera.cpp | 6 +++
src/libcamera/pipeline_handler.cpp | 41 +++++++++++++++++++
src/libcamera/request.cpp | 21 ++++++++++
7 files changed, 75 insertions(+)
diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index 94cee7bd8..eb7cdf81b 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 &> metadataAvailable;
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 fb28a18d0..6c6cad66f 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);
void cancelRequest(Request *request);
diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h
index 4e7d05b1e..286cd9d76 100644
--- a/include/libcamera/internal/request.h
+++ b/include/libcamera/internal/request.h
@@ -43,6 +43,8 @@ public:
void prepare(std::chrono::milliseconds timeout = 0ms);
Signal<> prepared;
+ ControlList addCompletedMetadata(const ControlList &metadata);
+
private:
friend class PipelineHandler;
friend std::ostream &operator<<(std::ostream &out, const Request &r);
@@ -60,6 +62,8 @@ private:
std::unordered_set<FrameBuffer *> pending_;
std::map<FrameBuffer *, std::unique_ptr<EventNotifier>> notifiers_;
std::unique_ptr<Timer> timer_;
+
+ std::unordered_set<unsigned int> completedMetadata_;
};
} /* namespace libcamera */
diff --git a/include/libcamera/request.h b/include/libcamera/request.h
index e214a9d13..2c78d9bb4 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>
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index 7507e9dda..22484721a 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -892,6 +892,12 @@ const std::string &Camera::id() const
* completed
*/
+/**
+ * \var Camera::metadataAvailable
+ * \brief Signal emitted when some metadata for a request is available 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 991b06f26..4ba96cfa2 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -531,6 +531,32 @@ 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 metadata belongs to
+ * \param[in] metadata The partial metadata that has completed
+ *
+ * This function could be called by pipeline handlers to signal availability of
+ * \a metadata before \a request completes. Early metadata completion allows to
+ * notify applications about the availability of a partial metadata buffer
+ * before the associated Request has completed.
+ *
+ * A metadata key is expected to be completed at most once. If it's completed
+ * more than once, the key will be dropped since the second time.
+ *
+ * \context This function shall be called from the CameraManager thread.
+ */
+void PipelineHandler::completeMetadata(Request *request, const ControlList &metadata)
+{
+ const ControlList validMetadata = request->_d()->addCompletedMetadata(metadata);
+ if (!validMetadata.empty()) {
+ request->metadata().merge(validMetadata);
+
+ Camera *camera = request->_d()->camera();
+ camera->metadataAvailable.emit(request, validMetadata);
+ }
+}
+
/**
* \brief Signal request completion
* \param[in] request The request that has completed
@@ -553,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->_d()->addCompletedMetadata(
+ request->metadata());
+ if (!validMetadata.empty())
+ camera->metadataAvailable.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 8c56ed30d..ae5cdeb19 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -178,6 +178,7 @@ void Request::Private::reset()
pending_.clear();
notifiers_.clear();
timer_.reset();
+ completedMetadata_.clear();
}
/*
@@ -270,6 +271,26 @@ void Request::Private::prepare(std::chrono::milliseconds timeout)
* if they have failed preparing.
*/
+/**
+ * \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::Private::addCompletedMetadata(const ControlList &metadata)
+{
+ ControlList resultMetadata;
+ for (auto &[id, value] : metadata) {
+ if (!completedMetadata_.count(id))
+ resultMetadata.set(id, value);
+ }
+
+ return resultMetadata;
+}
+
void Request::Private::notifierActivated(FrameBuffer *buffer)
{
/* Close the fence if successfully signalled. */
--
2.47.0.338.g60cca15819-goog
More information about the libcamera-devel
mailing list