From patchwork Tue Oct 1 14:17:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 21463 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 502ADBD80A for ; Tue, 1 Oct 2024 14:17:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 282566351F; Tue, 1 Oct 2024 16:17:56 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gh2Qk2Ng"; 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 C91AC60553 for ; Tue, 1 Oct 2024 16:17:54 +0200 (CEST) Received: from localhost.localdomain (unknown [IPv6:2405:201:2015:f873:55f8:639e:8e9f:12ec]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DCA9810B8; Tue, 1 Oct 2024 16:16:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1727792181; bh=XpStW0HgvXEpsC8K56hDz2YA1GFPArjlKbNDR6S/+r8=; h=From:To:Cc:Subject:Date:From; b=gh2Qk2NgUZtcNj3aO9vG5Cn1ztXEeLmIroxHchm4rlMYHt3ZaMKF3P82TzaOX8H0W DI3dVsK7i9Ob9hA6EkrhjadhUT6DSmX6YneotMmmv95w2FzT6FhQQvsTFJTa0fvALr D7Xme/WxFTuh0CxedtQO7cEouC4QWolVAVlMptZU= From: Umang Jain To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Kieran Bingham , Laurent Pinchart , Paul Elder , Umang Jain Subject: [PATCH] libcamera: rkisp1: Integrate SensorConfiguration support Date: Tue, 1 Oct 2024 19:47:38 +0530 Message-ID: <20241001141738.17471-1-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.45.0 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" Integrate the RkISP1 pipeline handler to support sensor configuration provided by applications through CameraConfiguration::sensorConfig. The SensorConfiguration must be validated on both RkISP1Path (mainPath and selfPath), so the parameters of RkISP1Path::validate() have been updated to include sensorConfig. For RAW paths, if a sensor configuration is provided, it will be adjusted based on the stream configuration. Finally, if the sensor configuration fails to apply, the camera configuration validation will be marked as invalid. Signed-off-by: Umang Jain --- Testing: - Developed over [PATCH 0/2] libcamera: pixelformat: Add isRaw() helper - Tested with cam+[1] on i.MX8MP with IMX283 attached [1]: https://patchwork.libcamera.org/patch/20080/ --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 79 +++++++++++++++++-- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 20 +++-- src/libcamera/pipeline/rkisp1/rkisp1_path.h | 2 + 3 files changed, 87 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 0c4519de..49fe8fb1 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -474,11 +474,12 @@ bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg) StreamConfiguration config; config = cfg; - if (data_->mainPath_->validate(sensor, &config) != Valid) + if (data_->mainPath_->validate(sensor, sensorConfig, &config) != Valid) return false; config = cfg; - if (data_->selfPath_ && data_->selfPath_->validate(sensor, &config) != Valid) + if (data_->selfPath_ && + data_->selfPath_->validate(sensor, sensorConfig, &config) != Valid) return false; return true; @@ -495,6 +496,31 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() status = validateColorSpaces(ColorSpaceFlag::StreamsShareColorSpace); + /* + * Make sure that if a sensor configuration has been requested it + * is valid. + */ + if (sensorConfig && !sensorConfig->isValid()) { + LOG(RkISP1, Error) << "Invalid sensor configuration request"; + return Invalid; + } + + if (sensorConfig) { + std::optional bitDepth = sensorConfig->bitDepth; + if (bitDepth != 8 && bitDepth != 10 && bitDepth != 12) { + /* + * Default to the first supported bit depth, if an + * unsupported one is supplied. + */ + V4L2SubdeviceFormat format = {}; + format.code = sensor->mbusCodes().at(0); + + sensorConfig->bitDepth = + MediaBusFormatInfo::info(format.code).bitsPerPixel; + status = Adjusted; + } + } + /* Cap the number of entries to the available streams. */ if (config_.size() > pathCount) { config_.resize(pathCount); @@ -540,7 +566,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Try to match stream without adjusting configuration. */ if (mainPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->mainPath_->validate(sensor, &tryCfg) == Valid) { + if (data_->mainPath_->validate(sensor, sensorConfig, &tryCfg) == Valid) { mainPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->mainPathStream_)); @@ -550,7 +576,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() if (selfPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->selfPath_->validate(sensor, &tryCfg) == Valid) { + if (data_->selfPath_->validate(sensor, sensorConfig, &tryCfg) == Valid) { selfPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->selfPathStream_)); @@ -561,7 +587,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Try to match stream allowing adjusting configuration. */ if (mainPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->mainPath_->validate(sensor, &tryCfg) == Adjusted) { + if (data_->mainPath_->validate(sensor, sensorConfig, &tryCfg) == Adjusted) { mainPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->mainPathStream_)); @@ -572,7 +598,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() if (selfPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->selfPath_->validate(sensor, &tryCfg) == Adjusted) { + if (data_->selfPath_->validate(sensor, sensorConfig, &tryCfg) == Adjusted) { selfPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->selfPathStream_)); @@ -589,26 +615,63 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Select the sensor format. */ PixelFormat rawFormat; + Size rawSize; Size maxSize; for (const StreamConfiguration &cfg : config_) { - if (cfg.pixelFormat.isRaw()) + if (cfg.pixelFormat.isRaw()) { rawFormat = cfg.pixelFormat; + rawSize = cfg.size; + } maxSize = std::max(maxSize, cfg.size); } + if (rawFormat.isValid() && sensorConfig) { + if (sensorConfig->outputSize != rawSize) { + sensorConfig->outputSize = rawSize; + status = Adjusted; + } + + const PixelFormatInfo &info = PixelFormatInfo::info(rawFormat); + if (sensorConfig->bitDepth != info.bitsPerPixel) { + sensorConfig->bitDepth = info.bitsPerPixel; + status = Adjusted; + } + } + std::vector mbusCodes; + Size sz = maxSize; if (rawFormat.isValid()) { mbusCodes = { rawFormats.at(rawFormat) }; + sz = rawSize; + } else if (sensorConfig) { + for (const auto &value : rawFormats) { + const PixelFormatInfo &info = PixelFormatInfo::info(value.first); + if (info.bitsPerPixel == sensorConfig->bitDepth) + mbusCodes.push_back(value.second); + } + sz = sensorConfig->outputSize; } else { std::transform(rawFormats.begin(), rawFormats.end(), std::back_inserter(mbusCodes), [](const auto &value) { return value.second; }); } - sensorFormat_ = sensor->getFormat(mbusCodes, maxSize); + sensorFormat_ = sensor->getFormat(mbusCodes, sz); + if (sensorConfig) { + int ret = data_->sensor_->applyConfiguration(*sensorConfig, + combinedTransform_, + &sensorFormat_); + if (ret) { + LOG(RkISP1, Error) + << "Sensor Configuration not supported: " + << strerror(-ret); + + return Invalid; + } + } if (sensorFormat_.size.isNull()) sensorFormat_.size = sensor->resolution(); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index 7c1f0c73..30becb75 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -253,8 +253,10 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, return cfg; } -CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, - StreamConfiguration *cfg) +CameraConfiguration::Status +RkISP1Path::validate(const CameraSensor *sensor, + std::optional sensorConfig, + StreamConfiguration *cfg) { const std::vector &mbusCodes = sensor->mbusCodes(); Size resolution = filterSensorResolution(sensor); @@ -281,12 +283,18 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, mbusCodes.end()) continue; - /* - * Store the raw format with the highest bits per pixel - * for later usage. + /* If the bits per pixel is supplied from the sensor + * configuration, choose a raw format that complies with + * it. Otherwise, store the raw format with the highest + * bits per pixel for later usage. */ const PixelFormatInfo &info = PixelFormatInfo::info(format); - if (info.bitsPerPixel > rawBitsPerPixel) { + + if (sensorConfig && + info.bitsPerPixel == sensorConfig->bitDepth) { + rawFormat = format; + rawBitsPerPixel = info.bitsPerPixel; + } else if (info.bitsPerPixel > rawBitsPerPixel) { rawBitsPerPixel = info.bitsPerPixel; rawFormat = format; } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index 9f75fe1f..8aae00ef 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -27,6 +27,7 @@ namespace libcamera { class CameraSensor; class MediaDevice; class V4L2Subdevice; +class SensorConfiguration; struct StreamConfiguration; struct V4L2SubdeviceFormat; @@ -45,6 +46,7 @@ public: const Size &resolution, StreamRole role); CameraConfiguration::Status validate(const CameraSensor *sensor, + std::optional sensorConfig, StreamConfiguration *cfg); int configure(const StreamConfiguration &config,