[telepathy-stream-engine/master] Signal the Video buffer sizes to the UI

Olivier Crête olivier.crete at collabora.co.uk
Thu Oct 22 04:11:35 PDT 2009


---
 api/Stream_Engine.xml  |   15 +++++++++
 configure.ac           |    6 +++
 src/Makefile.am        |    2 +
 src/tp-stream-engine.c |   56 +++++++++++++++++++++++++++------
 src/videosink.c        |   82 +++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 147 insertions(+), 14 deletions(-)

diff --git a/api/Stream_Engine.xml b/api/Stream_Engine.xml
index 84d357f..51fdad6 100644
--- a/api/Stream_Engine.xml
+++ b/api/Stream_Engine.xml
@@ -54,5 +54,20 @@
       </tp:docstring>
       <!-- FIXME: possible errors? -->
     </method>
+
+    <signal name="VideoOutputSize">
+      <arg type="o" name="channel_path" />
+      <arg type="u" name="stream_id" />
+      <arg type="u" name="window_id" />
+      <arg type="u" name="width" />
+      <arg type="u" name="height" />
+    </signal>
+
+    <signal name="VideoPreviewSize">
+      <arg type="u" name="window_id" />
+      <arg type="u" name="width" />
+      <arg type="u" name="height" />
+    </signal>
+
   </interface>
 </node>
diff --git a/configure.ac b/configure.ac
index 5859694..755cb08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -128,6 +128,12 @@ PKG_CHECK_MODULES(GST_INTERFACES, [gstreamer-interfaces-0.10 >= 0.10.18],[],
 AC_SUBST(GST_INTERFACES_CFLAGS)
 AC_SUBST(GST_INTERFACES_LIBS)
 
+dnl Check for gst-video
+PKG_CHECK_MODULES(GST_VIDEO, [gstreamer-video-0.10 >= 0.10.18],[],
+       [AC_MSG_ERROR([gst-plugins-base-0.10.18. is required])])
+AC_SUBST(GST_VIDEO_CFLAGS)
+AC_SUBST(GST_VIDEO_LIBS)
+
 
 dnl libx11
 PKG_CHECK_MODULES(X11, [x11 gtk+-2.0])
diff --git a/src/Makefile.am b/src/Makefile.am
index 199b083..73c3128 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ AM_CFLAGS = \
 	$(DBUS_CFLAGS) \
 	$(X11_CFLAGS) \
 	$(GST_CFLAGS) \
+	$(GST_VIDEO_CFLAGS) \
 	$(GST_INTERFACES_CFLAGS) \
 	$(FARSIGHT2_CFLAGS) \
 	$(TELEPATHY_CFLAGS) \
@@ -42,6 +43,7 @@ AM_LDFLAGS = \
 	$(DBUS_LIBS) \
 	$(X11_LIBS) \
 	$(GST_LIBS) \
+	$(GST_VIDEO_LIBS) \
 	$(GST_INTERFACES_LIBS) \
 	$(FARSIGHT2_LIBS) \
 	$(TELEPATHY_LIBS) \
diff --git a/src/tp-stream-engine.c b/src/tp-stream-engine.c
index 902217f..0106ac9 100644
--- a/src/tp-stream-engine.c
+++ b/src/tp-stream-engine.c
@@ -782,6 +782,31 @@ audio_sink_added_cb (TpStreamEngineAudioStream *audiostream,
 }
 
 static void
+output_size_changed (TpStreamEngineVideoStream *videostream,
+    guint width, guint height, gpointer user_data)
+{
+  TpStreamEngine *self = TP_STREAM_ENGINE (user_data);
+  TfStream *stream = NULL;
+  TfChannel *chan = NULL;
+  guint stream_id;
+  gchar *channel_path;
+  guint window_id;
+
+  g_object_get (videostream, "stream", &stream, "window-id", &window_id, NULL);
+
+  g_object_get (stream, "channel", &chan, "stream-id", &stream_id, NULL);
+
+  g_object_get (chan, "object-path", &channel_path, NULL);
+
+  stream_engine_svc_stream_engine_emit_video_output_size (self,
+      channel_path, stream_id, window_id, width, height);
+
+  g_object_unref (chan);
+  g_object_unref (stream);
+  g_free (channel_path);
+}
+
+static void
 channel_stream_created (TfChannel *chan G_GNUC_UNUSED,
     TfStream *stream, gpointer user_data)
 {
@@ -868,6 +893,8 @@ channel_stream_created (TfChannel *chan G_GNUC_UNUSED,
 
       g_signal_connect (videostream, "receiving",
           G_CALLBACK (stream_receiving), self);
+      g_signal_connect (videostream, "size-changed",
+          G_CALLBACK (output_size_changed), self);
 
       g_signal_connect (stream, "request-resource",
           G_CALLBACK (video_stream_request_resource), self);
@@ -1469,6 +1496,21 @@ _preview_window_plug_deleted (TpStreamEngineVideoPreview *preview,
   gst_object_unref (preview);
 }
 
+
+static void
+preview_size_changed (TpStreamEngineVideoPreview *videopreview,
+    guint width, guint height, gpointer user_data)
+{
+  TpStreamEngine *self = TP_STREAM_ENGINE (user_data);
+  guint window_id;
+
+  g_object_get (videopreview, "window-id", &window_id, NULL);
+
+  stream_engine_svc_stream_engine_emit_video_preview_size (self,
+      window_id, width, height);
+}
+
+
 /**
  * tp_stream_engine_create_preview_window
  *
@@ -1504,6 +1546,9 @@ tp_stream_engine_create_preview_window (StreamEngineSvcStreamEngine *iface,
 
   g_object_set (preview, "pad", pad, NULL);
 
+  g_signal_connect (preview, "size-changed",
+      G_CALLBACK (preview_size_changed), self);
+
   g_signal_connect (preview, "plug-deleted",
       G_CALLBACK (_preview_window_plug_deleted), self);
 
@@ -1556,17 +1601,8 @@ tp_stream_engine_get_preview_window (StreamEngineSvcStreamEngine *iface,
       return;
     }
 
+
   g_mutex_lock (self->priv->mutex);
-  if (self->priv->preview)
-    {
-      g_object_get (self->priv->preview, "window-id", &window_id, NULL);
-      g_mutex_unlock (self->priv->mutex);
-      stream_engine_svc_stream_engine_return_from_create_preview_window (
-          context,
-          window_id);
-      g_object_unref (preview);
-      return;
-    }
   self->priv->preview = preview;
   g_mutex_unlock (self->priv->mutex);
 
diff --git a/src/videosink.c b/src/videosink.c
index ab0771c..1cba818 100644
--- a/src/videosink.c
+++ b/src/videosink.c
@@ -26,12 +26,14 @@
 #include <stdlib.h>
 
 #include <gst/interfaces/xoverlay.h>
+#include <gst/video/video.h>
 #include <gst/farsight/fs-element-added-notifier.h>
 
 #include <tp-stream-engine.h>
 
 #include <gtk/gtk.h>
 
+#include "tp-stream-engine-signals-marshal.h"
 #include "videosink.h"
 #include "util.h"
 
@@ -43,6 +45,8 @@ struct _TpStreamEngineVideoSinkPrivate
   GstElement *sink;
   GtkWidget *plug;
 
+  GstPad *sinkpad;
+
   guint window_id;
 
   gboolean is_preview;
@@ -53,6 +57,11 @@ struct _TpStreamEngineVideoSinkPrivate
   GstClockTime last_timestamp;
   gdouble framerate;
   GstElement *textoverlay;
+
+  gulong caps_changed_id;
+
+  GStaticMutex mutex;
+  guint size_change_idle_id; /* mutex protected */
 };
 
 /* properties */
@@ -70,6 +79,7 @@ enum
 enum
 {
   PLUG_DELETED,
+  SIZE_CHANGED,
   SIGNAL_COUNT
 };
 
@@ -84,6 +94,8 @@ tp_stream_engine_video_sink_init (TpStreamEngineVideoSink *self)
 
   self->priv = priv;
 
+  g_static_mutex_init (&priv->mutex);
+
   priv->last_timestamp = GST_CLOCK_TIME_NONE;
 }
 
@@ -143,6 +155,34 @@ fps_qos_probe (GstPad *pad, GstEvent *event, gpointer user_data)
   return TRUE;
 }
 
+static gboolean
+size_change_idle_cb (gpointer data)
+{
+  TpStreamEngineVideoSink *self = data;
+  gint width, height;
+
+  g_static_mutex_lock (&self->priv->mutex);
+  self->priv->size_change_idle_id = 0;
+  g_static_mutex_unlock (&self->priv->mutex);
+
+  if (gst_video_get_size (self->priv->sinkpad, &width, &height))
+    g_signal_emit (self, signals[SIZE_CHANGED], 0, width, height);
+
+  return FALSE;
+}
+
+static void
+caps_changed (GObject *obj, GParamSpec *spec, gpointer user_data)
+{
+  TpStreamEngineVideoSink *self = user_data;
+
+  g_static_mutex_lock (&self->priv->mutex);
+  if (!self->priv->size_change_idle_id)
+    self->priv->size_change_idle_id =
+        g_idle_add ((GSourceFunc) size_change_idle_cb, self);
+  g_static_mutex_unlock (&self->priv->mutex);
+}
+
 
 static GstElement *
 make_video_sink (TpStreamEngineVideoSink *self, gboolean is_preview)
@@ -178,6 +218,10 @@ make_video_sink (TpStreamEngineVideoSink *self, gboolean is_preview)
       return NULL;
     }
 
+  if (g_object_has_property (sink, "force-aspect-ratio"))
+    g_object_set (sink, "force-aspect-ratio", TRUE, NULL);
+
+
   g_debug ("made video sink element %s", GST_ELEMENT_NAME (sink));
 
   bin = gst_bin_new (NULL);
@@ -259,7 +303,8 @@ make_video_sink (TpStreamEngineVideoSink *self, gboolean is_preview)
       sink = tmp;
     }
 
-  pad = gst_bin_find_unconnected_pad (GST_BIN (bin), GST_PAD_SINK);
+  self->priv->sinkpad = gst_bin_find_unconnected_pad (GST_BIN (bin),
+      GST_PAD_SINK);
 
   if (!pad)
     {
@@ -268,10 +313,14 @@ make_video_sink (TpStreamEngineVideoSink *self, gboolean is_preview)
       return NULL;
     }
 
+  self->priv->caps_changed_id = g_signal_connect (self->priv->sinkpad,
+      "notify::caps", G_CALLBACK (caps_changed), self);
+
   if (g_getenv ("STREAM_ENGINE_FPS"))
-    gst_pad_add_event_probe (pad, G_CALLBACK (fps_qos_probe), self);
+    gst_pad_add_event_probe (self->priv->sinkpad, G_CALLBACK (fps_qos_probe),
+ self);
 
-  ghostpad = gst_ghost_pad_new ("sink", pad);
+  ghostpad = gst_ghost_pad_new ("sink", self->priv->sinkpad);
   if (!gst_element_add_pad (bin, ghostpad))
     {
       gst_object_unref (ghostpad);
@@ -279,7 +328,6 @@ make_video_sink (TpStreamEngineVideoSink *self, gboolean is_preview)
       gst_object_unref (bin);
       return NULL;
     }
-  gst_object_unref (GST_OBJECT (pad));
 
   sink = bin;
 
@@ -353,12 +401,29 @@ tp_stream_engine_video_sink_dispose (GObject *object)
 {
   TpStreamEngineVideoSink *self = TP_STREAM_ENGINE_VIDEO_SINK (object);
 
+  if (self->priv->sinkpad)
+    {
+      if (self->priv->caps_changed_id)
+        g_signal_handler_disconnect (self->priv->sinkpad,
+            self->priv->caps_changed_id);
+      self->priv->caps_changed_id = 0;
+
+      gst_object_unref (self->priv->sinkpad);
+      self->priv->sinkpad = NULL;
+    }
+
   if (self->priv->sink)
     {
       gst_object_unref (self->priv->sink);
       self->priv->sink = NULL;
     }
 
+  g_static_mutex_lock (&self->priv->mutex);
+  if (self->priv->size_change_idle_id)
+    g_source_remove (self->priv->size_change_idle_id);
+  self->priv->size_change_idle_id = 0;
+  g_static_mutex_unlock (&self->priv->mutex);
+
   if (self->priv->delete_event_handler_id)
     {
       g_signal_handler_disconnect (self->priv->plug,
@@ -468,6 +533,15 @@ tp_stream_engine_video_sink_class_init (TpStreamEngineVideoSinkClass *klass)
           NULL, NULL,
           g_cclosure_marshal_VOID__VOID,
           G_TYPE_NONE, 0);
+
+  signals[SIZE_CHANGED] =
+      g_signal_new ("size-changed",
+          G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+          0,
+          NULL, NULL,
+          tp_stream_engine_marshal_VOID__UINT_UINT,
+          G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
 }
 
 struct xid_data
-- 
1.5.6.5




More information about the telepathy-commits mailing list