[PATCH v3 13/16] libcamera: swstats_cpu: Add support for 8, 10 and 12 bpp unpacked bayer input
Milan Zamazal
mzamazal at redhat.com
Fri Feb 16 11:11:46 CET 2024
Hans de Goede <hdegoede at redhat.com> writes:
> Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard
> bayer orders.
>
> Tested-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org> # sc8280xp Lenovo x13s
> Tested-by: Pavel Machek <pavel at ucw.cz>
> Reviewed-by: Pavel Machek <pavel at ucw.cz>
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
> src/libcamera/software_isp/swstats_cpu.cpp | 128 +++++++++++++++++++++
> src/libcamera/software_isp/swstats_cpu.h | 9 ++
> 2 files changed, 137 insertions(+)
>
> diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
> index a3a2eb94..c7e85f2e 100644
> --- a/src/libcamera/software_isp/swstats_cpu.cpp
> +++ b/src/libcamera/software_isp/swstats_cpu.cpp
> @@ -71,6 +71,83 @@ static const unsigned int kBlueYMul = 29; /* 0.114 * 256 */
> stats_.sumG_ += sumG; \
> stats_.sumB_ += sumB;
>
> +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[])
> +{
> + const uint8_t *src0 = src[1] + window_.x;
> + const uint8_t *src1 = src[2] + window_.x;
> +
> + SWSTATS_START_LINE_STATS(uint8_t)
> +
> + if (swapLines_)
> + std::swap(src0, src1);
> +
> + /* x += 4 sample every other 2x2 block */
> + for (int x = 0; x < (int)window_.width; x += 4) {
Why not `unsigned int x = 0'? (The same at the other similar places.)
> + b = src0[x];
> + g = src0[x + 1];
> + g2 = src1[x];
> + r = src1[x + 1];
> +
> + g = (g + g2) / 2;
> +
> + SWSTATS_ACCUMULATE_LINE_STATS(1)
> + }
> +
> + SWSTATS_FINISH_LINE_STATS()
> +}
> +
> +void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[])
> +{
> + const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
> + const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
> +
> + SWSTATS_START_LINE_STATS(uint16_t)
> +
> + if (swapLines_)
> + std::swap(src0, src1);
> +
> + /* x += 4 sample every other 2x2 block */
> + for (int x = 0; x < (int)window_.width; x += 4) {
> + b = src0[x];
> + g = src0[x + 1];
> + g2 = src1[x];
> + r = src1[x + 1];
> +
> + g = (g + g2) / 2;
> +
> + /* divide Y by 4 for 10 -> 8 bpp value */
> + SWSTATS_ACCUMULATE_LINE_STATS(4)
> + }
> +
> + SWSTATS_FINISH_LINE_STATS()
> +}
> +
> +void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[])
> +{
> + const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
> + const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
> +
> + SWSTATS_START_LINE_STATS(uint16_t)
> +
> + if (swapLines_)
> + std::swap(src0, src1);
> +
> + /* x += 4 sample every other 2x2 block */
> + for (int x = 0; x < (int)window_.width; x += 4) {
> + b = src0[x];
> + g = src0[x + 1];
> + g2 = src1[x];
> + r = src1[x + 1];
> +
> + g = (g + g2) / 2;
> +
> + /* divide Y by 16 for 12 -> 8 bpp value */
> + SWSTATS_ACCUMULATE_LINE_STATS(16)
> + }
> +
> + SWSTATS_FINISH_LINE_STATS()
> +}
> +
> void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[])
> {
> const uint8_t *src0 = src[1] + window_.x * 5 / 4;
> @@ -147,6 +224,42 @@ void SwStatsCpu::finishFrame(void)
> statsReady.emit(0);
> }
>
> +/**
> + * \brief Setup SwStatsCpu object for standard Bayer orders
> + * \param[in] order The Bayer order
> + *
> + * Check if order is a standard Bayer order and setup xShift_ and swapLines_
> + * so that a single BGGR stats function can be used for all 4 standard orders.
> + */
> +int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order)
> +{
> + switch (order) {
> + case BayerFormat::BGGR:
> + xShift_ = 0;
> + swapLines_ = false;
> + break;
> + case BayerFormat::GBRG:
> + xShift_ = 1; /* BGGR -> GBRG */
> + swapLines_ = false;
> + break;
> + case BayerFormat::GRBG:
> + xShift_ = 0;
> + swapLines_ = true; /* BGGR -> GRBG */
> + break;
> + case BayerFormat::RGGB:
> + xShift_ = 1; /* BGGR -> GBRG */
> + swapLines_ = true; /* GBRG -> RGGB */
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + patternSize_.height = 2;
> + patternSize_.width = 2;
> + ySkipMask_ = 0x02; /* Skip every 3th and 4th line */
> + return 0;
> +}
> +
> /**
> * \brief Configure the statistics object for the passed in input format.
> * \param[in] inputCfg The input format
> @@ -158,6 +271,21 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
> BayerFormat bayerFormat =
> BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
>
> + if (bayerFormat.packing == BayerFormat::Packing::None &&
> + setupStandardBayerOrder(bayerFormat.order) == 0) {
> + switch (bayerFormat.bitDepth) {
> + case 8:
> + stats0_ = (SwStatsCpu::statsProcessFn)&SwStatsCpu::statsBGGR8Line0;
> + return 0;
> + case 10:
> + stats0_ = (SwStatsCpu::statsProcessFn)&SwStatsCpu::statsBGGR10Line0;
> + return 0;
> + case 12:
> + stats0_ = (SwStatsCpu::statsProcessFn)&SwStatsCpu::statsBGGR12Line0;
> + return 0;
> + }
> + }
> +
> if (bayerFormat.bitDepth == 10 &&
> bayerFormat.packing == BayerFormat::Packing::CSI2) {
> patternSize_.height = 2;
> diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h
> index 166ebe28..fbc7919b 100644
> --- a/src/libcamera/software_isp/swstats_cpu.h
> +++ b/src/libcamera/software_isp/swstats_cpu.h
> @@ -17,6 +17,7 @@
>
> #include <libcamera/geometry.h>
>
> +#include "libcamera/internal/bayer_format.h"
> #include "libcamera/internal/shared_mem_object.h"
> #include "libcamera/internal/software_isp/swisp_stats.h"
>
> @@ -119,6 +120,14 @@ private:
> */
> typedef void (SwStatsCpu::*statsProcessFn)(const uint8_t *src[]);
>
> + int setupStandardBayerOrder(BayerFormat::Order order);
> + /* Bayer 8 bpp unpacked */
> + void statsBGGR8Line0(const uint8_t *src[]);
> + /* Bayer 10 bpp unpacked */
> + void statsBGGR10Line0(const uint8_t *src[]);
> + /* Bayer 12 bpp unpacked */
> + void statsBGGR12Line0(const uint8_t *src[]);
> + /* Bayer 10 bpp packed */
> void statsBGGR10PLine0(const uint8_t *src[]);
> void statsGBRG10PLine0(const uint8_t *src[]);
More information about the libcamera-devel
mailing list