[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