From patchwork Fri Oct 16 20:28:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28473 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 1DED7C324C for ; Fri, 16 Oct 2026 20:28:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 951F568E39; Fri, 16 Oct 2026 22:28:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RCsF61GK"; dkim-atps=neutral Received: from mail-vk1-xa32.google.com (mail-vk1-xa32.google.com [IPv6:2607:f8b0:4864:20::a32]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B1ABF689D7 for ; Fri, 16 Oct 2026 22:28:30 +0200 (CEST) Received: by mail-vk1-xa32.google.com with SMTP id 71dfb90a1353d-5e91e422859so146575e0c.2 for ; Fri, 16 Oct 2026 13:28:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182509; x=1792787309; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=O6IMcrMQopRjnTT3QwE0YRk0e8QEhXr3Jk4x+3QRUOk=; b=RCsF61GKyqRvh1sGgCIaPaTg3MDMXUk4tjOqHkW60rmtDc7pT/C4vIoEa0Tt9x/Yz3 7XrXlhah3u/v00zWd0CktzOXZCBvZDpF1bl1wXFHj87wHnQA6cTP3SDwKpeUpu9jc+jq bfQb/tetfUmhoOgu4ep0wI3Vi1Kl6kjaFmBt/fkMoud9uwtBPv7d8qaRKNYmWVShSXKZ jR0McrTUXGoUyC7k1XCVC+8lOQvF0PpsU9153zNkLkWpvH+7HyWKyiTPM8LPncvez6gD w4jU0oD9yLE0vPqLX7brJyAZOWA2mOBLr+W77r8HapMwW8ycdnFhp4mjBelqUQ/xP54P twHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182509; x=1792787309; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=O6IMcrMQopRjnTT3QwE0YRk0e8QEhXr3Jk4x+3QRUOk=; b=eTMvZW4wKy+32fKSZFkVMOhwJaKrTGBK0jelEGsxClVymC/jKJXE+BNDV5dKwv9drf T8/7Hiu7+OQK/W6b6l1ph1vUt7FxsbTxE5g0kWhP6o19mPOScHUr9po90LFsnrHfREuU FHJu9muA+2tm0mLlUBJKUhbKabjZjIfg4j29L3jSZW1K6XJxtlICtLgeE/c2kq3sGezd wCpJOkDnaAKz02N2ZOpmkU++Df+wjUJli3cnAIfr1dpxec+YWImtMeuzvd28NI+mYSv1 GBkyR8YxDKEuRbcilvgNvUYTb1uCJce4SaV29yc4kjTqkysaaDhFxBC3IIJKK8jNHafM aaVw== X-Gm-Message-State: AFq9FYLxUeBx/9vo3/1zWYYKnL8MBQ9SoKz2st7cNmQ/Gx0B0mgVQiUu lAPZZeKSj6Qs6D/TVDBMtlrGlJWDPkj/xjIrRFBGYV5+z5L5m6RZ/Z7NRHAItc3fncw= X-Gm-Gg: AYBFou0dlI4Q38c0jo4pIPFbqVQyjcZ9mu6WzhIiYIkY7/UI699JkiDu2X0r5PYfXgz L6l9g7M70YBXotlV1sTnqxwxDDhmek/JoBNUs33RUX9KnYdpEz9tjo1yfboFSzNwjEPAMQdBuuE QuUs635CXPeCfFZEQcS3TwrNZ72LEdVOAwef/PPNiJYxoftGObmRH5OJD7gYCm9bS4fuxShJ1M0 IAhT4ZXImsd/IVG/QNMe5/vT0WfuZvjbD674I9as1tLhqsuFACARnajnjhMAcJjNzTSpvpVUoJX rchZzSDfrWljJMLm03Q1GM2jS8rlhBPqtrr6Ae/RkV/fOqmIzaqM9J4hrXRXmGFPho4oWQ+ABym +E1OOTwHONSvcKv1uNatP/Zzpe/JDFlelh+JL37ny+lpVB9/anlrCz4zG/8umlKCG2It62L2Z1Q LpciJ2RdVMpXZugxNPoeqNQcSdeSfRFbKeMMaeJNiSZ0iEVf5MlyRJCxLtEqhQOVCCY8TKCCIqs sL1ilNWBxPLDG1KZDtHrOkR93uD X-Received: by 2002:a05:6123:4205:10b0:5d4:1193:73d3 with SMTP id 71dfb90a1353d-5eaaa64171fmr428322e0c.14.1792182509476; Fri, 16 Oct 2026 13:28:29 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:28 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 01/11] software-isp: Center the GPU image crop Date: Fri, 16 Oct 2026 16:28:08 -0400 Message-ID: <20261016202818.1405645-2-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode The GPU debayer path scales the image to fill a requested output size and crops any excess image area. Its projection positions the scaled image against one side of the output, so aspect-ratio changes and Bayer border removal shift the visible scene. The series aligns rendering and metering with a centered sensor crop. This commit centers the projection on the output region in sensor coordinates, distributing the crop across both sides. Signed-off-by: Ray Strode --- .../internal/software_isp/debayer_geometry.h | 43 +++++++++++++++++++ .../internal/software_isp/meson.build | 1 + src/libcamera/software_isp/debayer_egl.cpp | 21 +++------ 3 files changed, 49 insertions(+), 16 deletions(-) create mode 100644 include/libcamera/internal/software_isp/debayer_geometry.h diff --git a/include/libcamera/internal/software_isp/debayer_geometry.h b/include/libcamera/internal/software_isp/debayer_geometry.h new file mode 100644 index 00000000..70ae6a8b --- /dev/null +++ b/include/libcamera/internal/software_isp/debayer_geometry.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Red Hat Inc. + * + * Geometry for scaling and cropping debayered images + */ + +#pragma once + +#include +#include + +#include + +namespace libcamera { + +/* + * Return a column-major projection matrix for an input-sized viewport and an + * output-sized framebuffer. Scale to fill the output, centering the crop on + * the input. All sizes must be nonzero, with nativeSize contained in inputSize. + */ +inline std::array debayerProjection(const Size &inputSize, + const Size &nativeSize, + const Size &outputSize) +{ + float scale = std::max(static_cast(outputSize.width) / nativeSize.width, + static_cast(outputSize.height) / nativeSize.height); + + /* The framebuffer center is output/viewport - 1 in normalized coordinates. */ + float transX = static_cast(outputSize.width) / inputSize.width - 1.0f; + float transY = static_cast(outputSize.height) / inputSize.height - 1.0f; + + /* clang-format off */ + return { + scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, 1, 0, + transX, transY, 0, 1, + }; + /* clang-format on */ +} + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build index df7c3b97..e18597ed 100644 --- a/include/libcamera/internal/software_isp/meson.build +++ b/include/libcamera/internal/software_isp/meson.build @@ -2,6 +2,7 @@ libcamera_internal_headers += files([ 'benchmark.h', + 'debayer_geometry.h', 'debayer_params.h', 'software_isp.h', 'swisp_stats.h', diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 300822f9..1a7ad25c 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -9,7 +9,7 @@ #include "debayer_egl.h" -#include +#include #include #include #include @@ -24,6 +24,7 @@ #include "libcamera/internal/formats.h" #include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/software_isp/debayer_geometry.h" #include "../shaders/glsl_shaders.h" @@ -388,20 +389,8 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara GLfloat Step[] = { static_cast(bytesPerPixel_) / (inputConfig_.stride - 1), 1.0f / (height_ - 1) }; GLfloat Stride = (GLfloat)width_ / (shaderStridePixels_ / bytesPerPixel_); - /* - * Scale the output size from the native size the algorithm produces for - * the input size. Keep the aspect ratio and prefer cropping over black - * bars. - */ - GLfloat scale = std::max((GLfloat)outputSize_.width / nativeOutputSize_.width, - (GLfloat)outputSize_.height / nativeOutputSize_.height); - GLfloat trans = -(1.0f - scale); - GLfloat projMatrix[] = { - scale, 0, 0, 0, - 0, scale, 0, 0, - 0, 0, 1, 0, - trans, trans, 0, 1 - }; + const std::array projMatrix = + debayerProjection({ width_, height_ }, nativeOutputSize_, outputSize_); /* Static const coordinates */ static const GLfloat vcoordinates[4][2] = { { -1.0f, -1.0f }, @@ -445,7 +434,7 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara glUniform2fv(textureUniformSize_, 1, imgSize); glUniform2fv(textureUniformStep_, 1, Step); glUniform1f(textureUniformStrideFactor_, Stride); - glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix); + glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix.data()); LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ From patchwork Fri Oct 16 20:28:09 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28474 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 103E6C3305 for ; Fri, 16 Oct 2026 20:28:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2A85668E3B; Fri, 16 Oct 2026 22:28:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HGYsFgaf"; dkim-atps=neutral Received: from mail-vk1-xa35.google.com (mail-vk1-xa35.google.com [IPv6:2607:f8b0:4864:20::a35]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A47AD68E37 for ; Fri, 16 Oct 2026 22:28:31 +0200 (CEST) Received: by mail-vk1-xa35.google.com with SMTP id 71dfb90a1353d-5ea969fafeeso141510e0c.0 for ; Fri, 16 Oct 2026 13:28:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182510; x=1792787310; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BFkFlnHOd5d01Z6C9QKgQSdXmevfTQGxyuVigzB3iag=; b=HGYsFgafiJg50Vy7OfKwEWMRo0na4606BLia5+vGkeL1BXrs5HfhKOUgnnM7nJRj9t +yx0w8/6zU47RRM6B2QWlsdZDJQk2shsG83jWWvRcaFf4GeDgv7CgZxOjwSKaFfPhI3C +0o2oXPnL+PTCrWfdqoX+VAKaSJ2DQbA4wdgilHsMHDZgUhgcdAABmcqvf72j4gpQLO2 JPheWmnmDLfdt+nnLOLz+ysJuQ22oWS5rj1noGUM9BahsUTJbwjFuM/0Mi6b6MKaKbEX lKpQrgHEX8YjxqOI26FqACWle/aVN38dR6MvocBy38AAa8UAy+yIgHCflYUQh0G2IcJE ZEuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182510; x=1792787310; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BFkFlnHOd5d01Z6C9QKgQSdXmevfTQGxyuVigzB3iag=; b=VVdljqo4AljAxiWNX94Xhkw4VHEoDfNdvlbxHhpHqY5kacOo/VwKPbanlvXLIGVeCv Mt7kjrNmAxMYEjouBgqE1tXmm5gUMu+5JajQNNT7fdIjcKgL6mMYW316koX6ZimJcwmA +Nxj+3YU/S75IzCr3pZYXQjbemQGk7NaiT/6vr9XfB4KzgxKStDPFeHGTX8/1Ig413Kz 0IuE77eJ2CQ57r3RGGxz2xfZElB6FPl028rVSCrq1rvzJVQuY57OO4qssWgZ7tKEx4EA 9GvLUKhErXdHFUWbxYMmIRI+WJtiq1M9HNf5IyKSvzIqMHBJNJoZ7WR4lCqQ6YrMVOjO Jx8Q== X-Gm-Message-State: AFq9FYI1Q6e6PgnCN+uTLsS+iqP+Fb6nsPv2vajofOf3Fm94exvIbOnN yAoerWoavn5WlZrgPYZGd7Yw2FlhwN3weD5dTFkcddOCMowyFLnET+sr/WLVa8IZx9A= X-Gm-Gg: AYBFou2TOokskfz+Z3vOnEVuV6bvQAy8zElCgsj3wdeBYpqqH//Sl360b6Uc6aIshHi roHLd5jRXJiJTvL+fUwFMGYi4sLL3qgYDl9MlUAuJRJQ/r19+pJ0iuWqYUcNk4ftsZPbkG1kk5y 4mX7T6LcBV4pkhakX5MIyGxbo7uZDNODYlRt5vdSJkzjcha7/td1UTDMyYJkSuOR6qUsSEbOK6a Egl5PIHSEg9NC8FnKWxA9ziW9tjCQ866eHTFI3ln4yR2qJa2PaDNAl8E+z1Nbwv/x02veefwr0l cHsOEqSgmiAw8PC1NdifdFIeny9NqbQz4iqtT0zUJwjaqtlbFzs5ABxLpKvxL8YVmBYoDmnAP72 +/4gd/OJnh221MZiNnvN+x8le20VfkiCrj+zU/WpB1Fs+/Tn6QOIQ1TiccIZe7IeeBHgZszjNis NQ0VtuV2OL02mvArvXQFpNQaqy5ZrnIhJMklKfi45gpEVHeamKZeBa+tSftFGjtg37wZyuvmxm8 ei/RDbttxJHcCWk3+MFh65299KQ X-Received: by 2002:a05:6122:4b0a:b0:5c9:a60b:e5d8 with SMTP id 71dfb90a1353d-5eaaa678174mr541198e0c.18.1792182510482; Fri, 16 Oct 2026 13:28:30 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:29 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 02/11] tests: Validate debayer projection geometry Date: Fri, 16 Oct 2026 16:28:09 -0400 Message-ID: <20261016202818.1405645-3-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode The GPU debayer path uses a geometry helper to center the sensor image when output dimensions or aspect ratios change. The project lacks a direct regression check for the projection. An incorrect translation can shift the visible scene, including when the output only removes the Bayer border. This commit adds a unit test that projects the expected sensor crop corners and sensor center into output coordinates. Cases cover border removal, downscaling, and horizontal and vertical cropping. Signed-off-by: Ray Strode --- test/debayer-geometry.cpp | 96 +++++++++++++++++++++++++++++++++++++++ test/meson.build | 1 + 2 files changed, 97 insertions(+) create mode 100644 test/debayer-geometry.cpp diff --git a/test/debayer-geometry.cpp b/test/debayer-geometry.cpp new file mode 100644 index 00000000..27458aa1 --- /dev/null +++ b/test/debayer-geometry.cpp @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2026, Red Hat Inc. + * + * Debayer projection tests + */ + +#include +#include +#include +#include + +#include + +#include "libcamera/internal/software_isp/debayer_geometry.h" + +#include "test.h" + +using namespace libcamera; + +class DebayerGeometryTest : public Test +{ +protected: + int run() override + { + if (testProjection()) + return TestFail; + + return TestPass; + } + +private: + int testProjection() + { + static const struct { + Size input; + Size native; + Size output; + Rectangle visible; + } cases[] = { + /* No border or scaling. */ + { { 1920, 1080 }, { 1920, 1080 }, { 1920, 1080 }, { 0, 0, 1920, 1080 } }, + /* Native output splits the Bayer border between both sides. */ + { { 1924, 1080 }, { 1920, 1080 }, { 1920, 1080 }, { 2, 0, 1920, 1080 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 1920, 1092 }, { 4, 0, 1920, 1092 } }, + /* Vertical cropping, with and without downscaling. */ + { { 1928, 1092 }, { 1920, 1092 }, { 1920, 1080 }, { 4, 6, 1920, 1080 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 1280, 720 }, { 4, 6, 1920, 1080 } }, + /* Horizontal cropping for 4:3 and portrait outputs. */ + { { 1928, 1092 }, { 1920, 1092 }, { 640, 480 }, { 236, 0, 1456, 1092 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 512, 768 }, { 600, 0, 728, 1092 } }, + /* A wider output removes more rows from each side. */ + { { 1928, 1092 }, { 1920, 1092 }, { 1280, 640 }, { 4, 66, 1920, 960 } }, + }; + + for (const auto &entry : cases) { + const std::array matrix = + debayerProjection(entry.input, entry.native, entry.output); + int left = entry.visible.x; + int top = entry.visible.y; + int right = left + entry.visible.width; + int bottom = top + entry.visible.height; + const std::pair points[] = { + { { left, top }, { 0, 0 } }, + { { right, top }, { static_cast(entry.output.width), 0 } }, + { { left, bottom }, { 0, static_cast(entry.output.height) } }, + { { right, bottom }, { static_cast(entry.output.width), static_cast(entry.output.height) } }, + { Rectangle(entry.input).center(), Rectangle(entry.output).center() }, + }; + + for (const auto &[sensor, expected] : points) { + double x = 2.0 * sensor.x / entry.input.width - 1.0; + double y = 2.0 * sensor.y / entry.input.height - 1.0; + double w = matrix[3] * x + matrix[7] * y + matrix[15]; + double clipX = (matrix[0] * x + matrix[4] * y + matrix[12]) / w; + double clipY = (matrix[1] * x + matrix[5] * y + matrix[13]) / w; + /* The viewport has the input dimensions, even for smaller outputs. */ + double outputX = (clipX + 1.0) * entry.input.width / 2.0; + double outputY = (clipY + 1.0) * entry.input.height / 2.0; + + if (!std::isfinite(outputX) || !std::isfinite(outputY) || + std::abs(outputX - expected.x) > 0.001 || + std::abs(outputY - expected.y) > 0.001) { + std::cerr << "Projection " << entry.input << " -> " << entry.output + << " maps " << sensor << " to (" << outputX << ", " << outputY + << "), expected " << expected << std::endl; + return TestFail; + } + } + } + + return TestPass; + } +}; + +TEST_REGISTER(DebayerGeometryTest) diff --git a/test/meson.build b/test/meson.build index 363a2829..5027b7b1 100644 --- a/test/meson.build +++ b/test/meson.build @@ -52,6 +52,7 @@ internal_tests = [ {'name': 'bayer-format', 'sources': ['bayer-format.cpp']}, {'name': 'byte-stream-buffer', 'sources': ['byte-stream-buffer.cpp']}, {'name': 'camera-sensor', 'sources': ['camera-sensor.cpp']}, + {'name': 'debayer-geometry', 'sources': ['debayer-geometry.cpp']}, {'name': 'delayed_controls', 'sources': ['delayed_controls.cpp']}, {'name': 'event', 'sources': ['event.cpp']}, {'name': 'event-dispatcher', 'sources': ['event-dispatcher.cpp']}, From patchwork Fri Oct 16 20:28:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28475 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 3930BC324C for ; Fri, 16 Oct 2026 20:28:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 01AC168E42; Fri, 16 Oct 2026 22:28:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Amy0+IR1"; dkim-atps=neutral Received: from mail-vk1-xa2c.google.com (mail-vk1-xa2c.google.com [IPv6:2607:f8b0:4864:20::a2c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9E74E68E44 for ; Fri, 16 Oct 2026 22:28:32 +0200 (CEST) Received: by mail-vk1-xa2c.google.com with SMTP id 71dfb90a1353d-5e9528732b4so242025e0c.0 for ; Fri, 16 Oct 2026 13:28:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182511; x=1792787311; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ESp1FMYlRGar1R88XIXlQKmy4hkriyl4lEm0aN2dmdk=; b=Amy0+IR16gZYwfdYcAntuhgiQ5hlAK7HCKP0kC1rB+qsQN8xHA+1GYPnK3z7dAHt1X DII/t7irRTvlKYkAsIna0TfR6ut10Q3dab+HEg7RDLV0YK4bsvlsJhdWz4qvGibKR5l5 KQbZb74IIYCpnzuPJgP5VE40R8awQa0cPW1u/aCdsQLdgpw0c8Iz5KH0IUVXCU20NzVo zndfitjag3mbeoEYmxX6iSdAKDDHV+VvN+lKce8lb82Z5kVuQJQ04TqUJ6ApQz60K7SV /mWEitQypjEzji7NI9Y11Ucya6liFHcKV1UDH/xCwQd4dWmDSIZTSQNc8l9UgUhpm0mV 0qJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182511; x=1792787311; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=ESp1FMYlRGar1R88XIXlQKmy4hkriyl4lEm0aN2dmdk=; b=LnBse+fcbVa4R8IGZ7b/lAUqkarldYyaIxy9XvjgjMMyH3ermGoM2doWFNs8hXAiIT wscts+k+UNMfeLzIVZRrfPZoCybT2GKpX+QotEv9auyFZBDJ3ZG1mqeMcRIHcL2FPRKT CXdWSlHFTntC6s5qoXmt0jUYC1G6/zDi7Bxi2Kg8nWnbAco1hyWcPx12Rml0Om6IHqfk d/WNGAo0PGOuP638Po5wCxX5Z3GYGHmYHkXOtaDL2Oyo5p1+P/4xuFV8cSOXex72s0Ho 7wo6xwAUsUX74dHfIgRfjg3L/MWzkux5F7YxXX1nFKNWzUcux7H87h3SXyV14po8rpwJ gO/w== X-Gm-Message-State: AFq9FYKKeCzeADj6/KOXmvtFB5sFJVMDAwL5TZmQ7lyqYTLQnBkEud2t za7Zcvi/RPE+64kG07JGf975uPF6Ja9wNM9MSd3aoxcKm+jboLWS+Wb3X9mtTjW4wWU= X-Gm-Gg: AYBFou2UBIGv0ucIjV8b8sjI9ENrwFaF+h/92twKVrH12SV7HW6u2SsYFtXH/h+UqVh dfgtAWZenFNM6iZOvk/y+GzO0Nf1WGq0wOs+jFzacc7UYr5E4IJkeNrcGNDKIZPI9V3NcUUKcGy 7M2nPHtCUSgNgm9wUceVUt1SmbAa3B6zDrggVl9kVFL+3lPfn09bQmaZDBUXq+uPEXIzrdVpDC9 Z0meejw3434lAAixRPz+hrLKmNe43h6P2d/n/j0gxdvLWNhZ7mw5a/5AwelWRznvyHJayUZhXKR ucZ23kyFCvSKsO6KE0Eh+jWRLxlcn+2h3ch0eGZBpatcQm0BiVsINq2IqPwK1/33atnV2i8nabI SShEcXWtNhgwY59gvz5JCEfqlTu+cbFt3vhC3G+D0B+ICOfpPqb0FetJweYdIFIpAROS89foO1I vUYWoKQxgO6Qr7Z8BvBZz0o4OZk25NSXjj/zSa3HV7Qw5MCfIWD1S4RVfUuiS0NtYZge/Aycol8 Ztn0oluTw/hfqMhqHFndVW1S3bP X-Received: by 2002:a05:6122:4886:b0:5ea:a1ad:637d with SMTP id 71dfb90a1353d-5eaaa0f91f6mr728108e0c.1.1792182511528; Fri, 16 Oct 2026 13:28:31 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:30 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 03/11] software-isp: Align statistics with the visible sensor crop Date: Fri, 16 Oct 2026 16:28:10 -0400 Message-ID: <20261016202818.1405645-4-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit changes statistics gathering to follow the sensor area visible in the GPU output. The GPU debayer path fills the requested output with a centered crop of the sensor image. CPU statistics read the original sensor buffer, but their window uses the output dimensions and starts at the buffer's origin. A centered origin is calculated but never passed to the statistics engine. Metering therefore covers a different sensor region when the image is cropped or scaled. The window is now derived in sensor coordinates, accounting for Bayer border removal and cropping to the output aspect ratio, and centered in the sensor buffer. Changing resolution without changing aspect ratio leaves the rectangle unchanged. The statistics engine retains its existing Bayer alignment. Signed-off-by: Ray Strode --- .../internal/software_isp/debayer_geometry.h | 8 ++++++++ src/libcamera/software_isp/debayer_egl.cpp | 13 +++---------- src/libcamera/software_isp/debayer_egl.h | 1 - 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/libcamera/internal/software_isp/debayer_geometry.h b/include/libcamera/internal/software_isp/debayer_geometry.h index 70ae6a8b..46721753 100644 --- a/include/libcamera/internal/software_isp/debayer_geometry.h +++ b/include/libcamera/internal/software_isp/debayer_geometry.h @@ -40,4 +40,12 @@ inline std::array debayerProjection(const Size &inputSize, /* clang-format on */ } +/* Return the visible sensor rectangle, before statistics Bayer alignment. */ +inline Rectangle debayerCrop(const Size &inputSize, const Size &nativeSize, + const Size &outputSize) +{ + const Size visibleSize = nativeSize.boundedToAspectRatio(outputSize); + return visibleSize.centeredTo(Rectangle(inputSize).center()); +} + } /* namespace libcamera */ diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 1a7ad25c..9f3dc752 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -323,18 +323,11 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, outputSize_ = outputCfg.size; nativeOutputSize_ = outSizeRange.max; - window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & - ~(inputConfig_.patternSize.width - 1); - window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & - ~(inputConfig_.patternSize.height - 1); - window_.width = outputCfg.size.width; - window_.height = outputCfg.size.height; - /* - * Don't pass x,y from window_ since process() already adjusts for it. - * But crop the window to 2/3 of its width and height for speedup. + * The GPU scales the visible sensor crop to outputSize_. Statistics + * consume the original input buffer, so use sensor coordinates here. */ - stats_->setWindow(Rectangle(window_.size())); + stats_->setWindow(debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_)); inputBufferCount_ = inputCfg.bufferCount; outputBufferCount_ = outputCfg.bufferCount; diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 30e51a47..52b8aa07 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -111,7 +111,6 @@ private: GLint contrastExpUniformDataIn_; Size nativeOutputSize_; - Rectangle window_; std::unique_ptr stats_; eGL egl_; uint32_t width_; From patchwork Fri Oct 16 20:28:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28476 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 5A1E4C3305 for ; Fri, 16 Oct 2026 20:28:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A96B968E55; Fri, 16 Oct 2026 22:28:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="pgoPypZj"; dkim-atps=neutral Received: from mail-vk1-xa35.google.com (mail-vk1-xa35.google.com [IPv6:2607:f8b0:4864:20::a35]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E544E68E40 for ; Fri, 16 Oct 2026 22:28:33 +0200 (CEST) Received: by mail-vk1-xa35.google.com with SMTP id 71dfb90a1353d-5ea63f01606so181532e0c.1 for ; Fri, 16 Oct 2026 13:28:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182513; x=1792787313; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=02JAMWKdRQ16U0IDieCwBskgchSrhlfOdgVL8lNlzgI=; b=pgoPypZjcqXBzFtXH3ON41WN63ULwRrxW/rrcFGeL7ooPfZczrgasbz/xyjmGGNajX Finn/Aku7mLfHv1nlEgpph3OGnBD5lwiikAfIpYRTmu0V+6ZUi9gym7pL0/KELeSJBK8 r9Kt5msEI9pNaCl0tQKJcapqqN4HU6hOzpPu6T4rtM49KU7WyDuf7lyNRsgO47jCCv8W jzvUtAReb497Te7gJ2bsAmWaH+RNdnw8fCRjn5/SGpAknfUJfFUR7H++yM8+86m7oo4o 2SQvyA4R6inSmGkJHIxahWHgMKRErDEgBvitMf23K/KitI/jMQGPJgMaKpqP5N/n0ALX PVkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182513; x=1792787313; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=02JAMWKdRQ16U0IDieCwBskgchSrhlfOdgVL8lNlzgI=; b=m8gdpm6HGLuFLHjg1CiRMuTHHEjfJJ8L0PerSPgH6qHB4ze1vAil1JVoFt+h2Apm6n /n8SykR6IaQsOaRQqbqoSE/+Rz6SMi/eZ7laEng9jEnjjPj+ElM/BRFpEIMrcUbxr6v4 NhztC7MC4cLQRhZYUFZlh3aMd7e1PgA4ZizpraTJ1l/aYVkGIYoEW3bnWEX/LepX+l0h qUthCNgpDUtoQ4xe9i9uQGjYevED0/TVFz84UlnwMFWDOXsycHLVyCAjSSm1DAOSBRo+ 2oz3seET2QwV0mgKWs4GLLXaUEHB3KxY+JWF+9P8fz17qYNy3CzPmUsCcSMje3qjFcak Iogg== X-Gm-Message-State: AFq9FYLMRR338EmlofAnlmjp2Lnjw4pKsMNBwA5IhOpBVgHsOmd6drmf SUogZbkWZEzBvr0MxyOLkNpL3mU3azM3x9coImTmJiJ3wYvDwyLF2PtvNKQhZKEjUOU= X-Gm-Gg: AYBFou0Xx6Ln23KAAEJdB3rUZcEvzHLJxPXUEV2WvGBtEJ1B4VcgWiIM5Cj/ENkQdPP obFF8A3FyxW6FVmI/kYhUDSlMXTwdUHLwsCtAoLp/j/MqWGmL6Gx810LmPLvyexZyllZta+gk71 8CGl9Q6/l3rfAHLwNRnFG+Z9G4AnuR6F0Qnpfsyy5xSYYDCeETECkUSiOL5EGi9Kbonduz1Qt3F xxpURA0ezJEOwEtq34nR6rd2G+phS+JpoTKirbnYsfuYt+WQyDhxxge3NL0seyeWdreRl41NSRt iwH9FVg5zc4bMjDWaCsquV5IJ5GG+z/Fm/nxaL0qAYCZDcQfiC0vcshRkHgJPuxcupZYBF4JWzd hTn1iAwhN9yPDQt62aa17I6q+31bsOgiXYEhEboUc3d3vwHnBARazNtx4U4AAtbG47pRKB3Jn/p tFVucJiPXxVYoPWmsUUvyBxLMe0wdzmyW/DF32HXFMis120FP3ahDDyIYlxUvIMG1nmVBUMb0/1 DHd7CIBLvmYmkCdnLc0pWq6sdE4 X-Received: by 2002:a05:6122:3383:b0:5e4:f6c8:b0a5 with SMTP id 71dfb90a1353d-5eaa9eb7173mr541171e0c.0.1792182512734; Fri, 16 Oct 2026 13:28:32 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:31 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 04/11] tests: Validate the visible sensor crop Date: Fri, 16 Oct 2026 16:28:11 -0400 Message-ID: <20261016202818.1405645-5-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode The GPU debayer path selects its statistics window from the visible sensor crop. The geometry unit test checks the projection used for rendering. The project lacks a direct check that the sensor crop remains centered and follows the output aspect ratio without shrinking to the output resolution. This commit extends the geometry unit test with expected sensor rectangles for native, downscaled, wider, narrower, and portrait outputs. It also checks integer rounding that leaves an odd top coordinate before Bayer alignment. Signed-off-by: Ray Strode --- test/debayer-geometry.cpp | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/test/debayer-geometry.cpp b/test/debayer-geometry.cpp index 27458aa1..86d4248f 100644 --- a/test/debayer-geometry.cpp +++ b/test/debayer-geometry.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2026, Red Hat Inc. * - * Debayer projection tests + * Debayer projection and sensor crop tests */ #include @@ -23,7 +23,7 @@ class DebayerGeometryTest : public Test protected: int run() override { - if (testProjection()) + if (testProjection() || testCrop()) return TestFail; return TestPass; @@ -91,6 +91,38 @@ private: return TestPass; } + + int testCrop() + { + static const struct { + Size input; + Size native; + Size output; + Rectangle expected; + } cases[] = { + { { 1920, 1080 }, { 1920, 1080 }, { 1920, 1080 }, { 0, 0, 1920, 1080 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 1920, 1092 }, { 4, 0, 1920, 1092 } }, + /* Output resolution changes must not shrink the sensor window. */ + { { 1928, 1092 }, { 1920, 1092 }, { 1920, 1080 }, { 4, 6, 1920, 1080 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 1280, 720 }, { 4, 6, 1920, 1080 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 640, 480 }, { 236, 0, 1456, 1092 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 512, 768 }, { 600, 0, 728, 1092 } }, + { { 1928, 1092 }, { 1920, 1092 }, { 1280, 640 }, { 4, 66, 1920, 960 } }, + /* A smaller Bayer border leaves an odd top coordinate. */ + { { 1928, 1092 }, { 1924, 1092 }, { 1280, 720 }, { 2, 5, 1924, 1082 } }, + }; + + for (const auto &entry : cases) { + Rectangle crop = debayerCrop(entry.input, entry.native, entry.output); + if (crop != entry.expected) { + std::cerr << "Crop " << entry.input << " -> " << entry.output + << " is " << crop << ", expected " << entry.expected << std::endl; + return TestFail; + } + } + + return TestPass; + } }; TEST_REGISTER(DebayerGeometryTest) From patchwork Fri Oct 16 20:28:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28477 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 7903BC324C for ; Fri, 16 Oct 2026 20:28:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8AEF868E5A; Fri, 16 Oct 2026 22:28:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="i6caZUD0"; dkim-atps=neutral Received: from mail-vk1-xa2f.google.com (mail-vk1-xa2f.google.com [IPv6:2607:f8b0:4864:20::a2f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D072768E4F for ; Fri, 16 Oct 2026 22:28:34 +0200 (CEST) Received: by mail-vk1-xa2f.google.com with SMTP id 71dfb90a1353d-5e6b5794d26so407504e0c.1 for ; Fri, 16 Oct 2026 13:28:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182514; x=1792787314; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=fg6Wz5w0q7kuOpsuRFpHbNzx99wbLonQMAQ8qZfNWf8=; b=i6caZUD08+u0MiN5IZsP/A75DKSl3EOreSFozXllQYDWTQ90nrobf5NWtt8SrrPyy3 ZtTydsym5yxeTu2xphTSPkhOnpJIF53kSkjfbqhC+XpcqGELsGxyIeEw2yx3rpEwesQa DPbFbW1Fr9ihG1I7PHYTPgsen05j1W3mCMsCUEAfn+2bz+BxrB6uvWHUcL73Auy3BxvG tlSv1nVgzKnDK+Cx0VVJwu9S6ndy+spN7KJ2p9jbVL/sWP3Dd2nPn9ZXcAAj6xAUOzsk CGeITJrPjHonkfYkt1FkeTJnR4Rqhu24V3SOgxt7e78LYBAszlb2BQetpDw+FJyg13MF LuXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182514; x=1792787314; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=fg6Wz5w0q7kuOpsuRFpHbNzx99wbLonQMAQ8qZfNWf8=; b=yqBT3Q6obii1IeLbZyXCIliINwwznO07AqwnaHnp/Tq+MUUbm3NgD4rC6UKW2CZPYE zlffwJFWZRiQqGT7F3IRMsK4IzXV2F6ChfPwlKWb4laGFMdEoFwwolOVwl/iusfs+XLy RM7DHFgWmsrVQvK3nJQs2ksWEiXkStYfJDey+LDwfatBkqTiO7pZAIPDWqmfQRTGfYMy Kmrj5CCjZDWX2SQMJYP6n2c/aqDdeOjCxt7W3L4R7LHkcXVjSP5ePULeHkGrDGP2mrfo bUP3DswVDmTR+XYVT09WFHPoBX0VmGKzkJA37117Ozdf8N62Tjx8mGr8umRdOh3BT9+1 zSqw== X-Gm-Message-State: AFq9FYIWqzO38rpjrs6VNfFZrhbsoRT37pb1+4W0siXA3hb5tMQ2meWB BfqK3A313ehvXxZypCkaSmFSX/6PN+V3m51tjN1W4KGPomg3MP/M7o+eE1+1QyHLPOk= X-Gm-Gg: AYBFou1WNVgGlUVo9dC3uSkS+VgfFtQC5YzCQJ8Zvc2mqS17XWIN0Tf/v1CwdQWSpnM Zbvf6XYeoRpppPnlgNuB7McIuRzGAZ9FT/F9+oPDdKEn2kn0yeDTvRtV9bgRIsu6mSiabJacETt iBKWsHXnMigZYLyDDrNxyxscg1NKpsfMNGP0oT7rlQK3+4VNDO2NZv2ySUPAJOrZVd3EYDjK5xk eR0c63kViuG86DRAqdy+IKGmDVoo7dg+GHfV1/+YhnnZ5oLX849KGjJiFMIwNiJ23Tz65QGgQ23 uRrgmdW+iSWyF5/OKDH7cWjFJJAQNpd9mYnxSV4B6OoYGgJOS8+6IVWRkTgFD857aqGFpOeHf6l yvBr8Mj0KAJruJ/KL2AV5cAXuPMwB1U0rj1I+zsqLiLwywc+IrOwoLgUaEyUCS4bwGjFwSpQgcG JqWa6Xsz4R5D+wF5LTWVqfyr39IzKRUQBCD7ayJypzVPpXRbdrUQ3e+d/+R5MfD3RG1pEi+KxCF CPH3dN7kdwtR0XyYsiCHeCGpBb8geKd54BXhm4= X-Received: by 2002:a05:6122:d2a:b0:5e2:b1d5:2d6f with SMTP id 71dfb90a1353d-5ea980ce974mr1400061e0c.20.1792182513686; Fri, 16 Oct 2026 13:28:33 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:33 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 05/11] software-isp: Expose the configured image crop Date: Fri, 16 Oct 2026 16:28:12 -0400 Message-ID: <20261016202818.1405645-6-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit makes the image region selected by the debayer available to the pipeline handler, so ScalerCrop metadata can describe the processed output. The CPU and EGL backends crop input differently. CPU debayering keeps an output-sized window whose origin depends on the Bayer pattern and output channel order, while EGL scales a centered crop to fill the output. The pipeline currently cannot retrieve the region chosen by either backend. Each backend returns its actual configured image crop in input-buffer coordinates. The EGL crop is retained before statistics alignment, so the returned rectangle describes the image rather than its metering samples. Signed-off-by: Ray Strode --- .../libcamera/internal/software_isp/software_isp.h | 1 + src/libcamera/software_isp/debayer.cpp | 11 +++++++++++ src/libcamera/software_isp/debayer.h | 1 + src/libcamera/software_isp/debayer_cpu.h | 4 ++++ src/libcamera/software_isp/debayer_egl.cpp | 3 ++- src/libcamera/software_isp/debayer_egl.h | 2 ++ src/libcamera/software_isp/software_isp.cpp | 14 ++++++++++++++ 7 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index b8b24bb1..1e54a4fe 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -67,6 +67,7 @@ public: const std::vector> &outputCfgs, const ipa::softisp::IPAConfigInfo &configInfo, ControlInfoMap *ipaControls); + Rectangle inputCrop() const; int exportBuffers(const Stream *stream, unsigned int count, std::vector> *buffers); diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index a4854e51..14b09937 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -66,6 +66,17 @@ Debayer::~Debayer() } /** + * \fn Rectangle Debayer::inputCrop() const + * \brief Retrieve the input region visible in the configured output + * + * The rectangle is in input-buffer coordinates and excludes any additional + * alignment performed for statistics sampling. It is valid after a successful + * configure() call. + * + * \return The configured image crop + */ + +/** * \fn int Debayer::configure() * \brief Configure the debayer object according to the passed in parameters * \param[in] inputCfg The input configuration diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index 55685226..7ffdaea1 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -53,6 +53,7 @@ public: virtual void stop() {} virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0; + virtual Rectangle inputCrop() const = 0; virtual const SharedFD &getStatsFD() = 0; diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 2c88c9e1..1e037a79 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -46,6 +46,10 @@ public: int start() override; void stop() override; SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override; + Rectangle inputCrop() const override + { + return window_.translatedBy({ static_cast(xShift_), 0 }); + } const SharedFD &getStatsFD() override { return stats_->getStatsFD(); } private: diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 9f3dc752..cd9ad888 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -327,7 +327,8 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, * The GPU scales the visible sensor crop to outputSize_. Statistics * consume the original input buffer, so use sensor coordinates here. */ - stats_->setWindow(debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_)); + inputCrop_ = debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_); + stats_->setWindow(inputCrop_); inputBufferCount_ = inputCfg.bufferCount; outputBufferCount_ = outputCfg.bufferCount; diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 52b8aa07..5a4cd2d8 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -60,6 +60,7 @@ public: const SharedFD &getStatsFD() override { return stats_->getStatsFD(); } SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override; + Rectangle inputCrop() const override { return inputCrop_; } private: static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); @@ -111,6 +112,7 @@ private: GLint contrastExpUniformDataIn_; Size nativeOutputSize_; + Rectangle inputCrop_; std::unique_ptr stats_; eGL egl_; uint32_t width_; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index a4097605..c0c55fbf 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -306,6 +306,20 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, } /** + * \brief Retrieve the input region used to produce the configured output + * + * The rectangle is expressed in input-buffer pixels, before any Bayer + * alignment applied by the statistics engine. It is valid after configure() + * succeeds and describes the selected CPU or EGL debayer backend. + * + * \return The configured input crop + */ +Rectangle SoftwareIsp::inputCrop() const +{ + return debayer_->inputCrop(); +} + +/** * \brief Export the buffers from the Software ISP * \param[in] stream Output stream exporting the buffers * \param[in] count Number of buffers to allocate From patchwork Fri Oct 16 20:28:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28478 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 402A4C3305 for ; Fri, 16 Oct 2026 20:28:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B152F68E51; Fri, 16 Oct 2026 22:28:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="iLfw5Lzq"; dkim-atps=neutral Received: from mail-vk1-xa35.google.com (mail-vk1-xa35.google.com [IPv6:2607:f8b0:4864:20::a35]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2A4EF68E37 for ; Fri, 16 Oct 2026 22:28:36 +0200 (CEST) Received: by mail-vk1-xa35.google.com with SMTP id 71dfb90a1353d-5eaaa9b1591so190517e0c.3 for ; Fri, 16 Oct 2026 13:28:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182515; x=1792787315; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=MOPWXvnjHEaRoUjCDQjpT4jlwb+rRUMODm1OtxXGYL4=; b=iLfw5LzqaTN7b4UniSDYXyYEcQowsGI1X1odKS0u+YPDsN4ScmDnhUjUwRVC89Iu+Y ONN8WufLu/4k9f4Hp1PovX0ZEp0WRzzYqYQoo4LhiNvtyOZcavr6n2LI9CuwEPgPCne/ F6b4uVghs0FsLDDM5QZGrwhdFA5Ui0WtDiWYMb4WtnWswJysp5ePJwi7y52Tq88NlRIS Y2AgBeU31I5hkYG7rC0Vx2f1MKu9LyRo1dARJPJ+/Zw43tEmhlLstKTn1eCgPWu/isjo zOxoKWS0Llhuham4owHkXnarEXpgckxdWEXPc2lEf+2n4Eyk7YheV8MGLe/wxAzHmYVS KzHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182515; x=1792787315; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=MOPWXvnjHEaRoUjCDQjpT4jlwb+rRUMODm1OtxXGYL4=; b=Tm5VcP5uAuy62e31+2a4QH1Bv3gtQdgVNMODUwec+FUbCO5IySnJ5nVwVtEDx4VQso 2fcpI+H9hlFP3WEOI+P7KP1DTiNWCoaTbY2WLyzoiBLi+fWzjx2kzSL6l8Fn45/ZYGY+ dWwC8+IDAEP3N5gtFRGu43MFp7Pl9SFs3fAFGSW199SrUmgPBCGJkRiiHsMuY/CU1/OS GxzIKRKlE05ofYa6jw4rVVyIX7K2nbRnDoR4EbS842eEVmonf/P+SKmJDdGrUOOhoqRr xueDg2WXnLP11V8zopeKkZEa5Um7BgjbuRf5GJVAyPMGYxz3VlqQsMU/ZXsr5Q3+jSGm Ej0w== X-Gm-Message-State: AFq9FYJGgATIBKe/GbYp/AOtAnRJvENqxQXhRUooJwLPQzLXKTOSYEMg QG4W+4f7qIvisiSccWqx/ZOCKpCrWursVj5AO15vDAlSlqT7lapb00KKc4HhXu8Hvf4= X-Gm-Gg: AYBFou2kxeWx3RWsXwIXnt129paG/NlEEzJ/f19cPDpR7/dehBn9/4jGqLRla3mvXed ZWDAXvK0guwDaXZw3qTuLaZw31dviS03/Sa86o7dPeWPKHONwniWCd87KmAsEyg1+gha410QTag CSA5Zf3SHZBWGLmNPas66N1X7YVXoE8bCu5K47ojVgRoyD97/AYCQYf7VMZ8MZbACdxNcD2SpFB eLoFjbvAegNR6IVMmwuwRGvui+1PF0rcHkbIR7NdiAsWzdT7AD/7hloYR2IDxW8qjFg5mfAabrz pwvdcVzTn+qtvh+v5TURzC8MwUpD5hLd3cHuZYwyDSrubn+g8P3bHfp30QU6C3cWxyaJG6fMae8 FkONmAXV6mJ2U4QLgeALn/4mH3w4Tb4uDMuchNxECmum8RZqJKSA0pZO1S6uH2QNEGPBjv8JGbg ziwgzCm3aiWmq8HVWWfU1q5+D00VfWVWbN9PovuHhFA5LMKnyZsK7itqfuBN3UrpKphxvhPPVHA nP32snaYUtBl36O732dY+zaNIz9 X-Received: by 2002:a05:6122:311e:b0:5db:8e8e:41fa with SMTP id 71dfb90a1353d-5eaacc383d4mr254968e0c.7.1792182515019; Fri, 16 Oct 2026 13:28:35 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:34 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 06/11] tests: Check the configured CPU image crop Date: Fri, 16 Oct 2026 16:28:13 -0400 Message-ID: <20261016202818.1405645-7-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit checks the crop returned by CPU debayering for supported Bayer input formats and both RGB channel orders. Unpacked kernels may shift the first rendered pixel by one column depending on the Bayer pattern and output channel order. The reported image region must include that shift, while the specialized packed kernels retain their unshifted origin. The configuration-only cases cover all four standard Bayer orders at 8, 10 and 12 bits, including packed RAW10 and RAW12. Reusing the debayer across configurations also checks that changing formats clears a previous phase shift. Signed-off-by: Ray Strode --- test/meson.build | 1 + test/software_isp/debayer-crop.cpp | 102 +++++++++++++++++++++++++++++ test/software_isp/meson.build | 20 ++++++ 3 files changed, 123 insertions(+) create mode 100644 test/software_isp/debayer-crop.cpp create mode 100644 test/software_isp/meson.build diff --git a/test/meson.build b/test/meson.build index 5027b7b1..fc72d105 100644 --- a/test/meson.build +++ b/test/meson.build @@ -35,6 +35,7 @@ subdir('media_device') subdir('process') subdir('py') subdir('serialization') +subdir('software_isp') subdir('stream') subdir('v4l2_compat') subdir('v4l2_subdevice') diff --git a/test/software_isp/debayer-crop.cpp b/test/software_isp/debayer-crop.cpp new file mode 100644 index 00000000..40355b5a --- /dev/null +++ b/test/software_isp/debayer-crop.cpp @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2026, Red Hat Inc. + * + * CPU debayer crop configuration tests + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "libcamera/internal/formats.h" +#include "libcamera/internal/software_isp/swstats_cpu.h" + +#include "debayer_cpu.h" +#include "test.h" + +using namespace libcamera; + +class DebayerCropTest : public Test +{ +protected: + int run() override + { + CameraManager manager; + auto stats = std::make_unique(manager); + if (!stats->isValid()) + return TestFail; + + DebayerCpu debayer(std::move(stats), manager); + static const struct { + PixelFormat input; + int rgbShift; + int bgrShift; + } cases[] = { + { formats::SBGGR8, 0, 1 }, + { formats::SGBRG8, 1, 0 }, + { formats::SGRBG8, 0, 1 }, + { formats::SRGGB8, 1, 0 }, + { formats::SBGGR10, 0, 1 }, + { formats::SGBRG10, 1, 0 }, + { formats::SGRBG10, 0, 1 }, + { formats::SRGGB10, 1, 0 }, + { formats::SBGGR12, 0, 1 }, + { formats::SGBRG12, 1, 0 }, + { formats::SGRBG12, 0, 1 }, + { formats::SRGGB12, 1, 0 }, + /* Packed kernels use each Bayer order without a phase shift. */ + { formats::SBGGR10_CSI2P, 0, 0 }, + { formats::SGBRG10_CSI2P, 0, 0 }, + { formats::SGRBG10_CSI2P, 0, 0 }, + { formats::SRGGB10_CSI2P, 0, 0 }, + { formats::SBGGR12_CSI2P, 0, 0 }, + { formats::SGBRG12_CSI2P, 0, 0 }, + { formats::SGRBG12_CSI2P, 0, 0 }, + { formats::SRGGB12_CSI2P, 0, 0 }, + }; + + for (const auto &entry : cases) { + StreamConfiguration input; + input.pixelFormat = entry.input; + input.size = { 1928, 1092 }; + input.stride = PixelFormatInfo::info(entry.input).stride(input.size.width, 0); + + for (PixelFormat format : { formats::RGB888, formats::BGR888, + formats::XRGB8888, formats::XBGR8888 }) { + StreamConfiguration output; + output.pixelFormat = format; + output.size = { 1280, 720 }; + std::tie(output.stride, output.frameSize) = + debayer.strideAndFrameSize(format, output.size); + const std::vector> outputs{ output }; + if (debayer.configure(input, outputs, false)) { + std::cerr << "Unable to configure " << entry.input << " -> " << format + << std::endl; + return TestFail; + } + + int shift = (format == formats::RGB888 || format == formats::XRGB8888) + ? entry.rgbShift + : entry.bgrShift; + Rectangle expected(324 + shift, 186, 1280, 720); + if (debayer.inputCrop() != expected) { + std::cerr << "Crop for " << entry.input << " -> " << format << " is " + << debayer.inputCrop() << ", expected " << expected << std::endl; + return TestFail; + } + } + } + + return TestPass; + } +}; + +TEST_REGISTER(DebayerCropTest) diff --git a/test/software_isp/meson.build b/test/software_isp/meson.build new file mode 100644 index 00000000..ebabde59 --- /dev/null +++ b/test/software_isp/meson.build @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: CC0-1.0 + +if not softisp_enabled + subdir_done() +endif + +software_isp_tests = [ + {'name': 'debayer-crop', 'sources': ['debayer-crop.cpp']}, +] + +foreach test : software_isp_tests + exe = executable(test['name'], test['sources'], + dependencies : libcamera_private, + implicit_include_directories : false, + link_with : test_libraries, + include_directories : [test_includes_internal, + '../../src/libcamera/software_isp/']) + + test(test['name'], exe, suite : 'software_isp') +endforeach From patchwork Fri Oct 16 20:28:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28479 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 48A03C3307 for ; Fri, 16 Oct 2026 20:28:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CFEFA68E53; Fri, 16 Oct 2026 22:28:42 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="nU5dzNAV"; dkim-atps=neutral Received: from mail-vk1-xa29.google.com (mail-vk1-xa29.google.com [IPv6:2607:f8b0:4864:20::a29]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2A21068E4B for ; Fri, 16 Oct 2026 22:28:37 +0200 (CEST) Received: by mail-vk1-xa29.google.com with SMTP id 71dfb90a1353d-5ea93a316aaso164352e0c.0 for ; Fri, 16 Oct 2026 13:28:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182516; x=1792787316; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=tjB8EtehsH4sXU3Tzol5ve5WZoGk4eiS1O7HWeLNpIk=; b=nU5dzNAVnt6hEB2+Cpi7hcTJ/UTNwFeaX3QmY9lfyhF9P1d58BLSKRxntBkiSLeQjy zuPh1L4AJAEefxwZdmYCod23Dcq5UJb7UyXOim+BN+8g5s7ViRK4O7S8sVySdZV+3Kl7 32JwBtHIvqE9CJdxJlJycrSDUw/v3RYF25L5zCq/lWIf9F2eRXNU/U0pLvd1C3Er4WIc jnNJz4PkMsE/TSLMtjJ4v0CkJyH1xiF2Mu8/Erjl9PpzYcu+OFxw7uCOI4hcw2qg/v5h g0mku6tRo5PshlfL2f4/fJmCETCNkmPgBrk2JOR1l7sGfBCrp47nTmIQQOC6tGO8EB2z Au2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182516; x=1792787316; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=tjB8EtehsH4sXU3Tzol5ve5WZoGk4eiS1O7HWeLNpIk=; b=SW+0TRP3/FFgUf+V/VRG/msZbpIH53Le3slOcMjNaUsCQjOm095gSglt4+rJWK1hPI d0ZdsSitgw7sub8wgYX3ZHRbRStK82XHKjdczAjtLDjP5ZB3but4a5cQ32/3iNnKAja2 KTCSJFLoRfPELYe8aPibr+wJq4b54puCnOxkr0iRxvNggE/GDa+5UX1JUIwa9gdyr1KH b6VG+7+r6IPEnmOaRRjPw2y/KJsYEM9A9mOd0xONdyWdFA0M7YscUc1CAmCXTWJW7RNp zifMaybygirTZi4VRhCcUThwE/ac4Xw7wtX9ae7fjfjtNo+sBuSlyu5f/6ecIT0U5MNY 3C1Q== X-Gm-Message-State: AFq9FYJuOy/XKEHjrT1Or6oLsvYqPVjMaXvzsIKZLjMlAuYjiGuqR1YJ IZnrB7YV/OQZkqZEX/OZIQNQLpdP2OD7rBsAQ0ikgrx/dZ91I2TPjLbrtcglmbOWcdc= X-Gm-Gg: AYBFou1rwLlzhOEOoGO/XnasDmvbxEn5EgrNrMnupDtNU/nAslcIzPXQkahys1t1Yrj gXYm7Jl15bo2NSh2agqeUDEoCjKHAYGw4QB+6uNTbb6PQ6GJUduyCcKEFTsKtJL2PCIEl7cHLnu nYxsQKaKBKozof7WUvc3RKkjlrXAhxHVulvpPBL4l/9ejUYmRzdI/Gz4ZfQ3uxlj+kPFbwSucNM QRiWaIOSeoNNC9+VD7sOO1J3rc/XSz6rGRG8GvSFSyAeG4n1WxJSseQueNgq0gOUL6ih+Awfb8O oC6D5jZaYgs/cZGzfZ8v6gq01FLjSn5rXmPihITJZTi7EgbDcyz/5H0v7QpGduO0CDkW3dyCHNM GWEtFSIVF2cdINSAf/E7ybAcpp+qAvIrUr/YCnz0nYH9H3en3YWkkEOkmUQL0Iq+pcjTs14YKch ZH+2zlPQ737lhy5EDPMk4tNBQSibQmPXozG8S3YkLRgV+wuLaEAHTaxUGqSJ3ZynelkZaw3Ws/s iP3+rtN0ddG8u6UtB4IK9NSJPeZZjscLrKM+I8= X-Received: by 2002:a05:6122:1984:b0:5c9:c60e:3a40 with SMTP id 71dfb90a1353d-5eaaa678586mr546977e0c.18.1792182515963; Fri, 16 Oct 2026 13:28:35 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:35 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 07/11] software-isp: Map input crops to native sensor coordinates Date: Fri, 16 Oct 2026 16:28:14 -0400 Message-ID: <20261016202818.1405645-8-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit adds the coordinate conversion needed to report a debayer crop as ScalerCrop metadata. Debayer crops use captured-buffer pixels. ScalerCrop uses native sensor pixels relative to the active array, so sensor binning, analogue crop offsets and sensor transforms must be accounted for. The conversion reverses the sensor transform, maps the input rectangle into the analogue crop and subtracts the active-array origin. Integer coordinates and dimensions follow the truncation used by the existing rectangle transformation. Signed-off-by: Ray Strode --- .../internal/software_isp/debayer_geometry.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/libcamera/internal/software_isp/debayer_geometry.h b/include/libcamera/internal/software_isp/debayer_geometry.h index 46721753..8409fd09 100644 --- a/include/libcamera/internal/software_isp/debayer_geometry.h +++ b/include/libcamera/internal/software_isp/debayer_geometry.h @@ -9,8 +9,10 @@ #include #include +#include #include +#include namespace libcamera { @@ -48,4 +50,29 @@ inline Rectangle debayerCrop(const Size &inputSize, const Size &nativeSize, return visibleSize.centeredTo(Rectangle(inputSize).center()); } +/* + * Map an image crop to native sensor pixels relative to the active array. + * The input must cover the whole analogue crop. Undo the sensor transform + * before accounting for binning and the analogue crop offset. Integer + * coordinates and dimensions are truncated as in transformedBetween(). + */ +inline Rectangle debayerCropToSensor(Rectangle crop, Size inputSize, + const Rectangle &analogCrop, + const Rectangle &activeArea, + Transform transform) +{ + if (!!(transform & Transform::Transpose)) { + std::swap(crop.x, crop.y); + std::swap(crop.width, crop.height); + std::swap(inputSize.width, inputSize.height); + } + if (!!(transform & Transform::HFlip)) + crop.x = inputSize.width - crop.x - crop.width; + if (!!(transform & Transform::VFlip)) + crop.y = inputSize.height - crop.y - crop.height; + + return crop.transformedBetween(Rectangle(inputSize), analogCrop) + .translatedBy(-activeArea.topLeft()); +} + } /* namespace libcamera */ From patchwork Fri Oct 16 20:28:15 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28480 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 1206CC324C for ; Fri, 16 Oct 2026 20:28:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B518268E57; Fri, 16 Oct 2026 22:28:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JF0qtYwk"; dkim-atps=neutral Received: from mail-vk1-xa29.google.com (mail-vk1-xa29.google.com [IPv6:2607:f8b0:4864:20::a29]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4752F68E49 for ; Fri, 16 Oct 2026 22:28:38 +0200 (CEST) Received: by mail-vk1-xa29.google.com with SMTP id 71dfb90a1353d-5e6b5794d26so407536e0c.1 for ; Fri, 16 Oct 2026 13:28:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182517; x=1792787317; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=kPk9fP17Si+US2rvmZRJP8Lf8z4Pdwsurlzlm3vopzI=; b=JF0qtYwkAJ2mAeqmpG3u6JizeipklT0tHE1HSI3aVmIlQk8rSH1oPgOCCgVFHq8X8O IJsTUEaWg7/Ztlqh5ThTDikxZ24q/mrLwktFrnL7OJZjOyWDcHTWeSfkHzUusYpMwghC GE50CTbXluOMhG9QM58UEU4AuKgYuwm0hBT7Kpqqc5F83snzLERkD5vMW3MkrcsgsmT1 99F2swpoJrGOAtRuWPM2aNttM0DfDRxSlRbgjJQz2TIeqEdWh8EW6aGBFCIKZk+HwxW9 FScaoTpvl1o76PHmJD/Oc3Fjdrqa3sqz4LZHzA/VZ2ws4e25Uy46I/mQSIXxTKxYzymS rlmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182517; x=1792787317; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=kPk9fP17Si+US2rvmZRJP8Lf8z4Pdwsurlzlm3vopzI=; b=W9t+J/IOnn6CE8JYBWplMD5tYeXZf/l1CkbkoHuYoc1uy0qYtvaMnlAfBhiSgfVLto Y3UlZXwcs0tAkTsqTPhc66/cl8xj4ZQf5OzOZpM7ye1n0IBqDQZJseeblNnOiKlK+6vr sOhSsWwrrm3CDYDBr7Npyp+i86aq9bZsEr9Mi3G5LcddQ+KOBNZWPNY7gH8x63OT97/P CAl8bLqGJ1jwlDRd2k3p8N7luIQaPVpqaa7nqctrpU4Cu/NZB4rw+ATsp2u3cEu+fRLN 1V75n9k4EoiHMdtm+URWLzLb4yZ8Et8LexQpSlD964l3bmQEUpkoF52Al6ayvChIGVId 7q8Q== X-Gm-Message-State: AFq9FYK1IY0UyMl3lGdr1GorG+7+WpWD/TTBEE53gV27T8/FpPYMvjmN MZlwGZxDYxJW+mc2Mp96rTl0mMWMjfMLDcaoNwDV4Z/IELAWkd4sX7NdNlgqrDPLmLE= X-Gm-Gg: AYBFou3WKHKyOOfwB4NBmUHrS9MbWiYr3pd8Jat1CO9HSbJcjYxjWwfaikzDnzZ/w3z m2rrHF+02927o0vd6LptIyLLl16KHaPV97rYETXoDawM9etTX388pIdhgreKjnJOkNc7hhliu6O VJiqjGEU/m4rF8NEHmgljB/50qxrxrNlzczV38izdRmCUOPcS9xZl2FfgMOMNTC0kRqIzzBTF09 K5YAeQAA0Rr8N6AZ83cg9eFKUiu72e06KnR1uSwG7pc+/2pYSHeEnLRgkRQYPC03RbOx5yZlmL9 1vLL8/BF13mMb5puD/VRWsc7TxewkNKVEPwC2ztZzXHtR1gz+l4HItRefhLKwoRuDvDUCmykJRr gVImWtgBrAzqTk/RrDBFtQZ2xsQHcSK7vloWI09f1c0wqAOiYoeaezMwn/XwVOOkrZuLQDBc6uA N4QS+gv/zFOkAMk4C4kxYx9Xo/1KrkMjoPvFOrrANN5pcpw0G+yPghTl+Qg7sBVlh4F+BQRiKNh 3qJV6dUB8D3LcGm9ZVJtGscpVd4h+oWvNHnZHw= X-Received: by 2002:a05:6122:4014:b0:5ce:fc2e:d0e9 with SMTP id 71dfb90a1353d-5ea9801d848mr1232804e0c.13.1792182517009; Fri, 16 Oct 2026 13:28:37 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:36 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 08/11] tests: Validate native sensor crop coordinates Date: Fri, 16 Oct 2026 16:28:15 -0400 Message-ID: <20261016202818.1405645-9-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit checks the conversion from debayer crop rectangles to native sensor coordinates in the existing geometry unit test. The test currently verifies projection and crop selection in input-buffer coordinates. It does not check the coordinate system needed by ScalerCrop metadata. The new cases cover GPU and CPU crop sizes, sensor offsets, binning, flips, transposition and fractional coordinates. An odd image boundary checks that the conversion preserves image geometry before Bayer statistics alignment. Signed-off-by: Ray Strode --- test/debayer-geometry.cpp | 44 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/debayer-geometry.cpp b/test/debayer-geometry.cpp index 86d4248f..1d96fce1 100644 --- a/test/debayer-geometry.cpp +++ b/test/debayer-geometry.cpp @@ -23,7 +23,7 @@ class DebayerGeometryTest : public Test protected: int run() override { - if (testProjection() || testCrop()) + if (testProjection() || testCrop() || testSensorCrop()) return TestFail; return TestPass; @@ -123,6 +123,48 @@ private: return TestPass; } + + int testSensorCrop() + { + static const struct { + Rectangle crop; + Size input; + Rectangle analog; + Rectangle active; + Transform transform; + Rectangle expected; + } cases[] = { + /* GPU scaling keeps the full visible sensor region. */ + { { 4, 6, 1920, 1080 }, { 1928, 1092 }, { 0, 0, 1928, 1092 }, { 0, 0, 1928, 1092 }, Transform::Identity, { 4, 6, 1920, 1080 } }, + /* Sensor crop offsets and 2x binning use native pixels. */ + { { 4, 6, 1920, 1080 }, { 1928, 1092 }, { 100, 200, 3856, 2184 }, { 8, 8, 4000, 3000 }, Transform::Identity, { 100, 204, 3840, 2160 } }, + /* CPU debayering crops to output size without scaling. */ + { { 324, 186, 1280, 720 }, { 1928, 1092 }, { 100, 200, 3856, 2184 }, { 8, 8, 4000, 3000 }, Transform::Identity, { 740, 564, 2560, 1440 } }, + /* Preserve an odd image boundary before statistics alignment. */ + { { 2, 5, 1924, 1082 }, { 1928, 1092 }, { 0, 0, 3856, 2184 }, { 0, 0, 3856, 2184 }, Transform::Identity, { 4, 10, 3848, 2164 } }, + /* Undo sensor flips before reporting the native rectangle. */ + { { 2, 4, 20, 10 }, { 100, 60 }, { 10, 20, 200, 120 }, { 2, 4, 300, 200 }, Transform::HFlip, { 164, 24, 40, 20 } }, + { { 2, 4, 20, 10 }, { 100, 60 }, { 10, 20, 200, 120 }, { 2, 4, 300, 200 }, Transform::VFlip, { 12, 108, 40, 20 } }, + { { 2, 4, 20, 10 }, { 100, 60 }, { 10, 20, 200, 120 }, { 2, 4, 300, 200 }, Transform::HVFlip, { 164, 108, 40, 20 } }, + /* Transposition is undone before the flip. */ + { { 4, 2, 10, 20 }, { 60, 100 }, { 10, 20, 200, 120 }, { 2, 4, 300, 200 }, Transform::Rot270, { 164, 24, 40, 20 } }, + /* Fractional native coordinates and sizes truncate independently. */ + { { 1, 1, 3, 3 }, { 8, 8 }, { 10, 20, 12, 12 }, { 2, 4, 30, 40 }, Transform::Identity, { 9, 17, 4, 4 } }, + }; + + for (const auto &entry : cases) { + Rectangle crop = debayerCropToSensor(entry.crop, entry.input, + entry.analog, entry.active, + entry.transform); + if (crop != entry.expected) { + std::cerr << "Sensor mapping of " << entry.crop << " in " << entry.input + << " is " << crop << ", expected " << entry.expected << std::endl; + return TestFail; + } + } + + return TestPass; + } }; TEST_REGISTER(DebayerGeometryTest) From patchwork Fri Oct 16 20:28:16 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28481 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 76686C3305 for ; Fri, 16 Oct 2026 20:28:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2DBC768E77; Fri, 16 Oct 2026 22:28:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="o1tUi+Pu"; dkim-atps=neutral Received: from mail-vk1-xa2f.google.com (mail-vk1-xa2f.google.com [IPv6:2607:f8b0:4864:20::a2f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 05C0E68E3A for ; Fri, 16 Oct 2026 22:28:39 +0200 (CEST) Received: by mail-vk1-xa2f.google.com with SMTP id 71dfb90a1353d-5e930a11148so229657e0c.2 for ; Fri, 16 Oct 2026 13:28:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182518; x=1792787318; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=fqO4EYJ6COt1aye3c7JvLP4PBBEK2Ab6empI1mmiObs=; b=o1tUi+PuERbDmGbSkl9VUWMDzph6QdP2nA373YSDiI4RFus4P4HoI3GVvAXR5BuWNv O9i00XqK/tQ9ZtS6HJOHyK8uUdo+SUIemhKB5NddYlSbLN2nOU95OowPES01bOmpFGWl CO8xISeIM/kcu5kUzoP5LvOQgTgYdU/6aO11dB7WftPx/rOwCbSuehYHUYlucEIqXYYT R082pXjfelEg2Nowckkzs/ueueGBU1LbKBc1PxrUDh2+IIGx044LbGIHGFKyzq6Anl80 1640ODamhvJS6a5p0wg9ov1YMZqHHLwlrTz5aTkJAQjDdE578sJIqU0f27/2JrAdDIK1 RmSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182518; x=1792787318; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=fqO4EYJ6COt1aye3c7JvLP4PBBEK2Ab6empI1mmiObs=; b=JS4SZqsvViKQJDw8de6gKveybs3xYc66FT9Lv7tJioIel0TqwYERjiexZz6ReyW+bx veMODB9X6rcInfmYz8hoNfM45SdoZcu19kFFXq7IU7nVHOCbLpBBThqCFAn1dN3LiN78 PpovdktXBT0pIVYkb7ewBhpqFEy37LcnZnTk/rDXHHxHlVOxbDZzITJNeNzurYNvvb06 zkVfH8HWxj08fO1maAKYiugbYjwlPBxebSruuqxy1kUNJQeInnDuTWlN8/Cv7mGkaL1L P5dbxMJlh47xKUVGfy748Yj7rtPzDQzzOMN4uT32PYm63Mfkx1RJfNG7o2qNceIjDrL5 Wyeg== X-Gm-Message-State: AFq9FYLpdbavdaM77QAzDE+M4M6hkhe3JCIHi+UXK7fMdZajXMrynfNn cJU0E2XmgIECK9og1dGRFT+j8jqpT3q1EWYJUhMnCCO8857+7tPsnhlqMptoQriADA0= X-Gm-Gg: AYBFou0v7E7aFFHXwZrC+g9kYOwVq98ACkyzhCOL6WGZBwnmDnqOC1HtBr59LoQB6+t T+hI/x/lttL6OWGt4cuH9MxjnMgtn/RY7kiOfJxK8CXg6o2o2/Ik8nawzyskbDI3ZMfvnHX2yI7 HYk9jdFgNzvRkx/XA5+0pbLhOe0L2lIWRWXt/sjzSwfg/zOJ6bT/XcEghKSZ57ViC9PLZrnI9h4 9Draar6Zq5sWUyYPwZAOoLXzntlU1hdOfmj+YFAdUyNfJPUZ6eO9+P0/oOPPYKbmEWKNwcKeN5Q N8Z3pYngUHHe+ga/S6G6JTDevKfRd1jAAoH7BvkNqSwMqPg94WBpcvu5vWhxjhO8NdQP4vnmj+/ ATtNp8X4QhlSq1X9m0OLX0M+2dNKWBn8izQrcc5/51UN60l7dr4+RLio3W/Xlfh7r/ji8LaZlIw iJNTYcCj340n20tqeQyn54UHT5aurQXqbunaXv70GVKSgsrXv0A+fM/NHXsm13N+z4Zk6jH8Ba7 M6VaksssqTilbycOMIYaOMzOz4n X-Received: by 2002:a05:6122:e14b:b0:5c8:c5f:e8fa with SMTP id 71dfb90a1353d-5eaaa374143mr607698e0c.4.1792182517860; Fri, 16 Oct 2026 13:28:37 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:37 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 09/11] v4l2: Allow probing optional selection rectangles Date: Fri, 16 Oct 2026 16:28:16 -0400 Message-ID: <20261016202818.1405645-10-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit allows callers to query optional subdevice selections without logging an error when the API or target is unsupported. Determining the sensor region captured by a pipeline requires checking whether its intermediate subdevices crop or compose the image. The selection ioctl or a particular target may be absent on a pass-through device, and that expected result currently produces an error message. Signed-off-by: Ray Strode --- include/libcamera/internal/v4l2_subdevice.h | 7 ++++--- src/libcamera/v4l2_subdevice.cpp | 12 ++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h index c37a82af..41dc80f2 100644 --- a/include/libcamera/internal/v4l2_subdevice.h +++ b/include/libcamera/internal/v4l2_subdevice.h @@ -123,10 +123,11 @@ public: const MediaEntity *entity() const { return entity_; } int getSelection(const Stream &stream, unsigned int target, - Rectangle *rect); - int getSelection(unsigned int pad, unsigned int target, Rectangle *rect) + Rectangle *rect, bool optional = false); + int getSelection(unsigned int pad, unsigned int target, Rectangle *rect, + bool optional = false) { - return getSelection({ pad, 0 }, target, rect); + return getSelection({ pad, 0 }, target, rect, optional); } int setSelection(const Stream &stream, unsigned int target, Rectangle *rect); diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index a69de154..2e23f9ad 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -1171,13 +1171,17 @@ int V4L2Subdevice::open() * \param[in] stream The stream the rectangle is retrieved from * \param[in] target The selection target defined by the V4L2_SEL_TGT_* flags * \param[out] rect The retrieved selection rectangle + * \param[in] optional Whether unsupported targets are expected + * + * Optional queries return -ENOTTY or -EINVAL without logging an error when + * the selection API or target is unsupported. Other errors are logged normally. * * \todo Define a V4L2SelectionTarget enum for the selection target * * \return 0 on success or a negative error code otherwise */ int V4L2Subdevice::getSelection(const Stream &stream, unsigned int target, - Rectangle *rect) + Rectangle *rect, bool optional) { struct v4l2_subdev_selection sel = {}; @@ -1189,6 +1193,9 @@ int V4L2Subdevice::getSelection(const Stream &stream, unsigned int target, int ret = ioctl(VIDIOC_SUBDEV_G_SELECTION, &sel); if (ret < 0) { + if (optional && (ret == -ENOTTY || ret == -EINVAL)) + return ret; + LOG(V4L2, Error) << "Unable to get rectangle " << target << " on pad " << stream << ": " << strerror(-ret); @@ -1205,11 +1212,12 @@ int V4L2Subdevice::getSelection(const Stream &stream, unsigned int target, /** * \fn V4L2Subdevice::getSelection(unsigned int pad, unsigned int target, - * Rectangle *rect) + * Rectangle *rect, bool optional) * \brief Get selection rectangle \a rect for \a target * \param[in] pad The 0-indexed pad number the rectangle is retrieved from * \param[in] target The selection target defined by the V4L2_SEL_TGT_* flags * \param[out] rect The retrieved selection rectangle + * \param[in] optional Whether unsupported targets are expected * * \return 0 on success or a negative error code otherwise */ From patchwork Fri Oct 16 20:28:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28482 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 0FFADC3316 for ; Fri, 16 Oct 2026 20:28:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B495168E61; Fri, 16 Oct 2026 22:28:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jpVS5PpV"; dkim-atps=neutral Received: from mail-vk1-xa2b.google.com (mail-vk1-xa2b.google.com [IPv6:2607:f8b0:4864:20::a2b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B4F8B68E5B for ; Fri, 16 Oct 2026 22:28:40 +0200 (CEST) Received: by mail-vk1-xa2b.google.com with SMTP id 71dfb90a1353d-5e948e56b9dso117597e0c.1 for ; Fri, 16 Oct 2026 13:28:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182519; x=1792787319; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=a4MfcP/aL8c25kdB23Fap6IzVB63xsEyY26YTqRub9Y=; b=jpVS5PpVQagFOXxjpNNG7OCnsvMTMS+CHMhrHaqT82lkKDM87oepY9U6yCkaxSIvpq 86mxubkKoZrWnaOkLb60lA1d3t4pRo7T1DOx6v/Xa8+S4GdbIKlhMnLfSD4DRUtSERT0 kgLCUTgxo8g/wHVHrgUtN9JNw1rgjsM+V/d4M6zZ8a++xFwca92pKGXLCk0HV+j430/y MNS1DN7Elvv3Jmnx9kzsHdWylZ3GS3RFGMbprj8t6pXGmkm3a8Q4DNAm0CqoRnzsHlfu 0/FXrtdOocmmsB2qZb+6v4paEsFQoOyG449PQKUf1twQ3R2BCGkGYpbNsZj6ZnVfv2HH LXtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182519; x=1792787319; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=a4MfcP/aL8c25kdB23Fap6IzVB63xsEyY26YTqRub9Y=; b=FrrEBIwmwgmUGJQ/ZGM4w6PF+SmJc6+x/FdAfVYWHaxOX2IeDGpzZDXueNBvh3Pp+3 bfREqn4P/56llWWs2WfPQzBpetV4J1spktkgrAnpZCs/ztcBQ2xDipF3ZWMH/5yEToMX k9dbsE4cZn5wRGF+MAZrd5igT0Am9vY4fcRloayoPGOj153rcLJ4gJetLDGS4mRHQKHW IiUMOz2ahBWmqIWJGHmrrAhnEhjzuWJSgQ68rQFD73kE33oHBTTfonGNPN+/UIokZ6yP xgdHId7sk0pBhkr6Bx6GSQRddxDdCphhmtWFuj4a+sbmry5jNF+vD0XXOeImreVid7GR mLhw== X-Gm-Message-State: AFq9FYIctkYMpu9X3tXCBnbbN+POVTb7PqUInoeRZOkmdbEMskLMJ8Wy 1rnUWUAIPoneBZC6PzTC44wHts2rU9M3wmsKevB83+3UdvXo5mqrvGMGZ3bCr0XzYfY= X-Gm-Gg: AYBFou3dWtbj7pOh5LDYVzUR1VPRhE+29aZcrDYUZxhQYqeXWWGegEdXOq/9op8qS7W gJv5Q7UqXhF/TX4sVKIgBPrT9N7HzDSgpdCQbb7e6tdlAeVMM3kl1yM6F40qo4a5UR6U//aJoPJ fO776ceDpC5AZvJQByEUxkjL+m6wyo0y3d8WaR/nDGSAXouvbrvZVlAMQjCO4Fj4knqrDvyc8m1 M0Y0LjouCTuBasxErfA5D9gVCbSsWsVfrXqG00gw85J5/cBKlvyx/W4IYHMVbVepmrczdl3xJbB VT0FdjABAq/83oaDvsJzZEupNdC+vB8jPolku+hfZINFt09+CnN2snXXoiSkpwMKzwFIHsiWqTr rlGHSQqFgNu/cr51BIyB3W+R+saBAJRtq6EdYpgtkBGALw/ZhiUOy+qPM3gffpWdnFZbhsonQ5G LOTSS15W3Uhmzi0J2iSA1wHOAqz5BAp+kzi0G9romsHFkuddtewa8ceywISSJcEqLgWKj0Sx36V g0tyjNfXktC1ByiJVlvKKLgfBPN X-Received: by 2002:a05:6122:e443:b0:5ea:a9e1:d87c with SMTP id 71dfb90a1353d-5eaaa67b7b3mr534234e0c.18.1792182519472; Fri, 16 Oct 2026 13:28:39 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:38 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 10/11] pipeline: simple: Report the software ISP's maximum crop Date: Fri, 16 Oct 2026 16:28:17 -0400 Message-ID: <20261016202818.1405645-11-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit reports the software ISP's configured image region through the ScalerCropMaximum camera property. The simple pipeline currently exposes sensor properties without identifying the region retained by software processing. CPU debayering crops to the output dimensions, while EGL also scales the image, so the visible region can be smaller than the analogue sensor crop. The reported rectangle uses native sensor coordinates relative to the active array. Reporting is limited to capture paths that preserve the sensor output, since intermediate cropping or scaling requires an additional mapping. Reconfiguration restores the sensor properties so raw-only configurations do not retain an earlier processed-image crop. Based on Kieran Bingham's ScalerCropMaximum reporting patch, extended to account for the software ISP's selected image region. Link: https://patchwork.libcamera.org/patch/26678/ Signed-off-by: Ray Strode --- src/libcamera/pipeline/simple/simple.cpp | 54 +++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 35c29cec..91b149d1 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "libcamera/internal/camera.h" @@ -44,6 +45,7 @@ #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/request.h" +#include "libcamera/internal/software_isp/debayer_geometry.h" #include "libcamera/internal/software_isp/software_isp.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -292,6 +294,7 @@ public: Transform transform = Transform::Identity); void imageBufferReady(FrameBuffer *buffer); void clearIncompleteRequests(); + void updateScalerCrop(const Size &inputSize, Transform transform); unsigned int streamIndex(const Stream *stream) const { @@ -983,6 +986,48 @@ void SimpleCameraData::clearIncompleteRequests() } } +void SimpleCameraData::updateScalerCrop(const Size &inputSize, Transform transform) +{ + IPACameraSensorInfo sensorInfo; + if (sensor_->sensorInfo(&sensorInfo)) + return; + + /* + * The buffer-to-sensor mapping requires a capture path that preserves + * the sensor output. Intermediate cropping or scaling needs a separate + * mapping; do not report the analogue crop as if it included that work. + */ + if (sensorInfo.outputSize != inputSize) + return; + + for (const Entity &entity : entities_) { + if (!entity.sink || !entity.source) + continue; + + V4L2Subdevice *subdev = pipe()->subdev(entity.entity); + for (const MediaPad *pad : { entity.sink, entity.source }) { + V4L2SubdeviceFormat format{}; + if (subdev->getFormat(pad->index(), &format) || + format.size != inputSize) + return; + + for (unsigned int target : { V4L2_SEL_TGT_CROP, V4L2_SEL_TGT_COMPOSE }) { + Rectangle selection; + int ret = subdev->getSelection(pad->index(), target, &selection, true); + if (!ret && selection != Rectangle(inputSize)) + return; + if (ret && ret != -ENOTTY && ret != -EINVAL) + return; + } + } + } + + Rectangle crop = debayerCropToSensor(swIsp_->inputCrop(), inputSize, + sensorInfo.analogCrop, sensorInfo.activeArea, + transform); + properties_.set(properties::ScalerCropMaximum, crop); +} + void SimpleCameraData::tryCompleteRequest(Request *request) { if (request->hasPendingBuffers()) @@ -1505,6 +1550,8 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) V4L2VideoDevice *video = data->video_; int ret; + data->properties_ = data->sensor_->properties(); + /* * Configure links on the pipeline and propagate formats from the * sensor to the video node. @@ -1605,7 +1652,12 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) } else { ipa::softisp::IPAConfigInfo configInfo; configInfo.sensorControls = data->sensor_->controls(); - return data->swIsp_->configure(inputCfg, outputCfgs, configInfo, &data->controlInfo_); + ret = data->swIsp_->configure(inputCfg, outputCfgs, configInfo, &data->controlInfo_); + if (ret) + return ret; + + data->updateScalerCrop(inputCfg.size, config->combinedTransform()); + return 0; } } From patchwork Fri Oct 16 20:28:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28483 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 B3E3FC3357 for ; Fri, 16 Oct 2026 20:28:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 56AD268E63; Fri, 16 Oct 2026 22:28:48 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="rwyaoH+S"; dkim-atps=neutral Received: from mail-vk1-xa33.google.com (mail-vk1-xa33.google.com [IPv6:2607:f8b0:4864:20::a33]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9712168E4C for ; Fri, 16 Oct 2026 22:28:41 +0200 (CEST) Received: by mail-vk1-xa33.google.com with SMTP id 71dfb90a1353d-5e3e525cf4bso245375e0c.1 for ; Fri, 16 Oct 2026 13:28:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792182520; x=1792787320; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ewDEJKwgHJhq2HC7JgAl5zIuGK+JFX8Qb8/E/ErGGoU=; b=rwyaoH+SQ6NDN11n7PC2DxmP0hKjh8LuzIvoXA+fdQCJitKequR4hgQssSqH+f05KM 7+b10P8yVqIRNKYc4J0UyIm0TwiGmpJPX4i3Dqj6AhHEJargf65zM5ih71NTrItxNG6X p6zlv/snxzX4y9vhqlEsD6mARKPORTLlQnHo8wi6N3z03WZwkPYy75iYXhUsH7C4rhPu zGNnfd6bJRONlj1yaR2zzeIGH5jCfo1EvMvL15YSyPi2/Y+hwWuqD8DfDXjesh4G+7L0 71jZpzd5Cvlw4W5T7kOmuxLgdL2aefaGuovgDiUFO0r3HVMQ2ClKrtnT1Rz5oQfY4TtB +zOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792182520; x=1792787320; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=ewDEJKwgHJhq2HC7JgAl5zIuGK+JFX8Qb8/E/ErGGoU=; b=TCTV44inuQskPZ0//pOdUboUzUhCsWUh9W9a9Cw1XWsKdhen8TI/rV64zbRkwJQ6yD r4IqtCtjbjbnjHmNWK+Z5UF/ONxBseAa+Pbz3mNMbQZ6h6+ocnDucf9hQThsj8aLvbYc XFMkB8Zq6RyZYLWaCemu/KwOiNuUHZ3ydyLIB/B0u01jG3NVzZRP+ZYaJpdhN3QU4ENw eGkmrFzUux9xCxoBhUC8iQhHYR4P9XurWF+UG+mZZOHlazFrn7xS0NrzaCY+tgYe7L3Z oFa7LKaMW7JztHB/SrjlY2D/d8YTqWkzFEs7bRgl7YS7pezQPhxv/CPokIaOKm09we74 wWjw== X-Gm-Message-State: AFq9FYI815QbWJf8sRQilJaW75Ucry7MylDuJewrjHs9Jsfrf0zTwPeT zlE9Kunb4/WEqXPAuHB7GoWag5dScUuDhoqyTflDhfE1fDdwvxjXp+flONvbKCRVKOY= X-Gm-Gg: AYBFou2ViyKwPdG+8mvf5az6dlV2s2dXrgaVf44cGso0YpG2kLcAuB8mMUpQgvxCqNW iRcu5SAcB1U3QEyVA02ksLChuVtY9Bh2ELx20hZwPzW79+XsaxitXtCShcRQWTXVlXou5XRyocA LeP7DtX55VwoY6PMQPWpKSetDf+/Pormg1r+pGTJRpvxv+U8g8U9u1oV8FLvprZJayereTlYvn4 yGrnawZ9RGqUVmNMnuICfOyLp9bkrkMvKDGGLk2aQ/5iwPDYnPZuC7YqgZiXFD54mStk+A8m42l 0lVZiByXRPJxHIIjRLGKrUeE/s9Ip6g5e2QD5+Nzc2itYY0xjyB8WiTSuQOl5G+subf8PWZnpB8 6bnmSW96zkPC/x4Vq5IympfHYJkrjkI8o2uQtRN0s4SJMwRadeeynR46hWTZQDQ2HozOV21aCov WoDH1DoIno+Niglc0czNvoewdlY39maSxkvaEGTVfJ1YQZnbVZLsoNSORdnKiku4a5ncTCyb3A4 NQkPIoDvSzCDCrgA90PKe7gty8W X-Received: by 2002:a05:6122:4307:b0:5e7:8bd1:731f with SMTP id 71dfb90a1353d-5eaaa675dd4mr487145e0c.10.1792182520463; Fri, 16 Oct 2026 13:28:40 -0700 (PDT) Received: from localhost ([2601:19c:4a00:897d:3391:ed89:5571:41a8]) by smtp.gmail.com with ESMTPSA id 71dfb90a1353d-5ea9b2fef79sm2422500e0c.1.2026.10.16.13.28.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2026 13:28:39 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com Subject: [PATCH v3 11/11] pipeline: simple: Include the software ISP crop in request metadata Date: Fri, 16 Oct 2026 16:28:18 -0400 Message-ID: <20261016202818.1405645-12-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016202818.1405645-1-halfline@gmail.com> References: <20261015223604.311616-1-halfline@gmail.com> <20261016202818.1405645-1-halfline@gmail.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" From: Ray Strode This commit includes the software ISP's configured image region in completed requests as ScalerCrop metadata. The simple pipeline exposes this fixed region through ScalerCropMaximum, but completed requests still omit the sensor rectangle visible in their processed output. The crop is cached when the software ISP is configured and reported when each request completes. Reconfiguration clears the cached region so raw-only requests do not inherit an earlier processed-image crop. Based on Kieran Bingham's ScalerCrop metadata reporting patch, extended to use the software ISP's selected image region. Link: https://patchwork.libcamera.org/patch/26817/ Signed-off-by: Ray Strode --- src/libcamera/pipeline/simple/simple.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 91b149d1..cce42af7 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -363,6 +363,7 @@ public: std::unique_ptr converter_; std::unique_ptr swIsp_; SimpleFrames frameInfo_; + std::optional scalerCrop_; private: void tryPipeline(unsigned int code, const Size &size); @@ -1022,10 +1023,10 @@ void SimpleCameraData::updateScalerCrop(const Size &inputSize, Transform transfo } } - Rectangle crop = debayerCropToSensor(swIsp_->inputCrop(), inputSize, - sensorInfo.analogCrop, sensorInfo.activeArea, - transform); - properties_.set(properties::ScalerCropMaximum, crop); + scalerCrop_ = debayerCropToSensor(swIsp_->inputCrop(), inputSize, + sensorInfo.analogCrop, sensorInfo.activeArea, + transform); + properties_.set(properties::ScalerCropMaximum, *scalerCrop_); } void SimpleCameraData::tryCompleteRequest(Request *request) @@ -1042,6 +1043,9 @@ void SimpleCameraData::tryCompleteRequest(Request *request) if (info->metadataRequired && !info->metadataProcessed) return; + if (scalerCrop_) + request->_d()->metadata().set(controls::ScalerCrop, *scalerCrop_); + frameInfo_.destroy(info->frame); pipe()->completeRequest(request); } @@ -1550,6 +1554,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) V4L2VideoDevice *video = data->video_; int ret; + data->scalerCrop_.reset(); data->properties_ = data->sensor_->properties(); /*