[v2,21/35] libcamera: converter_dw100: Use vertex map
diff mbox series

Message ID 20251023144841.403689-22-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • Full dewarper support on imx8mp
Related show

Commit Message

Stefan Klug Oct. 23, 2025, 2:48 p.m. UTC
Use the new vertexmap class in the dw100 dewarper implementation.

As the dw100 kernel driver does not use the requests API, controls can
not be tied to a buffer. In the case that the dewarper has buffers
queued for which processing has not yet started, applying the dewarp map
would apply to an already queued buffer. Warn when this situation
occurs.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>

---

Changes in v2:
- Added documentation

Changes in v0.9:
- Include requests support

Changes in v0.8:
- Added warning when queue is not empty
---
 .../internal/converter/converter_dw100.h      | 19 +++++
 .../internal/converter/converter_v4l2_m2m.h   |  4 +-
 src/libcamera/converter/converter_dw100.cpp   | 74 +++++++++++++++++++
 3 files changed, 95 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/internal/converter/converter_dw100.h b/include/libcamera/internal/converter/converter_dw100.h
index dc41f365b5c7..54bc7de4de77 100644
--- a/include/libcamera/internal/converter/converter_dw100.h
+++ b/include/libcamera/internal/converter/converter_dw100.h
@@ -7,6 +7,7 @@ 
 
 #pragma once
 
+#include "libcamera/internal/converter/converter_dw100_vertexmap.h"
 #include "libcamera/internal/converter/converter_v4l2_m2m.h"
 
 namespace libcamera {
@@ -19,6 +20,24 @@  class ConverterDW100 : public V4L2M2MConverter
 {
 public:
 	ConverterDW100(std::shared_ptr<MediaDevice> media);
+
+	int applyVertexMap(const Stream *stream, const V4L2Request *request = nullptr);
+	Dw100VertexMap &vertexMap(const Stream *stream);
+
+private:
+	std::unique_ptr<V4L2M2MStream> makeStream(const Stream *stream) override;
+	class DW100Stream : public V4L2M2MConverter::V4L2M2MStream
+	{
+	public:
+		DW100Stream(V4L2M2MConverter *converter, const Stream *stream);
+
+		int configure(const StreamConfiguration &inputCfg,
+			      const StreamConfiguration &outputCfg) override;
+
+		int applyVertexMap(const V4L2Request *request = nullptr);
+
+		Dw100VertexMap vertexMap_;
+	};
 };
 
 } /* namespace libcamera */
diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h
index 79d008fc6918..03b6670daf22 100644
--- a/include/libcamera/internal/converter/converter_v4l2_m2m.h
+++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h
@@ -89,8 +89,8 @@  protected:
 
 		bool isValid() const { return m2m_ != nullptr; }
 
-		int configure(const StreamConfiguration &inputCfg,
-			      const StreamConfiguration &outputCfg);
+		virtual int configure(const StreamConfiguration &inputCfg,
+				      const StreamConfiguration &outputCfg);
 		int exportBuffers(unsigned int count,
 				  std::vector<std::unique_ptr<FrameBuffer>> *buffers);
 
diff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp
index 1d2d0435b08e..f0764ac8229e 100644
--- a/src/libcamera/converter/converter_dw100.cpp
+++ b/src/libcamera/converter/converter_dw100.cpp
@@ -7,9 +7,12 @@ 
 
 #include "libcamera/internal/converter/converter_dw100.h"
 
+#include <linux/dw100.h>
+
 #include <libcamera/base/log.h>
 
 #include <libcamera/geometry.h>
+#include <libcamera/stream.h>
 
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/v4l2_videodevice.h"
@@ -34,4 +37,75 @@  ConverterDW100::ConverterDW100(std::shared_ptr<MediaDevice> media)
 {
 }
 
+/**
+ * \brief Apply the vertex map for a given stream
+ * \param[in] stream The stream to update
+ * \param[in] request An optional request
+ *
+ * This function updates the vertex map on the stream \a stream. If \a request
+ * is provided, the updated happens in that request.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int ConverterDW100::applyVertexMap(const Stream *stream, const V4L2Request *request)
+{
+	auto iter = streams_.find(stream);
+	if (iter == streams_.end())
+		return -EINVAL;
+
+	return dynamic_cast<DW100Stream *>(iter->second.get())->applyVertexMap(request);
+}
+
+/**
+ * \brief Get the vertex map for a stream
+ * \param[in] stream The stream
+ *
+ * This function returns a reference to the vertex map of the stream \a stream.
+ *
+ * \return The vertex map
+ */
+Dw100VertexMap &ConverterDW100::vertexMap(const Stream *stream)
+{
+	auto iter = streams_.find(stream);
+	V4L2M2MConverter::V4L2M2MStream *s = iter->second.get();
+	ASSERT(s);
+	return dynamic_cast<DW100Stream *>(s)->vertexMap_;
+}
+
+std::unique_ptr<V4L2M2MConverter::V4L2M2MStream> ConverterDW100::makeStream(const Stream *stream)
+{
+	return std::unique_ptr<V4L2M2MConverter::V4L2M2MStream>(new DW100Stream(this, stream));
+}
+
+ConverterDW100::DW100Stream::DW100Stream(V4L2M2MConverter *converter,
+					 const Stream *stream)
+	: V4L2M2MConverter::V4L2M2MStream(converter, stream)
+{
+}
+
+int ConverterDW100::DW100Stream::configure(const StreamConfiguration &inputCfg,
+					   const StreamConfiguration &outputCfg)
+{
+	int ret;
+	ret = V4L2M2MConverter::V4L2M2MStream::configure(inputCfg, outputCfg);
+	if (ret)
+		return ret;
+
+	/* Todo: is that comment still valid?
+	 For actual dewarping we need the active area of the sensor mode here. */
+	vertexMap_.setInputSize(inputCfg.size);
+	vertexMap_.setOutputSize(outputCfg.size);
+	return 0;
+}
+
+int ConverterDW100::DW100Stream::applyVertexMap(const V4L2Request *request)
+{
+	std::vector<uint32_t> map = vertexMap_.getVertexMap();
+	auto value = Span<const int32_t>(reinterpret_cast<const int32_t *>(&map[0]), map.size());
+
+	ControlList ctrls;
+	ctrls.set(V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP, value);
+	return applyControls(ctrls, request);
+}
+
 } /* namespace libcamera */