From patchwork Wed Jul 29 09:31:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9061 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 920F4BD86F for ; Wed, 29 Jul 2020 09:32:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D9FCD616FF; Wed, 29 Jul 2020 11:32:04 +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="E5/rv9y1"; dkim-atps=neutral Received: from mail-wm1-x341.google.com (mail-wm1-x341.google.com [IPv6:2a00:1450:4864:20::341]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB787605B2 for ; Wed, 29 Jul 2020 11:32:02 +0200 (CEST) Received: by mail-wm1-x341.google.com with SMTP id 184so2262403wmb.0 for ; Wed, 29 Jul 2020 02:32:02 -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=HKmAuBxwIumr230KzlwI2CVDGfwWcBPc8QjmYgrFHx0=; b=E5/rv9y15EmQedP9cGMPqnZkyVkpaBOpS2W3M1mUPRN/5DjelgK0SCEXVeQn5ldOfI a1v2er30GXQrQRIG6kJ3gx8DOx4IMr1DdYxUp90C8LJ3cg71GMhIR8ijddbAzdWjLvPj eOpZdXDO9q129ZBPrDakuz3oV5MuXPSyJMdMg1W1IfCtJj7fRhIDjQILulg1JMm0ZXRH SJ5uOAxDpvdAZAg/3qKkAqS0LzB69K3UK5vjWG6dUgEigURXKgeEIjloHzGMEFS0aM/i aEXr3ZRMg1BrLwTooEfQ/m8r9hs2L+nL919NO+w0ykcE31IUzNyvsXWeXjExrwiBe5BH fA1Q== 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=HKmAuBxwIumr230KzlwI2CVDGfwWcBPc8QjmYgrFHx0=; b=cZK6iXy9QyTxhwMRM8fBbkniaTPVxv6n/POL/prYCMaoqjsfEm/W+EQ9iHgx86LXdX ok9JcZbLjEpESjgDbynBNHVf+l+q13BWt/Nb0C4PT3zj6+D4pYLklC5liSjymkC7YFiI n53BgJYHmBItfrNT0DHNyVQnwA6Etz5YowBpYVKUjcFSfLki0XDpn7BM7cSNgB5yocuV +NzL4rAeP30n/fKcmttk2uS165dfXBOd4FA1U7uOzWpr/2nubqIaoYTlvj7KsV7CmgLQ 1JTeMGcrB4e/ijQCVtBvt/Rqjo4AI0zqk+h3tyLvG6OaxZLfN02KvHB/N6z/tLyc0Onv Xrpw== X-Gm-Message-State: AOAM533jebKUmaHGbS0N01tlGPL5Oc88m1rwMg6nkH1lX8+F4PD+5ffY jiEHdcuSvC/73xai40BgiICCPbMGPqGwYw== X-Google-Smtp-Source: ABdhPJx3lc34VHsZNJ8gokXd7ru+x6odi7uLWe6vmQ6gUUTcrwO2tmHb/4eT0MOddQTDN+CZzt/xdg== X-Received: by 2002:a7b:c054:: with SMTP id u20mr7665782wmc.2.1596015121835; Wed, 29 Jul 2020 02:32:01 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id c15sm3709921wme.23.2020.07.29.02.32.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jul 2020 02:32:01 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Wed, 29 Jul 2020 10:31:51 +0100 Message-Id: <20200729093154.12296-3-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200729093154.12296-1-david.plowman@raspberrypi.com> References: <20200729093154.12296-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/5] libcamera: raspberrypi: Apply transform and pass through to IPA 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 user-supplied transform is applied to the camera, taking account of any pre-existing rotation. It is then also plumbed through to the IPA so that it will (in a further commit) be able to make use of it. --- include/libcamera/ipa/raspberrypi.h | 1 + src/ipa/raspberrypi/raspberrypi.cpp | 13 ++++++++- .../pipeline/raspberrypi/raspberrypi.cpp | 27 +++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h index ca62990..3905a4a 100644 --- a/include/libcamera/ipa/raspberrypi.h +++ b/include/libcamera/ipa/raspberrypi.h @@ -14,6 +14,7 @@ enum RPiConfigParameters { RPI_IPA_CONFIG_LS_TABLE = (1 << 0), RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1), RPI_IPA_CONFIG_SENSOR = (1 << 2), + RPI_IPA_CONFIG_TRANSFORM = (1 << 3), }; enum RPiOperations { diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 3747208..2809521 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -144,6 +145,9 @@ private: /* LS table allocation passed in from the pipeline handler. */ FileDescriptor lsTableHandle_; void *lsTable_; + + /* This is the transform requested by the user/application driving libcamera. */ + Transform userTransform_; }; int IPARPi::init(const IPASettings &settings) @@ -282,6 +286,7 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo, lastMode_ = mode_; /* Store the lens shading table pointer and handle if available. */ + unsigned int next_element = 0; if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) { /* Remove any previous table, if there was one. */ if (lsTable_) { @@ -290,7 +295,7 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo, } /* Map the LS table buffer into user space. */ - lsTableHandle_ = FileDescriptor(ipaConfig.data[0]); + lsTableHandle_ = FileDescriptor(ipaConfig.data[next_element++]); if (lsTableHandle_.isValid()) { lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, lsTableHandle_.fd(), 0); @@ -301,6 +306,12 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo, } } } + + /* Fish out any transform set by the user/application. */ + if (ipaConfig.operation & RPI_IPA_CONFIG_TRANSFORM) { + uint32_t transformType = ipaConfig.data[next_element++]; + userTransform_ = reinterpret_cast(transformType); + } } void IPARPi::mapBuffers(const std::vector &buffers) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 82a0a4d..5fb427a 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -324,6 +324,9 @@ public: uint32_t expectedSequence_; bool sensorMetadata_; + /* This is the transform requested by the user/application driving libcamera. */ + Transform userTransform_; + /* * All the functions in this class are called from a single calling * thread. So, we do not need to have any mutex to protect access to any @@ -400,6 +403,9 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() if (config_.empty()) return Invalid; + if (userTransform.contains(Transform::transpose())) + return Invalid; + unsigned int rawCount = 0, outCount = 0, count = 0, maxIndex = 0; std::pair outSize[2]; Size maxSize; @@ -609,6 +615,9 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) unsigned int maxIndex = 0; bool rawStream = false; + /* Record the transform requested by the application. */ + data->userTransform_ = config->userTransform; + /* * Look for the RAW stream (if given) size as well as the largest * ISP output size. @@ -1140,6 +1149,11 @@ int RPiCameraData::configureIPA() ipaConfig.data = { static_cast(lsTable_.fd()) }; } + /* We must pass the user transform to the IPA too. */ + uint32_t transformType = reinterpret_cast(userTransform_); + ipaConfig.operation |= RPI_IPA_CONFIG_TRANSFORM; + ipaConfig.data.push_back(transformType); + CameraSensorInfo sensorInfo = {}; int ret = sensor_->sensorInfo(&sensorInfo); if (ret) { @@ -1168,8 +1182,17 @@ int RPiCameraData::configureIPA() /* Configure the H/V flip controls based on the sensor rotation. */ ControlList ctrls(unicam_[Unicam::Image].dev()->controls()); int32_t rotation = sensor_->properties().get(properties::Rotation); - ctrls.set(V4L2_CID_HFLIP, static_cast(!!rotation)); - ctrls.set(V4L2_CID_VFLIP, static_cast(!!rotation)); + + /* The camera needs to compose the user transform with the rotation. */ + Transform rotationTransform; + if (Transform::rotation(rotation, rotationTransform) == false) + return -EINVAL; + Transform transform = userTransform_ * rotationTransform; + + ctrls.set(V4L2_CID_HFLIP, + static_cast(transform.contains(Transform::hflip()))); + ctrls.set(V4L2_CID_VFLIP, + static_cast(transform.contains(Transform::vflip()))); unicam_[Unicam::Image].dev()->setControls(&ctrls); }