From e3638943a8bd3f93b8d81c3996035c60755b97f6 Mon Sep 17 00:00:00 2001 From: Marttico Date: Wed, 20 Dec 2023 20:28:12 +0100 Subject: [PATCH 22/25] libcamera: debayer_cpu: Add support for 10bpp IGIG_GBGR_IGIG_GRGB input Add support to DebayerCpu for 10bpp IGIG_GBGR_IGIG_GRGB input generated by the Omnivision ov01a1s sensor. Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Toon Langendam Signed-off-by: Toon Langendam Signed-off-by: Marttico Signed-off-by: Hans de Goede --- .../internal/software_isp/debayer_cpu.h | 5 + src/libcamera/software_isp/debayer_cpu.cpp | 251 ++++++++++++++++++ 2 files changed, 256 insertions(+) diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h index bdeab7c0..52af117f 100644 --- a/include/libcamera/internal/software_isp/debayer_cpu.h +++ b/include/libcamera/internal/software_isp/debayer_cpu.h @@ -96,6 +96,11 @@ private: void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]); void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); + /* IGIG_GBGR_IGIG_GRGB unpacked 10-bit raw bayer format */ + void debayerIGIG10Line0(uint8_t *dst, const uint8_t *src[]); + void debayerGBGR10Line1(uint8_t *dst, const uint8_t *src[]); + void debayerIGIG10Line2(uint8_t *dst, const uint8_t *src[]); + void debayerGRGB10Line3(uint8_t *dst, const uint8_t *src[]); typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src[]); diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 0edea4d3..41c8805f 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -228,6 +228,238 @@ void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) } } +void DebayerCpu::debayerIGIG10Line0(uint8_t *dst, const uint8_t *src[]) +{ + const uint16_t *prev = (const uint16_t *)src[1]; + const uint16_t *curr = (const uint16_t *)src[2]; + const uint16_t *next = (const uint16_t *)src[3]; + + for (int x = 0; x < (int)window_.width;) { + /* + * IGIG line pixel 0: IGIGI + * GBGRG + * IGIGI + * GRGBG + * IGIGI + */ + *dst++ = blue_[(prev[x - 1] + next[x + 1]) / 8]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[(prev[x + 1] + next[x - 1]) / 8]; + x++; + + /* + * IGIG line pixel 1: GIGIG + * BGRGB + * GIGIG + * RGBGR + * GIGIG + */ + *dst++ = blue_[next[x] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[prev[x] / 4]; + x++; + + /* + * IGIG line pixel 2: IGIGI + * GRGBG + * IGIGI + * GBGRG + * IGIGI + */ + *dst++ = blue_[(prev[x + 1] + next[x - 1]) / 8]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[(prev[x - 1] + next[x + 1]) / 8]; + x++; + + /* + * IGIG line pixel 3: GIGIG + * RGBGR + * GIGIG + * BGRGB + * GIGIG + */ + *dst++ = blue_[prev[x] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[next[x] / 4]; + x++; + } +} + +void DebayerCpu::debayerGBGR10Line1(uint8_t *dst, const uint8_t *src[]) +{ + const uint16_t *prev2 = (const uint16_t *)src[0]; + const uint16_t *prev = (const uint16_t *)src[1]; + const uint16_t *curr = (const uint16_t *)src[2]; + const uint16_t *next = (const uint16_t *)src[3]; + const uint16_t *next2 = (const uint16_t *)src[4]; + + for (int x = 0; x < (int)window_.width;) { + /* + * GBGR line pixel 0: GBGRG + * IGIGI + * GRGBG + * IGIGI + * GBGRG + */ + *dst++ = blue_[curr[x + 1] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[curr[x - 1] / 4]; + x++; + + /* + * GBGR line pixel 1: BGRGB + * GIGIG + * RGBGR + * GIGIG + * BGRGB + */ + *dst++ = blue_[curr[x] / 4]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[(curr[x - 2] + curr[x + 2] + prev2[x] + next2[x]) / 16]; + x++; + + /* + * GBGR line pixel 2: GRGBG + * IGIGI + * GBGRG + * IGIGI + * GRGBG + */ + *dst++ = blue_[curr[x - 1] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[curr[x + 1] / 4]; + x++; + + /* + * GBGR line pixel 3: RGBGR + * GIGIG + * BGRGB + * GIGIG + * RGBGR + */ + *dst++ = blue_[(curr[x - 2] + curr[x + 2] + prev2[x] + next2[x]) / 16]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[curr[x] / 4]; + x++; + } +} + +void DebayerCpu::debayerIGIG10Line2(uint8_t *dst, const uint8_t *src[]) +{ + const uint16_t *prev = (const uint16_t *)src[1]; + const uint16_t *curr = (const uint16_t *)src[2]; + const uint16_t *next = (const uint16_t *)src[3]; + + for (int x = 0; x < (int)window_.width;) { + /* + * IGIG line pixel 0: IGIGI + * GRGBG + * IGIGI + * GBGRG + * IGIGI + */ + *dst++ = blue_[(prev[x + 1] + next[x - 1]) / 8]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[(prev[x - 1] + next[x + 1]) / 8]; + x++; + + /* + * IGIG line pixel 1: GIGIG + * RGBGR + * GIGIG + * BGRGB + * GIGIG + */ + *dst++ = blue_[prev[x] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[next[x] / 4]; + x++; + + /* + * IGIG line pixel 2: IGIGI + * GBGRG + * IGIGI + * GRGBG + * IGIGI + */ + *dst++ = blue_[(prev[x - 1] + next[x + 1]) / 8]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[(prev[x + 1] + next[x - 1]) / 8]; + x++; + + /* + * IGIG line pixel 3: GIGIG + * BGRGB + * GIGIG + * RGBGR + * GIGIG + */ + *dst++ = blue_[next[x] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[prev[x] / 4]; + x++; + } +} + +void DebayerCpu::debayerGRGB10Line3(uint8_t *dst, const uint8_t *src[]) +{ + const uint16_t *prev2 = (const uint16_t *)src[0]; + const uint16_t *prev = (const uint16_t *)src[1]; + const uint16_t *curr = (const uint16_t *)src[2]; + const uint16_t *next = (const uint16_t *)src[3]; + const uint16_t *next2 = (const uint16_t *)src[4]; + + for (int x = 0; x < (int)window_.width;) { + /* + * GRGB line pixel 0: GRGBG + * IGIGI + * GBGRG + * IGIGI + * GRGBG + */ + *dst++ = blue_[curr[x - 1] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[curr[x + 1] / 4]; + x++; + + /* + * GRGB line pixel 1: RGBGR + * GIGIG + * BGRGB + * GIGIG + * RGBGR + */ + *dst++ = blue_[(curr[x - 2] + curr[x + 2] + prev2[x] + next2[x]) / 16]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[curr[x] / 4]; + x++; + + /* + * GRGB line pixel 2: GBGRG + * IGIGI + * GRGBG + * IGIGI + * GBGRG + */ + *dst++ = blue_[curr[x + 1] / 4]; + *dst++ = green_[curr[x] / 4]; + *dst++ = red_[curr[x - 1] / 4]; + x++; + + /* + * GRGB line pixel 3: BGRGB + * GIGIG + * RGBGR + * GIGIG + * BGRGB + */ + *dst++ = blue_[curr[x] / 4]; + *dst++ = green_[(curr[x - 1] + curr[x + 1] + prev[x] + next[x]) / 16]; + *dst++ = red_[(curr[x - 2] + curr[x + 2] + prev2[x] + next2[x]) / 16]; + x++; + } +} + static bool isStandardBayerOrder(BayerFormat::Order order) { return order == BayerFormat::BGGR || order == BayerFormat::GBRG || @@ -259,6 +491,15 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf return 0; } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::None && + bayerFormat.order == BayerFormat::IGIG_GBGR_IGIG_GRGB) { + config.bpp = 16; + config.patternSize.height = 4; + config.patternSize.width = 4; + config.outputFormats = std::vector({ formats::RGB888 }); + return 0; + } + LOG(Debayer, Info) << "Unsupported input format " << inputFormat.toString(); return -EINVAL; @@ -384,6 +625,16 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF } } + if (bayerFormat.bitDepth == 10 && + bayerFormat.packing == BayerFormat::Packing::None && + bayerFormat.order == BayerFormat::IGIG_GBGR_IGIG_GRGB) { + debayer0_ = &DebayerCpu::debayerIGIG10Line0; + debayer1_ = &DebayerCpu::debayerGBGR10Line1; + debayer2_ = &DebayerCpu::debayerIGIG10Line2; + debayer3_ = &DebayerCpu::debayerGRGB10Line3; + return 0; + } + invalid_fmt: LOG(Debayer, Error) << "Unsupported input output format combination"; return -EINVAL; -- 2.43.0