diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-01-30 14:21:43 +0000 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-01-30 14:21:43 +0000 | 
| commit | 3ad6867c8c7251c3192378a1a0e2ed937ee47d1b (patch) | |
| tree | 879d3e37febab470e4b46c01f8b627dfd79308ae | |
| parent | a104e5ff05aa758b5499b316d1923f1c83915e55 (diff) | |
Fixes gstreamer caps and code cleanup.
| -rw-r--r-- | audio/gsta2dpsink.c | 40 | ||||
| -rw-r--r-- | audio/gstavdtpsink.c | 53 | ||||
| -rw-r--r-- | audio/gstavdtpsink.h | 1 | ||||
| -rw-r--r-- | audio/gstrtpsbcpay.c | 13 | ||||
| -rw-r--r-- | audio/gstsbcdec.c | 45 | ||||
| -rw-r--r-- | audio/gstsbcdec.h | 3 | ||||
| -rw-r--r-- | audio/gstsbcparse.c | 92 | ||||
| -rw-r--r-- | audio/gstsbcutil.c | 9 | 
8 files changed, 113 insertions, 143 deletions
| diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c index a2b3286c..b5b1c576 100644 --- a/audio/gsta2dpsink.c +++ b/audio/gsta2dpsink.c @@ -80,6 +80,17 @@ static void gst_a2dp_sink_finalize(GObject *obj)  	G_OBJECT_CLASS (parent_class)->finalize (obj);  } +static GstState gst_a2dp_sink_get_state(GstA2dpSink *self) +{ +	GstState current, pending; + +	gst_element_get_state(GST_ELEMENT(self), ¤t, &pending, 0); +	if (pending == GST_STATE_VOID_PENDING) +		return current; + +	return pending; +} +  /*   * Helper function to create elements, add to the bin and link it   * to another element. @@ -89,6 +100,7 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,  			GstElement *link_to)  {  	GstElement *element; +	GstState state;  	GST_LOG_OBJECT(self, "Initializing %s", elementname); @@ -104,17 +116,19 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,  		goto cleanup_and_fail;  	} -	if (gst_element_set_state(element, GST_STATE_PLAYING) == +	state = gst_a2dp_sink_get_state(self); +	if (gst_element_set_state(element, state) ==  			GST_STATE_CHANGE_FAILURE) {  		GST_ERROR_OBJECT(self, "%s failed to go to playing",  						elementname);  		goto remove_element_and_fail;  	} -	if (!gst_element_link(link_to, element)) { -		GST_ERROR_OBJECT(self, "couldn't link %s", elementname); -		goto remove_element_and_fail; -	} +	if (link_to != NULL) +		if (!gst_element_link(link_to, element)) { +			GST_ERROR_OBJECT(self, "couldn't link %s", elementname); +			goto remove_element_and_fail; +		}  	return element; @@ -241,7 +255,6 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,  	case GST_STATE_CHANGE_NULL_TO_READY:  		self->sink_is_in_bin = FALSE; -  		self->sink = GST_AVDTP_SINK(gst_element_factory_make(  				"avdtpsink", "avdtpsink"));  		if (self->sink == NULL) { @@ -260,8 +273,10 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,  		break;  	} -	if (ret == GST_STATE_CHANGE_FAILURE) +	if (ret == GST_STATE_CHANGE_FAILURE) { +		g_mutex_unlock(self->cb_mutex);  		return ret; +	}  	ret = GST_ELEMENT_CLASS(parent_class)->change_state(element,                          transition); @@ -295,7 +310,6 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,  		gst_a2dp_sink_remove_dynamic_elements(self);  		break; -  	default:  		break;  	} @@ -558,16 +572,16 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event)  		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 &&  			parent != GST_OBJECT_CAST(self)) { -		if (self->taglist == NULL) { +		if (self->taglist == NULL)  			gst_event_parse_tag(event, &self->taglist); -		} else { +		else {  			gst_event_parse_tag(event, &taglist);  			gst_tag_list_insert(self->taglist, taglist,  					GST_TAG_MERGE_REPLACE);  		} -		/* FIXME handle tag events */  	}  	if (parent != NULL) @@ -614,11 +628,15 @@ static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self)  static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self)  {  	g_mutex_lock(self->cb_mutex); +  	if (self->fakesink != NULL) { +		gst_element_set_locked_state(self->fakesink, TRUE);  		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; diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c index c956ecbd..25fc1ced 100644 --- a/audio/gstavdtpsink.c +++ b/audio/gstavdtpsink.c @@ -68,7 +68,7 @@ struct bluetooth_data {  };  #define IS_SBC(n) (strcmp((n), "audio/x-sbc") == 0) -#define IS_MPEG(n) (strcmp((n), "audio/mpeg") == 0) +#define IS_MPEG_AUDIO(n) (strcmp((n), "audio/mpeg") == 0)  enum {  	PROP_0, @@ -87,8 +87,12 @@ static const GstElementDetails avdtp_sink_details =  static GstStaticPadTemplate avdtp_sink_factory =  	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,  		GST_STATIC_CAPS("application/x-rtp, " -				"media = (string) \"audio\", " -				"encoding-name = (string) \"SBC\";" +				"media = (string) \"audio\"," +				"payload = (int) " +					GST_RTP_PAYLOAD_DYNAMIC_STRING ", " +				"clock-rate = (int) { 16000, 32000, " +					"44100, 48000 }, " +				"encoding-name = (string) \"SBC\"; "  				"application/x-rtp, "  				"media = (string) \"audio\", "  				"payload = (int) " @@ -231,7 +235,7 @@ static gint gst_avdtp_sink_bluetooth_recvmsg_fd(GstAvdtpSink *sink)  	return 0;  } -static gboolean gst_avdtp_sink_init_pkt_conf(GstAvdtpSink *sink, +static gboolean gst_avdtp_sink_init_sbc_pkt_conf(GstAvdtpSink *sink,  					GstCaps *caps,  					sbc_capabilities_t *pkt)  { @@ -242,9 +246,10 @@ static gboolean gst_avdtp_sink_init_pkt_conf(GstAvdtpSink *sink,  	GstStructure *structure = gst_caps_get_structure(caps, 0);  	name = gst_structure_get_name(structure); -	/* FIXME only sbc supported here, should suport mp3 */ +  	if (!(IS_SBC(name))) { -		GST_ERROR_OBJECT(sink, "Unsupported format %s", name); +		GST_ERROR_OBJECT(sink, "Unexpected format %s, " +				"was expecting sbc", name);  		return FALSE;  	} @@ -814,7 +819,7 @@ static void gst_avdtp_sink_tag(const GstTagList *taglist,  		if (!gst_tag_list_get_boolean(taglist, tag, &crc)) {  			GST_WARNING_OBJECT(self, "failed to get crc tag"); -			self->mpeg_stream_changed = TRUE; +			return;  		}  		gst_avdtp_sink_set_crc(self, crc); @@ -824,7 +829,7 @@ static void gst_avdtp_sink_tag(const GstTagList *taglist,  		if (!gst_tag_list_get_string(taglist, tag, &channel_mode)) {  			GST_WARNING_OBJECT(self,  				"failed to get channel-mode tag"); -			self->mpeg_stream_changed = TRUE; +			return;  		}  		self->channel_mode = gst_avdtp_sink_get_channel_mode( @@ -883,7 +888,6 @@ static gboolean gst_avdtp_sink_start(GstBaseSink *basesink)  	self->stream_caps = NULL;  	self->mp3_using_crc = -1;  	self->channel_mode = -1; -	self->mpeg_stream_changed = FALSE;  	if (!gst_avdtp_sink_get_capabilities(self)) {  		GST_ERROR_OBJECT(self, "failed to get capabilities " @@ -957,8 +961,17 @@ static gboolean gst_avdtp_sink_init_mp3_pkt_conf(  {  	const GValue *value = NULL;  	gint rate, layer; +	const gchar* name;  	GstStructure *structure = gst_caps_get_structure(caps, 0); +	name = gst_structure_get_name(structure); + +	if (!(IS_MPEG_AUDIO(name))) { +		GST_ERROR_OBJECT(self, "Unexpected format %s, " +				"was expecting mp3", name); +		return FALSE; +	} +  	/* layer */  	value = gst_structure_get_value(structure, "layer");  	layer = g_value_get_int(value); @@ -1016,9 +1029,6 @@ static gboolean gst_avdtp_sink_init_mp3_pkt_conf(  	/* vbr - we always say its vbr, we don't have how to know it */  	pkt->bitrate = 0x8000; -	/* bitrate - we don't set anything, its vbr */ -	/* FIXME - is this right? */ -  	return TRUE;  } @@ -1044,7 +1054,7 @@ static gboolean gst_avdtp_sink_configure(GstAvdtpSink *self,  	structure = gst_caps_get_structure(caps, 0);  	if (gst_structure_has_name(structure, "audio/x-sbc")) -		ret = gst_avdtp_sink_init_pkt_conf(self, caps, +		ret = gst_avdtp_sink_init_sbc_pkt_conf(self, caps,  				&req->sbc_capabilities);  	else if (gst_structure_has_name(structure, "audio/mpeg"))  		ret = gst_avdtp_sink_init_mp3_pkt_conf(self, caps, @@ -1188,8 +1198,8 @@ static void gst_avdtp_sink_class_init(GstAvdtpSinkClass *klass)  					"Bluetooth remote device address",  					NULL, G_PARAM_READWRITE)); -	GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "a2dpsendersink", 0, -				"A2DP sink element"); +	GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "avdtpsink", 0, +				"A2DP headset sink element");  }  static void gst_avdtp_sink_init(GstAvdtpSink *self, @@ -1203,6 +1213,11 @@ static void gst_avdtp_sink_init(GstAvdtpSink *self,  	self->dev_caps = NULL;  	self->sink_lock = g_mutex_new(); + +	/* FIXME this is for not synchronizing with clock, should be tested +	 * with devices to see the behaviour +	gst_base_sink_set_sync(GST_BASE_SINK(self), FALSE); +	*/  }  static GIOError gst_avdtp_sink_audioservice_send( @@ -1325,9 +1340,7 @@ void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc)  	/* test if we already received a different crc */  	if (self->mp3_using_crc != -1 && new_crc != self->mp3_using_crc) { -		GST_ERROR_OBJECT(self, "crc changed during stream"); -		/* FIXME test this, its not being used anywhere */ -		self->mpeg_stream_changed = TRUE; +		GST_WARNING_OBJECT(self, "crc changed during stream");  		return;  	}  	self->mp3_using_crc = new_crc; @@ -1342,8 +1355,8 @@ void gst_avdtp_sink_set_channel_mode(GstAvdtpSink *self,  	new_mode = gst_avdtp_sink_get_channel_mode(mode);  	if (self->channel_mode != -1 && new_mode != self->channel_mode) { -		GST_ERROR_OBJECT(self, "channel mode changed during stream"); -		self->mpeg_stream_changed = TRUE; +		GST_WARNING_OBJECT(self, "channel mode changed during stream"); +		return;  	}  	self->channel_mode = new_mode; diff --git a/audio/gstavdtpsink.h b/audio/gstavdtpsink.h index d0380829..237597da 100644 --- a/audio/gstavdtpsink.h +++ b/audio/gstavdtpsink.h @@ -57,7 +57,6 @@ struct _GstAvdtpSink {  	GIOChannel *server;  	/* mp3 stream data (outside caps data)*/ -	gboolean mpeg_stream_changed;  	gint mp3_using_crc;  	gint channel_mode; diff --git a/audio/gstrtpsbcpay.c b/audio/gstrtpsbcpay.c index 25bf70eb..ba2a4741 100644 --- a/audio/gstrtpsbcpay.c +++ b/audio/gstrtpsbcpay.c @@ -77,7 +77,7 @@ static const GstElementDetails gst_rtp_sbc_pay_details =  static GstStaticPadTemplate gst_rtp_sbc_pay_sink_factory =  	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, -		GST_STATIC_CAPS("audio/x-sbc, " /* FIXME remove those caps? */ +		GST_STATIC_CAPS("audio/x-sbc, "  				"rate = (int) { 16000, 32000, 44100, 48000 }, "  				"channels = (int) [ 1, 2 ], "  				"mode = (string) { mono, dual, stereo, joint }, " @@ -89,7 +89,12 @@ static GstStaticPadTemplate gst_rtp_sbc_pay_sink_factory =  static GstStaticPadTemplate gst_rtp_sbc_pay_src_factory =  	GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, -		GST_STATIC_CAPS("application/x-rtp") /* FIXME put things here */ +		GST_STATIC_CAPS( +			"application/x-rtp, " +			"media = (string) \"audio\"," +			"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " +			"clock-rate = (int) { 16000, 32000, 44100, 48000 }," +			"encoding-name = (string) \"SBC\"")  	);  static void gst_rtp_sbc_pay_set_property (GObject * object, guint prop_id, @@ -148,7 +153,7 @@ static gboolean gst_rtp_sbc_pay_set_caps(GstBaseRTPPayload *payload,  	sbcpay->frame_length = frame_len; -	gst_basertppayload_set_options (payload, "audio", FALSE, "SBC", rate); +	gst_basertppayload_set_options (payload, "audio", TRUE, "SBC", rate);  	GST_DEBUG_OBJECT(payload, "calculated frame length: %d ", frame_len); @@ -209,6 +214,8 @@ static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload,  	GstRtpSBCPay *sbcpay;  	guint available; +	/* FIXME check for negotiation */ +  	sbcpay = GST_RTP_SBC_PAY(payload);  	gst_adapter_push(sbcpay->adapter, gst_buffer_copy(buffer)); diff --git a/audio/gstsbcdec.c b/audio/gstsbcdec.c index 8c27daba..a686a406 100644 --- a/audio/gstsbcdec.c +++ b/audio/gstsbcdec.c @@ -80,26 +80,12 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)  	while (offset < size) {  		GstBuffer *output;  		GstPadTemplate *template; -		GstCaps *caps, *temp; +		GstCaps *caps;  		int consumed; -		caps = gst_caps_new_simple("audio/x-raw-int", -				"rate", G_TYPE_INT, dec->sbc.rate, -				"channels", G_TYPE_INT, dec->sbc.channels, -				NULL); - -		template = gst_static_pad_template_get(&sbc_dec_src_factory); - -		temp = gst_caps_intersect(caps, -					gst_pad_template_get_caps(template)); - -		gst_caps_unref(caps); -  		res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad,  						GST_BUFFER_OFFSET_NONE, -						codesize, temp, &output); - -		gst_caps_unref(temp); +						codesize, NULL, &output);  		if (res != GST_FLOW_OK)  			goto done; @@ -110,7 +96,25 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)  		if (consumed <= 0)  			break; -		GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer); +		/* we will reuse the same caps object */ +		if (dec->outcaps == NULL) { +			caps = gst_caps_new_simple("audio/x-raw-int", +					"rate", G_TYPE_INT, dec->sbc.rate, +					"channels", G_TYPE_INT, dec->sbc.channels, +					NULL); + +			template = gst_static_pad_template_get(&sbc_dec_src_factory); + +			dec->outcaps = gst_caps_intersect(caps, +						gst_pad_template_get_caps(template)); + +			gst_caps_unref(caps); +		} + +		gst_buffer_set_caps(output, dec->outcaps); + +		/* FIXME get a real timestamp */ +		GST_BUFFER_TIMESTAMP(output) = GST_CLOCK_TIME_NONE;  		res = gst_pad_push(dec->srcpad, output);  		if (res != GST_FLOW_OK) @@ -143,6 +147,7 @@ static GstStateChangeReturn sbc_dec_change_state(GstElement *element,  			dec->buffer = NULL;  		}  		sbc_init(&dec->sbc, 0); +		dec->outcaps = NULL;  		break;  	case GST_STATE_CHANGE_PAUSED_TO_READY: @@ -152,6 +157,10 @@ static GstStateChangeReturn sbc_dec_change_state(GstElement *element,  			dec->buffer = NULL;  		}  		sbc_finish(&dec->sbc); +		if (dec->outcaps) { +			gst_caps_unref(dec->outcaps); +			dec->outcaps = NULL; +		}  		break;  	default: @@ -197,6 +206,8 @@ static void gst_sbc_dec_init(GstSbcDec *self, GstSbcDecClass *klass)  	self->srcpad = gst_pad_new_from_static_template(  			&sbc_dec_src_factory, "src");  	gst_element_add_pad(GST_ELEMENT(self), self->srcpad); + +	self->outcaps = NULL;  }  gboolean gst_sbc_dec_plugin_init (GstPlugin * plugin) diff --git a/audio/gstsbcdec.h b/audio/gstsbcdec.h index 0bb0b57e..a88f8da5 100644 --- a/audio/gstsbcdec.h +++ b/audio/gstsbcdec.h @@ -49,6 +49,9 @@ struct _GstSbcDec {  	GstBuffer *buffer; +	/* caps for outgoing buffers */ +	GstCaps *outcaps; +  	sbc_t sbc;  }; diff --git a/audio/gstsbcparse.c b/audio/gstsbcparse.c index 49d0bb6e..1f699620 100644 --- a/audio/gstsbcparse.c +++ b/audio/gstsbcparse.c @@ -43,7 +43,8 @@ static const GstElementDetails sbc_parse_details =  static GstStaticPadTemplate sbc_parse_sink_factory =  	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, -		GST_STATIC_CAPS("audio/x-sbc")); +		GST_STATIC_CAPS("audio/x-sbc," +				"parsed = (boolean) false"));  static GstStaticPadTemplate sbc_parse_src_factory =  	GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -54,86 +55,8 @@ static GstStaticPadTemplate sbc_parse_src_factory =  				"blocks = (int) { 4, 8, 12, 16 }, "  				"subbands = (int) { 4, 8 }, "  				"allocation = (string) { snr, loudness }," -				"bitpool = (int) [ 2, 64 ]")); - -static gboolean sbc_parse_sink_setcaps(GstPad * pad, GstCaps * caps) -{ -	GstSbcParse *parse; -	GstStructure *structure; -	gint rate, channels; - -	parse = GST_SBC_PARSE(GST_PAD_PARENT(pad)); - -	structure = gst_caps_get_structure(caps, 0); - -	if (!gst_structure_get_int(structure, "rate", &rate)) -		return FALSE; - -	if (!gst_structure_get_int(structure, "channels", &channels)) -		return FALSE; - -	if (!(parse->rate == 0 || rate == parse->rate)) -		return FALSE; - -	if (!(parse->channels == 0 || channels == parse->channels)) -		return FALSE; - -	parse->rate = rate; -	parse->channels = channels; - -	return gst_sbc_util_fill_sbc_params(&parse->sbc, caps); -} - -static GstCaps* sbc_parse_src_getcaps(GstPad *pad) -{ -	GstCaps *caps; -	const GstCaps *allowed_caps; -	GstStructure *structure; -	GValue *value; -	GstSbcParse *parse = GST_SBC_PARSE(GST_PAD_PARENT(pad)); - -	allowed_caps = gst_pad_get_allowed_caps(pad); -	if (allowed_caps == NULL) -		allowed_caps = gst_pad_get_pad_template_caps(pad); -	caps = gst_caps_copy(allowed_caps); - -	value = g_new0(GValue, 1); - -	structure = gst_caps_get_structure(caps, 0); - -	if (parse->rate != 0) -		gst_sbc_util_set_structure_int_param(structure, "rate", -				parse->rate, value); -	if (parse->channels != 0) -		gst_sbc_util_set_structure_int_param(structure, "channels", -				parse->channels, value); - -	g_free(value); - -	return caps; -} - -static gboolean sbc_parse_src_acceptcaps(GstPad *pad, GstCaps *caps) -{ -	GstStructure *structure; -	GstSbcParse *parse; -	gint rate, channels; - -	parse = GST_SBC_PARSE(GST_PAD_PARENT(pad)); - -	structure = gst_caps_get_structure(caps, 0); - -	if (!gst_structure_get_int(structure, "rate", &rate)) -		return FALSE; -	if (!gst_structure_get_int(structure, "channels", &channels)) -		return FALSE; - -	if ((parse->rate == 0 || parse->rate == rate) -		&& (parse->channels == 0 || parse->channels == channels)) -		return TRUE; - -	return FALSE; -} +				"bitpool = (int) [ 2, 64 ]," +				"parsed = (boolean) true"));  static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer)  { @@ -261,17 +184,10 @@ static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass)  		&sbc_parse_sink_factory, "sink");  	gst_pad_set_chain_function(self->sinkpad,  		GST_DEBUG_FUNCPTR(sbc_parse_chain)); -	gst_pad_set_setcaps_function (self->sinkpad, -		GST_DEBUG_FUNCPTR (sbc_parse_sink_setcaps));  	gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);  	self->srcpad = gst_pad_new_from_static_template(  		&sbc_parse_src_factory, "src"); -	gst_pad_set_getcaps_function (self->srcpad, -		GST_DEBUG_FUNCPTR (sbc_parse_src_getcaps)); -	gst_pad_set_acceptcaps_function (self->srcpad, -		GST_DEBUG_FUNCPTR (sbc_parse_src_acceptcaps)); -	/* FIXME get encoding parameters on set caps */  	gst_element_add_pad(GST_ELEMENT(self), self->srcpad);  } diff --git a/audio/gstsbcutil.c b/audio/gstsbcutil.c index 78024f7e..e5d21af0 100644 --- a/audio/gstsbcutil.c +++ b/audio/gstsbcutil.c @@ -364,9 +364,12 @@ GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message)  		goto error;  	} else {  		value = gst_structure_get_value(structure, "mode"); -		if (GST_VALUE_HOLDS_LIST(value)) -			mode = gst_sbc_get_mode_from_list(value); -		else +		if (GST_VALUE_HOLDS_LIST(value)) { +			if (channels == 1) +				mode = "mono"; +			else +				mode = gst_sbc_get_mode_from_list(value); +		} else  			mode = g_value_get_string(value);  	} | 
