Patch Detail
Show a patch.
GET /api/patches/22058/?format=api
{ "id": 22058, "url": "https://patchwork.libcamera.org/api/patches/22058/?format=api", "web_url": "https://patchwork.libcamera.org/patch/22058/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20241122201305.1668098-2-mzamazal@redhat.com>", "date": "2024-11-22T20:13:04", "name": "[RFC,1/1] libcamera: simple: Fix raw output", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "9766ae2aab32f93e4327f1095a6826b7c804abc4", "submitter": { "id": 177, "url": "https://patchwork.libcamera.org/api/people/177/?format=api", "name": "Milan Zamazal", "email": "mzamazal@redhat.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/22058/mbox/", "series": [ { "id": 4814, "url": "https://patchwork.libcamera.org/api/series/4814/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4814", "date": "2024-11-22T20:13:03", "name": "Enable raw streams with software ISP", "version": 1, "mbox": "https://patchwork.libcamera.org/series/4814/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/22058/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/22058/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 4A2E7C3301\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 22 Nov 2024 20:13:22 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4AB9365FE3;\n\tFri, 22 Nov 2024 21:13:20 +0100 (CET)", "from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 77A7B65F51\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 22 Nov 2024 21:13:18 +0100 (CET)", "from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com\n\t(ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63])\n\tby relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n\tcipher=TLS_AES_256_GCM_SHA384) id us-mta-455-Lrxd60ntO8G7WNz21XXy2w-1;\n\tFri, 22 Nov 2024 15:13:16 -0500", "from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com\n\t[10.30.177.15])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (2048 bits)\n\tserver-digest SHA256) (No client certificate requested)\n\tby mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id 1E5B019560AF; Fri, 22 Nov 2024 20:13:15 +0000 (UTC)", "from nuthatch.redhat.com (unknown [10.45.224.2])\n\tby mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id 90A121955F43; Fri, 22 Nov 2024 20:13:13 +0000 (UTC)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"TE1gx9e8\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1732306397;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tcontent-transfer-encoding:content-transfer-encoding:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=osah4s1ASiDIZtvXJGEHzca7u6OxP5pS/RkoFMRcUwI=;\n\tb=TE1gx9e8xR2/95NxfhUO12XUw1ln571aJQLg6O77ptXlTibc3gu3hE7BS6Zq4Q01OIf8/g\n\tb1FfaWT1ZDQibnNnvyp38GiYs5jckUo3mhIWNOff196WZ1PSmo0OKgCbzqyU0fe9ePck91\n\touMF4FxhDOqaNZFKQGDrA9vCCZ399qU=", "X-MC-Unique": "Lrxd60ntO8G7WNz21XXy2w-1", "X-Mimecast-MFC-AGG-ID": "Lrxd60ntO8G7WNz21XXy2w", "From": "Milan Zamazal <mzamazal@redhat.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Milan Zamazal <mzamazal@redhat.com>,\n\tbryan.odonoghue@linaro.org", "Subject": "[RFC PATCH 1/1] libcamera: simple: Fix raw output", "Date": "Fri, 22 Nov 2024 21:13:04 +0100", "Message-ID": "<20241122201305.1668098-2-mzamazal@redhat.com>", "In-Reply-To": "<20241122201305.1668098-1-mzamazal@redhat.com>", "References": "<20241122201305.1668098-1-mzamazal@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.15", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "cGyjKETU95VWCvTLPHxJLP4Iu2seLtQ3n6nMyW6tW-8_1732306395", "X-Mimecast-Originator": "redhat.com", "Content-Transfer-Encoding": "8bit", "content-type": "text/plain; charset=\"US-ASCII\"; x-default=true", "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": "Simple pipeline was used to introduce software ISP. If software ISP is\nenabled, the pipeline always debayers the input and doesn't produce raw\noutput anymore, even when requested.\n\nThis patch fixes the problem and allows producing raw output if it is\nrequested, by specifying raw stream role. When raw output is requested,\nonly single stream (raw or processed) is allowed. This is not\nnecessarily an inherent property, it just simplifies the implementation\nand is sufficient for the current needs.\n\nIf raw stream is requested, it means raw as it is and no pixel format or\nsize conversions are permitted. This is not only logical but also\nsimplifying the changes because we don't have to check for raw when\nconversion is used.\n\nThe patch must deal with the fact that software ISP and its output\nconfigurations are arranged before we know whether a raw or a processed\nstream will be requested. This means that if software ISP is enabled\nthen it is always initialized and we store raw output configurations\ntogether with software ISP ones. We filter output configurations later\nas needed.\n\nThe raw output may not be useful without exposure and gain adjustments,\nit can be all black (or just noisy). This will be handled in a separate\npatch introducing manual gain and exposure controls.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n src/libcamera/pipeline/simple/simple.cpp | 66 +++++++++++++++++++-----\n 1 file changed, 54 insertions(+), 12 deletions(-)", "diff": "diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex 41fdf84cc..ec7cd7123 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -265,6 +265,7 @@ public:\n \t\tSize captureSize;\n \t\tstd::vector<PixelFormat> outputFormats;\n \t\tSizeRange outputSizes;\n+\t\tbool swisp;\n \t};\n \n \tstd::vector<Stream> streams_;\n@@ -289,6 +290,7 @@ public:\n \t};\n \tstd::queue<RequestOutputs> conversionQueue_;\n \tbool useConversion_;\n+\tbool isRaw_;\n \n \tstd::unique_ptr<Converter> converter_;\n \tstd::unique_ptr<SoftwareIsp> swIsp_;\n@@ -646,19 +648,24 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size)\n \t\tconfig.sensorSize = size;\n \t\tconfig.captureFormat = pixelFormat;\n \t\tconfig.captureSize = format.size;\n+\t\tconfig.swisp = false;\n \n \t\tif (converter_) {\n \t\t\tconfig.outputFormats = converter_->formats(pixelFormat);\n \t\t\tconfig.outputSizes = converter_->sizes(format.size);\n-\t\t} else if (swIsp_) {\n-\t\t\tconfig.outputFormats = swIsp_->formats(pixelFormat);\n-\t\t\tconfig.outputSizes = swIsp_->sizes(pixelFormat, format.size);\n-\t\t\tif (config.outputFormats.empty()) {\n-\t\t\t\t/* Do not use swIsp for unsupported pixelFormat's. */\n-\t\t\t\tconfig.outputFormats = { pixelFormat };\n-\t\t\t\tconfig.outputSizes = config.captureSize;\n-\t\t\t}\n \t\t} else {\n+\t\t\tif (swIsp_) {\n+\t\t\t\tConfiguration swispConfig = config;\n+\t\t\t\tswispConfig.outputFormats = swIsp_->formats(pixelFormat);\n+\t\t\t\tswispConfig.outputSizes = swIsp_->sizes(pixelFormat, format.size);\n+\t\t\t\tif (swispConfig.outputFormats.empty()) {\n+\t\t\t\t\t/* Do not use swIsp for unsupported pixelFormat's. */\n+\t\t\t\t\tswispConfig.outputFormats = { pixelFormat };\n+\t\t\t\t\tswispConfig.outputSizes = swispConfig.captureSize;\n+\t\t\t\t}\n+\t\t\t\tswispConfig.swisp = true;\n+\t\t\t\tconfigs_.push_back(swispConfig);\n+\t\t\t}\n \t\t\tconfig.outputFormats = { pixelFormat };\n \t\t\tconfig.outputSizes = config.captureSize;\n \t\t}\n@@ -859,7 +866,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n \n \t\tif (converter_)\n \t\t\tconverter_->queueBuffers(buffer, conversionQueue_.front().outputs);\n-\t\telse\n+\t\telse if (!isRaw_) {\n \t\t\t/*\n \t\t\t * request->sequence() cannot be retrieved from `buffer' inside\n \t\t\t * queueBuffers because unique_ptr's make buffer->request() invalid\n@@ -867,6 +874,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n \t\t\t */\n \t\t\tswIsp_->queueBuffers(request->sequence(), buffer,\n \t\t\t\t\t conversionQueue_.front().outputs);\n+\t\t}\n \n \t\tconversionQueue_.pop();\n \t\treturn;\n@@ -1049,6 +1057,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n \tpipeConfig_ = nullptr;\n \n \tfor (const SimpleCameraData::Configuration *pipeConfig : *configs) {\n+\t\tif (pipeConfig->swisp == data_->isRaw_)\n+\t\t\tcontinue;\n \t\tconst Size &size = pipeConfig->captureSize;\n \n \t\tif (size.width >= maxStreamSize.width &&\n@@ -1099,6 +1109,13 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n \n \t\tPixelFormat pixelFormat = *it;\n \t\tif (cfg.pixelFormat != pixelFormat) {\n+\t\t\tif (data_->isRaw_) {\n+\t\t\t\tLOG(SimplePipeline, Error)\n+\t\t\t\t\t<< \"Cannot convert pixel format with raw output (from \"\n+\t\t\t\t\t<< cfg.pixelFormat << \" to \"\n+\t\t\t\t\t<< pixelFormat << \")\";\n+\t\t\t\treturn Invalid;\n+\t\t\t}\n \t\t\tLOG(SimplePipeline, Debug) << \"Adjusting pixel format\";\n \t\t\tcfg.pixelFormat = pixelFormat;\n \t\t\tstatus = Adjusted;\n@@ -1112,8 +1129,16 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n \t\t\t * not guaranteed to be a valid output size. In such cases, use\n \t\t\t * the smaller valid output size closest to the requested.\n \t\t\t */\n-\t\t\tif (!pipeConfig_->outputSizes.contains(adjustedSize))\n+\t\t\tif (!pipeConfig_->outputSizes.contains(adjustedSize)) {\n+\t\t\t\tif (data_->isRaw_) {\n+\t\t\t\t\tLOG(SimplePipeline, Error)\n+\t\t\t\t\t\t<< \"Cannot adjust output size with raw output (from \"\n+\t\t\t\t\t\t<< cfg.pixelFormat << \" to \"\n+\t\t\t\t\t\t<< pixelFormat << \")\";\n+\t\t\t\t\treturn Invalid;\n+\t\t\t\t}\n \t\t\t\tadjustedSize = adjustSize(cfg.size, pipeConfig_->outputSizes);\n+\t\t\t}\n \t\t\tLOG(SimplePipeline, Debug)\n \t\t\t\t<< \"Adjusting size from \" << cfg.size\n \t\t\t\t<< \" to \" << adjustedSize;\n@@ -1174,12 +1199,29 @@ SimplePipelineHandler::generateConfiguration(Camera *camera, Span<const StreamRo\n \tif (roles.empty())\n \t\treturn config;\n \n+\tbool raw = false;\n+\tfor (auto &role : roles) {\n+\t\tif (role == StreamRole::Raw) {\n+\t\t\traw = true;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (raw && roles.size() > 1) {\n+\t\tLOG(SimplePipeline, Error)\n+\t\t\t<< \"Can't capture multiple streams with a raw stream\";\n+\t\treturn nullptr;\n+\t}\n+\tdata->isRaw_ = raw;\n+\tLOG(SimplePipeline, Debug) << \"Raw stream requested: \" << raw;\n+\n \t/* Create the formats map. */\n \tstd::map<PixelFormat, std::vector<SizeRange>> formats;\n \n \tfor (const SimpleCameraData::Configuration &cfg : data->configs_) {\n-\t\tfor (PixelFormat format : cfg.outputFormats)\n-\t\t\tformats[format].push_back(cfg.outputSizes);\n+\t\tif (raw != cfg.swisp) {\n+\t\t\tfor (PixelFormat format : cfg.outputFormats)\n+\t\t\t\tformats[format].push_back(cfg.outputSizes);\n+\t\t}\n \t}\n \n \t/* Sort the sizes and merge any consecutive overlapping ranges. */\n", "prefixes": [ "RFC", "1/1" ] }