From patchwork Mon Feb 23 16:09:27 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: 26226 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 09C29BE175 for ; Mon, 23 Feb 2026 16:09:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 061E462293; Mon, 23 Feb 2026 17:09:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="h2Dz0XUi"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="dsLHR58Y"; 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 94063621CE for ; Mon, 23 Feb 2026 17:09:36 +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 61NAX3F33698602 for ; Mon, 23 Feb 2026 16:09:35 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=2RrMTepel0f /n7pSHRAfooxWOp7CWavPYXh9mXTSMB4=; b=h2Dz0XUiqUQhM4AdDG9YhuR3cB9 EawSIHalryjNmdbjSq7snowYNbPWj31rga5N8b0Nmkkoxq13ZZMPqkd65DiwNIFh khZiW/TFiA0ZotnLbVFdXxemTTsGt5A2wG7nYx59Q37i8d203DEHaPvRqL5JfX6z y5E5zThE4lJ1GD9bQ3j85zrgz9ugLceLQG+oV2vk++4998D3an/mM1C8ZILBrgdV hZT7oPFHzp29A047oU4R5AJhGNpLJQm1bXQIEw2PVvR88nixd4BOd4uNHwtVWVix skp/qAAQ8FWcISpkJOI1+185hvdZAwNySbuhe8CLPeDVMCl3Iv9lBS3n1UQ== Received: from mail-vs1-f70.google.com (mail-vs1-f70.google.com [209.85.217.70]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cgn8191e0-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 23 Feb 2026 16:09:35 +0000 (GMT) Received: by mail-vs1-f70.google.com with SMTP id ada2fe7eead31-5fdede3f1ceso65109217137.1 for ; Mon, 23 Feb 2026 08:09:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771862974; x=1772467774; 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=2RrMTepel0f/n7pSHRAfooxWOp7CWavPYXh9mXTSMB4=; b=dsLHR58YMzTbiEmsxJi6OUh6OJRgjPJfjLaacn3uw32y6GQX3noACNW/GDyipeXMn8 C02Ius8y/iK4f1YfQiqwXXDnY8GSwngK+wnqnfWvhMC7OE1oPcBVr5pfL6yNmlXDMa60 coYwKa8CN9YEggHk8TFrZcMlvQyH+MqdivybzVuQUWRK8Jhai8Z+AVpnZDuAfLnvQjU5 IyvKtGeOFf0HUUJLGUZzg9CQhSUb9HUsRh7jZrnIRWkrYuCTguBD1XcMMbHklyBCDNoP CfRyJIy6O2jEILfHKPjm1Cx0tSLuBbr1I67gQAIsb798ButoLGxAowZ3SRmvZSMRigIV y4eg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771862974; x=1772467774; 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=2RrMTepel0f/n7pSHRAfooxWOp7CWavPYXh9mXTSMB4=; b=X4ErM/TXSeEnTudWxrsTjUVlLxRP2WOxPEX+QtCXhIpqyDpgcKwp5WVD1sGgawIIHx lgBPzv6x2dwWGY0hTT2K9K1eCj02U6AqBbacz7h7OvGx8wcXxcOr/YTub9Q2wHPE/t5O LzaAb2a5G7GqKuL34mXoAAkEusqeJsw7i/Enm3c/iQy9+y3Wfqg3oROHnEIrkps/NTzO iEOYbeecXJTQGM+r6yi7JLBG32Oh+UAzgqr1V7Z6wsxcUvlm7T5r8Fo61AmNGt7CPAiJ FXXrfoBXZePukofRTsXDpwbN5mcTeqsAaS+iUrex+xueGO8GKCLqcMwVxw3m8+CKiQBU F9iA== X-Gm-Message-State: AOJu0Yxiwg6QTOzpjwx4+mA5ONRAqjL7e+Z4qsTzdmuQ8uA5t5SCyhr5 atHqDCzJmu+TDgf9lA94iaU9nmjbLBgjF4tdc90n1Tuhm7O9aV5wxfEftBwk1lYJMpDerCFOfjQ QpaRGLVIwhnSSVFsEKYZ1hoTQaWZVnI9G98ifYZ77QE2yRM154sfF+sHPHMbKpJ48r8rcBZ9Ao3 pE9uZY3cY8 X-Gm-Gg: AZuq6aJgHKc7RlfFalEZcCYq/hKh6+jTTHs7rSDGd8LCFvV2DggoChl/p+QtGAGe3Zq Wd18EpT0tPuiK7P9Hikg3ko0wLliaPeyfvLKAIICmuFxHzITcM1P7yG3rAirbOYURx1tcdVeQRz Q/2UrXpqfZLJQqK9yZo/zHqEught57SxtPTZt9wDczvVHiSQSBnE9wIAHI8rK3m+52rBnk+YbZ2 HyXEponUikGhEBxpmsK8c4+TYIhLDChyf+UiOW6JQChq1uK9UpCrBbGVshgzpI+OzlCSiQl76Ge Wc+2jBfEykxR6FaZTYhdaAt+PHQSYkpGMfeuHkHmxSA8flWA86/t3q0Dzq+gjVkl5qj50IpTlJ8 Y286VC7GCmIdAeNFqRbc1Gjg+hbbT+siYwSI766ohebSBY+KtzA== X-Received: by 2002:a05:6102:dca:b0:5f7:24e9:6e91 with SMTP id ada2fe7eead31-5feb30faaebmr4985325137.36.1771862974238; Mon, 23 Feb 2026 08:09:34 -0800 (PST) X-Received: by 2002:a05:6102:dca:b0:5f7:24e9:6e91 with SMTP id ada2fe7eead31-5feb30faaebmr4985314137.36.1771862973768; Mon, 23 Feb 2026 08:09:33 -0800 (PST) Received: from t14s.vakwerkhuis.com ([78.108.130.194]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084c60b91sm338284066b.14.2026.02.23.08.09.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Feb 2026 08:09:33 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Hans de Goede Subject: [PATCH v2 1/4] software_isp: swstats_cpu: Prepare for multi-threading support Date: Mon, 23 Feb 2026 17:09:27 +0100 Message-ID: <20260223160930.27913-2-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> References: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-GUID: MM-xm84Y-0IxP98ELwm4l6TJ7sAkBWYR X-Proofpoint-ORIG-GUID: MM-xm84Y-0IxP98ELwm4l6TJ7sAkBWYR X-Authority-Analysis: v=2.4 cv=CbsFJbrl c=1 sm=1 tr=0 ts=699c7bbf cx=c_pps a=N1BjEkVkxJi3uNfLdpvX3g==:117 a=rrvG0T/C2D967D07Ol03YQ==:17 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=EUspDBNiAAAA:8 a=VvikW9XIONpR7lsxkDIA:9 a=crWF4MFLhNY0qMRaF8an:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjIzMDEzOSBTYWx0ZWRfX647zS9HdaeHr GejI4lJZIGpr3hqx+0CwoPR/Sgq+PknAIn/3TzY2diPip0ReGnTwQJpIlsXvSQScqKzQKQkiVUB IcVr8vNKnlGImDFBGzeIAJKZrR2UG20mnlkzymA0y0f5eVB+NIcwMHFAd8c5OfTM+csEewFZb2m VjzrRL8Nct1FV7pM+cavmfwXyKxuxgqWY8UEmzsddeQvxoFMZiURQfCtXDuDGDrJ4PnzMqEw6uZ XJZjgrC1RzNcr6gNJUWp8vTrv6UtZ6JP1XXPh76/V6RdjEH2nxnva7i+CHAe9Gl89RUrt7s1+Zx yOhKlEZuKS7eaCbLZwdmUhReNZaDiKOxOFwAhJChSuboNIuvJC0ReS49ZwRgDxuOf0Ujnocyojf +yungaeu9oL1Xibw5kjt/U+FYFdNkFAw4ujnWyDc6ujdWDHXl1KNcBzBRSnObxnrHGwnJ1iaTpt zOBhosGP5GjPnKiwE5g== 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-23_03,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 adultscore=0 impostorscore=0 priorityscore=1501 suspectscore=0 phishscore=0 spamscore=0 malwarescore=0 clxscore=1015 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602230139 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 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 64b3e23f5..feee92f99 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 1cedcfbc1..7c71aed96 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 (unsigned int i = 0; i < stats_.size(); i++) { + stats_[i].sum_ = RGB({ 0, 0, 0 }); + stats_[i].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 (unsigned int i = 0; i < stats_.size(); i++) { + sharedStats_->sum_ += stats_[i].sum_; + for (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++) + sharedStats_->yHistogram[j] += stats_[i].yHistogram[j]; + } + } + + 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 Mon Feb 23 16:09:28 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: 26228 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 D776DBE175 for ; Mon, 23 Feb 2026 16:09:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AD1C36229F; Mon, 23 Feb 2026 17:09:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="CnPWj1lq"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="eeaQvlgC"; 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 9EB746228C for ; Mon, 23 Feb 2026 17:09:38 +0100 (CET) Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61NDsIHr185231 for ; Mon, 23 Feb 2026 16:09:37 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=Hk4PSd+0CFh 8zus8u0oNViuor7lWwSz24+it6uh27zQ=; b=CnPWj1lq8et0BO4Q5BYRRskvJUO mpyi7QF0liBYzQNsqlWxfiHJOmoynhQseQ98OOfGrnP07FRKdOrsWj0S/nAUhgL8 b/Zcg8KeEpBvnd6IZWqhpfET6JsHSAekgvK+6OmEAOvLM9Sw+KuKvOiqNr2pe7nC IodJJQ/4WK+vpsrua/WxnkHocOuHvLwy8OWKhRRbPQKFq5uBcvZj30AcNsbDzTrG K1+r4CIAAWzjPZ/aoayMKCFLGvH6qkvG2tKxl/pQQIOX5a6CsToKwObG1ZgSxFTO O+OPji+bgE+TPiTvwUrsYZrEpHpdYmcAnRqZ0wWhtwXM5UGf8i6kN7Q1gFw== 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 4cgr69gefx-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 23 Feb 2026 16:09:36 +0000 (GMT) Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-8cb3ff05c73so4360646885a.0 for ; Mon, 23 Feb 2026 08:09:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771862976; x=1772467776; 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=Hk4PSd+0CFh8zus8u0oNViuor7lWwSz24+it6uh27zQ=; b=eeaQvlgCpQedAC1s2YZKkkdGP1asVyB+i/Ov/J644/mvm6HK2APVqri5NRKSd7EKYn BLQz/BR9rqzDqq7LLoqwByfjlNlaog7UqYl4g3YQyFsR4q0ECRoveegfc6IcZbzjp3sS NdnaEj25b/IEssWSuuX/JYFpkl/dnUnUxFqVERrWbdaxCHU67ddMWL/ZBw1iBKvbz9f6 Tyum1HkxuNv/FHzWkxeonTzAitZkiXrpxCs3L4CMl71iRDUq7ZfFl1AmXaz13yGkH8jQ jW8a4pRC/jKehKQTBKhGVA1caNJzWU+M2QaG8fZwssVssBDREDesfiAE3PHEcRZO51nB 57xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771862976; x=1772467776; 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=Hk4PSd+0CFh8zus8u0oNViuor7lWwSz24+it6uh27zQ=; b=FG7+2ZV8Q5rTcFA6FdpndZrW8E5Ab5ucXQQkoaHIgM3bHOjrO+fMrSol4Gr0AOyOGF p8K9W3nk2FP/JIZ2gAQ07Ng4l00rmaWJ9MFFR/Z+wmWveqTKnVDCsaCmBFN1tKyU1aHB zTxAU4loOBy+gcW4uszZIOWwjx66UoQRL9fYJ2iUdQsFsym42FbaMnMrZeEOiwH+Chwp uFzZRwppnQ3C9t2ukvYE5blX3D3A3DkYQb61FvuXOUlur22TBQRD51H6XZ/T1/b6Vg+v 81bng38nY095drgPUWH24cfEyh1kfhoxgUxjeFMYesyU9wjUhLfp3ciYRTZKhmMb16Ma TnXw== X-Gm-Message-State: AOJu0Yzf31OC/tJmHLMyIRWNVhhbd2NBxJ8UnOkUTaXwOMhhxskjDKF9 rYltCQCMsbPozjKdsRSmUfP9wWLIAyYnkkn9+yWxjPjaPMJ4BNLWalCvewvTKDDnAe8TDpdu1UM HooIibp0uecokhbncv+Qu/ewWN8zkaSJr4DPsMqOZNnp6ANvTk+PwQ3Y4L6LQgSxz532/ZH1WKa TYnqVHKbrJ X-Gm-Gg: AZuq6aKGEKd3M5aCRLjt5yBEH7GhUUZ/w/cn9j7Cco+X8dfpUSQIgjFQ+kCxLBFMKUE 2gvIrWxRvrzoVuNiJcqIjy68ToLi2T8Szz/pbROpiBjRZHVPhOKzmpcPBDvzPllR5W2DnCEyQQv olA7bgy0jGx55UG8gykVbdV9pcqeLdbLPtTFIYuiDPorFrX4fNZiD/esxw2FPpDJggTVUiuGHeD TSwbcY5nUE0ag6DsgMK35URtDtIZymIPfc6B/Aa/1khJqxc7w6gjZ709jI83qLRpJy0OhJtwuBa gv2yN4jTOLMkoywJCisSKEkoje5eUT4Bl7yh9mQUuAoowWIs+LSVXVwy99oF7m2F8JyuehIZfBK 3xsupE5htjX7It260nqWsd1PY5n6wMPJ3QXfsqcd6eKhtEQ5j5g== X-Received: by 2002:a05:620a:294f:b0:8c6:acca:4a29 with SMTP id af79cd13be357-8cb8c9d295cmr1190118685a.13.1771862975354; Mon, 23 Feb 2026 08:09:35 -0800 (PST) X-Received: by 2002:a05:620a:294f:b0:8c6:acca:4a29 with SMTP id af79cd13be357-8cb8c9d295cmr1190112085a.13.1771862974706; Mon, 23 Feb 2026 08:09:34 -0800 (PST) Received: from t14s.vakwerkhuis.com ([78.108.130.194]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084c60b91sm338284066b.14.2026.02.23.08.09.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Feb 2026 08:09:34 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Hans de Goede Subject: [PATCH v2 2/4] software_isp: debayer_cpu: Add DebayerCpuThread class Date: Mon, 23 Feb 2026 17:09:28 +0100 Message-ID: <20260223160930.27913-3-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> References: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Authority-Analysis: v=2.4 cv=O6A0fR9W c=1 sm=1 tr=0 ts=699c7bc0 cx=c_pps a=qKBjSQ1v91RyAK45QCPf5w==:117 a=rrvG0T/C2D967D07Ol03YQ==:17 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=Um2Pa8k9VHT-vaBCBUpS:22 a=EUspDBNiAAAA:8 a=SjPJea1MOwGqAC1umdEA:9 a=NFOGd7dJGGMPyQGDc5-O:22 X-Proofpoint-ORIG-GUID: mQBfYl70XMxUUsEkVBoIv4NSHL1cXpKl X-Proofpoint-GUID: mQBfYl70XMxUUsEkVBoIv4NSHL1cXpKl X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjIzMDEzOSBTYWx0ZWRfX22WHIFcxRukX 9d0yyxW7yji/H+aJuCZL+cmG096th4SQ2QHZjVDREw/yem4EGaR8y7UUoIVbcV/wNkfap64Ox9q vr7lxYHS9gAfSKK+VtGoaZ2oRoLSbqCfL5pM2Mzh07/R0i7M5d7TM/pZn//6vrSnTmVpgGPB3/v gPJrT5wM3ahDnG2IAeMEj/L/Xg+Qe5yTrZkaPOlf3YSOZjJtY1hSEa4+5m2uv0DOgneQSxYMNqD 5DVf4QcUYfsOZX8nfz2vNUl89obIC5TpB6eCusPkz2bnddzM/3O6cj1bZLfb1dXcYiClNtbaCmX H7BscVegbtev7w+uUVR0JA+C118C/N4kxONktu/xws5tpVed00uVF/ZkhwtLihdCtPe3tc6hqa0 y6g3VEW9Ixt6EtIyCFNZn2lH679e6Xq3jFOyXcLmbDdYrHK+eEjFJj/fLqAJhBeVnVE2wDpSiyx fh1ILUncNIPcceUOLWg== 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-23_03,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 clxscore=1015 lowpriorityscore=0 adultscore=0 priorityscore=1501 impostorscore=0 phishscore=0 malwarescore=0 bulkscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602230139 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 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 | 215 ++++++++++++++------- src/libcamera/software_isp/debayer_cpu.h | 20 +- 2 files changed, 159 insertions(+), 76 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index e7b012105..122bfbb05 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -27,6 +27,38 @@ namespace libcamera { +class DebayerCpuThread : public Object +{ +public: + DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, + bool enableInputMemcpy); + + void configure(unsigned int yStart, unsigned int yEnd); + void setupInputMemcpy(const uint8_t *linePointers[]); + void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); + void memcpyNextLine(const uint8_t *linePointers[]); + void process(uint32_t frame, const uint8_t *src, uint8_t *dst); + 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_; +}; + +DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, + bool enableInputMemcpy) + : debayer_(debayer), threadIndex_(threadIndex), + enableInputMemcpy_(enableInputMemcpy) +{ +} + /** * \class DebayerCpu * \brief Class for debayering on the CPU @@ -53,8 +85,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] = new DebayerCpuThread(this, i, enableInputMemcpy); } DebayerCpu::~DebayerCpu() = default; @@ -484,7 +522,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 +586,36 @@ 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; +} + +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 +656,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 +674,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 +700,42 @@ 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) +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 +745,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 +953,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 7a6517462..7196dcdd0 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::vectorthreads_; }; } /* namespace libcamera */ From patchwork Mon Feb 23 16:09:29 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: 26229 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 C0BD8C32EA for ; Mon, 23 Feb 2026 16:09:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5D09662299; Mon, 23 Feb 2026 17:09:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="b3oOvW2d"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="C5ZPSBiS"; 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 B739E62287 for ; Mon, 23 Feb 2026 17:09:38 +0100 (CET) Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61NAYcGQ322186 for ; Mon, 23 Feb 2026 16:09:37 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=pp4GDY/S4RF spnVUNwPz0HW9rkYc2d5geNOIcGEDaMI=; b=b3oOvW2dFLo2IQY9QZmWMxMkBig h93be8jE/tDzK1GBARkLEwZwWDp3syi+BnACXUHLCrntkSNeNJ+GffRcOPm4ClcL vBmK77l7xXEiGi37KpKHPlRU/j9B5pkoPicpVg8DDAJfE1pD3Iksb6KJzos1CGg5 4g7E8Rw5fMDQgFH9h9wpOMYCYyA11zwJ/gU9L/QfuMvth2qnHKRUmFm7pRCIFhcE zkG00JepyeDQxM1NN0/2euI+ppVjipHhwKKXsZXxUmHUszYZjixsevcMNYHIuHUY Tg16abZgjO0UenfSHUUzEm2ilOjfiyxbICLdcwXcLkoGFK8PEO13mYDm0BA== Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cgn8y1145-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 23 Feb 2026 16:09:37 +0000 (GMT) Received: by mail-qk1-f199.google.com with SMTP id af79cd13be357-8cb4d191ef1so652118185a.0 for ; Mon, 23 Feb 2026 08:09:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771862976; x=1772467776; 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=pp4GDY/S4RFspnVUNwPz0HW9rkYc2d5geNOIcGEDaMI=; b=C5ZPSBiSNS0j/DoEUsQM9nXEPhPA48gk/uXdZhSP8C8NZlTSzpcr7vbGUCtscgmPTa gR8C9BVhvEzmRRiYNMkQ2re4ryXXoFSsE+gMkG3JJsAPYg0Y3x1wIgZzHCEb0PHYiesU WGdjF8JilwZHa1BAXF3slBNji9l6ey8zkggzOqNdvjkipICjolF/qTfpLgFgGwo5W+lU l2xB+cVcMDfBjEXniS//wV2s9QIL2+Gx6QXm8i9fMNyWlCPwBsXJPjolUTmjNXSPQDLV FBYUalwvssKQpfpkdwgUi+dy34CuMzqIJK9N9E2mhmD4jGmElfT67balPyL/b3fzh8N2 ajrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771862976; x=1772467776; 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=pp4GDY/S4RFspnVUNwPz0HW9rkYc2d5geNOIcGEDaMI=; b=I03XSONgVW9i+3QewGSUdCpT6ces68xEVMVMPaLCMlIwpw9hKoB504C4ZsrACoI4pu pJk/FRiYlAtEPcAxx3bc5pSHAaynE4zAJt/U+L2lBUSu3YNzSnNYwETXAnId6b39R6bV Naxel1tjFEb+WtOWkQHHNPOhVWWEjT+NrbjQH9jg4yMNoiXXLEzCyL4Y0LnmoFT4M9mC UpXo+42AvgW3TOADN0y7d0bZz1uf3Y4DevHP3XdMCqde42QO0jXPCJ9iNGK+Gf3nc00A 4CHjh9XdwxNtwDz7CSsjuuz9PvmBVQYxyb+pco8sRMvOTtBLKDneAL/04OFkB5FK7oCL Dkdw== X-Gm-Message-State: AOJu0Yx3CSDSpoUiiRzz1b0ISsbpqJRXhnPHq9zG/72a6gv2bZb8aTpz k74JKvoVRCMiJkgZm5NcrSfBEOJV0ss3OpOirGdDs5//NSxy2HtGtmd4lsdRXslMKBsOoXe/Sbj PUhkquVpNcGxVK565N8yFKyDy+V4l/0P33JIL7XEpSUppCt+QTfY4UGXtziwvZemeE2VqgqvzhP Lvhk4XdudB X-Gm-Gg: AZuq6aIOfURWBbYpW0Ffz2iClKS6fXb4R3ihjPGb+UG47J0DA/b4UPVn6EcjmIDqdAN FgvuyWGQVCX9IQf42LFerixDGzRYDVWEOmJShZq4rAj58Wf1++2Y5zHbbKCGXyL5MXq1V7GfTTW WYy+T2cD08K1xetH8b54XDBmKchyvOsw2lXyshJ+Wj9Ptu3oUVO7isKdoad7i52vEiAfKhicJLL TXVw7SMUBG1LzEkXqVAKDn4ek1U+xVCG3lMrw8Sj6bxiYMGI4nQaoY+Rq+Gt8v4S26llMh0+9YW 718QiTKLd8XltaWHrSpuvcKKwnj09ThIDk7ATYjNhY/dtfcWNT9P2VGWNCZShCZQvLelRejgNRw ttkQ6HwrUMzyRFS0ncyQ1FY1bXBcISIoui79k5qpFDK5a3QMHLw== X-Received: by 2002:a05:620a:29c5:b0:8cb:4ba9:ccec with SMTP id af79cd13be357-8cb8ca92639mr1060160885a.72.1771862976286; Mon, 23 Feb 2026 08:09:36 -0800 (PST) X-Received: by 2002:a05:620a:29c5:b0:8cb:4ba9:ccec with SMTP id af79cd13be357-8cb8ca92639mr1060154585a.72.1771862975641; Mon, 23 Feb 2026 08:09:35 -0800 (PST) Received: from t14s.vakwerkhuis.com ([78.108.130.194]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084c60b91sm338284066b.14.2026.02.23.08.09.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Feb 2026 08:09:35 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Hans de Goede Subject: [PATCH v2 3/4] software_isp: debayer_cpu: Add multi-threading support Date: Mon, 23 Feb 2026 17:09:29 +0100 Message-ID: <20260223160930.27913-4-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> References: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjIzMDEzOSBTYWx0ZWRfX+2BIC4oSdKV+ ls8YZLbjOAL7aVU3sQDWeVa7weM/BbCo5TBtJJNPn6T27VuXmDCg2wagkuM6OaULC/rF/JKdWuZ 5yx98uhcohbtMopb4uWA75eMbWLhVW+JSTk262ZsH/nwSfxbOWa4hMgLeFyzRWwfTJ+c6cZvRlR sN6EOGzCgnvF5rb6fCa0HPBPIwg5nlLa5ESwAa658SJx4Ma5eNbHrjTTxCE/D5aImW7eDSZZeHE Y/FT2ejrXlvdJe79cfh5hGAdUyMclWK7CWmwFt0rEfCz/cDfUJC1LAbn/rtCeHoEURePpjQM0DD 8iiHI3HoJmeqUZi+47q8tvCkjK+hrkGveQoTRufhPRa8V0sfpXuatans+mO2TVRirK9IK1Mlta1 EkfLnq77cgHZb3vN7pGBSLTq2tPhe0RIXE+87cDDVN0whTdhmK04iB0OOUKOs3qZn5/AFg/f4jp 68x+HaN+ACfq17E97zw== X-Authority-Analysis: v=2.4 cv=edYwvrEH c=1 sm=1 tr=0 ts=699c7bc1 cx=c_pps a=HLyN3IcIa5EE8TELMZ618Q==:117 a=rrvG0T/C2D967D07Ol03YQ==:17 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=gowsoOTTUOVcmtlkKump:22 a=EUspDBNiAAAA:8 a=wcwPUnDRDUmv0zfwghEA:9 a=bTQJ7kPSJx9SKPbeHEYW:22 X-Proofpoint-GUID: VRgBxlBvilEpD_39Ykk9USmFBYyqWytG X-Proofpoint-ORIG-GUID: VRgBxlBvilEpD_39Ykk9USmFBYyqWytG 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-23_03,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 malwarescore=0 phishscore=0 clxscore=1015 priorityscore=1501 spamscore=0 impostorscore=0 bulkscore=0 suspectscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602230139 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 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 | 53 ++++++++++++++++++++-- src/libcamera/software_isp/debayer_cpu.h | 6 +++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 122bfbb05..ea1b17c1f 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" @@ -50,13 +52,15 @@ public: unsigned int lineBufferIndex_; std::vector lineBuffers_[DebayerCpu::kMaxLineBuffers]; bool enableInputMemcpy_; + Thread worker_; }; DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, bool enableInputMemcpy) : debayer_(debayer), threadIndex_(threadIndex), - enableInputMemcpy_(enableInputMemcpy) + enableInputMemcpy_(enableInputMemcpy), worker_("DebayerWorker") { + this->moveToThread(&worker_); } /** @@ -88,8 +92,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] = new DebayerCpuThread(this, i, enableInputMemcpy); @@ -714,6 +720,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) @@ -953,7 +964,24 @@ 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 (unsigned int i = 0; i < threads_.size(); i++) + threads_[i]->invokeMethod(&DebayerCpuThread::process, + ConnectionTypeQueued, frame, + in.planes()[0].data(), out.planes()[0].data()); + + { + MutexLocker locker(workPendingMutex_); + + auto workPending = ([&]() LIBCAMERA_TSA_REQUIRES(workPendingMutex_) { + return workPending_ == 0; + }); + + workPendingCv_.wait(locker, workPending); + } metadata.planes()[0].bytesused = out.planes()[0].size(); @@ -972,6 +1000,23 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output inputBufferReady.emit(input); } +int DebayerCpu::start() +{ + for (unsigned int i = 0; i < threads_.size(); i++) + threads_[i]->worker_.start(); + + return 0; +} + +void DebayerCpu::stop() +{ + for (unsigned int i = 0; i < threads_.size(); i++) + threads_[i]->worker_.exit(); + + for (unsigned int i = 0; i < threads_.size(); i++) + threads_[i]->worker_.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 7196dcdd0..2c84f8e40 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::vectorthreads_; }; From patchwork Mon Feb 23 16:09:30 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: 26230 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 4B52FC3293 for ; Mon, 23 Feb 2026 16:09:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EA5E6622A4; Mon, 23 Feb 2026 17:09:44 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="TWHPV6Fn"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="fq4xcnOD"; 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 292DC62292 for ; Mon, 23 Feb 2026 17:09:43 +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 61NEUlVU1217262 for ; Mon, 23 Feb 2026 16:09:41 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=I2h+swA9dGl FmB070M1FrKJWXEapp8T7v0FaAPedhvQ=; b=TWHPV6FnS8J8JLDUrN7GcMlc8Rj ZPzDy1NOQ5NmXxbKrRwfAN+9m44hKC9+a59brT6mtm6+2+1UEYhKeqQYOneUrT1C VmXx73J18RsLiP5VCmSgGpn0bVwNNIqEAfnzwjESV03zRDJzoUpfETRh59zVzP21 EXyOBpFUfiZMVBVIevdgqtMMdfgZ8lr9nkdcwU3ZaU0IJ8YFOJYPaOe0CArnTbkV OOGwx+Re2G0p6k8D4xsJBN1e5t7i0RIsnz752MsgN7zeDtXxFPLbSTx9jKlP2zWI 0Bo/C97Ks8WmiXk+2Br/ZUDJxVW0Jy1mynZq1NZomSZtZ207hcp0EK/8q1Q== Received: from mail-vs1-f70.google.com (mail-vs1-f70.google.com [209.85.217.70]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cf5vgwfat-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 23 Feb 2026 16:09:41 +0000 (GMT) Received: by mail-vs1-f70.google.com with SMTP id ada2fe7eead31-5fdfd7175c7so62749282137.2 for ; Mon, 23 Feb 2026 08:09:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771862980; x=1772467780; 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=I2h+swA9dGlFmB070M1FrKJWXEapp8T7v0FaAPedhvQ=; b=fq4xcnODbRSE+Xz9ZBY2qHxCjh1QZMarS1Cixi5hYhHNEIF1ZTNb+GIOPa3lR8qHRn iw1/SRV1a1XTFZ6BR98vNe+I59vc4B6fiw2QpRDgdfkS99aoZYFakqOyIimuiBHKNX5M m89OUlVMJ2+TAlPCWDqIyR9VSmB7Cw4LOmBMhzh+gnDeAdBidkrdM4DYu25gWuBPFA4Z QFYZICnzhlLboU8Sg4ka7Ok2oOQMejVSVOm//NmFGvPWJZxBpSWbrt62oqicFZrxnj09 T3Ob9+Y2oiFWy2jrgMRUebIafJof9FR60fcyeh1TQl0KrL54EyMzfacbXa1aJAcUGOlm 5xmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771862980; x=1772467780; 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=I2h+swA9dGlFmB070M1FrKJWXEapp8T7v0FaAPedhvQ=; b=v3ITp3n/A2nrOasx1dGRlx8Q7Y0ZUp7zDM6O5haRpFJCJ3jHw8jX8Nbt4m96ULU8Zb 4mcRsj9c9f6S0YEEh8FgaN1FXC6zUN0X6JnPzVlbwkcZGaV41MK5MPO7uwBvkvElanDH a9TQIuqEWraZb1hMZeFunK8RrrG6i9t77UaZlHknyR5YfV0thmgjJxfb5ERuYAOaMyAq w3Ls2an0INtZqN2iYwafNIHuF+LHOh5hP/n1ARc7BEE43/fnGVW7vW+WctgqLE2GFvCx xGH/+Qrjjs99B1pfVyxfxDgGGL1dKQ5vpaXiBOphI/cMYM87Fenb4H2yLRlIKAdsa+ib b6JA== X-Gm-Message-State: AOJu0YydPw/AmiqcpbEQojLRc97XeItNmrlfr7xm0XSiWzkv5T8mEdAy 5F4HG+OPNDNtxFvl4bFk8q4s08uYIS2FMq6FK7j744cCHVE99riWY5KuJMqW1JIcAJfwAG/j1+9 o++za7++IfcVaRFFbj5xhgXpUJRZMgJvzHwLxt75XGFiUFHuK52Ci/E+kPVImzgrXcw/5pg+AmY A61tvm6v4g X-Gm-Gg: AZuq6aLVACUDPnkHWNBMWVmJDeooI7tYSq2/hmGK7/D1Te2cxwoiN9kXB97JDtNkN3m D2VBl2Aly9ukdEk8ffAUSz4hFlzXJgCkjXoA3iOBXDte15tUuzLulIa/2ISEeONtcPwyUupnMRZ qVaaMX0XE2mOAYPDA1mW6Zs3TH3Iq6P5kKbb+KRklAbY95Nqk/2LPIGaxXu2nu++UhHvWmPqIqe nlr0zIHj4/D+mOQqMp7dQXMN9RVpISI7JkVNMv3CKRszY70Y0MyI0j/tD1A99620KOGebj97inG QpSh+4ubZCgdCQH1+y355mZcE3eqR5dzjDuecruJLUjkVRqTdTnAMC+3AgxFHjz5HXDQwQ9Rgfk AJfihHdIfBEshWVWRiLGAZL/5Lw6GRuzTxNIjwdm7Q2fPg6+jVA== X-Received: by 2002:a05:6102:d8f:b0:5e4:95f6:3dca with SMTP id ada2fe7eead31-5feb30b41bfmr4763170137.30.1771862977060; Mon, 23 Feb 2026 08:09:37 -0800 (PST) X-Received: by 2002:a05:6102:d8f:b0:5e4:95f6:3dca with SMTP id ada2fe7eead31-5feb30b41bfmr4763150137.30.1771862976696; Mon, 23 Feb 2026 08:09:36 -0800 (PST) Received: from t14s.vakwerkhuis.com ([78.108.130.194]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b9084c60b91sm338284066b.14.2026.02.23.08.09.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Feb 2026 08:09:36 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Hans de Goede Subject: [PATCH v2 4/4] software_isp: debayer_cpu: Log input config from configure() Date: Mon, 23 Feb 2026 17:09:30 +0100 Message-ID: <20260223160930.27913-5-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> References: <20260223160930.27913-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjIzMDEzOSBTYWx0ZWRfX7kgwyGqmnagc dHvub0JWGYX1MipSkAh3p+COSoP3P7bG0pY1zFxLR7YigglCJoIFAEDBdA4DIwS17M7D11Z5sny QxrijyOtpeSwBxznD4b85CQBTN8YNGyRWdfxi2MW0+Mud5ct5v1l3+gI+UpOGBYrVBmeppVRjFw ZGaSqiZqTxFxpXd7Mo8vgxmIMbUF2g3zmfbvMT04V00PxEXiM8ZhcSO8SJOjye90KYzzOWNNd+i 7RDbvyCtC1bENcMUknk5UYHr2uuKROVTg2xsWA4FSqC5XpMtfPBTP+mN9CnsyGOhoR/lRD7Nw/V am8moX9rmzy+KT6Dgql7etxFQQQN7aHEb3/ZrtzwCAgYSnFc5Doyjfr3lEFiUT72RQTaVZduo8z dWpSimXT+yYQvpOCdXtftL11AtCFzEVD46noDk6OGxfZsVEYz0/O/3TIzZcpVDZRQ4ZhWJ0c5Yf 1nhSYTEeCtLejEy8Igw== X-Authority-Analysis: v=2.4 cv=W+A1lBWk c=1 sm=1 tr=0 ts=699c7bc5 cx=c_pps a=N1BjEkVkxJi3uNfLdpvX3g==:117 a=rrvG0T/C2D967D07Ol03YQ==:17 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_K5XuSEh1TEqbUxoQ0s3:22 a=EUspDBNiAAAA:8 a=mKg8M22OkPar6P-70WAA:9 a=crWF4MFLhNY0qMRaF8an:22 X-Proofpoint-GUID: sb6ZHY2oIiE634gZMP-QP7Hz6yPzjBRt X-Proofpoint-ORIG-GUID: sb6ZHY2oIiE634gZMP-QP7Hz6yPzjBRt 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-23_03,2026-02-23_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 spamscore=0 bulkscore=0 adultscore=0 priorityscore=1501 clxscore=1015 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2602230139 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. Signed-off-by: Hans de Goede --- src/libcamera/software_isp/debayer_cpu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index ea1b17c1f..7c32c30d4 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -603,6 +603,11 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, } threads_[i]->configure(yStart, window_.height); + LOG(Debayer, Info) + << "Input " << inputCfg.size + << "-" << BayerFormat::fromPixelFormat(inputCfg.pixelFormat) + << " stride " << inputCfg.stride; + return 0; }