@@ -122,6 +122,7 @@ public:
const std::string &id() const;
+ Signal<Request *, const ControlList &> metadataCompleted;
Signal<Request *, FrameBuffer *> bufferCompleted;
Signal<Request *> requestCompleted;
Signal<> disconnected;
@@ -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);
@@ -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);
@@ -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
@@ -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)
@@ -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