[RFC 4/4] libcamera: swstats_cpu: Add processFrame() method
Milan Zamazal
mzamazal at redhat.com
Wed Oct 16 17:10:46 CEST 2024
Hans de Goede <hdegoede at redhat.com> writes:
> 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.
Makes sense. Although the actual use may be trickier, let's see.
Reviewed-by: Milan Zamazal <mzamazal at redhat.com>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
>
> ---
> src/libcamera/software_isp/swstats_cpu.cpp | 72 ++++++++++++++++++++++
> src/libcamera/software_isp/swstats_cpu.h | 10 +++
> 2 files changed, 82 insertions(+)
>
> diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
> index 5e4246a9..117147c2 100644
> --- a/src/libcamera/software_isp/swstats_cpu.cpp
> +++ b/src/libcamera/software_isp/swstats_cpu.cpp
> @@ -16,6 +16,7 @@
> #include <libcamera/stream.h>
>
> #include "libcamera/internal/bayer_format.h"
> +#include "libcamera/internal/mapped_framebuffer.h"
>
> namespace libcamera {
>
> @@ -363,8 +364,11 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
> BayerFormat bayerFormat =
> BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
>
> + stride_ = inputCfg.stride;
> +
> if (bayerFormat.packing == BayerFormat::Packing::None &&
> setupStandardBayerOrder(bayerFormat.order) == 0) {
> + bpp_ = (bayerFormat.bitDepth + 7) & ~7;
> switch (bayerFormat.bitDepth) {
> case 8:
> stats0_ = &SwStatsCpu::statsBGGR8Line0;
> @@ -385,6 +389,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
> /* Skip every 3th and 4th line, sample every other 2x2 block */
> ySkipMask_ = 0x02;
> xShift_ = 0;
> + bpp_ = 10;
>
> switch (bayerFormat.order) {
> case BayerFormat::BGGR:
> @@ -425,4 +430,71 @@ void SwStatsCpu::setWindow(const Rectangle &window)
> window_.height &= ~(patternSize_.height - 1);
> }
>
> +void SwStatsCpu::processFrame2(const uint8_t *src)
> +{
> + unsigned int yEnd = window_.y + window_.height;
> + const uint8_t *linePointers[3];
> +
> + /* Adjust src to top left corner of the window */
> + src += window_.y * stride_ + window_.x * bpp_ / 8;
> +
> + for (unsigned int y = window_.y; y < yEnd; 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;
> + }
> +}
> +
> +void SwStatsCpu::processFrame4(const uint8_t *src)
> +{
> + const unsigned int yEnd = window_.y + window_.height;
> + const uint8_t *linePointers[4];
> +
> + /* Adjust src to top left corner of the window */
> + src += window_.y * stride_ + window_.x * bpp_ / 8;
> +
> + for (unsigned int y = window_.y; y < yEnd; y += 4) {
> + if (y & ySkipMask_) {
> + src += stride_ * 4;
> + continue;
> + }
> +
> + /* linePointers[0] and [1] are not used by 4 line pattern stats0_ functions */
> + linePointers[2] = src;
> + linePointers[3] = src + stride_;
> + (this->*stats0_)(linePointers);
> + src += stride_ * 2;
> +
> + linePointers[2] = src;
> + linePointers[3] = src + stride_;
> + (this->*stats2_)(linePointers);
> + src += stride_ * 2;
> + }
> +}
> +
> +void SwStatsCpu::processFrame(FrameBuffer *input)
> +{
> + bench_.startFrame();
> +
> + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);
> + if (!in.isValid()) {
> + LOG(SwStatsCpu, Error) << "mmap-ing buffer(s) failed";
> + return;
> + }
> +
> + if (patternSize_.height == 2)
> + processFrame2(in.planes()[0].data());
> + else
> + processFrame4(in.planes()[0].data());
> +
> + bench_.finishFrame();
> +}
> +
> } /* namespace libcamera */
> diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h
> index 26a2f462..bb178a04 100644
> --- a/src/libcamera/software_isp/swstats_cpu.h
> +++ b/src/libcamera/software_isp/swstats_cpu.h
> @@ -18,9 +18,12 @@
> #include <libcamera/geometry.h>
>
> #include "libcamera/internal/bayer_format.h"
> +#include "libcamera/internal/framebuffer.h"
> #include "libcamera/internal/shared_mem_object.h"
> #include "libcamera/internal/software_isp/swisp_stats.h"
>
> +#include "benchmark.h"
> +
> namespace libcamera {
>
> class PixelFormat;
> @@ -42,6 +45,7 @@ public:
> void setWindow(const Rectangle &window);
> void startFrame();
> void finishFrame(uint32_t frame, uint32_t bufferId);
> + void processFrame(FrameBuffer *input);
>
> void processLine0(unsigned int y, const uint8_t *src[])
> {
> @@ -77,6 +81,9 @@ private:
> void statsBGGR10PLine0(const uint8_t *src[]);
> void statsGBRG10PLine0(const uint8_t *src[]);
>
> + void processFrame2(const uint8_t *src);
> + void processFrame4(const uint8_t *src);
> +
> /* Variables set by configure(), used every line */
> statsProcessFn stats0_;
> statsProcessFn stats2_;
> @@ -89,9 +96,12 @@ private:
> Size patternSize_;
>
> unsigned int xShift_;
> + unsigned int bpp_; /* Memory used per pixel, not precision */
> + unsigned int stride_;
>
> SharedMemObject<SwIspStats> sharedStats_;
> SwIspStats stats_;
> + Benchmark bench_;
> };
>
> } /* namespace libcamera */
More information about the libcamera-devel
mailing list