diff options
Diffstat (limited to 'audio/gstsbcenc.c')
| -rw-r--r-- | audio/gstsbcenc.c | 177 | 
1 files changed, 119 insertions, 58 deletions
| 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; | 
