mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
libgstgl: run a custom shader to convert YUV to RGB on mac and ios
When GL_APPLE_ycbcr_422 is available, run a custom shader to convert GL_TEXTURE_RECTANGLE textures from YUV to RGB. See https://www.opengl.org/registry/specs/APPLE/ycbcr_422.txt
This commit is contained in:
parent
8734abb1ce
commit
3655e8b8bc
1 changed files with 104 additions and 67 deletions
|
@ -136,6 +136,23 @@ static const gchar frag_REORDER[] =
|
|||
" gl_FragColor = vec4(t.%c, t.%c, t.%c, t.%c);\n"
|
||||
"}";
|
||||
|
||||
static const gchar frag_APPLE_YUV_TO_RGB[] =
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"uniform float width;\n"
|
||||
"uniform float height;\n"
|
||||
"uniform sampler2DRect tex;\n"
|
||||
"uniform vec2 tex_scale0;\n"
|
||||
"uniform vec2 tex_scale1;\n"
|
||||
"uniform vec2 tex_scale2;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" vec4 t = texture2DRect(tex, v_texcoord * vec2(width, height) * tex_scale0);\n"
|
||||
" gl_FragColor = vec4(t.%c, t.%c, t.%c, t.%c);\n"
|
||||
"}";
|
||||
|
||||
/* GRAY16 to RGB conversion
|
||||
* data transfered as GL_LUMINANCE_ALPHA then convert back to GRAY16
|
||||
* high byte weight as : 255*256/65535
|
||||
|
@ -816,77 +833,97 @@ _YUV_to_RGB (GstGLColorConvert * convert)
|
|||
gst_gl_context_check_feature (convert->context, "GL_EXT_texture_rg")
|
||||
|| gst_gl_context_check_feature (convert->context, "GL_ARB_texture_rg");
|
||||
#endif
|
||||
gboolean apple_ycbcr = gst_gl_context_check_feature (convert->context,
|
||||
"GL_APPLE_ycbcr_422");
|
||||
gboolean in_tex_rectangular = FALSE;
|
||||
|
||||
GstMemory *memory = gst_buffer_peek_memory (convert->inbuf, 0);
|
||||
if (gst_is_gl_memory (memory)) {
|
||||
in_tex_rectangular =
|
||||
((GstGLMemory *) memory)->tex_target == GL_TEXTURE_RECTANGLE;
|
||||
}
|
||||
|
||||
info->out_n_textures = 1;
|
||||
|
||||
switch (GST_VIDEO_INFO_FORMAT (&convert->in_info)) {
|
||||
case GST_VIDEO_FORMAT_AYUV:
|
||||
info->frag_prog = g_strdup_printf (frag_AYUV_to_RGB, pixel_order[0],
|
||||
pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "tex";
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
case GST_VIDEO_FORMAT_Y444:
|
||||
case GST_VIDEO_FORMAT_Y42B:
|
||||
case GST_VIDEO_FORMAT_Y41B:
|
||||
info->frag_prog = g_strdup_printf (frag_PLANAR_YUV_to_RGB, pixel_order[0],
|
||||
pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 3;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "Utex";
|
||||
info->shader_tex_names[2] = "Vtex";
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_YV12:
|
||||
info->frag_prog = g_strdup_printf (frag_PLANAR_YUV_to_RGB, pixel_order[0],
|
||||
pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 3;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "Vtex";
|
||||
info->shader_tex_names[2] = "Utex";
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_YUY2:
|
||||
{
|
||||
char uv_val = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_YUY2_UYVY_to_RGB, 'r', uv_val,
|
||||
uv_val, 'g', 'a', pixel_order[0], pixel_order[1], pixel_order[2],
|
||||
pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
break;
|
||||
if (in_tex_rectangular && apple_ycbcr
|
||||
&& gst_buffer_n_memory (convert->inbuf) == 1) {
|
||||
info->frag_prog =
|
||||
g_strdup_printf (frag_APPLE_YUV_TO_RGB, pixel_order[0], pixel_order[1],
|
||||
pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "tex";
|
||||
} else {
|
||||
switch (GST_VIDEO_INFO_FORMAT (&convert->in_info)) {
|
||||
case GST_VIDEO_FORMAT_AYUV:
|
||||
info->frag_prog = g_strdup_printf (frag_AYUV_to_RGB, pixel_order[0],
|
||||
pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "tex";
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
case GST_VIDEO_FORMAT_Y444:
|
||||
case GST_VIDEO_FORMAT_Y42B:
|
||||
case GST_VIDEO_FORMAT_Y41B:
|
||||
info->frag_prog =
|
||||
g_strdup_printf (frag_PLANAR_YUV_to_RGB, pixel_order[0],
|
||||
pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 3;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "Utex";
|
||||
info->shader_tex_names[2] = "Vtex";
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_YV12:
|
||||
info->frag_prog =
|
||||
g_strdup_printf (frag_PLANAR_YUV_to_RGB, pixel_order[0],
|
||||
pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 3;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "Vtex";
|
||||
info->shader_tex_names[2] = "Utex";
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_YUY2:
|
||||
{
|
||||
char uv_val = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_YUY2_UYVY_to_RGB, 'r', uv_val,
|
||||
uv_val, 'g', 'a', pixel_order[0], pixel_order[1], pixel_order[2],
|
||||
pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
{
|
||||
char val2 = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_NV12_NV21_to_RGB, 'r', val2,
|
||||
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 2;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "UVtex";
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_NV21:
|
||||
{
|
||||
char val2 = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_NV12_NV21_to_RGB, val2, 'r',
|
||||
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 2;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "UVtex";
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_UYVY:
|
||||
{
|
||||
char y_val = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_YUY2_UYVY_to_RGB, y_val, 'g',
|
||||
'g', 'r', 'b', pixel_order[0], pixel_order[1], pixel_order[2],
|
||||
pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
{
|
||||
char val2 = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_NV12_NV21_to_RGB, 'r', val2,
|
||||
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 2;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "UVtex";
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_NV21:
|
||||
{
|
||||
char val2 = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_NV12_NV21_to_RGB, val2, 'r',
|
||||
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||
info->in_n_textures = 2;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
info->shader_tex_names[1] = "UVtex";
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_UYVY:
|
||||
{
|
||||
char y_val = texture_rg ? 'g' : 'a';
|
||||
info->frag_prog = g_strdup_printf (frag_YUY2_UYVY_to_RGB, y_val, 'g',
|
||||
'g', 'r', 'b', pixel_order[0], pixel_order[1], pixel_order[2],
|
||||
pixel_order[3]);
|
||||
info->in_n_textures = 1;
|
||||
info->shader_tex_names[0] = "Ytex";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (gst_video_colorimetry_matches (&convert->in_info.colorimetry,
|
||||
|
|
Loading…
Reference in a new issue