libcamera: debayer_cpu: Add support for 8, 10 and 12 bpp unpacked bayer input
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> Reviewed-by: Milan Zamazal <mzamazal@redhat.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
e19adc453f
commit
17c58df4b4
2 changed files with 141 additions and 0 deletions
|
@ -61,6 +61,11 @@ DebayerCpu::~DebayerCpu()
|
||||||
free(lineBuffers_[i]);
|
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
|
* RGR
|
||||||
* GBG
|
* GBG
|
||||||
|
@ -105,6 +110,70 @@ DebayerCpu::~DebayerCpu()
|
||||||
*dst++ = red_[curr[x] / (div)]; \
|
*dst++ = red_[curr[x] / (div)]; \
|
||||||
x++;
|
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[])
|
void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
|
||||||
{
|
{
|
||||||
const int widthInBytes = window_.width * 5 / 4;
|
const int widthInBytes = window_.width * 5 / 4;
|
||||||
|
@ -206,6 +275,16 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
|
||||||
BayerFormat bayerFormat =
|
BayerFormat bayerFormat =
|
||||||
BayerFormat::fromPixelFormat(inputFormat);
|
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 &&
|
if (bayerFormat.bitDepth == 10 &&
|
||||||
bayerFormat.packing == BayerFormat::Packing::CSI2 &&
|
bayerFormat.packing == BayerFormat::Packing::CSI2 &&
|
||||||
isStandardBayerOrder(bayerFormat.order)) {
|
isStandardBayerOrder(bayerFormat.order)) {
|
||||||
|
@ -233,6 +312,32 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c
|
||||||
return -EINVAL;
|
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
|
/* \todo This ignores outputFormat since there is only 1 supported outputFormat
|
||||||
for now */
|
for now */
|
||||||
int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
|
int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
|
||||||
|
@ -240,6 +345,29 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi
|
||||||
BayerFormat bayerFormat =
|
BayerFormat bayerFormat =
|
||||||
BayerFormat::fromPixelFormat(inputFormat);
|
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 &&
|
if (bayerFormat.bitDepth == 10 &&
|
||||||
bayerFormat.packing == BayerFormat::Packing::CSI2) {
|
bayerFormat.packing == BayerFormat::Packing::CSI2) {
|
||||||
switch (bayerFormat.order) {
|
switch (bayerFormat.order) {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include <libcamera/base/object.h>
|
#include <libcamera/base/object.h>
|
||||||
|
|
||||||
|
#include "libcamera/internal/bayer_format.h"
|
||||||
|
|
||||||
#include "debayer.h"
|
#include "debayer.h"
|
||||||
#include "swstats_cpu.h"
|
#include "swstats_cpu.h"
|
||||||
|
|
||||||
|
@ -82,6 +84,15 @@ private:
|
||||||
*/
|
*/
|
||||||
using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);
|
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) */
|
/* 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_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
|
||||||
void debayer10P_GRGR_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 getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
|
||||||
int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
|
int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
|
||||||
|
int setupStandardBayerOrder(BayerFormat::Order order);
|
||||||
int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
|
int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
|
||||||
void setupInputMemcpy(const uint8_t *linePointers[]);
|
void setupInputMemcpy(const uint8_t *linePointers[]);
|
||||||
void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
|
void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
|
||||||
|
@ -131,6 +143,7 @@ private:
|
||||||
unsigned int lineBufferLength_;
|
unsigned int lineBufferLength_;
|
||||||
unsigned int lineBufferPadding_;
|
unsigned int lineBufferPadding_;
|
||||||
unsigned int lineBufferIndex_;
|
unsigned int lineBufferIndex_;
|
||||||
|
unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
|
||||||
bool enableInputMemcpy_;
|
bool enableInputMemcpy_;
|
||||||
float gammaCorrection_;
|
float gammaCorrection_;
|
||||||
unsigned int measuredFrames_;
|
unsigned int measuredFrames_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue