From patchwork Tue Nov 25 16:28:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 25207 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 CD921C3338 for ; Tue, 25 Nov 2025 16:30:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 797B760C6B; Tue, 25 Nov 2025 17:30:19 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="a3onN/CS"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3958A60A9E for ; Tue, 25 Nov 2025 17:30:18 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:bae1:340c:573c:570b]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 4C0DC20E6; Tue, 25 Nov 2025 17:28:09 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1764088089; bh=KaJ8SJFcJP01NIS+AmLdW5zLqpm8qBdeOgGbRh+56xY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a3onN/CSK42MgwlrPuxrC4Gjo2V81Gs1J3zrUmcP8jHxBX1A9ALsvAmhrRT+JemRy HqeHcIGSAbVgSLeK3r15ATa8xVC9RmFUDyi2W5HUM+t4EaW268IGZexR+Vv5KWADLK eEzX2ENnkrVlPGrcBEua2tP3u/ONAuVxJYE672Kc= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 28/29] DNI libcamera: rkisp1: Implement dw100 specific features Date: Tue, 25 Nov 2025 17:28:40 +0100 Message-ID: <20251125162851.2301793-29-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251125162851.2301793-1-stefan.klug@ideasonboard.com> References: <20251125162851.2301793-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" The dw100 allows more features implemented in the dw100 vertex map. Implement these features for the rkisp1 pipeline. Signed-off-by: Stefan Klug --- Changes in v3: - Move control handling from pipeline handler to the converter class - Moved controls into core namespace Changes in v2: - Marked as DoNotIntegrate because the puplic interface needs further discussions - Added Dw100EffectiveScale metadata --- .../converter/converter_dw100_vertexmap.h | 2 +- src/libcamera/control_ids_core.yaml | 50 +++++++++++++++++++ src/libcamera/converter/converter_dw100.cpp | 36 +++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/converter/converter_dw100_vertexmap.h b/include/libcamera/internal/converter/converter_dw100_vertexmap.h index 49ecc81678a0..f79274a6098a 100644 --- a/include/libcamera/internal/converter/converter_dw100_vertexmap.h +++ b/include/libcamera/internal/converter/converter_dw100_vertexmap.h @@ -42,7 +42,7 @@ public: const Transform &transform() const { return transform_; } void setScale(const float scale) { scale_ = scale; } - float effectiveScale() const { return (effectiveScaleX_ + effectiveScaleY_) * 0.5; } + std::array effectiveScale() const { return { static_cast(effectiveScaleX_), static_cast(effectiveScaleY_) }; } void setRotation(const float rotation) { rotation_ = rotation; } float rotation() const { return rotation_; } diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index 3bcb475fd102..e03b570282ba 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -1353,4 +1353,54 @@ controls: Enable or disable lens dewarping. This control is only available if lens dewarp parameters are configured in the tuning file. + - Dw100ScaleMode: + type: int32_t + direction: inout + description: | + Scale mode of the dewarper. + enum: + - name: Dw100ScaleModeFill + value: 0 + description: | + Fills the given output size with the largest rectangle possible. + Aspect ratio is not preserved. Dw100Scale is ignored. + - name: Dw100ScaleModeCrop + value: 1 + description: | + Crops to the given output size. The scale factor can be specified + using Dw100Scale. Aspect ratio is preserved. + + - Dw100Scale: + type: float + direction: inout + description: | + Scale factor applied to the image when Dw100ScaleMode is set to Crop. + This value is clamped, so that all pixels have valid input data. + Therefore a value of 0 always provides the largest possible field of + view. Scaling happens centered around the center of the ScalerCrop + + Dw10Offset. + + - Dw100Rotation: + type: float + direction: inout + description: | + Rotates the image by the given angle in degrees in clockwise direction + around the center of ScalerCrop + Dw100Offset + + - Dw100Offset: + type: Point + direction: inout + description: | + Moves the image by the given values in x and y direction in sensor + coordinate space. This is clamped, so that all output pixels contain + valid data. The offset is therefore ignored when the Dw100Scale value is + too small. + + - Dw100EffectiveScale: + type: float + direction: out + description: | + Effective scale + size: [2] + ... diff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp index 7adad1b502f0..b39e4ab23cd6 100644 --- a/src/libcamera/converter/converter_dw100.cpp +++ b/src/libcamera/converter/converter_dw100.cpp @@ -346,6 +346,13 @@ void ConverterDW100Module::updateControlInfos(const Stream *stream, ControlInfoM if (dewarpParams_.has_value()) controls[&controls::LensDewarpEnable] = ControlInfo(false, true, true); + controls[&controls::Dw100Scale] = ControlInfo(0.2f, 8.0f, 1.0f); + controls[&controls::Dw100Rotation] = ControlInfo(-180.0f, 180.0f, 0.0f); + controls[&controls::Dw100Offset] = + ControlInfo(Point(-10000, -10000), Point(10000, 10000), Point(0, 0)); + controls[&controls::Dw100ScaleMode] = + ControlInfo(controls::Dw100ScaleModeValues, controls::Dw100ScaleModeFill); + if (!converter_.supportsRequests()) LOG(Converter, Warning) << "dw100 kernel driver has no requests support." @@ -369,6 +376,30 @@ void ConverterDW100Module::setControls(const Stream *stream, const ControlList & auto &info = vertexMaps_[stream]; auto &vertexMap = info.map; + const auto &scale = controls.get(controls::Dw100Scale); + if (scale) { + vertexMap.setScale(*scale); + info.update = true; + } + + const auto &rotation = controls.get(controls::Dw100Rotation); + if (rotation) { + vertexMap.setRotation(*rotation); + info.update = true; + } + + const auto &offset = controls.get(controls::Dw100Offset); + if (offset) { + vertexMap.setOffset(*offset); + info.update = true; + } + + const auto &scaleMode = controls.get(controls::Dw100ScaleMode); + if (scaleMode) { + vertexMap.setMode(static_cast(*scaleMode)); + info.update = true; + } + const auto &lensDewarpEnable = controls.get(controls::LensDewarpEnable); if (lensDewarpEnable) { vertexMap.setLensDewarpEnable(*lensDewarpEnable); @@ -402,6 +433,11 @@ void ConverterDW100Module::populateMetadata(const Stream *stream, ControlList &m auto &vertexMap = vertexMaps_[stream].map; + std::array effectiveScale = vertexMap.effectiveScale(); + meta.set(controls::Dw100EffectiveScale, effectiveScale); + meta.set(controls::Dw100Scale, (effectiveScale[0] + effectiveScale[1]) / 2.0); + meta.set(controls::Dw100Rotation, vertexMap.rotation()); + meta.set(controls::Dw100Offset, vertexMap.effectiveOffset()); meta.set(controls::ScalerCrop, vertexMap.effectiveScalerCrop()); if (dewarpParams_.has_value())