[RFC,v2,19/22] libcamera: pipeline_handler: Inject "debug" metadata
diff mbox series

Message ID 20250721104622.1550908-20-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • libcamera: Add `MetadataList`
Related show

Commit Message

Barnabás Pőcze July 21, 2025, 10:46 a.m. UTC
Inject all metadata controls in the "debug" namespace into
the metadata plan of each camera so that they can be used
seamlessly. Dynamically sized array-like controls have a
hard-coded size of 32 elements.

Additionally, a new type is added for inspecting properties of
a control type at runtime since that was not available previously.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 include/libcamera/internal/controls.h | 39 +++++++++++++++++++++++
 src/libcamera/controls.cpp            |  2 +-
 src/libcamera/pipeline_handler.cpp    | 45 +++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 1 deletion(-)
 create mode 100644 include/libcamera/internal/controls.h

Patch
diff mbox series

diff --git a/include/libcamera/internal/controls.h b/include/libcamera/internal/controls.h
new file mode 100644
index 000000000..be3f93e43
--- /dev/null
+++ b/include/libcamera/internal/controls.h
@@ -0,0 +1,39 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ */
+
+#pragma once
+
+#include <libcamera/controls.h>
+
+namespace libcamera::controls::details {
+
+struct TypeInfo {
+	std::size_t size = 0;
+	std::size_t alignment = 0;
+
+	explicit operator bool() const { return alignment != 0; }
+
+	static constexpr TypeInfo get(ControlType t)
+	{
+		switch (t) {
+		case ControlTypeNone: return {};
+		case ControlTypeBool: return { sizeof(bool), alignof(bool) };
+		case ControlTypeByte: return { sizeof(uint8_t), alignof(uint8_t) };
+		case ControlTypeUnsigned16: return { sizeof(uint16_t), alignof(uint16_t) };
+		case ControlTypeUnsigned32: return { sizeof(uint32_t), alignof(uint32_t) };
+		case ControlTypeInteger32: return { sizeof(int32_t), alignof(int32_t) };
+		case ControlTypeInteger64: return { sizeof(int64_t), alignof(int64_t) };
+		case ControlTypeFloat: return { sizeof(float), alignof(float) };
+		case ControlTypeString: return { sizeof(char), alignof(char) };
+		case ControlTypeRectangle: return { sizeof(Rectangle), alignof(Rectangle) };
+		case ControlTypeSize: return { sizeof(Size), alignof(Size) };
+		case ControlTypePoint: return { sizeof(Point), alignof(Point) };
+		}
+
+		return {};
+	}
+};
+
+} /* libcamera::controls::details */
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
index a238141a5..d5a86da5e 100644
--- a/src/libcamera/controls.cpp
+++ b/src/libcamera/controls.cpp
@@ -17,7 +17,7 @@ 
 #include "libcamera/internal/control_validator.h"
 
 /**
- * \file controls.h
+ * \file libcamera/controls.h
  * \brief Framework to manage controls related to an object
  *
  * A control is a mean to govern or influence the operation of an object, and in
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index edfa9cf58..c8ac7a673 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -16,11 +16,13 @@ 
 #include <libcamera/base/utils.h>
 
 #include <libcamera/camera.h>
+#include <libcamera/control_ids.h>
 #include <libcamera/framebuffer.h>
 #include <libcamera/property_ids.h>
 
 #include "libcamera/internal/camera.h"
 #include "libcamera/internal/camera_manager.h"
+#include "libcamera/internal/controls.h"
 #include "libcamera/internal/device_enumerator.h"
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/request.h"
@@ -749,6 +751,47 @@  std::string PipelineHandler::configurationFile(const std::string &subdir,
 	return std::string();
 }
 
+namespace {
+
+/*
+ * This is kind of hack. The metadata controls in the "debug" namespace
+ * are forcefully injected into each Camera's MetadataListPlan so that
+ * they work seamlessly without any additional setup.
+ *
+ * The dynamically-sized array-like controls have a maximum capacity
+ * determined by the magic number below.
+ */
+void extendMetadataPlanWithDebugMetadata(MetadataListPlan& mlp)
+{
+	constexpr std::size_t kDynamicArrayCapacity = 32;
+
+	for (const auto &[id, ctrl] : controls::controls) {
+		if (!ctrl->isOutput())
+			continue;
+		if (ctrl->vendor() != "debug")
+			continue;
+		if (mlp.get(id))
+			continue;
+
+		std::size_t count = ctrl->size();
+		if (count == 0)
+			count = 1;
+		else if (ctrl->size() == libcamera::dynamic_extent)
+			count = kDynamicArrayCapacity;
+
+		const auto info = controls::details::TypeInfo::get(ctrl->type());
+		if (!info)
+			continue;
+
+		[[maybe_unused]] bool ok = mlp.set(id,
+						   info.size, info.alignment,
+						   count, ctrl->type(), ctrl->isArray());
+		ASSERT(ok);
+	}
+}
+
+} /* namespace */
+
 /**
  * \brief Register a camera to the camera manager and pipeline handler
  * \param[in] camera The camera to be added
@@ -794,6 +837,8 @@  void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
 	Camera::Private *data = camera->_d();
 	data->properties_.set(properties::SystemDevices, devnums);
 
+	extendMetadataPlanWithDebugMetadata(data->metadataPlan_);
+
 	manager_->_d()->addCamera(std::move(camera));
 }