bluez: Fix use of gstreamer plugin with rhythmbox and banshee and rtp timestamps.

This commit is contained in:
Luiz Augusto von Dentz 2008-01-23 19:17:33 +00:00 committed by Tim-Philipp Müller
parent 309c6ecc47
commit aba7785ba1
2 changed files with 91 additions and 12 deletions

View file

@ -66,6 +66,18 @@ static gboolean gst_a2dp_sink_handle_event (GstPad * pad, GstEvent * event);
static gboolean gst_a2dp_sink_set_caps (GstPad * pad, GstCaps * caps); static gboolean gst_a2dp_sink_set_caps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_a2dp_sink_get_caps (GstPad * pad); 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_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 * Helper function to create elements, add to the bin and link it
@ -90,9 +102,9 @@ gst_a2dp_sink_init_element (GstA2dpSink * self,
goto cleanup_and_fail; 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_STATE_CHANGE_FAILURE) {
GST_ERROR_OBJECT (self, "%s failed to go to ready", elementname); GST_ERROR_OBJECT (self, "%s failed to go to playing", elementname);
goto remove_element_and_fail; goto remove_element_and_fail;
} }
@ -221,6 +233,8 @@ gst_a2dp_sink_change_state (GstElement * element, GstStateChange transition)
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
self->taglist = gst_tag_list_new (); self->taglist = gst_tag_list_new ();
gst_a2dp_sink_init_fakesink (self);
break; break;
case GST_STATE_CHANGE_NULL_TO_READY: case GST_STATE_CHANGE_NULL_TO_READY:
@ -257,6 +271,7 @@ gst_a2dp_sink_change_state (GstElement * element, GstStateChange transition)
gst_event_unref (self->newseg_event); gst_event_unref (self->newseg_event);
self->newseg_event = NULL; self->newseg_event = NULL;
} }
gst_a2dp_sink_remove_fakesink (self);
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
@ -271,7 +286,6 @@ gst_a2dp_sink_change_state (GstElement * element, GstStateChange transition)
self->sink = NULL; self->sink = NULL;
gst_a2dp_sink_remove_dynamic_elements (self); gst_a2dp_sink_remove_dynamic_elements (self);
break; break;
default: default:
@ -292,6 +306,8 @@ gst_a2dp_sink_class_init (GstA2dpSinkClass * klass)
object_class->set_property = GST_DEBUG_FUNCPTR (gst_a2dp_sink_set_property); object_class->set_property = GST_DEBUG_FUNCPTR (gst_a2dp_sink_set_property);
object_class->get_property = GST_DEBUG_FUNCPTR (gst_a2dp_sink_get_property); 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); element_class->change_state = GST_DEBUG_FUNCPTR (gst_a2dp_sink_change_state);
g_object_class_install_property (object_class, PROP_DEVICE, g_object_class_install_property (object_class, PROP_DEVICE,
@ -302,7 +318,7 @@ gst_a2dp_sink_class_init (GstA2dpSinkClass * klass)
"A2DP sink element"); "A2DP sink element");
} }
static GstCaps * GstCaps *
gst_a2dp_sink_get_device_caps (GstA2dpSink * self) gst_a2dp_sink_get_device_caps (GstA2dpSink * self)
{ {
return gst_avdtp_sink_get_device_caps (self->sink); return gst_avdtp_sink_get_device_caps (self->sink);
@ -332,12 +348,16 @@ gst_a2dp_sink_get_caps (GstPad * pad)
} }
static gboolean static gboolean
gst_a2dp_sink_init_sender_sink (GstA2dpSink * self) gst_a2dp_sink_init_avdtp_sink (GstA2dpSink * self)
{ {
GstElement *sink; GstElement *sink;
/* check if we don't need a new sink */
if (self->sink_is_in_bin)
return TRUE;
if (self->sink == NULL) if (self->sink == NULL)
sink = gst_element_factory_make ("avdtpsink", "avdtosink"); sink = gst_element_factory_make ("avdtpsink", "avdtpsink");
else else
sink = GST_ELEMENT (self->sink); sink = GST_ELEMENT (self->sink);
@ -386,6 +406,10 @@ gst_a2dp_sink_init_rtp_sbc_element (GstA2dpSink * self)
{ {
GstElement *rtppay; 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", rtppay = gst_a2dp_sink_init_element (self, "rtpsbcpay", "rtp",
self->capsfilter); self->capsfilter);
if (rtppay == NULL) if (rtppay == NULL)
@ -404,8 +428,11 @@ gst_a2dp_sink_init_rtp_mpeg_element (GstA2dpSink * self)
{ {
GstElement *rtppay; 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 capsfilter is not created then we can't have our rtp element */
if (self->capsfilter == NULL) if (self->capsfilter == NULL)
return FALSE; return FALSE;
@ -433,6 +460,9 @@ gst_a2dp_sink_init_dynamic_elements (GstA2dpSink * self, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0); 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 */ /* first, we need to create our rtp payloader */
if (gst_structure_has_name (structure, "audio/x-sbc")) { if (gst_structure_has_name (structure, "audio/x-sbc")) {
GST_LOG_OBJECT (self, "sbc media received"); GST_LOG_OBJECT (self, "sbc media received");
@ -447,7 +477,7 @@ gst_a2dp_sink_init_dynamic_elements (GstA2dpSink * self, GstCaps * caps)
return FALSE; return FALSE;
} }
if (!gst_a2dp_sink_init_sender_sink (self)) if (!gst_a2dp_sink_init_avdtp_sink (self))
return FALSE; return FALSE;
/* check if we should push the taglist FIXME should we push this? /* check if we should push the taglist FIXME should we push this?
@ -506,18 +536,18 @@ gst_a2dp_sink_handle_event (GstPad * pad, GstEvent * event)
{ {
GstA2dpSink *self; GstA2dpSink *self;
GstTagList *taglist = NULL; GstTagList *taglist = NULL;
GstObject *parent;
self = GST_A2DP_SINK (GST_PAD_PARENT (pad)); 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 && if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT &&
gst_element_get_parent (GST_ELEMENT (self->sink)) != parent != GST_OBJECT_CAST (self)) {
GST_OBJECT_CAST (self)) {
if (self->newseg_event != NULL) if (self->newseg_event != NULL)
gst_event_unref (self->newseg_event); gst_event_unref (self->newseg_event);
self->newseg_event = gst_event_ref (event); self->newseg_event = gst_event_ref (event);
} else if (GST_EVENT_TYPE (event) == GST_EVENT_TAG && } else if (GST_EVENT_TYPE (event) == GST_EVENT_TAG &&
gst_element_get_parent (GST_ELEMENT (self->sink)) != parent != GST_OBJECT_CAST (self)) {
GST_OBJECT_CAST (self)) {
if (self->taglist == NULL) { if (self->taglist == NULL) {
gst_event_parse_tag (event, &self->taglist); gst_event_parse_tag (event, &self->taglist);
} else { } else {
@ -527,6 +557,9 @@ gst_a2dp_sink_handle_event (GstPad * pad, GstEvent * event)
/* FIXME handle tag events */ /* FIXME handle tag events */
} }
if (parent != NULL)
gst_object_unref (GST_OBJECT (parent));
return self->ghostpad_eventfunc (GST_PAD (self->ghostpad), event); return self->ghostpad_eventfunc (GST_PAD (self->ghostpad), event);
} }
@ -550,10 +583,42 @@ failed:
return FALSE; 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 static void
gst_a2dp_sink_init (GstA2dpSink * self, GstA2dpSinkClass * klass) gst_a2dp_sink_init (GstA2dpSink * self, GstA2dpSinkClass * klass)
{ {
self->sink = NULL; self->sink = NULL;
self->fakesink = NULL;
self->rtp = NULL; self->rtp = NULL;
self->device = NULL; self->device = NULL;
self->capsfilter = NULL; self->capsfilter = NULL;
@ -562,11 +627,15 @@ gst_a2dp_sink_init (GstA2dpSink * self, GstA2dpSinkClass * klass)
self->ghostpad = NULL; self->ghostpad = NULL;
self->sink_is_in_bin = FALSE; self->sink_is_in_bin = FALSE;
self->cb_mutex = g_mutex_new ();
/* we initialize our capsfilter */ /* we initialize our capsfilter */
gst_a2dp_sink_init_caps_filter (self); gst_a2dp_sink_init_caps_filter (self);
g_object_set (self->capsfilter, "caps", g_object_set (self->capsfilter, "caps",
gst_static_pad_template_get_caps (&gst_a2dp_sink_factory), NULL); gst_static_pad_template_get_caps (&gst_a2dp_sink_factory), NULL);
gst_a2dp_sink_init_fakesink (self);
gst_a2dp_sink_init_ghost_pad (self); gst_a2dp_sink_init_ghost_pad (self);
} }

View file

@ -25,6 +25,9 @@
#include <gst/rtp/gstbasertppayload.h> #include <gst/rtp/gstbasertppayload.h>
#include "gstavdtpsink.h" #include "gstavdtpsink.h"
#ifndef __GST_A2DP_SINK_H__
#define __GST_A2DP_SINK_H__
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_TYPE_A2DP_SINK \ #define GST_TYPE_A2DP_SINK \
@ -47,6 +50,7 @@ struct _GstA2dpSink {
GstBaseRTPPayload *rtp; GstBaseRTPPayload *rtp;
GstAvdtpSink *sink; GstAvdtpSink *sink;
GstElement *capsfilter; GstElement *capsfilter;
GstElement *fakesink;
gchar *device; gchar *device;
gboolean sink_is_in_bin; gboolean sink_is_in_bin;
@ -59,6 +63,8 @@ struct _GstA2dpSink {
/* Store the tags received before the a2dpsender sink is created /* Store the tags received before the a2dpsender sink is created
* when it is created we forward this to it */ * when it is created we forward this to it */
GstTagList *taglist; GstTagList *taglist;
GMutex *cb_mutex;
}; };
struct _GstA2dpSinkClass { struct _GstA2dpSinkClass {
@ -68,4 +74,8 @@ struct _GstA2dpSinkClass {
GType gst_a2dp_sink_get_type(void); GType gst_a2dp_sink_get_type(void);
gboolean gst_a2dp_sink_plugin_init (GstPlugin * plugin); gboolean gst_a2dp_sink_plugin_init (GstPlugin * plugin);
GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self);
G_END_DECLS G_END_DECLS
#endif