From patchwork Fri Sep 18 09:10:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28334 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 81FFAC3292 for ; Fri, 18 Sep 2026 09:18:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 239F668702; Fri, 18 Sep 2026 11:18:59 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="c2aW1htv"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5154B6849B for ; Fri, 18 Sep 2026 11:18:57 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6c1f:355d:1c19:aba6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7EB0B230; Fri, 18 Sep 2026 11:17:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789723034; bh=L7H3L6BysP1Agb6bQELQ1z+TXz2s+oEtGnLeuIl6Z1Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c2aW1htvodKvEthsmQQY8fYJRtCRXkZzr9zeuZUbt0yNkkP0RyPOOQdhZHVfe1Kqh bpW3DBbM10yS5a4A57uYNo/KV0SM0WpowDFoG494IgJp5zKH8zHFkM+1XN/0dgYlFO wHsj943J1NWYbhlXAarGwQxVhb7uFKo+p/4fL1dQ= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v4 1/4] libcamera: property_ids_core: Drop PixelArrayOpticalBlackRectangles Date: Fri, 18 Sep 2026 11:10:48 +0200 Message-ID: <20260918091835.2332386-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918091835.2332386-1-stefan.klug@ideasonboard.com> References: <20260918091835.2332386-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 PixelArrayOpticalBlackRectangles is neither used nor populated anywhere in libcamera. The definition of it is difficult (due to the handing of invalid pixels and sensors specifying different OB areas for different binning modes) and will therefore break on the first real world use-case. Drop it for now. This can be revisited when need arises. Signed-off-by: Stefan Klug --- Changes in v4: - Added this patch --- src/libcamera/property_ids_core.yaml | 95 ---------------------------- 1 file changed, 95 deletions(-) diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml index d5b3d309c055..96c7b55d8383 100644 --- a/src/libcamera/property_ids_core.yaml +++ b/src/libcamera/property_ids_core.yaml @@ -496,101 +496,6 @@ controls: \todo Rename this property to Size once we will have property categories (i.e. Properties::PixelArray::Size) - - PixelArrayOpticalBlackRectangles: - type: Rectangle - size: [n] - description: | - The pixel array region(s) which contain optical black pixels - considered valid for calibration purposes. - - This property describes the position and size of optical black pixel - regions in the raw data buffer as stored in memory, which might differ - from their actual physical location in the pixel array matrix. - - It is important to note, in fact, that camera sensors might - automatically reorder or skip portions of their pixels array matrix when - transmitting data to the receiver. For instance, a sensor may merge the - top and bottom optical black rectangles into a single rectangle, - transmitted at the beginning of the frame. - - The pixel array contains several areas with different purposes, - interleaved by lines and columns which are said not to be valid for - capturing purposes. Invalid lines and columns are defined as invalid as - they could be positioned too close to the chip margins or to the optical - black shielding placed on top of optical black pixels. - - PixelArraySize.width - /----------------------------------------------/ - x1 x2 - +--o---------------------------------------o---+ / - |IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII| | - |IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII| | - y1 oIIOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOII| | - |IIOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOII| | - |IIOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOII| | - y2 oIIOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOII| | - |IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII| | - |IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII| | - y3 |IIOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOOII| | - |IIOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOOII| | PixelArraySize.height - |IIOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOOII| | - ... ... ... ... ... - ... ... ... ... ... - y4 |IIOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOOII| | - |IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII| | - |IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII| | - +----------------------------------------------+ / - - The readable pixel array matrix is composed by - 2 invalid lines (I) - 4 lines of valid optical black pixels (O) - 2 invalid lines (I) - n lines of valid pixel data (P) - 2 invalid lines (I) - - And the position of the optical black pixel rectangles is defined by - - PixelArrayOpticalBlackRectangles = { - { x1, y1, x2 - x1 + 1, y2 - y1 + 1 }, - { x1, y3, 2, y4 - y3 + 1 }, - { x2, y3, 2, y4 - y3 + 1 }, - }; - - If the camera, when capturing the full pixel array matrix, automatically - skips the invalid lines and columns, producing the following data - buffer, when captured to memory - - PixelArraySize.width - /----------------------------------------------/ - x1 - +--------------------------------------------o-+ / - |OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO| | - |OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO| | - |OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO| | - |OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO| | - y1 oOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOO| | - |OOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOO| | - |OOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOO| | PixelArraySize.height - ... ... ... ... ... | - ... ... ... ... ... | - |OOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOO| | - |OOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOO| | - +----------------------------------------------+ / - - then the invalid lines and columns should not be reported as part of the - PixelArraySize property in first place. - - In this case, the position of the black pixel rectangles will be - - PixelArrayOpticalBlackRectangles = { - { 0, 0, y1 + 1, PixelArraySize[0] }, - { 0, y1, 2, PixelArraySize[1] - y1 + 1 }, - { x1, y1, 2, PixelArraySize[1] - y1 + 1 }, - }; - - \todo Rename this property to Size once we will have property - categories (i.e. Properties::PixelArray::OpticalBlackRectangles) - - PixelArrayActiveAreas: type: Rectangle size: [n] From patchwork Fri Sep 18 09:10:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28335 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 8DE5EBE175 for ; Fri, 18 Sep 2026 09:19:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F0D616871F; Fri, 18 Sep 2026 11:19:01 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="W4eMk15R"; 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 5439E6849B for ; Fri, 18 Sep 2026 11:19:00 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6c1f:355d:1c19:aba6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 83DE94DC; Fri, 18 Sep 2026 11:17:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789723037; bh=6G1FHSgmDiGK6yTjn55rMwVIgyPxvQcr2e55jUtdClY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W4eMk15RethUl7p6D/9RI9Etqz+kAHWQwsJhAzRjWuBZ+KNUPMMv2K9hK68duVZVn zdd6S0lWJz+wE3vLj68eiE2xWiEX5oSBk5/dXQkAzByzE4uREx8YzO0KoXClnwBqlB BjVhYe1m8MWJNvRoixwX1QKfLldGlaF0n91HhjkM= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Paul Elder , Jacopo Mondi Subject: [PATCH v4 2/4] libcamera: Clarify meaning of PixelArraySize and other rectangles Date: Fri, 18 Sep 2026 11:10:49 +0200 Message-ID: <20260918091835.2332386-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918091835.2332386-1-stefan.klug@ideasonboard.com> References: <20260918091835.2332386-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" Current documented behavior for PixelArraySize is to report the readable array size of the sensor data. If the readable array is offset relative to the physical sensor array, all related rectangles (ScalerCrop, PixelArrayActiveAreas) shall be reported relative to PixelArraySize. However no known pipeline and IPA implements it that way. All pipelines/IPAs report PixelArrayActiveAreas relative to the physical size resulting in an inconsistent behaviour where the right border of the active area is outside of PixelArraySize. Adjust the documentation to fit the actual implementations. Add another property named PixelArrayReadableArea to convey the information that PixelArraySize was intended for. While at it, rename PixelArraySize to PixelArrayArea with the intention to get rid of the awkward wording "... is relative to the PixelArraySize rectangle" and to keep the door open to have a PixelArrayArea with a negative top left corner (although that is very unlikely). This has the added benefit that all rectangles are relative to the physical sensor array, which helps in aligning tuning data like lens shading correction. Using the active area to align tuning data had the downside that the offset of the active area relative to the physical pixel array was nowhere reported by libcamera and is a property that can change in different versions of a sensor driver. Relying on physical coordinates is expected to provide long-term stable absolute coordinates. To explain that a bit further, imagine a sensor driver was upstreamed with a single mode with a centered FullHD crop. Now the next version of the driver adds a centered 4:3 mode with the same width but taller as the old mode. The active area of the sensor now changed which would render polynomial lsc configuration from the tuning files useless as it gets evaluated relative to the active areai. Having lsc data relative to the physical pixel array solves this. Another benefit is that it makes it easier to mix data coming from libcamera with data coming from other sources like raw v4l2 tools, as the coordinate systems match. Signed-off-by: Stefan Klug Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- Changes in v4: - Renamed PixelArraySize to PixelArrayArea - Set readableArea in CameraSensorLegacy::initVimcDefaultProperties() Changes in v3: - Collected tag Changes in v2: - Fixed typos reported by Paul - Collected tag - Improved commit message - Updated docs based on Jacpos review - Added PixelArrayReadableArea to CameraSensorRaw - Improved PixelArraySize in CameraSensorRaw but left a todo --- src/android/camera_capabilities.cpp | 6 +- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 2 +- src/libcamera/property_ids_core.yaml | 109 ++++++++++-------- src/libcamera/sensor/camera_sensor_legacy.cpp | 34 ++++-- src/libcamera/sensor/camera_sensor_raw.cpp | 18 ++- 5 files changed, 102 insertions(+), 67 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 795abc2d037c..00976f969d16 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -1066,9 +1066,9 @@ int CameraCapabilities::initializeStaticMetadata() /* Sensor static metadata. */ std::array pixelArraySize; { - const Size &size = properties.get(properties::PixelArraySize).value_or(utils::defopt); - pixelArraySize[0] = size.width; - pixelArraySize[1] = size.height; + const Rectangle &area = properties.get(properties::PixelArrayArea).value_or(utils::defopt); + pixelArraySize[0] = area.width; + pixelArraySize[1] = area.height; staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize); } diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 4b09bd6e2f7c..ecd6baace05f 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -597,7 +597,7 @@ int UVCCameraData::init(std::shared_ptr media) properties_.set(properties::Location, location); - properties_.set(properties::PixelArraySize, resolution); + properties_.set(properties::PixelArrayArea, Rectangle(resolution)); properties_.set(properties::PixelArrayActiveAreas, { Rectangle(resolution) }); /* Initialise the supported controls. */ diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml index 96c7b55d8383..06348c62db2d 100644 --- a/src/libcamera/property_ids_core.yaml +++ b/src/libcamera/property_ids_core.yaml @@ -424,16 +424,30 @@ controls: The property can be used to calculate the physical size of the sensor's pixel array area and for calibration purposes. - - PixelArraySize: - type: Size + - PixelArrayArea: + type: Rectangle description: | - The camera sensor pixel array readable area vertical and horizontal - sizes, in pixels. + The camera sensor pixel array area, in pixels. - The PixelArraySize property defines the size in pixel units of the - readable part of full pixel array matrix, including optical black + The PixelArrayArea property defines the size in pixel units of the full + pixel array matrix including readable and non-readable pixels. The top + left corner of this rectangle is always at (0,0). For the largest + readable area \see PixelArrayReadableArea. + + All other properties that describe portions of the pixel array such as + PixelArrayActiveAreas and PixelArrayReadableArea are defined relative to + this rectangle. + + - PixelArrayReadableArea: + type: Rectangle + description: | + The camera sensor pixel array readable area. + + The PixelArrayReadableArea property defines the rectangle in pixel units + of the readable part of full pixel array matrix, including optical black pixels used for calibration, pixels which are not considered valid for - capture and active pixels containing valid image data. + capture and active pixels containing valid image data. It is defined + relative to the PixelArrayArea rectangle. The property describes the maximum size of the raw data captured by the camera, which might not correspond to the physical size of the sensor @@ -442,23 +456,25 @@ controls: For example, let's consider a pixel array matrix assembled as follows - +--------------------------------------------------+ - |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| - |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| + PixelArrayArea.width + /--------------------------------------------------/ + +--------------------------------------------------+ / + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| | + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | PixelArrayArea.height ... ... ... ... ... ... ... ... ... ... - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| - |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| - |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| - +--------------------------------------------------+ + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| | + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| | + +--------------------------------------------------+ / starting with two lines of non-readable pixels (x), followed by N lines of readable data (D) surrounded by two columns of non-readable pixels on @@ -467,35 +483,32 @@ controls: sizes of the largest possible buffer of raw data that can be presented to applications. - PixelArraySize.width - /----------------------------------------------/ - +----------------------------------------------+ / - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | PixelArraySize.height - ... ... ... ... ... - ... ... ... ... ... - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - |DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD| | - +----------------------------------------------+ / + PixelArrayReadableArea.width + /--------------------------------------------/ + PixelArrayReadableArea.x + +--o-----------------------------------------------+ + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| + oxxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| / PixelArrayReadableArea.y + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | PixelArrayReadableArea.height + ... ... ... ... ... - This defines a rectangle whose top-left corner is placed in position (0, - 0) and whose vertical and horizontal sizes are defined by this property. - All other rectangles that describe portions of the pixel array, such as - the optical black pixels rectangles and active pixel areas, are defined - relatively to this rectangle. + ... ... ... ... ... + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| | + |xxDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDxx| / + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| + |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| + +--------------------------------------------------+ All the coordinates are expressed relative to the default sensor readout direction, without any transformation (such as horizontal and vertical flipping) applied. When mapping them to the raw pixel buffer, applications shall take any configured transformation into account. - \todo Rename this property to Size once we will have property - categories (i.e. Properties::PixelArray::Size) - - PixelArrayActiveAreas: type: Rectangle size: [n] @@ -507,7 +520,7 @@ controls: This property describes an arbitrary number of overlapping rectangles, with each rectangle representing the maximum image size that the camera sensor can produce for a particular aspect ratio. They are defined - relatively to the PixelArraySize rectangle. + relative to the PixelArrayArea rectangle. When multiple rectangles are reported, they shall be ordered from the tallest to the shortest. @@ -519,13 +532,13 @@ controls: and/or applying pixel sub-sampling techniques such as pixel skipping or binning. - PixelArraySize.width + PixelArrayArea.width /----------------/ x1 x2 (0,0)-> +-o------------o-+ / y1 o +------------+ | | | |////////////| | | - | |////////////| | | PixelArraySize.height + | |////////////| | | PixelArrayArea.height | |////////////| | | y2 o +------------+ | | +----------------+ / @@ -539,14 +552,14 @@ controls: resolutions will report several overlapping rectangles, one for each natively supported resolution. - PixelArraySize.width + PixelArrayArea.width /------------------/ x1 x2 x3 x4 (0,0)-> +o---o------o---o+ / y1 o +------+ | | | |//////| | | y2 o+---+------+---+| | - ||///|//////|///|| | PixelArraySize.height + ||///|//////|///|| | PixelArrayArea.height y3 o+---+------+---+| | | |//////| | | y4 o +------+ | | diff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp index 83e2c2593215..f8d05487202c 100644 --- a/src/libcamera/sensor/camera_sensor_legacy.cpp +++ b/src/libcamera/sensor/camera_sensor_legacy.cpp @@ -131,7 +131,8 @@ private: std::vector testPatternModes_; controls::draft::TestPatternModeEnum testPatternMode_; - Size pixelArraySize_; + Rectangle pixelArrayArea_; + Rectangle readableArea_; Rectangle activeArea_; const BayerFormat *bayerFormat_; bool supportHFlips_; @@ -396,33 +397,40 @@ int CameraSensorLegacy::validateSensorDriver() * \todo Make support for selection targets mandatory as soon as all * test platforms have been updated. */ - Rectangle rect; - int ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_BOUNDS, &rect); + int ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_NATIVE_SIZE, &pixelArrayArea_); if (ret) { /* * Default the pixel array size to the largest size supported * by the sensor. The sizes_ vector is sorted in ascending * order, the largest size is thus the last element. */ - pixelArraySize_ = sizes_.back(); + pixelArrayArea_ = Rectangle(sizes_.back()); LOG(CameraSensor, Warning) - << "The PixelArraySize property has been defaulted to " - << pixelArraySize_; + << "The PixelArrayArea property has been defaulted to " + << pixelArrayArea_; + err = -EINVAL; + } + + ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_BOUNDS, &readableArea_); + if (ret) { + readableArea_ = pixelArrayArea_; + LOG(CameraSensor, Warning) + << "The PixelArrayReadableArea property has been defaulted to " + << readableArea_; err = -EINVAL; - } else { - pixelArraySize_ = rect.size(); } ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_DEFAULT, &activeArea_); if (ret) { - activeArea_ = Rectangle(pixelArraySize_); + activeArea_ = readableArea_; LOG(CameraSensor, Warning) << "The PixelArrayActiveAreas property has been defaulted to " << activeArea_; err = -EINVAL; } + Rectangle rect; ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP, &rect); if (ret) { LOG(CameraSensor, Warning) @@ -476,8 +484,9 @@ int CameraSensorLegacy::validateSensorDriver() void CameraSensorLegacy::initVimcDefaultProperties() { /* Use the largest supported size. */ - pixelArraySize_ = sizes_.back(); - activeArea_ = Rectangle(pixelArraySize_); + pixelArrayArea_ = Rectangle(sizes_.back()); + readableArea_ = pixelArrayArea_; + activeArea_ = pixelArrayArea_; } void CameraSensorLegacy::initStaticProperties() @@ -627,7 +636,8 @@ int CameraSensorLegacy::initProperties() mountingOrientation_ = Orientation::Rotate0; } - properties_.set(properties::PixelArraySize, pixelArraySize_); + properties_.set(properties::PixelArrayArea, pixelArrayArea_); + properties_.set(properties::PixelArrayReadableArea, readableArea_); properties_.set(properties::PixelArrayActiveAreas, { activeArea_ }); /* Color filter array pattern, register only for RAW sensors. */ diff --git a/src/libcamera/sensor/camera_sensor_raw.cpp b/src/libcamera/sensor/camera_sensor_raw.cpp index e50111f1d5c7..117da63ef364 100644 --- a/src/libcamera/sensor/camera_sensor_raw.cpp +++ b/src/libcamera/sensor/camera_sensor_raw.cpp @@ -141,7 +141,8 @@ private: std::vector testPatternModes_; controls::draft::TestPatternModeEnum testPatternMode_; - Size pixelArraySize_; + Rectangle pixelArrayArea_; + Rectangle readableArea_; Rectangle activeArea_; BayerFormat::Order cfaPattern_; bool supportHFlips_; @@ -431,7 +432,17 @@ std::optional CameraSensorRaw::init() return { ret }; } - pixelArraySize_ = rect.size(); + /* + * \todo Implement querying the physical sensor size based on pad 1, + * stream 0. See + * https://lore.kernel.org/linux-media/20260409201501.975242-23-sakari.ailus@linux.intel.com/ + */ + LOG(CameraSensor, Warning) << "PixelArrayArea might be incorrect"; + pixelArrayArea_ = Rectangle(0, 0, + rect.x + rect.width, + rect.y + rect.height); + + readableArea_ = rect; ret = subdev_->getSelection(streams_.image.sink, V4L2_SEL_TGT_CROP_DEFAULT, &activeArea_); @@ -634,7 +645,8 @@ int CameraSensorRaw::initProperties() mountingOrientation_ = Orientation::Rotate0; } - properties_.set(properties::PixelArraySize, pixelArraySize_); + properties_.set(properties::PixelArrayArea, pixelArrayArea_); + properties_.set(properties::PixelArrayReadableArea, readableArea_); properties_.set(properties::PixelArrayActiveAreas, { activeArea_ }); /* Color filter array pattern. */ From patchwork Fri Sep 18 09:10:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28336 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 7B8B6C3356 for ; Fri, 18 Sep 2026 09:19:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DF7EC68718; Fri, 18 Sep 2026 11:19:03 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gwtG5+pr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9C0E368702 for ; Fri, 18 Sep 2026 11:19:02 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6c1f:355d:1c19:aba6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A0832C23; Fri, 18 Sep 2026 11:17:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789723039; bh=vlhUCeThgFduav+ZPKVXHnNyxQIJmLDgsDKUU1A5MYw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gwtG5+prM+TdhGLUqNj6ETPJSP8rJORsXofg4vGg1cxl2zajkebCa/rOeWOsAA76j g8YCIm1wF53xn88ssP1Dvh9fBJiNmXy2T31hgIouO90XdqWH8rCVCGsQU4O2Rzddrn FehBkr6sHgZsuXmlotUF8+svqKSaYbJ0KydBPXfc= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Naushir Patuck , Jacopo Mondi , David Plowman Subject: [PATCH v4 3/4] libcamera: ipa: core: Use native coordinates for IPACameraSensorInfo::analogCrop Date: Fri, 18 Sep 2026 11:10:50 +0200 Message-ID: <20260918091835.2332386-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918091835.2332386-1-stefan.klug@ideasonboard.com> References: <20260918091835.2332386-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" Now that the camera properties use the physical pixel array as reference coordinate system, do the same with IPACameraSensorInfo::analogCrop. Replace IPACameraSensorInfo::activeAreaSize with IPACameraSensorInfo::activeArea to be able to keep the existing calculations. Co-developed-by: Naushir Patuck Signed-off-by: Naushir Patuck Signed-off-by: Stefan Klug Reviewed-by: Jacopo Mondi Reviewed-by: David Plowman --- Changes in v4: - Collected tag - Reformatted changes in the lsc.cpp files to be checkstyle compatible Changes in v3: - Prevent negative crops and issue a warning in the rpi ipa - Reflowed docs for IPACameraSensorInfo::analogCrop - Added a fix for a typo in an comment that showed up in the patch Changes in v2: - Moved all hunks related to IPACameraSensorInfo from the previous patch to this one - Fixed some missing documentation changes - Moved IPACameraSensorInfo::pixelArraySize to a separate patch - Pulled in changes by Naush - Kept the rkisp1 lsc logic. The related changes will come one top --- include/libcamera/ipa/core.mojom | 29 ++++++++++++------- src/ipa/mali-c55/algorithms/lsc.cpp | 11 ++++--- src/ipa/rkisp1/algorithms/lsc.cpp | 11 ++++--- src/ipa/rpi/common/ipa_base.cpp | 20 ++++++++++--- src/libcamera/sensor/camera_sensor_legacy.cpp | 19 +++--------- src/libcamera/sensor/camera_sensor_raw.cpp | 17 ++--------- 6 files changed, 51 insertions(+), 56 deletions(-) diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom index bce797245829..32ff25bbfc2b 100644 --- a/include/libcamera/ipa/core.mojom +++ b/include/libcamera/ipa/core.mojom @@ -153,21 +153,28 @@ module libcamera; */ /** - * \var IPACameraSensorInfo::activeAreaSize - * \brief The size of the pixel array active area of the sensor + * \var IPACameraSensorInfo::activeArea + * \brief The active pixel area of the sensor, relative to the physical pixel + * array + * + * The active area rectangle is expressed relative to the top-left corner of the + * physical pixel array. It describes the region of the pixel array which + * produces valid image data, excluding non-readable and optical black pixels. + * + * \note New IPA implementations should *not* use this property and instead rely + * on coordinates relative to the physical sensor array */ /** * \var IPACameraSensorInfo::analogCrop - * \brief The portion of the pixel array active area which is read-out and - * processed + * \brief The portion of the pixel array which is read-out and processed * - * The analog crop rectangle top-left corner is defined as the displacement - * from the top-left corner of the pixel array active area. The rectangle - * horizontal and vertical sizes define the portion of the pixel array which - * is read-out and provided to the sensor's internal processing pipeline, before - * any pixel sub-sampling method, such as pixel binning, skipping and averaging - * take place. + * The analog crop rectangle top-left corner is defined as the displacement from + * the top-left corner of the physical pixel array. The rectangle horizontal and + * vertical sizes define the portion of the pixel array which is read-out and + * provided to the sensor's internal processing pipeline, before any pixel + * sub-sampling method, such as pixel binning, skipping and averaging take + * place. */ /** @@ -243,7 +250,7 @@ struct IPACameraSensorInfo { uint32 bitsPerPixel; uint32 cfaPattern; - Size activeAreaSize; + Rectangle activeArea; Rectangle analogCrop; Size outputSize; diff --git a/src/ipa/mali-c55/algorithms/lsc.cpp b/src/ipa/mali-c55/algorithms/lsc.cpp index fff0dc7d0e64..a79d8c80fa9f 100644 --- a/src/ipa/mali-c55/algorithms/lsc.cpp +++ b/src/ipa/mali-c55/algorithms/lsc.cpp @@ -53,12 +53,11 @@ int Lsc::init(IPAContext &context, const ValueNode &tuningData) { gridPos_ = segmentsToPosition(); - return lscAlgo_.init(tuningData, context.ctrlMap, { - .keys = { "r", "g", "b" }, - .numHSamples = kMeshSize, - .numVSamples = kMeshSize, - .sensorSize = context.sensorInfo.activeAreaSize - }); + return lscAlgo_.init(tuningData, context.ctrlMap, + { .keys = { "r", "g", "b" }, + .numHSamples = kMeshSize, + .numVSamples = kMeshSize, + .sensorSize = context.sensorInfo.activeArea.size() }); } int Lsc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 36f9a344ed3b..7994ad111ba2 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -124,12 +124,11 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context, xPos_ = sizesListToPositions(xSize_); yPos_ = sizesListToPositions(ySize_); - return lscAlgo_.init(tuningData, context.ctrlMap, { - .keys = { "r", "gr", "gb", "b" }, - .numHSamples = RKISP1_CIF_ISP_LSC_SAMPLES_MAX, - .numVSamples = RKISP1_CIF_ISP_LSC_SAMPLES_MAX, - .sensorSize = context.sensorInfo.activeAreaSize - }); + return lscAlgo_.init(tuningData, context.ctrlMap, + { .keys = { "r", "gr", "gb", "b" }, + .numHSamples = RKISP1_CIF_ISP_LSC_SAMPLES_MAX, + .numVSamples = RKISP1_CIF_ISP_LSC_SAMPLES_MAX, + .sensorSize = context.sensorInfo.activeArea.size() }); } /** diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp index bc8e65cb0811..a5d149036a37 100644 --- a/src/ipa/rpi/common/ipa_base.cpp +++ b/src/ipa/rpi/common/ipa_base.cpp @@ -561,10 +561,22 @@ void IpaBase::setMode(const IPACameraSensorInfo &sensorInfo) mode_.bitdepth = sensorInfo.bitsPerPixel; mode_.width = sensorInfo.outputSize.width; mode_.height = sensorInfo.outputSize.height; - mode_.sensorWidth = sensorInfo.activeAreaSize.width; - mode_.sensorHeight = sensorInfo.activeAreaSize.height; - mode_.cropX = sensorInfo.analogCrop.x; - mode_.cropY = sensorInfo.analogCrop.y; + mode_.sensorWidth = sensorInfo.activeArea.width; + mode_.sensorHeight = sensorInfo.activeArea.height; + /* + * CameraMode::cropX/Y are defined relative to the active pixel area, + * whereas IPACameraSensorInfo::analogCrop is relative to the physical + * pixel array. Rebase the crop origin onto the active area. + */ + mode_.cropX = sensorInfo.analogCrop.x - std::min(sensorInfo.activeArea.x, + sensorInfo.analogCrop.x); + mode_.cropY = sensorInfo.analogCrop.y - std::min(sensorInfo.activeArea.y, + sensorInfo.analogCrop.y); + if (sensorInfo.analogCrop.x < sensorInfo.activeArea.x || + sensorInfo.analogCrop.y < sensorInfo.activeArea.y) { + LOG(IPARPI, Warning) << "Analog crop lies outside the active area." + << " This can result in image artifacts."; + } mode_.pixelRate = sensorInfo.pixelRate; /* diff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp index f8d05487202c..62f346aa06df 100644 --- a/src/libcamera/sensor/camera_sensor_legacy.cpp +++ b/src/libcamera/sensor/camera_sensor_legacy.cpp @@ -888,14 +888,13 @@ int CameraSensorLegacy::sensorInfo(IPACameraSensorInfo *info) const info->model = model(); /* - * The active area size is a static property, while the crop - * rectangle needs to be re-read as it depends on the sensor - * configuration. + * The active area is a static property, while the crop rectangle needs + * to be re-read as it depends on the sensor configuration. */ - info->activeAreaSize = { activeArea_.width, activeArea_.height }; + info->activeArea = activeArea_; /* - * \todo Support for retreiving the crop rectangle is scheduled to + * \todo Support for retrieving the crop rectangle is scheduled to * become mandatory. For the time being use the default value if it has * been initialized at sensor driver validation time. */ @@ -906,16 +905,6 @@ int CameraSensorLegacy::sensorInfo(IPACameraSensorInfo *info) const << "The analogue crop rectangle has been defaulted to the active area size"; } - /* - * IPACameraSensorInfo::analogCrop::x and IPACameraSensorInfo::analogCrop::y - * are defined relatively to the active pixel area, while V4L2's - * TGT_CROP target is defined in respect to the full pixel array. - * - * Compensate it by subtracting the active area offset. - */ - info->analogCrop.x -= activeArea_.x; - info->analogCrop.y -= activeArea_.y; - /* The bit depth and image size depend on the currently applied format. */ V4L2SubdeviceFormat format{}; ret = subdev_->getFormat(pad_, &format); diff --git a/src/libcamera/sensor/camera_sensor_raw.cpp b/src/libcamera/sensor/camera_sensor_raw.cpp index 117da63ef364..940e7514ae93 100644 --- a/src/libcamera/sensor/camera_sensor_raw.cpp +++ b/src/libcamera/sensor/camera_sensor_raw.cpp @@ -1009,27 +1009,16 @@ int CameraSensorRaw::sensorInfo(IPACameraSensorInfo *info) const info->model = model(); /* - * The active area size is a static property, while the crop - * rectangle needs to be re-read as it depends on the sensor - * configuration. + * The active area is a static property, while the crop rectangle needs + * to be re-read as it depends on the sensor configuration. */ - info->activeAreaSize = { activeArea_.width, activeArea_.height }; + info->activeArea = activeArea_; int ret = subdev_->getSelection(streams_.image.sink, V4L2_SEL_TGT_CROP, &info->analogCrop); if (ret) return ret; - /* - * IPACameraSensorInfo::analogCrop::x and IPACameraSensorInfo::analogCrop::y - * are defined relatively to the active pixel area, while V4L2's - * TGT_CROP target is defined in respect to the full pixel array. - * - * Compensate it by subtracting the active area offset. - */ - info->analogCrop.x -= activeArea_.x; - info->analogCrop.y -= activeArea_.y; - /* The bit depth and image size depend on the currently applied format. */ V4L2SubdeviceFormat format{}; ret = subdev_->getFormat(streams_.image.source, &format); From patchwork Fri Sep 18 09:10:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28337 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 690CCC3357 for ; Fri, 18 Sep 2026 09:19:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C1EE668725; Fri, 18 Sep 2026 11:19:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="RV4dc0gP"; 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 224C668702 for ; Fri, 18 Sep 2026 11:19:05 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6c1f:355d:1c19:aba6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5A6E8C6A; Fri, 18 Sep 2026 11:17:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789723042; bh=k9oVCCxtlSjAwm9LKTrYfGLSajdbBjAJjzTS2KDu98Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RV4dc0gPEYNUln/QaCnKfEg8B+gnwLngOdNGlHt8ZOtv838oAK96gxduzDffgMl3b Dwm8iCBtk3GGPjKm4EUYgZVZJ+Vs31I8E11UrdWNm0rWb3/e8QkRqLKJAoRtVZbCX5 UUgyvF3S39F+KDt0V1hV6pqbmVD06vFkdsU0OMX0= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Jacopo Mondi Subject: [PATCH v4 4/4] libcamera: ipa: core: Add IPACameraSensorInfo::pixelArrayArea property Date: Fri, 18 Sep 2026 11:10:51 +0200 Message-ID: <20260918091835.2332386-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918091835.2332386-1-stefan.klug@ideasonboard.com> References: <20260918091835.2332386-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" Add a IPACameraSensorInfo::pixelArrayArea property to communicate the full area of the pixel array to the IPA. This property is not used today but will be useful to do sanity checks on coordinates handled in the algorithms. Signed-off-by: Stefan Klug Reviewed-by: Jacopo Mondi --- Changes in v4: - switch from pixelArraySize to pixelArrayArea Changes in v3: - Collected tag --- include/libcamera/ipa/core.mojom | 8 ++++++++ src/libcamera/sensor/camera_sensor_legacy.cpp | 1 + src/libcamera/sensor/camera_sensor_raw.cpp | 1 + 3 files changed, 10 insertions(+) diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom index 32ff25bbfc2b..5ff3d79c4366 100644 --- a/include/libcamera/ipa/core.mojom +++ b/include/libcamera/ipa/core.mojom @@ -152,6 +152,13 @@ module libcamera; * RGB for sensors that don't have a CFA. */ +/** + * \var IPACameraSensorInfo::pixelArrayArea + * \brief The area of the physical pixel array of the sensor in pixels + * + * The top left corner of this rectangle is always at (0,0). + */ + /** * \var IPACameraSensorInfo::activeArea * \brief The active pixel area of the sensor, relative to the physical pixel @@ -250,6 +257,7 @@ struct IPACameraSensorInfo { uint32 bitsPerPixel; uint32 cfaPattern; + Rectangle pixelArrayArea; Rectangle activeArea; Rectangle analogCrop; Size outputSize; diff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp index 62f346aa06df..bbe3f2e8fc7d 100644 --- a/src/libcamera/sensor/camera_sensor_legacy.cpp +++ b/src/libcamera/sensor/camera_sensor_legacy.cpp @@ -886,6 +886,7 @@ int CameraSensorLegacy::sensorInfo(IPACameraSensorInfo *info) const return -EINVAL; info->model = model(); + info->pixelArrayArea = pixelArrayArea_; /* * The active area is a static property, while the crop rectangle needs diff --git a/src/libcamera/sensor/camera_sensor_raw.cpp b/src/libcamera/sensor/camera_sensor_raw.cpp index 940e7514ae93..389b9ddfe19f 100644 --- a/src/libcamera/sensor/camera_sensor_raw.cpp +++ b/src/libcamera/sensor/camera_sensor_raw.cpp @@ -1007,6 +1007,7 @@ int CameraSensorRaw::setEmbeddedDataEnabled(bool enable) int CameraSensorRaw::sensorInfo(IPACameraSensorInfo *info) const { info->model = model(); + info->pixelArrayArea = pixelArrayArea_; /* * The active area is a static property, while the crop rectangle needs