diff options
Diffstat (limited to 'audio/gstsbcparse.c')
| -rw-r--r-- | audio/gstsbcparse.c | 186 | 
1 files changed, 170 insertions, 16 deletions
| diff --git a/audio/gstsbcparse.c b/audio/gstsbcparse.c index 5097a85f..e204870b 100644 --- a/audio/gstsbcparse.c +++ b/audio/gstsbcparse.c @@ -28,6 +28,7 @@  #include <string.h>  #include "gstsbcparse.h" +#include "gstsbcutil.h"  GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug);  #define GST_CAT_DEFAULT sbc_parse_debug @@ -54,6 +55,170 @@ static GstStaticPadTemplate sbc_parse_src_factory =  				"subbands = (int) { 4, 8 }, "  				"allocation = (string) { snr, loudness }")); +/* +	Creates a fixed caps from the caps given. + +*/ +static GstCaps* sbc_parse_select_caps(GstSbcParse *parse, GstCaps *caps) +{ +	GstCaps *result; +	GstStructure *structure; +	const GValue *value; +	gboolean error = FALSE; +	gint temp, rate, channels, blocks, subbands; +	const gchar* allocation = NULL; +	const gchar* mode = NULL; +	const gchar* error_message = NULL; + +	structure = gst_caps_get_structure(caps, 0); + +	/* rate */ +	if (!gst_structure_has_field(structure, "rate")) { +		error = TRUE; +		error_message = "no rate."; +		goto error; +	} else { +		value = gst_structure_get_value(structure, "rate"); +		if (GST_VALUE_HOLDS_LIST(value)) { +			temp = gst_sbc_select_rate_from_list(value); +		} else if (GST_VALUE_HOLDS_INT_RANGE(value)) { +			temp = gst_sbc_select_rate_from_range(value); +		} else { +			temp = g_value_get_int(value); +		} +		rate = temp; +	} + +	/* channels */ +	if (!gst_structure_has_field(structure, "channels")) { +		error = TRUE; +		error_message = "no channels."; +		goto error; +	} else { +		value = gst_structure_get_value(structure, "channels"); +		if (GST_VALUE_HOLDS_LIST(value)) { +			temp = gst_sbc_select_channels_from_list(value); +		} else if (GST_VALUE_HOLDS_INT_RANGE(value)) { +			temp = gst_sbc_select_channels_from_range(value); +		} else { +			temp = g_value_get_int(value); +		} +		channels = temp; +	} + +	/* blocks */ +	if (!gst_structure_has_field(structure, "blocks")) { +		error = TRUE; +		error_message = "no blocks."; +		goto error; +	} else { +		value = gst_structure_get_value(structure, "blocks"); +		if (GST_VALUE_HOLDS_LIST(value)) { +			temp = gst_sbc_select_blocks_from_list(value); +		} else if (GST_VALUE_HOLDS_INT_RANGE(value)) { +			temp = gst_sbc_select_blocks_from_range(value); +		} else { +			temp = g_value_get_int(value); +		} +		blocks = temp; +	} + +	/* subbands */ +	if (!gst_structure_has_field(structure, "subbands")) { +		error = TRUE; +		error_message = "no subbands."; +		goto error; +	} else { +		value = gst_structure_get_value(structure, "subbands"); +		if (GST_VALUE_HOLDS_LIST(value)) { +			temp = gst_sbc_select_subbands_from_list(value); +		} else if (GST_VALUE_HOLDS_INT_RANGE(value)) { +			temp = gst_sbc_select_subbands_from_range(value); +		} else { +			temp = g_value_get_int(value); +		} +		subbands = temp; +	} + +	/* allocation */ +	if (!gst_structure_has_field(structure, "allocation")) { +		error = TRUE; +		error_message = "no allocation."; +		goto error; +	} else { +		value = gst_structure_get_value(structure, "allocation"); +		if (GST_VALUE_HOLDS_LIST(value)) { +			allocation = gst_sbc_get_allocation_from_list(value); +		} else { +			allocation = g_value_get_string(value); +		} +	} + +	/* mode */ +	if (!gst_structure_has_field(structure, "mode")) { +		error = TRUE; +		error_message = "no mode."; +		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 { +			mode = g_value_get_string(value); +		} +	} + +error: +	if (error) { +		GST_ERROR_OBJECT (parse, "Invalid input caps: %s", +				error_message); +		return NULL; +	} + + +	result = gst_caps_new_simple("audio/x-sbc", +					"rate", G_TYPE_INT, rate, +					"channels", G_TYPE_INT, channels, +					"mode", G_TYPE_STRING, mode, +					"blocks", G_TYPE_INT, blocks, +					"subbands", G_TYPE_INT, subbands, +					"allocation", G_TYPE_STRING, allocation, +					NULL); +	parse->sbc.rate = rate; +	parse->sbc.channels = channels; +	parse->sbc.blocks = blocks; +	parse->sbc.subbands = subbands; +	parse->sbc.joint = gst_sbc_get_mode_int(mode); +	parse->sbc.allocation = gst_sbc_get_allocation_mode_int(allocation); + +	return result; +} + +static gboolean sbc_parse_sink_setcaps(GstPad * pad, GstCaps * caps) +{ +	GstSbcParse *parse; +	GstCaps *inter, *other, *srccaps; + +	parse = GST_SBC_PARSE(GST_PAD_PARENT(pad)); + +	other = gst_pad_peer_get_caps(parse->srcpad); +	if (other == NULL) +		other = gst_caps_new_any(); + +	inter = gst_caps_intersect(caps, other); +	srccaps = sbc_parse_select_caps(parse, inter); +	if (srccaps == NULL) +		return FALSE; + +	gst_pad_set_caps(parse->srcpad, srccaps); + +	gst_caps_unref(inter); +	gst_caps_unref(other); +	gst_caps_unref(srccaps); + +	return TRUE; +} +  static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer)  {  	GstSbcParse *parse = GST_SBC_PARSE(gst_pad_get_parent(pad)); @@ -78,31 +243,20 @@ static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer)  	while (offset < size) {  		GstBuffer *output; -		GstPadTemplate *template; -		GstCaps *caps, *temp; +		GstCaps *temp;  		int consumed;  		consumed = sbc_parse(&parse->sbc, data + offset, size - offset);  		if (consumed <= 0)  			break; -		caps = gst_caps_new_simple("audio/x-sbc", -				"rate", G_TYPE_INT, parse->sbc.rate, -				"channels", G_TYPE_INT, parse->sbc.channels, -				NULL); -		template = gst_static_pad_template_get(&sbc_parse_src_factory); - -		temp = gst_caps_intersect(caps, -					gst_pad_template_get_caps(template)); - -		gst_caps_unref(caps); +		temp = GST_PAD_CAPS(parse->srcpad);  		res = gst_pad_alloc_buffer_and_set_caps(parse->srcpad,  						GST_BUFFER_OFFSET_NONE,  						consumed, temp, &output); -		gst_caps_unref(temp);  		if (res != GST_FLOW_OK)  			goto done; @@ -141,7 +295,6 @@ static GstStateChangeReturn sbc_parse_change_state(GstElement *element,  		}  		sbc_init(&parse->sbc, 0);  		break; -  	case GST_STATE_CHANGE_PAUSED_TO_READY:  		GST_DEBUG("Finish subband codec");  		if (parse->buffer) { @@ -150,7 +303,6 @@ static GstStateChangeReturn sbc_parse_change_state(GstElement *element,  		}  		sbc_finish(&parse->sbc);  		break; -  	default:  		break;  	} @@ -180,13 +332,15 @@ static void gst_sbc_parse_class_init(GstSbcParseClass *klass)  	element_class->change_state = GST_DEBUG_FUNCPTR(sbc_parse_change_state);  	GST_DEBUG_CATEGORY_INIT(sbc_parse_debug, "sbcparse", 0, -						"SBC parsing element"); +				"SBC parsing element");  }  static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass)  {  	self->sinkpad = gst_pad_new_from_static_template(&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"); | 
