diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2007-08-25 19:32:03 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2007-08-25 19:32:03 +0000 | 
| commit | d542fb37a81d1d96604d41b36a6d6b11087ba2da (patch) | |
| tree | def78906f93346b776df63bebdb334a8fa73acee | |
| parent | 80c75b2aeb116ae9eb70b864f5dac1891551787d (diff) | |
Implement full encoding support
| -rw-r--r-- | audio/gstsbcenc.c | 115 | ||||
| -rw-r--r-- | audio/gstsbcenc.h | 4 | 
2 files changed, 117 insertions, 2 deletions
| diff --git a/audio/gstsbcenc.c b/audio/gstsbcenc.c index 6e63ac45..86a66270 100644 --- a/audio/gstsbcenc.c +++ b/audio/gstsbcenc.c @@ -25,7 +25,7 @@  #include <config.h>  #endif -#include "sbc.h" +#include <string.h>  #include "gstsbcenc.h" @@ -40,21 +40,132 @@ static const GstElementDetails sbc_enc_details =  				"Encode a SBC audio stream",  				"Marcel Holtmann <marcel@holtmann.org>"); +static GstStaticPadTemplate sbc_enc_sink_factory = +	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, +		GST_STATIC_CAPS("audio/x-raw-int, " +				"rate = (int) { 16000, 32000, 44100, 48000 }, " +				"channels = (int) [ 1, 2 ], " +				"endianness = (int) BYTE_ORDER, " +				"signed = (boolean) true, " +				"width = (int) 16, " +				"depth = (int) 16")); + +static GstStaticPadTemplate sbc_enc_src_factory = +	GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, +		GST_STATIC_CAPS("audio/x-sbc")); + +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; +		int consumed; + +		consumed = sbc_encode(&enc->sbc, data + offset, size - offset); +		if (consumed <= 0) +			break; + +		caps = GST_PAD_CAPS(enc->srcpad); + +		res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad, +						GST_BUFFER_OFFSET_NONE, +						enc->sbc.len, caps, &output); + +		if (res != GST_FLOW_OK) +			goto done; + +		memcpy(GST_BUFFER_DATA(output), enc->sbc.data, enc->sbc.len); + +		res = gst_pad_push(enc->srcpad, output); +		if (res != GST_FLOW_OK) +			goto done; + +		offset += consumed; +	} + +	if (offset < size) +		res = GST_FLOW_ERROR; + +done: +	gst_buffer_unref(buffer); +	gst_object_unref(enc); + +	return res; +} + +static GstStateChangeReturn sbc_enc_change_state(GstElement *element, +						GstStateChange transition) +{ +	GstSbcEnc *enc = GST_SBC_ENC(element); + +	switch (transition) { +	case GST_STATE_CHANGE_READY_TO_PAUSED: +		GST_DEBUG("Setup subband codec"); +		sbc_init(&enc->sbc, 0); +		break; + +	case GST_STATE_CHANGE_PAUSED_TO_READY: +		GST_DEBUG("Finish subband codec"); +		sbc_finish(&enc->sbc); +		break; + +	default: +		break; +	} + +	return parent_class->change_state(element, transition); +} +  static void gst_sbc_enc_base_init(gpointer g_class)  {  	GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); +	gst_element_class_add_pad_template(element_class, +		gst_static_pad_template_get(&sbc_enc_sink_factory)); + +	gst_element_class_add_pad_template(element_class, +		gst_static_pad_template_get(&sbc_enc_src_factory)); +  	gst_element_class_set_details(element_class, &sbc_enc_details);  }  static void gst_sbc_enc_class_init(GstSbcEncClass *klass)  { +	GstElementClass *element_class = GST_ELEMENT_CLASS(klass); +  	parent_class = g_type_class_peek_parent(klass); +	element_class->change_state = GST_DEBUG_FUNCPTR(sbc_enc_change_state); +  	GST_DEBUG_CATEGORY_INIT(sbc_enc_debug, "sbcenc", 0,  						"SBC encoding element");  } -static void gst_sbc_enc_init(GstSbcEnc *sbcenc, 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_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);  } diff --git a/audio/gstsbcenc.h b/audio/gstsbcenc.h index 64457d21..491135c1 100644 --- a/audio/gstsbcenc.h +++ b/audio/gstsbcenc.h @@ -23,6 +23,8 @@  #include <gst/gst.h> +#include "sbc.h" +  G_BEGIN_DECLS  #define GST_TYPE_SBC_ENC \ @@ -44,6 +46,8 @@ struct _GstSbcEnc {  	GstPad *sinkpad;  	GstPad *srcpad; + +	sbc_t sbc;  };  struct _GstSbcEncClass { | 
