diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-01-23 19:17:33 +0000 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-01-23 19:17:33 +0000 | 
| commit | 1f9f22f64d5e7c66c6e2d20452f6e5918d0020fb (patch) | |
| tree | 3400e5b2a3e4c3fa482de52843ca5cf6c38aee65 | |
| parent | e8e68d294cd662970de6082473e30ecd6ee8dd61 (diff) | |
Fix use of gstreamer plugin with rhythmbox and banshee and rtp timestamps.
| -rw-r--r-- | audio/gsta2dpsink.c | 93 | ||||
| -rw-r--r-- | audio/gsta2dpsink.h | 11 | ||||
| -rw-r--r-- | audio/gstrtpsbcpay.c | 6 | ||||
| -rw-r--r-- | audio/gstrtpsbcpay.h | 1 | 
4 files changed, 96 insertions, 15 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);  } diff --git a/audio/gsta2dpsink.h b/audio/gsta2dpsink.h index 26da4c47..d79307b2 100644 --- a/audio/gsta2dpsink.h +++ b/audio/gsta2dpsink.h @@ -25,6 +25,9 @@  #include <gst/rtp/gstbasertppayload.h>  #include "gstavdtpsink.h" +#ifndef __GST_A2DP_SINK_H__ +#define __GST_A2DP_SINK_H__ +  G_BEGIN_DECLS  #define GST_TYPE_A2DP_SINK \ @@ -47,6 +50,7 @@ struct _GstA2dpSink {  	GstBaseRTPPayload *rtp;  	GstAvdtpSink *sink;  	GstElement *capsfilter; +	GstElement *fakesink;  	gchar *device;  	gboolean sink_is_in_bin; @@ -59,6 +63,8 @@ struct _GstA2dpSink {  	/* Store the tags received before the a2dpsender sink is created  	 * when it is created we forward this to it */  	GstTagList *taglist; + +	GMutex *cb_mutex;  };  struct _GstA2dpSinkClass { @@ -68,4 +74,9 @@ struct _GstA2dpSinkClass {  GType gst_a2dp_sink_get_type(void);  gboolean gst_a2dp_sink_plugin_init (GstPlugin * plugin); +GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self); +  G_END_DECLS + +#endif + diff --git a/audio/gstrtpsbcpay.c b/audio/gstrtpsbcpay.c index 68aa28a9..fdb42d18 100644 --- a/audio/gstrtpsbcpay.c +++ b/audio/gstrtpsbcpay.c @@ -193,10 +193,10 @@ static GstFlowReturn gst_rtp_sbc_pay_flush_buffers(GstRtpSBCPay *sbcpay)  	memcpy(payload_data + RTP_SBC_PAYLOAD_HEADER_SIZE, data, max_payload);  	g_free(data); -	/* FIXME - timestamp it! */ +	GST_BUFFER_TIMESTAMP(outbuf) = sbcpay->timestamp;  	GST_DEBUG_OBJECT (sbcpay, "Pushing %d bytes", max_payload); -	return gst_basertppayload_push (GST_BASE_RTP_PAYLOAD(sbcpay), outbuf); +	return gst_basertppayload_push(GST_BASE_RTP_PAYLOAD(sbcpay), outbuf);  }  static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload, @@ -208,6 +208,7 @@ static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload,  	sbcpay = GST_RTP_SBC_PAY(payload);  	gst_adapter_push(sbcpay->adapter, gst_buffer_copy(buffer)); +	sbcpay->timestamp = GST_BUFFER_TIMESTAMP(buffer);  	available = gst_adapter_available(sbcpay->adapter);  	if (available + RTP_SBC_HEADER_TOTAL >=  			GST_BASE_RTP_PAYLOAD_MTU(sbcpay) || @@ -325,6 +326,7 @@ static void gst_rtp_sbc_pay_init(GstRtpSBCPay *self, GstRtpSBCPayClass *klass)  {  	self->adapter = gst_adapter_new();  	self->frame_length = 0; +	self->timestamp = 0;  	self->min_frames = DEFAULT_MIN_FRAMES;  } diff --git a/audio/gstrtpsbcpay.h b/audio/gstrtpsbcpay.h index f086a1c7..474d720a 100644 --- a/audio/gstrtpsbcpay.h +++ b/audio/gstrtpsbcpay.h @@ -48,6 +48,7 @@ struct _GstRtpSBCPay {  	GstBaseRTPPayload base;  	GstAdapter *adapter; +	GstClockTime timestamp;  	guint frame_length; | 
