@@ -7,16 +7,21 @@
#pragma once
+#include <functional>
#include <memory>
#include <string>
#include <sys/types.h>
#include <vector>
+#include <libcamera/base/details/cxx20.h>
#include <libcamera/base/object.h>
+#include <libcamera/camera.h>
#include <libcamera/controls.h>
#include <libcamera/stream.h>
+#include "libcamera/internal/request.h"
+
namespace libcamera {
class Camera;
@@ -58,6 +63,50 @@ public:
void registerRequest(Request *request);
void queueRequest(Request *request);
+ void metadataAvailable(Request *request, const ControlList &metadata);
+
+ template<typename T>
+ void metadataAvailable(Request *request, const Control<T> &ctrl,
+ const details::cxx20::type_identity_t<T> &value)
+ {
+ auto &m = request->metadata2();
+ const auto c = m.checkpoint();
+
+ m.set(ctrl, value);
+ request->metadata().set(ctrl, value);
+
+ const auto d = c.diffSince();
+ if (d)
+ request->_d()->camera()->metadataAvailable.emit(request, d);
+ }
+
+#ifndef __DOXYGEN__
+ struct MetadataSetter {
+ Request *request;
+
+ template<typename T>
+ void operator()(const Control<T> &ctrl,
+ const details::cxx20::type_identity_t<T> &value) const
+ {
+ request->metadata().set(ctrl, value);
+ request->metadata2().set(ctrl, value);
+ }
+ };
+
+ template<typename Func, std::enable_if_t<std::is_invocable_v<Func&, MetadataSetter>> * = nullptr>
+#else
+ template<typename Func>
+#endif
+ void metadataAvailable(Request *request, Func func)
+ {
+ const auto c = request->metadata2().checkpoint();
+
+ std::invoke(func, MetadataSetter{ request });
+
+ if (const auto d = c.diffSince())
+ request->_d()->camera()->metadataAvailable.emit(request, d);
+ }
+
bool completeBuffer(Request *request, FrameBuffer *buffer);
void completeRequest(Request *request);
void cancelRequest(Request *request);
@@ -532,6 +532,90 @@ void PipelineHandler::doQueueRequests(Camera *camera)
* \return 0 on success or a negative error code otherwise
*/
+/**
+ * \brief Signal the availability of metadata for \a request
+ * \param[in] request The request the metadata belongs to
+ * \param[in] metadata The collection of metadata items
+ *
+ * This function copies metadata items from \a metadata to the cumulative metadata
+ * collection of \a request. This function may be called multiple times, but metadata
+ * items already present in Request::metadata() are ignored. Afterwards the function
+ * notifies the application by triggering the Camera::availableMetadata signal with
+ * the just added metadata items.
+ *
+ * Early metadata completion allows pipeline handlers to fast track delivery of
+ * metadata results as soon as they are available before the completion of \a
+ * request. The full list of metadata results of a Request is available at
+ * Request completion time in Request::metadata().
+ *
+ * \context This function shall be called from the CameraManager thread.
+ *
+ * \sa PipelineHandler::metadataAvailable(Request *request, Func func)
+ * \sa PipelineHandler::metadataAvailable(Request *request,
+ * const Control<T> &ctrl,
+ * const details::cxx20::type_identity_t<T> &value)
+ */
+void PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+{
+ request->metadata().merge(metadata);
+
+ const auto d = request->metadata2().merge(metadata);
+ if (d)
+ request->_d()->camera()->metadataAvailable.emit(request, d);
+}
+
+/**
+ * \fn void PipelineHandler::metadataAvailable(Request *request, const Control<T> &ctrl,
+ * const details::cxx20::type_identity_t<T> &value)
+ * \copybrief PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+ * \param[in] request The request the metadata belongs to
+ * \param[in] ctrl The control id of the metadata item
+ * \param[in] value The value of the metadata item
+ *
+ * This function servers the same purpose as PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+ * but it allows a single metadata item to be reported directly,
+ * without creating a ControlList.
+ *
+ * \context This function shall be called from the CameraManager thread.
+ * \sa PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+ */
+
+/**
+ * \fn void PipelineHandler::metadataAvailable(Request *request, Func func)
+ * \copybrief PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+ * \param[in] request The request the metadata belongs to
+ * \param[in] func The callback to invoke
+ *
+ * This function serves the same purpose as PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+ * but it provides more flexibility for pipeline handlers. This function invokes
+ * \a func, which receives as its sole argument an object of unspecified type whose
+ * operator() can be used to add metadata items.
+ *
+ * For example, a PipelineHandler might use this function to conditionally report two
+ * metadata items without creating an intermediate ControlList:
+ *
+ * \code
+ metadataAvailable(request, [&](auto set) {
+ if (x)
+ set(controls::X, x);
+ if (y)
+ set(controls::Y, y);
+ // ...
+ });
+ * \endcode
+ *
+ * The advantage of the above over two calls to PipelineHandler::metadataAvailable(Request *request, const Control<T> &ctrl, const details::cxx20::type_identity_t<T> &value)
+ * is that the application is only notified once, after \a func has returned.
+ *
+ * \note Calling any overload of metadataAvailable() inside \a func is not allowed.
+ * \note The object passed to \a func is only usable while \a func runs, it must not
+ * be saved or reused.
+ *
+ * \context This function shall be called from the CameraManager thread.
+ *
+ * \sa PipelineHandler::metadataAvailable(Request *request, const ControlList &metadata)
+ */
+
/**
* \brief Complete a buffer for a request
* \param[in] request The request the buffer belongs to