Message ID | ZXt1mDW1SpMyLrbT@duo.ucw.cz |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
Hi Pavel, On 12/14/23 22:37, Pavel Machek wrote: > --- > > Did I get it mostly right? I can't test other formats but providing > them should not be too hard. Does it make sense to add this to your > series or is it better to just wait for v1 to be merged? Yes this looks about right. Yesterday I finished about a 10 day libcamera sprint so for now I'm not going to touch libcamera for a few days. I plan to get back to libcamera again on Wednesday. I'll add a commit adding 8bpp bayer, all 4 orders, to my personal libcamera softisp branch then and when that is in place I'll send you an email asking to test it. Regards, Hans > > > diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h > index 7fb5be77..f3bb4321 100644 > --- a/include/libcamera/internal/software_isp/debayer_cpu.h > +++ b/include/libcamera/internal/software_isp/debayer_cpu.h > @@ -67,6 +67,9 @@ private: > void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src); > void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src); > > + void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src); > + void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src); > + > typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src); > > struct DebayerInputConfig { > diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h > index 0ceb995f..3c43e146 100644 > --- a/include/libcamera/internal/software_isp/swstats_cpu.h > +++ b/include/libcamera/internal/software_isp/swstats_cpu.h > @@ -29,6 +29,8 @@ public: > /* FIXME this should be dropped once AWB has moved to the IPA */ > SwIspStats getStats() { return *sharedStats_; } > private: > + void statsBGGR8Line0(const uint8_t *src, unsigned int stride); > + > void statsBGGR10PLine0(const uint8_t *src, unsigned int stride); > void statsGBRG10PLine0(const uint8_t *src, unsigned int stride); > void statsGRBG10PLine0(const uint8_t *src, unsigned int stride); > diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp > index 3eacdd5d..52910a03 100644 > --- a/src/libcamera/software_isp/debayer_cpu.cpp > +++ b/src/libcamera/software_isp/debayer_cpu.cpp > @@ -111,6 +111,36 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src) > } > } > > +void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src) > +{ > + const int width_in_bytes = window_.width; > + struct ctxt_8bit_src c = { > + src - inputConfig_.stride, src, src + inputConfig_.stride, > + red_, green_, blue_ }; > + > + for (int x = 0; x < width_in_bytes; ) { > + /* Even pixel */ > + bggr8_bgr888(c, dst, x++, 1, 1); > + /* Odd pixel BGGR -> GBRG */ > + gbrg8_bgr888(c, dst, x++, 1, 1); > + } > +} > + > +void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src) > +{ > + const int width_in_bytes = window_.width; > + struct ctxt_8bit_src c = { > + src - inputConfig_.stride, src, src + inputConfig_.stride, > + red_, green_, blue_ }; > + > + for (int x = 0; x < width_in_bytes; ) { > + /* Even pixel */ > + grbg8_bgr888(c, dst, x++, 1, 1); > + /* Odd pixel GRBG -> RGGB */ > + rggb8_bgr888(c, dst, x++, 1, 1); > + } > +} > + > void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src) > { > const int width_in_bytes = window_.width * 5 / 4; > @@ -152,6 +182,22 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf > BayerFormat bayerFormat = > BayerFormat::fromPixelFormat(inputFormat); > > + if (bayerFormat.bitDepth == 8) { > + config.bpp = 8; > + config.patternSize.height = 2; > + config.patternSize.width = 4; > + config.x_shift = 0; > + config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 }); > + > + switch (bayerFormat.order) { > + case BayerFormat::BGGR: > + return 0; > + default: > + break; > + } > + /* } else if (future supported fmts) { ... */ > + } > + > if (bayerFormat.bitDepth == 10 && > bayerFormat.packing == BayerFormat::Packing::CSI2) { > config.bpp = 10; > @@ -195,6 +241,17 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi > BayerFormat bayerFormat = > BayerFormat::fromPixelFormat(inputFormat); > > + if (bayerFormat.bitDepth == 8) { > + switch (bayerFormat.order) { > + case BayerFormat::BGGR: > + debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888; > + debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888; > + return 0; > + default: > + break; > + } > + } > + > if (bayerFormat.bitDepth == 10 && > bayerFormat.packing == BayerFormat::Packing::CSI2) { > switch (bayerFormat.order) { > diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp > index 15f23953..e65b1b65 100644 > --- a/src/libcamera/software_isp/swstats_cpu.cpp > +++ b/src/libcamera/software_isp/swstats_cpu.cpp > @@ -37,9 +37,9 @@ static const unsigned int GREEN_Y_MUL = 150; /* 0.59 * 256 */ > static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */ > > static inline __attribute__((always_inline)) void > -statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_) > +statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_, bool is10p) > { > - const int width_in_bytes = width * 5 / 4; > + const int width_in_bytes = width * (4 + is10p) / 4; > uint8_t r, g, b, g2; > unsigned int y_val; > unsigned int sumR = 0; > @@ -49,7 +49,7 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg > unsigned int bright_sum = 0; > unsigned int too_bright_sum = 0; > > - for (int x = 0; x < width_in_bytes; x += 5) { > + for (int x = 0; x < width_in_bytes; x += (4 + is10p)) { > if (bggr) { > /* BGGR */ > b = src0[x]; > @@ -84,26 +84,31 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg > too_bright_sum_ += too_bright_sum; > } > > +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src, unsigned int stride) > +{ > + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, false); > +} > + > void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src, unsigned int stride) > { > - statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_); > + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, true); > } > > void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src, unsigned int stride) > { > - statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_); > + statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_, true); > } > > void SwStatsCpu::statsGRBG10PLine0(const uint8_t *src, unsigned int stride) > { > /* GRBG is BGGR with the lines swapped */ > - statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_); > + statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_, true); > } > > void SwStatsCpu::statsRGGB10PLine0(const uint8_t *src, unsigned int stride) > { > /* RGGB is GBRG with the lines swapped */ > - statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_); > + statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_, true); > } > > void SwStatsCpu::resetStats(void) > @@ -134,6 +139,24 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) > startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats; > finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats; > > + if (bayerFormat.bitDepth == 8) { > + bpp_ = 8; > + patternSize_.height = 2; > + patternSize_.width = 4; > + y_skip_mask_ = 0x0c; /* Skip every 3th and 4th line */ > + x_shift_ = 0; > + > + switch (bayerFormat.order) { > + case BayerFormat::BGGR: > + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR8Line0; > + return 0; > + default: > + break; > + } > + /* } else if (future supported fmts) { ... */ > + } > + > + > if (bayerFormat.bitDepth == 10 && > bayerFormat.packing == BayerFormat::Packing::CSI2) { > bpp_ = 10; >
diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h index 7fb5be77..f3bb4321 100644 --- a/include/libcamera/internal/software_isp/debayer_cpu.h +++ b/include/libcamera/internal/software_isp/debayer_cpu.h @@ -67,6 +67,9 @@ private: void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src); void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src); + void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src); + void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src); + typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src); struct DebayerInputConfig { diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 0ceb995f..3c43e146 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -29,6 +29,8 @@ public: /* FIXME this should be dropped once AWB has moved to the IPA */ SwIspStats getStats() { return *sharedStats_; } private: + void statsBGGR8Line0(const uint8_t *src, unsigned int stride); + void statsBGGR10PLine0(const uint8_t *src, unsigned int stride); void statsGBRG10PLine0(const uint8_t *src, unsigned int stride); void statsGRBG10PLine0(const uint8_t *src, unsigned int stride); diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 3eacdd5d..52910a03 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -111,6 +111,36 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src) } } +void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src) +{ + const int width_in_bytes = window_.width; + struct ctxt_8bit_src c = { + src - inputConfig_.stride, src, src + inputConfig_.stride, + red_, green_, blue_ }; + + for (int x = 0; x < width_in_bytes; ) { + /* Even pixel */ + bggr8_bgr888(c, dst, x++, 1, 1); + /* Odd pixel BGGR -> GBRG */ + gbrg8_bgr888(c, dst, x++, 1, 1); + } +} + +void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src) +{ + const int width_in_bytes = window_.width; + struct ctxt_8bit_src c = { + src - inputConfig_.stride, src, src + inputConfig_.stride, + red_, green_, blue_ }; + + for (int x = 0; x < width_in_bytes; ) { + /* Even pixel */ + grbg8_bgr888(c, dst, x++, 1, 1); + /* Odd pixel GRBG -> RGGB */ + rggb8_bgr888(c, dst, x++, 1, 1); + } +} + void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src) { const int width_in_bytes = window_.width * 5 / 4; @@ -152,6 +182,22 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + if (bayerFormat.bitDepth == 8) { + config.bpp = 8; + config.patternSize.height = 2; + config.patternSize.width = 4; + config.x_shift = 0; + config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 }); + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + return 0; + default: + break; + } + /* } else if (future supported fmts) { ... */ + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { config.bpp = 10; @@ -195,6 +241,17 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + if (bayerFormat.bitDepth == 8) { + switch (bayerFormat.order) { + case BayerFormat::BGGR: + debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888; + debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888; + return 0; + default: + break; + } + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { switch (bayerFormat.order) { diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 15f23953..e65b1b65 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -37,9 +37,9 @@ static const unsigned int GREEN_Y_MUL = 150; /* 0.59 * 256 */ static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */ static inline __attribute__((always_inline)) void -statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_) +statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_, bool is10p) { - const int width_in_bytes = width * 5 / 4; + const int width_in_bytes = width * (4 + is10p) / 4; uint8_t r, g, b, g2; unsigned int y_val; unsigned int sumR = 0; @@ -49,7 +49,7 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg unsigned int bright_sum = 0; unsigned int too_bright_sum = 0; - for (int x = 0; x < width_in_bytes; x += 5) { + for (int x = 0; x < width_in_bytes; x += (4 + is10p)) { if (bggr) { /* BGGR */ b = src0[x]; @@ -84,26 +84,31 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg too_bright_sum_ += too_bright_sum; } +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src, unsigned int stride) +{ + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, false); +} + void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src, unsigned int stride) { - statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_); + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, true); } void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src, unsigned int stride) { - statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_); + statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_, true); } void SwStatsCpu::statsGRBG10PLine0(const uint8_t *src, unsigned int stride) { /* GRBG is BGGR with the lines swapped */ - statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_); + statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_, true); } void SwStatsCpu::statsRGGB10PLine0(const uint8_t *src, unsigned int stride) { /* RGGB is GBRG with the lines swapped */ - statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_); + statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_, true); } void SwStatsCpu::resetStats(void) @@ -134,6 +139,24 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats; finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats; + if (bayerFormat.bitDepth == 8) { + bpp_ = 8; + patternSize_.height = 2; + patternSize_.width = 4; + y_skip_mask_ = 0x0c; /* Skip every 3th and 4th line */ + x_shift_ = 0; + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR8Line0; + return 0; + default: + break; + } + /* } else if (future supported fmts) { ... */ + } + + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { bpp_ = 10;