From patchwork Wed Jul 24 10:28:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 20699 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 3453FC323E for ; Wed, 24 Jul 2024 10:28:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 58B256336F; Wed, 24 Jul 2024 12:28:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="hpedoLdJ"; 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 5D00D619A0 for ; Wed, 24 Jul 2024 12:28:19 +0200 (CEST) Received: from fedora.local (unknown [IPv6:2405:201:2015:f873:55d7:c02e:b2eb:ee3f]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C738D4CF; Wed, 24 Jul 2024 12:27:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1721816856; bh=vQFVVRQ7stnG1jEvt1cyI+bwTWCeE+3X1fKz+BidexM=; h=From:To:Cc:Subject:Date:From; b=hpedoLdJ8HQBzXR5/qCoUMYrz+uYyTkh9f8H5yVwG3HjkQdeGnGahO5XS3tNC6pl4 KkCySebXdkGZRYbTw33TDkQJGoH3bgYwwf4xhirmpxZvKonkAYDyuLjCrmNradH7LH IjaqdHr+uOXDDiGG5lGkEayAp+3fqDXe4dRWpmX4= From: Umang Jain To: libcamera-devel@lists.libcamera.org Cc: Paul Elder , Umang Jain Subject: [PATCH] pipeline: rkisp1: Fix validation when sensor max is larger than ISP input Date: Wed, 24 Jul 2024 15:58:12 +0530 Message-ID: <20240724102812.27431-1-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.45.2 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" From: Paul Elder If the maximum sensor output size is larger than the maximum ISP input size, the maximum sensor size could be selected and the pipeline would fail with an EPIPE. Fix this by validating a suitable sensor output size which is less than or equal to, the ISP input. Signed-off-by: Paul Elder Signed-off-by: Umang Jain --- Split out from https://patchwork.libcamera.org/project/libcamera/list/?series=4143 Changes in v2: - trivial var rename - Properly obtain a resolution from sensor supported for ISP max input - Refactor slightly to fit better --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 ++++++- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 51 +++++++++++++------ src/libcamera/pipeline/rkisp1/rkisp1_path.h | 5 +- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 4cbf105d..5f94f422 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -1202,11 +1202,24 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) if (param_->open() < 0) return false; + /* + * Retrieve the ISP maximum input size for config validation in the + * path classes. + */ + Size ispMaxInputSize; + V4L2Subdevice::Formats ispFormats = isp_->formats(0); + for (const auto &[mbus, sizes] : ispFormats) { + for (const auto &size : sizes) { + if (ispMaxInputSize < size.max) + ispMaxInputSize = size.max; + } + } + /* Locate and open the ISP main and self paths. */ - if (!mainPath_.init(media_)) + if (!mainPath_.init(media_, ispMaxInputSize)) return false; - if (hasSelfPath_ && !selfPath_.init(media_)) + if (hasSelfPath_ && !selfPath_.init(media_, ispMaxInputSize)) return false; mainPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index c49017d1..6b40cdd2 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -62,7 +62,7 @@ RkISP1Path::RkISP1Path(const char *name, const Span &formats, { } -bool RkISP1Path::init(MediaDevice *media) +bool RkISP1Path::init(MediaDevice *media, const Size &ispMaxInputSize) { std::string resizer = std::string("rkisp1_resizer_") + name_ + "path"; std::string video = std::string("rkisp1_") + name_ + "path"; @@ -75,6 +75,7 @@ bool RkISP1Path::init(MediaDevice *media) if (video_->open() < 0) return false; + ispMaxInputSize_ = ispMaxInputSize; populateFormats(); link_ = media->link("rkisp1_isp", 2, resizer, 0); @@ -126,12 +127,33 @@ void RkISP1Path::populateFormats() } } +Size RkISP1Path::maxSupportedSensorResolution(const CameraSensor *sensor) +{ + Size sensorResolution; + + /* Get highest sensor resolution which is just less than or equal to ISP input */ + for (const auto &format : streamFormats_) { + auto sizes = sensor->sizes(formatToMediaBus.at(format)); + for (auto &sz : sizes) { + if (sz <= ispMaxInputSize_ && sz > sensorResolution) + sensorResolution = sz; + } + } + + return sensorResolution; +} + StreamConfiguration RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, StreamRole role) { const std::vector &mbusCodes = sensor->mbusCodes(); - const Size &resolution = sensor->resolution(); + Size resolution = maxSupportedSensorResolution(sensor); + if (resolution.isNull()) { + LOG(RkISP1, Error) << "No suitable format/resolution found" + << "for ISP input"; + return {}; + } /* Min and max resolutions to populate the available stream formats. */ Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) @@ -220,7 +242,12 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, StreamConfiguration *cfg) { const std::vector &mbusCodes = sensor->mbusCodes(); - const Size &resolution = sensor->resolution(); + Size resolution = maxSupportedSensorResolution(sensor); + if (resolution.isNull()) { + LOG(RkISP1, Error) << "No suitable format/resolution found" + << "for ISP input"; + return {}; + } const StreamConfiguration reqCfg = *cfg; CameraConfiguration::Status status = CameraConfiguration::Valid; @@ -275,8 +302,8 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, if (!found) cfg->pixelFormat = isRaw ? rawFormat : formats::NV12; - Size minResolution; - Size maxResolution; + Size maxResolution = maxResolution_.boundedTo(resolution); + Size minResolution = minResolution_.expandedToAspectRatio(resolution); if (isRaw) { /* @@ -287,16 +314,10 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, V4L2SubdeviceFormat sensorFormat = sensor->getFormat({ mbusCode }, cfg->size); - minResolution = sensorFormat.size; - maxResolution = sensorFormat.size; - } else { - /* - * Adjust the size based on the sensor resolution and absolute - * limits of the ISP. - */ - minResolution = minResolution_.expandedToAspectRatio(resolution); - maxResolution = maxResolution_.boundedToAspectRatio(resolution) - .boundedTo(resolution); + if (!sensorFormat.size.isNull()) { + minResolution = sensorFormat.size.boundedTo(ispMaxInputSize_); + maxResolution = sensorFormat.size.boundedTo(ispMaxInputSize_); + } } cfg->size.boundTo(maxResolution); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index 08edefec..a9bcfe36 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -35,7 +35,7 @@ public: RkISP1Path(const char *name, const Span &formats, const Size &minResolution, const Size &maxResolution); - bool init(MediaDevice *media); + bool init(MediaDevice *media, const Size &ispMaxInputSize); int setEnabled(bool enable) { return link_->setEnabled(enable); } bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; } @@ -63,6 +63,7 @@ public: private: void populateFormats(); + Size maxSupportedSensorResolution(const CameraSensor *sensor); static constexpr unsigned int RKISP1_BUFFER_COUNT = 4; @@ -77,6 +78,8 @@ private: std::unique_ptr resizer_; std::unique_ptr video_; MediaLink *link_; + + Size ispMaxInputSize_; }; class RkISP1MainPath : public RkISP1Path