[04/35] libcamera: software_isp: Move benchmark code to its own class
diff mbox series

Message ID 20250611013245.133785-5-bryan.odonoghue@linaro.org
State New
Headers show
Series
  • Add GLES 2.0 GPUISP to libcamera
Related show

Commit Message

Bryan O'Donoghue June 11, 2025, 1:32 a.m. UTC
From: Hans de Goede <hdegoede@redhat.com>

Move the code for the builtin benchmark to its own small
Benchmark class.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 .../internal/software_isp/benchmark.h         | 36 +++++++
 .../internal/software_isp/meson.build         |  1 +
 src/libcamera/software_isp/benchmark.cpp      | 93 +++++++++++++++++++
 src/libcamera/software_isp/debayer_cpu.cpp    | 36 +------
 src/libcamera/software_isp/debayer_cpu.h      |  7 +-
 src/libcamera/software_isp/meson.build        |  1 +
 6 files changed, 135 insertions(+), 39 deletions(-)
 create mode 100644 include/libcamera/internal/software_isp/benchmark.h
 create mode 100644 src/libcamera/software_isp/benchmark.cpp

Comments

Laurent Pinchart June 11, 2025, 12:10 p.m. UTC | #1
On Wed, Jun 11, 2025 at 02:32:14AM +0100, Bryan O'Donoghue wrote:
> From: Hans de Goede <hdegoede@redhat.com>
> 
> Move the code for the builtin benchmark to its own small
> Benchmark class.
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
>  .../internal/software_isp/benchmark.h         | 36 +++++++
>  .../internal/software_isp/meson.build         |  1 +
>  src/libcamera/software_isp/benchmark.cpp      | 93 +++++++++++++++++++
>  src/libcamera/software_isp/debayer_cpu.cpp    | 36 +------
>  src/libcamera/software_isp/debayer_cpu.h      |  7 +-
>  src/libcamera/software_isp/meson.build        |  1 +
>  6 files changed, 135 insertions(+), 39 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 00000000..8af25015
> --- /dev/null
> +++ b/include/libcamera/internal/software_isp/benchmark.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2024, Red Hat Inc.
> + *
> + * Authors:
> + * Hans de Goede <hdegoede@redhat.com>
> + *
> + * Simple builtin benchmark to measure software ISP processing times
> + */
> +
> +#pragma once
> +
> +#include <stdint.h>
> +#include <time.h>
> +
> +namespace libcamera {
> +
> +class Benchmark

This is a bit generic of a name for something specific to the soft ISP.
Is it time to move the soft ISP to a namespace ?

> +{
> +public:
> +	Benchmark();
> +	~Benchmark();
> +
> +	void startFrame(void);
> +	void finishFrame(void);
> +
> +private:
> +	unsigned int measuredFrames_;
> +	int64_t frameProcessTime_;
> +	timespec frameStartTime_;
> +	/* Skip 30 frames for things to stabilize then measure 30 frames */
> +	static constexpr unsigned int kFramesToSkip = 30;
> +	static constexpr unsigned int kLastFrameToMeasure = 60;
> +};
> +
> +} /* namespace libcamera */
> diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build
> index ea3f3f1c..df7c3b97 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 00000000..b3da3c41
> --- /dev/null
> +++ b/src/libcamera/software_isp/benchmark.cpp
> @@ -0,0 +1,93 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2024, Red Hat Inc.
> + *
> + * Authors:
> + * Hans de Goede <hdegoede@redhat.com>
> + *
> + * Simple builtin benchmark to measure software ISP processing times
> + */
> +
> +#include "libcamera/internal/software_isp/benchmark.h"
> +
> +#include <libcamera/base/log.h>
> +
> +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()
> +	: measuredFrames_(0), frameProcessTime_(0)
> +{
> +}
> +
> +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)
> +{
> +	if (measuredFrames_ >= Benchmark::kLastFrameToMeasure)
> +		return;
> +
> +	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 (measuredFrames_ >= Benchmark::kLastFrameToMeasure)
> +		return;
> +
> +	measuredFrames_++;
> +
> +	if (measuredFrames_ <= Benchmark::kFramesToSkip)
> +		return;
> +
> +	timespec frameEndTime = {};
> +	clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
> +	frameProcessTime_ += timeDiff(frameEndTime, frameStartTime_);
> +
> +	if (measuredFrames_ == Benchmark::kLastFrameToMeasure) {
> +		const unsigned int measuredFrames = Benchmark::kLastFrameToMeasure -
> +						    Benchmark::kFramesToSkip;
> +		LOG(Benchmark, Info)
> +			<< "Processed " << measuredFrames
> +			<< " frames in " << frameProcessTime_ / 1000 << "us, "
> +			<< frameProcessTime_ / (1000 * measuredFrames)
> +			<< " us/frame";
> +	}
> +}
> +
> +} /* namespace libcamera */
> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
> index 66f6038c..8d30bf4a 100644
> --- a/src/libcamera/software_isp/debayer_cpu.cpp
> +++ b/src/libcamera/software_isp/debayer_cpu.cpp
> @@ -554,9 +554,6 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,
>  			lineBuffers_[i].resize(lineBufferLength_);
>  	}
>  
> -	measuredFrames_ = 0;
> -	frameProcessTime_ = 0;
> -
>  	return 0;
>  }
>  
> @@ -746,24 +743,9 @@ void DebayerCpu::process4(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;
> -
> -	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) {
> -		frameStartTime = {};
> -		clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
> -	}
> +	bench_.startFrame();
>  
>  	std::vector<DmaSyncer> dmaSyncers;
>  	for (const FrameBuffer::Plane &plane : input->planes())
> @@ -817,21 +799,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output
>  	dmaSyncers.clear();
>  
>  	/* Measure before emitting signals */
> -	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
> -	    ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
> -		timespec frameEndTime = {};
> -		clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
> -		frameProcessTime_ += timeDiff(frameEndTime, frameStartTime);
> -		if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {
> -			const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -
> -							    DebayerCpu::kFramesToSkip;
> -			LOG(Debayer, Info)
> -				<< "Processed " << measuredFrames
> -				<< " frames in " << frameProcessTime_ / 1000 << "us, "
> -				<< frameProcessTime_ / (1000 * measuredFrames)
> -				<< " 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 89a89893..182607cd 100644
> --- a/src/libcamera/software_isp/debayer_cpu.h
> +++ b/src/libcamera/software_isp/debayer_cpu.h
> @@ -17,6 +17,7 @@
>  
>  #include <libcamera/base/object.h>
>  
> +#include "libcamera/internal/software_isp/benchmark.h"
>  #include "libcamera/internal/bayer_format.h"
>  #include "libcamera/internal/software_isp/swstats_cpu.h"
>  
> @@ -160,11 +161,7 @@ private:
>  	unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
>  	bool enableInputMemcpy_;
>  	bool swapRedBlueGains_;
> -	unsigned int measuredFrames_;
> -	int64_t frameProcessTime_;
> -	/* Skip 30 frames for things to stabilize then measure 30 frames */
> -	static constexpr unsigned int kFramesToSkip = 30;
> -	static constexpr unsigned int kLastFrameToMeasure = 60;
> +	Benchmark bench_;
>  };
>  
>  } /* namespace libcamera */
> diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
> index aac7eda7..59fa5f02 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',

Patch
diff mbox series

diff --git a/include/libcamera/internal/software_isp/benchmark.h b/include/libcamera/internal/software_isp/benchmark.h
new file mode 100644
index 00000000..8af25015
--- /dev/null
+++ b/include/libcamera/internal/software_isp/benchmark.h
@@ -0,0 +1,36 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Red Hat Inc.
+ *
+ * Authors:
+ * Hans de Goede <hdegoede@redhat.com>
+ *
+ * Simple builtin benchmark to measure software ISP processing times
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <time.h>
+
+namespace libcamera {
+
+class Benchmark
+{
+public:
+	Benchmark();
+	~Benchmark();
+
+	void startFrame(void);
+	void finishFrame(void);
+
+private:
+	unsigned int measuredFrames_;
+	int64_t frameProcessTime_;
+	timespec frameStartTime_;
+	/* Skip 30 frames for things to stabilize then measure 30 frames */
+	static constexpr unsigned int kFramesToSkip = 30;
+	static constexpr unsigned int kLastFrameToMeasure = 60;
+};
+
+} /* namespace libcamera */
diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build
index ea3f3f1c..df7c3b97 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 00000000..b3da3c41
--- /dev/null
+++ b/src/libcamera/software_isp/benchmark.cpp
@@ -0,0 +1,93 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Red Hat Inc.
+ *
+ * Authors:
+ * Hans de Goede <hdegoede@redhat.com>
+ *
+ * Simple builtin benchmark to measure software ISP processing times
+ */
+
+#include "libcamera/internal/software_isp/benchmark.h"
+
+#include <libcamera/base/log.h>
+
+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()
+	: measuredFrames_(0), frameProcessTime_(0)
+{
+}
+
+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)
+{
+	if (measuredFrames_ >= Benchmark::kLastFrameToMeasure)
+		return;
+
+	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 (measuredFrames_ >= Benchmark::kLastFrameToMeasure)
+		return;
+
+	measuredFrames_++;
+
+	if (measuredFrames_ <= Benchmark::kFramesToSkip)
+		return;
+
+	timespec frameEndTime = {};
+	clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
+	frameProcessTime_ += timeDiff(frameEndTime, frameStartTime_);
+
+	if (measuredFrames_ == Benchmark::kLastFrameToMeasure) {
+		const unsigned int measuredFrames = Benchmark::kLastFrameToMeasure -
+						    Benchmark::kFramesToSkip;
+		LOG(Benchmark, Info)
+			<< "Processed " << measuredFrames
+			<< " frames in " << frameProcessTime_ / 1000 << "us, "
+			<< frameProcessTime_ / (1000 * measuredFrames)
+			<< " us/frame";
+	}
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
index 66f6038c..8d30bf4a 100644
--- a/src/libcamera/software_isp/debayer_cpu.cpp
+++ b/src/libcamera/software_isp/debayer_cpu.cpp
@@ -554,9 +554,6 @@  int DebayerCpu::configure(const StreamConfiguration &inputCfg,
 			lineBuffers_[i].resize(lineBufferLength_);
 	}
 
-	measuredFrames_ = 0;
-	frameProcessTime_ = 0;
-
 	return 0;
 }
 
@@ -746,24 +743,9 @@  void DebayerCpu::process4(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;
-
-	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) {
-		frameStartTime = {};
-		clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
-	}
+	bench_.startFrame();
 
 	std::vector<DmaSyncer> dmaSyncers;
 	for (const FrameBuffer::Plane &plane : input->planes())
@@ -817,21 +799,7 @@  void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output
 	dmaSyncers.clear();
 
 	/* Measure before emitting signals */
-	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
-	    ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
-		timespec frameEndTime = {};
-		clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
-		frameProcessTime_ += timeDiff(frameEndTime, frameStartTime);
-		if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {
-			const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -
-							    DebayerCpu::kFramesToSkip;
-			LOG(Debayer, Info)
-				<< "Processed " << measuredFrames
-				<< " frames in " << frameProcessTime_ / 1000 << "us, "
-				<< frameProcessTime_ / (1000 * measuredFrames)
-				<< " 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 89a89893..182607cd 100644
--- a/src/libcamera/software_isp/debayer_cpu.h
+++ b/src/libcamera/software_isp/debayer_cpu.h
@@ -17,6 +17,7 @@ 
 
 #include <libcamera/base/object.h>
 
+#include "libcamera/internal/software_isp/benchmark.h"
 #include "libcamera/internal/bayer_format.h"
 #include "libcamera/internal/software_isp/swstats_cpu.h"
 
@@ -160,11 +161,7 @@  private:
 	unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
 	bool enableInputMemcpy_;
 	bool swapRedBlueGains_;
-	unsigned int measuredFrames_;
-	int64_t frameProcessTime_;
-	/* Skip 30 frames for things to stabilize then measure 30 frames */
-	static constexpr unsigned int kFramesToSkip = 30;
-	static constexpr unsigned int kLastFrameToMeasure = 60;
+	Benchmark bench_;
 };
 
 } /* namespace libcamera */
diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
index aac7eda7..59fa5f02 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',