Patch Detail
Show a patch.
GET /api/1.1/patches/25394/?format=api
{ "id": 25394, "url": "https://patchwork.libcamera.org/api/1.1/patches/25394/?format=api", "web_url": "https://patchwork.libcamera.org/patch/25394/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20251209180954.332392-6-isaac.scott@ideasonboard.com>", "date": "2025-12-09T18:09:53", "name": "[RFC,5/6] rkisp1_path: Determine if the ISP is bypassed for YUV and RAW formats", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "4bb438068d47f412c5f76ce9c23f0ea0d750bccd", "submitter": { "id": 215, "url": "https://patchwork.libcamera.org/api/1.1/people/215/?format=api", "name": "Isaac Scott", "email": "isaac.scott@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/25394/mbox/", "series": [ { "id": 5643, "url": "https://patchwork.libcamera.org/api/1.1/series/5643/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5643", "date": "2025-12-09T18:09:48", "name": "rkisp1: Add support for YUV bypass", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5643/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/25394/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/25394/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 2F1F9BD1F1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 9 Dec 2025 18:10:14 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D554C6141D;\n\tTue, 9 Dec 2025 19:10:13 +0100 (CET)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5503F61410\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 9 Dec 2025 19:10:08 +0100 (CET)", "from isaac-ThinkPad-T16-Gen-2.infra.iob\n\t(cpc90716-aztw32-2-0-cust408.18-1.cable.virginm.net [86.26.101.153])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8DE7F82E;\n\tTue, 9 Dec 2025 19:10:07 +0100 (CET)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"mguezhcr\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1765303807;\n\tbh=efSWrNgpvzTSPc6PIY8X75DdN7ACWuAtq6GhyIR3nYg=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=mguezhcrVh9s3GJLJMNHKZQkVM78He9d7tGRQtAVO7/BRQ/zT7xM2uDNoLmQicDYC\n\txVNn/VcQXNIA6fgKpKn2C4pkUGZE/trYFP0iWr1oXlMxRQ0YFkoPW5Llwv53aZdYmf\n\tv8p/CUf8yFXpB7ERXHm/DuDt81UltOqGOzdhwaa0=", "From": "Isaac Scott <isaac.scott@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Isaac Scott <isaac.scott@ideasonboard.com>", "Subject": "[RFC PATCH 5/6] rkisp1_path: Determine if the ISP is bypassed for\n\tYUV 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", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "So as to not break existing use cases, in the viewfinder StreamRole RAW\nformats that can be converted to NV12 should be preferred, even if the\nbits per pixel is lower. Therefore, we should select the RAW format as\nour stream format to be configured on the pipeline by default.\n\nHowever, the user should be given the option to explicitly select if\nthey wish to use a bypass format if available. This means we have to\nenumerate all possible output formats as well as their supported sizes.\n\nUpdate the rkisp1's generateConfiguration implementation to facilitate\nthis.\n\nSigned-off-by: Isaac Scott <isaac.scott@ideasonboard.com>\n---\n src/libcamera/pipeline/rkisp1/rkisp1.cpp | 13 +++--\n src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 58 ++++++++++++-------\n 2 files changed, 45 insertions(+), 26 deletions(-)", "diff": "diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\nindex 0c8c15ea5..51c57be50 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n@@ -761,19 +761,24 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()\n \t\tmbusCodes = { bypassFormats.at(config_[0].pixelFormat) };\n \n \t/* Select the sensor format. */\n-\tPixelFormat bypassFormat;\n+\tPixelFormat bypassFormat, rawFormat;\n \tSize maxSize;\n \n \tfor (const StreamConfiguration &cfg : config_) {\n \t\tconst PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat);\n-\t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW ||\n-\t\t info.colourEncoding == PixelFormatInfo::ColourEncodingYUV)\n+\t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)\n+\t\t\trawFormat = cfg.pixelFormat;\n+\t\telse\n \t\t\tbypassFormat = cfg.pixelFormat;\n \n \t\tmaxSize = std::max(maxSize, cfg.size);\n \t}\n \n-\tif (bypassFormat.isValid()) {\n+\t/* We want to prefer to use the RAW format if available */\n+\tif (rawFormat.isValid()) {\n+\t\tLOG(RkISP1, Info) << \"Using RAW format \" << rawFormat;\n+\t\tmbusCodes = { bypassFormats.at(rawFormat) };\n+\t} else if (bypassFormat.isValid()) {\n \t\tLOG(RkISP1, Info) << \"Using bypass format \" << bypassFormat;\n \t\tmbusCodes = { bypassFormats.at(bypassFormat) };\n \t} else {\ndiff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\nindex 903e1aaeb..dce0ed1d3 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n@@ -176,7 +176,6 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,\n \t/* Min and max resolutions to populate the available stream formats. */\n \tSize maxResolution = maxResolution_.boundedToAspectRatio(resolution)\n \t\t\t\t\t .boundedTo(resolution);\n-\tSize minResolution = minResolution_.expandedToAspectRatio(resolution);\n \n \t/* The desired stream size, bound to the max resolution. */\n \tSize streamSize = size.boundedTo(maxResolution);\n@@ -184,6 +183,7 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,\n \t/* Create the list of supported stream formats. */\n \tstd::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n \tunsigned int rawBitsPerPixel = 0;\n+\tPixelFormat bypassFormat;\n \tPixelFormat rawFormat;\n \n \tfor (const auto &format : streamFormats_) {\n@@ -193,8 +193,14 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,\n \t\tif (info.colourEncoding != PixelFormatInfo::ColourEncodingRAW) {\n \t\t\tif (role == StreamRole::Raw)\n \t\t\t\tcontinue;\n+\t\t\tfor (const auto &imageSize : sensor->sizes(formatToMediaBus.at(format))) {\n+\t\t\t\tif (imageSize.width > maxResolution_.width ||\n+\t\t\t\t imageSize.height > maxResolution_.height)\n+\t\t\t\t\tcontinue;\n \n-\t\t\tstreamFormats[format] = { { minResolution, maxResolution } };\n+\t\t\t\tstreamFormats[format].push_back({ imageSize, imageSize });\n+\t\t\t\tbypassFormat = format;\n+\t\t\t}\n \t\t\tcontinue;\n \t\t}\n \n@@ -243,7 +249,8 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,\n \t\t\tformat = rawFormat;\n \t\t}\n \t} else {\n-\t\tformat = formats::NV12;\n+\t\t/* Prefer RAW formats */\n+\t\tformat = rawFormat ? rawFormat : bypassFormat;\n \t}\n \n \tStreamFormats formats(streamFormats);\n@@ -269,18 +276,22 @@ RkISP1Path::validate(const CameraSensor *sensor,\n \t * Validate the pixel format. If the requested format isn't supported,\n \t * default to either NV12 (all versions of the ISP are guaranteed to\n \t * support NV12 on both the main and self paths) if the requested format\n-\t * is not a raw format, or to the supported raw format with the highest\n+\t * is not a raw or YUV format, or to the supported raw format with the highest\n \t * bits per pixel otherwise.\n \t */\n-\tunsigned int rawBitsPerPixel = 0;\n-\tPixelFormat rawFormat;\n+\tunsigned int bypassBitsPerPixel = 0;\n+\tPixelFormat bypassFormat;\n \tbool found = false;\n \n \tfor (const auto &format : streamFormats_) {\n \t\tconst PixelFormatInfo &info = PixelFormatInfo::info(format);\n \n+\t\t/*\n+\t\t * Even if the YUV format is a higher BPP, we still want to prefer\n+\t\t * the raw format, so we can do the processing ourselves.\n+\t\t */\n \t\tif (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) {\n-\t\t\t/* Skip raw formats not supported by the sensor. */\n+\t\t\t/* Skip formats not supported by the sensor. */\n \t\t\tuint32_t mbusCode = formatToMediaBus.at(format);\n \t\t\tif (std::find(mbusCodes.begin(), mbusCodes.end(), mbusCode) ==\n \t\t\t mbusCodes.end())\n@@ -295,9 +306,9 @@ RkISP1Path::validate(const CameraSensor *sensor,\n \t\t\tif (sensorConfig && info.bitsPerPixel != sensorConfig->bitDepth)\n \t\t\t\tcontinue;\n \n-\t\t\tif (info.bitsPerPixel > rawBitsPerPixel) {\n-\t\t\t\trawBitsPerPixel = info.bitsPerPixel;\n-\t\t\t\trawFormat = format;\n+\t\t\tif (info.bitsPerPixel > bypassBitsPerPixel) {\n+\t\t\t\tbypassBitsPerPixel = info.bitsPerPixel;\n+\t\t\t\tbypassFormat = format;\n \t\t\t}\n \t\t}\n \n@@ -307,26 +318,28 @@ RkISP1Path::validate(const CameraSensor *sensor,\n \t\t}\n \t}\n \n-\tif (sensorConfig && !rawFormat.isValid())\n+\tif (sensorConfig && !bypassFormat.isValid())\n \t\treturn CameraConfiguration::Invalid;\n \n-\tbool isRaw = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding ==\n-\t\t PixelFormatInfo::ColourEncodingRAW;\n+\tbool isIspBypassed = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding ==\n+\t\t\t PixelFormatInfo::ColourEncodingRAW ||\n+\t\t\t PixelFormatInfo::info(cfg->pixelFormat).colourEncoding ==\n+\t\t\t PixelFormatInfo::ColourEncodingYUV;\n \n \t/*\n \t * If no raw format supported by the sensor has been found, use a\n \t * processed format.\n \t */\n-\tif (!rawFormat.isValid())\n-\t\tisRaw = false;\n+\tif (!bypassFormat.isValid())\n+\t\tisIspBypassed = false;\n \n \tif (!found)\n-\t\tcfg->pixelFormat = isRaw ? rawFormat : formats::NV12;\n+\t\tcfg->pixelFormat = isIspBypassed ? bypassFormat : formats::NV12;\n \n \tSize minResolution;\n \tSize maxResolution;\n \n-\tif (isRaw) {\n+\tif (isIspBypassed) {\n \t\t/*\n \t\t * Use the sensor output size closest to the requested stream\n \t\t * size while ensuring the output size doesn't exceed ISP limits.\n@@ -338,11 +351,11 @@ RkISP1Path::validate(const CameraSensor *sensor,\n \t\tuint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);\n \t\tcfg->size.boundTo(resolution);\n \n-\t\tSize rawSize = sensorConfig ? sensorConfig->outputSize\n+\t\tSize bypassSize = sensorConfig ? sensorConfig->outputSize\n \t\t\t\t\t : cfg->size;\n \n \t\tV4L2SubdeviceFormat sensorFormat =\n-\t\t\tsensor->getFormat(std::array{ mbusCode }, rawSize);\n+\t\t\tsensor->getFormat(std::array{ mbusCode }, bypassSize);\n \n \t\tif (sensorConfig &&\n \t\t sensorConfig->outputSize != sensorFormat.size)\n@@ -352,7 +365,7 @@ RkISP1Path::validate(const CameraSensor *sensor,\n \t\tmaxResolution = sensorFormat.size;\n \t} else if (sensorConfig) {\n \t\t/*\n-\t\t * We have already ensured 'rawFormat' has the matching bit\n+\t\t * We have already ensured 'bypassFormat' has the matching bit\n \t\t * depth with sensorConfig.bitDepth hence, only validate the\n \t\t * sensorConfig's output size here.\n \t\t */\n@@ -361,7 +374,7 @@ RkISP1Path::validate(const CameraSensor *sensor,\n \t\tif (sensorSize > resolution)\n \t\t\treturn CameraConfiguration::Invalid;\n \n-\t\tuint32_t mbusCode = formatToMediaBus.at(rawFormat);\n+\t\tuint32_t mbusCode = formatToMediaBus.at(bypassFormat);\n \t\tV4L2SubdeviceFormat sensorFormat =\n \t\t\tsensor->getFormat(std::array{ mbusCode }, sensorSize);\n \n@@ -524,7 +537,8 @@ void RkISP1Path::stop()\n namespace {\n constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 };\n constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 };\n-constexpr std::array<PixelFormat, 18> RKISP1_RSZ_MP_FORMATS{\n+constexpr std::array<PixelFormat, 19> RKISP1_RSZ_MP_FORMATS{\n+\tformats::UYVY,\n \tformats::YUYV,\n \tformats::NV16,\n \tformats::NV61,\n", "prefixes": [ "RFC", "5/6" ] }