From patchwork Tue Sep 29 16:39:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9864 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 87EEFC3B5B for ; Tue, 29 Sep 2020 16:40:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 55C4C621FC; Tue, 29 Sep 2020 18:40:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="VgVJ1x/w"; dkim-atps=neutral Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3405B60BD3 for ; Tue, 29 Sep 2020 18:40:06 +0200 (CEST) Received: by mail-wr1-x444.google.com with SMTP id k15so6137541wrn.10 for ; Tue, 29 Sep 2020 09:40:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rK6TJchWCNdtebZ+uvmNEKNtyULDOcjn0Q2lyYeXKa4=; b=VgVJ1x/w5rLBjaMKOqacTu0WOh4HJayHQkdlwmwnx7K0BBlH2+xcW9Ce8fvYsr2Yyb wDpk/cbVrFse/FfS8l6VxGxPIOdj7YhXKU87R9o7Gg0cMxUn2UPQfB8p3pSUm5XgvbXa Flmm0muYiFnVsdma97VUeGHD+jANFZ+aiBGMocsY/Xw/Wok/Hv8dMdXjrXu2ZnGm7pXt 6rpU5f9XMCuPd3u64lmkBbPe/QwNgHIcgWS5J55lqhBqsmWF27Em494t5aBelWClrfBT YDjUZ9jrIFPMxWXK9dHKVY5UA/+hnSO80fuSfalrAuZ/Sk9Q+nX9eCHT6PNCSJkniw9y iTDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rK6TJchWCNdtebZ+uvmNEKNtyULDOcjn0Q2lyYeXKa4=; b=pMUcTmGPWKSchDXLlzK2VanN/4zNfuss2MHiBdWkE/INz0uyA7b8sHUqVLSeP5jj0R sm4Lavbn2B8uZJtmJz9du1zZ7c+txtIMxMWKHlEI0svlyOsBzo6ucxohng9GbOelVVLO ukMmRLYGs1TwCEiK671dwkbIdQ8dCdaIRJJuYH3YUuo8V2bm7CykHbRGR5hPz/Qt/nCY QQ2SlCvlGfkzxJCRNj/PEgYDPBG8KCuWTGsRt4UdJJ88BkBCtOIvBcWMttS3gjH3/qzt q0lIBXP17jXRgY2PId0IHQ2oZMbrb7Sxq6dQw4puLXH4NO9XfeLvHnqhhlj0oSBgDexs pGPQ== X-Gm-Message-State: AOAM532pyn/TYiRnLhkg07OavyluO1eToFbRQ8ik95P/2TGPp05/EyPs N5d31JRCFK0JLQ1j2GkgjtG03sDgRLM9EA== X-Google-Smtp-Source: ABdhPJxhBUXxeKnClCdnKAsEeX8FZ0k0Ci9EIKURXP7H/4RarCXD3Ncqpbi6uVqnNvTA7NZzZ+/uDg== X-Received: by 2002:a5d:4f82:: with SMTP id d2mr5277783wru.65.1601397605542; Tue, 29 Sep 2020 09:40:05 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:04 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:39:55 +0100 Message-Id: <20200929164000.15429-2-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/6] libcamera: Add SensorOutputSize property 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 SensorOutputSize camera property reports the image size that the next step in processing after the sensor and CSI-2 receiver - usually the ISP - will see. It will normally change when a new camera mode is selected, and can be used to implement digital zoom. Signed-off-by: David Plowman Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/property_ids.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index 74ad0195..8011b88c 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -640,4 +640,23 @@ controls: \todo Rename this property to ActiveAreas once we will have property categories (i.e. Properties::PixelArray::ActiveAreas) + - SensorOutputSize: + type: Size + description: | + The size, in pixels, of the image being used to produce the + desired output streams. The image size might correspond to the + size of the frames produced by the image sensor but would also + take into account additional cropping (or even re-scaling) + performed by the CSI-2 receiver to adjust the sensor frame + size to conform to the output image sizes and aspect ratios. + The property is meaningful only after the Camera has been + successfully configured and its value changes whenever a new + configuration is applied. It can be used to implement digital + zoom. + + \sa controls::ISPCrop + + \todo Move this property to CameraConfiguration once the + feature is made available + ... From patchwork Tue Sep 29 16:39:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9865 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 508D0C3B5B for ; Tue, 29 Sep 2020 16:40:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D2DEC621D4; Tue, 29 Sep 2020 18:40:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="S6wQbgQ2"; dkim-atps=neutral Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 24F95621DA for ; Tue, 29 Sep 2020 18:40:07 +0200 (CEST) Received: by mail-wr1-x442.google.com with SMTP id s12so6127962wrw.11 for ; Tue, 29 Sep 2020 09:40:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UHcAEvjMSMHLSIvS9uZ3RdWwkxfjBYL70NVjYWLjY38=; b=S6wQbgQ2eO4EEY8198pr9znjyVhVJVYINwjV8jZLgQxm6pA/bm+Rcnr466ycVuXTkq evtseh7DnjKUU8tLQfG+Dj8/HIiHY9TJwWPzAzRliaLuaj/hEoJpmbUbGEqbdWKXatOr RPXWOSpXNdxQjNju6OU/SPV6NdBw9JW6Qljm7HRt/AIPro6ezJq9e1e+G9oRNS9teYfa OfqqtGFTR0yuNG80q7Hk1nBUuaWk5QaQQJecPwQW3Xp6e9HyqFiRMC5lRddbJrKJHxug OEqczTIAC867EphXubVbGOdiHnMN5AHt5CFoLSaZ6bMWlbusrHHsMUtOZikaK7KrmP52 g+TQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UHcAEvjMSMHLSIvS9uZ3RdWwkxfjBYL70NVjYWLjY38=; b=L9Vo6fXjsTSgJyo+pKthbsUQqTFCUXeNRkcm7fMAdkVhFSsYk3S5uRHWC0rZhd57en 9+yi4flFCg9Sr67mr1E3YUyIoA1rD+cbFKrlAdo19v1Uq1FvKeWCG33fHTLK0uLMIQ+R OI6S2eiMg04d4O1m/3X5dRFocXVBnH5HLeUHLFBM1artl0/vvwikP1G4LZ45WeEEtbrZ a3rbKmAZlkulxeqTzuX1r2ziZst8P5b6Ona56rcCmRO+Z3wl34Kki+aoolJRFfnNZgmi zWcMwCj7ePol/DkbzBUasyBhcnaAbN6g3LgBJfPrPbBtFp9jO9lhPDogz0iOMveKg+gw w5nA== X-Gm-Message-State: AOAM533hKUlzHUmSLWud9KWYvD3tdT7/KRS7vWes9GDPPpE2gvt/cD0h 8iQuu7XqY19W1lVBzqkvzP4Psw2J+0O0+A== X-Google-Smtp-Source: ABdhPJzdkpBGw7dxIcgwsT5ph3DnPirE5948LQrMFohhZm8dipfKzYIdRSThNoAZeJAPktd2G/+n8A== X-Received: by 2002:adf:e802:: with SMTP id o2mr5242799wrm.309.1601397606523; Tue, 29 Sep 2020 09:40:06 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:05 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:39:56 +0100 Message-Id: <20200929164000.15429-3-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/6] libcamera: Initialise the SensorOutputSize property 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 default initialisation according to the sensor resolution, though it will need updating when the camera mode changes. Signed-off-by: David Plowman Reviewed-by: Jacopo Mondi --- src/libcamera/camera_sensor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index d2679a4b..c9a19b02 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -277,6 +277,12 @@ int CameraSensor::init() */ resolution_ = sizes_.back(); + /* + * Set a default value for the SensorOutputSize, though it will have to + * be updated when new camera modes are chosen. + */ + properties_.set(properties::SensorOutputSize, resolution_); + return 0; } From patchwork Tue Sep 29 16:39:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9866 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 09513C3B5B for ; Tue, 29 Sep 2020 16:40:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9DC6C621F1; Tue, 29 Sep 2020 18:40:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="QhEAzrnn"; dkim-atps=neutral Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D45FA60BD3 for ; Tue, 29 Sep 2020 18:40:07 +0200 (CEST) Received: by mail-wr1-x444.google.com with SMTP id m6so6196498wrn.0 for ; Tue, 29 Sep 2020 09:40:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/leO2kIIvDQeQWWXnaPMsfkqUL7f0ewPekfAGiaUNTY=; b=QhEAzrnnP4gu0fwDhxVL9lHwwPJk0OxUD4LSFbYOxGT22M1N2XX7/YlQjdN5eskzYd unVRlr6UVRUrNZso0QB6apJF7LByvIkzNmx3/EVwmpsn1GikD3l/5AITL0c54ijm5eyT MM0WQWhXcFxDM1TVRQi5u7aGY3ohDSCVfFta2dnzl/qGenuRBSKoh5eqfCkaiMlmb2Mi PKALkGYRRdE8znWiO0lZ+XunFVruiTKSmE5dStv7mewmqDlqPNfX70ovXGc5x8MZYHKu i+bSnHBLWLHcdTcKRo2twAwwXQ7+NezmV+2ehKQtFWLMwMtAN6DD1MgonkoRtszf0fks 0WIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/leO2kIIvDQeQWWXnaPMsfkqUL7f0ewPekfAGiaUNTY=; b=WMGgGwNHvmpfp52bbRp3QEb1i5jz/BuF5OpS9A10bnUJbb0ZsqdrUqFOcBZ1sXvprl 59fqpwQ6bLxPQ9KMyhlxqiHrE9t8dO/OD804qJNRUSI28c3so/p2GBGlWvPEggyWeQAs r7pr7qty8tU/W4Kk2ouiQXAHVbvKM3P5pHpqqwjuUPOaiIThDcf//U0qOlNhl7WTU56n re4i/nyRKB1UwirIIT8krrhc3gKyoWqtx+SoTyqwW3h0ihi/tG3Q9gQRQ+76sn5eR8K0 V2StdbsFFZRsuNGjIyqTTZF0w89DNiTtUkSGsYIGupx6jQxCULYenKs5og/oZtzrzJ1I 2Cag== X-Gm-Message-State: AOAM531PZBJSvH4q95LTi0g4jnRm3R92Av3PW8AJWsYJ41jzQQbtnTca 8Qy1idbORoo1a0sau3nH+2ckIOYxqQfcpQ== X-Google-Smtp-Source: ABdhPJwvYguy3r+pSwjXRuuTpG7nKcBq5squGv1opK5FB4sjAVhbNgFpvY/0ITdadXejUlT+uaLgdA== X-Received: by 2002:adf:ec92:: with SMTP id z18mr5692652wrn.53.1601397607396; Tue, 29 Sep 2020 09:40:07 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:06 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:39:57 +0100 Message-Id: <20200929164000.15429-4-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/6] libcamera: Add IspCrop control 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 IspCrop control selects how much of the sensor's output image will be scaled to form the output image. It can be used to implement digital zoom. Signed-off-by: David Plowman Reviewed-by: Kieran Bingham --- src/libcamera/control_ids.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml index 3560d4a8..46a4bd94 100644 --- a/src/libcamera/control_ids.yaml +++ b/src/libcamera/control_ids.yaml @@ -273,4 +273,16 @@ controls: order in an array of 9 floating point values. size: [3x3] + + - IspCrop: + type: Rectangle + description: | + Sets the image portion that will be scaled up to form the + whole of the final output image. The selection rectangle is + expressed in pixel units and defined relatively to the size + of the frame described by the SensorOutputSize property. + + This control can be used to implement digital zoom. + + \sa properties::SensorOutputSize ... From patchwork Tue Sep 29 16:39:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9867 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 D8100C3B5B for ; Tue, 29 Sep 2020 16:40:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A4B2B62213; Tue, 29 Sep 2020 18:40:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="HBTX5fo+"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F2956621C2 for ; Tue, 29 Sep 2020 18:40:08 +0200 (CEST) Received: by mail-wr1-x436.google.com with SMTP id x14so6134561wrl.12 for ; Tue, 29 Sep 2020 09:40:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g9k5si71vIidZueH7m+O0H4368v3VtJ6f9kU5NAWJuA=; b=HBTX5fo+tjgVv6NRC9kOVzeHgt+mB+UqwN52MVjqrw857mzx02bVWWetMDKKmcGxm2 hxtxFWVSiTS+RJSkIo8BBZygZ2ut/ormxKZylq/3R8lG6AzLiL3BXIVO4SOOZTGBNTcl GQVYnsuyL11O5EDeB8JxOpFaSQFI4Q4fBUIumquZUtfbKzNs/WxOAhXkKJnRcEJTX8TH z/VddfaQ3kxAySN4T19u0kVmonwi2X2710D3pRJuci6TxBXVvKKKkpy1UYwUQjbb6qQI HXR7ZRYMLMKwgn+op5ygvYD9V9XwO+O1nOvRSwam9zQv2R4LJRwQ29sQMhQO5+4lld+R w+Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g9k5si71vIidZueH7m+O0H4368v3VtJ6f9kU5NAWJuA=; b=cyRjiMV75BDvOXlKsLYhlU+Dp5xlHCBqw2/DgQ6YnjxPOrbTF2+9JIrFA4Cob7xR+c o7oFRhJvZc6q0nGp42cmqbEon6qFbI193z6lKuGZxqFe/zKwSW1k/9k9Y6nuko2jPewb +ud2aZOO4hzEIHKNN3FjrGJbeaHwqVD5a/RZSesaeYdy/ysDyBQCYXAnnCV7k/yrx4U6 RUk0GCKLcjsv30VJ1Nv4EpE0OTqvb1Y/glsjO2zopLuRauIXsM19HUnpIxOR7hzj5DSj TmMGZTijXdPrvVDw0y0b27Yd/TOiMFYUM8WAVJiOKcZIpxWwptnUbE9cBTgamra8M34A nN5g== X-Gm-Message-State: AOAM531WcW6XGSAhWjb9LdjY26rWNm+yP0y3/5wBSObz1H4XGVMgxbK1 7ueycyfP7r+2oCW8p66enc+p51XfqQDVjA== X-Google-Smtp-Source: ABdhPJzVl4LGEGQegwf+bOMrTBL24ei5OWagthEHRR4f/CUN0U5ZEMdoxi+XcXYuozSTNB2FG7fbeQ== X-Received: by 2002:adf:e58b:: with SMTP id l11mr5680562wrm.210.1601397608272; Tue, 29 Sep 2020 09:40:08 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:07 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:39:58 +0100 Message-Id: <20200929164000.15429-5-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 4/6] libcamera: Add geometry helper functions 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" These functions are aimed at making it easier to calculate cropping rectangles, particularly in order to implement digital zoom. Signed-off-by: David Plowman Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/geometry.h | 20 ++++++ src/libcamera/geometry.cpp | 129 +++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h index 02fb63c0..0447ee3e 100644 --- a/include/libcamera/geometry.h +++ b/include/libcamera/geometry.h @@ -13,6 +13,8 @@ namespace libcamera { +class Rectangle; + class Size { public: @@ -93,8 +95,17 @@ public: std::max(height, expand.height) }; } + + Size alignedDownToAspectRatio(const Size &ratio) const; + Size alignedUpToAspectRatio(const Size &ratio) const; + + Rectangle centredTo(const Rectangle ®ion, + int offsetX = 0, int offsetY = 0) const; }; +Size operator*(const Size &size, float f); +Size operator/(const Size &size, float f); + bool operator==(const Size &lhs, const Size &rhs); bool operator<(const Size &lhs, const Size &rhs); @@ -176,6 +187,11 @@ public: { } + constexpr explicit Rectangle(const Size &size) + : x(0), y(0), width(size.width), height(size.height) + { + } + int x; int y; unsigned int width; @@ -183,6 +199,10 @@ public: bool isNull() const { return !width && !height; } const std::string toString() const; + + Size size() const; + + Rectangle boundedTo(const Rectangle &boundary) const; }; bool operator==(const Rectangle &lhs, const Rectangle &rhs); diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp index b12e1a62..649ee179 100644 --- a/src/libcamera/geometry.cpp +++ b/src/libcamera/geometry.cpp @@ -143,6 +143,88 @@ const std::string Size::toString() const * height of this size and the \a expand size */ +/** + * \brief Align down to the aspect ratio given by \a ratio + * \param[in] ratio The size whose aspect ratio to align down to + * \return A Size whose width and height are equal to the width and height + * of this Size aligned down to the aspect ratio of \a ratio + */ +Size Size::alignedDownToAspectRatio(const Size &ratio) const +{ + uint64_t ratio1 = static_cast(width) * + static_cast(ratio.height); + uint64_t ratio2 = static_cast(ratio.width) * + static_cast(height); + + if (ratio1 > ratio2) + return { static_cast(ratio2 / ratio.height), height }; + else + return { width, static_cast(ratio1 / ratio.width) }; +} + +/** + * \brief Align up to the aspect ratio given by \a ratio + * \param[in] ratio The size whose aspect ratio to align up to + * \return A Size whose width and height are equal to the width and height + * of this Size aligned up to the aspect ratio of \a ratio + */ +Size Size::alignedUpToAspectRatio(const Size &ratio) const +{ + uint64_t ratio1 = static_cast(width) * + static_cast(ratio.height); + uint64_t ratio2 = static_cast(ratio.width) * + static_cast(height); + + if (ratio1 < ratio2) + return { static_cast(ratio2 / ratio.height), height }; + else + return { width, static_cast(ratio1 / ratio.width) }; +} + +/** + * \brief Centre a rectangle of this size within another rectangular region, + * with optional offsets + * \param[in] region The rectangular region relative to which the returned + * rectangle can be position + * \param[in] offsetX The X offset of the mid-point of the returned rectangle + * relative to the mid-point of the region + * \param[in] offsetY The Y offset of the mid-point of the returned rectangle + * relative to the mid-point of the region + * + * A Rectangle of this object's size is positioned within the Rectangle + * given by \a region. It is positioned so that its mid-point coincides + * with the mid-point of \a region, and is then further offset by the + * values \a offsetX and \a offsetY. + * + * \return A Rectangle with the horizontal and vertical sizes of + * this Size instance, centred with offsets within a region + */ +Rectangle Size::centredTo(const Rectangle ®ion, int offsetX, int offsetY) const +{ + int x = (region.width - width) / 2 + region.x + offsetX; + int y = (region.height - height) / 2 + region.y + offsetY; + + return Rectangle(x, y, width, height); +} + +/** + * \brief Scale size up by the given factor + * \return The scaled Size + */ +Size operator*(const Size &size, float f) +{ + return Size(size.width * f, size.height * f); +} + +/** + * \brief Scale size down by the given factor + * \return The scaled Size + */ +Size operator/(const Size &size, float f) +{ + return Size(size.width / f, size.height / f); +} + /** * \brief Compare sizes for equality * \return True if the two sizes are equal, false otherwise @@ -365,6 +447,12 @@ bool operator==(const SizeRange &lhs, const SizeRange &rhs) * \param[in] height The height */ +/** + * \fn Rectangle::Rectangle(const Size &size) + * \brief Construct a Rectangle with zero offsets and the given \a size + * \param[in] size The desired Rectangle size + */ + /** * \var Rectangle::x * \brief The horizontal coordinate of the rectangle's top-left corner @@ -404,6 +492,47 @@ const std::string Rectangle::toString() const return ss.str(); } +/** + * \brief Retrieve the size of this rectangle + * \return A Size reporting the Rectangle horizontal and vertical sizes + */ +Size Rectangle::size() const +{ + return Size(width, height); +} + +/** + * \brief Bound a Rectangle so as not to exceeed another Rectangle + * \param[in] boundary The limit that the returned Rectangle will not exceed + * + * The Rectangle is bounded so that it does not exceeed the given \a boundary. + * This process involves translating the Rectangle if any of its edges + * lie beyond \a boundary, so that those edges then lie along the boundary + * instead. + * + * If either width or height are larger than \a bounary, then the returned + * Rectangle is clipped to be no larger. But other than this, the + * Rectangle is not clipped or reduced in size, merely translated. + * + * We note that this is not a conventional Rectangle intersection function. + * + * \return A Rectangle that does not extend beyond a boundary Rectangle + */ +Rectangle Rectangle::boundedTo(const Rectangle &boundary) const +{ + Rectangle result(*this); + + result.width = std::min(result.width, boundary.width); + result.x = std::clamp(result.x, boundary.x, + boundary.x + boundary.width - result.width); + + result.height = std::min(result.height, boundary.height); + result.y = std::clamp(result.y, boundary.y, + boundary.y + boundary.height - result.height); + + return result; +} + /** * \brief Compare rectangles for equality * \return True if the two rectangles are equal, false otherwise From patchwork Tue Sep 29 16:39:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9868 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 5510CC3B5B for ; Tue, 29 Sep 2020 16:40:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0AF086221D; Tue, 29 Sep 2020 18:40:14 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="Uck40433"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 02143621EA for ; Tue, 29 Sep 2020 18:40:10 +0200 (CEST) Received: by mail-wr1-x436.google.com with SMTP id k10so6162206wru.6 for ; Tue, 29 Sep 2020 09:40:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=U07BFgIs43AOzvJHddqiQga4NTJKjxfhWxvHzgV1B3M=; b=Uck40433/9a5V1F/Es2ZnjVSef7VdeseZ2ALqCgFm76A7klfLwlN2v3cXh2dW8dIrI QMALrQePc/1vlZyN3Jsq+Y73BsNvVmO5ms3RLns+7gZB2j0IPvX+Sh/7yq1JCtzfWU9+ haTQW3ww5pSm6qqE1zv1l7CGv6ENumQGILtko8u9HhJMXOnoJgguyxlVhUUhZKPTOZtp 250MuFaQ1/gX/bxqr+Sxi3XiVns4SnlVkB7vS5JqfWK6ER8DEipYkihrx02mc2DXc0P0 07Yt/0PwOuL+AnBL6GqVSV6kUOJQmz7Zs9eqUuVfUYr+9On8UzXAx2ensUALz+7aVsbK tnzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=U07BFgIs43AOzvJHddqiQga4NTJKjxfhWxvHzgV1B3M=; b=q2wHZvB/EcMMIz8gDq4PGDCyuDIPdtTVedQdCG6OYGxteevlCkmmbKcBjYO40GXqM0 qwnn8Z+yD8EspxSUjJ3ACkqFkqfydgKAAbVFKXLgvQrQ3nLqZ6jJc59A1RnJzBY4kQlp Hiz/eg8X4hxygTvIaIDMyX4v6zOquvfRTCmCn0/I0AuZ4RGjciWfkdb7egnRSRTKFO4J ZiaLntfhsp0QZYmH+GAdEIx8XmMS2tx1HovFbXwC+2n+XD3vKdPHkjFjrh9i9NwzGPh0 Zxmb8n9K+ER50A5AG4PQyIBlXxDRHTyPzPp5559qPKLF+XHS3CeWNhQ6hKDxeADYLCNg IRBw== X-Gm-Message-State: AOAM530kpsmU3vZ0abkQbjtFtvzWtr3hlbhS6fT6UpvDou/2CDDdKblV e373sM0QIera9PjiGk6guTusfZt0gDPyfA== X-Google-Smtp-Source: ABdhPJz4DfhL36AfbjDrbvYaeaV1n6+rtyx9ZJ95NldnIHx8qXLNqBW4O04JRQGLL8BJh0kQWoMX/w== X-Received: by 2002:adf:f34f:: with SMTP id e15mr5092303wrp.387.1601397609303; Tue, 29 Sep 2020 09:40:09 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:08 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:39:59 +0100 Message-Id: <20200929164000.15429-6-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: raspberrypi: Implementation of digital zoom 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" During configure() we update the SensorOutputSize to the correct value for this camera mode (which we also note internally) and work out the minimum crop size allowed by the ISP. Whenever a new IspCrop request is received we check it's valid and apply it to the ISP V4L2 device. We also forward it to the IPA so that the IPA can return the values used in the image metadata. Signed-off-by: David Plowman Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/ipa/raspberrypi.h | 1 + src/ipa/raspberrypi/raspberrypi.cpp | 7 +++ .../pipeline/raspberrypi/raspberrypi.cpp | 47 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h index b3041591..9ef5f6fc 100644 --- a/include/libcamera/ipa/raspberrypi.h +++ b/include/libcamera/ipa/raspberrypi.h @@ -60,6 +60,7 @@ static const ControlInfoMap Controls = { { &controls::Saturation, ControlInfo(0.0f, 32.0f) }, { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) }, { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) }, + { &controls::IspCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) }, }; } /* namespace RPi */ diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index b0c7d1c1..dc73c20b 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -699,6 +699,13 @@ void IPARPi::queueRequest(const ControlList &controls) break; } + case controls::ISP_CROP: { + /* Just copy the information back. */ + Rectangle crop = ctrl.second.get(); + libcameraMetadata_.set(controls::IspCrop, crop); + break; + } + default: LOG(IPARPI, Warning) << "Ctrl " << controls::controls.at(ctrl.first)->name() diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index d2bee150..4a6d0bf4 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -193,6 +193,11 @@ public: bool flipsAlterBayerOrder_; BayerFormat::Order nativeBayerOrder_; + /* For handling digital zoom. */ + Size ispMinSize_; + Size sensorOutputSize_; + Rectangle lastIspCrop_; + unsigned int dropFrameCount_; private: @@ -587,6 +592,14 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) */ ret = data->isp_[Isp::Input].dev()->setFormat(&sensorFormat); + /* + * Update the SensorOutputSize to the correct value for this camera mode. + * + * \todo Move this property to CameraConfiguration when that + * feature will be made available and set it at validate() time + */ + data->properties_.set(properties::SensorOutputSize, sensorFormat.size); + /* * See which streams are requested, and route the user * StreamConfiguration appropriately. @@ -677,6 +690,16 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) return ret; } + /* + * Figure out the smallest selection the ISP will allow. We also store + * the output image size, in pixels, from the sensor. These will be + * used for digital zoom. + */ + Rectangle testCrop(0, 0, 1, 1); + data->isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &testCrop); + data->ispMinSize_ = testCrop.size(); + data->sensorOutputSize_ = sensorFormat.size; + /* Adjust aspect ratio by providing crops on the input image. */ Rectangle crop{ 0, 0, sensorFormat.size }; @@ -693,6 +716,8 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) crop.y = (sensorFormat.size.height - crop.height) >> 1; data->isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &crop); + data->lastIspCrop_ = crop; + ret = data->configureIPA(config); if (ret) LOG(RPI, Error) << "Failed to configure the IPA: " << ret; @@ -1588,6 +1613,28 @@ void RPiCameraData::tryRunPipeline() /* Take the first request from the queue and action the IPA. */ Request *request = requestQueue_.front(); + if (request->controls().contains(controls::IspCrop)) { + Rectangle crop = request->controls().get(controls::IspCrop); + if (crop.width && crop.height) { + /* + * The crop that we set must be: + * 1. At least as big as ispMinSize_, once that's been + * enlarged to the same aspect ratio. + * 2. With the same mid-point, if possible. + * 3. But it can't go outside the sensor area. + */ + Size minSize = ispMinSize_.alignedUpToAspectRatio(crop.size()); + Size size = crop.size().expandedTo(minSize); + crop = size.centredTo(crop).boundedTo(Rectangle(sensorOutputSize_)); + + if (crop != lastIspCrop_) + isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &crop); + lastIspCrop_ = crop; + } + + request->controls().set(controls::IspCrop, lastIspCrop_); + } + /* * Process all the user controls by the IPA. Once this is complete, we * queue the ISP output buffer listed in the request to start the HW From patchwork Tue Sep 29 16:40:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9869 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 BA482C3B5B for ; Tue, 29 Sep 2020 16:40:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7B2706221F; Tue, 29 Sep 2020 18:40:14 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="lVa87LLF"; dkim-atps=neutral Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0D68A62211 for ; Tue, 29 Sep 2020 18:40:11 +0200 (CEST) Received: by mail-wr1-x433.google.com with SMTP id z4so6185050wrr.4 for ; Tue, 29 Sep 2020 09:40:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WDoEdN80X2fj4rhVFmRDdDnGzuHzhrvAaQt+7lJP83w=; b=lVa87LLFzTT3HPK4FkFoSCyIEaruvxMSXDxHwJtkjOLaxeJCYlQUQvHusA7pPL8ux7 XWDrGD2lyAfkA/Vvw+TOqwFLuuCbDPZTI3HOeyBZVJWVw9Hesgdpr5s7gDEHx3xukfcx B3ixrabf6y7s62Me6ccSb2f1nDY5oAZTtlJovPKd1RPC0afU6Bo1CfPB09QD/qzehyEj DPfZ8UOs8CayPRT3TQ7mvYMPdkCAu/VoW5h8gtHvsos4NuqVWeRyKxEwrUez1aN8FXat uQssRMgIptZalmCaTs5QcK6/4Bq9ECSIQHIXRw59DsndYGGRBwcYu1mGJd0FcKzVthIj ftEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WDoEdN80X2fj4rhVFmRDdDnGzuHzhrvAaQt+7lJP83w=; b=S8z4uikHr2T4HVl3WotA5uHq8SPTunD8TM+ZVb0iUfMDE1eNLXwp8vQEp+JtppDyiQ pdnfP/EOqualEQ7xG3jb6raDoVAGwNq+icjp+zALnMg5UexpQDvE4lWnNfVZztQF/hre hB5uB13gcviW7O5Wj0carrvVrFGrnaHCJ5WFts2KmjYgv4WjGRiy9EeCpPJYKZpVj41k DXY0+jjguGjBu9Vtld6J/x4XdJXD8voI3SHWaULCcCngP9KtrMd73VABnKF0C5xsk8H2 hNl1I6mEV9GTQxsCGn9Z3aEPsssjdMwdsRB2n0XkV0Qc3IyajhR9s7Bg1HyZLJ/gLTuU dmyQ== X-Gm-Message-State: AOAM533k9yxY6dYkOR9olf9gwMFj71brmF1Dci1OgxF7ZnM1RHM3nr2D k+5VnGIoioW3/8DQ2iMLU82+xWshdVQJEg== X-Google-Smtp-Source: ABdhPJxM2mGdRI1BAW944mzbsluGJJkR14rX+QpPl4SooH1dm/3//qoleV6SmWGApK8bVdAeUEcuUA== X-Received: by 2002:a5d:5404:: with SMTP id g4mr5099203wrv.134.1601397610412; Tue, 29 Sep 2020 09:40:10 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:09 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:40:00 +0100 Message-Id: <20200929164000.15429-7-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 6/6] cam: Add command line option to test IspCrop control 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" This allows the user to request digital zoom by adding, for example, "-z 0.25,0.25,0.5,0.5" which would give a 2x zoom, still centred in the middle of the image. Signed-off-by: David Plowman --- src/cam/capture.cpp | 25 +++++++++++++++++++++++-- src/cam/capture.h | 2 +- src/cam/main.cpp | 3 +++ src/cam/main.h | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp index 5510c009..3b50c591 100644 --- a/src/cam/capture.cpp +++ b/src/cam/capture.cpp @@ -10,6 +10,9 @@ #include #include +#include +#include + #include "capture.h" #include "main.h" @@ -58,7 +61,7 @@ int Capture::run(const OptionsParser::Options &options) FrameBufferAllocator *allocator = new FrameBufferAllocator(camera_); - ret = capture(allocator); + ret = capture(allocator, options); if (options.isSet(OptFile)) { delete writer_; @@ -70,7 +73,7 @@ int Capture::run(const OptionsParser::Options &options) return ret; } -int Capture::capture(FrameBufferAllocator *allocator) +int Capture::capture(FrameBufferAllocator *allocator, const OptionsParser::Options &options) { int ret; @@ -120,6 +123,24 @@ int Capture::capture(FrameBufferAllocator *allocator) requests.push_back(request); } + /* Set up digital zoom if it was requested on the command line. */ + if (options.isSet(OptZoom)) { + std::string zoom = options[OptZoom].toString(); + float x, y, width, height; + + if (sscanf(zoom.c_str(), "%f,%f,%f,%f", &x, &y, &width, &height) == 4) { + Size sensorArea = camera_->properties().get(properties::SensorOutputSize); + Rectangle crop(x * sensorArea.width, + y * sensorArea.height, + width * sensorArea.width, + height * sensorArea.height); + + requests.front()->controls().set(controls::IspCrop, crop); + } else { + std::cout << "Invalid zoom values - ignoring" << std::endl; + } + } + ret = camera_->start(); if (ret) { std::cout << "Failed to start capture" << std::endl; diff --git a/src/cam/capture.h b/src/cam/capture.h index 0aebdac9..52806164 100644 --- a/src/cam/capture.h +++ b/src/cam/capture.h @@ -29,7 +29,7 @@ public: int run(const OptionsParser::Options &options); private: - int capture(libcamera::FrameBufferAllocator *allocator); + int capture(libcamera::FrameBufferAllocator *allocator, const OptionsParser::Options &options); void requestComplete(libcamera::Request *request); diff --git a/src/cam/main.cpp b/src/cam/main.cpp index 244720b4..b871d049 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -201,6 +201,9 @@ int CamApp::parseOptions(int argc, char *argv[]) parser.addOption(OptStrictFormats, OptionNone, "Do not allow requested stream format(s) to be adjusted", "strict-formats"); + parser.addOption(OptZoom, OptionString, + "Zoom in on the image portion described by the x,y,width,height rectangle (fractions of the maximum FOV) e.g. 0.25,0.25,0.5,0.5", + "zoom", ArgumentRequired, "zoom"); options_ = parser.parse(argc, argv); if (!options_.valid()) diff --git a/src/cam/main.h b/src/cam/main.h index ea8dfd33..a1fd899f 100644 --- a/src/cam/main.h +++ b/src/cam/main.h @@ -17,6 +17,7 @@ enum { OptListProperties = 'p', OptMonitor = 'm', OptStream = 's', + OptZoom = 'z', OptListControls = 256, OptStrictFormats = 257, };