From b05002776bb6470a9f001173dc13a33aea55f2be Mon Sep 17 00:00:00 2001 From: =?utf8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 2 Jul 2015 20:10:50 -0400 Subject: [PATCH] glvideomixer: Add GstControlBinding proxy This is used to proxy GstControlBinding to the pad on the parent object. This avoid having to sync the values in the proxy pad, this is too early if you have a queue between the pad and the actual aggregation operation. https://bugzilla.gnome.org/show_bug.cgi?id=734060 --- ext/gl/gstglvideomixer.c | 214 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 159 insertions(+), 55 deletions(-) diff --git a/ext/gl/gstglvideomixer.c b/ext/gl/gstglvideomixer.c index 3c55480..25897d8 100644 --- a/ext/gl/gstglvideomixer.c +++ b/ext/gl/gstglvideomixer.c @@ -71,6 +71,151 @@ gst_gl_video_mixer_background_get_type (void) return mixer_background_type; } +typedef struct _GstGLMixerControlBindingProxy GstGLMixerControlBindingProxy; +typedef struct _GstGLMixerControlBindingProxyClass + GstGLMixerControlBindingProxyClass; + +struct _GstGLMixerControlBindingProxy +{ + GstControlBinding parent; + + GstObject *ref_object; + const gchar *property_name; +}; + +struct _GstGLMixerControlBindingProxyClass +{ + GstControlBindingClass parent_class; +}; + +GType gst_gl_mixer_control_binding_proxy_get_type (void); +#define GST_TYPE_GL_MIXER_CONTROL_BINDING \ + (gst_gl_mixer_control_binding_proxy_get_type()) + +G_DEFINE_TYPE (GstGLMixerControlBindingProxy, + gst_gl_mixer_control_binding_proxy, GST_TYPE_CONTROL_BINDING); + +static void +gst_gl_mixer_control_binding_proxy_init (GstGLMixerControlBindingProxy * self) +{ +} + +static gboolean +gst_gl_mixer_control_binding_proxy_sync_values (GstControlBinding * binding, + GstObject * object, GstClockTime timestamp, GstClockTime last_sync) +{ + GstGLMixerControlBindingProxy *self = (GstGLMixerControlBindingProxy *) + binding; + GstControlBinding *ref_binding; + gboolean ret = TRUE; + + ref_binding = gst_object_get_control_binding (self->ref_object, + self->property_name); + + if (ref_binding) { + ret = gst_control_binding_sync_values (ref_binding, self->ref_object, + timestamp, last_sync); + gst_object_unref (ref_binding); + } + + return ret; +} + +static GValue * +gst_gl_mixer_control_binding_proxy_get_value (GstControlBinding * binding, + GstClockTime timestamp) +{ + GstGLMixerControlBindingProxy *self = (GstGLMixerControlBindingProxy *) + binding; + GstControlBinding *ref_binding; + GValue *ret = NULL; + + ref_binding = gst_object_get_control_binding (self->ref_object, + self->property_name); + + if (ref_binding) { + ret = gst_control_binding_get_value (ref_binding, timestamp); + gst_object_unref (ref_binding); + } + + return ret; +} + +static gboolean +gst_gl_mixer_control_binding_proxy_get_value_array (GstControlBinding * binding, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values) +{ + GstGLMixerControlBindingProxy *self = (GstGLMixerControlBindingProxy *) + binding; + GstControlBinding *ref_binding; + gboolean ret = FALSE; + + ref_binding = gst_object_get_control_binding (self->ref_object, + self->property_name); + + if (ref_binding) { + ret = gst_control_binding_get_value_array (ref_binding, timestamp, + interval, n_values, values); + gst_object_unref (ref_binding); + } + + return ret; +} + +static gboolean +gst_gl_mixer_control_binding_proxy_get_g_value_array (GstControlBinding * + binding, GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values) +{ + GstGLMixerControlBindingProxy *self = (GstGLMixerControlBindingProxy *) + binding; + GstControlBinding *ref_binding; + gboolean ret = FALSE; + + ref_binding = gst_object_get_control_binding (self->ref_object, + self->property_name); + + if (ref_binding) { + ret = gst_control_binding_get_g_value_array (ref_binding, timestamp, + interval, n_values, values); + gst_object_unref (ref_binding); + } + + return ret; +} + + +static void + gst_gl_mixer_control_binding_proxy_class_init + (GstGLMixerControlBindingProxyClass * klass) +{ + GstControlBindingClass *cb_class = GST_CONTROL_BINDING_CLASS (klass); + + cb_class->sync_values = gst_gl_mixer_control_binding_proxy_sync_values; + cb_class->get_value = gst_gl_mixer_control_binding_proxy_get_value; + cb_class->get_value_array = + gst_gl_mixer_control_binding_proxy_get_value_array; + cb_class->get_g_value_array = + gst_gl_mixer_control_binding_proxy_get_g_value_array; +} + +static GstControlBinding * +gst_gl_mixer_control_binding_proxy_new (GstObject * object, + const gchar * property_name, GstObject * ref_object, + const gchar * ref_property_name) +{ + GstGLMixerControlBindingProxy *self = + g_object_new (GST_TYPE_GL_MIXER_CONTROL_BINDING, "object", object, + "name", property_name, NULL); + + self->ref_object = ref_object; + self->property_name = ref_property_name; + + return (GstControlBinding *) self; +} + + #define DEFAULT_PAD_XPOS 0 #define DEFAULT_PAD_YPOS 0 #define DEFAULT_PAD_WIDTH 0 @@ -94,11 +239,6 @@ static void gst_gl_video_mixer_input_get_property (GObject * object, static void gst_gl_video_mixer_input_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static GstFlowReturn gst_gl_video_mixer_input_chain (GstPad * pad, - GstObject * parent, GstBuffer * buffer); -static GstFlowReturn gst_gl_video_mixer_input_event (GstPad * pad, - GstObject * parent, GstEvent * event); - typedef struct _GstGLVideoMixerInput GstGLVideoMixerInput; typedef GstGhostPadClass GstGLVideoMixerInputClass; @@ -118,9 +258,6 @@ G_DEFINE_TYPE (GstGLVideoMixerInput, gst_gl_video_mixer_input, static void gst_gl_video_mixer_input_init (GstGLVideoMixerInput * self) { - GstPad *pad = GST_PAD (self); - - gst_pad_set_event_function (pad, gst_gl_video_mixer_input_event); } static void @@ -177,51 +314,6 @@ gst_gl_video_mixer_input_set_property (GObject * object, guint prop_id, g_object_set_property (G_OBJECT (self->mixer_pad), pspec->name, value); } -static GstFlowReturn -gst_gl_video_mixer_input_chain (GstPad * pad, GstObject * parent, - GstBuffer * buffer) -{ - GstGLVideoMixerInput *self = (GstGLVideoMixerInput *) pad; - GstClockTime timestamp, stream_time; -// gdouble alpha; - - timestamp = GST_BUFFER_TIMESTAMP (buffer); - - stream_time = - gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME, timestamp); - - gst_object_sync_values (GST_OBJECT (self), stream_time); -#if 0 - /* FIXME: implement no-upload on alpha = 0 */ - g_object_get (self, "alpha", &alpha, NULL); - - if (alpha <= 0.0) { - GST_DEBUG_OBJECT (self, "dropping buffer %" GST_PTR_FORMAT - " due to alpha value %f", buffer, alpha); - gst_buffer_unref (buffer); - return GST_FLOW_OK; - } -#endif - return gst_proxy_pad_chain_default (pad, parent, buffer); -} - -static GstFlowReturn -gst_gl_video_mixer_input_event (GstPad * pad, GstObject * parent, - GstEvent * event) -{ - GstGLVideoMixerInput *self = (GstGLVideoMixerInput *) pad; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - gst_event_copy_segment (event, &self->segment); - break; - default: - break; - } - - return gst_pad_event_default (pad, parent, event); -} - static GstGhostPad * _create_video_mixer_input (GstGLMixerBin * self, GstPad * mixer_pad) { @@ -229,13 +321,25 @@ _create_video_mixer_input (GstGLMixerBin * self, GstPad * mixer_pad) g_object_new (gst_gl_video_mixer_input_get_type (), "name", GST_OBJECT_NAME (mixer_pad), "direction", GST_PAD_DIRECTION (mixer_pad), NULL); + GstControlBinding *cb; if (!gst_ghost_pad_construct (GST_GHOST_PAD (input))) { gst_object_unref (input); return NULL; } - - gst_pad_set_chain_function (GST_PAD (input), gst_gl_video_mixer_input_chain); +#define ADD_PROXY_CONTROL_BINDING(prop) \ + cb = gst_gl_mixer_control_binding_proxy_new (GST_OBJECT (input), \ + G_STRINGIFY (prop), GST_OBJECT (mixer_pad), G_STRINGIFY (prop)); \ + gst_object_add_control_binding (GST_OBJECT (input), 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); + +#undef ADD_PROXY_CONTROL_BINDING input->mixer_pad = mixer_pad; -- 2.7.4