From patchwork Thu Oct 23 14:48:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24748 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 36CB2C333E for ; Thu, 23 Oct 2025 14:49:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9EA4B6083E; Thu, 23 Oct 2025 16:49:50 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="hW2jcGXj"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BA4116081B for ; Thu, 23 Oct 2025 16:49:49 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:7328:357b:4ce1:72b6]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id C795CEFE; Thu, 23 Oct 2025 16:48:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1761230884; bh=zMPONoLmMpfnqpDZLSi9vEhOn9O6IhoX/4F6zyJ6XB4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hW2jcGXjNJhyrMljDGOkxg3sNheakHeq4Mkxae8ti9yyZrwK1fh4ICrIqt8ttqIxb nd5FDIfrPftlDOWreqF1DOqrhRXYpAatJS1B/E43CvrIzF0XghG3JKOx8FPRImkXct B3Gmz8OqGXo6bQaqyNky3QePizhxvCrFIyRiqFtg= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v2 21/35] libcamera: converter_dw100: Use vertex map Date: Thu, 23 Oct 2025 16:48:22 +0200 Message-ID: <20251023144841.403689-22-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251023144841.403689-1-stefan.klug@ideasonboard.com> References: <20251023144841.403689-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- 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(-) 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 media); + + int applyVertexMap(const Stream *stream, const V4L2Request *request = nullptr); + Dw100VertexMap &vertexMap(const Stream *stream); + +private: + std::unique_ptr 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> *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 + #include #include +#include #include "libcamera/internal/media_device.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -34,4 +37,75 @@ ConverterDW100::ConverterDW100(std::shared_ptr 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(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(s)->vertexMap_; +} + +std::unique_ptr ConverterDW100::makeStream(const Stream *stream) +{ + return std::unique_ptr(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 map = vertexMap_.getVertexMap(); + auto value = Span(reinterpret_cast(&map[0]), map.size()); + + ControlList ctrls; + ctrls.set(V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP, value); + return applyControls(ctrls, request); +} + } /* namespace libcamera */