diff options
| -rw-r--r-- | audio/gstsbcenc.c | 156 | ||||
| -rw-r--r-- | audio/gstsbcenc.h | 5 | 
2 files changed, 146 insertions, 15 deletions
| diff --git a/audio/gstsbcenc.c b/audio/gstsbcenc.c index 812c1193..ea97563e 100644 --- a/audio/gstsbcenc.c +++ b/audio/gstsbcenc.c @@ -28,6 +28,13 @@  #include <string.h>  #include "gstsbcenc.h" +#include "gstsbcutil.h" + + +#define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO +#define SBC_ENC_DEFAULT_BLOCKS 16 +#define SBC_ENC_DEFAULT_SUB_BANDS 8 +#define SBC_ENC_DEFAULT_ALLOCATION CFG_ALLOCATION_AUTO  GST_DEBUG_CATEGORY_STATIC(sbc_enc_debug);  #define GST_CAT_DEFAULT sbc_enc_debug @@ -52,9 +59,31 @@ static GType gst_sbc_mode_get_type(void)  	return sbc_mode_type;  } +#define GST_TYPE_SBC_ALLOCATION (gst_sbc_allocation_get_type()) + +static GType gst_sbc_allocation_get_type(void) +{ +	static GType sbc_allocation_type = 0; +	static GEnumValue sbc_allocations[] = { +		{ CFG_ALLOCATION_AUTO,		"Auto",		"auto" }, +		{ CFG_ALLOCATION_LOUDNESS,	"Loudness",	"loudness" }, +		{ CFG_ALLOCATION_SNR,		"SNR",		"snr" }, +		{ -1, NULL, NULL} +	}; + +	if (!sbc_allocation_type) +		sbc_allocation_type = g_enum_register_static( +				"GstSbcAllocation", sbc_allocations); + +	return sbc_allocation_type; +} +  enum {  	PROP_0,  	PROP_MODE, +	PROP_ALLOCATION, +	PROP_BLOCKS, +	PROP_SUB_BANDS  };  GST_BOILERPLATE(GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); @@ -85,27 +114,81 @@ static GstStaticPadTemplate sbc_enc_src_factory =  				"subbands = (int) { 4, 8 }, "  				"allocation = (string) { snr, loudness }")); + +static GstCaps* sbc_enc_generate_srcpad_caps(GstSbcEnc *enc, GstCaps *caps) +{ +	gint rate; +	gint channels; +	GstCaps* src_caps; +	GstStructure *structure; + +	structure = gst_caps_get_structure(caps, 0); + +	if (!gst_structure_get_int (structure, "rate", &rate)) +		return NULL; +	if (!gst_structure_get_int (structure, "channels", &channels)) +		return NULL; + +	enc->sbc.rate = rate; +	enc->sbc.channels = channels; + +	if (enc->mode == 0) +		enc->sbc.joint = CFG_MODE_JOINT_STEREO; +	else +		enc->sbc.joint = enc->mode; + +	enc->sbc.blocks = enc->blocks; +	enc->sbc.subbands = enc->subbands; +	if (enc->allocation == 0) +		enc->sbc.allocation = CFG_ALLOCATION_LOUDNESS; +	else +		enc->sbc.allocation = enc->allocation; + +	src_caps = gst_caps_new_simple("audio/x-sbc", "rate", G_TYPE_INT, +			enc->sbc.rate, "channels", G_TYPE_INT, +			enc->sbc.channels, "mode", G_TYPE_STRING, +			gst_sbc_get_mode_string(enc->sbc.joint), "subbands", +			G_TYPE_INT, enc->sbc.subbands, "blocks", G_TYPE_INT, +			enc->sbc.blocks, "allocation", G_TYPE_STRING, +			gst_sbc_get_allocation_string(enc->sbc.allocation), +			NULL); + +	return src_caps; +} + +static gboolean sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +{ +	GstSbcEnc *enc; +	GstStructure *structure; +	GstCaps *othercaps; + +	enc = GST_SBC_ENC(GST_PAD_PARENT (pad)); +	structure = gst_caps_get_structure(caps, 0); + +	othercaps = sbc_enc_generate_srcpad_caps(enc, caps); +	if (othercaps == NULL) +		goto error; + +	gst_pad_set_caps (enc->srcpad, othercaps); +	gst_caps_unref(othercaps); + +	return TRUE; + +error: +	GST_ERROR_OBJECT (enc, "invalid input caps"); +	return FALSE; +} +  static GstFlowReturn sbc_enc_chain(GstPad *pad, GstBuffer *buffer)  {  	GstSbcEnc *enc = GST_SBC_ENC(gst_pad_get_parent(pad));  	GstFlowReturn res = GST_FLOW_OK; -	GstStructure *structure; -	gint rate, channels;  	guint size, offset = 0;  	guint8 *data;  	data = GST_BUFFER_DATA(buffer);  	size = GST_BUFFER_SIZE(buffer); -	structure = gst_caps_get_structure(GST_PAD_CAPS(pad), 0); -	gst_structure_get_int(structure, "rate", &rate); -	gst_structure_get_int(structure, "channels", &channels); - -	enc->sbc.rate = rate; -	enc->sbc.channels = channels; -	enc->sbc.subbands = 8; -	enc->sbc.joint = 0; -  	while (offset < size) {  		GstBuffer *output;  		GstCaps *caps; @@ -184,11 +267,23 @@ static void gst_sbc_enc_set_property(GObject *object, guint prop_id,  {  	GstSbcEnc *enc = GST_SBC_ENC(object); +	/* TODO - CAN ONLY BE CHANGED ON READY AND BELOW */ +  	switch (prop_id) {  	case PROP_MODE:  		enc->mode = g_value_get_enum(value);  		break; - +	case PROP_ALLOCATION: +		enc->allocation = g_value_get_enum(value); +		break; +	case PROP_BLOCKS: +		/* TODO - verify consistency */ +		enc->blocks = g_value_get_int(value); +		break; +	case PROP_SUB_BANDS: +		/* TODO - verify consistency */ +		enc->subbands = g_value_get_int(value); +		break;  	default:  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);  		break; @@ -204,7 +299,15 @@ static void gst_sbc_enc_get_property(GObject *object, guint prop_id,  	case PROP_MODE:  		g_value_set_enum(value, enc->mode);  		break; - +	case PROP_ALLOCATION: +		g_value_set_enum(value, enc->allocation); +		break; +	case PROP_BLOCKS: +		g_value_set_int(value, enc->blocks); +		break; +	case PROP_SUB_BANDS: +		g_value_set_int(value, enc->subbands); +		break;  	default:  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);  		break; @@ -224,8 +327,24 @@ static void gst_sbc_enc_class_init(GstSbcEncClass *klass)  	element_class->change_state = GST_DEBUG_FUNCPTR(sbc_enc_change_state);  	g_object_class_install_property(object_class, PROP_MODE, -			g_param_spec_enum("mode", "Mode", "Encoding mode", -				GST_TYPE_SBC_MODE, 0, G_PARAM_READWRITE)); +			g_param_spec_enum("mode", "Mode", +				"Encoding mode", GST_TYPE_SBC_MODE, +				SBC_ENC_DEFAULT_MODE, G_PARAM_READWRITE)); + +	g_object_class_install_property(object_class, PROP_ALLOCATION, +			g_param_spec_enum("allocation", "Allocation", +				"Allocation mode", GST_TYPE_SBC_ALLOCATION, +				SBC_ENC_DEFAULT_ALLOCATION, G_PARAM_READWRITE)); + +	g_object_class_install_property(object_class, PROP_BLOCKS, +			g_param_spec_int("blocks", "Blocks", +				"Blocks", 0, G_MAXINT, +				SBC_ENC_DEFAULT_BLOCKS,	G_PARAM_READWRITE)); + +	g_object_class_install_property(object_class, PROP_SUB_BANDS, +			g_param_spec_int("subbands", "Sub Bands", +				"Sub Bands", 0, G_MAXINT, +				SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE));  	GST_DEBUG_CATEGORY_INIT(sbc_enc_debug, "sbcenc", 0,  						"SBC encoding element"); @@ -234,9 +353,16 @@ static void gst_sbc_enc_class_init(GstSbcEncClass *klass)  static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)  {  	self->sinkpad = gst_pad_new_from_static_template(&sbc_enc_sink_factory, "sink"); +	gst_pad_set_setcaps_function (self->sinkpad, +			GST_DEBUG_FUNCPTR (sbc_enc_sink_setcaps));  	gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);  	self->srcpad = gst_pad_new_from_static_template(&sbc_enc_src_factory, "src");  	gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR(sbc_enc_chain));  	gst_element_add_pad(GST_ELEMENT(self), self->srcpad); + +	self->subbands = SBC_ENC_DEFAULT_SUB_BANDS; +	self->blocks = SBC_ENC_DEFAULT_BLOCKS; +	self->mode = SBC_ENC_DEFAULT_MODE; +	self->allocation = SBC_ENC_DEFAULT_ALLOCATION;  } diff --git a/audio/gstsbcenc.h b/audio/gstsbcenc.h index e7daf2d3..0a95bcef 100644 --- a/audio/gstsbcenc.h +++ b/audio/gstsbcenc.h @@ -24,6 +24,8 @@  #include <gst/gst.h>  #include "sbc.h" +#include "ipc.h" +  G_BEGIN_DECLS @@ -48,6 +50,9 @@ struct _GstSbcEnc {  	GstPad *srcpad;  	gint mode; +	gint blocks; +	gint allocation; +	gint subbands;  	sbc_t sbc;  }; | 
