@@ -50,6 +50,7 @@ private:
void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
void memcpyNextLine(const uint8_t *linePointers[]);
void process2(uint32_t frame, const uint8_t *src, uint8_t *dst);
+ void processMono2(uint32_t frame, const uint8_t *src, uint8_t *dst);
void process4(uint32_t frame, const uint8_t *src, uint8_t *dst);
/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */
@@ -424,6 +425,90 @@ void DebayerCpu::debayer12P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
+template<bool addAlphaByte, bool ccmEnabled>
+void DebayerCpu::debayer8_MONO_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ const uint8_t *cur = src[1];
+
+ for (int x = 0; x < static_cast<int>(window_.width);) {
+ uint8_t pixel_val = *cur++;
+ STORE_PIXEL(pixel_val, pixel_val, pixel_val)
+ }
+}
+
+template<bool addAlphaByte, bool ccmEnabled>
+void DebayerCpu::debayer10_MONO_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ const uint16_t *cur = reinterpret_cast<const uint16_t *>(src[1]);
+
+ for (int x = 0; x < static_cast<int>(window_.width);) {
+ uint16_t native_val = *cur++;
+ uint8_t pixel_val = static_cast<uint8_t>(native_val >> 2);
+
+ STORE_PIXEL(pixel_val, pixel_val, pixel_val)
+ }
+}
+
+template<bool addAlphaByte, bool ccmEnabled>
+void DebayerCpu::debayer12_MONO_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ const uint16_t *cur = reinterpret_cast<const uint16_t *>(src[1]);
+
+ for (int x = 0; x < static_cast<int>(window_.width);) {
+ uint16_t native_val = *cur++;
+ uint8_t pixel_val = static_cast<uint8_t>(native_val >> 4);
+
+ STORE_PIXEL(pixel_val, pixel_val, pixel_val)
+ }
+}
+
+template<bool addAlphaByte, bool ccmEnabled>
+void DebayerCpu::debayer10P_MONO_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ const uint8_t *cur = src[1];
+
+ for (int x = 0; x < static_cast<int>(window_.width);) {
+ uint8_t gray0 = *cur++;
+ uint8_t gray1 = *cur++;
+ uint8_t gray2 = *cur++;
+ uint8_t gray3 = *cur++;
+ cur++;
+
+ STORE_PIXEL(gray0, gray0, gray0)
+ STORE_PIXEL(gray1, gray1, gray1)
+ STORE_PIXEL(gray2, gray2, gray2)
+ STORE_PIXEL(gray3, gray3, gray3)
+ }
+}
+
+template<bool addAlphaByte, bool ccmEnabled>
+void DebayerCpu::debayer12P_MONO_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ const uint8_t *cur = src[1];
+
+ for (int x = 0; x < static_cast<int>(window_.width);) {
+ uint8_t gray0 = *cur++;
+ uint8_t gray1 = *cur++;
+ cur++;
+
+ STORE_PIXEL(gray0, gray0, gray0)
+ STORE_PIXEL(gray1, gray1, gray1)
+ }
+}
+
+template<bool addAlphaByte, bool ccmEnabled>
+void DebayerCpu::debayer16_MONO_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ const uint16_t *cur = reinterpret_cast<const uint16_t *>(src[1]);
+
+ for (int x = 0; x < static_cast<int>(window_.width);) {
+ uint16_t native_val = *cur++;
+ uint8_t pixel_val = static_cast<uint8_t>(native_val >> 8);
+
+ STORE_PIXEL(pixel_val, pixel_val, pixel_val)
+ }
+}
+
/*
* Setup the Debayer object according to the passed in parameters.
* Return 0 on success, a negative errno value on failure
@@ -433,6 +518,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
{
BayerFormat bayerFormat =
BayerFormat::fromPixelFormat(inputFormat);
+
std::vector<PixelFormat> outputFormats = { formats::RGB888,
formats::XRGB8888,
formats::ARGB8888,
@@ -440,6 +526,20 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
formats::XBGR8888,
formats::ABGR8888 };
+ if (bayerFormat.order == BayerFormat::Order::MONO) {
+ if (bayerFormat.packing == BayerFormat::Packing::None) {
+ config.bpp = (bayerFormat.bitDepth + 7) & ~7;
+ config.patternSize.width = 2;
+ config.patternSize.height = 2;
+ } else if (bayerFormat.packing == BayerFormat::Packing::CSI2) {
+ config.bpp = bayerFormat.bitDepth;
+ config.patternSize.width = (bayerFormat.bitDepth == 10) ? 4 : 2;
+ config.patternSize.height = 2;
+ }
+ config.outputFormats = outputFormats;
+ return 0;
+ }
+
if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
bayerFormat.packing == BayerFormat::Packing::None &&
isStandardBayerOrder(bayerFormat.order)) {
@@ -513,8 +613,6 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat,
PixelFormat outputFormat,
bool ccmEnabled)
{
- BayerFormat bayerFormat =
- BayerFormat::fromPixelFormat(inputFormat);
bool addAlphaByte = false;
xShift_ = 0;
@@ -525,6 +623,47 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat,
return -EINVAL;
};
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat);
+
+ if (bayerFormat.order == BayerFormat::Order::MONO) {
+
+
+ /* \todo Disable CCM via IPA; force false here to prevent monochrome coloration */
+ ccmEnabled = false;
+
+ if (outputFormat == formats::XRGB8888 || outputFormat == formats::ARGB8888 ||
+ outputFormat == formats::XBGR8888 || outputFormat == formats::ABGR8888) {
+ addAlphaByte = true;
+ }
+ if (bayerFormat.packing == BayerFormat::Packing::None) {
+ switch (bayerFormat.bitDepth) {
+ case 8:
+ SET_DEBAYER_METHODS(debayer8_MONO_BGR888, debayer8_MONO_BGR888)
+ return 0;
+ case 10:
+ SET_DEBAYER_METHODS(debayer10_MONO_BGR888, debayer10_MONO_BGR888)
+ return 0;
+ case 12:
+ SET_DEBAYER_METHODS(debayer12_MONO_BGR888, debayer12_MONO_BGR888)
+ return 0;
+ case 16:
+ SET_DEBAYER_METHODS(debayer16_MONO_BGR888, debayer16_MONO_BGR888)
+ return 0;
+ }
+ }
+ if (bayerFormat.packing == BayerFormat::Packing::CSI2) {
+ switch (bayerFormat.bitDepth) {
+ case 10:
+ SET_DEBAYER_METHODS(debayer10P_MONO_BGR888, debayer10P_MONO_BGR888)
+ return 0;
+ case 12:
+ SET_DEBAYER_METHODS(debayer12P_MONO_BGR888, debayer12P_MONO_BGR888)
+ return 0;
+ }
+ }
+ return invalidFmt();
+ }
+
switch (outputFormat) {
case formats::XRGB8888:
case formats::ARGB8888:
@@ -632,6 +771,9 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,
return -EINVAL;
}
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
+ isMono_ = (bayerFormat.order == BayerFormat::Order::MONO);
+
if (stats_->configure(inputCfg, threads_.size()) != 0)
return -EINVAL;
@@ -682,10 +824,16 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,
*/
params_.gamma = 1.0;
- window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
- ~(inputConfig_.patternSize.width - 1);
- window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) &
- ~(inputConfig_.patternSize.height - 1);
+ /* Setup the window geometry according to the format type */
+ if (isMono_) {
+ window_.x = 0;
+ window_.y = 0;
+ } else {
+ window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
+ ~(inputConfig_.patternSize.width - 1);
+ window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) &
+ ~(inputConfig_.patternSize.height - 1);
+ }
window_.width = outputCfg.size.width;
window_.height = outputCfg.size.height;
@@ -827,7 +975,9 @@ void DebayerCpuThread::process(uint32_t frame, const uint8_t *src, uint8_t *dst)
/* Adjust dst for yStart_ */
dst += yStart_ * debayer_->outputConfig_.stride;
- if (debayer_->inputConfig_.patternSize.height == 2)
+ if (debayer_->isMono_)
+ processMono2(frame, src, dst);
+ else if (debayer_->inputConfig_.patternSize.height == 2)
process2(frame, src, dst);
else
process4(frame, src, dst);
@@ -904,6 +1054,27 @@ void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst
}
}
+void DebayerCpuThread::processMono2(uint32_t frame, const uint8_t *src, uint8_t *dst)
+{
+ unsigned int outputStride = debayer_->outputConfig_.stride;
+ unsigned int inputStride = debayer_->inputConfig_.stride;
+ /* Holds [0] previous- [1] current- [2] next-line */
+ const uint8_t *linePointers[3];
+
+ for (unsigned int y = yStart_; y < yEnd_; y += 2) {
+ linePointers[1] = src;
+ debayer_->stats_->processLine0(frame, y, linePointers, threadIndex_);
+ debayer_->debayer0(dst, linePointers);
+ src += inputStride;
+ dst += outputStride;
+
+ linePointers[1] = src;
+ debayer_->debayer1(dst, linePointers);
+ src += inputStride;
+ dst += outputStride;
+ }
+}
+
void DebayerCpuThread::process4(uint32_t frame, const uint8_t *src, uint8_t *dst)
{
unsigned int outputStride = debayer_->outputConfig_.stride;
@@ -1124,11 +1295,12 @@ void DebayerCpu::stop()
SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize)
{
Size patternSize = this->patternSize(inputFormat);
- unsigned int borderHeight = patternSize.height;
-
if (patternSize.isNull())
return {};
+ /* FIX: borderHeight is now safely initialized after the isNull() check */
+ unsigned int borderHeight = patternSize.height;
+
/* No need for top/bottom border with a pattern height of 2 */
if (patternSize.height == 2)
borderHeight = 0;
@@ -1140,13 +1312,16 @@ SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize)
if (inputSize.width < (3 * patternSize.width) ||
inputSize.height < (2 * borderHeight + patternSize.height)) {
LOG(Debayer, Warning)
- << "Input format size too small: " << inputSize.toString();
+ << "Input format size too small: " << inputSize;
return {};
}
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat);
+ bool localIsMono = (bayerFormat.order == BayerFormat::Order::MONO);
+
return SizeRange(Size(patternSize.width, patternSize.height),
- Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1),
- (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)),
+ Size((inputSize.width - (localIsMono ? 0 : 2 * patternSize.width)) & ~(patternSize.width - 1),
+ (inputSize.height - (localIsMono ? 0 : 2 * borderHeight)) & ~(patternSize.height - 1)),
patternSize.width, patternSize.height);
}
@@ -119,6 +119,24 @@ private:
void debayer12P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]);
template<bool addAlphaByte, bool ccmEnabled>
void debayer12P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* 8-bit raw monochrome format */
+ template<bool addAlphaByte, bool ccmEnabled>
+ void debayer8_MONO_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* unpacked 10-bit raw monochrome format */
+ template<bool addAlphaByte, bool ccmEnabled>
+ void debayer10_MONO_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* unpacked 12-bit raw monochrome format */
+ template<bool addAlphaByte, bool ccmEnabled>
+ void debayer12_MONO_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* CSI-2 packed 10-bit raw monochrome format */
+ template<bool addAlphaByte, bool ccmEnabled>
+ void debayer10P_MONO_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* CSI-2 packed 12-bit raw monochrome format */
+ template<bool addAlphaByte, bool ccmEnabled>
+ void debayer12P_MONO_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* Mono 16 bpp unpacked */
+ template<bool addAlphaByte, bool ccmEnabled>
+ void debayer16_MONO_BGR888(uint8_t *dst, const uint8_t *src[]);
static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
int setupStandardBayerOrder(BayerFormat::Order order);
@@ -146,6 +164,7 @@ private:
std::array<double, kGammaLookupSize> gammaTable_;
LookupTable gammaLut_;
bool ccmEnabled_;
+ bool isMono_;
DebayerParams params_;
debayerFn debayer0_;
Signed-off-by: Alain CousiniƩ <alain.cousinie@laposte.net> --- src/libcamera/software_isp/debayer_cpu.cpp | 199 +++++++++++++++++++-- src/libcamera/software_isp/debayer_cpu.h | 19 ++ 2 files changed, 206 insertions(+), 12 deletions(-) -- 2.55.0