From patchwork Mon Feb 16 19:02:00 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: 26164 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 7CFD8C0DA4 for ; Mon, 16 Feb 2026 19:02:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 16F68621F6; Mon, 16 Feb 2026 20:02:12 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="S9+VVNS7"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Jhn03iVy"; 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 7584562084 for ; Mon, 16 Feb 2026 20:02:10 +0100 (CET) Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61GBCMhu2522870 for ; Mon, 16 Feb 2026 19:02:09 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=ZPJPpQWAv3f wV2B3qD8jcpXwRAqAWVW9lYTGrYN+zBY=; b=S9+VVNS7WFJNfxZMOBLZuxQjSSY c+QssJXfMo/9Uq+Mb1YIm6c2xibe26TQmr9qVcarO9kDp9FctTeaaM+4owaGkEr1 1Q8JssshbLvLFy6Q2abEglwymaEBHP6kQT1CYQnRXJwCxeJaln6/DNZ0waaBFoxi YwnvXJfjoXKZxmOUw2usG3znCihsvpDnNPgXHoU8eYTBJ2HWDL0eDmMsEESZwd81 Glps/M36dVjimNjbYVs1ACRf2ll3hNv9hUyF8qBdLHZBfRpzOuqb86G8EUSLuqR/ cmbNvzD5VgrKrrSd+yk2nBdgWPMyQfZH+jEveqdkf/llfFmJzDIDwXPI89A== Received: from mail-vk1-f198.google.com (mail-vk1-f198.google.com [209.85.221.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cb6bukt7g-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 16 Feb 2026 19:02:08 +0000 (GMT) Received: by mail-vk1-f198.google.com with SMTP id 71dfb90a1353d-5662a8e87a0so6082139e0c.1 for ; Mon, 16 Feb 2026 11:02:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1771268527; x=1771873327; 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=ZPJPpQWAv3fwV2B3qD8jcpXwRAqAWVW9lYTGrYN+zBY=; b=Jhn03iVySC94d16byLjk7kIoWiv4/ClQw8BK/2gaPpyb32yRTR9VMUOOcYiSV4e8W9 CbSRQs2Qz+PT2sgIsnuyXiwbRajYXJSe98e5wtVM6dcsn93puPkXszpOaeZsQGIrRQg7 AwjMOsOrvvvn15YWfslnGSPho7CLGKst4DUiAesGZ9iBly93l7xQEGnpltpaiV9R8Zke lPzTXKPR0DI9i53oA5pxuzOqt6YvU51nyxZGxejV4Bg/SOkXmlkoV0NxuMTxJ6zI2v6s UpV4YlbEVDoqqndxuBONgJZwZA8NcNLigX3qCQnE/ddIsgEl+8ItShucu+gKPWKRC/kW JJhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771268527; x=1771873327; 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=ZPJPpQWAv3fwV2B3qD8jcpXwRAqAWVW9lYTGrYN+zBY=; b=XNBi4bYhAvP6NNw6AEl70TOms/EaS0+TbmJnUiismemtyINO5r0ICrbkyLDZaDkRcu dR7owhq+mp0Zb0JQp3Ue+fIVXAyRGEfx2DkXPc9knGNyTSL2Ho6mjzhtsLvLw5ruFPau UjKma71vGIILs9KTRBfgKWP0MZBO7/9T7AF3t7ppv9J+0TLFKZqRQFnDnrfk43WB/NgW sQGa+nQQhP37jyEfASaOdaD1KEQe72V6rv8r4JUIQTy4oYXUJrxXA1abdP0+ja5/WM4r HhV2irvl/iqhVvyAe9WvdonNiAms5fNHnKVDUOQrXYli9+CY9Ve6swy730mkAkQMz5hf qqOw== X-Gm-Message-State: AOJu0YwqXTIWjLMTkKkfVwXdTkLsaCI9Oevd5L0nlS496TrnQzCJdonR /UUnvwoCSrtSZ2wUW624gZth/kTj6rdI0n21+65U6GXxUorkhtBGDxkZPdg/USXRj4pv8fnYyVw hoyxa9iydz7kge2RUGjMPbHLTwmHuS5TW1dprEEVjRwqdYRiqneIFcsNW2njDf6TRThg6vTpTqn vzysj+RrME X-Gm-Gg: AZuq6aKjSkAJa3560N/GmHV7aAk6LOvM7EgbCe7OUdBZzHbce9kJvrwtKUSsrB+5/8i 7Qx6cWiymkquCzxs6jmcopCPzAjQEH22wmyJ7sH8EpCVGkwAHga++2bTeV07tdrYAHe8GwVbVsx xXgkY45lAi6rzgrjE5ZLjYCtbKIxrqGA8tT7sPYMD6QLu79y7dQYn1pXC+y2pbwRg0La7b6bdQh jSz1PgzT/4gjeXHfAMYE4MFVmC29Ono2TE0LUmh5y6rNpLyvuqh2tighO3CH6q/aQTSlQsdk11L Q7/UW3wL2mDXzSJhX2EUOJh5BdypoPH9UQxn2JjOaBT+XEwAuSSo5RiQ2cb/e/ZDe/yfMo/bCDf b6I93n5D1ZQpmnlJH9u+Lkd0p2BDOZs0K+qVbQfXvK9a3Yo/oy38mxNT52bWCQ65bFkFpNc84A/ 6WEKDqG4/QfzlUc/vSQPc5z981d0W7SAOwrMVb X-Received: by 2002:a05:6122:a01:b0:563:73ff:19be with SMTP id 71dfb90a1353d-56889b6bd02mr2103340e0c.8.1771268527254; Mon, 16 Feb 2026 11:02:07 -0800 (PST) X-Received: by 2002:a05:6122:a01:b0:563:73ff:19be with SMTP id 71dfb90a1353d-56889b6bd02mr2103283e0c.8.1771268526657; Mon, 16 Feb 2026 11:02:06 -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-b8fc735e587sm276698966b.2.2026.02.16.11.02.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Feb 2026 11:02:06 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org, Milan Zamazal Cc: Hans de Goede Subject: [PATCH 1/5] software_isp: swstats_cpu: Move accumulator storage out of the class Date: Mon, 16 Feb 2026 20:02:00 +0100 Message-ID: <20260216190204.106922-2-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260216190204.106922-1-johannes.goede@oss.qualcomm.com> References: <20260216190204.106922-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-GUID: j7gR0LYcap0kG8jzxCFVBwRbf8C_6K8R X-Proofpoint-ORIG-GUID: j7gR0LYcap0kG8jzxCFVBwRbf8C_6K8R X-Authority-Analysis: v=2.4 cv=M8dA6iws c=1 sm=1 tr=0 ts=699369b0 cx=c_pps a=1Os3MKEOqt8YzSjcPV0cFA==:117 a=xqWC_Br6kY4A:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=EUspDBNiAAAA:8 a=3n2xhyToohh5fnZkaeQA:9 a=hhpmQAJR8DioWGSBphRh:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjE2MDE2MyBTYWx0ZWRfX6LJNkA33AM6L 7CzMv7vI1yC8IXt0EjsZwOoYMtoGufYJE6j16rjM349g5IrkQEpOGyj/wkRgGwV7rW4vMUVqQ25 oJYBkw8BO8gZ+f6qDVcqAJ8lTr1OfIi7D2v92PmQzbBYvEXrcJB6lUlebneMkMpjfuKrXb9xzqI HB9LgW852xrBuDOoCRdGjnvwCh1PS9MxQT1SJMwYjmIVndumxDJZ80vIWTt/IDpnRm4YQst9g+T cPhoFWMkCCyuzksjjfKd0YEbKl1w/neKWEl8ZU7zBX62/nssz0tC2zRNa5V5vepvVjojJWRn/N2 qwUfG0loJCqPLZKe/6ScxMWqNm0U6UFT0M3ZerHhZsSd5NgkqA2dWgqgkkxUimL+vuYc7PnFtpG bDXoe1fmAqjJyU6NBj0J5FXU7LTL71qgXn+24PELY9tAVmfiO+gJRG/AWIRu2a2Po9EyudeQXO0 LlpjNEk+8bOTcjE+Zxg== 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-16_06,2026-02-16_04,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 adultscore=0 suspectscore=0 bulkscore=0 impostorscore=0 clxscore=1015 phishscore=0 lowpriorityscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602160163 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" Move the storage used to accumulate the RGB sums and the Y histogram out of the SwStatsCpu class and into the callers. The idea is to allow a single SwStatsCpu object to be shared between multiple threads each processing part of the image, with finishFrame() accumulating the per thread data into the final stats for the entire frame. This is a preparation patch for making DebayerCpu support multi-threading and this could also be used to make processFrame() multi-threaded. Benchmarking with the GPU-ISP which does separate swstats benchmarking, on the Uno-Q which has a weak CPU which is good for performance testing, shows 20-21ms to generate stats for a 3272x2464 frame both before and after this change. Signed-off-by: Hans de Goede --- .../internal/software_isp/swstats_cpu.h | 29 ++++----- src/libcamera/software_isp/debayer_cpu.cpp | 12 ++-- src/libcamera/software_isp/debayer_cpu.h | 1 + src/libcamera/software_isp/swstats_cpu.cpp | 65 +++++++++++++------ 4 files changed, 65 insertions(+), 42 deletions(-) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 64b3e23f..a157afe8 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -53,11 +53,11 @@ public: int configure(const StreamConfiguration &inputCfg); void setWindow(const Rectangle &window); - void startFrame(uint32_t frame); - void finishFrame(uint32_t frame, uint32_t bufferId); + void startFrame(uint32_t frame, struct SwIspStats statsBuffer[], unsigned int statsBufferCount); + void finishFrame(uint32_t frame, uint32_t bufferId, struct SwIspStats statsBuffer[], unsigned int statsBufferCount); 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[], SwIspStats *stats) { if (frame % kStatPerNumFrames) return; @@ -66,10 +66,10 @@ public: y >= (window_.y + window_.height)) return; - (this->*stats0_)(src); + (this->*stats0_)(src, stats); } - void processLine2(uint32_t frame, unsigned int y, const uint8_t *src[]) + void processLine2(uint32_t frame, unsigned int y, const uint8_t *src[], SwIspStats *stats) { if (frame % kStatPerNumFrames) return; @@ -78,27 +78,27 @@ public: y >= (window_.y + window_.height)) return; - (this->*stats2_)(src); + (this->*stats2_)(src, stats); } Signal statsReady; private: - using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]); - using processFrameFn = void (SwStatsCpu::*)(MappedFrameBuffer &in); + using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[], SwIspStats *stats); + using processFrameFn = void (SwStatsCpu::*)(MappedFrameBuffer &in, SwIspStats *stats); 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); + void processBayerFrame2(MappedFrameBuffer &in, SwIspStats *stats); processFrameFn processFrame_; @@ -117,7 +117,6 @@ private: unsigned int stride_; SharedMemObject sharedStats_; - SwIspStats stats_; Benchmark bench_; }; diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index d0988357..97c1959a 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -673,7 +673,7 @@ void DebayerCpu::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) for (unsigned int y = 0; y < yEnd; y += 2) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine0(frame, y, linePointers); + stats_->processLine0(frame, y, linePointers, &statsBuffer_); (this->*debayer0_)(dst, linePointers); src += inputConfig_.stride; dst += outputConfig_.stride; @@ -688,7 +688,7 @@ void DebayerCpu::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) if (window_.y == 0) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine0(frame, yEnd, linePointers); + stats_->processLine0(frame, yEnd, linePointers, &statsBuffer_); (this->*debayer0_)(dst, linePointers); src += inputConfig_.stride; dst += outputConfig_.stride; @@ -724,7 +724,7 @@ void DebayerCpu::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) for (unsigned int y = 0; y < window_.height; y += 4) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine0(frame, y, linePointers); + stats_->processLine0(frame, y, linePointers, &statsBuffer_); (this->*debayer0_)(dst, linePointers); src += inputConfig_.stride; dst += outputConfig_.stride; @@ -737,7 +737,7 @@ void DebayerCpu::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - stats_->processLine2(frame, y, linePointers); + stats_->processLine2(frame, y, linePointers, &statsBuffer_); (this->*debayer2_)(dst, linePointers); src += inputConfig_.stride; dst += outputConfig_.stride; @@ -866,7 +866,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output return; } - stats_->startFrame(frame); + stats_->startFrame(frame, &statsBuffer_, 1); if (inputConfig_.patternSize.height == 2) process2(frame, in.planes()[0].data(), out.planes()[0].data()); @@ -885,7 +885,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output * * \todo Pass real bufferId once stats buffer passing is changed. */ - stats_->finishFrame(frame, 0); + stats_->finishFrame(frame, 0, &statsBuffer_, 1); outputBufferReady.emit(output); inputBufferReady.emit(input); } diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 7a651746..8abf5168 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -135,6 +135,7 @@ private: LookupTable gammaLut_; bool ccmEnabled_; DebayerParams params_; + SwIspStats statsBuffer_; debayerFn debayer0_; debayerFn debayer1_; diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 5c3011a7..23842f6c 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -182,14 +182,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 +214,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 +240,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 +266,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 +292,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; @@ -321,10 +321,13 @@ void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[]) /** * \brief Reset state to start statistics gathering for a new frame * \param[in] frame The frame number + * \param[in] statsBuffer Array of buffers storing stats + * \param[in] statsBufferCount number of buffers in the statsBuffer array * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::startFrame(uint32_t frame) +void SwStatsCpu::startFrame(uint32_t frame, + struct SwIspStats statsBuffer[], unsigned int statsBufferCount) { if (frame % kStatPerNumFrames) return; @@ -332,21 +335,39 @@ 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 < statsBufferCount; i++) { + statsBuffer[i].sum_ = RGB({ 0, 0, 0 }); + statsBuffer[i].yHistogram.fill(0); + } } /** * \brief Finish statistics calculation for the current frame * \param[in] frame The frame number * \param[in] bufferId ID of the statistics buffer + * \param[in] statsBuffer Array of buffers storing stats + * \param[in] statsBufferCount number of buffers in the statsBuffer array * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId) +void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId, + struct SwIspStats statsBuffer[], unsigned int statsBufferCount) { - stats_.valid = frame % kStatPerNumFrames == 0; - *sharedStats_ = stats_; + if (frame % kStatPerNumFrames) { + sharedStats_->valid = false; + statsReady.emit(frame, bufferId); + return; + } + + sharedStats_->sum_ = RGB({ 0, 0, 0 }); + sharedStats_->yHistogram.fill(0); + for (unsigned int i = 0; i < statsBufferCount; i++) { + sharedStats_->sum_ += statsBuffer[i].sum_; + for (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++) + sharedStats_->yHistogram[j] += statsBuffer[i].yHistogram[j]; + } + + sharedStats_->valid = true; statsReady.emit(frame, bufferId); } @@ -487,7 +508,7 @@ void SwStatsCpu::setWindow(const Rectangle &window) window_.height &= ~(patternSize_.height - 1); } -void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in) +void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in, SwIspStats *stats) { const uint8_t *src = in.planes()[0].data(); const uint8_t *linePointers[3]; @@ -504,7 +525,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); src += stride_ * 2; } } @@ -520,12 +541,14 @@ void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in) void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input) { if (frame % kStatPerNumFrames) { - finishFrame(frame, bufferId); + finishFrame(frame, bufferId, NULL, 0); return; } + SwIspStats stats; + bench_.startFrame(); - startFrame(frame); + startFrame(frame, &stats, 1); MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); if (!in.isValid()) { @@ -533,8 +556,8 @@ void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *in return; } - (this->*processFrame_)(in); - finishFrame(frame, bufferId); + (this->*processFrame_)(in, &stats); + finishFrame(frame, bufferId, &stats, 1); bench_.finishFrame(); }