diff options
Diffstat (limited to 'audio/gsta2dpsink.c')
-rw-r--r-- | audio/gsta2dpsink.c | 73 |
1 files changed, 56 insertions, 17 deletions
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c index b24dc8b8..1b893cc1 100644 --- a/audio/gsta2dpsink.c +++ b/audio/gsta2dpsink.c @@ -45,6 +45,7 @@ GST_DEBUG_CATEGORY_STATIC(a2dp_sink_debug); #define GST_CAT_DEFAULT a2dp_sink_debug #define BUFFER_SIZE 2048 +#define TEMPLATE_MAX_BITPOOL_VALUE 64 #define GST_A2DP_SINK_MUTEX_LOCK(s) G_STMT_START { \ g_mutex_lock (s->sink_lock); \ @@ -56,8 +57,8 @@ GST_DEBUG_CATEGORY_STATIC(a2dp_sink_debug); struct bluetooth_data { - struct bt_getcapabilities_rsp cfg; /* Bluetooth device config */ - gint link_mtu; + struct bt_getcapabilities_rsp caps; /* Bluetooth device capabilities */ + struct bt_setconfiguration_rsp cfg; /* Bluetooth device configuration */ int samples; /* Number of encoded samples */ gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */ gsize count; /* Codec transfer buffer counter */ @@ -67,6 +68,7 @@ struct bluetooth_data { int frame_count; /* Current frames in buffer*/ }; + #define IS_SBC(n) (strcmp((n), "audio/x-sbc") == 0) #define IS_MPEG(n) (strcmp((n), "audio/mpeg") == 0) @@ -92,6 +94,7 @@ static GstStaticPadTemplate a2dp_sink_factory = "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }," + /* FIXME use constant here */ "bitpool = (int) [ 2, 64 ]; " "audio/mpeg, " "mpegversion = (int) 1, " @@ -230,9 +233,10 @@ static gboolean gst_a2dp_sink_init_pkt_conf(GstA2dpSink *sink, GstCaps *caps, sbc_capabilities_t *pkt) { - sbc_capabilities_t *cfg = &sink->data->cfg.sbc_capabilities; + sbc_capabilities_t *cfg = &sink->data->caps.sbc_capabilities; const GValue *value = NULL; const char *pref, *name; + gint rate, blocks, subbands; GstStructure *structure = gst_caps_get_structure(caps, 0); name = gst_structure_get_name(structure); @@ -243,7 +247,19 @@ static gboolean gst_a2dp_sink_init_pkt_conf(GstA2dpSink *sink, } value = gst_structure_get_value(structure, "rate"); - cfg->frequency = g_value_get_int(value); + rate = g_value_get_int(value); + if (rate == 44100) + cfg->frequency = BT_A2DP_SAMPLING_FREQ_44100; + else if (rate == 48000) + cfg->frequency = BT_A2DP_SAMPLING_FREQ_48000; + else if (rate == 32000) + cfg->frequency = BT_A2DP_SAMPLING_FREQ_32000; + else if (rate == 16000) + cfg->frequency = BT_A2DP_SAMPLING_FREQ_16000; + else { + GST_ERROR_OBJECT(sink, "Invalid rate while setting caps"); + return FALSE; + } value = gst_structure_get_value(structure, "mode"); pref = g_value_get_string(value); @@ -276,13 +292,34 @@ static gboolean gst_a2dp_sink_init_pkt_conf(GstA2dpSink *sink, } value = gst_structure_get_value(structure, "subbands"); - cfg->subbands = g_value_get_int(value); + subbands = g_value_get_int(value); + if (subbands == 8) + cfg->subbands = BT_A2DP_SUBBANDS_8; + else if (subbands == 4) + cfg->subbands = BT_A2DP_SUBBANDS_4; + else { + GST_ERROR_OBJECT(sink, "Invalid subbands %d", subbands); + return FALSE; + } value = gst_structure_get_value(structure, "blocks"); - cfg->block_length = g_value_get_int(value); + blocks = g_value_get_int(value); + if (blocks == 16) + cfg->block_length = BT_A2DP_BLOCK_LENGTH_16; + else if (blocks == 12) + cfg->block_length = BT_A2DP_BLOCK_LENGTH_12; + else if (blocks == 8) + cfg->block_length = BT_A2DP_BLOCK_LENGTH_8; + else if (blocks == 4) + cfg->block_length = BT_A2DP_BLOCK_LENGTH_4; + else { + GST_ERROR_OBJECT(sink, "Invalid blocks %d", blocks); + return FALSE; + } /* FIXME min and max ??? */ value = gst_structure_get_value(structure, "bitpool"); + cfg->max_bitpool = cfg->min_bitpool = g_value_get_int(value); memcpy(pkt, cfg, sizeof(*pkt)); @@ -375,7 +412,7 @@ static gboolean server_callback(GIOChannel *chan, static gboolean gst_a2dp_sink_update_caps(GstA2dpSink *self) { - sbc_capabilities_t *sbc = &self->data->cfg.sbc_capabilities; + sbc_capabilities_t *sbc = &self->data->caps.sbc_capabilities; GstStructure *structure; GValue *value; GValue *list; @@ -519,7 +556,9 @@ static gboolean gst_a2dp_sink_update_caps(GstA2dpSink *self) /* bitpool */ value = g_value_init(value, GST_TYPE_INT_RANGE); - gst_value_set_int_range(value, sbc->min_bitpool, sbc->max_bitpool); + gst_value_set_int_range(value, + MIN(sbc->min_bitpool, TEMPLATE_MAX_BITPOOL_VALUE), + MIN(sbc->max_bitpool, TEMPLATE_MAX_BITPOOL_VALUE)); gst_structure_set_value(structure, "bitpool", value); /* channels */ @@ -528,6 +567,8 @@ static gboolean gst_a2dp_sink_update_caps(GstA2dpSink *self) g_free(value); + if (self->dev_caps != NULL) + gst_caps_unref(self->dev_caps); self->dev_caps = gst_caps_new_full(structure, NULL); tmp = gst_caps_to_string(self->dev_caps); @@ -549,8 +590,6 @@ static gboolean gst_a2dp_sink_get_capabilities(GstA2dpSink *self) req->h.msg_type = BT_GETCAPABILITIES_REQ; strncpy(req->device, self->device, 18); - req->transport = BT_CAPABILITIES_TRANSPORT_A2DP; - req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE; io_error = gst_a2dp_sink_audioservice_send(self, &req->h); if (io_error != G_IO_ERROR_NONE) { GST_ERROR_OBJECT(self, "Error while asking device caps"); @@ -570,12 +609,7 @@ static gboolean gst_a2dp_sink_get_capabilities(GstA2dpSink *self) return FALSE; } - if (rsp->transport != BT_CAPABILITIES_TRANSPORT_A2DP) { - GST_ERROR_OBJECT(self, "Non a2dp answer from device"); - return FALSE; - } - - memcpy(&self->data->cfg, rsp, sizeof(*rsp)); + memcpy(&self->data->caps, rsp, sizeof(*rsp)); if (!gst_a2dp_sink_update_caps(self)) { GST_WARNING_OBJECT(self, "failed to update capabilities"); return FALSE; @@ -685,6 +719,7 @@ static gboolean gst_a2dp_sink_configure(GstA2dpSink *self, GstCaps *caps) memset (req, 0, sizeof(buf)); req->h.msg_type = BT_SETCONFIGURATION_REQ; + req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE; strncpy(req->device, self->device, 18); ret = gst_a2dp_sink_init_pkt_conf(self, caps, &req->sbc_capabilities); if (!ret) { @@ -716,6 +751,7 @@ static gboolean gst_a2dp_sink_configure(GstA2dpSink *self, GstCaps *caps) return FALSE; } + memcpy(&self->data->cfg, rsp, sizeof(*rsp)); GST_DEBUG_OBJECT(self, "configuration set"); return TRUE; @@ -801,7 +837,10 @@ static GstCaps* gst_a2dp_sink_get_caps(GstBaseSink *basesink) { GstA2dpSink *self = GST_A2DP_SINK(basesink); - return self->dev_caps ? gst_caps_ref(self->dev_caps): NULL; + if (self->dev_caps) + return gst_caps_ref(self->dev_caps); + + return gst_caps_copy(gst_pad_get_pad_template_caps(GST_BASE_SINK_PAD(self))); } static gboolean gst_a2dp_sink_set_caps(GstBaseSink *basesink, GstCaps *caps) |