Message ID | 20241009200110.275544-5-hdegoede@redhat.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
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? 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. -- Kieran > > Signed-off-by: Hans de Goede <hdegoede@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 */ > -- > 2.46.2 >
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 >> >
Hans de Goede <hdegoede@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@redhat.com> > Signed-off-by: Hans de Goede <hdegoede@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 */
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 */
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. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- src/libcamera/software_isp/swstats_cpu.cpp | 72 ++++++++++++++++++++++ src/libcamera/software_isp/swstats_cpu.h | 10 +++ 2 files changed, 82 insertions(+)