mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 14:56:36 +00:00
glcolorconvert: fix planar YUV download
- sample the u and v planes properly - output the correctly scaled u and v planes for different chroma block sizes
This commit is contained in:
parent
4fa5392e14
commit
df6967c274
1 changed files with 54 additions and 5 deletions
|
@ -237,15 +237,39 @@ static const gchar frag_RGB_to_PLANAR_YUV[] =
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"varying vec2 v_texcoord;\n"
|
"varying vec2 v_texcoord;\n"
|
||||||
"uniform sampler2D tex;\n"
|
"uniform sampler2D tex;\n"
|
||||||
"uniform float w, h;\n"
|
"uniform float width;\n"
|
||||||
|
"uniform float height;\n"
|
||||||
|
"uniform vec2 chroma_sampling;\n"
|
||||||
RGB_TO_YUV_COEFFICIENTS
|
RGB_TO_YUV_COEFFICIENTS
|
||||||
"void main(void) {\n"
|
"void main(void) {\n"
|
||||||
" float y, u, v;\n"
|
" float y, u, v;\n"
|
||||||
|
" vec4 uv_texel;\n"
|
||||||
" vec4 texel = texture2D(tex, v_texcoord).%c%c%c%c;\n"
|
" vec4 texel = texture2D(tex, v_texcoord).%c%c%c%c;\n"
|
||||||
" vec4 texel2 = texture2D(tex, v_texcoord * 2.0).%c%c%c%c;\n"
|
/* One u and v sample can be generated by a nxm sized block given by
|
||||||
|
* @chroma_sampling. The result is the average of all the values in the
|
||||||
|
* block computed with a rolling average.
|
||||||
|
*/
|
||||||
|
" vec2 size = vec2(width, height);\n"
|
||||||
|
" vec2 pos = v_texcoord * size;\n"
|
||||||
|
/* scale for chroma size */
|
||||||
|
" vec2 chroma_pos = v_texcoord * chroma_sampling * size;\n"
|
||||||
|
/* offset chroma to the center of the first texel in the block */
|
||||||
|
" chroma_pos -= clamp(chroma_sampling * 0.5 - 0.5, vec2(0.0), chroma_sampling);\n"
|
||||||
|
" if (chroma_pos.x < width && chroma_pos.y < height) {\n"
|
||||||
|
" for (int i = 0; i < int(chroma_sampling.x); i++) {\n"
|
||||||
|
" vec2 delta = vec2 (float(i), 0.0);\n"
|
||||||
|
" for (int j = 0; j < int(chroma_sampling.y); j++) {\n"
|
||||||
|
" int n = (i+1)*(j+1);\n"
|
||||||
|
" delta.y = float(j);\n"
|
||||||
|
" vec4 sample = texture2D(tex, (chroma_pos + delta) / size).%c%c%c%c;\n"
|
||||||
|
/* rolling average */
|
||||||
|
" uv_texel = (float(n-1) * uv_texel + sample) / float(n);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
" y = dot(texel.rgb, coeff1);\n"
|
" y = dot(texel.rgb, coeff1);\n"
|
||||||
" u = dot(texel2.rgb, coeff2);\n"
|
" u = dot(uv_texel.rgb, coeff2);\n"
|
||||||
" v = dot(texel2.rgb, coeff3);\n"
|
" v = dot(uv_texel.rgb, coeff3);\n"
|
||||||
" y += offset.x;\n"
|
" y += offset.x;\n"
|
||||||
" u += offset.y;\n"
|
" u += offset.y;\n"
|
||||||
" v += offset.z;\n"
|
" v += offset.z;\n"
|
||||||
|
@ -380,6 +404,7 @@ struct ConvertInfo
|
||||||
gfloat *cms_coeff1; /* r,y */
|
gfloat *cms_coeff1; /* r,y */
|
||||||
gfloat *cms_coeff2; /* g,u */
|
gfloat *cms_coeff2; /* g,u */
|
||||||
gfloat *cms_coeff3; /* b,v */
|
gfloat *cms_coeff3; /* b,v */
|
||||||
|
gfloat chroma_sampling[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstGLColorConvertPrivate
|
struct _GstGLColorConvertPrivate
|
||||||
|
@ -418,6 +443,8 @@ static void
|
||||||
gst_gl_color_convert_init (GstGLColorConvert * convert)
|
gst_gl_color_convert_init (GstGLColorConvert * convert)
|
||||||
{
|
{
|
||||||
convert->priv = GST_GL_COLOR_CONVERT_GET_PRIVATE (convert);
|
convert->priv = GST_GL_COLOR_CONVERT_GET_PRIVATE (convert);
|
||||||
|
|
||||||
|
gst_gl_color_convert_reset (convert);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -477,6 +504,9 @@ gst_gl_color_convert_reset (GstGLColorConvert * convert)
|
||||||
convert->priv->out_tex[i] = NULL;
|
convert->priv->out_tex[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convert->priv->convert_info.chroma_sampling[0] = 1.0f;
|
||||||
|
convert->priv->convert_info.chroma_sampling[1] = 1.0f;
|
||||||
|
|
||||||
if (convert->shader) {
|
if (convert->shader) {
|
||||||
gst_object_unref (convert->shader);
|
gst_object_unref (convert->shader);
|
||||||
convert->shader = NULL;
|
convert->shader = NULL;
|
||||||
|
@ -810,6 +840,7 @@ _RGB_to_YUV (GstGLColorConvert * convert)
|
||||||
struct ConvertInfo *info = &convert->priv->convert_info;
|
struct ConvertInfo *info = &convert->priv->convert_info;
|
||||||
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
|
GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
|
||||||
const gchar *in_format_str = gst_video_format_to_string (in_format);
|
const gchar *in_format_str = gst_video_format_to_string (in_format);
|
||||||
|
GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
|
||||||
gchar *pixel_order = _RGB_pixel_order (in_format_str, "rgba");
|
gchar *pixel_order = _RGB_pixel_order (in_format_str, "rgba");
|
||||||
const gchar *alpha;
|
const gchar *alpha;
|
||||||
|
|
||||||
|
@ -818,7 +849,7 @@ _RGB_to_YUV (GstGLColorConvert * convert)
|
||||||
|
|
||||||
info->shader_tex_names[0] = "tex";
|
info->shader_tex_names[0] = "tex";
|
||||||
|
|
||||||
switch (GST_VIDEO_INFO_FORMAT (&convert->out_info)) {
|
switch (out_format) {
|
||||||
case GST_VIDEO_FORMAT_AYUV:
|
case GST_VIDEO_FORMAT_AYUV:
|
||||||
alpha = _is_RGBx (in_format) ? "1.0" : "texel.a";
|
alpha = _is_RGBx (in_format) ? "1.0" : "texel.a";
|
||||||
info->frag_prog = g_strdup_printf (frag_RGB_to_AYUV, pixel_order[0],
|
info->frag_prog = g_strdup_printf (frag_RGB_to_AYUV, pixel_order[0],
|
||||||
|
@ -834,6 +865,17 @@ _RGB_to_YUV (GstGLColorConvert * convert)
|
||||||
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
|
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
|
||||||
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
|
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
|
||||||
info->out_n_textures = 3;
|
info->out_n_textures = 3;
|
||||||
|
if (out_format == GST_VIDEO_FORMAT_Y444) {
|
||||||
|
info->chroma_sampling[0] = info->chroma_sampling[1] = 1.0f;
|
||||||
|
} else if (out_format == GST_VIDEO_FORMAT_Y42B) {
|
||||||
|
info->chroma_sampling[0] = 2.0f;
|
||||||
|
info->chroma_sampling[1] = 1.0f;
|
||||||
|
} else if (out_format == GST_VIDEO_FORMAT_Y41B) {
|
||||||
|
info->chroma_sampling[0] = 4.0f;
|
||||||
|
info->chroma_sampling[1] = 1.0f;
|
||||||
|
} else {
|
||||||
|
info->chroma_sampling[0] = info->chroma_sampling[1] = 2.0f;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_YUY2:
|
case GST_VIDEO_FORMAT_YUY2:
|
||||||
info->frag_prog = g_strdup_printf (frag_RGB_to_YUY2_UYVY,
|
info->frag_prog = g_strdup_printf (frag_RGB_to_YUY2_UYVY,
|
||||||
|
@ -1053,6 +1095,13 @@ _init_convert (GstGLColorConvert * convert)
|
||||||
|
|
||||||
gst_gl_shader_set_uniform_1f (convert->shader, "width",
|
gst_gl_shader_set_uniform_1f (convert->shader, "width",
|
||||||
GST_VIDEO_INFO_WIDTH (&convert->in_info));
|
GST_VIDEO_INFO_WIDTH (&convert->in_info));
|
||||||
|
gst_gl_shader_set_uniform_1f (convert->shader, "height",
|
||||||
|
GST_VIDEO_INFO_HEIGHT (&convert->in_info));
|
||||||
|
|
||||||
|
if (info->chroma_sampling[0] > 0.0f && info->chroma_sampling[1] > 0.0f) {
|
||||||
|
gst_gl_shader_set_uniform_2fv (convert->shader, "chroma_sampling", 1,
|
||||||
|
info->chroma_sampling);
|
||||||
|
}
|
||||||
|
|
||||||
gst_gl_context_clear_shader (convert->context);
|
gst_gl_context_clear_shader (convert->context);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue