[PATCH v4 14/18] libcamera: debayer_cpu: Add support for 8, 10 and 12 bpp unpacked bayer input
Milan Zamazal
mzamazal at redhat.com
Mon Mar 4 18:42:56 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>
Reviewed-by: Milan Zamazal <mzamazal at redhat.com>
(My e-mail client displays smileys in this patch so it must be right.)
> ---
> Changes in v3:
> - Also add support for 12bpp (by Kieran Bingham)
> ---
> src/libcamera/software_isp/debayer_cpu.cpp | 128 +++++++++++++++++++++
> src/libcamera/software_isp/debayer_cpu.h | 13 +++
> 2 files changed, 141 insertions(+)
>
> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
> index 53e90776..22ae99cd 100644
> --- a/src/libcamera/software_isp/debayer_cpu.cpp
> +++ b/src/libcamera/software_isp/debayer_cpu.cpp
> @@ -56,6 +56,11 @@ DebayerCpu::~DebayerCpu()
> free(lineBuffers_[i]);
> }
>
> +#define DECLARE_SRC_POINTERS(pixel_t) \
> + const pixel_t *prev = (const pixel_t *)src[0] + xShift_; \
> + const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \
> + const pixel_t *next = (const pixel_t *)src[2] + xShift_;
> +
> // RGR
> // GBG
> // RGR
> @@ -92,6 +97,70 @@ DebayerCpu::~DebayerCpu()
> *dst++ = red_[curr[x] / (div)]; \
> x++;
>
> +void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
> +{
> + DECLARE_SRC_POINTERS(uint8_t)
> +
> + for (int x = 0; x < (int)window_.width;) {
> + BGGR_BGR888(1, 1, 1)
> + GBRG_BGR888(1, 1, 1)
> + }
> +}
> +
> +void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
> +{
> + DECLARE_SRC_POINTERS(uint8_t)
> +
> + for (int x = 0; x < (int)window_.width;) {
> + GRBG_BGR888(1, 1, 1)
> + RGGB_BGR888(1, 1, 1)
> + }
> +}
> +
> +void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
> +{
> + DECLARE_SRC_POINTERS(uint16_t)
> +
> + for (int x = 0; x < (int)window_.width;) {
> + /* divide values by 4 for 10 -> 8 bpp value */
> + BGGR_BGR888(1, 1, 4)
> + GBRG_BGR888(1, 1, 4)
> + }
> +}
> +
> +void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
> +{
> + DECLARE_SRC_POINTERS(uint16_t)
> +
> + for (int x = 0; x < (int)window_.width;) {
> + /* divide values by 4 for 10 -> 8 bpp value */
> + GRBG_BGR888(1, 1, 4)
> + RGGB_BGR888(1, 1, 4)
> + }
> +}
> +
> +void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
> +{
> + DECLARE_SRC_POINTERS(uint16_t)
> +
> + for (int x = 0; x < (int)window_.width;) {
> + /* divide values by 16 for 12 -> 8 bpp value */
> + BGGR_BGR888(1, 1, 16)
> + GBRG_BGR888(1, 1, 16)
> + }
> +}
> +
> +void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
> +{
> + DECLARE_SRC_POINTERS(uint16_t)
> +
> + for (int x = 0; x < (int)window_.width;) {
> + /* divide values by 16 for 12 -> 8 bpp value */
> + GRBG_BGR888(1, 1, 16)
> + RGGB_BGR888(1, 1, 16)
> + }
> +}
> +
> void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
> {
> const int width_in_bytes = window_.width * 5 / 4;
> @@ -186,6 +255,16 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
> BayerFormat bayerFormat =
> BayerFormat::fromPixelFormat(inputFormat);
>
> + if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
> + bayerFormat.packing == BayerFormat::Packing::None &&
> + isStandardBayerOrder(bayerFormat.order)) {
> + config.bpp = (bayerFormat.bitDepth + 7) & ~7;
> + config.patternSize.width = 2;
> + config.patternSize.height = 2;
> + config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
> + return 0;
> + }
> +
> if (bayerFormat.bitDepth == 10 &&
> bayerFormat.packing == BayerFormat::Packing::CSI2 &&
> isStandardBayerOrder(bayerFormat.order)) {
> @@ -213,12 +292,61 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c
> return -EINVAL;
> }
>
> +/*
> + * Check for standard Bayer orders and set xShift_ and swap debayer0/1, so that
> + * a single pair of BGGR debayer functions can be used for all 4 standard orders.
> + */
> +int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)
> +{
> + switch (order) {
> + case BayerFormat::BGGR:
> + break;
> + case BayerFormat::GBRG:
> + xShift_ = 1; /* BGGR -> GBRG */
> + break;
> + case BayerFormat::GRBG:
> + std::swap(debayer0_, debayer1_); /* BGGR -> GRBG */
> + break;
> + case BayerFormat::RGGB:
> + xShift_ = 1; /* BGGR -> GBRG */
> + std::swap(debayer0_, debayer1_); /* GBRG -> RGGB */
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> /* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */
> int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
> {
> BayerFormat bayerFormat =
> BayerFormat::fromPixelFormat(inputFormat);
>
> + xShift_ = 0;
> +
> + if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
> + bayerFormat.packing == BayerFormat::Packing::None &&
> + isStandardBayerOrder(bayerFormat.order)) {
> + switch (bayerFormat.bitDepth) {
> + case 8:
> + debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888;
> + debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888;
> + break;
> + case 10:
> + debayer0_ = &DebayerCpu::debayer10_BGBG_BGR888;
> + debayer1_ = &DebayerCpu::debayer10_GRGR_BGR888;
> + break;
> + case 12:
> + debayer0_ = &DebayerCpu::debayer12_BGBG_BGR888;
> + debayer1_ = &DebayerCpu::debayer12_GRGR_BGR888;
> + break;
> + }
> + setupStandardBayerOrder(bayerFormat.order);
> + return 0;
> + }
> +
> if (bayerFormat.bitDepth == 10 &&
> bayerFormat.packing == BayerFormat::Packing::CSI2) {
> switch (bayerFormat.order) {
> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
> index 98782838..73ca41f1 100644
> --- a/src/libcamera/software_isp/debayer_cpu.h
> +++ b/src/libcamera/software_isp/debayer_cpu.h
> @@ -17,6 +17,8 @@
>
> #include <libcamera/base/object.h>
>
> +#include "libcamera/internal/bayer_format.h"
> +
> #include "debayer.h"
> #include "swstats_cpu.h"
>
> @@ -82,6 +84,15 @@ private:
> */
> using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);
>
> + /* 8-bit raw bayer format */
> + void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
> + void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
> + /* unpacked 10-bit raw bayer format */
> + void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
> + void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
> + /* unpacked 12-bit raw bayer format */
> + void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
> + void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
> /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */
> void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
> void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
> @@ -103,6 +114,7 @@ private:
>
> int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
> int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
> + int setupStandardBayerOrder(BayerFormat::Order order);
> int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
> void setupInputMemcpy(const uint8_t *linePointers[]);
> void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
> @@ -131,6 +143,7 @@ private:
> unsigned int lineBufferLength_;
> unsigned int lineBufferPadding_;
> unsigned int lineBufferIndex_;
> + unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
> bool enableInputMemcpy_;
> float gamma_correction_;
> unsigned int measuredFrames_;
More information about the libcamera-devel
mailing list