Patch Detail
Show a patch.
GET /api/patches/26252/?format=api
{ "id": 26252, "url": "https://patchwork.libcamera.org/api/patches/26252/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26252/", "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": "<20260304075052.11599-4-johannes.goede@oss.qualcomm.com>", "date": "2026-03-04T07:50:50", "name": "[v5,3/5] software_isp: debayer_cpu: Add multi-threading support", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "0d8c510359a5a317aa2562d3b349157ad116aa3d", "submitter": { "id": 242, "url": "https://patchwork.libcamera.org/api/people/242/?format=api", "name": "Hans de Goede", "email": "johannes.goede@oss.qualcomm.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26252/mbox/", "series": [ { "id": 5817, "url": "https://patchwork.libcamera.org/api/series/5817/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5817", "date": "2026-03-04T07:50:47", "name": "software_isp: debayer_cpu: Add multi-threading support", "version": 5, "mbox": "https://patchwork.libcamera.org/series/5817/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26252/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26252/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 28680C32EF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 4 Mar 2026 07:51:06 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BD656623A8;\n\tWed, 4 Mar 2026 08:51:05 +0100 (CET)", "from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com\n\t[205.220.168.131])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 71E9A6239C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 4 Mar 2026 08:51:02 +0100 (CET)", "from pps.filterd (m0279866.ppops.net [127.0.0.1])\n\tby mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n\t6245SiB8152731 for <libcamera-devel@lists.libcamera.org>;\n\tWed, 4 Mar 2026 07:51:00 GMT", "from mail-qk1-f200.google.com (mail-qk1-f200.google.com\n\t[209.85.222.200])\n\tby mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cp3tvjnpf-1\n\t(version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 04 Mar 2026 07:50:59 +0000 (GMT)", "by mail-qk1-f200.google.com with SMTP id\n\taf79cd13be357-8c70b6a5821so3532893485a.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 03 Mar 2026 23:50:59 -0800 (PST)", "from shalem\n\t(2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl.\n\t[2001:1c00:c32:7800:5bfa:a036:83f0:f9ec])\n\tby smtp.gmail.com with ESMTPSA id\n\ta640c23a62f3a-b935ac73a5dsm693263366b.25.2026.03.03.23.50.57\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tTue, 03 Mar 2026 23:50:57 -0800 (PST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=qualcomm.com header.i=@qualcomm.com\n\theader.b=\"LryNL55/\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n\theader.b=\"kNFev4bo\"; dkim-atps=neutral", "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n\tcc:content-transfer-encoding:date:from:in-reply-to:message-id\n\t:mime-version:references:subject:to; s=qcppdkim1; bh=2pTT2vd9CrP\n\tiuo7G72w3VpawJDhZAO0mN9LyY+btYmM=; b=LryNL55/S7qHtwXA63kzh/HyvPP\n\tRVCxLNEPfb8MAU7e0yE7g1TLb7B+FECzIwHIDxp3rUFREGToEFWUVpBp/yEyQcmi\n\taVWSQskdD5EKQeXb1+S52D9vbPaF2pGPbr0I/s7c7KpvRTpJRLYEF5wA4S+d5TDV\n\tjigGw7bBC12dF+vmm5u95WMU5eMOIvHwHECS2fLAC8YSWpgtGktUzM0JhQ6jscPQ\n\tOAweCUitnlmgRwtiRPIrSGoz7W/MqZiLiMtVJ13ym5QuDe2plE3TqQxdVlHtlBor\n\tlKe+1SHx/7byhMuOjbFZdEAQ/bE1PdSa57C4KrigwSFLsFk0toRccQMmawg==", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=oss.qualcomm.com; s=google; t=1772610658; x=1773215458;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=2pTT2vd9CrPiuo7G72w3VpawJDhZAO0mN9LyY+btYmM=;\n\tb=kNFev4boXZFvkOCB+hBVMwg/bx220UHss050Lfj4kky8pZg/E2Gpkxtv8cqK4nZu6f\n\tqg9NM75zPqpcGaUZKLnjN0hpF1g2CwWTiRsg8D0NbxKfBzN5hsp4iN42CZ00IU61Iry2\n\tTMhqYUswcqn+jTgtjKYHa954PDhdcZTzlHnRtPYwqLyvXwjC7+5J+ZcYNHHyAZ0m6Pcr\n\tkmn5fNynu9fdS4jCHvw0wOrhiYCOg8dRnM2FKtfqbXHu4F9c9q3ILqopOubVrsQzqTe+\n\t2O4GK0OmrgE1qfKOz1cjCDqbm0v0h8LmEm+NHfStU3UsLjE/hlvOiz2WfzkvUTDvK8xy\n\tJz4g==" ], "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1772610658; x=1773215458;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n\t:to:cc:subject:date:message-id:reply-to;\n\tbh=2pTT2vd9CrPiuo7G72w3VpawJDhZAO0mN9LyY+btYmM=;\n\tb=rcr1FJuX8rE4BXG83HqV5OttLwXAXqS4033pIvZmKLaE5f3u5vBJXGqJaSpM8IRgkH\n\tDnJxC6BtW8JY1nDmapRuvshLOBfYOncj68pDIblh0t9r6jx6xUNUEQ+61TKc0GQDQ6Ag\n\tCHsLRsbME+dWjKqYCpMiTwnAGQitQXyOmkiSomYOrm4NFpH7JhkNg5Mp0b3ul9VvLYo1\n\tqyHV7ugAY5BA1gB47CFWlFQ+F5vjRxYNKaiTLZ7dz4TL4UxMQ748BAecuq80reFG39/5\n\tLqJxUDYYieEbIxvmvBpTyHMNowQJ/fHYhmQ7NJVRVaoR/igFsLDq67wTNMM7roIO8MEw\n\tgUBA==", "X-Gm-Message-State": "AOJu0YycYX1D1WZpadjxnyZVCktJ7Rjfc8QN2fvPFYAcv5A0f5w7ki/k\n\tkF7mlIRRop6BEDfZFthAl2TvCJHHss8ubwEeZAHvSPnuzBnAucTh23ObeWcUIWKHwwxibvLYKHu\n\tYEzRzwXagwLRAyV2c9K3ZvdZnc0f0SLW6sEO7Z22bfskWt9xSBbSMVBIl8O+2yPipaxmm/mWkbh\n\t6oQjF4jFSC", "X-Gm-Gg": "ATEYQzzK8jvHC8yMnowrpHChafcllD/bjQZSiTiLvqC4+bKXxzLCwAmgJRLDa5x6eQZ\n\tqE/IAS5yj48VX5d42+iHENf8RNBcKX89cPX7PljTed91Xk3bvkwrLI9JwpUSo30ZhMnkToPOoa3\n\tdCy443z1NxBtpGdfO+7JWu9GdUyo9hTpyeYOiKu83WcsZzBvs/Re74o/Flkk6xNmfmJ2hBigx1m\n\tlJ6pgMRDvdHZcn27jLPUqjN21zl8B0I6J6THxsunzvO7eksFjC8TgoM8h6hBQIhX0KjN5enBcfF\n\tNlVNaGHRdsKyD1roUPhZUCW4Vfb0aZSKO80ykHOdJRUErJejqVkCikrsD80fVB4RaBC4A8b60vg\n\tj3ELIjnREL2bYcQnlLv8+wcenCAXXdjwBgtICTwlkdQhqzVkc3rwD7fQmpANAGSFTj5apxKw3PS\n\tGaIc4hki26LpMo8drsEcZcinSzUkPiLDUSLQBq", "X-Received": [ "by 2002:a05:620a:25cf:b0:8b2:ec1e:fe24 with SMTP id\n\taf79cd13be357-8cd5af7852dmr133029085a.42.1772610658371; \n\tTue, 03 Mar 2026 23:50:58 -0800 (PST)", "by 2002:a05:620a:25cf:b0:8b2:ec1e:fe24 with SMTP id\n\taf79cd13be357-8cd5af7852dmr133028185a.42.1772610657870; \n\tTue, 03 Mar 2026 23:50:57 -0800 (PST)" ], "From": "Hans de Goede <johannes.goede@oss.qualcomm.com>", "To": "libcamera-devel@lists.libcamera.org, Milan Zamazal <mzamazal@redhat.com>", "Cc": "Hans de Goede <johannes.goede@oss.qualcomm.com>", "Subject": "[PATCH v5 3/5] software_isp: debayer_cpu: Add multi-threading\n\tsupport", "Date": "Wed, 4 Mar 2026 08:50:50 +0100", "Message-ID": "<20260304075052.11599-4-johannes.goede@oss.qualcomm.com>", "X-Mailer": "git-send-email 2.52.0", "In-Reply-To": "<20260304075052.11599-1-johannes.goede@oss.qualcomm.com>", "References": "<20260304075052.11599-1-johannes.goede@oss.qualcomm.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Proofpoint-Spam-Details-Enc": "AW1haW4tMjYwMzA0MDA2MiBTYWx0ZWRfX04yOHmJTkvo+\n\t0fnprhJIhRyBGL9DNZAcLsV1kA4PA2fhQlv9tYhDb5xrM6rstxfQHSVqSXI5j6kRbEXaQHQQ9U6\n\tjyUVRCG4dEeVTHzYQirYs+72abiJfE1X9yGMURCo+Deuf4xIAxq56lomsw2ufSuAjBUUtXMMt35\n\tHYscxBJ9BIDo2a4Z5zKopBJBQ//nWujgzqRNYkMbzGK5cVxd8jE37gRWtqMvhuq4pH432LpPZLM\n\tYVOOmHmRPxesw55Efzfnb38clqvx4FHwtLMHPWENRp/0mPZMoP7Yr2bd7SA/CZqY3huqUs/pFkO\n\tSMXQj7ZwAcAEj149KMSO/jwLHPeisq9Ov7HO9YPdKjTxTh6sC3gsqH2foHZx8eCnAkZ4iIBiaTe\n\tAbUlWNDhJdafLypHz8eirxvnIVpL29OOhAqym8HiQ4s/IgXiyLs2eOqcjS+IbhC3qbSZVLjWeQl\n\tSJAogZ7d5BkW+T3LjHA==", "X-Authority-Analysis": "v=2.4 cv=VYv6/Vp9 c=1 sm=1 tr=0 ts=69a7e463 cx=c_pps\n\ta=hnmNkyzTK/kJ09Xio7VxxA==:117 a=xqWC_Br6kY4A:10 a=Yq5XynenixoA:10\n\ta=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22\n\ta=YMgV9FUhrdKAYTUUvYB2:22 a=EUspDBNiAAAA:8 a=4i1XYD-pSnUufzSozdQA:9\n\ta=PEH46H7Ffwr30OY-TuGO:22", "X-Proofpoint-GUID": "qVGW4iuvJhaBZHaEVmSlfEUl9BBZrR9a", "X-Proofpoint-ORIG-GUID": "qVGW4iuvJhaBZHaEVmSlfEUl9BBZrR9a", "X-Proofpoint-Virus-Version": "vendor=baseguard\n\tengine=ICAP:2.0.293, Aquarius:18.0.1121, Hydra:6.1.51,\n\tFMLib:17.12.100.49\n\tdefinitions=2026-03-04_02,2026-03-03_01,2025-10-01_01", "X-Proofpoint-Spam-Details": "rule=outbound_notspam policy=outbound score=0\n\tclxscore=1015 lowpriorityscore=0 suspectscore=0 bulkscore=0\n\tadultscore=0\n\tspamscore=0 phishscore=0 priorityscore=1501 impostorscore=0\n\tmalwarescore=0\n\tclassifier=typeunknown authscore=0 authtc= authcc= route=outbound\n\tadjust=0\n\treason=mlx scancount=1 engine=8.22.0-2602130000\n\tdefinitions=main-2603040062", "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": "Add CPU soft ISP multi-threading support.\n\nBenchmark results for the Arduino Uno-Q with a weak CPU which is good for\nperformance testing, all numbers with an IMX219 running at\n3280x2464 -> 3272x2464:\n\n1 thread : 147ms / frame, ~6.5 fps\n2 threads: 80ms / frame, ~12.5 fps\n3 threads: 65ms / frame, ~15 fps\n\nAdding a 4th thread does not improve performance.\n\nSigned-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>\n---\nChanges in v5:\n- Extend software_isp.threads docs in runtime_configuration.rst\n\nChanges in v4:\n- Document software_isp.threads option in runtime_configuration.rst\n- Add an use constants for min/max/default number of threads\n\nChanges in v3:\n- Adjust for DebayerCpuThread now inheriting from Thread\n- Use for (auto &thread : threads_)\n\nChanges in v2:\n- Adjust to use the new DebayerCpuThread class introduced in the v2 patch-series\n- Re-use threads instead of starting new threads every frame\n---\n Documentation/runtime_configuration.rst | 8 ++++\n src/libcamera/software_isp/debayer_cpu.cpp | 45 ++++++++++++++++++++--\n src/libcamera/software_isp/debayer_cpu.h | 10 +++++\n 3 files changed, 60 insertions(+), 3 deletions(-)", "diff": "diff --git a/Documentation/runtime_configuration.rst b/Documentation/runtime_configuration.rst\nindex e99ef2fb9..651929a4d 100644\n--- a/Documentation/runtime_configuration.rst\n+++ b/Documentation/runtime_configuration.rst\n@@ -51,6 +51,7 @@ file structure:\n measure:\n skip: # non-negative integer, frames to skip initially\n number: # non-negative integer, frames to measure\n+ threads: # integer >= 1, number of render threads to use, default 2\n \n Configuration file example\n --------------------------\n@@ -84,6 +85,7 @@ Configuration file example\n measure:\n skip: 50\n number: 30\n+ threads: 2\n \n List of variables and configuration options\n -------------------------------------------\n@@ -167,6 +169,12 @@ software_isp.measure.skip, software_isp.measure.number\n \n Example `number` value: ``30``\n \n+software_isp.threads\n+ Number of render threads the software ISP uses when using the CPU.\n+ This must be between 1 and 8 and the default is 2.\n+\n+ Example value: ``2``\n+\n Further details\n ---------------\n \ndiff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\nindex d57d640df..f7c3e1751 100644\n--- a/src/libcamera/software_isp/debayer_cpu.cpp\n+++ b/src/libcamera/software_isp/debayer_cpu.cpp\n@@ -76,6 +76,7 @@ DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex\n \t debayer_(debayer), threadIndex_(threadIndex),\n \t enableInputMemcpy_(enableInputMemcpy)\n {\n+\tmoveToThread(this);\n }\n \n /**\n@@ -107,8 +108,10 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats, const GlobalConfigurat\n \tbool enableInputMemcpy =\n \t\tconfiguration.option<bool>({ \"software_isp\", \"copy_input_buffer\" }).value_or(true);\n \n-\t/* Just one thread object for now, which will be called inline rather than async */\n-\tthreads_.resize(1);\n+\tunsigned int threadCount =\n+\t\tconfiguration.option<unsigned int>({ \"software_isp\", \"threads\" }).value_or(kDefaultThreads);\n+\tthreadCount = std::clamp(threadCount, kMinThreads, kMaxThreads);\n+\tthreads_.resize(threadCount);\n \n \tfor (unsigned int i = 0; i < threads_.size(); i++)\n \t\tthreads_[i] = std::make_unique<DebayerCpuThread>(this, i, enableInputMemcpy);\n@@ -746,6 +749,11 @@ void DebayerCpuThread::process(uint32_t frame, const uint8_t *src, uint8_t *dst)\n \t\tprocess2(frame, src, dst);\n \telse\n \t\tprocess4(frame, src, dst);\n+\n+\tdebayer_->workPendingMutex_.lock();\n+\tdebayer_->workPending_ &= ~(1 << threadIndex_);\n+\tdebayer_->workPendingMutex_.unlock();\n+\tdebayer_->workPendingCv_.notify_one();\n }\n \n void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst)\n@@ -985,7 +993,21 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \n \tstats_->startFrame(frame);\n \n-\tthreads_[0]->process(frame, in.planes()[0].data(), out.planes()[0].data());\n+\tworkPendingMutex_.lock();\n+\tworkPending_ = (1 << threads_.size()) - 1;\n+\tworkPendingMutex_.unlock();\n+\n+\tfor (auto &thread : threads_)\n+\t\tthread->invokeMethod(&DebayerCpuThread::process,\n+\t\t\t\t ConnectionTypeQueued, frame,\n+\t\t\t\t in.planes()[0].data(), out.planes()[0].data());\n+\n+\t{\n+\t\tMutexLocker locker(workPendingMutex_);\n+\t\tworkPendingCv_.wait(locker, [&]() LIBCAMERA_TSA_REQUIRES(workPendingMutex_) {\n+\t\t\treturn workPending_ == 0;\n+\t\t});\n+\t}\n \n \tmetadata.planes()[0].bytesused = out.planes()[0].size();\n \n@@ -1004,6 +1026,23 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \tinputBufferReady.emit(input);\n }\n \n+int DebayerCpu::start()\n+{\n+\tfor (auto &thread : threads_)\n+\t\tthread->start();\n+\n+\treturn 0;\n+}\n+\n+void DebayerCpu::stop()\n+{\n+\tfor (auto &thread : threads_)\n+\t\tthread->exit();\n+\n+\tfor (auto &thread : threads_)\n+\t\tthread->wait();\n+}\n+\n SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize)\n {\n \tSize patternSize = this->patternSize(inputFormat);\ndiff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\nindex 780576090..11280c0a1 100644\n--- a/src/libcamera/software_isp/debayer_cpu.h\n+++ b/src/libcamera/software_isp/debayer_cpu.h\n@@ -16,6 +16,7 @@\n #include <vector>\n \n #include <libcamera/base/object.h>\n+#include <libcamera/base/mutex.h>\n \n #include \"libcamera/internal/bayer_format.h\"\n #include \"libcamera/internal/global_configuration.h\"\n@@ -41,6 +42,8 @@ public:\n \tstd::tuple<unsigned int, unsigned int>\n \tstrideAndFrameSize(const PixelFormat &outputFormat, const Size &size);\n \tvoid process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms);\n+\tint start();\n+\tvoid stop();\n \tSizeRange sizes(PixelFormat inputFormat, const Size &inputSize);\n \tconst SharedFD &getStatsFD() { return stats_->getStatsFD(); }\n \n@@ -144,6 +147,13 @@ private:\n \tstd::unique_ptr<SwStatsCpu> stats_;\n \tunsigned int xShift_; /* Offset of 0/1 applied to window_.x */\n \n+\tstatic constexpr unsigned int kMinThreads = 1;\n+\tstatic constexpr unsigned int kMaxThreads = 8;\n+\tstatic constexpr unsigned int kDefaultThreads = 2;\n+\n+\tunsigned int workPending_ LIBCAMERA_TSA_GUARDED_BY(workPendingMutex_);\n+\tMutex workPendingMutex_;\n+\tConditionVariable workPendingCv_;\n \tstd::vector<std::unique_ptr<DebayerCpuThread>>threads_;\n };\n \n", "prefixes": [ "v5", "3/5" ] }