bluez: Fix sbc negotiation and improves buffer handling by using GstAdapter.

This commit is contained in:
Luiz Augusto von Dentz 2007-11-01 19:45:00 +00:00 committed by Tim-Philipp Müller
parent ff77205750
commit 22d80ddff0
2 changed files with 84 additions and 2 deletions

View file

@ -37,6 +37,7 @@
#include "ipc.h" #include "ipc.h"
#include "rtp.h" #include "rtp.h"
#include "gstsbcutil.h"
#include "gsta2dpsink.h" #include "gsta2dpsink.h"
@ -148,10 +149,17 @@ gst_a2dp_sink_stop (GstBaseSink * basesink)
self->watch_id = 0; self->watch_id = 0;
} }
if (self->stream) {
g_io_channel_flush (self->stream, NULL);
g_io_channel_close (self->stream);
g_io_channel_unref (self->stream);
self->stream = NULL;
}
if (self->server) { if (self->server) {
g_io_channel_close (self->server); g_io_channel_close (self->server);
g_io_channel_unref (self->server); g_io_channel_unref (self->server);
self->stream = NULL; self->server = NULL;
} }
if (self->data) { if (self->data) {
@ -159,6 +167,16 @@ gst_a2dp_sink_stop (GstBaseSink * basesink)
self->data = NULL; self->data = NULL;
} }
if (self->sbc) {
g_free (self->sbc);
self->sbc = NULL;
}
if (self->dev_caps) {
gst_caps_unref (self->dev_caps);
self->dev_caps = NULL;
}
return TRUE; return TRUE;
} }
@ -258,6 +276,25 @@ gst_a2dp_sink_bluetooth_recvmsg_fd (GstA2dpSink * sink)
return -EINVAL; return -EINVAL;
} }
static void
gst_a2dp_sink_check_dev_caps (GstA2dpSink * self)
{
GstStructure *structure;
GstCaps *dev_caps;
gint channels;
structure = gst_caps_get_structure (self->dev_caps, 0);
if (!gst_structure_get_int (structure, "channels", &channels))
channels = 2; /* FIXME how to get channels */
dev_caps = gst_sbc_caps_from_sbc (&(self->data->cfg), self->sbc, channels);
self->new_dev_caps = TRUE;
gst_caps_unref (self->dev_caps);
self->dev_caps = gst_caps_ref (dev_caps);
}
static int static int
gst_a2dp_sink_bluetooth_a2dp_init (GstA2dpSink * self, gst_a2dp_sink_bluetooth_a2dp_init (GstA2dpSink * self,
struct ipc_codec_sbc *sbc) struct ipc_codec_sbc *sbc)
@ -413,6 +450,9 @@ gst_a2dp_sink_conf_resp (GstA2dpSink * sink)
} }
memcpy (&sink->data->cfg, cfg, sizeof (*cfg)); memcpy (&sink->data->cfg, cfg, sizeof (*cfg));
memcpy (sink->sbc, sbc, sizeof (struct ipc_codec_sbc));
gst_a2dp_sink_check_dev_caps (sink);
GST_DEBUG_OBJECT (sink, "Device configuration:\n\tchannel=%p\n\t" GST_DEBUG_OBJECT (sink, "Device configuration:\n\tchannel=%p\n\t"
"fd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u", "fd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u",
@ -421,6 +461,7 @@ gst_a2dp_sink_conf_resp (GstA2dpSink * sink)
sink->data->cfg.rate); sink->data->cfg.rate);
if (sink->data->cfg.codec == CFG_CODEC_SBC) { if (sink->data->cfg.codec == CFG_CODEC_SBC) {
/* FIXME is this necessary? */
ret = gst_a2dp_sink_bluetooth_a2dp_init (sink, sbc); ret = gst_a2dp_sink_bluetooth_a2dp_init (sink, sbc);
if (ret < 0) if (ret < 0)
return FALSE; return FALSE;
@ -579,8 +620,12 @@ gst_a2dp_sink_start (GstBaseSink * basesink)
self->data = g_new0 (struct bluetooth_data, 1); self->data = g_new0 (struct bluetooth_data, 1);
memset (self->data, 0, sizeof (struct bluetooth_data)); memset (self->data, 0, sizeof (struct bluetooth_data));
self->sbc = g_new0 (struct ipc_codec_sbc, 1);
self->stream = NULL; self->stream = NULL;
self->con_state = NOT_CONFIGURED; self->con_state = NOT_CONFIGURED;
self->new_dev_caps = FALSE;
self->dev_caps = NULL;
self->waiting_con_conf = FALSE; self->waiting_con_conf = FALSE;
@ -724,8 +769,16 @@ gst_a2dp_sink_set_caps (GstBaseSink * basesink, GstCaps * caps)
GstA2dpSink *self = GST_A2DP_SINK (basesink); GstA2dpSink *self = GST_A2DP_SINK (basesink);
GST_A2DP_SINK_MUTEX_LOCK (self); GST_A2DP_SINK_MUTEX_LOCK (self);
if (self->con_state == NOT_CONFIGURED) if (self->con_state == NOT_CONFIGURED) {
gst_a2dp_sink_start_dev_conf (self, caps); gst_a2dp_sink_start_dev_conf (self, caps);
if (self->dev_caps)
gst_caps_unref (self->dev_caps);
self->dev_caps = gst_caps_ref (caps);
/* we suppose the device will accept this caps */
self->new_dev_caps = FALSE;
}
GST_A2DP_SINK_MUTEX_UNLOCK (self); GST_A2DP_SINK_MUTEX_UNLOCK (self);
return TRUE; return TRUE;
@ -742,6 +795,30 @@ gst_a2dp_sink_unlock (GstBaseSink * basesink)
return TRUE; return TRUE;
} }
static GstFlowReturn
gst_a2dp_sink_buffer_alloc (GstBaseSink * basesink,
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf)
{
GstA2dpSink *self = GST_A2DP_SINK (basesink);
*buf = gst_buffer_new_and_alloc (size);
if (!(*buf)) {
GST_ERROR_OBJECT (self, "buffer allocation failed");
return GST_FLOW_ERROR;
}
if (self->new_dev_caps && self->dev_caps) {
GST_INFO_OBJECT (self, "new caps from device");
gst_buffer_set_caps (*buf, self->dev_caps);
self->new_dev_caps = FALSE;
} else
gst_buffer_set_caps (*buf, caps);
GST_BUFFER_OFFSET (*buf) = offset;
return GST_FLOW_OK;
}
static void static void
gst_a2dp_sink_class_init (GstA2dpSinkClass * klass) gst_a2dp_sink_class_init (GstA2dpSinkClass * klass)
{ {
@ -760,6 +837,7 @@ gst_a2dp_sink_class_init (GstA2dpSinkClass * klass)
basesink_class->preroll = GST_DEBUG_FUNCPTR (gst_a2dp_sink_preroll); basesink_class->preroll = GST_DEBUG_FUNCPTR (gst_a2dp_sink_preroll);
basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_a2dp_sink_set_caps); basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_a2dp_sink_set_caps);
basesink_class->unlock = GST_DEBUG_FUNCPTR (gst_a2dp_sink_unlock); basesink_class->unlock = GST_DEBUG_FUNCPTR (gst_a2dp_sink_unlock);
basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_a2dp_sink_buffer_alloc);
g_object_class_install_property (object_class, PROP_DEVICE, g_object_class_install_property (object_class, PROP_DEVICE,
g_param_spec_string ("device", "Device", g_param_spec_string ("device", "Device",
@ -773,6 +851,7 @@ gst_a2dp_sink_init (GstA2dpSink * self, GstA2dpSinkClass * klass)
{ {
self->device = NULL; self->device = NULL;
self->data = NULL; self->data = NULL;
self->sbc = NULL;
self->stream = NULL; self->stream = NULL;
self->con_state = NOT_CONFIGURED; self->con_state = NOT_CONFIGURED;

View file

@ -49,9 +49,12 @@ struct _GstA2dpSink {
GIOChannel *stream; GIOChannel *stream;
struct bluetooth_data *data; struct bluetooth_data *data;
struct ipc_codec_sbc *sbc;
GIOChannel *server; GIOChannel *server;
gint con_state; gint con_state;
GstCaps *dev_caps;
gboolean new_dev_caps;
GCond *con_conf_end; GCond *con_conf_end;
gboolean waiting_con_conf; gboolean waiting_con_conf;