diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-02-01 19:28:37 +0000 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-02-01 19:28:37 +0000 | 
| commit | ae689c59cc62acc9f160afe6beb6ccc07b6c6f55 (patch) | |
| tree | e086ade151baea0e5e9064c6cc72d0437bb6751d | |
| parent | 9225eadeb28150fcb0b05ec0b31349ce812dd3d0 (diff) | |
Add bitpool property and others fixes for gstreamer plugin.
| -rw-r--r-- | audio/gsta2dpsink.c | 13 | ||||
| -rw-r--r-- | audio/gstsbcenc.c | 177 | ||||
| -rw-r--r-- | audio/gstsbcenc.h | 2 | ||||
| -rw-r--r-- | audio/gstsbcutil.c | 64 | ||||
| -rw-r--r-- | audio/gstsbcutil.h | 3 | 
5 files changed, 181 insertions, 78 deletions
| diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c index 6595d0b5..4ff30b84 100644 --- a/audio/gsta2dpsink.c +++ b/audio/gsta2dpsink.c @@ -109,12 +109,12 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,  	element = gst_element_factory_make(elementname, name);  	if (element == NULL) { -		GST_ERROR_OBJECT(self, "Couldn't create %s", elementname); +		GST_DEBUG_OBJECT(self, "Couldn't create %s", elementname);  		return NULL;  	}  	if (!gst_bin_add(GST_BIN(self), element)) { -		GST_ERROR_OBJECT(self, "failed to add %s to the bin", +		GST_DEBUG_OBJECT(self, "failed to add %s to the bin",  						elementname);  		goto cleanup_and_fail;  	} @@ -122,14 +122,15 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,  	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", +		GST_DEBUG_OBJECT(self, "%s failed to go to playing",  						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); +			GST_DEBUG_OBJECT(self, "couldn't link %s", +					elementname);  			goto remove_element_and_fail;  		} @@ -293,10 +294,8 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,  		break;  	} -	if (ret == GST_STATE_CHANGE_FAILURE) { -		g_mutex_unlock(self->cb_mutex); +	if (ret == GST_STATE_CHANGE_FAILURE)  		return ret; -	}  	ret = GST_ELEMENT_CLASS(parent_class)->change_state(element,                          transition); diff --git a/audio/gstsbcenc.c b/audio/gstsbcenc.c index 08ddc14f..88737475 100644 --- a/audio/gstsbcenc.c +++ b/audio/gstsbcenc.c @@ -34,11 +34,16 @@  #define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_AUTO  #define SBC_ENC_DEFAULT_BLOCKS 0  #define SBC_ENC_DEFAULT_SUB_BANDS 0 -#define SBC_ENC_DEFAULT_BITPOOL 0  #define SBC_ENC_DEFAULT_ALLOCATION BT_A2DP_ALLOCATION_AUTO  #define SBC_ENC_DEFAULT_RATE 0  #define SBC_ENC_DEFAULT_CHANNELS 0 +#define SBC_ENC_BITPOOL_AUTO 1 +#define SBC_ENC_BITPOOL_MIN 2 +#define SBC_ENC_BITPOOL_MIN_STR "2" +#define SBC_ENC_BITPOOL_MAX 64 +#define SBC_ENC_BITPOOL_MAX_STR "64" +  GST_DEBUG_CATEGORY_STATIC(sbc_enc_debug);  #define GST_CAT_DEFAULT sbc_enc_debug @@ -81,12 +86,53 @@ static GType gst_sbc_allocation_get_type(void)  	return sbc_allocation_type;  } +#define GST_TYPE_SBC_BLOCKS (gst_sbc_blocks_get_type()) + +static GType gst_sbc_blocks_get_type(void) +{ +	static GType sbc_blocks_type = 0; +	static GEnumValue sbc_blocks[] = { +		{ 0,	"Auto",		"auto" }, +		{ 4,	"4",		"4" }, +		{ 8,	"8",		"8" }, +		{ 12,	"12",		"12" }, +		{ 16,	"16",		"16" }, +		{ -1, NULL, NULL} +	}; + +	if (!sbc_blocks_type) +		sbc_blocks_type = g_enum_register_static( +				"GstSbcBlocks", sbc_blocks); + +	return sbc_blocks_type; +} + +#define GST_TYPE_SBC_SUBBANDS (gst_sbc_subbands_get_type()) + +static GType gst_sbc_subbands_get_type(void) +{ +	static GType sbc_subbands_type = 0; +	static GEnumValue sbc_subbands[] = { +		{ 0,	"Auto",		"auto" }, +		{ 4,	"4 subbands",	"4" }, +		{ 8,	"8 subbands",	"8" }, +		{ -1, NULL, NULL} +	}; + +	if (!sbc_subbands_type) +		sbc_subbands_type = g_enum_register_static( +				"GstSbcSubbands", sbc_subbands); + +	return sbc_subbands_type; +} +  enum {  	PROP_0,  	PROP_MODE,  	PROP_ALLOCATION,  	PROP_BLOCKS, -	PROP_SUBBANDS +	PROP_SUBBANDS, +	PROP_BITPOOL  };  GST_BOILERPLATE(GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); @@ -116,7 +162,8 @@ static GstStaticPadTemplate sbc_enc_src_factory =  				"blocks = (int) { 4, 8, 12, 16 }, "  				"subbands = (int) { 4, 8 }, "  				"allocation = (string) { snr, loudness }," -				"bitpool = (int) [ 2, 64 ]")); +				"bitpool = (int) [ " SBC_ENC_BITPOOL_MIN_STR +				", " SBC_ENC_BITPOOL_MAX_STR " ]"));  gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps); @@ -150,6 +197,10 @@ static GstCaps* sbc_enc_generate_srcpad_caps(GstSbcEnc *enc)  		gst_sbc_util_set_structure_int_param(structure, "blocks",  			enc->blocks, value); +	if (enc->bitpool != SBC_ENC_BITPOOL_AUTO) +		gst_sbc_util_set_structure_int_param(structure, "bitpool", +			enc->bitpool, value); +  	if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO) {  		enum_class = g_type_class_ref(GST_TYPE_SBC_MODE);  		enum_value = g_enum_get_value(enum_class, enc->mode); @@ -201,7 +252,7 @@ static GstCaps* sbc_enc_src_caps_fixate(GstSbcEnc *enc, GstCaps *caps)  	result = gst_sbc_util_caps_fixate(caps, &error_message);  	if (!result) { -		GST_ERROR_OBJECT (enc, "Invalid input caps caused parsing " +		GST_WARNING_OBJECT (enc, "Invalid input caps caused parsing "  				"error: %s", error_message);  		g_free(error_message);  		return NULL; @@ -212,18 +263,13 @@ static GstCaps* sbc_enc_src_caps_fixate(GstSbcEnc *enc, GstCaps *caps)  static GstCaps* sbc_enc_get_fixed_srcpad_caps(GstSbcEnc *enc)  { -	GstCaps *peer_caps; -	GstCaps *src_caps;  	GstCaps *caps;  	gboolean res = TRUE;  	GstCaps *result_caps = NULL; -	peer_caps = gst_pad_peer_get_caps(enc->srcpad); -	if (!peer_caps) -		return NULL; - -	src_caps = sbc_enc_generate_srcpad_caps(enc); -	caps = gst_caps_intersect(src_caps, peer_caps); +	caps = gst_pad_get_allowed_caps(enc->srcpad); +	if (caps == NULL) +		caps = sbc_enc_src_getcaps(enc->srcpad);  	if (caps == GST_CAPS_NONE || gst_caps_is_empty(caps)) {  		res = FALSE; @@ -233,9 +279,6 @@ static GstCaps* sbc_enc_get_fixed_srcpad_caps(GstSbcEnc *enc)  	result_caps = sbc_enc_src_caps_fixate(enc, caps);  done: - -	gst_caps_unref(src_caps); -	gst_caps_unref(peer_caps);  	gst_caps_unref(caps);  	if (!res) @@ -256,45 +299,71 @@ static gboolean sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps)  	structure = gst_caps_get_structure(caps, 0);  	if (!gst_structure_get_int(structure, "rate", &rate)) -		goto error; +		return FALSE;  	if (!gst_structure_get_int(structure, "channels", &channels)) -		goto error; +		return FALSE;  	enc->rate = rate;  	enc->channels = channels;  	src_caps = sbc_enc_get_fixed_srcpad_caps(enc);  	if (!src_caps) -		goto error; +		return FALSE;  	res = gst_pad_set_caps(enc->srcpad, src_caps);  	gst_caps_unref(src_caps);  	return res; - -error: -	GST_ERROR_OBJECT (enc, "invalid input caps"); -	return FALSE;  }  gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps)  { +	gint mode; + +	if (!gst_caps_is_fixed(caps)) { +		GST_DEBUG_OBJECT(enc, "didn't receive fixed caps, " +				"returning false"); +		return FALSE; +	}  	if (!gst_sbc_util_fill_sbc_params(&enc->sbc, caps))  		return FALSE; -	enc->rate = enc->sbc.rate; -	enc->channels = enc->sbc.channels; -	enc->blocks = enc->sbc.blocks; -	enc->subbands = enc->sbc.subbands; -	enc->mode = enc->sbc.joint; -	enc->allocation = enc->sbc.allocation; +	if (enc->rate != 0 && enc->sbc.rate != enc->rate) +		goto fail; + +	if (enc->channels != 0 && enc->sbc.channels != enc->channels) +		goto fail; + +	if (enc->blocks != 0 && enc->sbc.blocks != enc->blocks) +		goto fail; + +	if (enc->subbands != 0 && enc->sbc.subbands != enc->subbands) +		goto fail; + +	mode = gst_sbc_get_mode_int_from_sbc_t(&enc->sbc); +	if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO && mode != enc->mode) +		goto fail; + +	if (enc->allocation != BT_A2DP_ALLOCATION_AUTO && +				enc->sbc.allocation != enc->allocation) +		goto fail; + +	if (enc->bitpool != SBC_ENC_BITPOOL_AUTO && +				enc->sbc.bitpool != enc->bitpool) +		goto fail; +  	enc->codesize = sbc_get_codesize(&enc->sbc);  	enc->frame_length = sbc_get_frame_length(&enc->sbc);  	enc->frame_duration = sbc_get_frame_duration(&enc->sbc); +  	GST_DEBUG("codesize: %d, frame_length: %d, frame_duration: %d",  			enc->codesize, enc->frame_length, enc->frame_duration);  	return TRUE; + +fail: +	memset(&enc->sbc, 0, sizeof(sbc_t)); +	return FALSE;  }  static GstFlowReturn sbc_enc_chain(GstPad *pad, GstBuffer *buffer) @@ -393,23 +462,6 @@ static void gst_sbc_enc_base_init(gpointer g_class)  	gst_element_class_set_details(element_class, &sbc_enc_details);  } -static gboolean sbc_enc_set_blocks(GstSbcEnc *enc, gint value) -{ -	if (value != 4 && value != 8 && value != 12 && -			value != 16 && value != 0) -		return FALSE; -	enc->blocks = value; -	return TRUE; -} - -static gboolean sbc_enc_set_subbands(GstSbcEnc *enc, gint value) -{ -	if (value != 4 && value != 8 && value != 0) -		return FALSE; -	enc->subbands = value; -	return TRUE; -} -  static void gst_sbc_enc_set_property(GObject *object, guint prop_id,  					const GValue *value, GParamSpec *pspec)  { @@ -426,14 +478,13 @@ static void gst_sbc_enc_set_property(GObject *object, guint prop_id,  		enc->allocation = g_value_get_enum(value);  		break;  	case PROP_BLOCKS: -		if (!sbc_enc_set_blocks(enc, g_value_get_int(value))) -			GST_WARNING_OBJECT(enc, "invalid value %d for " -				"blocks property", g_value_get_int(value)); +		enc->blocks = g_value_get_enum(value);  		break;  	case PROP_SUBBANDS: -		if (!sbc_enc_set_subbands(enc, g_value_get_int(value))) -			GST_WARNING_OBJECT(enc, "invalid value %d for " -				"subbands property", g_value_get_int(value)); +		enc->subbands = g_value_get_enum(value); +		break; +	case PROP_BITPOOL: +		enc->bitpool = g_value_get_int(value);  		break;  	default:  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -454,10 +505,13 @@ static void gst_sbc_enc_get_property(GObject *object, guint prop_id,  		g_value_set_enum(value, enc->allocation);  		break;  	case PROP_BLOCKS: -		g_value_set_int(value, enc->blocks); +		g_value_set_enum(value, enc->blocks);  		break;  	case PROP_SUBBANDS: -		g_value_set_int(value, enc->subbands); +		g_value_set_enum(value, enc->subbands); +		break; +	case PROP_BITPOOL: +		g_value_set_int(value, enc->bitpool);  		break;  	default:  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -485,19 +539,25 @@ static void gst_sbc_enc_class_init(GstSbcEncClass *klass)  	g_object_class_install_property(object_class, PROP_ALLOCATION,  			g_param_spec_enum("allocation", "Allocation", -				"Allocation mode", GST_TYPE_SBC_ALLOCATION, +				"Allocation method", 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, +			g_param_spec_enum("blocks", "Blocks", +				"Blocks", GST_TYPE_SBC_BLOCKS,  				SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE));  	g_object_class_install_property(object_class, PROP_SUBBANDS, -			g_param_spec_int("subbands", "Sub Bands", -				"Sub Bands", 0, G_MAXINT, +			g_param_spec_enum("subbands", "Sub bands", +				"Number of sub bands", GST_TYPE_SBC_SUBBANDS,  				SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE)); +	g_object_class_install_property(object_class, PROP_BITPOOL, +			g_param_spec_int("bitpool", "Bitpool", +				"Bitpool (use 1 for automatic selection)", +				SBC_ENC_BITPOOL_AUTO, SBC_ENC_BITPOOL_MAX, +				SBC_ENC_BITPOOL_AUTO, G_PARAM_READWRITE)); +  	GST_DEBUG_CATEGORY_INIT(sbc_enc_debug, "sbcenc", 0,  						"SBC encoding element");  } @@ -527,6 +587,7 @@ static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)  	self->allocation = SBC_ENC_DEFAULT_ALLOCATION;  	self->rate = SBC_ENC_DEFAULT_RATE;  	self->channels = SBC_ENC_DEFAULT_CHANNELS; +	self->bitpool = SBC_ENC_BITPOOL_AUTO;  	self->frame_length = 0;  	self->frame_duration = 0; diff --git a/audio/gstsbcenc.h b/audio/gstsbcenc.h index c7b21638..41417507 100644 --- a/audio/gstsbcenc.h +++ b/audio/gstsbcenc.h @@ -55,6 +55,8 @@ struct _GstSbcEnc {  	gint blocks;  	gint allocation;  	gint subbands; +	gint bitpool; +  	gint codesize;  	gint frame_length;  	gint frame_duration; diff --git a/audio/gstsbcutil.c b/audio/gstsbcutil.c index e5d21af0..7c47dbca 100644 --- a/audio/gstsbcutil.c +++ b/audio/gstsbcutil.c @@ -90,21 +90,39 @@ const gchar *gst_sbc_get_allocation_from_list(const GValue *value)  /*   * Selects one mode from the ones on the list   */ -const gchar *gst_sbc_get_mode_from_list(const GValue *list) +const gchar *gst_sbc_get_mode_from_list(const GValue *list, gint channels)  {  	int i;  	const GValue *value;  	const gchar *aux; +	gboolean joint, stereo, dual, mono; +	joint = stereo = dual = mono = FALSE;  	guint size = gst_value_list_get_size(list); +  	for (i = 0; i < size; i++) {  		value = gst_value_list_get_value(list, i);  		aux = g_value_get_string(value); -		if (strcmp("joint", aux) == 0) { +		if (strcmp("joint", aux) == 0) +			joint = TRUE; +		else if (strcmp("stereo", aux) == 0) +			stereo = TRUE; +		else if (strcmp("dual", aux) == 0) +			dual = TRUE; +		else if (strcmp("mono", aux) == 0) +			mono = TRUE; +	} + +	if (channels == 1 && mono) +		return "mono"; +	else if (channels == 2) { +		if (joint)  			return "joint"; -		} +		else if (stereo) +			return "stereo";  	} -	return g_value_get_string(gst_value_list_get_value(list, size-1)); + +	return NULL;  }  gint gst_sbc_get_allocation_mode_int(const gchar *allocation) @@ -148,7 +166,20 @@ gboolean gst_sbc_get_mode_int_for_sbc_t(const gchar *mode)  		return -1;  } -const gchar *gst_sbc_get_mode_string(int joint) +gint gst_sbc_get_mode_int_from_sbc_t(const sbc_t *sbc) +{ +	/* TODO define constants */ +	if (sbc->channels == 2 && sbc->joint == 1) +		return 4; +	else if (sbc->channels == 2 && sbc->joint == 0) +		return 3; +	else if (sbc->channels == 1) +		return 1; +	else +		return -1; +} + +const gchar *gst_sbc_get_mode_string(gint joint)  {  	switch (joint) {  	case BT_A2DP_CHANNEL_MODE_MONO: @@ -166,7 +197,7 @@ const gchar *gst_sbc_get_mode_string(int joint)  	}  } -const gchar *gst_sbc_get_allocation_string(int alloc) +const gchar *gst_sbc_get_allocation_string(gint alloc)  {  	switch (alloc) {  	case BT_A2DP_ALLOCATION_LOUDNESS: @@ -190,7 +221,7 @@ const gchar *gst_sbc_get_allocation_string(int alloc)  #define SBC_AM_LOUDNESS         0x00  #define SBC_AM_SNR              0x01 -const gchar *gst_sbc_get_mode_string_from_sbc_t(int channels, int joint) +const gchar *gst_sbc_get_mode_string_from_sbc_t(gint channels, gint joint)  {  	if (channels == 2 && joint == 1)  		return "joint"; @@ -202,7 +233,7 @@ const gchar *gst_sbc_get_mode_string_from_sbc_t(int channels, int joint)  		return NULL;  } -const gchar *gst_sbc_get_allocation_string_from_sbc_t(int alloc) +const gchar *gst_sbc_get_allocation_string_from_sbc_t(gint alloc)  {  	switch (alloc) {  	case SBC_AM_LOUDNESS: @@ -365,14 +396,23 @@ GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message)  	} else {  		value = gst_structure_get_value(structure, "mode");  		if (GST_VALUE_HOLDS_LIST(value)) { -			if (channels == 1) -				mode = "mono"; -			else -				mode = gst_sbc_get_mode_from_list(value); +			mode = gst_sbc_get_mode_from_list(value, channels);  		} else  			mode = g_value_get_string(value);  	} +	/* perform validation  +	 * if channels is 1, we must have channel mode = mono +	 * if channels is 2, we can't have channel mode = mono, dual */ +	if ( (channels == 1 && (strcmp(mode, "mono") != 0) ) || +			( channels == 2 && ( strcmp(mode, "mono") == 0 || +			strcmp(mode, "dual") == 0 ) )) { +		*error_message = g_strdup_printf("Invalid combination of " +					"channels (%d) and channel mode (%s)", +					channels, mode); +		error = TRUE; +	} +  error:  	if (error)  		return NULL; diff --git a/audio/gstsbcutil.h b/audio/gstsbcutil.h index 4bdb5ac5..9e81af1a 100644 --- a/audio/gstsbcutil.h +++ b/audio/gstsbcutil.h @@ -42,8 +42,9 @@ const gchar *gst_sbc_get_allocation_from_list(const GValue *value);  gint gst_sbc_get_allocation_mode_int(const gchar *allocation);  const gchar *gst_sbc_get_allocation_string(int alloc); -const gchar *gst_sbc_get_mode_from_list(const GValue *value); +const gchar *gst_sbc_get_mode_from_list(const GValue *value, gint channels);  gint gst_sbc_get_mode_int(const gchar *mode); +gint gst_sbc_get_mode_int_from_sbc_t(const sbc_t *sbc);  const gchar *gst_sbc_get_mode_string(int joint);  GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels); | 
