summaryrefslogtreecommitdiffstats
path: root/audio/gsta2dpsink.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-01-23 19:17:33 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-01-23 19:17:33 +0000
commit1f9f22f64d5e7c66c6e2d20452f6e5918d0020fb (patch)
tree3400e5b2a3e4c3fa482de52843ca5cf6c38aee65 /audio/gsta2dpsink.c
parente8e68d294cd662970de6082473e30ecd6ee8dd61 (diff)
Fix use of gstreamer plugin with rhythmbox and banshee and rtp timestamps.
Diffstat (limited to 'audio/gsta2dpsink.c')
-rw-r--r--audio/gsta2dpsink.c93
1 files changed, 80 insertions, 13 deletions
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c
index a3f3655a..a2b3286c 100644
--- a/audio/gsta2dpsink.c
+++ b/audio/gsta2dpsink.c
@@ -68,6 +68,17 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event);
static gboolean gst_a2dp_sink_set_caps(GstPad *pad, GstCaps *caps);
static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad);
static gboolean gst_a2dp_sink_init_caps_filter(GstA2dpSink *self);
+static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self);
+static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self);
+
+static void gst_a2dp_sink_finalize(GObject *obj)
+{
+ GstA2dpSink *self = GST_A2DP_SINK(obj);
+
+ g_mutex_free(self->cb_mutex);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
/*
* Helper function to create elements, add to the bin and link it
@@ -93,9 +104,9 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,
goto cleanup_and_fail;
}
- if (gst_element_set_state(element, GST_STATE_READY) ==
+ if (gst_element_set_state(element, GST_STATE_PLAYING) ==
GST_STATE_CHANGE_FAILURE) {
- GST_ERROR_OBJECT(self, "%s failed to go to ready",
+ GST_ERROR_OBJECT(self, "%s failed to go to playing",
elementname);
goto remove_element_and_fail;
}
@@ -224,6 +235,8 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
self->taglist = gst_tag_list_new();
+
+ gst_a2dp_sink_init_fakesink(self);
break;
case GST_STATE_CHANGE_NULL_TO_READY:
@@ -263,6 +276,7 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
gst_event_unref(self->newseg_event);
self->newseg_event = NULL;
}
+ gst_a2dp_sink_remove_fakesink(self);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
@@ -280,7 +294,6 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
self->sink = NULL;
gst_a2dp_sink_remove_dynamic_elements(self);
-
break;
default:
@@ -302,6 +315,9 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass)
object_class->get_property = GST_DEBUG_FUNCPTR(
gst_a2dp_sink_get_property);
+ object_class->finalize = GST_DEBUG_FUNCPTR(
+ gst_a2dp_sink_finalize);
+
element_class->change_state = GST_DEBUG_FUNCPTR(
gst_a2dp_sink_change_state);
@@ -314,7 +330,7 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass)
"A2DP sink element");
}
-static GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self)
+GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self)
{
return gst_avdtp_sink_get_device_caps(self->sink);
}
@@ -343,12 +359,16 @@ static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad)
return caps;
}
-static gboolean gst_a2dp_sink_init_sender_sink(GstA2dpSink *self)
+static gboolean gst_a2dp_sink_init_avdtp_sink(GstA2dpSink *self)
{
GstElement *sink;
+ /* check if we don't need a new sink */
+ if (self->sink_is_in_bin)
+ return TRUE;
+
if (self->sink == NULL)
- sink = gst_element_factory_make("avdtpsink", "avdtosink");
+ sink = gst_element_factory_make("avdtpsink", "avdtpsink");
else
sink = GST_ELEMENT(self->sink);
@@ -399,6 +419,10 @@ static gboolean gst_a2dp_sink_init_rtp_sbc_element(GstA2dpSink *self)
{
GstElement *rtppay;
+ /* if we already have a rtp, we don't need a new one */
+ if (self->rtp != NULL)
+ return TRUE;
+
rtppay = gst_a2dp_sink_init_element(self, "rtpsbcpay", "rtp",
self->capsfilter);
if (rtppay == NULL)
@@ -416,13 +440,16 @@ static gboolean gst_a2dp_sink_init_rtp_mpeg_element(GstA2dpSink *self)
{
GstElement *rtppay;
- GST_LOG_OBJECT(self, "Initializing rtp mpeg element");
+ /* check if we don't need a new rtp */
+ if (self->rtp)
+ return TRUE;
+ GST_LOG_OBJECT(self, "Initializing rtp mpeg element");
/* if capsfilter is not created then we can't have our rtp element */
if (self->capsfilter == NULL)
return FALSE;
- rtppay = gst_a2dp_sink_init_element(self, "rtpmpapay", "rtp",
+ rtppay = gst_a2dp_sink_init_element(self, "rtpmpapay", "rtp",
self->capsfilter);
if (rtppay == NULL)
return FALSE;
@@ -445,6 +472,9 @@ static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self,
structure = gst_caps_get_structure(caps, 0);
+ /* before everything we need to remove fakesink */
+ gst_a2dp_sink_remove_fakesink(self);
+
/* first, we need to create our rtp payloader */
if (gst_structure_has_name(structure, "audio/x-sbc")) {
GST_LOG_OBJECT(self, "sbc media received");
@@ -459,7 +489,7 @@ static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self,
return FALSE;
}
- if (!gst_a2dp_sink_init_sender_sink(self))
+ if (!gst_a2dp_sink_init_avdtp_sink(self))
return FALSE;
/* check if we should push the taglist FIXME should we push this?
@@ -518,18 +548,18 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event)
{
GstA2dpSink *self;
GstTagList *taglist = NULL;
+ GstObject *parent;
self = GST_A2DP_SINK(GST_PAD_PARENT(pad));
+ parent = gst_element_get_parent(GST_ELEMENT(self->sink));
if (GST_EVENT_TYPE(event) == GST_EVENT_NEWSEGMENT &&
- gst_element_get_parent(GST_ELEMENT(self->sink)) !=
- GST_OBJECT_CAST(self)) {
+ parent != GST_OBJECT_CAST(self)) {
if (self->newseg_event != NULL)
gst_event_unref(self->newseg_event);
self->newseg_event = gst_event_ref(event);
} else if (GST_EVENT_TYPE(event) == GST_EVENT_TAG &&
- gst_element_get_parent(GST_ELEMENT(self->sink)) !=
- GST_OBJECT_CAST(self)) {
+ parent != GST_OBJECT_CAST(self)) {
if (self->taglist == NULL) {
gst_event_parse_tag(event, &self->taglist);
} else {
@@ -540,6 +570,9 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event)
/* FIXME handle tag events */
}
+ if (parent != NULL)
+ gst_object_unref(GST_OBJECT(parent));
+
return self->ghostpad_eventfunc(GST_PAD(self->ghostpad), event);
}
@@ -562,10 +595,40 @@ failed:
return FALSE;
}
+static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self)
+{
+ if (self->fakesink != NULL)
+ return TRUE;
+
+ g_mutex_lock (self->cb_mutex);
+ self->fakesink = gst_a2dp_sink_init_element(self, "fakesink",
+ "fakesink", self->capsfilter);
+ g_mutex_unlock (self->cb_mutex);
+
+ if (!self->fakesink)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self)
+{
+ g_mutex_lock(self->cb_mutex);
+ if (self->fakesink != NULL) {
+ gst_element_set_state(self->fakesink, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(self), self->fakesink);
+ self->fakesink = NULL;
+ }
+ g_mutex_unlock(self->cb_mutex);
+
+ return TRUE;
+}
+
static void gst_a2dp_sink_init(GstA2dpSink *self,
GstA2dpSinkClass *klass)
{
self->sink = NULL;
+ self->fakesink = NULL;
self->rtp = NULL;
self->device = NULL;
self->capsfilter = NULL;
@@ -574,12 +637,16 @@ static void gst_a2dp_sink_init(GstA2dpSink *self,
self->ghostpad = NULL;
self->sink_is_in_bin = FALSE;
+ self->cb_mutex = g_mutex_new();
+
/* we initialize our capsfilter */
gst_a2dp_sink_init_caps_filter(self);
g_object_set(self->capsfilter, "caps",
gst_static_pad_template_get_caps(&gst_a2dp_sink_factory),
NULL);
+ gst_a2dp_sink_init_fakesink(self);
+
gst_a2dp_sink_init_ghost_pad(self);
}