From patchwork Tue Dec 9 18:09:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaac Scott X-Patchwork-Id: 25394 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 2F1F9BD1F1 for ; Tue, 9 Dec 2025 18:10:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D554C6141D; Tue, 9 Dec 2025 19:10:13 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mguezhcr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5503F61410 for ; Tue, 9 Dec 2025 19:10:08 +0100 (CET) Received: from isaac-ThinkPad-T16-Gen-2.infra.iob (cpc90716-aztw32-2-0-cust408.18-1.cable.virginm.net [86.26.101.153]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8DE7F82E; Tue, 9 Dec 2025 19:10:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1765303807; bh=efSWrNgpvzTSPc6PIY8X75DdN7ACWuAtq6GhyIR3nYg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mguezhcrVh9s3GJLJMNHKZQkVM78He9d7tGRQtAVO7/BRQ/zT7xM2uDNoLmQicDYC xVNn/VcQXNIA6fgKpKn2C4pkUGZE/trYFP0iWr1oXlMxRQ0YFkoPW5Llwv53aZdYmf v8p/CUf8yFXpB7ERXHm/DuDt81UltOqGOzdhwaa0= From: Isaac Scott To: libcamera-devel@lists.libcamera.org Cc: Isaac Scott Subject: [RFC PATCH 5/6] rkisp1_path: Determine if the ISP is bypassed for YUV and RAW formats Date: Tue, 9 Dec 2025 18:09:53 +0000 Message-ID: <20251209180954.332392-6-isaac.scott@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251209180954.332392-1-isaac.scott@ideasonboard.com> References: <20251209180954.332392-1-isaac.scott@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" So as to not break existing use cases, in the viewfinder StreamRole RAW formats that can be converted to NV12 should be preferred, even if the bits per pixel is lower. Therefore, we should select the RAW format as our stream format to be configured on the pipeline by default. However, the user should be given the option to explicitly select if they wish to use a bypass format if available. This means we have to enumerate all possible output formats as well as their supported sizes. Update the rkisp1's generateConfiguration implementation to facilitate this. Signed-off-by: Isaac Scott --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 13 +++-- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 58 ++++++++++++------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 0c8c15ea5..51c57be50 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -761,19 +761,24 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() mbusCodes = { bypassFormats.at(config_[0].pixelFormat) }; /* Select the sensor format. */ - PixelFormat bypassFormat; + PixelFormat bypassFormat, rawFormat; Size maxSize; for (const StreamConfiguration &cfg : config_) { const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW || - info.colourEncoding == PixelFormatInfo::ColourEncodingYUV) + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + rawFormat = cfg.pixelFormat; + else bypassFormat = cfg.pixelFormat; maxSize = std::max(maxSize, cfg.size); } - if (bypassFormat.isValid()) { + /* We want to prefer to use the RAW format if available */ + if (rawFormat.isValid()) { + LOG(RkISP1, Info) << "Using RAW format " << rawFormat; + mbusCodes = { bypassFormats.at(rawFormat) }; + } else if (bypassFormat.isValid()) { LOG(RkISP1, Info) << "Using bypass format " << bypassFormat; mbusCodes = { bypassFormats.at(bypassFormat) }; } else { diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index 903e1aaeb..dce0ed1d3 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -176,7 +176,6 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, /* Min and max resolutions to populate the available stream formats. */ Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) .boundedTo(resolution); - Size minResolution = minResolution_.expandedToAspectRatio(resolution); /* The desired stream size, bound to the max resolution. */ Size streamSize = size.boundedTo(maxResolution); @@ -184,6 +183,7 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, /* Create the list of supported stream formats. */ std::map> streamFormats; unsigned int rawBitsPerPixel = 0; + PixelFormat bypassFormat; PixelFormat rawFormat; for (const auto &format : streamFormats_) { @@ -193,8 +193,14 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, if (info.colourEncoding != PixelFormatInfo::ColourEncodingRAW) { if (role == StreamRole::Raw) continue; + for (const auto &imageSize : sensor->sizes(formatToMediaBus.at(format))) { + if (imageSize.width > maxResolution_.width || + imageSize.height > maxResolution_.height) + continue; - streamFormats[format] = { { minResolution, maxResolution } }; + streamFormats[format].push_back({ imageSize, imageSize }); + bypassFormat = format; + } continue; } @@ -243,7 +249,8 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size, format = rawFormat; } } else { - format = formats::NV12; + /* Prefer RAW formats */ + format = rawFormat ? rawFormat : bypassFormat; } StreamFormats formats(streamFormats); @@ -269,18 +276,22 @@ RkISP1Path::validate(const CameraSensor *sensor, * Validate the pixel format. If the requested format isn't supported, * default to either NV12 (all versions of the ISP are guaranteed to * support NV12 on both the main and self paths) if the requested format - * is not a raw format, or to the supported raw format with the highest + * is not a raw or YUV format, or to the supported raw format with the highest * bits per pixel otherwise. */ - unsigned int rawBitsPerPixel = 0; - PixelFormat rawFormat; + unsigned int bypassBitsPerPixel = 0; + PixelFormat bypassFormat; bool found = false; for (const auto &format : streamFormats_) { const PixelFormatInfo &info = PixelFormatInfo::info(format); + /* + * Even if the YUV format is a higher BPP, we still want to prefer + * the raw format, so we can do the processing ourselves. + */ if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { - /* Skip raw formats not supported by the sensor. */ + /* Skip formats not supported by the sensor. */ uint32_t mbusCode = formatToMediaBus.at(format); if (std::find(mbusCodes.begin(), mbusCodes.end(), mbusCode) == mbusCodes.end()) @@ -295,9 +306,9 @@ RkISP1Path::validate(const CameraSensor *sensor, if (sensorConfig && info.bitsPerPixel != sensorConfig->bitDepth) continue; - if (info.bitsPerPixel > rawBitsPerPixel) { - rawBitsPerPixel = info.bitsPerPixel; - rawFormat = format; + if (info.bitsPerPixel > bypassBitsPerPixel) { + bypassBitsPerPixel = info.bitsPerPixel; + bypassFormat = format; } } @@ -307,26 +318,28 @@ RkISP1Path::validate(const CameraSensor *sensor, } } - if (sensorConfig && !rawFormat.isValid()) + if (sensorConfig && !bypassFormat.isValid()) return CameraConfiguration::Invalid; - bool isRaw = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding == - PixelFormatInfo::ColourEncodingRAW; + bool isIspBypassed = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding == + PixelFormatInfo::ColourEncodingRAW || + PixelFormatInfo::info(cfg->pixelFormat).colourEncoding == + PixelFormatInfo::ColourEncodingYUV; /* * If no raw format supported by the sensor has been found, use a * processed format. */ - if (!rawFormat.isValid()) - isRaw = false; + if (!bypassFormat.isValid()) + isIspBypassed = false; if (!found) - cfg->pixelFormat = isRaw ? rawFormat : formats::NV12; + cfg->pixelFormat = isIspBypassed ? bypassFormat : formats::NV12; Size minResolution; Size maxResolution; - if (isRaw) { + if (isIspBypassed) { /* * Use the sensor output size closest to the requested stream * size while ensuring the output size doesn't exceed ISP limits. @@ -338,11 +351,11 @@ RkISP1Path::validate(const CameraSensor *sensor, uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat); cfg->size.boundTo(resolution); - Size rawSize = sensorConfig ? sensorConfig->outputSize + Size bypassSize = sensorConfig ? sensorConfig->outputSize : cfg->size; V4L2SubdeviceFormat sensorFormat = - sensor->getFormat(std::array{ mbusCode }, rawSize); + sensor->getFormat(std::array{ mbusCode }, bypassSize); if (sensorConfig && sensorConfig->outputSize != sensorFormat.size) @@ -352,7 +365,7 @@ RkISP1Path::validate(const CameraSensor *sensor, maxResolution = sensorFormat.size; } else if (sensorConfig) { /* - * We have already ensured 'rawFormat' has the matching bit + * We have already ensured 'bypassFormat' has the matching bit * depth with sensorConfig.bitDepth hence, only validate the * sensorConfig's output size here. */ @@ -361,7 +374,7 @@ RkISP1Path::validate(const CameraSensor *sensor, if (sensorSize > resolution) return CameraConfiguration::Invalid; - uint32_t mbusCode = formatToMediaBus.at(rawFormat); + uint32_t mbusCode = formatToMediaBus.at(bypassFormat); V4L2SubdeviceFormat sensorFormat = sensor->getFormat(std::array{ mbusCode }, sensorSize); @@ -524,7 +537,8 @@ void RkISP1Path::stop() namespace { constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 }; constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 }; -constexpr std::array RKISP1_RSZ_MP_FORMATS{ +constexpr std::array RKISP1_RSZ_MP_FORMATS{ + formats::UYVY, formats::YUYV, formats::NV16, formats::NV61,