PROP_GST_BUS,
PROP_MIN_WIDTH,
PROP_MIN_HEIGHT,
+ PROP_SYNC,
+ PROP_ASYNC,
};
/* private structure */
FsElementAddedNotifier *notifier;
gint min_width;
gint min_height;
+ gboolean sync;
+ gboolean async;
+
+ GMutex *lock;
};
#define GET_PRIV(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
- EMPATHY_TYPE_GST_GTK_WIDGET, EmpathyVideoWidgetPriv))
+ EMPATHY_TYPE_VIDEO_WIDGET, EmpathyVideoWidgetPriv))
static void
empathy_video_widget_init (EmpathyVideoWidget *obj)
EmpathyVideoWidgetPriv *priv = GET_PRIV (obj);
GdkColor black;
+ priv->lock = g_mutex_new ();
+
priv->notifier = fs_element_added_notifier_new ();
g_signal_connect (priv->notifier, "element-added",
G_CALLBACK (empathy_video_widget_element_added_cb),
empathy_video_widget_constructed (GObject *object)
{
EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
+ GstElement *colorspace, *videoscale, *sink;
+ GstPad *pad;
+
+ priv->videosink = gst_bin_new (NULL);
- priv->videosink = gst_element_factory_make ("gconfvideosink", NULL);
gst_object_ref (priv->videosink);
gst_object_sink (priv->videosink);
priv->sink_pad = gst_element_get_static_pad (priv->videosink, "sink");
+ sink = gst_element_factory_make ("gconfvideosink", NULL);
+ g_assert (sink != NULL);
+
+ videoscale = gst_element_factory_make ("videoscale", NULL);
+ g_assert (videoscale != NULL);
+
+ g_object_set (videoscale, "qos", FALSE, NULL);
+
+ colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+ g_assert (colorspace != NULL);
+
+ g_object_set (colorspace, "qos", FALSE, NULL);
+
+ gst_bin_add_many (GST_BIN (priv->videosink), colorspace, videoscale,
+ sink, NULL);
+
+ if (!gst_element_link (colorspace, videoscale))
+ g_error ("Failed to link ffmpegcolorspace and videoscale");
+
+ if (!gst_element_link (videoscale, sink))
+ g_error ("Failed to link videoscale and gconfvideosink");
+
+ pad = gst_element_get_static_pad (colorspace, "sink");
+ g_assert (pad != NULL);
+
+ priv->sink_pad = gst_ghost_pad_new ("sink", pad);
+ if (!gst_element_add_pad (priv->videosink, priv->sink_pad))
+ g_error ("Couldn't add sink ghostpad to the bin");
+
+ gst_object_unref (pad);
+
fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->videosink));
gst_bus_enable_sync_message_emission (priv->bus);
static void empathy_video_widget_dispose (GObject *object);
static void empathy_video_widget_finalize (GObject *object);
+
static gboolean empathy_video_widget_expose_event (GtkWidget *widget,
GdkEventExpose *event);
+static void
+empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self);
static void
empathy_video_widget_set_property (GObject *object,
case PROP_MIN_HEIGHT:
priv->min_height = g_value_get_int (value);
break;
+ case PROP_SYNC:
+ priv->sync = g_value_get_boolean (value);
+ empathy_video_widget_element_set_sink_properties (
+ EMPATHY_VIDEO_WIDGET (object));
+ break;
+ case PROP_ASYNC:
+ priv->async = g_value_get_boolean (value);
+ empathy_video_widget_element_set_sink_properties (
+ EMPATHY_VIDEO_WIDGET (object));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
case PROP_MIN_HEIGHT:
g_value_set_int (value, priv->min_height);
break;
+ case PROP_SYNC:
+ g_value_set_boolean (value, priv->sync);
+ break;
+ case PROP_ASYNC:
+ g_value_set_boolean (value, priv->async);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_MIN_HEIGHT, param_spec);
+ param_spec = g_param_spec_boolean ("sync",
+ "sync",
+ "Whether the underlying sink should be sync or not",
+ TRUE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_SYNC, param_spec);
+
+ param_spec = g_param_spec_boolean ("async",
+ "async",
+ "Whether the underlying sink should be async or not",
+ TRUE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_ASYNC, param_spec);
}
void
void
empathy_video_widget_finalize (GObject *object)
{
- //EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
- //EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+ EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
+ EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
/* free any data held directly by the object here */
+ g_mutex_free (priv->lock);
G_OBJECT_CLASS (empathy_video_widget_parent_class)->finalize (object);
}
+
+static void
+empathy_video_widget_element_set_sink_properties_unlocked (
+ EmpathyVideoWidget *self)
+{
+ EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+
+ if (priv->overlay == NULL)
+ return;
+
+ if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay),
+ "force-aspect-ratio"))
+ g_object_set (G_OBJECT (priv->overlay), "force-aspect-ratio", TRUE, NULL);
+
+ if (g_object_class_find_property (
+ G_OBJECT_GET_CLASS (priv->overlay), "sync"))
+ g_object_set (G_OBJECT (priv->overlay), "sync", priv->sync, NULL);
+
+ if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay),
+ "async"))
+ g_object_set (G_OBJECT (priv->overlay), "async", priv->async, NULL);
+}
+
+static void
+empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self)
+{
+ EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+
+ g_mutex_lock (priv->lock);
+ empathy_video_widget_element_set_sink_properties_unlocked (self);
+ g_mutex_unlock (priv->lock);
+}
+
static void
empathy_video_widget_element_added_cb (FsElementAddedNotifier *notifier,
GstBin *bin, GstElement *element, EmpathyVideoWidget *self)
{
EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+ /* We assume the overlay is the sink */
+ g_mutex_lock (priv->lock);
if (priv->overlay == NULL && GST_IS_X_OVERLAY (element))
{
priv->overlay = element;
+ g_object_add_weak_pointer (G_OBJECT (element),
+ (gpointer) &priv->overlay);
+ empathy_video_widget_element_set_sink_properties_unlocked (self);
gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
}
-
- if (g_object_class_find_property (
- G_OBJECT_GET_CLASS (element), "force-aspect-ratio"))
- {
- g_object_set (G_OBJECT (element), "force-aspect-ratio", TRUE, NULL);
- }
+ g_mutex_unlock (priv->lock);
}
static void
if (gst_structure_has_name (s, "prepare-xwindow-id"))
{
+ g_assert (GTK_WIDGET_REALIZED (GTK_WIDGET (self)));
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
GDK_WINDOW_XID (GTK_WIDGET (self)->window));
}
return TRUE;
if (priv->overlay == NULL)
- return TRUE;
+ {
+ gdk_window_clear_area (widget->window, 0, 0,
+ widget->allocation.width, widget->allocation.height);
+ return TRUE;
+ }
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
GDK_WINDOW_XID (widget->window));
{
g_return_val_if_fail (bus != NULL, NULL);
- return GTK_WIDGET (g_object_new (EMPATHY_TYPE_GST_GTK_WIDGET,
+ return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET,
"gst-bus", bus,
"min-width", width,
"min-height", height,
{
g_return_val_if_fail (bus != NULL, NULL);
- return GTK_WIDGET (g_object_new (EMPATHY_TYPE_GST_GTK_WIDGET,
+ return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET,
"gst-bus", bus,
NULL));
}