From patchwork Tue Dec 2 13:31:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25293 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 2EB11C32E0 for ; Tue, 2 Dec 2025 13:32:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8729D60C90; Tue, 2 Dec 2025 14:32:17 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="FJeuWeuq"; dkim-atps=neutral Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6DAAD60C7C for ; Tue, 2 Dec 2025 14:32:09 +0100 (CET) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-47789cd2083so32350935e9.2 for ; Tue, 02 Dec 2025 05:32:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764682329; x=1765287129; 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=yyoWJ0Rzqed6amy1jTZnt8wvjKyWv6LvwRUBP/6g4Vc=; b=FJeuWeuq2j3bdOPlrpDDkw6xxrvB6T4p2eVXrZRpIfGWsPs6eSZZE+ZxKunLHyN/CC k4om9Ikrrk8Q2ggeE+1jJMrXZljOZv2fzTd9VmbXNRsiWZ15ZsBsxeUeFfmKMmTWmiD5 demWWn8TUQzBLYq/JB4IEBMpeWXUb+d9cx+KiOR2L9sBNxVwXiD0B/sFrLkF8SMSk/PJ NwBo7eaNsmq+x5551u+unlXRPh2zFGK7dci6gAnL0SHI9XJTNJT6JjwRNrr6xOZgEPW3 VvBokXuC2gZ9ci4R9Ds75UiYabqUyoShn+G5cVUPGiQRgtrPU16MPQ2sSHR2SxzDmtU3 vFYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764682329; x=1765287129; 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=yyoWJ0Rzqed6amy1jTZnt8wvjKyWv6LvwRUBP/6g4Vc=; b=O0baHnyMGPMRNxhIVSq0ds0U/IcjyL3CvGrs1K7HyvFe5G4/5puBrTsD8EAkp3ZZBT O8pB//N43ncJhy4T5eBuCkoXjp8Br1J+wHcMoj5OXO5UnIP3DDl3bK3DTKCOQ1CunRWx fjOTF86j9eZ4AUPPHQXTT03Dg4pdSin1fbJhzrkc2SZUX9byca88QbGL2oRVDWndBrhp PBju3uFapkyyPbeVDd0zEz4G14sj44rR2sS72GzXSPw4sl2QflFA43W+7hgyIYXpLKyf g/hsXova6Jo3/rYHyJ+pGxGJ5f/Sb+anJlFkPrrDO/R/IxstdUI1OY7NLJJnr8Yr1jNL pmpA== X-Gm-Message-State: AOJu0YxQ1UyVLwvLaaQVj1o+dcIQhN5gCUbwag3e3mOLOeY4uaNtoitI 4AiCKh4rWqUqLsxCQ6F35ymg8GTpkRDxpPQI853Et2m1hyJ1yQl8TuskrPZB5IrO0FaTjxrW39+ jSuoF X-Gm-Gg: ASbGncvsKDhKyCV7c3lJKZND4b8MQ2Jgh4C0e8kMUa60n+K9SUdGetGEYUHukXPJGUX 8mQDcVs3B99GE05WpXJXoIYCr8ZiBzb2WFIMQB4u7MqosWAYCfaH8Vhv2CwDhWUD7pnqbCAqIqZ XKMjwL4A9F/1CoHhRaOvJz1qcXKFSbG8U1K66kBU2wW8xY1UKkWLmLpljATKMRXtltF39VGU27T +GLY7wbsW9NvJsy5EEkt3pxB7bkYYEKxue1KE9orVog3oWtfSOdfLvLyFbrvd+G7EvqM59bki9W 0g4tSKdlhuTgHX/qqLWElBPZhKTtVj5cDphklo39Cu5M8VlUgtV+96Rq4EseAjbYK+YWq43DzJe HWyL0XW021MLtoQokRLykMYCiGLlnAev/2fbRM/ZeOi9h2LnQZGGFb0lf2UM/ZK3H7xYtfbtsKV dCKHyM/mu6H+n+O9iNmjEmCjYWzrkG/d5I7h7TQhOnmVDQSEfjWt4Yo+SVY27KgS1c0Y0= X-Google-Smtp-Source: AGHT+IExBPtsx/U3v6pqhlHcvi6DmZSguLO4+sJnjQy1uL0nUm9usxxe3wy4elIogrnyoBSby+6zkQ== X-Received: by 2002:a05:600c:4ed2:b0:477:9e10:3e63 with SMTP id 5b1f17b1804b1-477c1164cebmr397194255e9.35.1764682328667; Tue, 02 Dec 2025 05:32:08 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42e1c5c30c4sm33363322f8f.9.2025.12.02.05.32.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:32:08 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Hans de Goede , Kieran Bingham , Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v3 07/22] libcamera: software_isp: Move benchmark code to its own class Date: Tue, 2 Dec 2025 13:31:38 +0000 Message-ID: <20251202133157.661407-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202133157.661407-1-bryan.odonoghue@linaro.org> References: <20251202133157.661407-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" From: Hans de Goede Move the code for the builtin benchmark to its own small Benchmark class. Reviewed-by: Kieran Bingham Reviewed-by: Milan Zamazal Signed-off-by: Hans de Goede [bod: Fixed up some drift in this patch since initial propostion] Signed-off-by: Bryan O'Donoghue --- .../internal/software_isp/benchmark.h | 39 ++++++++ .../internal/software_isp/meson.build | 1 + src/libcamera/software_isp/benchmark.cpp | 92 +++++++++++++++++++ src/libcamera/software_isp/debayer_cpu.cpp | 45 +-------- src/libcamera/software_isp/debayer_cpu.h | 6 +- src/libcamera/software_isp/meson.build | 1 + 6 files changed, 138 insertions(+), 46 deletions(-) create mode 100644 include/libcamera/internal/software_isp/benchmark.h create mode 100644 src/libcamera/software_isp/benchmark.cpp diff --git a/include/libcamera/internal/software_isp/benchmark.h b/include/libcamera/internal/software_isp/benchmark.h new file mode 100644 index 000000000..0680d6cd9 --- /dev/null +++ b/include/libcamera/internal/software_isp/benchmark.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * Simple builtin benchmark to measure software ISP processing times + */ + +#pragma once + +#include +#include +#include +#include "libcamera/internal/global_configuration.h" + +namespace libcamera { + +class Benchmark +{ +public: + Benchmark(const GlobalConfiguration &configuration); + ~Benchmark(); + + void startFrame(void); + void finishFrame(void); + +private: + timespec frameStartTime_; + bool measure; + /* Skip 30 frames for things to stabilize then measure 30 frames */ + unsigned int encounteredFrames_ = 0; + int64_t frameProcessTime_ = 0; + unsigned int skipBeforeMeasure_ = 30; + unsigned int framesToMeasure_ = 30; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build index ea3f3f1c1..df7c3b97d 100644 --- a/include/libcamera/internal/software_isp/meson.build +++ b/include/libcamera/internal/software_isp/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_internal_headers += files([ + 'benchmark.h', 'debayer_params.h', 'software_isp.h', 'swisp_stats.h', diff --git a/src/libcamera/software_isp/benchmark.cpp b/src/libcamera/software_isp/benchmark.cpp new file mode 100644 index 000000000..1a00ae569 --- /dev/null +++ b/src/libcamera/software_isp/benchmark.cpp @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * Simple builtin benchmark to measure software ISP processing times + */ + +#include "libcamera/internal/software_isp/benchmark.h" + +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Benchmark) + +/** + * \class Benchmark + * \brief Simple builtin benchmark + * + * Simple builtin benchmark to measure software ISP processing times. + */ + +/** + * \brief Constructs a Benchmark object + */ +Benchmark::Benchmark(const GlobalConfiguration &configuration) +{ + skipBeforeMeasure_ = configuration.option( + { "software_isp", "measure", "skip" }) + .value_or(skipBeforeMeasure_); + framesToMeasure_ = configuration.option( + { "software_isp", "measure", "number" }) + .value_or(framesToMeasure_); +} + +Benchmark::~Benchmark() +{ +} + +static inline int64_t timeDiff(timespec &after, timespec &before) +{ + return (after.tv_sec - before.tv_sec) * 1000000000LL + + (int64_t)after.tv_nsec - (int64_t)before.tv_nsec; +} + +/** + * \brief Start measuring process time for a single frame + * + * Call this function before processing frame data to start measuring + * the process time for a frame. + */ +void Benchmark::startFrame(void) +{ + measure = framesToMeasure_ > 0 && + encounteredFrames_ < skipBeforeMeasure_ + framesToMeasure_ && + ++encounteredFrames_ > skipBeforeMeasure_; + + if (measure) { + frameStartTime_ = {}; + clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime_); + } +} + +/** + * \brief Finish measuring process time for a single frame + * + * Call this function after processing frame data to finish measuring + * the process time for a frame. + * + * This function will log frame processing time information after + * Benchmark::kLastFrameToMeasure frames have been processed. + */ +void Benchmark::finishFrame(void) +{ + if (measure) { + timespec frameEndTime = {}; + clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime); + frameProcessTime_ += timeDiff(frameEndTime, frameStartTime_); + if (encounteredFrames_ == skipBeforeMeasure_ + framesToMeasure_) { + LOG(Benchmark, Info) + << "Processed " << framesToMeasure_ + << " frames in " << frameProcessTime_ / 1000 << "us, " + << frameProcessTime_ / (1000 * framesToMeasure_) + << " us/frame"; + } + } +} + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 67a303c65..b92c6a904 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -42,7 +42,7 @@ namespace libcamera { * \param[in] configuration The global configuration */ DebayerCpu::DebayerCpu(std::unique_ptr stats, const GlobalConfiguration &configuration) - : stats_(std::move(stats)) + : stats_(std::move(stats)), bench_(configuration) { /* * Reading from uncached buffers may be very slow. @@ -58,13 +58,6 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats, const GlobalConfigurat enableInputMemcpy_ = configuration.option({ "software_isp", "copy_input_buffer" }).value_or(true); - skipBeforeMeasure_ = configuration.option( - { "software_isp", "measure", "skip" }) - .value_or(skipBeforeMeasure_); - framesToMeasure_ = configuration.option( - { "software_isp", "measure", "number" }) - .value_or(framesToMeasure_); - /* Initialize color lookup tables */ for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { red_[i] = green_[i] = blue_[i] = i; @@ -571,9 +564,6 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, lineBuffers_[i].resize(lineBufferLength_); } - encounteredFrames_ = 0; - frameProcessTime_ = 0; - return 0; } @@ -765,27 +755,9 @@ void DebayerCpu::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) } } -namespace { - -inline int64_t timeDiff(timespec &after, timespec &before) -{ - return (after.tv_sec - before.tv_sec) * 1000000000LL + - (int64_t)after.tv_nsec - (int64_t)before.tv_nsec; -} - -} /* namespace */ - void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) { - timespec frameStartTime; - - bool measure = framesToMeasure_ > 0 && - encounteredFrames_ < skipBeforeMeasure_ + framesToMeasure_ && - ++encounteredFrames_ > skipBeforeMeasure_; - if (measure) { - frameStartTime = {}; - clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime); - } + bench_.startFrame(); std::vector dmaSyncers; for (const FrameBuffer::Plane &plane : input->planes()) @@ -840,18 +812,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output dmaSyncers.clear(); /* Measure before emitting signals */ - if (measure) { - timespec frameEndTime = {}; - clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime); - frameProcessTime_ += timeDiff(frameEndTime, frameStartTime); - if (encounteredFrames_ == skipBeforeMeasure_ + framesToMeasure_) { - LOG(Debayer, Info) - << "Processed " << framesToMeasure_ - << " frames in " << frameProcessTime_ / 1000 << "us, " - << frameProcessTime_ / (1000 * framesToMeasure_) - << " us/frame"; - } - } + bench_.finishFrame(); /* * Buffer ids are currently not used, so pass zeros as its parameter. diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 1cd411f26..aff32491e 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -17,6 +17,7 @@ #include +#include "libcamera/internal/software_isp/benchmark.h" #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/global_configuration.h" #include "libcamera/internal/software_isp/swstats_cpu.h" @@ -161,10 +162,7 @@ private: unsigned int xShift_; /* Offset of 0/1 applied to window_.x */ bool enableInputMemcpy_; bool swapRedBlueGains_; - unsigned int encounteredFrames_; - int64_t frameProcessTime_; - unsigned int skipBeforeMeasure_ = 30; - unsigned int framesToMeasure_ = 30; + Benchmark bench_; }; } /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index aac7eda7b..59fa5f02a 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -8,6 +8,7 @@ if not softisp_enabled endif libcamera_internal_sources += files([ + 'benchmark.cpp', 'debayer.cpp', 'debayer_cpu.cpp', 'software_isp.cpp',