libcamera: swstats_cpu: Add processFrame() method
Add a method to the SwstatsCpu class to process a whole Framebuffer in one go, rather then line by line. This is useful for gathering stats when debayering is not necessary or is not done on the CPU. Reviewed-by: Milan Zamazal <mzamazal@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> [bod: various rebase splats fixed] [bod: Added constructor Doxygen header] [bod: Squashed a fix from Hans to calculate stats on every 4th frame] Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
committed by
Kieran Bingham
parent
bf51f39f3b
commit
134f926346
@@ -18,18 +18,23 @@
|
||||
#include <libcamera/geometry.h>
|
||||
|
||||
#include "libcamera/internal/bayer_format.h"
|
||||
#include "libcamera/internal/framebuffer.h"
|
||||
#include "libcamera/internal/global_configuration.h"
|
||||
#include "libcamera/internal/shared_mem_object.h"
|
||||
#include "libcamera/internal/software_isp/swisp_stats.h"
|
||||
|
||||
#include "benchmark.h"
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
class PixelFormat;
|
||||
class MappedFrameBuffer;
|
||||
struct StreamConfiguration;
|
||||
|
||||
class SwStatsCpu
|
||||
{
|
||||
public:
|
||||
SwStatsCpu();
|
||||
SwStatsCpu(const GlobalConfiguration &configuration);
|
||||
~SwStatsCpu() = default;
|
||||
|
||||
/*
|
||||
@@ -50,6 +55,7 @@ public:
|
||||
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[])
|
||||
{
|
||||
@@ -79,6 +85,7 @@ public:
|
||||
|
||||
private:
|
||||
using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]);
|
||||
using processFrameFn = void (SwStatsCpu::*)(MappedFrameBuffer &in);
|
||||
|
||||
int setupStandardBayerOrder(BayerFormat::Order order);
|
||||
/* Bayer 8 bpp unpacked */
|
||||
@@ -91,6 +98,10 @@ private:
|
||||
void statsBGGR10PLine0(const uint8_t *src[]);
|
||||
void statsGBRG10PLine0(const uint8_t *src[]);
|
||||
|
||||
void processBayerFrame2(MappedFrameBuffer &in);
|
||||
|
||||
processFrameFn processFrame_;
|
||||
|
||||
/* Variables set by configure(), used every line */
|
||||
statsProcessFn stats0_;
|
||||
statsProcessFn stats2_;
|
||||
@@ -103,9 +114,11 @@ private:
|
||||
Size patternSize_;
|
||||
|
||||
unsigned int xShift_;
|
||||
unsigned int stride_;
|
||||
|
||||
SharedMemObject<SwIspStats> sharedStats_;
|
||||
SwIspStats stats_;
|
||||
Benchmark bench_;
|
||||
};
|
||||
|
||||
} /* namespace libcamera */
|
||||
|
||||
@@ -108,14 +108,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
|
||||
return;
|
||||
}
|
||||
|
||||
auto stats = std::make_unique<SwStatsCpu>();
|
||||
const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration();
|
||||
|
||||
auto stats = std::make_unique<SwStatsCpu>(configuration);
|
||||
if (!stats->isValid()) {
|
||||
LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object";
|
||||
return;
|
||||
}
|
||||
stats->statsReady.connect(this, &SoftwareIsp::statsReady);
|
||||
|
||||
const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration();
|
||||
debayer_ = std::make_unique<DebayerCpu>(std::move(stats), configuration);
|
||||
debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);
|
||||
debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <libcamera/stream.h>
|
||||
|
||||
#include "libcamera/internal/bayer_format.h"
|
||||
#include "libcamera/internal/mapped_framebuffer.h"
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
@@ -34,6 +35,15 @@ namespace libcamera {
|
||||
* instead of processing the whole frame.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration)
|
||||
* \brief Construct a SwStatsCpu object
|
||||
* \param[in] configuration Global configuration reference
|
||||
*
|
||||
* Creates a SwStatsCpu object and initialises shared memory for statistics
|
||||
* exchange.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn bool SwStatsCpu::isValid() const
|
||||
* \brief Gets whether the statistics object is valid
|
||||
@@ -144,8 +154,8 @@ namespace libcamera {
|
||||
|
||||
LOG_DEFINE_CATEGORY(SwStatsCpu)
|
||||
|
||||
SwStatsCpu::SwStatsCpu()
|
||||
: sharedStats_("softIsp_stats")
|
||||
SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration)
|
||||
: sharedStats_("softIsp_stats"), bench_(configuration)
|
||||
{
|
||||
if (!sharedStats_)
|
||||
LOG(SwStatsCpu, Error)
|
||||
@@ -386,11 +396,14 @@ int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order)
|
||||
*/
|
||||
int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
|
||||
{
|
||||
stride_ = inputCfg.stride;
|
||||
|
||||
BayerFormat bayerFormat =
|
||||
BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
|
||||
|
||||
if (bayerFormat.packing == BayerFormat::Packing::None &&
|
||||
setupStandardBayerOrder(bayerFormat.order) == 0) {
|
||||
processFrame_ = &SwStatsCpu::processBayerFrame2;
|
||||
switch (bayerFormat.bitDepth) {
|
||||
case 8:
|
||||
stats0_ = &SwStatsCpu::statsBGGR8Line0;
|
||||
@@ -411,6 +424,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
|
||||
/* Skip every 3th and 4th line, sample every other 2x2 block */
|
||||
ySkipMask_ = 0x02;
|
||||
xShift_ = 0;
|
||||
processFrame_ = &SwStatsCpu::processBayerFrame2;
|
||||
|
||||
switch (bayerFormat.order) {
|
||||
case BayerFormat::BGGR:
|
||||
@@ -475,4 +489,55 @@ void SwStatsCpu::setWindow(const Rectangle &window)
|
||||
window_.height &= ~(patternSize_.height - 1);
|
||||
}
|
||||
|
||||
void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in)
|
||||
{
|
||||
const uint8_t *src = in.planes()[0].data();
|
||||
const uint8_t *linePointers[3];
|
||||
|
||||
/* Adjust src for starting at window_.y */
|
||||
src += window_.y * stride_;
|
||||
|
||||
for (unsigned int y = 0; y < window_.height; y += 2) {
|
||||
if (y & ySkipMask_) {
|
||||
src += stride_ * 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* linePointers[0] is not used by any stats0_ functions */
|
||||
linePointers[1] = src;
|
||||
linePointers[2] = src + stride_;
|
||||
(this->*stats0_)(linePointers);
|
||||
src += stride_ * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate statistics for a frame in one go
|
||||
* \param[in] frame The frame number
|
||||
* \param[in] bufferId ID of the statistics buffer
|
||||
* \param[in] input The frame to process
|
||||
*
|
||||
* This may only be called after a successful setWindow() call.
|
||||
*/
|
||||
void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input)
|
||||
{
|
||||
if (frame % kStatPerNumFrames) {
|
||||
finishFrame(frame, bufferId);
|
||||
return;
|
||||
}
|
||||
|
||||
bench_.startFrame();
|
||||
startFrame(frame);
|
||||
|
||||
MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);
|
||||
if (!in.isValid()) {
|
||||
LOG(SwStatsCpu, Error) << "mmap-ing buffer(s) failed";
|
||||
return;
|
||||
}
|
||||
|
||||
(this->*processFrame_)(in);
|
||||
finishFrame(frame, bufferId);
|
||||
bench_.finishFrame();
|
||||
}
|
||||
|
||||
} /* namespace libcamera */
|
||||
|
||||
Reference in New Issue
Block a user