From patchwork Wed Nov 20 08:57:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22028 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 9F73AC330C for ; Wed, 20 Nov 2024 08:58:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1FD3B65F4B; Wed, 20 Nov 2024 09:58:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="R0FvuOse"; 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 B9D1665F40 for ; Wed, 20 Nov 2024 09:58:14 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:bbd:82cc:f3f3:e12e]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C494A75A; Wed, 20 Nov 2024 09:57:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732093076; bh=xPhnwj2ouJPX8A8sMaZGYgdC+NbcDE6V0SSmFlfMdeo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R0FvuOseKNmcghl6yCcH4nu977/LNYn3L/F4/menvIvkrlM2jvf+oUJvvLk06OBUw jXMEXreaJj1eR1MkiSJYChy2ueT8F8gw6F6WpNylgFz1GeA4gI6Y8PL75M0CHvk+oR 82Y1ljOcNdgzN2p8MFIzThvrjFpJdEro/Tirzr6c= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 6/7] pipeline: rkisp1: Fix ScalerCrop to be in sensor coordinates Date: Wed, 20 Nov 2024 09:57:45 +0100 Message-ID: <20241120085753.1993436-7-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241120085753.1993436-1-stefan.klug@ideasonboard.com> References: <20241120085753.1993436-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" ScalerCrop is specified as beeing in sensor coordinates. The current dewarper implementation on the imx8mp handles ScalerCrop in dewarper coordinates. This leads to unexpected results and a unusable ScalerCrop control in camshark. Fix that by transforming back and forth between sensor coordinates and dewarper coordinates. Signed-off-by: Stefan Klug Reviewed-by: Paul Elder --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 49 +++++++++++++++++++----- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 4a226d9b809f..c2ce38b1c253 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -204,6 +204,7 @@ private: RkISP1SelfPath selfPath_; std::unique_ptr dewarper_; + Rectangle dewarperSensorCrop_; bool useDewarper_; std::optional activeCrop_; @@ -862,6 +863,14 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) outputCfgs.push_back(const_cast(cfg)); ret = dewarper_->configure(cfg, outputCfgs); useDewarper_ = ret ? false : true; + + /* + * Calculate the crop rectangle of the data + * flowing into the dewarper in sensor + * coordinates. + */ + dewarperSensorCrop_ = outputCrop.mappedBetween(inputCrop, + ipaConfig.sensorInfo.analogCrop); } } else if (hasSelfPath_) { ret = selfPath_.configure(cfg, format); @@ -1224,10 +1233,21 @@ int PipelineHandlerRkISP1::updateControls(RkISP1CameraData *data) std::pair cropLimits = dewarper_->inputCropBounds(&data->mainPathStream_); - controls[&controls::ScalerCrop] = ControlInfo(cropLimits.first, - cropLimits.second, - cropLimits.second); - activeCrop_ = cropLimits.second; + /* + * ScalerCrop is specified to be in Sensor coordinates. + * So we need to transform the limits to sensor coordinates. + * We can safely assume that the maximum crop limit contains the + * full fov of the dewarper. + */ + Rectangle min = cropLimits.first.mappedBetween(cropLimits.second, + dewarperSensorCrop_); + Rectangle max = cropLimits.second.mappedBetween(cropLimits.second, + dewarperSensorCrop_); + + controls[&controls::ScalerCrop] = ControlInfo(min, + max, + max); + activeCrop_ = max; } /* Add the IPA registered controls to list of camera controls. */ @@ -1478,22 +1498,33 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer) /* Handle scaler crop control. */ const auto &crop = request->controls().get(controls::ScalerCrop); if (crop) { - Rectangle appliedRect = crop.value(); + Rectangle rect = crop.value(); + + /* + * ScalerCrop is specified to be in Sensor coordinates. + * So we need to transform it into dewarper coordinates. + * We can safely assume that the maximum crop limit contains the + * full fov of the dewarper. + */ + std::pair cropLimits = + dewarper_->inputCropBounds(&data->mainPathStream_); + rect = rect.mappedBetween(dewarperSensorCrop_, cropLimits.second); int ret = dewarper_->setInputCrop(&data->mainPathStream_, - &appliedRect); - if (!ret && appliedRect != crop.value()) { + &rect); + rect = rect.mappedBetween(cropLimits.second, dewarperSensorCrop_); + if (!ret && rect != crop.value()) { /* * If the rectangle is changed by setInputCrop on the * dewarper, log a debug message and cache the actual * applied rectangle for metadata reporting. */ LOG(RkISP1, Debug) - << "Applied rectangle " << appliedRect.toString() + << "Applied rectangle " << rect.toString() << " differs from requested " << crop.value().toString(); } - activeCrop_ = appliedRect; + activeCrop_ = rect; } /*