From patchwork Tue Feb 24 19:37:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 26233 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 1AAE7C0DA4 for ; Tue, 24 Feb 2026 19:37:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B8BF8622E3; Tue, 24 Feb 2026 20:37:54 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="o7AYJKKg"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Cc3+kVW6"; dkim-atps=neutral Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EF724622AE for ; Tue, 24 Feb 2026 20:37:51 +0100 (CET) Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61OICGh2057305 for ; Tue, 24 Feb 2026 19:37:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=5//7ZazaTSh rjC8C7EEiB8EeyQWURuIBSfCyUyz5LZc=; b=o7AYJKKgsZNLQ6cS8PoG0twOOZZ /Dat3Ms9ylGPzfbMAEI2dqd8pCRNOoXA3yYFgHFhw6BlwDE1fgaz0fpVGoziV9JJ Lfpus86QRAiOly2yZdIBnIF63WUGpAHBwyawerun4sAOBGkxQxW8egKs1PcWRKs4 ElDwTN7qcIAuJlXGEiD+e+sN8plmZN9o49j4JIkqckQDHE3BZRKMPFXlWImf6Z/Y gdYQKPnu6IbyGjMXhSK0QYQIyz3hhDtCHf1lTf37hCe5oA1gDK5JIEvLs4wOVE0R aL9HCGwF5ksYMpqq4YRsAFlCDBoCpt2kXWSasm4orxhVmrdmUSsUuJ4z6JA== Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ch9sa9vxk-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 24 Feb 2026 19:37:50 +0000 (GMT) Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-8c7166a4643so5440105685a.0 for ; Tue, 24 Feb 2026 11:37:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771961869; x=1772566669; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5//7ZazaTShrjC8C7EEiB8EeyQWURuIBSfCyUyz5LZc=; b=Cc3+kVW6W7cRNmn2dX5YtL8qXIzO8V12ByUfOSthj7uJhK/WlUPv67N9VDTHff35Ki dqWTc4zVPGC9Q3WM4xFoNaGt8w2MsSxa2jqEyi7yDeesZ0hsHXgO93jV/z5d6fqBNajh KtAT2ikI7GLmxTrV0c0T4vH05SSz3XzNr6bVpv7ENr+CkJtGQ63+b9NX9xAXVnPE8U9P Lclw7j5RePUa27PQ9s2rjQDBJ//mSu42UHvzya7YJOEe+kSEZcLyA/kRem1Zl3TqLGFv AFkRQa3brUf+vh4CRVmcmqgwV0Ug2rOfCehKnXWlXFSl70MM2iSC/bnvKrc9budA6YIA S4xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771961869; x=1772566669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5//7ZazaTShrjC8C7EEiB8EeyQWURuIBSfCyUyz5LZc=; b=LnHerFfOlJc7QIUtVzMocRazY+AdTU8Uzfc0ROMXlLfe+O/KaG8Q9ixCm/9JxLoY/I 4Uad7EIFcT0BFKFbPnk5tybruO5Z0bqPsWRBVjpnhZ9x9CqThQI4DrCOOCryPm+KIbEE stlWa3glofzs8yTbYpAS/nfdjL7j8a00PXyj9Vg8DiuYVjFZwvGDKgsD7IGm7QzM//F+ NkdjwopsQtu3CjgVSoCbDI95ktQuTrIYEc28EF4vgq/56+kTwJcScKDj6NBwWYpo815J 5mtre6lU9h6m/Q/wNSmFUQDRw2EfQCAyvsMqoBe+ODSExMv3GLEy49gndQSb/DWEkFAy xaXg== X-Gm-Message-State: AOJu0Yydns8TRdGJrODFQ7m/ZOPHyPAp2MQAVbzOFOzWXyBTCPvNgRCm Q/6UCWj8f8OB3a6Yfe46wOgB10kUKUltaZxnPFwaJbHQWyoToL0zr5ou7q+UXZ4AOrV0ohWI2g4 F/JgR2nl7B7Z3tuZ50MJE1HWhGuaPtRH/PqiE4sTO4h6pOrrTWXWcjYgRV5jzffgvl2tSYfu7qU Y0bCkoLJxQ X-Gm-Gg: AZuq6aJ2jklwrgo1elPCBgrrH59y8rAw5etwmnYefTFUYTxLJKuJ0DvyhLL59vfGIxR DmlnjTNNnDrv02ECdNYxTzKBeFAfSIareMAYCPY8+iZUt+a9toyRGqnC8FyqNkuGJGhotz97Vap YkeCvNZsNCYpzSCVuiWRlqC+xKfw/84xI5Xy58IOSaqj4yXpgQ7QBcn1XHTA82Ks9lvXjuS1Y7W d9fKjJVvuSTEu+hkTmuHG+Lft64wqSFGa1v39Danqqd78V9gPZQhbjd5SKrbhfU6e9rENAeD03Y HsDZfr4PAVF1zqoICmWcEg2N0irkWD3uSh5hrdDWNXHh1A8viaqNZRNDxHXHCE5KD/VpTAsBAHZ Zd731dR/jY1EjdEoWQDSDx2wzhat6hobOJMDncPZPx74DfSwTmUbNsSIxmrTYr+hkVoZokB/Pte juaDjS9sjC5SXELM3oBOiABDh24kWM33TfDuWC X-Received: by 2002:a05:620a:f04:b0:8ca:3d7c:e74a with SMTP id af79cd13be357-8cb8ca7fac2mr1343406085a.56.1771961868792; Tue, 24 Feb 2026 11:37:48 -0800 (PST) X-Received: by 2002:a05:620a:f04:b0:8ca:3d7c:e74a with SMTP id af79cd13be357-8cb8ca7fac2mr1343401685a.56.1771961868104; Tue, 24 Feb 2026 11:37:48 -0800 (PST) Received: from shalem (2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl. [2001:1c00:c32:7800:5bfa:a036:83f0:f9ec]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084e8cb3fsm458232866b.48.2026.02.24.11.37.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 11:37:47 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org, Milan Zamazal Cc: Hans de Goede Subject: [PATCH v3 1/4] software_isp: swstats_cpu: Prepare for multi-threading support Date: Tue, 24 Feb 2026 20:37:42 +0100 Message-ID: <20260224193745.106186-2-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> References: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjI0MDE2OCBTYWx0ZWRfX96OtKGSsy2Px UFl/K4SyfGxY7wOJtgJU4w5OiGMEjvrcIpA1AF03mUm58k4loyjaSHT0VH+dB7vyCF61w6RXRtC aoZM95J8BI3rEUxN8p3CAwy689IVi1hFk3+LqUImIf+MXXi+o0KM1Wo0g68aE2Qfjw1YYk0lWJ1 NkAeYTMnHxHUl27TymDL7U4ZEzHcdgUId704hKg82NW2mWa0gTJ5m4efXnWbb6T6vMSfq6SnYVz XdtEpT5f9hkdb/6fbfVgUHQurNAIOWd+TaLFKJXg5RZNOt7+xMcCKxHZ11rJ3DKxRjs49WszBAD Fn79sovGa+s8ltr1c9qMU4Z6n6CAeALYpWDCaFsd4pNnny2YrwiXWK6NyAE/T/L+0jNCEnL+VSc O9Pt3kwj5hTRuQVOmpKxkCSYjyXN4cAl1poLoZh8W1DFbX8C85TnMa2u+wGSXlMu7h1gG+u8ZQr cgSbF/zunQiAiDpwNew== X-Proofpoint-ORIG-GUID: Un7l6alY7RW7IOB1Mh72NltnAk4PR6zH X-Authority-Analysis: v=2.4 cv=e7ELiKp/ c=1 sm=1 tr=0 ts=699dfe0e cx=c_pps a=qKBjSQ1v91RyAK45QCPf5w==:117 a=xqWC_Br6kY4A:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_K5XuSEh1TEqbUxoQ0s3:22 a=EUspDBNiAAAA:8 a=VvikW9XIONpR7lsxkDIA:9 a=NFOGd7dJGGMPyQGDc5-O:22 X-Proofpoint-GUID: Un7l6alY7RW7IOB1Mh72NltnAk4PR6zH X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293, Aquarius:18.0.1121, Hydra:6.1.51, FMLib:17.12.100.49 definitions=2026-02-24_02,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 adultscore=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 clxscore=1015 phishscore=0 spamscore=0 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602240168 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" Make the storage used to accumulate the RGB sums and the Y histogram value a vector of SwIspStats objects instead of a single object so that when using multi-threading every thread can use its own storage to collect intermediate stats to avoid cache-line bouncing. Benchmarking with the GPU-ISP which does separate swstats benchmarking, on the Arduino Uno-Q which has a weak CPU which is good for performance testing, shows 20ms to generate stats for a 3272x2464 frame both before and after this change. Signed-off-by: Hans de Goede --- Changes in v3: - Use for (auto &s : stats_) {} Changes in v2: - Move the allocation of the vector of SwIspStats objects to inside the SwStatsCpu class, controlled by a configure() arguments instead of making the caller allocate the objects --- .../internal/software_isp/swstats_cpu.h | 25 ++++----- src/libcamera/software_isp/swstats_cpu.cpp | 54 +++++++++++++------ 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 64b3e23f..feee92f9 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include @@ -51,13 +52,13 @@ public: const Size &patternSize() { return patternSize_; } - int configure(const StreamConfiguration &inputCfg); + int configure(const StreamConfiguration &inputCfg, unsigned int statsBufferCount = 1); void setWindow(const Rectangle &window); void startFrame(uint32_t frame); void finishFrame(uint32_t frame, uint32_t bufferId); void processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input); - void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[]) + void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[], unsigned int statsBufferIndex = 0) { if (frame % kStatPerNumFrames) return; @@ -66,10 +67,10 @@ public: y >= (window_.y + window_.height)) return; - (this->*stats0_)(src); + (this->*stats0_)(src, stats_[statsBufferIndex]); } - void processLine2(uint32_t frame, unsigned int y, const uint8_t *src[]) + void processLine2(uint32_t frame, unsigned int y, const uint8_t *src[], unsigned int statsBufferIndex = 0) { if (frame % kStatPerNumFrames) return; @@ -78,25 +79,25 @@ public: y >= (window_.y + window_.height)) return; - (this->*stats2_)(src); + (this->*stats2_)(src, stats_[statsBufferIndex]); } Signal statsReady; private: - using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]); + using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[], SwIspStats &stats); using processFrameFn = void (SwStatsCpu::*)(MappedFrameBuffer &in); int setupStandardBayerOrder(BayerFormat::Order order); /* Bayer 8 bpp unpacked */ - void statsBGGR8Line0(const uint8_t *src[]); + void statsBGGR8Line0(const uint8_t *src[], SwIspStats &stats); /* Bayer 10 bpp unpacked */ - void statsBGGR10Line0(const uint8_t *src[]); + void statsBGGR10Line0(const uint8_t *src[], SwIspStats &stats); /* Bayer 12 bpp unpacked */ - void statsBGGR12Line0(const uint8_t *src[]); + void statsBGGR12Line0(const uint8_t *src[], SwIspStats &stats); /* Bayer 10 bpp packed */ - void statsBGGR10PLine0(const uint8_t *src[]); - void statsGBRG10PLine0(const uint8_t *src[]); + void statsBGGR10PLine0(const uint8_t *src[], SwIspStats &stats); + void statsGBRG10PLine0(const uint8_t *src[], SwIspStats &stats); void processBayerFrame2(MappedFrameBuffer &in); @@ -116,8 +117,8 @@ private: unsigned int xShift_; unsigned int stride_; + std::vector stats_; SharedMemObject sharedStats_; - SwIspStats stats_; Benchmark bench_; }; diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 1cedcfbc..41b73e43 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -74,11 +74,12 @@ namespace libcamera { */ /** - * \fn void SwStatsCpu::processLine0(uint32_t frame, unsigned int y, const uint8_t *src[]) + * \fn void SwStatsCpu::processLine0(uint32_t frame, unsigned int y, const uint8_t *src[], unsigned int statsBufferIndex = 0) * \brief Process line 0 * \param[in] frame The frame number * \param[in] y The y coordinate. * \param[in] src The input data. + * \param[in] statsBufferIndex Index of stats buffer to use for multi-threading. * * This function processes line 0 for input formats with * patternSize height == 1. @@ -97,14 +98,18 @@ namespace libcamera { * to the line in plane 0, etc. * * For non Bayer single plane input data only a single src pointer is required. + * + * The statsBufferIndex value must be less than the statsBufferCount value passed + * to configure(). */ /** - * \fn void SwStatsCpu::processLine2(uint32_t frame, unsigned int y, const uint8_t *src[]) + * \fn void SwStatsCpu::processLine2(uint32_t frame, unsigned int y, const uint8_t *src[], unsigned int statsBufferIndex = 0) * \brief Process line 2 and 3 * \param[in] frame The frame number * \param[in] y The y coordinate. * \param[in] src The input data. + * \param[in] statsBufferIndex Index of stats buffer to use for multi-threading. * * This function processes line 2 and 3 for input formats with * patternSize height == 4. @@ -182,14 +187,14 @@ static constexpr unsigned int kBlueYMul = 29; /* 0.114 * 256 */ yVal = r * kRedYMul; \ yVal += g * kGreenYMul; \ yVal += b * kBlueYMul; \ - stats_.yHistogram[yVal * SwIspStats::kYHistogramSize / (256 * 256 * (div))]++; + stats.yHistogram[yVal * SwIspStats::kYHistogramSize / (256 * 256 * (div))]++; #define SWSTATS_FINISH_LINE_STATS() \ - stats_.sum_.r() += sumR; \ - stats_.sum_.g() += sumG; \ - stats_.sum_.b() += sumB; + stats.sum_.r() += sumR; \ + stats.sum_.g() += sumG; \ + stats.sum_.b() += sumB; -void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[]) +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[], SwIspStats &stats) { const uint8_t *src0 = src[1] + window_.x; const uint8_t *src1 = src[2] + window_.x; @@ -214,7 +219,7 @@ void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[]) SWSTATS_FINISH_LINE_STATS() } -void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[]) +void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[], SwIspStats &stats) { const uint16_t *src0 = (const uint16_t *)src[1] + window_.x; const uint16_t *src1 = (const uint16_t *)src[2] + window_.x; @@ -240,7 +245,7 @@ void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[]) SWSTATS_FINISH_LINE_STATS() } -void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[]) +void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[], SwIspStats &stats) { const uint16_t *src0 = (const uint16_t *)src[1] + window_.x; const uint16_t *src1 = (const uint16_t *)src[2] + window_.x; @@ -266,7 +271,7 @@ void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[]) SWSTATS_FINISH_LINE_STATS() } -void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[]) +void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[], SwIspStats &stats) { const uint8_t *src0 = src[1] + window_.x * 5 / 4; const uint8_t *src1 = src[2] + window_.x * 5 / 4; @@ -292,7 +297,7 @@ void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[]) SWSTATS_FINISH_LINE_STATS() } -void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[]) +void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[], SwIspStats &stats) { const uint8_t *src0 = src[1] + window_.x * 5 / 4; const uint8_t *src1 = src[2] + window_.x * 5 / 4; @@ -332,8 +337,10 @@ void SwStatsCpu::startFrame(uint32_t frame) if (window_.width == 0) LOG(SwStatsCpu, Error) << "Calling startFrame() without setWindow()"; - stats_.sum_ = RGB({ 0, 0, 0 }); - stats_.yHistogram.fill(0); + for (auto &s : stats_) { + s.sum_ = RGB({ 0, 0, 0 }); + s.yHistogram.fill(0); + } } /** @@ -345,8 +352,19 @@ void SwStatsCpu::startFrame(uint32_t frame) */ void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId) { - stats_.valid = frame % kStatPerNumFrames == 0; - *sharedStats_ = stats_; + bool valid = frame % kStatPerNumFrames == 0; + + if (valid) { + sharedStats_->sum_ = RGB({ 0, 0, 0 }); + sharedStats_->yHistogram.fill(0); + for (auto &s : stats_) { + sharedStats_->sum_ += s.sum_; + for (unsigned int i = 0; i < SwIspStats::kYHistogramSize; i++) + sharedStats_->yHistogram[i] += s.yHistogram[i]; + } + } + + sharedStats_->valid = valid; statsReady.emit(frame, bufferId); } @@ -389,12 +407,14 @@ int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order) /** * \brief Configure the statistics object for the passed in input format * \param[in] inputCfg The input format + * \param[in] statsBufferCount number of internal stats buffers to use for multi-threading * * \return 0 on success, a negative errno value on failure */ -int SwStatsCpu::configure(const StreamConfiguration &inputCfg) +int SwStatsCpu::configure(const StreamConfiguration &inputCfg, unsigned int statsBufferCount) { stride_ = inputCfg.stride; + stats_.resize(statsBufferCount); BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputCfg.pixelFormat); @@ -504,7 +524,7 @@ void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in) /* linePointers[0] is not used by any stats0_ functions */ linePointers[1] = src; linePointers[2] = src + stride_; - (this->*stats0_)(linePointers); + (this->*stats0_)(linePointers, stats_[0]); src += stride_ * 2; } } From patchwork Tue Feb 24 19:37:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 26234 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 8C8D5C32C8 for ; Tue, 24 Feb 2026 19:37:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 93841622AD; Tue, 24 Feb 2026 20:37:55 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="bC9KGrlC"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Zyv8KsDt"; dkim-atps=neutral Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 513F9622B1 for ; Tue, 24 Feb 2026 20:37:52 +0100 (CET) Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61OFQZ8P3177060 for ; Tue, 24 Feb 2026 19:37:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=me+HBKUkDgV dYQngZuHh24uEVJQAqxiMU3chL38HdgA=; b=bC9KGrlCv3XOaXOJl07CrWb8q6E g1S9MpMrEnbO1HIGDJcDPz59GLCBvnCnaRl6JZWaxtd0GKe6Zmkcmu6i4XhmI1N5 p/2L1/GT1hhBvLQZZfVklsFXuG9kQXd9JxBNPJZ5WbY3MjPx0g7r399DFkB7qAGC JkWjlqJwCh9JaipObsObg+uD9fLTSt/Lx0OZdq5P5kt4JCb4rvcmeBWs9SdCRr7B yoy4h8fG1NsJL1Tx8kMPVukSeckLf7LGRUWw4fCMhgtCV92eMRk/+DjCAwA4oQI0 rH4hnFMeYsheq3J60A6h8tdpPS+4mzT/imri7R8xiyHvI1GnvbqujniAIXQ== Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4chemnry0k-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 24 Feb 2026 19:37:50 +0000 (GMT) Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-8cb42f56c4aso5291949185a.3 for ; Tue, 24 Feb 2026 11:37:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771961870; x=1772566670; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=me+HBKUkDgVdYQngZuHh24uEVJQAqxiMU3chL38HdgA=; b=Zyv8KsDtnyu+320MNNR8lQsdx6IDr/JEzx74xqpc8DNfyU6HC7isSJ5piNd33gOM5G FPDvgBavTDKs8B40YTNjlhD0I7Lcrc71mBPVE82DEMrXN/BtuE07d+bk73P8CJtozIU2 xXrngx1W6VXgBrlWKW2Mj1tpOPnslvhRs2ZAmqlvmCrlpQFPR7XoWilihjZ+lmb1MNbP I2F/PDflHFM0cLdADvsOhjOX7bXni7IzNZSatePJKApFoCEO/OSe8zURGh393NAObWUf 73gI8xI0Uo1mUt+X68GNyWOv553zVp33AIW/vJA/KXZU7hrz7320CgtpRhOgQqRhMWqj Mj2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771961870; x=1772566670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=me+HBKUkDgVdYQngZuHh24uEVJQAqxiMU3chL38HdgA=; b=eoZ7stHzWJvuBMHZJNqhggnZxIExm4now6fODZbxWIIQO6O3/OxGgoifZCoZHpDk5/ gkA4cei9klnrjop0zkqC0lk76n5wiLS+s1Nb7V2FBo8FZZEbR6J+5Z4MzOE5yCfOr8IH z2bF3VWlOr7u4ap7CQ7up/a2wBHNmGo9/kSphjqe/kFdVGI/ab0RJdDYjATfV3dx9KFj IQHBMHk99kBH3UHteiaS9W0HiFOVP3KB/SVJzx5/BHikljbg3c8dVTXglPXQoZjkoTLo shbm1i0DXDs+zkRQahAZQYSqPB3auCdc7Wtqhb1ZSGAj+FYVKKBHlYOZterxrj2UzWzo JqAA== X-Gm-Message-State: AOJu0YyjMhH56lywqpL9Mm1uEK1prqmoGzub+qHdVyQF2JoPurK7Wf05 Vygm+2gHdQsY4XD2g8LyGDKwy0rkAJZ0qtmHUVcG/lyVaix4Ey+XFVHBQKwP6itQri4Z/OacRYv 06aNQEErJxOCV4Xy5giZIYsmYU4SCrisgpYOBt4pkomxgGst1AmK9ZOUqnUomN8Ku/HFNjK+GWp KbYIWuLMIr X-Gm-Gg: AZuq6aKVO8+6uASheRkNOdn//2a3G8p6OPkKQGIb+ZShOBzq9aivcNuYXamLuu0yQ5z FfXnYRySU3QsHEIPB+yfvu5wlquM+6Y2+7B5DEFf3O8DIk8R51LugvWzCzxPHckRHPLYBGFLAoX zcbzlhvAtGAEHC2dgqO9teLnpMOWW2ulBXPg3nLTRcE4np04VDQtayKJPnv4/8rbORLtzGsHhh0 4HXCdExC0XtQ2CpQzgOBbO9hua58NbBmIViuQGEyqwkgCYF9k4W+NUAaAKWDvXKY++b/3tLK7r7 svj4U8b/CTEky2ln6Fu2vhVqXosRh89uTVWQMi89GiiRmLqMW34JU9BMW94ftDUtATRNUrAmF5r MhIoOpZn71YIUmJwi34XwNNfcknUWB8pCi+HSTbZo1vLJAqyFM4pat7+qShK6OxpHkbITR7H3gJ q5sdcdYipYVVV+4MWfrV9nO7/Fts+/szMfSvtx X-Received: by 2002:a05:620a:f0d:b0:8ca:2a04:3ff3 with SMTP id af79cd13be357-8cb8ca03fe5mr1726073185a.30.1771961869804; Tue, 24 Feb 2026 11:37:49 -0800 (PST) X-Received: by 2002:a05:620a:f0d:b0:8ca:2a04:3ff3 with SMTP id af79cd13be357-8cb8ca03fe5mr1726068185a.30.1771961869063; Tue, 24 Feb 2026 11:37:49 -0800 (PST) Received: from shalem (2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl. [2001:1c00:c32:7800:5bfa:a036:83f0:f9ec]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084e8cb3fsm458232866b.48.2026.02.24.11.37.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 11:37:48 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org, Milan Zamazal Cc: Hans de Goede Subject: [PATCH v3 2/4] software_isp: debayer_cpu: Add DebayerCpuThread class Date: Tue, 24 Feb 2026 20:37:43 +0100 Message-ID: <20260224193745.106186-3-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> References: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjI0MDE2OCBTYWx0ZWRfX0xfvC0eBxnbf fATYZNK0GSo2SCm5R4DidTEqSPOhRUqc3GDqxngo54jucTR9BgZOVHtlTZl+5pczhO0UOzrLq5k QvSStBNWE5UOh426Q8jTtF0jVYqIwPuo8ALrvt/qZJ+YD4vIbKGBDBPwL9+ekDFi+5Kt/5RCkmZ Aa8zbgjJ/CYlxo48lbzrJ3GaY8j9ZASxFP0y4eI2cxASD9d0s33wlDCViKBOJ5DHA5TnsD+7XDl MRtXmcBkzkQvbFmjcwm3I1JqGF9ndwOMMmf/IMkr5doU2rwamJrF9C2EcUiXyHYWNJczfOF37Wj h0CIP1xKpmaeQumMqbjcpEKcBDRFxALd8CqEJ3rn5MqHNlXhbSu6YuYRRa7l60CfGZsB7sQkKlQ mQDWQKIVuDrmsI75dvPzRN7bRXdzAGFgvHOpFvyzUC70FGb/kQLZFlanoYPWcf1ohwItaVidXwz j1g1ZFWespV2BflEYvg== X-Proofpoint-ORIG-GUID: UJCy6G2eL79Q09R1KrjsvfUNMsml0xzc X-Authority-Analysis: v=2.4 cv=Ro7I7SmK c=1 sm=1 tr=0 ts=699dfe0e cx=c_pps a=qKBjSQ1v91RyAK45QCPf5w==:117 a=xqWC_Br6kY4A:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=EUspDBNiAAAA:8 a=Chkswc9nKTKKIei3T8UA:9 a=NFOGd7dJGGMPyQGDc5-O:22 X-Proofpoint-GUID: UJCy6G2eL79Q09R1KrjsvfUNMsml0xzc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293, Aquarius:18.0.1121, Hydra:6.1.51, FMLib:17.12.100.49 definitions=2026-02-24_02,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 clxscore=1015 spamscore=0 bulkscore=0 adultscore=0 impostorscore=0 phishscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602240168 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" Add a DebayerCpuThreadclass and use this in the inner render loop. This contains data which needs to be separate per thread. This is a preparation patch for making DebayerCpu support multi-threading. Benchmarking on the Arduino Uno-Q with a weak CPU which is good for performance testing, shows 146-147ms per 3272x2464 frame both before and after this change, with things maybe being 0.5 ms slower after this change. Signed-off-by: Hans de Goede --- Changes in v3: - Use std::unique_ptr for the DebayerCpuThread pointers - Document new DebayerCpuThread class - Make DebayerCpuThread inherit from both Thread and Object Changes in v2: - Replace the DebayerCpuThreadData struct from v1 with a DebayerCpuThread class, derived from Object to allow calling invokeMethod for thread re-use in followup patches - As part of this also move a bunch of methods which primarily deal with per thread data: setupInputMemcpy(), shiftLinePointers(), memcpyNextLine(), process*() to the new DebayerCpuThread class --- src/libcamera/software_isp/debayer_cpu.cpp | 244 +++++++++++++++------ src/libcamera/software_isp/debayer_cpu.h | 20 +- 2 files changed, 188 insertions(+), 76 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index e7b01210..36b7881b 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include "libcamera/internal/bayer_format.h" @@ -27,6 +29,52 @@ namespace libcamera { +/** + * \brief Class representing one CPU debayering thread + * + * Implementation for CPU based debayering threads. + */ +class DebayerCpuThread : public Thread, public Object +{ +public: + DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, + bool enableInputMemcpy); + + void configure(unsigned int yStart, unsigned int yEnd); + void process(uint32_t frame, const uint8_t *src, uint8_t *dst); + +private: + void setupInputMemcpy(const uint8_t *linePointers[]); + void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); + void memcpyNextLine(const uint8_t *linePointers[]); + void process2(uint32_t frame, const uint8_t *src, uint8_t *dst); + void process4(uint32_t frame, const uint8_t *src, uint8_t *dst); + + DebayerCpu *debayer_; + unsigned int threadIndex_; + unsigned int yStart_; + unsigned int yEnd_; + unsigned int lineBufferLength_; + unsigned int lineBufferPadding_; + unsigned int lineBufferIndex_; + std::vector lineBuffers_[DebayerCpu::kMaxLineBuffers]; + bool enableInputMemcpy_; +}; + +/** + * \brief Construct a DebayerCpuThread object + * \param[in] debayer pointer back to the DebayerCpuObject this thread belongs to + * \param[in] threadIndex 0 .. n thread-index value for the thread + * \param[in] enableInputMemcpy when set copy input data to a heap buffer before use + */ +DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, + bool enableInputMemcpy) + : Thread("DebayerCpu:" + std::to_string(threadIndex)), + debayer_(debayer), threadIndex_(threadIndex), + enableInputMemcpy_(enableInputMemcpy) +{ +} + /** * \class DebayerCpu * \brief Class for debayering on the CPU @@ -53,8 +101,14 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats, const GlobalConfigurat * \todo Make memcpy automatic based on runtime detection of platform * capabilities. */ - enableInputMemcpy_ = + bool enableInputMemcpy = configuration.option({ "software_isp", "copy_input_buffer" }).value_or(true); + + /* Just one thread object for now, which will be called inline rather than async */ + threads_.resize(1); + + for (unsigned int i = 0; i < threads_.size(); i++) + threads_[i] = std::make_unique(this, i, enableInputMemcpy); } DebayerCpu::~DebayerCpu() = default; @@ -484,7 +538,7 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; - if (stats_->configure(inputCfg) != 0) + if (stats_->configure(inputCfg, threads_.size()) != 0) return -EINVAL; const Size &statsPatternSize = stats_->patternSize(); @@ -548,17 +602,43 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, */ stats_->setWindow(Rectangle(window_.size())); + unsigned int yStart = 0; + unsigned int linesPerThread = (window_.height / threads_.size()) & + ~(inputConfig_.patternSize.height - 1); + unsigned int i; + + for (i = 0; i < (threads_.size() - 1); i++) { + threads_[i]->configure(yStart, yStart + linesPerThread); + yStart += linesPerThread; + } + threads_[i]->configure(yStart, window_.height); + + return 0; +} + +/** + * \brief Configure thread to process a specific part of the image + * \param[in] yStart y coordinate of first line to process + * \param[in] yEnd y coordinate of the line at which to stop processing + * + * Configure the thread to process lines yStart - (yEnd - 1). + */ +void DebayerCpuThread::configure(unsigned int yStart, unsigned int yEnd) +{ + Debayer::DebayerInputConfig &inputConfig = debayer_->inputConfig_; + + yStart_ = yStart; + yEnd_ = yEnd; + /* pad with patternSize.Width on both left and right side */ - lineBufferPadding_ = inputConfig_.patternSize.width * inputConfig_.bpp / 8; - lineBufferLength_ = window_.width * inputConfig_.bpp / 8 + + lineBufferPadding_ = inputConfig.patternSize.width * inputConfig.bpp / 8; + lineBufferLength_ = debayer_->window_.width * inputConfig.bpp / 8 + 2 * lineBufferPadding_; if (enableInputMemcpy_) { - for (unsigned int i = 0; i <= inputConfig_.patternSize.height; i++) + for (unsigned int i = 0; i <= inputConfig.patternSize.height; i++) lineBuffers_[i].resize(lineBufferLength_); } - - return 0; } /* @@ -599,9 +679,9 @@ DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size return std::make_tuple(stride, stride * size.height); } -void DebayerCpu::setupInputMemcpy(const uint8_t *linePointers[]) +void DebayerCpuThread::setupInputMemcpy(const uint8_t *linePointers[]) { - const unsigned int patternHeight = inputConfig_.patternSize.height; + const unsigned int patternHeight = debayer_->inputConfig_.patternSize.height; if (!enableInputMemcpy_) return; @@ -617,20 +697,20 @@ void DebayerCpu::setupInputMemcpy(const uint8_t *linePointers[]) lineBufferIndex_ = patternHeight; } -void DebayerCpu::shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src) +void DebayerCpuThread::shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src) { - const unsigned int patternHeight = inputConfig_.patternSize.height; + const unsigned int patternHeight = debayer_->inputConfig_.patternSize.height; for (unsigned int i = 0; i < patternHeight; i++) linePointers[i] = linePointers[i + 1]; - linePointers[patternHeight] = src + - (patternHeight / 2) * (int)inputConfig_.stride; + linePointers[patternHeight] = + src + (patternHeight / 2) * (int)debayer_->inputConfig_.stride; } -void DebayerCpu::memcpyNextLine(const uint8_t *linePointers[]) +void DebayerCpuThread::memcpyNextLine(const uint8_t *linePointers[]) { - const unsigned int patternHeight = inputConfig_.patternSize.height; + const unsigned int patternHeight = debayer_->inputConfig_.patternSize.height; if (!enableInputMemcpy_) return; @@ -643,23 +723,48 @@ void DebayerCpu::memcpyNextLine(const uint8_t *linePointers[]) lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1); } -void DebayerCpu::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) +/** + * \brief Process part of the image assigned to this debayer thread + * \param[in] frame The frame number + * \param[in] src The source buffer + * \param[in] dst The destination buffer + */ +void DebayerCpuThread::process(uint32_t frame, const uint8_t *src, uint8_t *dst) { - unsigned int yEnd = window_.height; + Rectangle &window = debayer_->window_; + + /* Adjust src to top left corner of the window */ + src += (window.y + yStart_) * debayer_->inputConfig_.stride + + window.x * debayer_->inputConfig_.bpp / 8; + /* Adjust dst for yStart_ */ + dst += yStart_ * debayer_->outputConfig_.stride; + + if (debayer_->inputConfig_.patternSize.height == 2) + process2(frame, src, dst); + else + process4(frame, src, dst); +} + +void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) +{ + unsigned int outputStride = debayer_->outputConfig_.stride; + unsigned int inputStride = debayer_->inputConfig_.stride; + Rectangle &window = debayer_->window_; + unsigned int yEnd = yEnd_; /* Holds [0] previous- [1] current- [2] next-line */ const uint8_t *linePointers[3]; - /* Adjust src to top left corner of the window */ - src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8; - /* [x] becomes [x - 1] after initial shiftLinePointers() call */ - if (window_.y) { - linePointers[1] = src - inputConfig_.stride; /* previous-line */ + if (window.y + yStart_) { + linePointers[1] = src - inputStride; /* previous-line */ linePointers[2] = src; } else { - /* window_.y == 0, use the next line as prev line */ - linePointers[1] = src + inputConfig_.stride; + /* Top line, use the next line as prev line */ + linePointers[1] = src + inputStride; linePointers[2] = src; + } + + if (window.y == 0 && yEnd_ == window.height) { /* * Last 2 lines also need special handling. * (And configure() ensures that yEnd >= 2.) @@ -669,83 +774,93 @@ void DebayerCpu::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) setupInputMemcpy(linePointers); - for (unsigned int y = 0; y < yEnd; y += 2) { + /* + * Note y is the line-number *inside* the window, since stats_' window + * is the stats window inside/relative to the debayer window. IOW for + * single thread rendering y goes from 0 to window.height. + */ + for (unsigned int y = yStart_; y < yEnd; y += 2) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine0(frame, y, linePointers); - (this->*debayer0_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->stats_->processLine0(frame, y, linePointers, threadIndex_); + debayer_->debayer0(dst, linePointers); + src += inputStride; + dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - (this->*debayer1_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->debayer1(dst, linePointers); + src += inputStride; + dst += outputStride; } - if (window_.y == 0) { + if (window.y == 0 && yEnd_ == window.height) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine0(frame, yEnd, linePointers); - (this->*debayer0_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->stats_->processLine0(frame, yEnd, linePointers, threadIndex_); + debayer_->debayer0(dst, linePointers); + src += inputStride; + dst += outputStride; shiftLinePointers(linePointers, src); /* next line may point outside of src, use prev. */ linePointers[2] = linePointers[0]; - (this->*debayer1_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->debayer1(dst, linePointers); + src += inputStride; + dst += outputStride; } } -void DebayerCpu::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) +void DebayerCpuThread::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) { + unsigned int outputStride = debayer_->outputConfig_.stride; + unsigned int inputStride = debayer_->inputConfig_.stride; + /* * This holds pointers to [0] 2-lines-up [1] 1-line-up [2] current-line * [3] 1-line-down [4] 2-lines-down. */ const uint8_t *linePointers[5]; - /* Adjust src to top left corner of the window */ - src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8; - /* [x] becomes [x - 1] after initial shiftLinePointers() call */ - linePointers[1] = src - 2 * inputConfig_.stride; - linePointers[2] = src - inputConfig_.stride; + linePointers[1] = src - 2 * inputStride; + linePointers[2] = src - inputStride; linePointers[3] = src; - linePointers[4] = src + inputConfig_.stride; + linePointers[4] = src + inputStride; setupInputMemcpy(linePointers); - for (unsigned int y = 0; y < window_.height; y += 4) { + /* + * Note y is the line-number *inside* the window, since stats_' window + * is the stats window inside/relative to the debayer window. IOW for + * single thread rendering y goes from 0 to window.height. + */ + for (unsigned int y = yStart_; y < yEnd_; y += 4) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine0(frame, y, linePointers); - (this->*debayer0_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->stats_->processLine0(frame, y, linePointers, threadIndex_); + debayer_->debayer0(dst, linePointers); + src += inputStride; + dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - (this->*debayer1_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->debayer1(dst, linePointers); + src += inputStride; + dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine2(frame, y, linePointers); - (this->*debayer2_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->stats_->processLine2(frame, y, linePointers, threadIndex_); + debayer_->debayer2(dst, linePointers); + src += inputStride; + dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - (this->*debayer3_)(dst, linePointers); - src += inputConfig_.stride; - dst += outputConfig_.stride; + debayer_->debayer3(dst, linePointers); + src += inputStride; + dst += outputStride; } } @@ -867,10 +982,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output stats_->startFrame(frame); - if (inputConfig_.patternSize.height == 2) - process2(frame, in.planes()[0].data(), out.planes()[0].data()); - else - process4(frame, in.planes()[0].data(), out.planes()[0].data()); + threads_[0]->process(frame, in.planes()[0].data(), out.planes()[0].data()); metadata.planes()[0].bytesused = out.planes()[0].size(); diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 7a651746..1074bc9c 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -26,6 +26,7 @@ namespace libcamera { +class DebayerCpuThread; class DebayerCpu : public Debayer { public: @@ -44,6 +45,8 @@ public: const SharedFD &getStatsFD() { return stats_->getStatsFD(); } private: + friend class DebayerCpuThread; + /** * \brief Called to debayer 1 line of Bayer input data to output format * \param[out] dst Pointer to the start of the output line to write @@ -74,6 +77,11 @@ private: */ using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]); + void debayer0(uint8_t *dst, const uint8_t *src[]) { (this->*debayer0_)(dst, src); } + void debayer1(uint8_t *dst, const uint8_t *src[]) { (this->*debayer1_)(dst, src); } + void debayer2(uint8_t *dst, const uint8_t *src[]) { (this->*debayer2_)(dst, src); } + void debayer3(uint8_t *dst, const uint8_t *src[]) { (this->*debayer3_)(dst, src); } + /* 8-bit raw bayer format */ template void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); @@ -105,11 +113,6 @@ private: int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat, bool ccmEnabled); - void setupInputMemcpy(const uint8_t *linePointers[]); - void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); - void memcpyNextLine(const uint8_t *linePointers[]); - void process2(uint32_t frame, const uint8_t *src, uint8_t *dst); - void process4(uint32_t frame, const uint8_t *src, uint8_t *dst); void updateGammaTable(const DebayerParams ¶ms); void updateLookupTables(const DebayerParams ¶ms); @@ -142,12 +145,9 @@ private: debayerFn debayer3_; Rectangle window_; std::unique_ptr stats_; - std::vector lineBuffers_[kMaxLineBuffers]; - unsigned int lineBufferLength_; - unsigned int lineBufferPadding_; - unsigned int lineBufferIndex_; unsigned int xShift_; /* Offset of 0/1 applied to window_.x */ - bool enableInputMemcpy_; + + std::vector>threads_; }; } /* namespace libcamera */ From patchwork Tue Feb 24 19:37:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 26235 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 708E5C0DA4 for ; Tue, 24 Feb 2026 19:37:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 23DB1622B7; Tue, 24 Feb 2026 20:37:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="fdb6yK38"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Gwekh/f7"; dkim-atps=neutral Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 23F9D622A2 for ; Tue, 24 Feb 2026 20:37:53 +0100 (CET) Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61OFO0WH2432436 for ; Tue, 24 Feb 2026 19:37:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=Dg+H+cXUvva SQunQpgmYy3lZMM8Jgoeiy1NGwXPXAos=; b=fdb6yK38Xrbp5RlwYqLQ1CR/Mpb vfU3Xdl4XhBs6QE9cqpewmgpvDJUEX5YpNyXbdSJx1UTc+4FCebuIK/4NxVAahJ3 lnl9y3Ytqm33bVARB9i0Ynwzan4aMFV9t3BgAi6L6/EJDT55uAr9ehWm8fBQHqFH J4ZxibxnudF2aziwb3H8MaFxDsnlbY/WTaPdiIRJMJuWRk9niEireT9JwiKfHg1u fArjixlkBy+x6Cg+H+2PUk3+4VZb/rbjX4qAFOhX0n5lUTr3++up3ihKOC71XkaI lpKuTxKSyylBHOEmAqWfxOKh3nnSkXskK6q0t6FQgKu7ZvI2rcVSzL907lw== Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4chekj8ygx-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 24 Feb 2026 19:37:51 +0000 (GMT) Received: by mail-qk1-f200.google.com with SMTP id af79cd13be357-8cb4817f3c8so4472312685a.3 for ; Tue, 24 Feb 2026 11:37:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771961871; x=1772566671; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Dg+H+cXUvvaSQunQpgmYy3lZMM8Jgoeiy1NGwXPXAos=; b=Gwekh/f77ArA7xrXlPmac9BExCao+9ndJBB2X7bbPELTR4vYWKrFOxtFZFMQkgJKmL sun3CM89511a+OlKbO3QZBOoxgNhnBSqwNPb9FA88XJBrOdC6so7VSHv2meLiZt37g/s AmTf69GEc/0KAa3sEMXlPQjWzE3QFMF7+vSzppXnIqaAj7bDYqfELTsSLJnayqRrLTuM xyMiOkJy2p5H00Irk19qFSO9TrPnImqUKNOLwF2Bz55J+QtlUOrJTuf74UFXVA08ZIcA CaTxk/a2zbQiYFW6yqP6K2N9gPbvAlJMHFH54nIWDeRNDyJPbDdU/Em3WtWu/39MWj9i O/zQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771961871; x=1772566671; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Dg+H+cXUvvaSQunQpgmYy3lZMM8Jgoeiy1NGwXPXAos=; b=pKj4309VbZ7l/UTf2EQgSlblsMq9vqqUZKW4NT1gibXem341CqYjp34A/K0Pid1oZ8 LwWU2wEORoPbdG2s3jHjSZIcr5ReEX4rtgWfZtNX9zprEn0WOHUXKVGHyDjW4t/Czd3o xiuqceI3lP1cWbbIrNRaTK3FWj5D0BWucErtFA2X56S9L332oCniFpQrj0IsOfqHd6WK 8gTYRNuECZQrssJg0ObSdwd1YITmsCt6eaKW5ICmNB6h0/n5eZ+RsfSENI5uwsfpPnOf 2H8Z5AZXnabdXzHn+w4hldqagMKs3iUTEx5IiEV3LPIUjJX6D2E1DNJKpLo6hLQMPJs8 2JLA== X-Gm-Message-State: AOJu0Ywt6xRfTY1juRL8XEATBwPggOFSl8AmjggBWx79YiBrzow2ylyk Gm6xhnut18P+VKGPHvHdlVVko4oyHNcLkkEPdNTGGpRlVS2Ox5Mt8S+Q0tdfIlq9WjP9J4vFd/T 97leX/PSUYEIFA1E7Fxl2FRmJlHnJtDR9/LKZIYtmJcxMf191yv97VrBpvgPDC9slVtBGwmxSNC iOxWtiGXN5 X-Gm-Gg: AZuq6aIowf2MRuy9t6wXjn4xo5E7AAoWZ/s47P2+cKyL5OH6TqvgEPwdVJPQKemIjaA Q63PCYY3E6KmvAGMiRE3WCrjBpW6EKI+E/3OGGSRcW8B6n7I7k8bBjaxumaiXJD3G2BmZGTtca+ +nJgnFiLqWYQUvaLfyYTglNndwQrBxFuHNVjlzaGotaow32plJUevRBbVKQHhJwxDMDZAr13SEu 3L5G2LUAP8z5oG7wbkaxXyiMc044U+vF8bhhIZKXh6NtTgbA4otwI3sTkDdgP1Qpnll85Y1K2lG JAdV0Pwl2qj5cd7pv5izWCnMOqDDWmW+ihhos25hS15VL+y7tyLVSZ+kNVtObvMyFxiif3R1eQz +CkOWGd38gdEC5LFX/8xu3x24bZiTx0XxECEWBXp9QxN0yK1ZKhmmDzIcMNJxQSMntT4lreZt8Q ON1UH0U6h4kFKdksK7nw+Frlpv2iczUyZcip2K X-Received: by 2002:a05:620a:4449:b0:8cb:4d64:e972 with SMTP id af79cd13be357-8cb8c9cdc56mr1454365385a.9.1771961870574; Tue, 24 Feb 2026 11:37:50 -0800 (PST) X-Received: by 2002:a05:620a:4449:b0:8cb:4d64:e972 with SMTP id af79cd13be357-8cb8c9cdc56mr1454362385a.9.1771961870052; Tue, 24 Feb 2026 11:37:50 -0800 (PST) Received: from shalem (2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl. [2001:1c00:c32:7800:5bfa:a036:83f0:f9ec]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084e8cb3fsm458232866b.48.2026.02.24.11.37.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 11:37:49 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org, Milan Zamazal Cc: Hans de Goede Subject: [PATCH v3 3/4] software_isp: debayer_cpu: Add multi-threading support Date: Tue, 24 Feb 2026 20:37:44 +0100 Message-ID: <20260224193745.106186-4-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> References: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Authority-Analysis: v=2.4 cv=RNe+3oi+ c=1 sm=1 tr=0 ts=699dfe0f cx=c_pps a=hnmNkyzTK/kJ09Xio7VxxA==:117 a=xqWC_Br6kY4A:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=rJkE3RaqiGZ5pbrm-msn:22 a=EUspDBNiAAAA:8 a=uyevB83Nksalfc49Bg4A:9 a=PEH46H7Ffwr30OY-TuGO:22 X-Proofpoint-ORIG-GUID: WgMGUl3KVxKeQaaHLsIkBcIFUhhhTmKC X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjI0MDE2OCBTYWx0ZWRfX58vuduKb+Msb PxOk93PCPgDqqxDNKvWjBq+OcJ6f7Aj0bM+jVC5JOZTZXfUknlW64l8+tq0sXXZBUOOKlybnqqc 2oPsaw+zkyM4mfX7XfzNcVLOYeX5DfGCr2dpvfXjeUYlnLi0PEjO69h+mSXeEfLuSYWrWTR/TxX dssyaUFFXdiovtIlVKNxh1cTlvU9cFGRbc5y3Tfl1IvS9gVUPF8pt4lhIfzmzJc0nL5tbvXrzLi PtrOo4nVEnx2pbi97syxqVQtWUOL3ITYpjD578aLlUMo64EOyO9K0alMcUoGlRdwVbnrHnsS1H/ ywL8yhu8n0jh+6s3HMhe9Mm8jG1CGYM35voLllAzFpdSedYG9hEOlGFaLlYvj9Qn0es5C7AQNXR F9xAwCo24iq8SKA5Bp6q/hLTN9VIXT5e7r5C+1EP13TqEOKCayKSlmaZWciyyPz7v6xzJWlp1m1 urzUcoJcO93uLeLg6+w== X-Proofpoint-GUID: WgMGUl3KVxKeQaaHLsIkBcIFUhhhTmKC X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293, Aquarius:18.0.1121, Hydra:6.1.51, FMLib:17.12.100.49 definitions=2026-02-24_02,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 lowpriorityscore=0 adultscore=0 priorityscore=1501 phishscore=0 clxscore=1015 spamscore=0 impostorscore=0 suspectscore=0 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602240168 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" Add CPU soft ISP multi-threading support. Benchmark results for the Arduino Uno-Q with a weak CPU which is good for performance testing, all numbers with an IMX219 running at 3280x2464 -> 3272x2464: 1 thread : 147ms / frame, ~6.5 fps 2 threads: 80ms / frame, ~12.5 fps 3 threads: 65ms / frame, ~15 fps Adding a 4th thread does not improve performance. Signed-off-by: Hans de Goede --- Changes in v3: - Adjust for DebayerCpuThread now inheriting from Thread - Use for (auto &thread : threads_) Changes in v2: - Adjust to use the new DebayerCpuThread class introduced in the v2 patch-series - Re-use threads instead of starting new threads every frame --- src/libcamera/software_isp/debayer_cpu.cpp | 45 ++++++++++++++++++++-- src/libcamera/software_isp/debayer_cpu.h | 6 +++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 36b7881b..cf16f00b 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -73,6 +73,7 @@ DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex debayer_(debayer), threadIndex_(threadIndex), enableInputMemcpy_(enableInputMemcpy) { + moveToThread(this); } /** @@ -104,8 +105,10 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats, const GlobalConfigurat bool enableInputMemcpy = configuration.option({ "software_isp", "copy_input_buffer" }).value_or(true); - /* Just one thread object for now, which will be called inline rather than async */ - threads_.resize(1); + unsigned int threadCount = + configuration.option({ "software_isp", "threads" }).value_or(2); + threadCount = std::clamp(threadCount, 1u, 8u); + threads_.resize(threadCount); for (unsigned int i = 0; i < threads_.size(); i++) threads_[i] = std::make_unique(this, i, enableInputMemcpy); @@ -743,6 +746,11 @@ void DebayerCpuThread::process(uint32_t frame, const uint8_t *src, uint8_t *dst) process2(frame, src, dst); else process4(frame, src, dst); + + debayer_->workPendingMutex_.lock(); + debayer_->workPending_ &= ~(1 << threadIndex_); + debayer_->workPendingMutex_.unlock(); + debayer_->workPendingCv_.notify_one(); } void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) @@ -982,7 +990,21 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output stats_->startFrame(frame); - threads_[0]->process(frame, in.planes()[0].data(), out.planes()[0].data()); + workPendingMutex_.lock(); + workPending_ = (1 << threads_.size()) - 1; + workPendingMutex_.unlock(); + + for (auto &thread : threads_) + thread->invokeMethod(&DebayerCpuThread::process, + ConnectionTypeQueued, frame, + in.planes()[0].data(), out.planes()[0].data()); + + { + MutexLocker locker(workPendingMutex_); + workPendingCv_.wait(locker, [&]() LIBCAMERA_TSA_REQUIRES(workPendingMutex_) { + return workPending_ == 0; + }); + } metadata.planes()[0].bytesused = out.planes()[0].size(); @@ -1001,6 +1023,23 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output inputBufferReady.emit(input); } +int DebayerCpu::start() +{ + for (auto &thread : threads_) + thread->start(); + + return 0; +} + +void DebayerCpu::stop() +{ + for (auto &thread : threads_) + thread->exit(); + + for (auto &thread : threads_) + thread->wait(); +} + SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize) { Size patternSize = this->patternSize(inputFormat); diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 1074bc9c..eb52f101 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -16,6 +16,7 @@ #include #include +#include #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/global_configuration.h" @@ -41,6 +42,8 @@ public: std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms); + int start(); + void stop(); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); const SharedFD &getStatsFD() { return stats_->getStatsFD(); } @@ -147,6 +150,9 @@ private: std::unique_ptr stats_; unsigned int xShift_; /* Offset of 0/1 applied to window_.x */ + unsigned int workPending_ LIBCAMERA_TSA_GUARDED_BY(workPendingMutex_); + Mutex workPendingMutex_; + ConditionVariable workPendingCv_; std::vector>threads_; }; From patchwork Tue Feb 24 19:37:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 26236 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 E2E51C32C8 for ; Tue, 24 Feb 2026 19:37:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8E106622AB; Tue, 24 Feb 2026 20:37:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="hhw1OqXp"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="hz+biL5J"; dkim-atps=neutral Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C84C6622AB for ; Tue, 24 Feb 2026 20:37:53 +0100 (CET) Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61OFO7C52432689 for ; Tue, 24 Feb 2026 19:37:52 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=ia9XTQD3rvi OTPlc4kW0P9cX6uRJDrqGvpie2wAkg40=; b=hhw1OqXpkRgRqSHJclFcvs9D4R6 hD7z1t9ilaCGzdNEJ6+kTr2qutl7itHUTuWVOxWX6QEtR6FMbIRS8QuFcVZvFyIZ ssDPkMGFIPa/fainaiLVQMP16gR0WWZC+q/TjJe3iLZgun6MmuDYURTxBkupPd6R ISKbbXORsSNOkcvuj7/44QT6lIRJHQhyktuhJJpH9tCxk46mkjU65GponJwhNZUq MwqZFQzBvdO+uUwaYOiy94KIGGea5x7Jp5AyVJG9DZtartyQAU/x5SVFwWopHNCY TmY3UVTSFz/VTLZh81ZAjByon+jAtWo2kYsk6t+yfDTGnr5o3kZUk+Da8+g== Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4chekj8yh1-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 24 Feb 2026 19:37:52 +0000 (GMT) Received: by mail-qv1-f69.google.com with SMTP id 6a1803df08f44-899b041cc64so41666356d6.3 for ; Tue, 24 Feb 2026 11:37:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771961871; x=1772566671; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ia9XTQD3rviOTPlc4kW0P9cX6uRJDrqGvpie2wAkg40=; b=hz+biL5JAoRVzcNnxxV1S2OZyq7QkmOVB00X0/mlB8CDMvp7RxedC1+uoY5+RtHHdY jD9auW0+3HzqVS8TFMMYXMqgN8D39e940ErLfl1Km398oIQkE7zM/b5ZQlGJFLL/+U00 V2+WCTF1kKt+6XqZCEJrkv7w5sumR68amGY3YkWengX51vI81tHgKkWl1PUrKE+nWzBv zL8V0ApoauHMORQjGf3+fBfxZHdaskxqEkzAz+nQnrOwNwuSd/e2I8ZJYL9i0LdWrXG0 Klw47imS9MB4svEivD5VvkM8/Lx5KdD3EuA2eqYX4MvUDQmBrC3rJu9YDkK8kOdB3I5U rG0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771961871; x=1772566671; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ia9XTQD3rviOTPlc4kW0P9cX6uRJDrqGvpie2wAkg40=; b=XvFVPXTY+ZF8QVsJsUPbwCw9uiOAwLqZKOTkgiErSOPjsLPtv1PQR5TyN8+7rzAGiS vMM50rRIW/fti7icCYeQw7Hgb6pR2DAKLXIM1CB5vfOlFnIB1OT8/1YVoOq8arH1SU9G lMJXkwwJWE9Q6gWfGXkJmQGYMlYy/38vKuANjttDzQElVmHZdwxp0YOG6WQ7IoNgKJhV A8mpotxAHkNHOh6MrtPe4PBiZ4w7vwm7fpSjqVd6QSiaxQZghaHKWneSKyZ5DADDl1lB /SO/avt2UDxUB5Zif6EiqXK7d4V1IfZ5dGo8p7fBYtayzNEO6p60Xve0fy/NC3yvkjGC bqAA== X-Gm-Message-State: AOJu0YyMKjT8IL+X8wN8kuRE8doeufds69nb9IA3VQtzzCy8addEycO3 wKWJrKgBlwI9nJoAqyCO+ydrjjLAUMyLpT2oWTl8d/Mr4YIlSs7zaUMCmz3/jDUhSorBN82XTcB T761AKNERJSIzpQ0DQG7C8/QxaZzdCi0pDRiH1xlezeVj2V26TewJ1xWeAJ42DKchDzh/l/LcOH gwANlhIJ+t X-Gm-Gg: AZuq6aIAPYglFSZDu9SvAe5Ty4I6FV8O7BU01YC59tXFDeO9SOpqeGl1YQ5+hVcKKOt QEzeb78jbSkNu2cfypLO+FITagnDJzo/dTuQTKc7ytTrXjfVTaOAkExVIGS57FOhmyL03jD28V7 3VG7ODMZ+ZksCUAR34/8/8lC6DnD5UDfHhvt96rojsohLMnvwb58oyt0k6n9DTWyACWEpWcCuHy A4T7iONEhK1Xun1BhJrShBmSfoMEWqhv/F1lHdKw/2vYJqegyXPf9pPubqOtkGkyffnDCa8xfso WkXKyihLWqa6QBKv45F0BZVe6CVgjkTjXL62zfOds/1Ua+Iu/RN0tk04ihxP7KnUG9YT06msP17 3Cw/2FAnu5UiZn+1RPbgH306XDM/15n9VlSgN/F/7qdvf3/YpiQws5PnbuidBoeYiChDrQTFTgN RxoYY4kla42i4V23WasZWPsAKLwBKjCzUUNFTl X-Received: by 2002:a05:620a:7114:b0:8ca:934a:5e39 with SMTP id af79cd13be357-8cb8c9fe514mr1942639885a.19.1771961871566; Tue, 24 Feb 2026 11:37:51 -0800 (PST) X-Received: by 2002:a05:620a:7114:b0:8ca:934a:5e39 with SMTP id af79cd13be357-8cb8c9fe514mr1942635385a.19.1771961871016; Tue, 24 Feb 2026 11:37:51 -0800 (PST) Received: from shalem (2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl. [2001:1c00:c32:7800:5bfa:a036:83f0:f9ec]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084e8cb3fsm458232866b.48.2026.02.24.11.37.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 11:37:50 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org, Milan Zamazal Cc: Hans de Goede Subject: [PATCH v3 4/4] software_isp: Log input config from configure() Date: Tue, 24 Feb 2026 20:37:45 +0100 Message-ID: <20260224193745.106186-5-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> References: <20260224193745.106186-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Authority-Analysis: v=2.4 cv=RNe+3oi+ c=1 sm=1 tr=0 ts=699dfe10 cx=c_pps a=wEM5vcRIz55oU/E2lInRtA==:117 a=xqWC_Br6kY4A:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=rJkE3RaqiGZ5pbrm-msn:22 a=20KFwNOVAAAA:8 a=EUspDBNiAAAA:8 a=mKg8M22OkPar6P-70WAA:9 a=OIgjcC2v60KrkQgK7BGD:22 X-Proofpoint-ORIG-GUID: IZAbtlJY_qdpP7ejR8K79SVZJeoCPAHL X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjI0MDE2OCBTYWx0ZWRfX/HdZFxqNp/f7 L/DsZs4d7axTsIA4rH2GPSS51jvxzCwXylOun81Ny+Bi5qddijSGZMO7Lu72IvfnHoJnMI+1s61 hsLHuTtMSZufbeDnQSbNxj14qZ4K5fpknBM6eswT9wCmOQiI82MX+rUSVEU2WXpvNOevBG6QE1K 5WxlaAEm0FdRkacpQ8HzTzsQ1WfSHi6uQ04v9for3OPaoBdLQw1IabcdaF/X0QoCSHEyADag9fE Qp9pyVHhJzxC79VXiN2hiyFk1UI45NrEW4/orRfoLcF5ve3oV5cY9XcJC3jgd/7jD6Sq6o09jS2 entoYTWn8ZA3/zP6L0mt+vKPDS9qocAxDRqBbFbLP6jKbPGNzjK1iocdh6jCZmwsyxSai1IrX+S UKBDbXp0bhem+ov1Pscf+CRr0ul8EPieWVOQSir691ZQT5pB5plqskBfhJ2V7gAs0IV9tBZnAEm qWonAenTtUZ2HP+vpsQ== X-Proofpoint-GUID: IZAbtlJY_qdpP7ejR8K79SVZJeoCPAHL X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293, Aquarius:18.0.1121, Hydra:6.1.51, FMLib:17.12.100.49 definitions=2026-02-24_02,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 lowpriorityscore=0 adultscore=0 priorityscore=1501 phishscore=0 clxscore=1015 spamscore=0 impostorscore=0 suspectscore=0 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602240168 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" As shown by commit 94d32fdc55a3 ("pipeline: simple: Consider output sizes when choosing pipe config"), the extra pixel columns CPU debayering requires on the input side makes resolution selection non trivial. Add logging of the selected input config on a successful configure() so that the logs clearly show which sensor mode has been selected. Reviewed-by: Milan Zamazal Signed-off-by: Hans de Goede --- Changes in v3: - Move from DebayerCpu::configure() to SoftwareIsp::configure() so that the input fmt also gets logged when using the DebayerEgl class Changes in v2: - New patch in v2 series --- src/libcamera/software_isp/software_isp.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 562cdba2..4cf5639d 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -21,6 +21,7 @@ #include #include +#include "libcamera/internal/bayer_format.h" #include "libcamera/internal/framebuffer.h" #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/software_isp/debayer_params.h" @@ -270,7 +271,16 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, if (ret < 0) return ret; - return debayer_->configure(inputCfg, outputCfgs, ccmEnabled_); + ret = debayer_->configure(inputCfg, outputCfgs, ccmEnabled_); + if (ret < 0) + return ret; + + LOG(SoftwareIsp, Info) + << "Input " << inputCfg.size + << "-" << BayerFormat::fromPixelFormat(inputCfg.pixelFormat) + << " stride " << inputCfg.stride; + + return 0; } /**