summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/gsta2dpsink.c40
-rw-r--r--audio/gstavdtpsink.c53
-rw-r--r--audio/gstavdtpsink.h1
-rw-r--r--audio/gstrtpsbcpay.c13
-rw-r--r--audio/gstsbcdec.c45
-rw-r--r--audio/gstsbcdec.h3
-rw-r--r--audio/gstsbcparse.c92
-rw-r--r--audio/gstsbcutil.c9
8 files changed, 113 insertions, 143 deletions
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c
index a2b3286c..b5b1c576 100644
--- a/audio/gsta2dpsink.c
+++ b/audio/gsta2dpsink.c
@@ -80,6 +80,17 @@ static void gst_a2dp_sink_finalize(GObject *obj)
G_OBJECT_CLASS (parent_class)->finalize (obj);
}
+static GstState gst_a2dp_sink_get_state(GstA2dpSink *self)
+{
+ GstState current, pending;
+
+ gst_element_get_state(GST_ELEMENT(self), &current, &pending, 0);
+ if (pending == GST_STATE_VOID_PENDING)
+ return current;
+
+ return pending;
+}
+
/*
* Helper function to create elements, add to the bin and link it
* to another element.
@@ -89,6 +100,7 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,
GstElement *link_to)
{
GstElement *element;
+ GstState state;
GST_LOG_OBJECT(self, "Initializing %s", elementname);
@@ -104,17 +116,19 @@ static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,
goto cleanup_and_fail;
}
- if (gst_element_set_state(element, GST_STATE_PLAYING) ==
+ 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",
elementname);
goto remove_element_and_fail;
}
- if (!gst_element_link(link_to, element)) {
- GST_ERROR_OBJECT(self, "couldn't link %s", 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);
+ goto remove_element_and_fail;
+ }
return element;
@@ -241,7 +255,6 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
case GST_STATE_CHANGE_NULL_TO_READY:
self->sink_is_in_bin = FALSE;
-
self->sink = GST_AVDTP_SINK(gst_element_factory_make(
"avdtpsink", "avdtpsink"));
if (self->sink == NULL) {
@@ -260,8 +273,10 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
break;
}
- if (ret == GST_STATE_CHANGE_FAILURE)
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_mutex_unlock(self->cb_mutex);
return ret;
+ }
ret = GST_ELEMENT_CLASS(parent_class)->change_state(element,
transition);
@@ -295,7 +310,6 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
gst_a2dp_sink_remove_dynamic_elements(self);
break;
-
default:
break;
}
@@ -558,16 +572,16 @@ static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event)
if (self->newseg_event != NULL)
gst_event_unref(self->newseg_event);
self->newseg_event = gst_event_ref(event);
+
} else if (GST_EVENT_TYPE(event) == GST_EVENT_TAG &&
parent != GST_OBJECT_CAST(self)) {
- if (self->taglist == NULL) {
+ if (self->taglist == NULL)
gst_event_parse_tag(event, &self->taglist);
- } else {
+ else {
gst_event_parse_tag(event, &taglist);
gst_tag_list_insert(self->taglist, taglist,
GST_TAG_MERGE_REPLACE);
}
- /* FIXME handle tag events */
}
if (parent != NULL)
@@ -614,11 +628,15 @@ static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self)
static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self)
{
g_mutex_lock(self->cb_mutex);
+
if (self->fakesink != NULL) {
+ gst_element_set_locked_state(self->fakesink, TRUE);
gst_element_set_state(self->fakesink, GST_STATE_NULL);
+
gst_bin_remove(GST_BIN(self), self->fakesink);
self->fakesink = NULL;
}
+
g_mutex_unlock(self->cb_mutex);
return TRUE;
diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c
index c956ecbd..25fc1ced 100644
--- a/audio/gstavdtpsink.c
+++ b/audio/gstavdtpsink.c
@@ -68,7 +68,7 @@ struct bluetooth_data {
};
#define IS_SBC(n) (strcmp((n), "audio/x-sbc") == 0)
-#define IS_MPEG(n) (strcmp((n), "audio/mpeg") == 0)
+#define IS_MPEG_AUDIO(n) (strcmp((n), "audio/mpeg") == 0)
enum {
PROP_0,
@@ -87,8 +87,12 @@ static const GstElementDetails avdtp_sink_details =
static GstStaticPadTemplate avdtp_sink_factory =
GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
GST_STATIC_CAPS("application/x-rtp, "
- "media = (string) \"audio\", "
- "encoding-name = (string) \"SBC\";"
+ "media = (string) \"audio\","
+ "payload = (int) "
+ GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
+ "clock-rate = (int) { 16000, 32000, "
+ "44100, 48000 }, "
+ "encoding-name = (string) \"SBC\"; "
"application/x-rtp, "
"media = (string) \"audio\", "
"payload = (int) "
@@ -231,7 +235,7 @@ static gint gst_avdtp_sink_bluetooth_recvmsg_fd(GstAvdtpSink *sink)
return 0;
}
-static gboolean gst_avdtp_sink_init_pkt_conf(GstAvdtpSink *sink,
+static gboolean gst_avdtp_sink_init_sbc_pkt_conf(GstAvdtpSink *sink,
GstCaps *caps,
sbc_capabilities_t *pkt)
{
@@ -242,9 +246,10 @@ static gboolean gst_avdtp_sink_init_pkt_conf(GstAvdtpSink *sink,
GstStructure *structure = gst_caps_get_structure(caps, 0);
name = gst_structure_get_name(structure);
- /* FIXME only sbc supported here, should suport mp3 */
+
if (!(IS_SBC(name))) {
- GST_ERROR_OBJECT(sink, "Unsupported format %s", name);
+ GST_ERROR_OBJECT(sink, "Unexpected format %s, "
+ "was expecting sbc", name);
return FALSE;
}
@@ -814,7 +819,7 @@ static void gst_avdtp_sink_tag(const GstTagList *taglist,
if (!gst_tag_list_get_boolean(taglist, tag, &crc)) {
GST_WARNING_OBJECT(self, "failed to get crc tag");
- self->mpeg_stream_changed = TRUE;
+ return;
}
gst_avdtp_sink_set_crc(self, crc);
@@ -824,7 +829,7 @@ static void gst_avdtp_sink_tag(const GstTagList *taglist,
if (!gst_tag_list_get_string(taglist, tag, &channel_mode)) {
GST_WARNING_OBJECT(self,
"failed to get channel-mode tag");
- self->mpeg_stream_changed = TRUE;
+ return;
}
self->channel_mode = gst_avdtp_sink_get_channel_mode(
@@ -883,7 +888,6 @@ static gboolean gst_avdtp_sink_start(GstBaseSink *basesink)
self->stream_caps = NULL;
self->mp3_using_crc = -1;
self->channel_mode = -1;
- self->mpeg_stream_changed = FALSE;
if (!gst_avdtp_sink_get_capabilities(self)) {
GST_ERROR_OBJECT(self, "failed to get capabilities "
@@ -957,8 +961,17 @@ static gboolean gst_avdtp_sink_init_mp3_pkt_conf(
{
const GValue *value = NULL;
gint rate, layer;
+ const gchar* name;
GstStructure *structure = gst_caps_get_structure(caps, 0);
+ name = gst_structure_get_name(structure);
+
+ if (!(IS_MPEG_AUDIO(name))) {
+ GST_ERROR_OBJECT(self, "Unexpected format %s, "
+ "was expecting mp3", name);
+ return FALSE;
+ }
+
/* layer */
value = gst_structure_get_value(structure, "layer");
layer = g_value_get_int(value);
@@ -1016,9 +1029,6 @@ static gboolean gst_avdtp_sink_init_mp3_pkt_conf(
/* vbr - we always say its vbr, we don't have how to know it */
pkt->bitrate = 0x8000;
- /* bitrate - we don't set anything, its vbr */
- /* FIXME - is this right? */
-
return TRUE;
}
@@ -1044,7 +1054,7 @@ static gboolean gst_avdtp_sink_configure(GstAvdtpSink *self,
structure = gst_caps_get_structure(caps, 0);
if (gst_structure_has_name(structure, "audio/x-sbc"))
- ret = gst_avdtp_sink_init_pkt_conf(self, caps,
+ ret = gst_avdtp_sink_init_sbc_pkt_conf(self, caps,
&req->sbc_capabilities);
else if (gst_structure_has_name(structure, "audio/mpeg"))
ret = gst_avdtp_sink_init_mp3_pkt_conf(self, caps,
@@ -1188,8 +1198,8 @@ static void gst_avdtp_sink_class_init(GstAvdtpSinkClass *klass)
"Bluetooth remote device address",
NULL, G_PARAM_READWRITE));
- GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "a2dpsendersink", 0,
- "A2DP sink element");
+ GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "avdtpsink", 0,
+ "A2DP headset sink element");
}
static void gst_avdtp_sink_init(GstAvdtpSink *self,
@@ -1203,6 +1213,11 @@ static void gst_avdtp_sink_init(GstAvdtpSink *self,
self->dev_caps = NULL;
self->sink_lock = g_mutex_new();
+
+ /* FIXME this is for not synchronizing with clock, should be tested
+ * with devices to see the behaviour
+ gst_base_sink_set_sync(GST_BASE_SINK(self), FALSE);
+ */
}
static GIOError gst_avdtp_sink_audioservice_send(
@@ -1325,9 +1340,7 @@ void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc)
/* test if we already received a different crc */
if (self->mp3_using_crc != -1 && new_crc != self->mp3_using_crc) {
- GST_ERROR_OBJECT(self, "crc changed during stream");
- /* FIXME test this, its not being used anywhere */
- self->mpeg_stream_changed = TRUE;
+ GST_WARNING_OBJECT(self, "crc changed during stream");
return;
}
self->mp3_using_crc = new_crc;
@@ -1342,8 +1355,8 @@ void gst_avdtp_sink_set_channel_mode(GstAvdtpSink *self,
new_mode = gst_avdtp_sink_get_channel_mode(mode);
if (self->channel_mode != -1 && new_mode != self->channel_mode) {
- GST_ERROR_OBJECT(self, "channel mode changed during stream");
- self->mpeg_stream_changed = TRUE;
+ GST_WARNING_OBJECT(self, "channel mode changed during stream");
+ return;
}
self->channel_mode = new_mode;
diff --git a/audio/gstavdtpsink.h b/audio/gstavdtpsink.h
index d0380829..237597da 100644
--- a/audio/gstavdtpsink.h
+++ b/audio/gstavdtpsink.h
@@ -57,7 +57,6 @@ struct _GstAvdtpSink {
GIOChannel *server;
/* mp3 stream data (outside caps data)*/
- gboolean mpeg_stream_changed;
gint mp3_using_crc;
gint channel_mode;
diff --git a/audio/gstrtpsbcpay.c b/audio/gstrtpsbcpay.c
index 25bf70eb..ba2a4741 100644
--- a/audio/gstrtpsbcpay.c
+++ b/audio/gstrtpsbcpay.c
@@ -77,7 +77,7 @@ static const GstElementDetails gst_rtp_sbc_pay_details =
static GstStaticPadTemplate gst_rtp_sbc_pay_sink_factory =
GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS("audio/x-sbc, " /* FIXME remove those caps? */
+ GST_STATIC_CAPS("audio/x-sbc, "
"rate = (int) { 16000, 32000, 44100, 48000 }, "
"channels = (int) [ 1, 2 ], "
"mode = (string) { mono, dual, stereo, joint }, "
@@ -89,7 +89,12 @@ static GstStaticPadTemplate gst_rtp_sbc_pay_sink_factory =
static GstStaticPadTemplate gst_rtp_sbc_pay_src_factory =
GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
- GST_STATIC_CAPS("application/x-rtp") /* FIXME put things here */
+ GST_STATIC_CAPS(
+ "application/x-rtp, "
+ "media = (string) \"audio\","
+ "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
+ "clock-rate = (int) { 16000, 32000, 44100, 48000 },"
+ "encoding-name = (string) \"SBC\"")
);
static void gst_rtp_sbc_pay_set_property (GObject * object, guint prop_id,
@@ -148,7 +153,7 @@ static gboolean gst_rtp_sbc_pay_set_caps(GstBaseRTPPayload *payload,
sbcpay->frame_length = frame_len;
- gst_basertppayload_set_options (payload, "audio", FALSE, "SBC", rate);
+ gst_basertppayload_set_options (payload, "audio", TRUE, "SBC", rate);
GST_DEBUG_OBJECT(payload, "calculated frame length: %d ", frame_len);
@@ -209,6 +214,8 @@ static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload,
GstRtpSBCPay *sbcpay;
guint available;
+ /* FIXME check for negotiation */
+
sbcpay = GST_RTP_SBC_PAY(payload);
gst_adapter_push(sbcpay->adapter, gst_buffer_copy(buffer));
diff --git a/audio/gstsbcdec.c b/audio/gstsbcdec.c
index 8c27daba..a686a406 100644
--- a/audio/gstsbcdec.c
+++ b/audio/gstsbcdec.c
@@ -80,26 +80,12 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
while (offset < size) {
GstBuffer *output;
GstPadTemplate *template;
- GstCaps *caps, *temp;
+ GstCaps *caps;
int consumed;
- caps = gst_caps_new_simple("audio/x-raw-int",
- "rate", G_TYPE_INT, dec->sbc.rate,
- "channels", G_TYPE_INT, dec->sbc.channels,
- NULL);
-
- template = gst_static_pad_template_get(&sbc_dec_src_factory);
-
- temp = gst_caps_intersect(caps,
- gst_pad_template_get_caps(template));
-
- gst_caps_unref(caps);
-
res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad,
GST_BUFFER_OFFSET_NONE,
- codesize, temp, &output);
-
- gst_caps_unref(temp);
+ codesize, NULL, &output);
if (res != GST_FLOW_OK)
goto done;
@@ -110,7 +96,25 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
if (consumed <= 0)
break;
- GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer);
+ /* we will reuse the same caps object */
+ if (dec->outcaps == NULL) {
+ caps = gst_caps_new_simple("audio/x-raw-int",
+ "rate", G_TYPE_INT, dec->sbc.rate,
+ "channels", G_TYPE_INT, dec->sbc.channels,
+ NULL);
+
+ template = gst_static_pad_template_get(&sbc_dec_src_factory);
+
+ dec->outcaps = gst_caps_intersect(caps,
+ gst_pad_template_get_caps(template));
+
+ gst_caps_unref(caps);
+ }
+
+ gst_buffer_set_caps(output, dec->outcaps);
+
+ /* FIXME get a real timestamp */
+ GST_BUFFER_TIMESTAMP(output) = GST_CLOCK_TIME_NONE;
res = gst_pad_push(dec->srcpad, output);
if (res != GST_FLOW_OK)
@@ -143,6 +147,7 @@ static GstStateChangeReturn sbc_dec_change_state(GstElement *element,
dec->buffer = NULL;
}
sbc_init(&dec->sbc, 0);
+ dec->outcaps = NULL;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
@@ -152,6 +157,10 @@ static GstStateChangeReturn sbc_dec_change_state(GstElement *element,
dec->buffer = NULL;
}
sbc_finish(&dec->sbc);
+ if (dec->outcaps) {
+ gst_caps_unref(dec->outcaps);
+ dec->outcaps = NULL;
+ }
break;
default:
@@ -197,6 +206,8 @@ static void gst_sbc_dec_init(GstSbcDec *self, GstSbcDecClass *klass)
self->srcpad = gst_pad_new_from_static_template(
&sbc_dec_src_factory, "src");
gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
+
+ self->outcaps = NULL;
}
gboolean gst_sbc_dec_plugin_init (GstPlugin * plugin)
diff --git a/audio/gstsbcdec.h b/audio/gstsbcdec.h
index 0bb0b57e..a88f8da5 100644
--- a/audio/gstsbcdec.h
+++ b/audio/gstsbcdec.h
@@ -49,6 +49,9 @@ struct _GstSbcDec {
GstBuffer *buffer;
+ /* caps for outgoing buffers */
+ GstCaps *outcaps;
+
sbc_t sbc;
};
diff --git a/audio/gstsbcparse.c b/audio/gstsbcparse.c
index 49d0bb6e..1f699620 100644
--- a/audio/gstsbcparse.c
+++ b/audio/gstsbcparse.c
@@ -43,7 +43,8 @@ static const GstElementDetails sbc_parse_details =
static GstStaticPadTemplate sbc_parse_sink_factory =
GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS("audio/x-sbc"));
+ GST_STATIC_CAPS("audio/x-sbc,"
+ "parsed = (boolean) false"));
static GstStaticPadTemplate sbc_parse_src_factory =
GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
@@ -54,86 +55,8 @@ static GstStaticPadTemplate sbc_parse_src_factory =
"blocks = (int) { 4, 8, 12, 16 }, "
"subbands = (int) { 4, 8 }, "
"allocation = (string) { snr, loudness },"
- "bitpool = (int) [ 2, 64 ]"));
-
-static gboolean sbc_parse_sink_setcaps(GstPad * pad, GstCaps * caps)
-{
- GstSbcParse *parse;
- GstStructure *structure;
- gint rate, channels;
-
- parse = GST_SBC_PARSE(GST_PAD_PARENT(pad));
-
- structure = gst_caps_get_structure(caps, 0);
-
- if (!gst_structure_get_int(structure, "rate", &rate))
- return FALSE;
-
- if (!gst_structure_get_int(structure, "channels", &channels))
- return FALSE;
-
- if (!(parse->rate == 0 || rate == parse->rate))
- return FALSE;
-
- if (!(parse->channels == 0 || channels == parse->channels))
- return FALSE;
-
- parse->rate = rate;
- parse->channels = channels;
-
- return gst_sbc_util_fill_sbc_params(&parse->sbc, caps);
-}
-
-static GstCaps* sbc_parse_src_getcaps(GstPad *pad)
-{
- GstCaps *caps;
- const GstCaps *allowed_caps;
- GstStructure *structure;
- GValue *value;
- GstSbcParse *parse = GST_SBC_PARSE(GST_PAD_PARENT(pad));
-
- allowed_caps = gst_pad_get_allowed_caps(pad);
- if (allowed_caps == NULL)
- allowed_caps = gst_pad_get_pad_template_caps(pad);
- caps = gst_caps_copy(allowed_caps);
-
- value = g_new0(GValue, 1);
-
- structure = gst_caps_get_structure(caps, 0);
-
- if (parse->rate != 0)
- gst_sbc_util_set_structure_int_param(structure, "rate",
- parse->rate, value);
- if (parse->channels != 0)
- gst_sbc_util_set_structure_int_param(structure, "channels",
- parse->channels, value);
-
- g_free(value);
-
- return caps;
-}
-
-static gboolean sbc_parse_src_acceptcaps(GstPad *pad, GstCaps *caps)
-{
- GstStructure *structure;
- GstSbcParse *parse;
- gint rate, channels;
-
- parse = GST_SBC_PARSE(GST_PAD_PARENT(pad));
-
- structure = gst_caps_get_structure(caps, 0);
-
- if (!gst_structure_get_int(structure, "rate", &rate))
- return FALSE;
- if (!gst_structure_get_int(structure, "channels", &channels))
- return FALSE;
-
- if ((parse->rate == 0 || parse->rate == rate)
- && (parse->channels == 0 || parse->channels == channels))
- return TRUE;
-
- return FALSE;
-}
+ "bitpool = (int) [ 2, 64 ],"
+ "parsed = (boolean) true"));
static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer)
{
@@ -261,17 +184,10 @@ static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass)
&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");
- gst_pad_set_getcaps_function (self->srcpad,
- GST_DEBUG_FUNCPTR (sbc_parse_src_getcaps));
- gst_pad_set_acceptcaps_function (self->srcpad,
- GST_DEBUG_FUNCPTR (sbc_parse_src_acceptcaps));
- /* FIXME get encoding parameters on set caps */
gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
}
diff --git a/audio/gstsbcutil.c b/audio/gstsbcutil.c
index 78024f7e..e5d21af0 100644
--- a/audio/gstsbcutil.c
+++ b/audio/gstsbcutil.c
@@ -364,9 +364,12 @@ GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message)
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
+ if (GST_VALUE_HOLDS_LIST(value)) {
+ if (channels == 1)
+ mode = "mono";
+ else
+ mode = gst_sbc_get_mode_from_list(value);
+ } else
mode = g_value_get_string(value);
}