diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-11-01 19:45:00 +0000 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-11-01 19:45:00 +0000 |
commit | 96d6078ada20a76f885ea04893aac5f0ca5fe48d (patch) | |
tree | 5a555aaae3228f5c5faf2497b71227557aecc650 /audio/gsta2dpsink.c | |
parent | a4bc7122fb5c7e4545cf8055cf71d1e88515998f (diff) |
Fix sbc negotiation and improves buffer handling by using GstAdapter.
Diffstat (limited to 'audio/gsta2dpsink.c')
-rw-r--r-- | audio/gsta2dpsink.c | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c index be81efe8..e605158f 100644 --- a/audio/gsta2dpsink.c +++ b/audio/gsta2dpsink.c @@ -37,6 +37,7 @@ #include "ipc.h" #include "rtp.h" +#include "gstsbcutil.h" #include "gsta2dpsink.h" @@ -143,10 +144,17 @@ static gboolean gst_a2dp_sink_stop(GstBaseSink *basesink) 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) { g_io_channel_close(self->server); g_io_channel_unref(self->server); - self->stream = NULL; + self->server = NULL; } if (self->data) { @@ -154,6 +162,16 @@ static gboolean gst_a2dp_sink_stop(GstBaseSink *basesink) 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; } @@ -250,6 +268,25 @@ static gint gst_a2dp_sink_bluetooth_recvmsg_fd(GstA2dpSink *sink) 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 gst_a2dp_sink_bluetooth_a2dp_init(GstA2dpSink *self, struct ipc_codec_sbc *sbc) { @@ -406,6 +443,9 @@ static gboolean gst_a2dp_sink_conf_resp(GstA2dpSink *sink) } 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" "fd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u", @@ -414,6 +454,7 @@ static gboolean gst_a2dp_sink_conf_resp(GstA2dpSink *sink) sink->data->cfg.rate); if (sink->data->cfg.codec == CFG_CODEC_SBC) { + /* FIXME is this necessary? */ ret = gst_a2dp_sink_bluetooth_a2dp_init(sink, sbc); if (ret < 0) return FALSE; @@ -577,8 +618,12 @@ static gboolean gst_a2dp_sink_start(GstBaseSink *basesink) self->data = g_new0(struct bluetooth_data, 1); memset(self->data, 0, sizeof(struct bluetooth_data)); + self->sbc = g_new0(struct ipc_codec_sbc, 1); + self->stream = NULL; self->con_state = NOT_CONFIGURED; + self->new_dev_caps = FALSE; + self->dev_caps = NULL; self->waiting_con_conf = FALSE; @@ -718,8 +763,16 @@ static gboolean gst_a2dp_sink_set_caps(GstBaseSink *basesink, GstCaps *caps) GstA2dpSink *self = GST_A2DP_SINK(basesink); 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); + + 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); return TRUE; @@ -735,6 +788,30 @@ static gboolean gst_a2dp_sink_unlock(GstBaseSink *basesink) 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 gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); @@ -754,6 +831,8 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) basesink_class->preroll = GST_DEBUG_FUNCPTR(gst_a2dp_sink_preroll); basesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_a2dp_sink_set_caps); 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_param_spec_string("device", "Device", @@ -768,6 +847,7 @@ static void gst_a2dp_sink_init(GstA2dpSink *self, GstA2dpSinkClass *klass) { self->device = NULL; self->data = NULL; + self->sbc = NULL; self->stream = NULL; self->con_state = NOT_CONFIGURED; |