u/sink: Add Bayer format converter

This commit is contained in:
Jakob Bornecrantz 2020-09-15 16:21:44 +01:00 committed by Jakob Bornecrantz
parent 5b6e6bf6a6
commit eec3446e5b
3 changed files with 163 additions and 3 deletions

View file

@ -0,0 +1 @@
u/sink: Add Bayer format converter.

View file

@ -44,6 +44,15 @@ u_sink_create_to_r8g8b8_or_l8(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *downstream,
struct xrt_frame_sink **out_xfs);
/*!
* @relatesalso xrt_frame_sink
* @relates xrt_frame_context
*/
void
u_sink_create_to_r8g8b8_bayer_or_l8(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *downstream,
struct xrt_frame_sink **out_xfs);
/*!
* @relatesalso xrt_frame_sink
* @relates xrt_frame_context

View file

@ -341,6 +341,44 @@ from_MJPEG_to_YUV888(struct xrt_frame *dst_frame, size_t size, const uint8_t *da
#endif
/*
*
* Bayer
*
*/
static void
from_BAYER_GR8_to_R8G8B8(struct xrt_frame *dst_frame, uint32_t w, uint32_t h, size_t stride, const uint8_t *data)
{
const uint8_t *src_data = data;
uint32_t src_stride = stride;
uint8_t *dst_data = dst_frame->data;
uint32_t dst_stride = dst_frame->stride;
for (uint32_t y = 0; y < h; y++) {
const uint8_t *src0 = src_data + (y * 2) * src_stride;
const uint8_t *src1 = src_data + (y * 2 + 1) * src_stride;
uint8_t *dst = dst_data + (y * dst_stride);
for (uint32_t x = 0; x < w; x++) {
uint8_t g0 = src0[0];
uint8_t r = src0[1];
uint8_t b = src1[0];
uint8_t g1 = src1[1];
dst[0] = r;
dst[1] = (g0 + g1) / 2;
dst[2] = b;
src0 += 2;
src1 += 2;
dst += 3;
}
}
}
/*
*
* Misc functions.
@ -349,15 +387,16 @@ from_MJPEG_to_YUV888(struct xrt_frame *dst_frame, size_t size, const uint8_t *da
/*!
* Creates a frame that the conversion should happen to.
* Creates a frame that the conversion should happen to, allows to set the size.
*
* @todo Allocate from a pool of frames.
*/
static bool
create_frame_with_format(struct xrt_frame *xf, enum xrt_format format, struct xrt_frame **out_frame)
create_frame_with_format_of_size(
struct xrt_frame *xf, uint32_t w, uint32_t h, enum xrt_format format, struct xrt_frame **out_frame)
{
struct xrt_frame *frame = NULL;
u_frame_create_one_off(format, xf->width, xf->height, &frame);
u_frame_create_one_off(format, w, h, &frame);
if (frame == NULL) {
U_LOG_E("Failed to create target frame!");
*out_frame = NULL;
@ -375,6 +414,15 @@ create_frame_with_format(struct xrt_frame *xf, enum xrt_format format, struct xr
return true;
}
/*!
* Creates a frame that the conversion should happen to.
*/
static bool
create_frame_with_format(struct xrt_frame *xf, enum xrt_format format, struct xrt_frame **out_frame)
{
return create_frame_with_format_of_size(xf, xf->width, xf->height, format, out_frame);
}
static void
receive_frame_r8g8b8_or_l8(struct xrt_frame_sink *xs, struct xrt_frame *xf)
{
@ -385,6 +433,62 @@ receive_frame_r8g8b8_or_l8(struct xrt_frame_sink *xs, struct xrt_frame *xf)
switch (xf->format) {
case XRT_FORMAT_L8:
case XRT_FORMAT_R8G8B8: s->downstream->push_frame(s->downstream, xf); return;
case XRT_FORMAT_BAYER_GR8:;
uint32_t w = xf->width / 2;
uint32_t h = xf->height / 2;
if (!create_frame_with_format_of_size(xf, w, h, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
from_BAYER_GR8_to_R8G8B8(converted, w, h, xf->stride, xf->data);
break;
case XRT_FORMAT_YUYV422:
if (!create_frame_with_format(xf, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
from_YUYV422_to_R8G8B8(converted, xf->width, xf->height, xf->stride, xf->data);
break;
case XRT_FORMAT_UYVY422:
if (!create_frame_with_format(xf, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
from_UYVY422_to_R8G8B8(converted, xf->width, xf->height, xf->stride, xf->data);
break;
case XRT_FORMAT_YUV888:
if (!create_frame_with_format(xf, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
from_YUV888_to_R8G8B8(converted, xf->width, xf->height, xf->stride, xf->data);
break;
#ifdef XRT_HAVE_JPEG
case XRT_FORMAT_MJPEG:
if (!create_frame_with_format(xf, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
if (!from_MJPEG_to_R8G8B8(converted, xf->size, xf->data)) {
return;
}
break;
#endif
default: U_LOG_E("Can not convert from '%s' to R8G8B8 or L8!", u_format_str(xf->format)); return;
}
s->downstream->push_frame(s->downstream, converted);
// Refcount in case it's being held downstream.
xrt_frame_reference(&converted, NULL);
}
static void
receive_frame_r8g8b8_bayer_or_l8(struct xrt_frame_sink *xs, struct xrt_frame *xf)
{
struct u_sink_converter *s = (struct u_sink_converter *)xs;
struct xrt_frame *converted = NULL;
switch (xf->format) {
case XRT_FORMAT_L8:
case XRT_FORMAT_R8G8B8:
case XRT_FORMAT_BAYER_GR8:; s->downstream->push_frame(s->downstream, xf); return;
case XRT_FORMAT_YUYV422:
if (!create_frame_with_format(xf, XRT_FORMAT_R8G8B8, &converted)) {
return;
@ -431,6 +535,14 @@ receive_frame_r8g8b8(struct xrt_frame_sink *xs, struct xrt_frame *xf)
switch (xf->format) {
case XRT_FORMAT_R8G8B8: s->downstream->push_frame(s->downstream, xf); return;
case XRT_FORMAT_BAYER_GR8:;
uint32_t w = xf->width / 2;
uint32_t h = xf->height / 2;
if (!create_frame_with_format_of_size(xf, w, h, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
from_BAYER_GR8_to_R8G8B8(converted, w, h, xf->stride, xf->data);
break;
case XRT_FORMAT_YUYV422:
if (!create_frame_with_format(xf, XRT_FORMAT_R8G8B8, &converted)) {
return;
@ -533,6 +645,27 @@ receive_frame_yuv_or_yuyv(struct xrt_frame_sink *xs, struct xrt_frame *xf)
xrt_frame_reference(&converted, NULL);
}
XRT_MAYBE_UNUSED static void
receive_frame_bayer(struct xrt_frame_sink *xs, struct xrt_frame *xf)
{
struct u_sink_converter *s = (struct u_sink_converter *)xs;
uint32_t w = xf->width / 2;
uint32_t h = xf->height / 2;
struct xrt_frame *converted = NULL;
if (!create_frame_with_format_of_size(xf, w, h, XRT_FORMAT_R8G8B8, &converted)) {
return;
}
from_BAYER_GR8_to_R8G8B8(converted, w, h, xf->stride, xf->data);
s->downstream->push_frame(s->downstream, converted);
// Refcount in case it's being held downstream.
xrt_frame_reference(&converted, NULL);
}
static void
break_apart(struct xrt_frame_node *node)
{}
@ -598,6 +731,23 @@ u_sink_create_to_r8g8b8_or_l8(struct xrt_frame_context *xfctx,
*out_xfs = &s->base;
}
void
u_sink_create_to_r8g8b8_bayer_or_l8(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *downstream,
struct xrt_frame_sink **out_xfs)
{
struct u_sink_converter *s = U_TYPED_CALLOC(struct u_sink_converter);
s->base.push_frame = receive_frame_r8g8b8_bayer_or_l8;
s->node.break_apart = break_apart;
s->node.destroy = destroy;
s->downstream = downstream;
xrt_frame_context_add(xfctx, &s->node);
*out_xfs = &s->base;
}
void
u_sink_create_to_yuv_yuyv_uyvy_or_l8(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *downstream,