Add debayering support for all bayer CFAs

This commit is contained in:
Yassine Oudjana
2022-01-17 17:05:51 +04:00
parent c16dbf6810
commit 212e75ed3c
6 changed files with 65 additions and 14 deletions

View File

@@ -60,7 +60,7 @@ when previewing.
* `width=640` and `height=480` the resolution to use for the sensor * `width=640` and `height=480` the resolution to use for the sensor
* `rate=15` the refresh rate in fps to use for the sensor * `rate=15` the refresh rate in fps to use for the sensor
* `fmt=BGGR8` sets the pixel and bus formats used when capturing from the sensor, only BGGR8 is fully supported * `fmt=BGGR8` sets the pixel and bus formats used when capturing from the sensor.
# Post processing # Post processing

View File

@@ -44,9 +44,15 @@ main()
texture2D(texture, bottom_right_uv).r); texture2D(texture, bottom_right_uv).r);
#endif #endif
// Assume BGGR for now. Currently this just takes 3 of the four samples #if defined(CFA_BGGR)
// for each pixel, there's room here to do some better debayering.
vec3 color = vec3(samples.w, (samples.y + samples.z) / 2.0, samples.x); vec3 color = vec3(samples.w, (samples.y + samples.z) / 2.0, samples.x);
#elif defined(CFA_GBRG)
vec3 color = vec3(samples.z, (samples.x + samples.w) / 2.0, samples.y);
#elif defined(CFA_GRBG)
vec3 color = vec3(samples.y, (samples.x + samples.w) / 2.0, samples.z);
#else
vec3 color = vec3(samples.x, (samples.y + samples.z) / 2.0, samples.w);
#endif
// Some crude blacklevel correction to make the preview a bit nicer, this // Some crude blacklevel correction to make the preview a bit nicer, this
// should be an uniform // should be an uniform

View File

@@ -144,6 +144,38 @@ mp_pixel_format_pixel_depth(MPPixelFormat pixel_format)
} }
} }
const char *
mp_pixel_format_cfa(MPPixelFormat pixel_format)
{
g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
switch (pixel_format) {
case MP_PIXEL_FMT_BGGR8:
case MP_PIXEL_FMT_BGGR10P:
return "BGGR";
break;
case MP_PIXEL_FMT_GBRG8:
case MP_PIXEL_FMT_GBRG10P:
return "GBRG";
break;
case MP_PIXEL_FMT_GRBG8:
case MP_PIXEL_FMT_GRBG10P:
return "GRBG";
break;
case MP_PIXEL_FMT_RGGB8:
case MP_PIXEL_FMT_RGGB10P:
return "RGGB";
break;
case MP_PIXEL_FMT_UYVY:
return "UYUV";
break;
case MP_PIXEL_FMT_YUYV:
return "YUYV";
break;
default:
return "unsupported";
}
}
uint32_t uint32_t
mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width) mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width)
{ {

View File

@@ -31,6 +31,7 @@ uint32_t mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format);
uint32_t mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format); uint32_t mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format);
uint32_t mp_pixel_format_pixel_depth(MPPixelFormat pixel_format); uint32_t mp_pixel_format_pixel_depth(MPPixelFormat pixel_format);
const char *mp_pixel_format_cfa(MPPixelFormat pixel_format);
uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width); uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width);
uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width); uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width);
uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format,

View File

@@ -24,7 +24,10 @@ struct _GLES2Debayer {
GLES2Debayer * GLES2Debayer *
gles2_debayer_new(MPPixelFormat format) gles2_debayer_new(MPPixelFormat format)
{ {
if (format != MP_PIXEL_FMT_BGGR8 && format != MP_PIXEL_FMT_BGGR10P) { if (format != MP_PIXEL_FMT_BGGR8 && format != MP_PIXEL_FMT_GBRG8 &&
format != MP_PIXEL_FMT_GRBG8 && format != MP_PIXEL_FMT_RGGB8 &&
format != MP_PIXEL_FMT_BGGR10P && format != MP_PIXEL_FMT_GBRG10P &&
format != MP_PIXEL_FMT_GRBG10P && format != MP_PIXEL_FMT_RGGB10P) {
return NULL; return NULL;
} }
@@ -32,10 +35,11 @@ gles2_debayer_new(MPPixelFormat format)
glGenFramebuffers(1, &frame_buffer); glGenFramebuffers(1, &frame_buffer);
check_gl(); check_gl();
char format_def[32]; char format_def[64];
snprintf(format_def, snprintf(format_def,
32, 64,
"#define BITS_%d\n", "#define CFA_%s\n#define BITS_%d\n",
mp_pixel_format_cfa(format),
mp_pixel_format_bits_per_pixel(format)); mp_pixel_format_bits_per_pixel(format));
const GLchar *def[1] = { format_def }; const GLchar *def[1] = { format_def };

View File

@@ -224,14 +224,9 @@ init_gl(MPPipeline *pipeline, GdkSurface **surface)
check_gl(); check_gl();
} }
gles2_debayer = gles2_debayer_new(MP_PIXEL_FMT_BGGR8);
check_gl();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
check_gl(); check_gl();
gles2_debayer_use(gles2_debayer);
for (size_t i = 0; i < NUM_BUFFERS; ++i) { for (size_t i = 0; i < NUM_BUFFERS; ++i) {
glGenTextures(1, &output_buffers[i].texture_id); glGenTextures(1, &output_buffers[i].texture_id);
glBindTexture(GL_TEXTURE_2D, output_buffers[i].texture_id); glBindTexture(GL_TEXTURE_2D, output_buffers[i].texture_id);
@@ -718,7 +713,7 @@ mp_process_pipeline_capture()
} }
static void static void
on_output_changed() on_output_changed(bool format_changed)
{ {
output_buffer_width = mode.width / 2; output_buffer_width = mode.width / 2;
output_buffer_height = mode.height / 2; output_buffer_height = mode.height / 2;
@@ -744,6 +739,17 @@ on_output_changed()
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
// Create new gles2_debayer on format change
if (format_changed) {
if (gles2_debayer)
gles2_debayer_free(gles2_debayer);
gles2_debayer = gles2_debayer_new(mode.pixel_format);
check_gl();
gles2_debayer_use(gles2_debayer);
}
gles2_debayer_configure( gles2_debayer_configure(
gles2_debayer, gles2_debayer,
output_buffer_width, output_buffer_width,
@@ -772,6 +778,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
preview_height != state->preview_height || preview_height != state->preview_height ||
device_rotation != state->device_rotation; device_rotation != state->device_rotation;
const bool format_changed = mode.pixel_format != state->mode.pixel_format;
camera = state->camera; camera = state->camera;
mode = state->mode; mode = state->mode;
@@ -793,7 +801,7 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
if (output_changed) { if (output_changed) {
camera_rotation = mod(camera->rotate - device_rotation, 360); camera_rotation = mod(camera->rotate - device_rotation, 360);
on_output_changed(); on_output_changed(format_changed);
} }
struct mp_main_state main_state = { struct mp_main_state main_state = {