Message ID | 20240229183654.7206-15-hdegoede@redhat.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hans de Goede <hdegoede@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@linaro.org> # sc8280xp Lenovo x13s > Tested-by: Pavel Machek <pavel@ucw.cz> > Reviewed-by: Pavel Machek <pavel@ucw.cz> > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Milan Zamazal <mzamazal@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_;
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_;