From patchwork Fri Dec 6 10:13:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22198 X-Patchwork-Delegate: paul.elder@ideasonboard.com 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 275F3BF415 for ; Fri, 6 Dec 2024 10:14:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C370566148; Fri, 6 Dec 2024 11:14:08 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qlo48CKQ"; 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 944126613D for ; Fri, 6 Dec 2024 11:14:05 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:3543:aebe:e043:ef86]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3BD469FC; Fri, 6 Dec 2024 11:13:36 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1733480016; bh=V/J4wJ4pkpHSj6jhg+sH3h5VyeMjLU9+u+us9Tt+Ack=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qlo48CKQl1GbIr10HQs27hU6b64vP7/8VGrKltwi7tSrjlJzJEHA+cPmycUMr0Swj rx1Q4LvXQimsnNo/wx/emYlJRHJhDLAdg8jSBPaKqzvONOslRn0UiKDPDlGaQhvQCA +aiF4DOjkat5TuiQO/hA0U3gIF2Gzh9yvgGZrrVM= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 06/17] libcamera: converter_v4l2_m2m: Improve crop bounds support Date: Fri, 6 Dec 2024 11:13:28 +0100 Message-ID: <20241206101344.767170-7-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241206101344.767170-1-stefan.klug@ideasonboard.com> References: <20241206101344.767170-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" When a converter (dw100 on imx8mp in this case) is used in a pipeline, the ScalerCrop control get's created at createCamera() time. As this is before configure(), no streams were configured on the converter and the stream specific crop bounds are not known. Extend the converter class to report the default crop bounds in case the provided stream is not found. Signed-off-by: Stefan Klug --- .../internal/converter/converter_v4l2_m2m.h | 1 + src/libcamera/converter.cpp | 3 + .../converter/converter_v4l2_m2m.cpp | 113 +++++++++--------- 3 files changed, 59 insertions(+), 58 deletions(-) diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h index 0bc0d053e2c4..a5286166f574 100644 --- a/include/libcamera/internal/converter/converter_v4l2_m2m.h +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h @@ -105,6 +105,7 @@ private: std::map> streams_; std::map queue_; + std::pair inputCropBounds_; }; } /* namespace libcamera */ diff --git a/src/libcamera/converter.cpp b/src/libcamera/converter.cpp index 3a3f84344c5e..aa16970cd446 100644 --- a/src/libcamera/converter.cpp +++ b/src/libcamera/converter.cpp @@ -195,6 +195,9 @@ Converter::~Converter() * this function should be called after the \a stream has been configured using * configure(). * + * When called with an invalid \a stream, the function returns the default crop + * bounds of the converter. + * * \return A pair containing the minimum and maximum crop bound in that order */ diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp index d63ef2f8028f..bd7e5cce600d 100644 --- a/src/libcamera/converter/converter_v4l2_m2m.cpp +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp @@ -30,6 +30,52 @@ namespace libcamera { LOG_DECLARE_CATEGORY(Converter) +namespace { + +int getCropBounds(V4L2VideoDevice *device, Rectangle &minCrop, + Rectangle &maxCrop) +{ + Rectangle minC; + Rectangle maxC; + + /* Find crop bounds */ + minC.width = 1; + minC.height = 1; + maxC.width = UINT_MAX; + maxC.height = UINT_MAX; + + int ret = device->setSelection(V4L2_SEL_TGT_CROP, &minC); + if (ret) { + LOG(Converter, Error) + << "Could not query minimum selection crop: " + << strerror(-ret); + return ret; + } + + ret = device->getSelection(V4L2_SEL_TGT_CROP_BOUNDS, &maxC); + if (ret) { + LOG(Converter, Error) + << "Could not query maximum selection crop: " + << strerror(-ret); + return ret; + } + + /* Reset the crop to its maximum */ + ret = device->setSelection(V4L2_SEL_TGT_CROP, &maxC); + if (ret) { + LOG(Converter, Error) + << "Could not reset selection crop: " + << strerror(-ret); + return ret; + } + + minCrop = minC; + maxCrop = maxC; + return 0; +} + +} /* namespace */ + /* ----------------------------------------------------------------------------- * V4L2M2MConverter::V4L2M2MStream */ @@ -98,41 +144,10 @@ int V4L2M2MConverter::V4L2M2MStream::configure(const StreamConfiguration &inputC outputBufferCount_ = outputCfg.bufferCount; if (converter_->features() & Feature::InputCrop) { - Rectangle minCrop; - Rectangle maxCrop; - - /* Find crop bounds */ - minCrop.width = 1; - minCrop.height = 1; - maxCrop.width = UINT_MAX; - maxCrop.height = UINT_MAX; - - ret = setInputSelection(V4L2_SEL_TGT_CROP, &minCrop); - if (ret) { - LOG(Converter, Error) - << "Could not query minimum selection crop: " - << strerror(-ret); - return ret; - } - - ret = getInputSelection(V4L2_SEL_TGT_CROP_BOUNDS, &maxCrop); - if (ret) { - LOG(Converter, Error) - << "Could not query maximum selection crop: " - << strerror(-ret); - return ret; - } - - /* Reset the crop to its maximum */ - ret = setInputSelection(V4L2_SEL_TGT_CROP, &maxCrop); - if (ret) { - LOG(Converter, Error) - << "Could not reset selection crop: " - << strerror(-ret); + ret = getCropBounds(m2m_->output(), inputCropBounds_.first, + inputCropBounds_.second); + if (ret) return ret; - } - - inputCropBounds_ = { minCrop, maxCrop }; } return 0; @@ -258,27 +273,9 @@ V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media) return; } - /* Discover Feature::InputCrop */ - Rectangle maxCrop; - maxCrop.width = UINT_MAX; - maxCrop.height = UINT_MAX; - - ret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &maxCrop); - if (ret) - return; - - /* - * Rectangles for cropping targets are defined even if the device - * does not support cropping. Their sizes and positions will be - * fixed in such cases. - * - * Set and inspect a crop equivalent to half of the maximum crop - * returned earlier. Use this to determine whether the crop on - * input is really supported. - */ - Rectangle halfCrop(maxCrop.size() / 2); - ret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &halfCrop); - if (!ret && halfCrop != maxCrop) { + ret = getCropBounds(m2m_->output(), inputCropBounds_.first, + inputCropBounds_.second); + if (!ret && inputCropBounds_.first != inputCropBounds_.second) { features_ |= Feature::InputCrop; LOG(Converter, Info) @@ -477,10 +474,10 @@ std::pair V4L2M2MConverter::inputCropBounds(const Stream *stream) { auto iter = streams_.find(stream); - if (iter == streams_.end()) - return {}; + if (iter != streams_.end()) + return iter->second->inputCropBounds(); - return iter->second->inputCropBounds(); + return inputCropBounds_; } /**