[RFC 4/4] libcamera: swstats_cpu: Add processFrame() method
Hans de Goede
hdegoede at redhat.com
Thu Oct 10 14:21:39 CEST 2024
Hi,
On 10-Oct-24 1:15 AM, Kieran Bingham wrote:
> Quoting Hans de Goede (2024-10-09 21:01:10)
>> 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.
>
> I can't see how this is used yet. Is it just something that you would be
> able to directly set up and call on a frame explicitly if desired?
Yes that is the idea. It could be e.g. used to do a raw-bayer pipeline
while still having 3A in place.
> I expect that's possible as it's RFC ... So I think I'll leave this one
> to other soft-isp devs... But I can understand that it could be useful
> for future development.
Regards,
Hans
>> ---
>> 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 */
>> --
>> 2.46.2
>>
>
More information about the libcamera-devel
mailing list