From afdc81fe4d61dc407fa5191a8575f61b02606490 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 12 Jan 2016 18:21:50 +1100 Subject: [PATCH] glvideomixer: implement glBlendFunc and glBlendEquation Allows more blending options than just A over B e.g. frame comparisons are now possible. glvideomixer name=m sink_0::zorder=0 sink_1::zorder=1 sink_1::blend-equation-rgb={subtract,reverse-subtract} sink_1::blend-function-src-rgb=src-color sink_1::blend-function-dst-rgb=dst-color ! glimagesinkelement videotestsrc pattern=checkers-4 ! m.sink_0 videotestsrc pattern=checkers-8 ! m.sink_1 --- ext/gl/gstglvideomixer.c | 452 +++++++++++++++++++++++++++++++++++++-- ext/gl/gstglvideomixer.h | 60 ++++++ 2 files changed, 500 insertions(+), 12 deletions(-) diff --git a/ext/gl/gstglvideomixer.c b/ext/gl/gstglvideomixer.c index 9376793be2..f372f0cfb1 100644 --- a/ext/gl/gstglvideomixer.c +++ b/ext/gl/gstglvideomixer.c @@ -71,6 +71,72 @@ gst_gl_video_mixer_background_get_type (void) return mixer_background_type; } +#define GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION (gst_gl_video_mixer_blend_equation_get_type()) +static GType +gst_gl_video_mixer_blend_equation_get_type (void) +{ + static GType mixer_blend_equation_type = 0; + + static const GEnumValue mixer_blend_equations[] = { + {GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD, "Add", "add"}, + {GST_GL_VIDEO_MIXER_BLEND_EQUATION_SUBTRACT, "Subtract", "subtract"}, + {GST_GL_VIDEO_MIXER_BLEND_EQUATION_REVERSE_SUBTRACT, "Reverse Subtract", + "reverse-subtract"}, + {0, NULL, NULL}, + }; + + if (!mixer_blend_equation_type) { + mixer_blend_equation_type = + g_enum_register_static ("GstGLVideoMixerBlendEquation", + mixer_blend_equations); + } + return mixer_blend_equation_type; +} + +#define GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION (gst_gl_video_mixer_blend_function_get_type()) +static GType +gst_gl_video_mixer_blend_function_get_type (void) +{ + static GType mixer_blend_function_type = 0; + + static const GEnumValue mixer_blend_funcs[] = { + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ZERO, "Zero", "zero"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE, "One", "one"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_COLOR, "Source Color", "src-color"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_COLOR, + "One Minus Source Color", "one-minus-src-color"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_COLOR, "Destination Color", + "dst-color"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_COLOR, + "One Minus Destination Color", "one-minus-dst-color"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA, "Source Alpha", "src-alpha"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA, + "One Minus Source Alpha", "one-minus-src-alpha"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_ALPHA, "Destination Alpha", + "dst-alpha"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_ALPHA, + "One Minus Destination Alpha", "one-minus-dst-alpha"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_COLOR, "Constant Color", + "constant-color"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR, + "One Minus Constant Color", "one-minus-contant-color"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA, "Constant Alpha", + "constant-alpha"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR, + "One Minus Constant Alpha", "one-minus-contant-alpha"}, + {GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE, + "Source Alpha Saturate", "src-alpha-saturate"}, + {0, NULL, NULL}, + }; + + if (!mixer_blend_function_type) { + mixer_blend_function_type = + g_enum_register_static ("GstGLVideoMixerBlendFunction", + mixer_blend_funcs); + } + return mixer_blend_function_type; +} + typedef struct _GstGLMixerControlBindingProxy GstGLMixerControlBindingProxy; typedef struct _GstGLMixerControlBindingProxyClass GstGLMixerControlBindingProxyClass; @@ -223,6 +289,12 @@ gst_gl_mixer_control_binding_proxy_new (GstObject * object, #define DEFAULT_PAD_ALPHA 1.0 #define DEFAULT_PAD_ZORDER 0 #define DEFAULT_PAD_IGNORE_EOS FALSE +#define DEFAULT_PAD_BLEND_EQUATION_RGB GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD +#define DEFAULT_PAD_BLEND_EQUATION_ALPHA GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD +#define DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA +#define DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA +#define DEFAULT_PAD_BLEND_FUNCTION_DST_RGB GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA +#define DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA enum { @@ -232,6 +304,16 @@ enum PROP_INPUT_WIDTH, PROP_INPUT_HEIGHT, PROP_INPUT_ALPHA, + PROP_INPUT_BLEND_EQUATION_RGB, + PROP_INPUT_BLEND_EQUATION_ALPHA, + PROP_INPUT_BLEND_FUNCTION_SRC_RGB, + PROP_INPUT_BLEND_FUNCTION_SRC_ALPHA, + PROP_INPUT_BLEND_FUNCTION_DST_RGB, + PROP_INPUT_BLEND_FUNCTION_DST_ALPHA, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_RED, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_GREEN, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_BLUE, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA, PROP_INPUT_ZORDER, PROP_INPUT_IGNORE_EOS, }; @@ -299,6 +381,71 @@ gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass) g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0, DEFAULT_PAD_ALPHA, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_EQUATION_RGB, + g_param_spec_enum ("blend-equation-rgb", "Blend Equation RGB", + "Blend Equation for RGB", + GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION, + DEFAULT_PAD_BLEND_EQUATION_RGB, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_EQUATION_ALPHA, + g_param_spec_enum ("blend-equation-alpha", "Blend Equation Alpha", + "Blend Equation for Alpha", GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION, + DEFAULT_PAD_BLEND_EQUATION_ALPHA, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_SRC_RGB, + g_param_spec_enum ("blend-function-src-rgb", "Blend Function Source RGB", + "Blend Function for Source RGB", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_SRC_ALPHA, + g_param_spec_enum ("blend-function-src-alpha", + "Blend Function Source Alpha", "Blend Function for Source Alpha", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_DST_RGB, + g_param_spec_enum ("blend-function-dst-rgb", + "Blend Function Destination RGB", + "Blend Function for Destination RGB", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_DST_RGB, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_DST_ALPHA, + g_param_spec_enum ("blend-function-dst-alpha", + "Blend Function Destination Alpha", + "Blend Function for Destiniation Alpha", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_RED, + g_param_spec_double ("blend-constant-color-red", + "Blend Constant Color Red", "Blend Constant Color Red", 0.0, 1.0, 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_GREEN, + g_param_spec_double ("blend-constant-color-green", + "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0, + 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_BLUE, + g_param_spec_double ("blend-constant-color-blue", + "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0, + 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA, + g_param_spec_double ("blend-constant-color-alpha", + "Blend Constant Color Alpha", "Blend Constant Color Alpha", 0.0, 1.0, + 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); } static void @@ -336,15 +483,25 @@ _create_video_mixer_input (GstGLMixerBin * self, GstPad * mixer_pad) } #define ADD_PROXY_CONTROL_BINDING(prop) \ cb = gst_gl_mixer_control_binding_proxy_new (GST_OBJECT (mixer_pad), \ - G_STRINGIFY (prop), GST_OBJECT (input), G_STRINGIFY (prop)); \ + prop, GST_OBJECT (input), prop); \ gst_object_add_control_binding (GST_OBJECT (mixer_pad), cb) - ADD_PROXY_CONTROL_BINDING (zorder); - ADD_PROXY_CONTROL_BINDING (xpos); - ADD_PROXY_CONTROL_BINDING (ypos); - ADD_PROXY_CONTROL_BINDING (width); - ADD_PROXY_CONTROL_BINDING (height); - ADD_PROXY_CONTROL_BINDING (alpha); + ADD_PROXY_CONTROL_BINDING ("zorder"); + ADD_PROXY_CONTROL_BINDING ("xpos"); + ADD_PROXY_CONTROL_BINDING ("ypos"); + ADD_PROXY_CONTROL_BINDING ("width"); + ADD_PROXY_CONTROL_BINDING ("height"); + ADD_PROXY_CONTROL_BINDING ("alpha"); + ADD_PROXY_CONTROL_BINDING ("blend-equation-rgb"); + ADD_PROXY_CONTROL_BINDING ("blend-equation-alpha"); + ADD_PROXY_CONTROL_BINDING ("blend-function-src-rgb"); + ADD_PROXY_CONTROL_BINDING ("blend-function-src-alpha"); + ADD_PROXY_CONTROL_BINDING ("blend-function-dst-rgb"); + ADD_PROXY_CONTROL_BINDING ("blend-function-dst-alpha"); + ADD_PROXY_CONTROL_BINDING ("blend-constant-color-red"); + ADD_PROXY_CONTROL_BINDING ("blend-constant-color-green"); + ADD_PROXY_CONTROL_BINDING ("blend-constant-color-blue"); + ADD_PROXY_CONTROL_BINDING ("blend-constant-color-alpha"); #undef ADD_PROXY_CONTROL_BINDING @@ -534,6 +691,17 @@ struct _GstGLVideoMixerPad gint width, height; gdouble alpha; + GstGLVideoMixerBlendEquation blend_equation_rgb; + GstGLVideoMixerBlendEquation blend_equation_alpha; + GstGLVideoMixerBlendFunction blend_function_src_rgb; + GstGLVideoMixerBlendFunction blend_function_src_alpha; + GstGLVideoMixerBlendFunction blend_function_dst_rgb; + GstGLVideoMixerBlendFunction blend_function_dst_alpha; + gdouble blend_constant_color_red; + gdouble blend_constant_color_green; + gdouble blend_constant_color_blue; + gdouble blend_constant_color_alpha; + gboolean geometry_change; GLuint vertex_buffer; }; @@ -559,13 +727,29 @@ enum PROP_PAD_YPOS, PROP_PAD_WIDTH, PROP_PAD_HEIGHT, - PROP_PAD_ALPHA + PROP_PAD_ALPHA, + PROP_PAD_BLEND_EQUATION_RGB, + PROP_PAD_BLEND_EQUATION_ALPHA, + PROP_PAD_BLEND_FUNCTION_SRC_RGB, + PROP_PAD_BLEND_FUNCTION_SRC_ALPHA, + PROP_PAD_BLEND_FUNCTION_DST_RGB, + PROP_PAD_BLEND_FUNCTION_DST_ALPHA, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA, }; static void gst_gl_video_mixer_pad_init (GstGLVideoMixerPad * pad) { - pad->alpha = 1.0; + pad->alpha = DEFAULT_PAD_ALPHA; + pad->blend_equation_rgb = DEFAULT_PAD_BLEND_EQUATION_RGB; + pad->blend_equation_alpha = DEFAULT_PAD_BLEND_EQUATION_ALPHA; + pad->blend_function_src_rgb = DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB; + pad->blend_function_src_alpha = DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA; + pad->blend_function_dst_rgb = DEFAULT_PAD_BLEND_FUNCTION_DST_RGB; + pad->blend_function_dst_alpha = DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA; } static void @@ -596,6 +780,71 @@ gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass) g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0, DEFAULT_PAD_ALPHA, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_EQUATION_RGB, + g_param_spec_enum ("blend-equation-rgb", "Blend Equation RGB", + "Blend Equation for RGB", + GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION, + DEFAULT_PAD_BLEND_EQUATION_RGB, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_EQUATION_ALPHA, + g_param_spec_enum ("blend-equation-alpha", "Blend Equation Alpha", + "Blend Equation for Alpha", GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION, + DEFAULT_PAD_BLEND_EQUATION_ALPHA, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_SRC_RGB, + g_param_spec_enum ("blend-function-src-rgb", "Blend Function Source RGB", + "Blend Function for Source RGB", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_SRC_ALPHA, + g_param_spec_enum ("blend-function-src-alpha", + "Blend Function Source Alpha", "Blend Function for Source Alpha", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_DST_RGB, + g_param_spec_enum ("blend-function-dst-rgb", + "Blend Function Destination RGB", + "Blend Function for Destination RGB", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_DST_RGB, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_INPUT_BLEND_FUNCTION_DST_ALPHA, + g_param_spec_enum ("blend-function-dst-alpha", + "Blend Function Destination Alpha", + "Blend Function for Destiniation Alpha", + GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION, + DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED, + g_param_spec_double ("blend-constant-color-red", + "Blend Constant Color Red", "Blend Constant Color Red", 0.0, 1.0, 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN, + g_param_spec_double ("blend-constant-color-green", + "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0, + 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE, + g_param_spec_double ("blend-constant-color-blue", + "Blend Constant Color Green", "Blend Constant Color Green", 0.0, 1.0, + 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA, + g_param_spec_double ("blend-constant-color-alpha", + "Blend Constant Color Alpha", "Blend Constant Color Alpha", 0.0, 1.0, + 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); } static void @@ -620,6 +869,36 @@ gst_gl_video_mixer_pad_get_property (GObject * object, guint prop_id, case PROP_PAD_ALPHA: g_value_set_double (value, pad->alpha); break; + case PROP_PAD_BLEND_EQUATION_RGB: + g_value_set_enum (value, pad->blend_equation_rgb); + break; + case PROP_PAD_BLEND_EQUATION_ALPHA: + g_value_set_enum (value, pad->blend_equation_alpha); + break; + case PROP_PAD_BLEND_FUNCTION_SRC_RGB: + g_value_set_enum (value, pad->blend_function_src_rgb); + break; + case PROP_PAD_BLEND_FUNCTION_SRC_ALPHA: + g_value_set_enum (value, pad->blend_function_src_alpha); + break; + case PROP_PAD_BLEND_FUNCTION_DST_RGB: + g_value_set_enum (value, pad->blend_function_dst_rgb); + break; + case PROP_PAD_BLEND_FUNCTION_DST_ALPHA: + g_value_set_enum (value, pad->blend_function_dst_alpha); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED: + g_value_set_double (value, pad->blend_constant_color_red); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN: + g_value_set_double (value, pad->blend_constant_color_green); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE: + g_value_set_double (value, pad->blend_constant_color_blue); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA: + g_value_set_double (value, pad->blend_constant_color_alpha); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -653,6 +932,36 @@ gst_gl_video_mixer_pad_set_property (GObject * object, guint prop_id, case PROP_PAD_ALPHA: pad->alpha = g_value_get_double (value); break; + case PROP_PAD_BLEND_EQUATION_RGB: + pad->blend_equation_rgb = g_value_get_enum (value); + break; + case PROP_PAD_BLEND_EQUATION_ALPHA: + pad->blend_equation_alpha = g_value_get_enum (value); + break; + case PROP_PAD_BLEND_FUNCTION_SRC_RGB: + pad->blend_function_src_rgb = g_value_get_enum (value); + break; + case PROP_PAD_BLEND_FUNCTION_SRC_ALPHA: + pad->blend_function_src_alpha = g_value_get_enum (value); + break; + case PROP_PAD_BLEND_FUNCTION_DST_RGB: + pad->blend_function_dst_rgb = g_value_get_enum (value); + break; + case PROP_PAD_BLEND_FUNCTION_DST_ALPHA: + pad->blend_function_dst_alpha = g_value_get_enum (value); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_RED: + pad->blend_constant_color_red = g_value_get_double (value); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_GREEN: + pad->blend_constant_color_green = g_value_get_double (value); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_BLUE: + pad->blend_constant_color_blue = g_value_get_double (value); + break; + case PROP_PAD_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA: + pad->blend_constant_color_alpha = g_value_get_double (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1017,6 +1326,123 @@ _draw_background (GstGLVideoMixer * video_mixer) return TRUE; } +static guint +_blend_equation_to_gl (GstGLVideoMixerBlendEquation equation) +{ + switch (equation) { + case GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD: + return GL_FUNC_ADD; + case GST_GL_VIDEO_MIXER_BLEND_EQUATION_SUBTRACT: + return GL_FUNC_SUBTRACT; + case GST_GL_VIDEO_MIXER_BLEND_EQUATION_REVERSE_SUBTRACT: + return GL_FUNC_REVERSE_SUBTRACT; + default: + g_assert_not_reached (); + return 0; + } +} + +static guint +_blend_function_to_gl (GstGLVideoMixerBlendFunction equation) +{ + switch (equation) { + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ZERO: + return GL_ZERO; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE: + return GL_ONE; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_COLOR: + return GL_SRC_COLOR; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_COLOR: + return GL_ONE_MINUS_SRC_COLOR; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_COLOR: + return GL_DST_COLOR; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_COLOR: + return GL_ONE_MINUS_DST_COLOR; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA: + return GL_SRC_ALPHA; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_ALPHA: + return GL_DST_ALPHA; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_ALPHA: + return GL_ONE_MINUS_DST_ALPHA; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_COLOR: + return GL_CONSTANT_COLOR; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR: + return GL_ONE_MINUS_CONSTANT_COLOR; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA: + return GL_CONSTANT_ALPHA; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_ALPHA: + return GL_ONE_MINUS_CONSTANT_ALPHA; + case GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE: + return GL_SRC_ALPHA_SATURATE; + default: + g_assert_not_reached (); + return 0; + } +} + +static gboolean +_set_blend_state (GstGLVideoMixer * video_mixer, GstGLVideoMixerPad * mix_pad) +{ + const GstGLFuncs *gl = GST_GL_BASE_MIXER (video_mixer)->context->gl_vtable; + gboolean require_separate = FALSE; + guint gl_func_src_rgb, gl_func_src_alpha, gl_func_dst_rgb, gl_func_dst_alpha; + guint gl_equation_rgb, gl_equation_alpha; + + require_separate = + mix_pad->blend_equation_rgb != mix_pad->blend_equation_alpha + || mix_pad->blend_function_src_rgb != mix_pad->blend_function_src_alpha + || mix_pad->blend_function_dst_rgb != mix_pad->blend_function_dst_alpha; + + if (require_separate && (!gl->BlendFuncSeparate + || !gl->BlendEquationSeparate)) { + GST_ERROR_OBJECT (mix_pad, + "separated blend equations/functions requested however " + "glBlendFuncSeparate or glBlendEquationSeparate not available"); + return FALSE; + } + + if (mix_pad->blend_function_dst_rgb == + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE) { + GST_ERROR_OBJECT (mix_pad, + "Destination RGB blend function cannot be \'SRC_ALPHA_SATURATE\'"); + return FALSE; + } + + if (mix_pad->blend_function_dst_alpha == + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE) { + GST_ERROR_OBJECT (mix_pad, + "Destination alpha blend function cannot be \'SRC_ALPHA_SATURATE\'"); + return FALSE; + } + + gl_equation_rgb = _blend_equation_to_gl (mix_pad->blend_equation_rgb); + gl_equation_alpha = _blend_equation_to_gl (mix_pad->blend_equation_alpha); + + gl_func_src_rgb = _blend_function_to_gl (mix_pad->blend_function_src_rgb); + gl_func_src_alpha = _blend_function_to_gl (mix_pad->blend_function_src_alpha); + gl_func_dst_rgb = _blend_function_to_gl (mix_pad->blend_function_dst_rgb); + gl_func_dst_alpha = _blend_function_to_gl (mix_pad->blend_function_dst_alpha); + + if (gl->BlendEquationSeparate) + gl->BlendEquationSeparate (gl_equation_rgb, gl_equation_alpha); + else + gl->BlendEquation (gl_equation_rgb); + + if (gl->BlendFuncSeparate) + gl->BlendFuncSeparate (gl_func_src_rgb, gl_func_dst_rgb, gl_func_src_alpha, + gl_func_dst_alpha); + else + gl->BlendFunc (gl_func_src_rgb, gl_func_dst_rgb); + + gl->BlendColor (mix_pad->blend_constant_color_red, + mix_pad->blend_constant_color_green, mix_pad->blend_constant_color_blue, + mix_pad->blend_constant_color_alpha); + + return TRUE; +} + /* opengl scene, params: input texture (not the output mixer->texture) */ static void gst_gl_video_mixer_callback (gpointer stuff) @@ -1094,6 +1520,11 @@ gst_gl_video_mixer_callback (gpointer stuff) continue; } + if (!_set_blend_state (video_mixer, pad)) { + GST_FIXME_OBJECT (pad, "skipping due to incorrect blend parameters"); + continue; + } + in_tex = frame->texture; _init_vbo_indices (video_mixer); @@ -1135,9 +1566,6 @@ gst_gl_video_mixer_callback (gpointer stuff) } gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, video_mixer->vbo_indices); - gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gl->BlendEquation (GL_FUNC_ADD); - gl->ActiveTexture (GL_TEXTURE0); gl->BindTexture (GL_TEXTURE_2D, in_tex); gst_gl_shader_set_uniform_1i (video_mixer->shader, "texture", 0); diff --git a/ext/gl/gstglvideomixer.h b/ext/gl/gstglvideomixer.h index 0d0252b56f..86c0506d25 100644 --- a/ext/gl/gstglvideomixer.h +++ b/ext/gl/gstglvideomixer.h @@ -53,6 +53,66 @@ typedef enum } GstGLVideoMixerBackground; +/** + * GstGLVideoMixerBlendEquation: + * @GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD: Add the two results. + * @GST_GL_VIDEO_MIXER_BLEND_EQUATION_SUBTRACT: Subtract component-wise the destination from the source (S - D). + * @GST_GL_VIDEO_MIXER_BLEND_EQUATION_REVERSE_SUBTRACT: Subtract component-wise the source from the destination (D - S). + * + * The blending equation to use. See the opengl specificition for + * glBlendEquationSeparate + */ +typedef enum +{ + GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD, + GST_GL_VIDEO_MIXER_BLEND_EQUATION_SUBTRACT, + GST_GL_VIDEO_MIXER_BLEND_EQUATION_REVERSE_SUBTRACT, +} +GstGLVideoMixerBlendEquation; + +/** + * GstGLVideoMixerBlendFunction: + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ZERO: All components are zero + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE: All components are one + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_COLOR: Use the source color/alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_COLOR: One minus the source color/alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_COLOR: Use the destination color/alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_COLOR: One minus the destination color/alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA: All components are the source alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA: All components are one minus the source alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_ALPHA: All components are the destination alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_ALPHA: All components are one minus the destination alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_COLOR: Use the constant color/alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR: Use one minus the constant color/alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA: All components are the constant alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR: All components are one minus the constant alpha + * @GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE: All color components + * are the minimum of source alpha and one minus the destination alpha. + * Alpha is equal to one. + * + * The blending function to use. See the opengl specificition for + * glBlendFuncSeparate + */ +typedef enum +{ + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ZERO, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_COLOR, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_COLOR, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_COLOR, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_COLOR, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_DST_ALPHA, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_DST_ALPHA, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_COLOR, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_ALPHA, + GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE, +} +GstGLVideoMixerBlendFunction; + struct _GstGLVideoMixer { GstGLMixer mixer;