Support rendering YUV formatted frames

This commit is contained in:
Martijn Braam
2023-11-24 16:28:25 +01:00
parent 8a3f1a5540
commit 9d189b88b4
10 changed files with 146 additions and 53 deletions

View File

@@ -38,27 +38,27 @@ main()
// Note the coordinates for texture samples need to be a varying, as the
// Mali-400 has this as a fast path allowing 32-bit floats. Otherwise
// they end up as 16-bit floats and that's not accurate enough.
#ifdef BITS_10
#ifdef BITS_10
vec4 samples = vec4(texture2D(texture, skip_5th_pixel(top_left_uv)).r,
texture2D(texture, skip_5th_pixel(top_right_uv)).r,
texture2D(texture, skip_5th_pixel(bottom_left_uv)).r,
texture2D(texture, skip_5th_pixel(bottom_right_uv)).r);
#else
#else
vec4 samples = vec4(texture2D(texture, top_left_uv).r,
texture2D(texture, top_right_uv).r,
texture2D(texture, bottom_left_uv).r,
texture2D(texture, bottom_right_uv).r);
#endif
#endif
#if defined(CFA_BGGR)
#if defined(CFA_BGGR)
vec3 color = vec3(samples.w, (samples.y + samples.z) / 2.0, samples.x);
#elif defined(CFA_GBRG)
#elif defined(CFA_GBRG)
vec3 color = vec3(samples.z, (samples.x + samples.w) / 2.0, samples.y);
#elif defined(CFA_GRBG)
#elif defined(CFA_GRBG)
vec3 color = vec3(samples.y, (samples.x + samples.w) / 2.0, samples.z);
#else
#else
vec3 color = vec3(samples.x, (samples.y + samples.z) / 2.0, samples.w);
#endif
#endif
color -= blacklevel;
color *= color_matrix;

View File

@@ -17,5 +17,7 @@
<file>solid.frag</file>
<file>debayer.vert</file>
<file>debayer.frag</file>
<file>yuv.vert</file>
<file>yuv.frag</file>
</gresource>
</gresources>

32
data/yuv.frag Normal file
View File

@@ -0,0 +1,32 @@
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D texture;
uniform mat3 color_matrix;
uniform float inv_gamma;
uniform float blacklevel;
varying vec2 top_left_uv;
varying vec2 top_right_uv;
varying vec2 bottom_left_uv;
varying vec2 bottom_right_uv;
void
main()
{
// Note the coordinates for texture samples need to be a varying, as the
// Mali-400 has this as a fast path allowing 32-bit floats. Otherwise
// they end up as 16-bit floats and that's not accurate enough.
vec4 samples = vec4(texture2D(texture, top_left_uv).r,
texture2D(texture, top_right_uv).r,
texture2D(texture, bottom_left_uv).r,
texture2D(texture, bottom_right_uv).r);
vec3 color = vec3(samples.x, samples.y, samples.z);
color *= color_matrix;
vec3 gamma_color = pow(color, vec3(inv_gamma));
gl_FragColor = vec4(gamma_color, 1);
}

25
data/yuv.vert Normal file
View File

@@ -0,0 +1,25 @@
#ifdef GL_ES
precision mediump float;
#endif
attribute vec2 vert;
attribute vec2 tex_coord;
uniform mat3 transform;
uniform vec2 pixel_size;
varying vec2 top_left_uv;
varying vec2 top_right_uv;
varying vec2 bottom_left_uv;
varying vec2 bottom_right_uv;
void
main()
{
top_left_uv = tex_coord - pixel_size / 2.0;
bottom_right_uv = tex_coord + pixel_size / 2.0;
top_right_uv = vec2(top_left_uv.x, bottom_right_uv.y);
bottom_left_uv = vec2(bottom_right_uv.x, top_left_uv.y);
gl_Position = vec4(transform * vec3(vert, 1), 1);
}

View File

@@ -386,6 +386,7 @@ mp_camera_capture_buffer(MPCamera *camera, MPBuffer *buffer)
}
int format = camera->camera->current_mode->format;
assert(format != 0);
uint32_t width = camera->camera->current_mode->width;
uint32_t height = camera->camera->current_mode->height;

View File

@@ -12,11 +12,21 @@
GLES2Debayer *
gles2_debayer_new(int format)
{
// Cannot run on format 0 (Undefined)
assert(format != 0);
uint32_t pixfmt = libmegapixels_format_to_v4l_pixfmt(format);
if (pixfmt != V4L2_PIX_FMT_SBGGR8 && pixfmt != V4L2_PIX_FMT_SGBRG8 &&
pixfmt != V4L2_PIX_FMT_SGRBG8 && pixfmt != V4L2_PIX_FMT_SRGGB8 &&
pixfmt != V4L2_PIX_FMT_SBGGR10P && pixfmt != V4L2_PIX_FMT_SGBRG10P &&
pixfmt != V4L2_PIX_FMT_SGRBG10P && pixfmt != V4L2_PIX_FMT_SRGGB10P) {
int shader = 0;
if (pixfmt == V4L2_PIX_FMT_SBGGR8 || pixfmt == V4L2_PIX_FMT_SGBRG8 ||
pixfmt == V4L2_PIX_FMT_SGRBG8 || pixfmt == V4L2_PIX_FMT_SRGGB8 ||
pixfmt == V4L2_PIX_FMT_SBGGR10P || pixfmt == V4L2_PIX_FMT_SGBRG10P ||
pixfmt == V4L2_PIX_FMT_SGRBG10P || pixfmt == V4L2_PIX_FMT_SRGGB10P) {
shader = SHADER_DEBAYER;
} else if (pixfmt == V4L2_PIX_FMT_YUYV) {
shader = SHADER_YUV;
} else {
return NULL;
}
@@ -33,17 +43,22 @@ gles2_debayer_new(int format)
const GLchar *def[1] = { format_def };
GLuint shaders[] = {
gl_util_load_shader("/org/postmarketos/Megapixels/debayer.vert",
GL_VERTEX_SHADER,
NULL,
0),
gl_util_load_shader("/org/postmarketos/Megapixels/debayer.frag",
GL_FRAGMENT_SHADER,
def,
1),
};
char shader_vertex[64];
char shader_fragment[64];
snprintf(shader_vertex,
64,
"/org/postmarketos/Megapixels/%s.vert",
shader == SHADER_DEBAYER ? "debayer" : "yuv");
snprintf(shader_fragment,
64,
"/org/postmarketos/Megapixels/%s.frag",
shader == SHADER_DEBAYER ? "debayer" : "yuv");
GLuint shaders[] = {
gl_util_load_shader(shader_vertex, GL_VERTEX_SHADER, NULL, 0),
gl_util_load_shader(shader_fragment, GL_FRAGMENT_SHADER, def, 1),
};
printf("Using shader %s and %s\n", shader_vertex, shader_fragment);
GLuint program = gl_util_link_program(shaders, 2);
glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert");
glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord");
@@ -51,6 +66,7 @@ gles2_debayer_new(int format)
GLES2Debayer *self = malloc(sizeof(GLES2Debayer));
self->format = format;
self->shader = shader;
self->frame_buffer = frame_buffer;
self->program = program;
@@ -116,7 +132,9 @@ gles2_debayer_set_shading(GLES2Debayer *self,
multiply_matrices(xyzd65, XYZD65_to_sRGB, colormat);
glUniformMatrix3fv(
self->uniform_color_matrix, 1, GL_FALSE, colormat);
} else if (self->shader == SHADER_YUV) {
glUniformMatrix3fv(
self->uniform_color_matrix, 1, GL_FALSE, YUV_to_RGB);
} else {
glUniformMatrix3fv(
self->uniform_color_matrix, 1, GL_FALSE, IDENTITY);

View File

@@ -4,8 +4,12 @@
#include <assert.h>
#include <stdio.h>
#define SHADER_DEBAYER 1
#define SHADER_YUV 2
typedef struct {
int format;
int shader;
float forward_matrix[9];
GLuint frame_buffer;

View File

@@ -457,6 +457,9 @@ update_state(MPPipeline *pipeline, const mp_state_io *new_state)
float score = 0;
int area_preview =
state_io.preview_width * state_io.preview_height;
if (area_preview == 0) {
area_preview = 1280 * 720;
}
for (int m = 0; m < state_io.camera->num_modes; m++) {
float mscore = 0;
if (state_io.camera->modes[m]->rate > 29) {

View File

@@ -24,6 +24,14 @@ static float XYZD65_to_sRGB[] = {
// clang-format on
};
static float YUV_to_RGB[] = {
// clang-format off
0.299f, 0.587f, 0.114f,
-0.299f, -0.587f, 0.886f,
0.701f, -0.597f, -0.114f
// clang-format on
};
void print_matrix(float m[9]);
void multiply_matrices(const float a[9], const float b[9], float out[9]);