Skip to content

Commit

Permalink
gl: add support for GBR and GBRA
Browse files Browse the repository at this point in the history
example pipeline:
gst-launch-1.0 videotestsrc ! video/x-raw,format=GBR ! glimagesink

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/789>
  • Loading branch information
xhaihao authored and GStreamer Merge Bot committed Sep 9, 2020
1 parent f54ef6c commit 9ccc3db
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 16 deletions.
20 changes: 10 additions & 10 deletions docs/plugins/gst_plugins_cache.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions gst-libs/gst/gl/glprototypes/gstgl_gles2compat.h
Expand Up @@ -42,6 +42,9 @@ G_BEGIN_DECLS
#ifndef GL_COLOR_ATTACHMENT2
#define GL_COLOR_ATTACHMENT2 0x8CE2
#endif
#ifndef GL_COLOR_ATTACHMENT3
#define GL_COLOR_ATTACHMENT3 0x8CE3
#endif
#ifndef GL_TEXTURE_ENV
#define GL_TEXTURE_ENV 0
#endif
Expand Down
214 changes: 210 additions & 4 deletions gst-libs/gst/gl/gstglcolorconvert.c
Expand Up @@ -129,6 +129,7 @@ static const gfloat from_rgb_bt709_vcoeff[] = {0.440654f, -0.400285f, -0.040370f
"uniform vec2 tex_scale0;\n" \
"uniform vec2 tex_scale1;\n" \
"uniform vec2 tex_scale2;\n" \
"uniform vec2 tex_scale3;\n" \
"uniform float width;\n" \
"uniform float height;\n" \
"uniform float poffset_x;\n" \
Expand Down Expand Up @@ -391,6 +392,57 @@ static const struct shader_templ templ_RGB_to_YUY2_UYVY =
GST_GL_TEXTURE_TARGET_2D
};

/* PLANAR RGB to PACKED RGB conversion */
static const gchar templ_PLANAR_RGB_to_PACKED_RGB_BODY[] =
"vec4 rgba;\n"
"rgba.r = texture2D(Rtex, texcoord * tex_scale0).r;\n"
"rgba.g = texture2D(Gtex, texcoord * tex_scale1).r;\n"
"rgba.b = texture2D(Btex, texcoord * tex_scale2).r;\n"
"%s\n" /* alpha channel */
"gl_FragColor=vec4(rgba.%c,rgba.%c,rgba.%c,rgba.%c);\n";

static const struct shader_templ templ_PLANAR_RGB_to_PACKED_RGB =
{ NULL,
DEFAULT_UNIFORMS "uniform sampler2D Rtex, Gtex, Btex, Atex;\n",
{ NULL, },
GST_GL_TEXTURE_TARGET_2D
};

/* PACKED RGB to PLANAR RGB conversion */
static const gchar templ_PACKED_RGB_to_PLANAR_RGB_BODY[] =
"vec4 rgba;\n"
"rgba = texture2D(tex, texcoord).%c%c%c%c;\n"
"gl_FragData[0] = vec4(rgba.r, 0, 0, 1.0);\n"
"gl_FragData[1] = vec4(rgba.g, 0, 0, 1.0);\n"
"gl_FragData[2] = vec4(rgba.b, 0, 0, 1.0);\n"
"%s\n";

static const struct shader_templ templ_PACKED_RGB_to_PLANAR_RGB =
{ NULL,
DEFAULT_UNIFORMS "uniform sampler2D tex;\n",
{ NULL, },
GST_GL_TEXTURE_TARGET_2D
};

/* PLANAR RGB to PLANAR RGB conversion */
static const gchar templ_PLANAR_RGB_to_PLANAR_RGB_BODY[] =
"vec4 rgba;\n"
"rgba.r = texture2D(Rtex, texcoord * tex_scale0).r;\n"
"rgba.g = texture2D(Gtex, texcoord * tex_scale1).r;\n"
"rgba.b = texture2D(Btex, texcoord * tex_scale2).r;\n"
"%s\n" /* alpha channel */
"gl_FragData[0] = vec4(rgba.%c, 0, 0, 1.0);\n"
"gl_FragData[1] = vec4(rgba.%c, 0, 0, 1.0);\n"
"gl_FragData[2] = vec4(rgba.%c, 0, 0, 1.0);\n"
"%s\n";

static const struct shader_templ templ_PLANAR_RGB_to_PLANAR_RGB =
{ NULL,
DEFAULT_UNIFORMS "uniform sampler2D Rtex, Gtex, Btex, Atex;\n",
{ NULL, },
GST_GL_TEXTURE_TARGET_2D
};

static const gchar text_vertex_shader[] =
"attribute vec4 a_position; \n"
"attribute vec2 a_texcoord; \n"
Expand Down Expand Up @@ -912,8 +964,8 @@ _init_supported_formats (GstGLContext * context, gboolean output,

/* Always supported input formats or output with multiple draw buffers */
if (!output || (!context || context->gl_vtable->DrawBuffers))
_append_value_string_list (supported_formats, "Y444", "I420", "YV12",
"Y42B", "Y41B", "NV12", "NV21", "NV16", "NV61", NULL);
_append_value_string_list (supported_formats, "GBRA", "GBR", "Y444",
"I420", "YV12", "Y42B", "Y41B", "NV12", "NV21", "NV16", "NV61", NULL);

/* Requires reading from a RG/LA framebuffer... */
if (!context || (USING_GLES3 (context) || USING_OPENGL (context)))
Expand Down Expand Up @@ -1411,6 +1463,26 @@ _is_RGBx (GstVideoFormat v_format)
}
}

static inline gboolean
_is_planar_rgb (GstVideoFormat v_format)
{
switch (v_format) {
case GST_VIDEO_FORMAT_GBR:
case GST_VIDEO_FORMAT_GBR_10BE:
case GST_VIDEO_FORMAT_GBR_10LE:
case GST_VIDEO_FORMAT_GBRA:
case GST_VIDEO_FORMAT_GBRA_10BE:
case GST_VIDEO_FORMAT_GBRA_10LE:
case GST_VIDEO_FORMAT_GBR_12BE:
case GST_VIDEO_FORMAT_GBR_12LE:
case GST_VIDEO_FORMAT_GBRA_12BE:
case GST_VIDEO_FORMAT_GBRA_12LE:
return TRUE;
default:
return FALSE;
}
}

static inline gchar
_index_to_shader_swizzle (int idx)
{
Expand Down Expand Up @@ -1572,15 +1644,129 @@ _get_n_textures (GstVideoFormat v_format)
case GST_VIDEO_FORMAT_Y42B:
case GST_VIDEO_FORMAT_Y41B:
case GST_VIDEO_FORMAT_YV12:
case GST_VIDEO_FORMAT_GBR:
return 3;
case GST_VIDEO_FORMAT_GBRA:
return 4;
default:
g_assert_not_reached ();
return 0;
}
}

static void
_RGB_to_RGB (GstGLColorConvert * convert)
_PLANAR_RGB_to_PLANAR_RGB (GstGLColorConvert * convert)
{
struct ConvertInfo *info = &convert->priv->convert_info;
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
const gchar *in_format_str = gst_video_format_to_string (in_format);
GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
const gchar *out_format_str = gst_video_format_to_string (out_format);
gchar *pixel_order = _RGB_pixel_order (in_format_str, out_format_str);
const gchar *in_alpha = NULL;
gchar *out_alpha = NULL;

info->frag_prog = NULL;

if (GST_VIDEO_INFO_HAS_ALPHA (&convert->in_info)) {
in_alpha = "rgba.a = texture2D(Atex, texcoord * tex_scale3).r;";
info->shader_tex_names[0] = "Rtex";
info->shader_tex_names[1] = "Gtex";
info->shader_tex_names[2] = "Btex";
info->shader_tex_names[3] = "Atex";
} else {
in_alpha = "rgba.a = 1.0;";
info->shader_tex_names[0] = "Rtex";
info->shader_tex_names[1] = "Gtex";
info->shader_tex_names[2] = "Btex";
}

if (GST_VIDEO_INFO_HAS_ALPHA (&convert->out_info)) {
out_alpha =
g_strdup_printf ("gl_FragData[3] = vec4(rgba.%c, 0, 0, 1.0);",
pixel_order[3]);
info->out_n_textures = 4;
} else {
out_alpha = g_strdup_printf ("\n");
info->out_n_textures = 3;
}

info->templ = &templ_PLANAR_RGB_to_PLANAR_RGB;
info->frag_body =
g_strdup_printf (templ_PLANAR_RGB_to_PLANAR_RGB_BODY, in_alpha,
pixel_order[0], pixel_order[1], pixel_order[2], out_alpha);

g_free (out_alpha);
g_free (pixel_order);
}

static void
_PLANAR_RGB_to_PACKED_RGB (GstGLColorConvert * convert)
{
struct ConvertInfo *info = &convert->priv->convert_info;
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
const gchar *in_format_str = gst_video_format_to_string (in_format);
GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
const gchar *out_format_str = gst_video_format_to_string (out_format);
gchar *pixel_order = _RGB_pixel_order (in_format_str, out_format_str);
const gchar *alpha = NULL;

info->frag_prog = NULL;

if (GST_VIDEO_INFO_HAS_ALPHA (&convert->in_info)) {
alpha = "rgba.a = texture2D(Atex, texcoord * tex_scale3).r;";
info->shader_tex_names[0] = "Rtex";
info->shader_tex_names[1] = "Gtex";
info->shader_tex_names[2] = "Btex";
info->shader_tex_names[3] = "Atex";
} else {
alpha = "rgba.a = 1.0;";
info->shader_tex_names[0] = "Rtex";
info->shader_tex_names[1] = "Gtex";
info->shader_tex_names[2] = "Btex";
}

info->out_n_textures = 1;

info->templ = &templ_PLANAR_RGB_to_PACKED_RGB;
info->frag_body = g_strdup_printf (templ_PLANAR_RGB_to_PACKED_RGB_BODY, alpha,
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);

g_free (pixel_order);
}

static void
_PACKED_RGB_to_PLANAR_RGB (GstGLColorConvert * convert)
{
struct ConvertInfo *info = &convert->priv->convert_info;
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
const gchar *in_format_str = gst_video_format_to_string (in_format);
GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
const gchar *out_format_str = gst_video_format_to_string (out_format);
gchar *pixel_order = _RGB_pixel_order (in_format_str, out_format_str);
const gchar *alpha;

info->frag_prog = NULL;
info->shader_tex_names[0] = "tex";

if (GST_VIDEO_INFO_HAS_ALPHA (&convert->out_info)) {
alpha = "gl_FragData[3] = vec4(rgba.a, 0, 0, 1.0);";
info->out_n_textures = 4;
} else {
alpha = "";
info->out_n_textures = 3;
}

info->templ = &templ_PACKED_RGB_to_PLANAR_RGB;
info->frag_body = g_strdup_printf (templ_PACKED_RGB_to_PLANAR_RGB_BODY,
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3], alpha);
info->shader_tex_names[0] = "tex";

g_free (pixel_order);
}

static void
_PACKED_RGB_to_PACKED_RGB (GstGLColorConvert * convert)
{
struct ConvertInfo *info = &convert->priv->convert_info;
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
Expand Down Expand Up @@ -1610,6 +1796,25 @@ _RGB_to_RGB (GstGLColorConvert * convert)
g_free (pixel_order);
}

static void
_RGB_to_RGB (GstGLColorConvert * convert)
{
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);

if (_is_planar_rgb (in_format)) {
if (_is_planar_rgb (out_format))
_PLANAR_RGB_to_PLANAR_RGB (convert);
else
_PLANAR_RGB_to_PACKED_RGB (convert);
} else {
if (_is_planar_rgb (out_format))
_PACKED_RGB_to_PLANAR_RGB (convert);
else
_PACKED_RGB_to_PACKED_RGB (convert);
}
}

static void
_YUV_to_RGB (GstGLColorConvert * convert)
{
Expand Down Expand Up @@ -2699,7 +2904,8 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
GLenum multipleRT[] = {
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3
};

gl = context->gl_vtable;
Expand Down
2 changes: 1 addition & 1 deletion gst-libs/gst/gl/gstglcolorconvert.h
Expand Up @@ -100,7 +100,7 @@ struct _GstGLColorConvertClass
* The currently supported formats that can be converted
*/
#define GST_GL_COLOR_CONVERT_FORMATS "{ RGBA, RGB, RGBx, BGR, BGRx, BGRA, xRGB, " \
"xBGR, ARGB, ABGR, Y444, I420, YV12, Y42B, " \
"xBGR, ARGB, ABGR, GBRA, GBR, Y444, I420, YV12, Y42B, " \
"Y41B, NV12, NV21, NV16, NV61, YUY2, UYVY, Y210, AYUV, " \
"VUYA, Y410, GRAY8, GRAY16_LE, GRAY16_BE, " \
"RGB16, BGR16, ARGB64 " \
Expand Down
3 changes: 3 additions & 0 deletions gst-libs/gst/gl/gstglformat.c
Expand Up @@ -220,6 +220,9 @@ gst_gl_format_from_video_info (GstGLContext * context, GstVideoInfo * vinfo,
case GST_VIDEO_FORMAT_Y412_LE:
case GST_VIDEO_FORMAT_Y412_BE:
return GST_GL_RGBA16;
case GST_VIDEO_FORMAT_GBR:
case GST_VIDEO_FORMAT_GBRA:
return GST_GL_R8;
default:
n_plane_components = 4;
g_assert_not_reached ();
Expand Down
2 changes: 1 addition & 1 deletion gst-libs/gst/gl/gstglmemory.h
Expand Up @@ -62,7 +62,7 @@ GType gst_gl_memory_allocator_get_type(void);
* List of video formats that are supported by #GstGLMemory
*/
#define GST_GL_MEMORY_VIDEO_FORMATS_STR \
"{ RGBA, BGRA, RGBx, BGRx, ARGB, ABGR, xRGB, xBGR, RGB, BGR, RGB16, BGR16, " \
"{ RGBA, BGRA, RGBx, BGRx, ARGB, ABGR, xRGB, xBGR, GBRA, GBR, RGB, BGR, RGB16, BGR16, " \
"AYUV, VUYA, Y410, I420, YV12, NV12, NV21, NV16, NV61, YUY2, UYVY, Y210, Y41B, " \
"Y42B, Y444, GRAY8, GRAY16_LE, GRAY16_BE, ARGB64" \
GST_GL_MEMORY_VIDEO_EXT_FORMATS "}"
Expand Down

0 comments on commit 9ccc3db

Please sign in to comment.