summaryrefslogtreecommitdiff
path: root/src/libcamera/software_isp/debayer_cpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/software_isp/debayer_cpu.cpp')
-rw-r--r--src/libcamera/software_isp/debayer_cpu.cpp189
1 files changed, 125 insertions, 64 deletions
diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
index 077f7f4b..66f6038c 100644
--- a/src/libcamera/software_isp/debayer_cpu.cpp
+++ b/src/libcamera/software_isp/debayer_cpu.cpp
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2023, Linaro Ltd
- * Copyright (C) 2023, Red Hat Inc.
+ * Copyright (C) 2023-2025 Red Hat Inc.
*
* Authors:
* Hans de Goede <hdegoede@redhat.com>
@@ -11,12 +11,18 @@
#include "debayer_cpu.h"
+#include <algorithm>
#include <stdlib.h>
+#include <sys/ioctl.h>
#include <time.h>
+#include <utility>
+
+#include <linux/dma-buf.h>
#include <libcamera/formats.h>
#include "libcamera/internal/bayer_format.h"
+#include "libcamera/internal/dma_buf_allocator.h"
#include "libcamera/internal/framebuffer.h"
#include "libcamera/internal/mapped_framebuffer.h"
@@ -47,8 +53,12 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
enableInputMemcpy_ = true;
/* Initialize color lookup tables */
- for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++)
+ for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
red_[i] = green_[i] = blue_[i] = i;
+ redCcm_[i] = { static_cast<int16_t>(i), 0, 0 };
+ greenCcm_[i] = { 0, static_cast<int16_t>(i), 0 };
+ blueCcm_[i] = { 0, 0, static_cast<int16_t>(i) };
+ }
}
DebayerCpu::~DebayerCpu() = default;
@@ -58,59 +68,71 @@ DebayerCpu::~DebayerCpu() = default;
const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \
const pixel_t *next = (const pixel_t *)src[2] + xShift_;
+#define GAMMA(value) \
+ *dst++ = gammaLut_[std::clamp(value, 0, static_cast<int>(gammaLut_.size()) - 1)]
+
+#define STORE_PIXEL(b_, g_, r_) \
+ if constexpr (ccmEnabled) { \
+ const DebayerParams::CcmColumn &blue = blueCcm_[b_]; \
+ const DebayerParams::CcmColumn &green = greenCcm_[g_]; \
+ const DebayerParams::CcmColumn &red = redCcm_[r_]; \
+ GAMMA(blue.b + green.b + red.b); \
+ GAMMA(blue.g + green.g + red.g); \
+ GAMMA(blue.r + green.r + red.r); \
+ } else { \
+ *dst++ = blue_[b_]; \
+ *dst++ = green_[g_]; \
+ *dst++ = red_[r_]; \
+ } \
+ if constexpr (addAlphaByte) \
+ *dst++ = 255; \
+ x++;
+
/*
* RGR
* GBG
* RGR
*/
-#define BGGR_BGR888(p, n, div) \
- *dst++ = blue_[curr[x] / (div)]; \
- *dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))]; \
- *dst++ = red_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \
- if constexpr (addAlphaByte) \
- *dst++ = 255; \
- x++;
+#define BGGR_BGR888(p, n, div) \
+ STORE_PIXEL( \
+ curr[x] / (div), \
+ (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)), \
+ (prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div)))
/*
* GBG
* RGR
* GBG
*/
-#define GRBG_BGR888(p, n, div) \
- *dst++ = blue_[(prev[x] + next[x]) / (2 * (div))]; \
- *dst++ = green_[curr[x] / (div)]; \
- *dst++ = red_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \
- if constexpr (addAlphaByte) \
- *dst++ = 255; \
- x++;
+#define GRBG_BGR888(p, n, div) \
+ STORE_PIXEL( \
+ (prev[x] + next[x]) / (2 * (div)), \
+ curr[x] / (div), \
+ (curr[x - p] + curr[x + n]) / (2 * (div)))
/*
* GRG
* BGB
* GRG
*/
-#define GBRG_BGR888(p, n, div) \
- *dst++ = blue_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \
- *dst++ = green_[curr[x] / (div)]; \
- *dst++ = red_[(prev[x] + next[x]) / (2 * (div))]; \
- if constexpr (addAlphaByte) \
- *dst++ = 255; \
- x++;
+#define GBRG_BGR888(p, n, div) \
+ STORE_PIXEL( \
+ (curr[x - p] + curr[x + n]) / (2 * (div)), \
+ curr[x] / (div), \
+ (prev[x] + next[x]) / (2 * (div)))
/*
* BGB
* GRG
* BGB
*/
-#define RGGB_BGR888(p, n, div) \
- *dst++ = blue_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \
- *dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))]; \
- *dst++ = red_[curr[x] / (div)]; \
- if constexpr (addAlphaByte) \
- *dst++ = 255; \
- x++;
+#define RGGB_BGR888(p, n, div) \
+ STORE_PIXEL( \
+ (prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div)), \
+ (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)), \
+ curr[x] / (div))
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
{
DECLARE_SRC_POINTERS(uint8_t)
@@ -121,7 +143,7 @@ void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
{
DECLARE_SRC_POINTERS(uint8_t)
@@ -132,7 +154,7 @@ void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
{
DECLARE_SRC_POINTERS(uint16_t)
@@ -144,7 +166,7 @@ void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
{
DECLARE_SRC_POINTERS(uint16_t)
@@ -156,7 +178,7 @@ void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
{
DECLARE_SRC_POINTERS(uint16_t)
@@ -168,7 +190,7 @@ void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
{
DECLARE_SRC_POINTERS(uint16_t)
@@ -180,7 +202,7 @@ void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
{
const int widthInBytes = window_.width * 5 / 4;
@@ -206,7 +228,7 @@ void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
{
const int widthInBytes = window_.width * 5 / 4;
@@ -227,7 +249,7 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])
{
const int widthInBytes = window_.width * 5 / 4;
@@ -248,7 +270,7 @@ void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])
}
}
-template<bool addAlphaByte>
+template<bool addAlphaByte, bool ccmEnabled>
void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])
{
const int widthInBytes = window_.width * 5 / 4;
@@ -364,7 +386,17 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)
return 0;
}
-int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat)
+#define SET_DEBAYER_METHODS(method0, method1) \
+ debayer0_ = addAlphaByte \
+ ? (ccmEnabled ? &DebayerCpu::method0<true, true> : &DebayerCpu::method0<true, false>) \
+ : (ccmEnabled ? &DebayerCpu::method0<false, true> : &DebayerCpu::method0<false, false>); \
+ debayer1_ = addAlphaByte \
+ ? (ccmEnabled ? &DebayerCpu::method1<true, true> : &DebayerCpu::method1<true, false>) \
+ : (ccmEnabled ? &DebayerCpu::method1<false, true> : &DebayerCpu::method1<false, false>);
+
+int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat,
+ PixelFormat outputFormat,
+ bool ccmEnabled)
{
BayerFormat bayerFormat =
BayerFormat::fromPixelFormat(inputFormat);
@@ -419,16 +451,13 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF
isStandardBayerOrder(bayerFormat.order)) {
switch (bayerFormat.bitDepth) {
case 8:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer8_BGBG_BGR888<true> : &DebayerCpu::debayer8_BGBG_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer8_GRGR_BGR888<true> : &DebayerCpu::debayer8_GRGR_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer8_BGBG_BGR888, debayer8_GRGR_BGR888)
break;
case 10:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer10_BGBG_BGR888<true> : &DebayerCpu::debayer10_BGBG_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer10_GRGR_BGR888<true> : &DebayerCpu::debayer10_GRGR_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer10_BGBG_BGR888, debayer10_GRGR_BGR888)
break;
case 12:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer12_BGBG_BGR888<true> : &DebayerCpu::debayer12_BGBG_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer12_GRGR_BGR888<true> : &DebayerCpu::debayer12_GRGR_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer12_BGBG_BGR888, debayer12_GRGR_BGR888)
break;
}
setupStandardBayerOrder(bayerFormat.order);
@@ -439,20 +468,16 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF
bayerFormat.packing == BayerFormat::Packing::CSI2) {
switch (bayerFormat.order) {
case BayerFormat::BGGR:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_BGBG_BGR888<true> : &DebayerCpu::debayer10P_BGBG_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_GRGR_BGR888<true> : &DebayerCpu::debayer10P_GRGR_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer10P_BGBG_BGR888, debayer10P_GRGR_BGR888)
return 0;
case BayerFormat::GBRG:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_GBGB_BGR888<true> : &DebayerCpu::debayer10P_GBGB_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_RGRG_BGR888<true> : &DebayerCpu::debayer10P_RGRG_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer10P_GBGB_BGR888, debayer10P_RGRG_BGR888)
return 0;
case BayerFormat::GRBG:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_GRGR_BGR888<true> : &DebayerCpu::debayer10P_GRGR_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_BGBG_BGR888<true> : &DebayerCpu::debayer10P_BGBG_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer10P_GRGR_BGR888, debayer10P_BGBG_BGR888)
return 0;
case BayerFormat::RGGB:
- debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_RGRG_BGR888<true> : &DebayerCpu::debayer10P_RGRG_BGR888<false>;
- debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_GBGB_BGR888<true> : &DebayerCpu::debayer10P_GBGB_BGR888<false>;
+ SET_DEBAYER_METHODS(debayer10P_RGRG_BGR888, debayer10P_GBGB_BGR888)
return 0;
default:
break;
@@ -463,7 +488,8 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF
}
int DebayerCpu::configure(const StreamConfiguration &inputCfg,
- const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)
+ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,
+ bool ccmEnabled)
{
if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0)
return -EINVAL;
@@ -502,7 +528,10 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,
return -EINVAL;
}
- if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0)
+ int ret = setDebayerFunctions(inputCfg.pixelFormat,
+ outputCfg.pixelFormat,
+ ccmEnabled);
+ if (ret != 0)
return -EINVAL;
window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
@@ -608,8 +637,7 @@ void DebayerCpu::memcpyNextLine(const uint8_t *linePointers[])
memcpy(lineBuffers_[lineBufferIndex_].data(),
linePointers[patternHeight] - lineBufferPadding_,
lineBufferLength_);
- linePointers[patternHeight] = lineBuffers_[lineBufferIndex_].data()
- + lineBufferPadding_;
+ linePointers[patternHeight] = lineBuffers_[lineBufferIndex_].data() + lineBufferPadding_;
lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1);
}
@@ -718,13 +746,17 @@ void DebayerCpu::process4(const uint8_t *src, uint8_t *dst)
}
}
-static inline int64_t timeDiff(timespec &after, timespec &before)
+namespace {
+
+inline int64_t timeDiff(timespec &after, timespec &before)
{
return (after.tv_sec - before.tv_sec) * 1000000000LL +
(int64_t)after.tv_nsec - (int64_t)before.tv_nsec;
}
-void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params)
+} /* namespace */
+
+void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params)
{
timespec frameStartTime;
@@ -733,9 +765,31 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
}
+ std::vector<DmaSyncer> dmaSyncers;
+ for (const FrameBuffer::Plane &plane : input->planes())
+ dmaSyncers.emplace_back(plane.fd, DmaSyncer::SyncType::Read);
+
+ for (const FrameBuffer::Plane &plane : output->planes())
+ dmaSyncers.emplace_back(plane.fd, DmaSyncer::SyncType::Write);
+
green_ = params.green;
- red_ = swapRedBlueGains_ ? params.blue : params.red;
- blue_ = swapRedBlueGains_ ? params.red : params.blue;
+ greenCcm_ = params.greenCcm;
+ if (swapRedBlueGains_) {
+ red_ = params.blue;
+ blue_ = params.red;
+ redCcm_ = params.blueCcm;
+ blueCcm_ = params.redCcm;
+ for (unsigned int i = 0; i < 256; i++) {
+ std::swap(redCcm_[i].r, redCcm_[i].b);
+ std::swap(blueCcm_[i].r, blueCcm_[i].b);
+ }
+ } else {
+ red_ = params.red;
+ blue_ = params.blue;
+ redCcm_ = params.redCcm;
+ blueCcm_ = params.blueCcm;
+ }
+ gammaLut_ = params.gammaLut;
/* Copy metadata from the input buffer */
FrameMetadata &metadata = output->_d()->metadata();
@@ -760,6 +814,8 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
metadata.planes()[0].bytesused = out.planes()[0].size();
+ dmaSyncers.clear();
+
/* Measure before emitting signals */
if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
++measuredFrames_ > DebayerCpu::kFramesToSkip) {
@@ -777,7 +833,12 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
}
}
- stats_->finishFrame();
+ /*
+ * Buffer ids are currently not used, so pass zeros as its parameter.
+ *
+ * \todo Pass real bufferId once stats buffer passing is changed.
+ */
+ stats_->finishFrame(frame, 0);
outputBufferReady.emit(output);
inputBufferReady.emit(input);
}