glvideomixer: Add GstControlBinding proxy
authorOlivier Crête <olivier.crete@collabora.com>
Fri, 3 Jul 2015 00:10:50 +0000 (20:10 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Thu, 23 Jul 2015 00:59:50 +0000 (20:59 -0400)
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

index 3c55480..25897d8 100644 (file)
@@ -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;