libcamera: software_isp: Move benchmark code to its own class

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>
This commit is contained in:
Hans de Goede 2025-05-10 16:12:16 +02:00 committed by Bryan O'Donoghue
parent d9ffeb0bf1
commit ba4218669b
6 changed files with 135 additions and 39 deletions

View file

@ -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 */

View file

@ -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',

View file

@ -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 */

View file

@ -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.

View file

@ -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 */

View file

@ -8,6 +8,7 @@ if not softisp_enabled
endif
libcamera_internal_sources += files([
'benchmark.cpp',
'debayer.cpp',
'debayer_cpu.cpp',
'software_isp.cpp',