From 27f3623c76fde72d4b4553fd0c89d11da6b3e922 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 Nov 2012 09:49:28 +0100 Subject: [PATCH] audio: Remove GStreamer plugin --- audio/gsta2dpsink.c | 729 -------------------------- audio/gsta2dpsink.h | 84 --- audio/gstavdtpsink.c | 1152 ------------------------------------------ audio/gstavdtpsink.h | 106 ---- audio/gstbluetooth.c | 109 ---- audio/gstpragma.h | 24 - audio/gstrtpsbcpay.c | 351 ------------- audio/gstrtpsbcpay.h | 66 --- audio/gstsbcdec.c | 221 -------- audio/gstsbcdec.h | 66 --- audio/gstsbcenc.c | 601 ---------------------- audio/gstsbcenc.h | 75 --- audio/gstsbcparse.c | 219 -------- audio/gstsbcparse.h | 69 --- audio/gstsbcutil.c | 520 ------------------- audio/gstsbcutil.h | 74 --- 16 files changed, 4466 deletions(-) delete mode 100644 audio/gsta2dpsink.c delete mode 100644 audio/gsta2dpsink.h delete mode 100644 audio/gstavdtpsink.c delete mode 100644 audio/gstavdtpsink.h delete mode 100644 audio/gstbluetooth.c delete mode 100644 audio/gstpragma.h delete mode 100644 audio/gstrtpsbcpay.c delete mode 100644 audio/gstrtpsbcpay.h delete mode 100644 audio/gstsbcdec.c delete mode 100644 audio/gstsbcdec.h delete mode 100644 audio/gstsbcenc.c delete mode 100644 audio/gstsbcenc.h delete mode 100644 audio/gstsbcparse.c delete mode 100644 audio/gstsbcparse.h delete mode 100644 audio/gstsbcutil.c delete mode 100644 audio/gstsbcutil.h diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c deleted file mode 100644 index c8f6346b3..000000000 --- a/audio/gsta2dpsink.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "gstpragma.h" -#include "gsta2dpsink.h" - -GST_DEBUG_CATEGORY_STATIC(gst_a2dp_sink_debug); -#define GST_CAT_DEFAULT gst_a2dp_sink_debug - -#define A2DP_SBC_RTP_PAYLOAD_TYPE 1 -#define TEMPLATE_MAX_BITPOOL_STR "64" - -#define DEFAULT_AUTOCONNECT TRUE - -enum { - PROP_0, - PROP_DEVICE, - PROP_AUTOCONNECT, - PROP_TRANSPORT -}; - -GST_BOILERPLATE(GstA2dpSink, gst_a2dp_sink, GstBin, GST_TYPE_BIN); - -static const GstElementDetails gst_a2dp_sink_details = - GST_ELEMENT_DETAILS("Bluetooth A2DP sink", - "Sink/Audio", - "Plays audio to an A2DP device", - "Marcel Holtmann "); - -static GstStaticPadTemplate gst_a2dp_sink_factory = - GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS("audio/x-sbc, " - "rate = (int) { 16000, 32000, 44100, 48000 }, " - "channels = (int) [ 1, 2 ], " - "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, " - "blocks = (int) { 4, 8, 12, 16 }, " - "subbands = (int) { 4, 8 }, " - "allocation = (string) { \"snr\", \"loudness\" }, " - "bitpool = (int) [ 2, " - TEMPLATE_MAX_BITPOOL_STR " ]; " - "audio/mpeg" - )); - -static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event); -static gboolean gst_a2dp_sink_set_caps(GstPad *pad, GstCaps *caps); -static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad); -static gboolean gst_a2dp_sink_init_caps_filter(GstA2dpSink *self); -static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self); -static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self); - -static void gst_a2dp_sink_finalize(GObject *obj) -{ - GstA2dpSink *self = GST_A2DP_SINK(obj); - - g_mutex_free(self->cb_mutex); - - 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), ¤t, &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. - */ -static GstElement *gst_a2dp_sink_init_element(GstA2dpSink *self, - const gchar *elementname, const gchar *name, - GstElement *link_to) -{ - GstElement *element; - GstState state; - - GST_LOG_OBJECT(self, "Initializing %s", elementname); - - element = gst_element_factory_make(elementname, name); - if (element == NULL) { - GST_DEBUG_OBJECT(self, "Couldn't create %s", elementname); - return NULL; - } - - if (!gst_bin_add(GST_BIN(self), element)) { - GST_DEBUG_OBJECT(self, "failed to add %s to the bin", - elementname); - goto cleanup_and_fail; - } - - state = gst_a2dp_sink_get_state(self); - if (gst_element_set_state(element, state) == - GST_STATE_CHANGE_FAILURE) { - GST_DEBUG_OBJECT(self, "%s failed to go to playing", - elementname); - goto remove_element_and_fail; - } - - if (link_to != NULL) - if (!gst_element_link(link_to, element)) { - GST_DEBUG_OBJECT(self, "couldn't link %s", - elementname); - goto remove_element_and_fail; - } - - return element; - -remove_element_and_fail: - gst_element_set_state(element, GST_STATE_NULL); - gst_bin_remove(GST_BIN(self), element); - return NULL; - -cleanup_and_fail: - g_object_unref(G_OBJECT(element)); - - return NULL; -} - -static void gst_a2dp_sink_base_init(gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); - - gst_element_class_set_details(element_class, - &gst_a2dp_sink_details); - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&gst_a2dp_sink_factory)); -} - -static void gst_a2dp_sink_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GstA2dpSink *self = GST_A2DP_SINK(object); - - switch (prop_id) { - case PROP_DEVICE: - if (self->sink != NULL) - gst_avdtp_sink_set_device(self->sink, - g_value_get_string(value)); - - if (self->device != NULL) - g_free(self->device); - self->device = g_value_dup_string(value); - break; - - case PROP_TRANSPORT: - if (self->sink != NULL) - gst_avdtp_sink_set_transport(self->sink, - g_value_get_string(value)); - - if (self->transport != NULL) - g_free(self->transport); - self->transport = g_value_dup_string(value); - break; - - case PROP_AUTOCONNECT: - self->autoconnect = g_value_get_boolean(value); - - if (self->sink != NULL) - g_object_set(G_OBJECT(self->sink), "auto-connect", - self->autoconnect, NULL); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void gst_a2dp_sink_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GstA2dpSink *self = GST_A2DP_SINK(object); - gchar *device, *transport; - - switch (prop_id) { - case PROP_DEVICE: - if (self->sink != NULL) { - device = gst_avdtp_sink_get_device(self->sink); - if (device != NULL) - g_value_take_string(value, device); - } - break; - case PROP_AUTOCONNECT: - if (self->sink != NULL) - g_object_get(G_OBJECT(self->sink), "auto-connect", - &self->autoconnect, NULL); - - g_value_set_boolean(value, self->autoconnect); - break; - case PROP_TRANSPORT: - if (self->sink != NULL) { - transport = gst_avdtp_sink_get_transport(self->sink); - if (transport != NULL) - g_value_take_string(value, transport); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static gboolean gst_a2dp_sink_init_ghost_pad(GstA2dpSink *self) -{ - GstPad *capsfilter_pad; - - /* we search for the capsfilter sinkpad */ - capsfilter_pad = gst_element_get_static_pad(self->capsfilter, "sink"); - - /* now we add a ghostpad */ - self->ghostpad = GST_GHOST_PAD(gst_ghost_pad_new("sink", - capsfilter_pad)); - g_object_unref(capsfilter_pad); - - /* the getcaps of our ghostpad must reflect the device caps */ - gst_pad_set_getcaps_function(GST_PAD(self->ghostpad), - gst_a2dp_sink_get_caps); - self->ghostpad_setcapsfunc = GST_PAD_SETCAPSFUNC(self->ghostpad); - gst_pad_set_setcaps_function(GST_PAD(self->ghostpad), - GST_DEBUG_FUNCPTR(gst_a2dp_sink_set_caps)); - - /* we need to handle events on our own and we also need the eventfunc - * of the ghostpad for forwarding calls */ - self->ghostpad_eventfunc = GST_PAD_EVENTFUNC(GST_PAD(self->ghostpad)); - gst_pad_set_event_function(GST_PAD(self->ghostpad), - gst_a2dp_sink_handle_event); - - if (!gst_element_add_pad(GST_ELEMENT(self), GST_PAD(self->ghostpad))) - GST_ERROR_OBJECT(self, "failed to add ghostpad"); - - return TRUE; -} - -static void gst_a2dp_sink_remove_dynamic_elements(GstA2dpSink *self) -{ - if (self->rtp) { - GST_LOG_OBJECT(self, "removing rtp element from the bin"); - if (!gst_bin_remove(GST_BIN(self), GST_ELEMENT(self->rtp))) - GST_WARNING_OBJECT(self, "failed to remove rtp " - "element from bin"); - else - self->rtp = NULL; - } -} - -static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element, - GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstA2dpSink *self = GST_A2DP_SINK(element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - self->taglist = gst_tag_list_new(); - - gst_a2dp_sink_init_fakesink(self); - break; - - 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) { - GST_WARNING_OBJECT(self, "failed to create avdtpsink"); - return GST_STATE_CHANGE_FAILURE; - } - - if (self->device != NULL) - gst_avdtp_sink_set_device(self->sink, - self->device); - - if (self->transport != NULL) - gst_avdtp_sink_set_transport(self->sink, - self->transport); - - g_object_set(G_OBJECT(self->sink), "auto-connect", - self->autoconnect, NULL); - - ret = gst_element_set_state(GST_ELEMENT(self->sink), - GST_STATE_READY); - break; - default: - break; - } - - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, - transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (self->taglist) { - gst_tag_list_free(self->taglist); - self->taglist = NULL; - } - if (self->newseg_event != NULL) { - gst_event_unref(self->newseg_event); - self->newseg_event = NULL; - } - gst_a2dp_sink_remove_fakesink(self); - break; - - case GST_STATE_CHANGE_READY_TO_NULL: - if (self->sink_is_in_bin) { - if (!gst_bin_remove(GST_BIN(self), - GST_ELEMENT(self->sink))) - GST_WARNING_OBJECT(self, "Failed to remove " - "avdtpsink from bin"); - } else if (self->sink != NULL) { - gst_element_set_state(GST_ELEMENT(self->sink), - GST_STATE_NULL); - g_object_unref(G_OBJECT(self->sink)); - } - - self->sink = NULL; - - gst_a2dp_sink_remove_dynamic_elements(self); - break; - default: - break; - } - - return ret; -} - -static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GstElementClass *element_class = GST_ELEMENT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - object_class->set_property = GST_DEBUG_FUNCPTR( - gst_a2dp_sink_set_property); - object_class->get_property = GST_DEBUG_FUNCPTR( - gst_a2dp_sink_get_property); - - object_class->finalize = GST_DEBUG_FUNCPTR( - gst_a2dp_sink_finalize); - - element_class->change_state = GST_DEBUG_FUNCPTR( - gst_a2dp_sink_change_state); - - g_object_class_install_property(object_class, PROP_DEVICE, - g_param_spec_string("device", "Device", - "Bluetooth remote device address", - NULL, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_AUTOCONNECT, - g_param_spec_boolean("auto-connect", "Auto-connect", - "Automatically attempt to connect to device", - DEFAULT_AUTOCONNECT, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_TRANSPORT, - g_param_spec_string("transport", "Transport", - "Use configured transport", - NULL, G_PARAM_READWRITE)); - - GST_DEBUG_CATEGORY_INIT(gst_a2dp_sink_debug, "a2dpsink", 0, - "A2DP sink element"); -} - -GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self) -{ - return gst_avdtp_sink_get_device_caps(self->sink); -} - -static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad) -{ - GstCaps *caps; - GstCaps *caps_aux; - GstA2dpSink *self = GST_A2DP_SINK(GST_PAD_PARENT(pad)); - - if (self->sink == NULL) { - GST_DEBUG_OBJECT(self, "a2dpsink isn't initialized " - "returning template caps"); - caps = gst_static_pad_template_get_caps( - &gst_a2dp_sink_factory); - } else { - GST_LOG_OBJECT(self, "Getting device caps"); - caps = gst_a2dp_sink_get_device_caps(self); - if (caps == NULL) - caps = gst_static_pad_template_get_caps( - &gst_a2dp_sink_factory); - } - caps_aux = gst_caps_copy(caps); - g_object_set(self->capsfilter, "caps", caps_aux, NULL); - gst_caps_unref(caps_aux); - return caps; -} - -static gboolean gst_a2dp_sink_init_avdtp_sink(GstA2dpSink *self) -{ - GstElement *sink; - - /* check if we don't need a new sink */ - if (self->sink_is_in_bin) - return TRUE; - - if (self->sink == NULL) - sink = gst_element_factory_make("avdtpsink", "avdtpsink"); - else - sink = GST_ELEMENT(self->sink); - - if (sink == NULL) { - GST_ERROR_OBJECT(self, "Couldn't create avdtpsink"); - return FALSE; - } - - if (!gst_bin_add(GST_BIN(self), sink)) { - GST_ERROR_OBJECT(self, "failed to add avdtpsink " - "to the bin"); - goto cleanup_and_fail; - } - - if (gst_element_set_state(sink, GST_STATE_READY) == - GST_STATE_CHANGE_FAILURE) { - GST_ERROR_OBJECT(self, "avdtpsink failed to go to ready"); - goto remove_element_and_fail; - } - - if (!gst_element_link(GST_ELEMENT(self->rtp), sink)) { - GST_ERROR_OBJECT(self, "couldn't link rtpsbcpay " - "to avdtpsink"); - goto remove_element_and_fail; - } - - self->sink = GST_AVDTP_SINK(sink); - self->sink_is_in_bin = TRUE; - g_object_set(G_OBJECT(self->sink), "device", self->device, NULL); - g_object_set(G_OBJECT(self->sink), "transport", self->transport, NULL); - - gst_element_set_state(sink, GST_STATE_PAUSED); - - return TRUE; - -remove_element_and_fail: - gst_element_set_state(sink, GST_STATE_NULL); - gst_bin_remove(GST_BIN(self), sink); - return FALSE; - -cleanup_and_fail: - if (sink != NULL) - g_object_unref(G_OBJECT(sink)); - - return FALSE; -} - -static gboolean gst_a2dp_sink_init_rtp_sbc_element(GstA2dpSink *self) -{ - GstElement *rtppay; - - /* if we already have a rtp, we don't need a new one */ - if (self->rtp != NULL) - return TRUE; - - rtppay = gst_a2dp_sink_init_element(self, "rtpsbcpay", "rtp", - self->capsfilter); - if (rtppay == NULL) - return FALSE; - - self->rtp = GST_BASE_RTP_PAYLOAD(rtppay); - g_object_set(G_OBJECT(self->rtp), "min-frames", -1, NULL); - - gst_element_set_state(rtppay, GST_STATE_PAUSED); - - return TRUE; -} - -static gboolean gst_a2dp_sink_init_rtp_mpeg_element(GstA2dpSink *self) -{ - GstElement *rtppay; - - /* check if we don't need a new rtp */ - if (self->rtp) - return TRUE; - - GST_LOG_OBJECT(self, "Initializing rtp mpeg element"); - /* if capsfilter is not created then we can't have our rtp element */ - if (self->capsfilter == NULL) - return FALSE; - - rtppay = gst_a2dp_sink_init_element(self, "rtpmpapay", "rtp", - self->capsfilter); - if (rtppay == NULL) - return FALSE; - - self->rtp = GST_BASE_RTP_PAYLOAD(rtppay); - - gst_element_set_state(rtppay, GST_STATE_PAUSED); - - return TRUE; -} - -static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self, - GstCaps *caps) -{ - GstStructure *structure; - GstEvent *event; - GstPad *capsfilterpad; - gboolean crc; - gchar *mode = NULL; - - structure = gst_caps_get_structure(caps, 0); - - /* before everything we need to remove fakesink */ - gst_a2dp_sink_remove_fakesink(self); - - /* first, we need to create our rtp payloader */ - if (gst_structure_has_name(structure, "audio/x-sbc")) { - GST_LOG_OBJECT(self, "sbc media received"); - if (!gst_a2dp_sink_init_rtp_sbc_element(self)) - return FALSE; - } else if (gst_structure_has_name(structure, "audio/mpeg")) { - GST_LOG_OBJECT(self, "mp3 media received"); - if (!gst_a2dp_sink_init_rtp_mpeg_element(self)) - return FALSE; - } else { - GST_ERROR_OBJECT(self, "Unexpected media type"); - return FALSE; - } - - if (!gst_a2dp_sink_init_avdtp_sink(self)) - return FALSE; - - /* check if we should push the taglist FIXME should we push this? - * we can send the tags directly if needed */ - if (self->taglist != NULL && - gst_structure_has_name(structure, "audio/mpeg")) { - - event = gst_event_new_tag(self->taglist); - - /* send directly the crc */ - if (gst_tag_list_get_boolean(self->taglist, "has-crc", &crc)) - gst_avdtp_sink_set_crc(self->sink, crc); - - if (gst_tag_list_get_string(self->taglist, "channel-mode", - &mode)) - gst_avdtp_sink_set_channel_mode(self->sink, mode); - - capsfilterpad = gst_ghost_pad_get_target(self->ghostpad); - gst_pad_send_event(capsfilterpad, event); - self->taglist = NULL; - g_free(mode); - } - - if (!gst_avdtp_sink_set_device_caps(self->sink, caps)) - return FALSE; - - g_object_set(G_OBJECT(self->rtp), "mtu", - gst_avdtp_sink_get_link_mtu(self->sink), NULL); - - /* we forward our new segment here if we have one */ - if (self->newseg_event) { - gst_pad_send_event(GST_BASE_RTP_PAYLOAD_SINKPAD(self->rtp), - self->newseg_event); - self->newseg_event = NULL; - } - - return TRUE; -} - -static gboolean gst_a2dp_sink_set_caps(GstPad *pad, GstCaps *caps) -{ - GstA2dpSink *self; - - self = GST_A2DP_SINK(GST_PAD_PARENT(pad)); - GST_INFO_OBJECT(self, "setting caps"); - - /* now we know the caps */ - gst_a2dp_sink_init_dynamic_elements(self, caps); - - return self->ghostpad_setcapsfunc(GST_PAD(self->ghostpad), caps); -} - -/* used for catching newsegment events while we don't have a sink, for - * later forwarding it to the sink */ -static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event) -{ - GstA2dpSink *self; - GstTagList *taglist = NULL; - GstObject *parent; - - self = GST_A2DP_SINK(GST_PAD_PARENT(pad)); - parent = gst_element_get_parent(GST_ELEMENT(self->sink)); - - if (GST_EVENT_TYPE(event) == GST_EVENT_NEWSEGMENT && - parent != GST_OBJECT_CAST(self)) { - 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) - gst_event_parse_tag(event, &self->taglist); - else { - gst_event_parse_tag(event, &taglist); - gst_tag_list_insert(self->taglist, taglist, - GST_TAG_MERGE_REPLACE); - } - } - - if (parent != NULL) - gst_object_unref(GST_OBJECT(parent)); - - return self->ghostpad_eventfunc(GST_PAD(self->ghostpad), event); -} - -static gboolean gst_a2dp_sink_init_caps_filter(GstA2dpSink *self) -{ - GstElement *element; - - element = gst_element_factory_make("capsfilter", "filter"); - if (element == NULL) - goto failed; - - if (!gst_bin_add(GST_BIN(self), element)) - goto failed; - - self->capsfilter = element; - return TRUE; - -failed: - GST_ERROR_OBJECT(self, "Failed to initialize caps filter"); - return FALSE; -} - -static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self) -{ - if (self->fakesink != NULL) - return TRUE; - - g_mutex_lock(self->cb_mutex); - self->fakesink = gst_a2dp_sink_init_element(self, "fakesink", - "fakesink", self->capsfilter); - g_mutex_unlock(self->cb_mutex); - - if (!self->fakesink) - return FALSE; - - return TRUE; -} - -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; -} - -static void gst_a2dp_sink_init(GstA2dpSink *self, - GstA2dpSinkClass *klass) -{ - self->sink = NULL; - self->fakesink = NULL; - self->rtp = NULL; - self->device = NULL; - self->transport = NULL; - self->autoconnect = DEFAULT_AUTOCONNECT; - self->capsfilter = NULL; - self->newseg_event = NULL; - self->taglist = NULL; - self->ghostpad = NULL; - self->sink_is_in_bin = FALSE; - - self->cb_mutex = g_mutex_new(); - - /* we initialize our capsfilter */ - gst_a2dp_sink_init_caps_filter(self); - g_object_set(self->capsfilter, "caps", - gst_static_pad_template_get_caps(&gst_a2dp_sink_factory), - NULL); - - gst_a2dp_sink_init_fakesink(self); - - gst_a2dp_sink_init_ghost_pad(self); - -} - -gboolean gst_a2dp_sink_plugin_init(GstPlugin *plugin) -{ - return gst_element_register(plugin, "a2dpsink", - GST_RANK_MARGINAL, GST_TYPE_A2DP_SINK); -} diff --git a/audio/gsta2dpsink.h b/audio/gsta2dpsink.h deleted file mode 100644 index 1a591b22e..000000000 --- a/audio/gsta2dpsink.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GST_A2DP_SINK_H__ -#define __GST_A2DP_SINK_H__ - -#include -#include -#include "gstavdtpsink.h" - -G_BEGIN_DECLS - -#define GST_TYPE_A2DP_SINK \ - (gst_a2dp_sink_get_type()) -#define GST_A2DP_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_A2DP_SINK,GstA2dpSink)) -#define GST_A2DP_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_A2DP_SINK,GstA2dpSinkClass)) -#define GST_IS_A2DP_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_A2DP_SINK)) -#define GST_IS_A2DP_SINK_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_A2DP_SINK)) - -typedef struct _GstA2dpSink GstA2dpSink; -typedef struct _GstA2dpSinkClass GstA2dpSinkClass; - -struct _GstA2dpSink { - GstBin bin; - - GstBaseRTPPayload *rtp; - GstAvdtpSink *sink; - GstElement *capsfilter; - GstElement *fakesink; - - gchar *device; - gchar *transport; - gboolean autoconnect; - gboolean sink_is_in_bin; - - GstGhostPad *ghostpad; - GstPadSetCapsFunction ghostpad_setcapsfunc; - GstPadEventFunction ghostpad_eventfunc; - - GstEvent *newseg_event; - /* Store the tags received before the a2dpsender sink is created - * when it is created we forward this to it */ - GstTagList *taglist; - - GMutex *cb_mutex; -}; - -struct _GstA2dpSinkClass { - GstBinClass parent_class; -}; - -GType gst_a2dp_sink_get_type(void); - -gboolean gst_a2dp_sink_plugin_init (GstPlugin * plugin); - -GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self); - -G_END_DECLS - -#endif diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c deleted file mode 100644 index 601791001..000000000 --- a/audio/gstavdtpsink.c +++ /dev/null @@ -1,1152 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include - -#include "rtp.h" -#include "a2dp-codecs.h" - -#include "gstpragma.h" -#include "gstavdtpsink.h" - -GST_DEBUG_CATEGORY_STATIC(avdtp_sink_debug); -#define GST_CAT_DEFAULT avdtp_sink_debug - -#define BUFFER_SIZE 2048 -#define TEMPLATE_MAX_BITPOOL 64 -#define CRC_PROTECTED 1 -#define CRC_UNPROTECTED 0 - -#define DEFAULT_AUTOCONNECT TRUE - -#define GST_AVDTP_SINK_MUTEX_LOCK(s) G_STMT_START { \ - g_mutex_lock(s->sink_lock); \ - } G_STMT_END - -#define GST_AVDTP_SINK_MUTEX_UNLOCK(s) G_STMT_START { \ - g_mutex_unlock(s->sink_lock); \ - } G_STMT_END - -struct bluetooth_data { - guint link_mtu; - - DBusConnection *conn; - guint8 codec; /* Bluetooth transport configuration */ - gchar *uuid; - guint8 *config; - gint config_size; - - gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */ -}; - -#define IS_SBC(n) (strcmp((n), "audio/x-sbc") == 0) -#define IS_MPEG_AUDIO(n) (strcmp((n), "audio/mpeg") == 0) - -enum { - PROP_0, - PROP_DEVICE, - PROP_AUTOCONNECT, - PROP_TRANSPORT -}; - -GST_BOILERPLATE(GstAvdtpSink, gst_avdtp_sink, GstBaseSink, - GST_TYPE_BASE_SINK); - -static const GstElementDetails avdtp_sink_details = - GST_ELEMENT_DETAILS("Bluetooth AVDTP sink", - "Sink/Audio", - "Plays audio to an A2DP device", - "Marcel Holtmann "); - -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\"," - "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) " - GST_RTP_PAYLOAD_MPA_STRING ", " - "clock-rate = (int) 90000; " - "application/x-rtp, " - "media = (string) \"audio\", " - "payload = (int) " - GST_RTP_PAYLOAD_DYNAMIC_STRING ", " - "clock-rate = (int) 90000, " - "encoding-name = (string) \"MPA\"" - )); - -static void gst_avdtp_sink_base_init(gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&avdtp_sink_factory)); - - gst_element_class_set_details(element_class, &avdtp_sink_details); -} - -static void gst_avdtp_sink_transport_release(GstAvdtpSink *self) -{ - DBusMessage *msg; - const char *access_type = "w"; - - msg = dbus_message_new_method_call("org.bluez", self->transport, - "org.bluez.MediaTransport", - "Release"); - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &access_type, - DBUS_TYPE_INVALID); - - dbus_connection_send(self->data->conn, msg, NULL); - - dbus_message_unref(msg); -} - -static gboolean gst_avdtp_sink_stop(GstBaseSink *basesink) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(basesink); - - GST_INFO_OBJECT(self, "stop"); - - if (self->watch_id != 0) { - g_source_remove(self->watch_id); - self->watch_id = 0; - } - - if (self->stream) { - g_io_channel_shutdown(self->stream, TRUE, NULL); - g_io_channel_unref(self->stream); - self->stream = NULL; - } - - if (self->data) { - if (self->transport) - gst_avdtp_sink_transport_release(self); - if (self->data->conn) - dbus_connection_unref(self->data->conn); - g_free(self->data); - self->data = NULL; - } - - if (self->stream_caps) { - gst_caps_unref(self->stream_caps); - self->stream_caps = NULL; - } - - if (self->dev_caps) { - gst_caps_unref(self->dev_caps); - self->dev_caps = NULL; - } - - return TRUE; -} - -static void gst_avdtp_sink_finalize(GObject *object) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(object); - - if (self->data) - gst_avdtp_sink_stop(GST_BASE_SINK(self)); - - if (self->device) - g_free(self->device); - - if (self->transport) - g_free(self->transport); - - g_mutex_free(self->sink_lock); - - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -static void gst_avdtp_sink_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GstAvdtpSink *sink = GST_AVDTP_SINK(object); - - switch (prop_id) { - case PROP_DEVICE: - if (sink->device) - g_free(sink->device); - sink->device = g_value_dup_string(value); - break; - - case PROP_AUTOCONNECT: - sink->autoconnect = g_value_get_boolean(value); - break; - - case PROP_TRANSPORT: - if (sink->transport) - g_free(sink->transport); - sink->transport = g_value_dup_string(value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void gst_avdtp_sink_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GstAvdtpSink *sink = GST_AVDTP_SINK(object); - - switch (prop_id) { - case PROP_DEVICE: - g_value_set_string(value, sink->device); - break; - - case PROP_AUTOCONNECT: - g_value_set_boolean(value, sink->autoconnect); - break; - - case PROP_TRANSPORT: - g_value_set_string(value, sink->transport); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static GstStructure *gst_avdtp_sink_parse_sbc_raw(GstAvdtpSink *self) -{ - a2dp_sbc_t *sbc = (a2dp_sbc_t *) self->data->config; - GstStructure *structure; - GValue *value; - GValue *list; - gboolean mono, stereo; - - structure = gst_structure_empty_new("audio/x-sbc"); - value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING); - - /* mode */ - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO) { - g_value_set_static_string(value, "mono"); - gst_value_list_prepend_value(list, value); - } - if (sbc->channel_mode & SBC_CHANNEL_MODE_STEREO) { - g_value_set_static_string(value, "stereo"); - gst_value_list_prepend_value(list, value); - } - if (sbc->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL) { - g_value_set_static_string(value, "dual"); - gst_value_list_prepend_value(list, value); - } - if (sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) { - g_value_set_static_string(value, "joint"); - gst_value_list_prepend_value(list, value); - } - g_value_unset(value); - if (list) { - gst_structure_set_value(structure, "mode", list); - g_free(list); - list = NULL; - } - - /* subbands */ - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - value = g_value_init(value, G_TYPE_INT); - if (sbc->subbands & SBC_SUBBANDS_4) { - g_value_set_int(value, 4); - gst_value_list_prepend_value(list, value); - } - if (sbc->subbands & SBC_SUBBANDS_8) { - g_value_set_int(value, 8); - gst_value_list_prepend_value(list, value); - } - g_value_unset(value); - if (list) { - gst_structure_set_value(structure, "subbands", list); - g_free(list); - list = NULL; - } - - /* blocks */ - value = g_value_init(value, G_TYPE_INT); - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - if (sbc->block_length & SBC_BLOCK_LENGTH_16) { - g_value_set_int(value, 16); - gst_value_list_prepend_value(list, value); - } - if (sbc->block_length & SBC_BLOCK_LENGTH_12) { - g_value_set_int(value, 12); - gst_value_list_prepend_value(list, value); - } - if (sbc->block_length & SBC_BLOCK_LENGTH_8) { - g_value_set_int(value, 8); - gst_value_list_prepend_value(list, value); - } - if (sbc->block_length & SBC_BLOCK_LENGTH_4) { - g_value_set_int(value, 4); - gst_value_list_prepend_value(list, value); - } - g_value_unset(value); - if (list) { - gst_structure_set_value(structure, "blocks", list); - g_free(list); - list = NULL; - } - - /* allocation */ - g_value_init(value, G_TYPE_STRING); - list = g_value_init(g_new0(GValue,1), GST_TYPE_LIST); - if (sbc->allocation_method & SBC_ALLOCATION_LOUDNESS) { - g_value_set_static_string(value, "loudness"); - gst_value_list_prepend_value(list, value); - } - if (sbc->allocation_method & SBC_ALLOCATION_SNR) { - g_value_set_static_string(value, "snr"); - gst_value_list_prepend_value(list, value); - } - g_value_unset(value); - if (list) { - gst_structure_set_value(structure, "allocation", list); - g_free(list); - list = NULL; - } - - /* rate */ - g_value_init(value, G_TYPE_INT); - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - if (sbc->frequency & SBC_SAMPLING_FREQ_48000) { - g_value_set_int(value, 48000); - gst_value_list_prepend_value(list, value); - } - if (sbc->frequency & SBC_SAMPLING_FREQ_44100) { - g_value_set_int(value, 44100); - gst_value_list_prepend_value(list, value); - } - if (sbc->frequency & SBC_SAMPLING_FREQ_32000) { - g_value_set_int(value, 32000); - gst_value_list_prepend_value(list, value); - } - if (sbc->frequency & SBC_SAMPLING_FREQ_16000) { - g_value_set_int(value, 16000); - gst_value_list_prepend_value(list, value); - } - g_value_unset(value); - if (list) { - gst_structure_set_value(structure, "rate", list); - g_free(list); - list = NULL; - } - - /* bitpool */ - value = g_value_init(value, GST_TYPE_INT_RANGE); - gst_value_set_int_range(value, - MIN(sbc->min_bitpool, TEMPLATE_MAX_BITPOOL), - MIN(sbc->max_bitpool, TEMPLATE_MAX_BITPOOL)); - gst_structure_set_value(structure, "bitpool", value); - g_value_unset(value); - - /* channels */ - mono = FALSE; - stereo = FALSE; - if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO) - mono = TRUE; - if ((sbc->channel_mode & SBC_CHANNEL_MODE_STEREO) || - (sbc->channel_mode & - SBC_CHANNEL_MODE_DUAL_CHANNEL) || - (sbc->channel_mode & - SBC_CHANNEL_MODE_JOINT_STEREO)) - stereo = TRUE; - - if (mono && stereo) { - g_value_init(value, GST_TYPE_INT_RANGE); - gst_value_set_int_range(value, 1, 2); - } else { - g_value_init(value, G_TYPE_INT); - if (mono) - g_value_set_int(value, 1); - else if (stereo) - g_value_set_int(value, 2); - else { - GST_ERROR_OBJECT(self, - "Unexpected number of channels"); - g_value_set_int(value, 0); - } - } - - gst_structure_set_value(structure, "channels", value); - g_free(value); - - return structure; -} - -static GstStructure *gst_avdtp_sink_parse_mpeg_raw(GstAvdtpSink *self) -{ - a2dp_mpeg_t *mpeg = (a2dp_mpeg_t *) self->data->config; - GstStructure *structure; - GValue *value; - GValue *list; - gboolean valid_layer = FALSE; - gboolean mono, stereo; - - GST_LOG_OBJECT(self, "parsing mpeg caps"); - - structure = gst_structure_empty_new("audio/mpeg"); - value = g_new0(GValue, 1); - g_value_init(value, G_TYPE_INT); - - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - g_value_set_int(value, 1); - gst_value_list_prepend_value(list, value); - g_value_set_int(value, 2); - gst_value_list_prepend_value(list, value); - gst_structure_set_value(structure, "mpegversion", list); - g_free(list); - - /* layer */ - GST_LOG_OBJECT(self, "setting mpeg layer"); - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - if (mpeg->layer & MPEG_LAYER_MP1) { - g_value_set_int(value, 1); - gst_value_list_prepend_value(list, value); - valid_layer = TRUE; - } - if (mpeg->layer & MPEG_LAYER_MP2) { - g_value_set_int(value, 2); - gst_value_list_prepend_value(list, value); - valid_layer = TRUE; - } - if (mpeg->layer & MPEG_LAYER_MP3) { - g_value_set_int(value, 3); - gst_value_list_prepend_value(list, value); - valid_layer = TRUE; - } - if (list) { - gst_structure_set_value(structure, "layer", list); - g_free(list); - list = NULL; - } - - if (!valid_layer) { - gst_structure_free(structure); - g_free(value); - return NULL; - } - - /* rate */ - GST_LOG_OBJECT(self, "setting mpeg rate"); - list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - if (mpeg->frequency & MPEG_SAMPLING_FREQ_48000) { - g_value_set_int(value, 48000); - gst_value_list_prepend_value(list, value); - } - if (mpeg->frequency & MPEG_SAMPLING_FREQ_44100) { - g_value_set_int(value, 44100); - gst_value_list_prepend_value(list, value); - } - if (mpeg->frequency & MPEG_SAMPLING_FREQ_32000) { - g_value_set_int(value, 32000); - gst_value_list_prepend_value(list, value); - } - if (mpeg->frequency & MPEG_SAMPLING_FREQ_24000) { - g_value_set_int(value, 24000); - gst_value_list_prepend_value(list, value); - } - if (mpeg->frequency & MPEG_SAMPLING_FREQ_22050) { - g_value_set_int(value, 22050); - gst_value_list_prepend_value(list, value); - } - if (mpeg->frequency & MPEG_SAMPLING_FREQ_16000) { - g_value_set_int(value, 16000); - gst_value_list_prepend_value(list, value); - } - g_value_unset(value); - if (list) { - gst_structure_set_value(structure, "rate", list); - g_free(list); - list = NULL; - } - - /* channels */ - GST_LOG_OBJECT(self, "setting mpeg channels"); - mono = FALSE; - stereo = FALSE; - if (mpeg->channel_mode & MPEG_CHANNEL_MODE_MONO) - mono = TRUE; - if ((mpeg->channel_mode & MPEG_CHANNEL_MODE_STEREO) || - (mpeg->channel_mode & - MPEG_CHANNEL_MODE_DUAL_CHANNEL) || - (mpeg->channel_mode & - MPEG_CHANNEL_MODE_JOINT_STEREO)) - stereo = TRUE; - - if (mono && stereo) { - g_value_init(value, GST_TYPE_INT_RANGE); - gst_value_set_int_range(value, 1, 2); - } else { - g_value_init(value, G_TYPE_INT); - if (mono) - g_value_set_int(value, 1); - else if (stereo) - g_value_set_int(value, 2); - else { - GST_ERROR_OBJECT(self, - "Unexpected number of channels"); - g_value_set_int(value, 0); - } - } - gst_structure_set_value(structure, "channels", value); - g_free(value); - - return structure; -} - -static gboolean gst_avdtp_sink_update_config(GstAvdtpSink *self) -{ - GstStructure *structure; - gchar *tmp; - - switch (self->data->codec) { - case A2DP_CODEC_SBC: - structure = gst_avdtp_sink_parse_sbc_raw(self); - break; - case A2DP_CODEC_MPEG12: - structure = gst_avdtp_sink_parse_mpeg_raw(self); - break; - default: - GST_ERROR_OBJECT(self, "Unsupported configuration"); - return FALSE; - } - - if (structure == NULL) - return FALSE; - - 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); - GST_DEBUG_OBJECT(self, "Transport configuration: %s", tmp); - g_free(tmp); - - return TRUE; -} - -static gboolean gst_avdtp_sink_update_caps(GstAvdtpSink *self) -{ - GST_LOG_OBJECT(self, "updating device caps"); - - if (self->data->config_size == 0 || self->data->config == NULL) - return FALSE; - - return gst_avdtp_sink_update_config(self); -} - -static gint gst_avdtp_sink_get_channel_mode(const gchar *mode) -{ - if (strcmp(mode, "stereo") == 0) - return SBC_CHANNEL_MODE_STEREO; - else if (strcmp(mode, "joint-stereo") == 0) - return SBC_CHANNEL_MODE_JOINT_STEREO; - else if (strcmp(mode, "dual-channel") == 0) - return SBC_CHANNEL_MODE_DUAL_CHANNEL; - else if (strcmp(mode, "mono") == 0) - return SBC_CHANNEL_MODE_MONO; - else - return -1; -} - -static void gst_avdtp_sink_tag(const GstTagList *taglist, - const gchar *tag, gpointer user_data) -{ - gboolean crc; - gchar *channel_mode = NULL; - GstAvdtpSink *self = GST_AVDTP_SINK(user_data); - - if (strcmp(tag, "has-crc") == 0) { - - if (!gst_tag_list_get_boolean(taglist, tag, &crc)) { - GST_WARNING_OBJECT(self, "failed to get crc tag"); - return; - } - - gst_avdtp_sink_set_crc(self, crc); - - } else if (strcmp(tag, "channel-mode") == 0) { - - if (!gst_tag_list_get_string(taglist, tag, &channel_mode)) { - GST_WARNING_OBJECT(self, - "failed to get channel-mode tag"); - return; - } - - self->channel_mode = gst_avdtp_sink_get_channel_mode( - channel_mode); - if (self->channel_mode == -1) - GST_WARNING_OBJECT(self, "Received invalid channel " - "mode: %s", channel_mode); - g_free(channel_mode); - - } else - GST_DEBUG_OBJECT(self, "received unused tag: %s", tag); -} - -static gboolean gst_avdtp_sink_event(GstBaseSink *basesink, - GstEvent *event) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(basesink); - GstTagList *taglist = NULL; - - if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) { - /* we check the tags, mp3 has tags that are importants and - * are outside caps */ - gst_event_parse_tag(event, &taglist); - gst_tag_list_foreach(taglist, gst_avdtp_sink_tag, self); - } - - return TRUE; -} - -static gboolean gst_avdtp_sink_transport_parse_property(GstAvdtpSink *self, - DBusMessageIter *i) -{ - const char *key; - DBusMessageIter variant_i; - - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) { - GST_ERROR_OBJECT(self, "Property name not a string."); - return FALSE; - } - - dbus_message_iter_get_basic(i, &key); - - if (!dbus_message_iter_next(i)) { - GST_ERROR_OBJECT(self, "Property value missing"); - return FALSE; - } - - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) { - GST_ERROR_OBJECT(self, "Property value not a variant."); - return FALSE; - } - - dbus_message_iter_recurse(i, &variant_i); - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - case DBUS_TYPE_BYTE: { - uint8_t value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (g_str_equal(key, "Codec") == TRUE) - self->data->codec = value; - - break; - } - case DBUS_TYPE_STRING: { - const char *value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (g_str_equal(key, "UUID") == TRUE) { - g_free(self->data->uuid); - self->data->uuid = g_strdup(value); - } - - break; - } - case DBUS_TYPE_ARRAY: { - DBusMessageIter array_i; - char *value; - int size; - - dbus_message_iter_recurse(&variant_i, &array_i); - dbus_message_iter_get_fixed_array(&array_i, &value, &size); - - if (g_str_equal(key, "Configuration")) { - g_free(self->data->config); - self->data->config = g_new0(guint8, size); - self->data->config_size = size; - memcpy(self->data->config, value, size); - } - - break; - } - } - - return TRUE; -} - -static gboolean gst_avdtp_sink_transport_acquire(GstAvdtpSink *self) -{ - DBusMessage *msg, *reply; - DBusError err; - const char *access_type = "w"; - int fd; - uint16_t imtu, omtu; - - dbus_error_init(&err); - - if (self->data->conn == NULL) - self->data->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - - msg = dbus_message_new_method_call("org.bluez", self->transport, - "org.bluez.MediaTransport", - "Acquire"); - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &access_type, - DBUS_TYPE_INVALID); - - reply = dbus_connection_send_with_reply_and_block(self->data->conn, - msg, -1, &err); - - dbus_message_unref(msg); - - if (dbus_error_is_set(&err)) - goto fail; - - if (dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd, - DBUS_TYPE_UINT16, &imtu, - DBUS_TYPE_UINT16, &omtu, - DBUS_TYPE_INVALID) == FALSE) - goto fail; - - dbus_message_unref(reply); - - self->stream = g_io_channel_unix_new(fd); - g_io_channel_set_encoding(self->stream, NULL, NULL); - g_io_channel_set_close_on_unref(self->stream, TRUE); - self->data->link_mtu = omtu; - GST_DEBUG_OBJECT(self, "stream_fd=%d mtu=%d", fd, omtu); - - return TRUE; - -fail: - GST_ERROR_OBJECT(self, "Failed to acquire transport stream: %s", - err.message); - - dbus_error_free(&err); - - if (reply) - dbus_message_unref(reply); - - return FALSE; -} - -static gboolean gst_avdtp_sink_transport_get_properties(GstAvdtpSink *self) -{ - DBusMessage *msg, *reply; - DBusMessageIter arg_i, ele_i; - DBusError err; - - dbus_error_init(&err); - - /* Transport need to be acquire first to make sure the MTUs are - available */ - if (gst_avdtp_sink_transport_acquire(self) == FALSE) - return FALSE; - - msg = dbus_message_new_method_call("org.bluez", self->transport, - "org.bluez.MediaTransport", - "GetProperties"); - if (!msg) { - GST_ERROR_OBJECT(self, "D-Bus Memory allocation failed"); - return FALSE; - } - - reply = dbus_connection_send_with_reply_and_block(self->data->conn, - msg, -1, &err); - dbus_message_unref(msg); - - if (dbus_error_is_set(&err)) { - GST_ERROR_OBJECT(self, "GetProperties failed: %s", err.message); - dbus_error_free(&err); - return FALSE; - } - - if (!dbus_message_iter_init(reply, &arg_i)) { - GST_ERROR_OBJECT(self, "GetProperties reply has no arguments."); - goto fail; - } - - if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) { - GST_ERROR_OBJECT(self, "GetProperties argument is not an array."); - goto fail; - } - - dbus_message_iter_recurse(&arg_i, &ele_i); - while (dbus_message_iter_get_arg_type(&ele_i) != DBUS_TYPE_INVALID) { - - if (dbus_message_iter_get_arg_type(&ele_i) == - DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter dict_i; - - dbus_message_iter_recurse(&ele_i, &dict_i); - - gst_avdtp_sink_transport_parse_property(self, &dict_i); - } - - if (!dbus_message_iter_next(&ele_i)) - break; - } - - return gst_avdtp_sink_update_caps(self); - -fail: - dbus_message_unref(reply); - return FALSE; - -} - -static gboolean gst_avdtp_sink_start(GstBaseSink *basesink) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(basesink); - - GST_INFO_OBJECT(self, "start"); - - self->data = g_new0(struct bluetooth_data, 1); - - self->stream = NULL; - self->stream_caps = NULL; - self->mp3_using_crc = -1; - self->channel_mode = -1; - - if (self->transport == NULL) - return FALSE; - - return gst_avdtp_sink_transport_get_properties(self); -} - -static gboolean gst_avdtp_sink_conf_recv_stream_fd(GstAvdtpSink *self) -{ - struct bluetooth_data *data = self->data; - GError *gerr = NULL; - GIOStatus status; - GIOFlags flags; - int fd; - - /* Proceed if stream was already acquired */ - if (self->stream == NULL) { - GST_ERROR_OBJECT(self, "Error while configuring device: " - "could not acquire audio socket"); - return FALSE; - } - - /* set stream socket to nonblock */ - GST_LOG_OBJECT(self, "setting stream socket to nonblock"); - flags = g_io_channel_get_flags(self->stream); - flags |= G_IO_FLAG_NONBLOCK; - status = g_io_channel_set_flags(self->stream, flags, &gerr); - if (status != G_IO_STATUS_NORMAL) { - if (gerr) - GST_WARNING_OBJECT(self, "Error while " - "setting server socket to nonblock: " - "%s", gerr->message); - else - GST_WARNING_OBJECT(self, "Error while " - "setting server " - "socket to nonblock"); - } - - fd = g_io_channel_unix_get_fd(self->stream); - - /* It is possible there is some outstanding - data in the pipe - we have to empty it */ - GST_LOG_OBJECT(self, "emptying stream pipe"); - while (1) { - ssize_t bread = read(fd, data->buffer, data->link_mtu); - if (bread <= 0) - break; - } - - /* set stream socket to block */ - GST_LOG_OBJECT(self, "setting stream socket to block"); - flags = g_io_channel_get_flags(self->stream); - flags &= ~G_IO_FLAG_NONBLOCK; - status = g_io_channel_set_flags(self->stream, flags, &gerr); - if (status != G_IO_STATUS_NORMAL) { - if (gerr) - GST_WARNING_OBJECT(self, "Error while " - "setting server socket to block:" - "%s", gerr->message); - else - GST_WARNING_OBJECT(self, "Error while " - "setting server " - "socket to block"); - } - - memset(data->buffer, 0, sizeof(data->buffer)); - - return TRUE; -} - -static GstFlowReturn gst_avdtp_sink_preroll(GstBaseSink *basesink, - GstBuffer *buffer) -{ - GstAvdtpSink *sink = GST_AVDTP_SINK(basesink); - gboolean ret; - - GST_AVDTP_SINK_MUTEX_LOCK(sink); - - ret = gst_avdtp_sink_conf_recv_stream_fd(sink); - - GST_AVDTP_SINK_MUTEX_UNLOCK(sink); - - if (!ret) - return GST_FLOW_ERROR; - - return GST_FLOW_OK; -} - -static GstFlowReturn gst_avdtp_sink_render(GstBaseSink *basesink, - GstBuffer *buffer) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(basesink); - ssize_t ret; - int fd; - - fd = g_io_channel_unix_get_fd(self->stream); - - ret = write(fd, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); - if (ret < 0) { - GST_ERROR_OBJECT(self, "Error while writting to socket: %s", - strerror(errno)); - return GST_FLOW_ERROR; - } - - return GST_FLOW_OK; -} - -static gboolean gst_avdtp_sink_unlock(GstBaseSink *basesink) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(basesink); - - if (self->stream != NULL) - g_io_channel_flush(self->stream, NULL); - - return TRUE; -} - -static GstFlowReturn gst_avdtp_sink_buffer_alloc(GstBaseSink *basesink, - guint64 offset, guint size, GstCaps *caps, - GstBuffer **buf) -{ - GstAvdtpSink *self = GST_AVDTP_SINK(basesink); - - *buf = gst_buffer_new_and_alloc(size); - if (!(*buf)) { - GST_ERROR_OBJECT(self, "buffer allocation failed"); - return GST_FLOW_ERROR; - } - - gst_buffer_set_caps(*buf, caps); - - GST_BUFFER_OFFSET(*buf) = offset; - - return GST_FLOW_OK; -} - -static void gst_avdtp_sink_class_init(GstAvdtpSinkClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - object_class->finalize = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_finalize); - object_class->set_property = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_set_property); - object_class->get_property = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_get_property); - - basesink_class->start = GST_DEBUG_FUNCPTR(gst_avdtp_sink_start); - basesink_class->stop = GST_DEBUG_FUNCPTR(gst_avdtp_sink_stop); - basesink_class->render = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_render); - basesink_class->preroll = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_preroll); - basesink_class->unlock = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_unlock); - basesink_class->event = GST_DEBUG_FUNCPTR( - gst_avdtp_sink_event); - - basesink_class->buffer_alloc = - GST_DEBUG_FUNCPTR(gst_avdtp_sink_buffer_alloc); - - g_object_class_install_property(object_class, PROP_DEVICE, - g_param_spec_string("device", "Device", - "Bluetooth remote device address", - NULL, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_AUTOCONNECT, - g_param_spec_boolean("auto-connect", - "Auto-connect", - "Automatically attempt to connect " - "to device", DEFAULT_AUTOCONNECT, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_TRANSPORT, - g_param_spec_string("transport", - "Transport", - "Use configured transport", - NULL, G_PARAM_READWRITE)); - - GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "avdtpsink", 0, - "A2DP headset sink element"); -} - -static void gst_avdtp_sink_init(GstAvdtpSink *self, - GstAvdtpSinkClass *klass) -{ - self->device = NULL; - self->transport = NULL; - self->data = NULL; - - self->stream = NULL; - - self->dev_caps = NULL; - - self->autoconnect = DEFAULT_AUTOCONNECT; - - 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); - */ -} - -gboolean gst_avdtp_sink_plugin_init(GstPlugin *plugin) -{ - return gst_element_register(plugin, "avdtpsink", GST_RANK_NONE, - GST_TYPE_AVDTP_SINK); -} - - -/* public functions */ -GstCaps *gst_avdtp_sink_get_device_caps(GstAvdtpSink *sink) -{ - if (sink->dev_caps == NULL) - return NULL; - - return gst_caps_copy(sink->dev_caps); -} - -gboolean gst_avdtp_sink_set_device_caps(GstAvdtpSink *self, - GstCaps *caps) -{ - GST_DEBUG_OBJECT(self, "setting device caps"); - GST_AVDTP_SINK_MUTEX_LOCK(self); - - if (self->stream_caps) - gst_caps_unref(self->stream_caps); - self->stream_caps = gst_caps_ref(caps); - - GST_AVDTP_SINK_MUTEX_UNLOCK(self); - - return TRUE; -} - -guint gst_avdtp_sink_get_link_mtu(GstAvdtpSink *sink) -{ - return sink->data->link_mtu; -} - -void gst_avdtp_sink_set_device(GstAvdtpSink *self, const gchar *dev) -{ - if (self->device != NULL) - g_free(self->device); - - GST_LOG_OBJECT(self, "Setting device: %s", dev); - self->device = g_strdup(dev); -} - -void gst_avdtp_sink_set_transport(GstAvdtpSink *self, const gchar *trans) -{ - if (self->transport != NULL) - g_free(self->transport); - - GST_LOG_OBJECT(self, "Setting transport: %s", trans); - self->transport = g_strdup(trans); -} - -gchar *gst_avdtp_sink_get_device(GstAvdtpSink *self) -{ - return g_strdup(self->device); -} - -gchar *gst_avdtp_sink_get_transport(GstAvdtpSink *self) -{ - return g_strdup(self->transport); -} - -void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc) -{ - gint new_crc; - - new_crc = crc ? CRC_PROTECTED : CRC_UNPROTECTED; - - /* test if we already received a different crc */ - if (self->mp3_using_crc != -1 && new_crc != self->mp3_using_crc) { - GST_WARNING_OBJECT(self, "crc changed during stream"); - return; - } - self->mp3_using_crc = new_crc; - -} - -void gst_avdtp_sink_set_channel_mode(GstAvdtpSink *self, - const gchar *mode) -{ - gint new_mode; - - new_mode = gst_avdtp_sink_get_channel_mode(mode); - - if (self->channel_mode != -1 && new_mode != self->channel_mode) { - GST_WARNING_OBJECT(self, "channel mode changed during stream"); - return; - } - - self->channel_mode = new_mode; - if (self->channel_mode == -1) - GST_WARNING_OBJECT(self, "Received invalid channel " - "mode: %s", mode); -} diff --git a/audio/gstavdtpsink.h b/audio/gstavdtpsink.h deleted file mode 100644 index 4862e7fcd..000000000 --- a/audio/gstavdtpsink.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GST_AVDTP_SINK_H -#define __GST_AVDTP_SINK_H - -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_AVDTP_SINK \ - (gst_avdtp_sink_get_type()) -#define GST_AVDTP_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVDTP_SINK,\ - GstAvdtpSink)) -#define GST_AVDTP_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVDTP_SINK,\ - GstAvdtpSinkClass)) -#define GST_IS_AVDTP_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVDTP_SINK)) -#define GST_IS_AVDTP_SINK_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVDTP_SINK)) - -typedef struct _GstAvdtpSink GstAvdtpSink; -typedef struct _GstAvdtpSinkClass GstAvdtpSinkClass; - -struct bluetooth_data; - -struct _GstAvdtpSink { - GstBaseSink sink; - - gchar *device; - gchar *transport; - GIOChannel *stream; - - struct bluetooth_data *data; - gboolean autoconnect; - - /* mp3 stream data (outside caps data)*/ - gint mp3_using_crc; - gint channel_mode; - - /* stream connection data */ - GstCaps *stream_caps; - - GstCaps *dev_caps; - - GMutex *sink_lock; - - guint watch_id; -}; - -struct _GstAvdtpSinkClass { - GstBaseSinkClass parent_class; -}; - -GType gst_avdtp_sink_get_type(void); - -GstCaps *gst_avdtp_sink_get_device_caps(GstAvdtpSink *sink); -gboolean gst_avdtp_sink_set_device_caps(GstAvdtpSink *sink, - GstCaps *caps); - -guint gst_avdtp_sink_get_link_mtu(GstAvdtpSink *sink); - -void gst_avdtp_sink_set_device(GstAvdtpSink *sink, - const gchar *device); - -void gst_avdtp_sink_set_transport(GstAvdtpSink *sink, - const gchar *transport); - -gchar *gst_avdtp_sink_get_device(GstAvdtpSink *sink); - -gchar *gst_avdtp_sink_get_transport(GstAvdtpSink *sink); - -gboolean gst_avdtp_sink_plugin_init(GstPlugin *plugin); - -void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc); - -void gst_avdtp_sink_set_channel_mode(GstAvdtpSink *self, - const gchar *mode); - - -G_END_DECLS - -#endif /* __GST_AVDTP_SINK_H */ diff --git a/audio/gstbluetooth.c b/audio/gstbluetooth.c deleted file mode 100644 index 99308206a..000000000 --- a/audio/gstbluetooth.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include - -#include "gstsbcutil.h" -#include - -#include "gstsbcenc.h" -#include "gstsbcdec.h" -#include "gstsbcparse.h" -#include "gstavdtpsink.h" -#include "gsta2dpsink.h" -#include "gstrtpsbcpay.h" - -static GstStaticCaps sbc_caps = GST_STATIC_CAPS("audio/x-sbc"); - -#define SBC_CAPS (gst_static_caps_get(&sbc_caps)) - -static void sbc_typefind(GstTypeFind *tf, gpointer ignore) -{ - GstCaps *caps; - guint8 *aux; - sbc_t sbc; - guint8 *data = gst_type_find_peek(tf, 0, 32); - - if (data == NULL) - return; - - if (sbc_init(&sbc, 0) < 0) - return; - - aux = g_new(guint8, 32); - memcpy(aux, data, 32); - if (sbc_parse(&sbc, aux, 32) < 0) - goto done; - - caps = gst_sbc_parse_caps_from_sbc(&sbc); - gst_type_find_suggest(tf, GST_TYPE_FIND_POSSIBLE, caps); - gst_caps_unref(caps); - -done: - g_free(aux); - sbc_finish(&sbc); -} - -static gchar *sbc_exts[] = { "sbc", NULL }; - -static gboolean plugin_init(GstPlugin *plugin) -{ - GST_INFO("Bluetooth plugin %s", VERSION); - - if (gst_type_find_register(plugin, "sbc", - GST_RANK_PRIMARY, sbc_typefind, sbc_exts, - SBC_CAPS, NULL, NULL) == FALSE) - return FALSE; - - if (!gst_sbc_enc_plugin_init(plugin)) - return FALSE; - - if (!gst_sbc_dec_plugin_init(plugin)) - return FALSE; - - if (!gst_sbc_parse_plugin_init(plugin)) - return FALSE; - - if (!gst_avdtp_sink_plugin_init(plugin)) - return FALSE; - - if (!gst_a2dp_sink_plugin_init(plugin)) - return FALSE; - - if (!gst_rtp_sbc_pay_plugin_init(plugin)) - return FALSE; - - return TRUE; -} - -extern GstPluginDesc gst_plugin_desc __attribute__ ((visibility("default"))); - -GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, - "bluetooth", "Bluetooth plugin library", - plugin_init, VERSION, "LGPL", "BlueZ", "http://www.bluez.org/") diff --git a/audio/gstpragma.h b/audio/gstpragma.h deleted file mode 100644 index 0cb08d277..000000000 --- a/audio/gstpragma.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* #pragma GCC diagnostic warning "-Wmissing-declarations" */ diff --git a/audio/gstrtpsbcpay.c b/audio/gstrtpsbcpay.c deleted file mode 100644 index 11aa733b0..000000000 --- a/audio/gstrtpsbcpay.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "gstpragma.h" -#include "gstrtpsbcpay.h" -#include -#include - -#define RTP_SBC_PAYLOAD_HEADER_SIZE 1 -#define DEFAULT_MIN_FRAMES 0 -#define RTP_SBC_HEADER_TOTAL (12 + RTP_SBC_PAYLOAD_HEADER_SIZE) - -#if __BYTE_ORDER == __LITTLE_ENDIAN - -struct rtp_payload { - guint8 frame_count:4; - guint8 rfa0:1; - guint8 is_last_fragment:1; - guint8 is_first_fragment:1; - guint8 is_fragmented:1; -} __attribute__ ((packed)); - -#elif __BYTE_ORDER == __BIG_ENDIAN - -struct rtp_payload { - guint8 is_fragmented:1; - guint8 is_first_fragment:1; - guint8 is_last_fragment:1; - guint8 rfa0:1; - guint8 frame_count:4; -} __attribute__ ((packed)); - -#else -#error "Unknown byte order" -#endif - -enum { - PROP_0, - PROP_MIN_FRAMES -}; - -GST_DEBUG_CATEGORY_STATIC(gst_rtp_sbc_pay_debug); -#define GST_CAT_DEFAULT gst_rtp_sbc_pay_debug - -GST_BOILERPLATE(GstRtpSBCPay, gst_rtp_sbc_pay, GstBaseRTPPayload, - GST_TYPE_BASE_RTP_PAYLOAD); - -static const GstElementDetails gst_rtp_sbc_pay_details = - GST_ELEMENT_DETAILS("RTP packet payloader", - "Codec/Payloader/Network", - "Payload SBC audio as RTP packets", - "Thiago Sousa Santos " - ""); - -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, " - "rate = (int) { 16000, 32000, 44100, 48000 }, " - "channels = (int) [ 1, 2 ], " - "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, " - "blocks = (int) { 4, 8, 12, 16 }, " - "subbands = (int) { 4, 8 }, " - "allocation = (string) { \"snr\", \"loudness\" }, " - "bitpool = (int) [ 2, 64 ]") - ); - -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, " - "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, - const GValue *value, GParamSpec *pspec); -static void gst_rtp_sbc_pay_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); - -static gint gst_rtp_sbc_pay_get_frame_len(gint subbands, gint channels, - gint blocks, gint bitpool, const gchar *channel_mode) -{ - gint len; - gint join; - - len = 4 + (4 * subbands * channels)/8; - - if (strcmp(channel_mode, "mono") == 0 || - strcmp(channel_mode, "dual") == 0) - len += ((blocks * channels * bitpool) + 7) / 8; - else { - join = strcmp(channel_mode, "joint") == 0 ? 1 : 0; - len += ((join * subbands + blocks * bitpool) + 7) / 8; - } - - return len; -} - -static gboolean gst_rtp_sbc_pay_set_caps(GstBaseRTPPayload *payload, - GstCaps *caps) -{ - GstRtpSBCPay *sbcpay; - gint rate, subbands, channels, blocks, bitpool; - gint frame_len; - const gchar *channel_mode; - GstStructure *structure; - - sbcpay = GST_RTP_SBC_PAY(payload); - - 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 (!gst_structure_get_int(structure, "blocks", &blocks)) - return FALSE; - if (!gst_structure_get_int(structure, "bitpool", &bitpool)) - return FALSE; - if (!gst_structure_get_int(structure, "subbands", &subbands)) - return FALSE; - - channel_mode = gst_structure_get_string(structure, "mode"); - if (!channel_mode) - return FALSE; - - frame_len = gst_rtp_sbc_pay_get_frame_len(subbands, channels, blocks, - bitpool, channel_mode); - - sbcpay->frame_length = frame_len; - - gst_basertppayload_set_options(payload, "audio", TRUE, "SBC", rate); - - GST_DEBUG_OBJECT(payload, "calculated frame length: %d ", frame_len); - - return gst_basertppayload_set_outcaps(payload, NULL); -} - -static GstFlowReturn gst_rtp_sbc_pay_flush_buffers(GstRtpSBCPay *sbcpay) -{ - guint available; - guint max_payload; - GstBuffer *outbuf; - guint8 *payload_data; - guint frame_count; - guint payload_length; - struct rtp_payload *payload; - - if (sbcpay->frame_length == 0) { - GST_ERROR_OBJECT(sbcpay, "Frame length is 0"); - return GST_FLOW_ERROR; - } - - available = gst_adapter_available(sbcpay->adapter); - - max_payload = gst_rtp_buffer_calc_payload_len( - GST_BASE_RTP_PAYLOAD_MTU(sbcpay) - RTP_SBC_PAYLOAD_HEADER_SIZE, - 0, 0); - - max_payload = MIN(max_payload, available); - frame_count = max_payload / sbcpay->frame_length; - payload_length = frame_count * sbcpay->frame_length; - if (payload_length == 0) /* Nothing to send */ - return GST_FLOW_OK; - - outbuf = gst_rtp_buffer_new_allocate(payload_length + - RTP_SBC_PAYLOAD_HEADER_SIZE, 0, 0); - - gst_rtp_buffer_set_payload_type(outbuf, - GST_BASE_RTP_PAYLOAD_PT(sbcpay)); - - payload_data = gst_rtp_buffer_get_payload(outbuf); - payload = (struct rtp_payload *) payload_data; - memset(payload, 0, sizeof(struct rtp_payload)); - payload->frame_count = frame_count; - - gst_adapter_copy(sbcpay->adapter, payload_data + - RTP_SBC_PAYLOAD_HEADER_SIZE, 0, payload_length); - gst_adapter_flush(sbcpay->adapter, payload_length); - - GST_BUFFER_TIMESTAMP(outbuf) = sbcpay->timestamp; - GST_DEBUG_OBJECT(sbcpay, "Pushing %d bytes", payload_length); - - return gst_basertppayload_push(GST_BASE_RTP_PAYLOAD(sbcpay), outbuf); -} - -static GstFlowReturn gst_rtp_sbc_pay_handle_buffer(GstBaseRTPPayload *payload, - GstBuffer *buffer) -{ - GstRtpSBCPay *sbcpay; - guint available; - - /* FIXME check for negotiation */ - - sbcpay = GST_RTP_SBC_PAY(payload); - sbcpay->timestamp = GST_BUFFER_TIMESTAMP(buffer); - - gst_adapter_push(sbcpay->adapter, buffer); - - available = gst_adapter_available(sbcpay->adapter); - if (available + RTP_SBC_HEADER_TOTAL >= - GST_BASE_RTP_PAYLOAD_MTU(sbcpay) || - (available > - (sbcpay->min_frames * sbcpay->frame_length))) - return gst_rtp_sbc_pay_flush_buffers(sbcpay); - - return GST_FLOW_OK; -} - -static gboolean gst_rtp_sbc_pay_handle_event(GstPad *pad, - GstEvent *event) -{ - GstRtpSBCPay *sbcpay = GST_RTP_SBC_PAY(GST_PAD_PARENT(pad)); - - switch (GST_EVENT_TYPE(event)) { - case GST_EVENT_EOS: - gst_rtp_sbc_pay_flush_buffers(sbcpay); - break; - default: - break; - } - - return FALSE; -} - -static void gst_rtp_sbc_pay_base_init(gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&gst_rtp_sbc_pay_sink_factory)); - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&gst_rtp_sbc_pay_src_factory)); - - gst_element_class_set_details(element_class, &gst_rtp_sbc_pay_details); -} - -static void gst_rtp_sbc_pay_finalize(GObject *object) -{ - GstRtpSBCPay *sbcpay = GST_RTP_SBC_PAY(object); - g_object_unref(sbcpay->adapter); - - GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); -} - -static void gst_rtp_sbc_pay_class_init(GstRtpSBCPayClass *klass) -{ - GObjectClass *gobject_class; - GstBaseRTPPayloadClass *payload_class = - GST_BASE_RTP_PAYLOAD_CLASS(klass); - - gobject_class = G_OBJECT_CLASS(klass); - parent_class = g_type_class_peek_parent(klass); - - gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_rtp_sbc_pay_finalize); - gobject_class->set_property = GST_DEBUG_FUNCPTR( - gst_rtp_sbc_pay_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR( - gst_rtp_sbc_pay_get_property); - - payload_class->set_caps = GST_DEBUG_FUNCPTR(gst_rtp_sbc_pay_set_caps); - payload_class->handle_buffer = GST_DEBUG_FUNCPTR( - gst_rtp_sbc_pay_handle_buffer); - payload_class->handle_event = GST_DEBUG_FUNCPTR( - gst_rtp_sbc_pay_handle_event); - - /* properties */ - g_object_class_install_property(G_OBJECT_CLASS(klass), - PROP_MIN_FRAMES, - g_param_spec_int("min-frames", "minimum frame number", - "Minimum quantity of frames to send in one packet " - "(-1 for maximum allowed by the mtu)", - -1, G_MAXINT, DEFAULT_MIN_FRAMES, G_PARAM_READWRITE)); - - GST_DEBUG_CATEGORY_INIT(gst_rtp_sbc_pay_debug, "rtpsbcpay", 0, - "RTP SBC payloader"); -} - -static void gst_rtp_sbc_pay_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GstRtpSBCPay *sbcpay; - - sbcpay = GST_RTP_SBC_PAY(object); - - switch (prop_id) { - case PROP_MIN_FRAMES: - sbcpay->min_frames = g_value_get_int(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void gst_rtp_sbc_pay_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GstRtpSBCPay *sbcpay; - - sbcpay = GST_RTP_SBC_PAY(object); - - switch (prop_id) { - case PROP_MIN_FRAMES: - g_value_set_int(value, sbcpay->min_frames); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void gst_rtp_sbc_pay_init(GstRtpSBCPay *self, GstRtpSBCPayClass *klass) -{ - self->adapter = gst_adapter_new(); - self->frame_length = 0; - self->timestamp = 0; - - self->min_frames = DEFAULT_MIN_FRAMES; -} - -gboolean gst_rtp_sbc_pay_plugin_init(GstPlugin *plugin) -{ - return gst_element_register(plugin, "rtpsbcpay", GST_RANK_NONE, - GST_TYPE_RTP_SBC_PAY); -} diff --git a/audio/gstrtpsbcpay.h b/audio/gstrtpsbcpay.h deleted file mode 100644 index 398de82e4..000000000 --- a/audio/gstrtpsbcpay.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_RTP_SBC_PAY \ - (gst_rtp_sbc_pay_get_type()) -#define GST_RTP_SBC_PAY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SBC_PAY,\ - GstRtpSBCPay)) -#define GST_RTP_SBC_PAY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SBC_PAY,\ - GstRtpSBCPayClass)) -#define GST_IS_RTP_SBC_PAY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SBC_PAY)) -#define GST_IS_RTP_SBC_PAY_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SBC_PAY)) - -typedef struct _GstRtpSBCPay GstRtpSBCPay; -typedef struct _GstRtpSBCPayClass GstRtpSBCPayClass; - -struct _GstRtpSBCPay { - GstBaseRTPPayload base; - - GstAdapter *adapter; - GstClockTime timestamp; - - guint frame_length; - - guint min_frames; -}; - -struct _GstRtpSBCPayClass { - GstBaseRTPPayloadClass parent_class; -}; - -GType gst_rtp_sbc_pay_get_type(void); - -gboolean gst_rtp_sbc_pay_plugin_init (GstPlugin * plugin); - -G_END_DECLS diff --git a/audio/gstsbcdec.c b/audio/gstsbcdec.c deleted file mode 100644 index c52834e34..000000000 --- a/audio/gstsbcdec.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "gstpragma.h" -#include "gstsbcutil.h" -#include "gstsbcdec.h" - -GST_DEBUG_CATEGORY_STATIC(sbc_dec_debug); -#define GST_CAT_DEFAULT sbc_dec_debug - -GST_BOILERPLATE(GstSbcDec, gst_sbc_dec, GstElement, GST_TYPE_ELEMENT); - -static const GstElementDetails sbc_dec_details = - GST_ELEMENT_DETAILS("Bluetooth SBC decoder", - "Codec/Decoder/Audio", - "Decode a SBC audio stream", - "Marcel Holtmann "); - -static GstStaticPadTemplate sbc_dec_sink_factory = - GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS("audio/x-sbc")); - -static GstStaticPadTemplate sbc_dec_src_factory = - GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS("audio/x-raw-int, " - "rate = (int) { 16000, 32000, 44100, 48000 }, " - "channels = (int) [ 1, 2 ], " - "endianness = (int) BYTE_ORDER, " - "signed = (boolean) true, " - "width = (int) 16, " - "depth = (int) 16")); - -static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer) -{ - GstSbcDec *dec = GST_SBC_DEC(gst_pad_get_parent(pad)); - GstFlowReturn res = GST_FLOW_OK; - guint size, codesize, offset = 0; - guint8 *data; - - codesize = sbc_get_codesize(&dec->sbc); - - if (dec->buffer) { - GstBuffer *temp = buffer; - buffer = gst_buffer_span(dec->buffer, 0, buffer, - GST_BUFFER_SIZE(dec->buffer) + GST_BUFFER_SIZE(buffer)); - gst_buffer_unref(temp); - gst_buffer_unref(dec->buffer); - dec->buffer = NULL; - } - - data = GST_BUFFER_DATA(buffer); - size = GST_BUFFER_SIZE(buffer); - - while (offset < size) { - GstBuffer *output; - GstPadTemplate *template; - GstCaps *caps; - int consumed; - - res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad, - GST_BUFFER_OFFSET_NONE, - codesize, NULL, &output); - - if (res != GST_FLOW_OK) - goto done; - - consumed = sbc_decode(&dec->sbc, data + offset, size - offset, - GST_BUFFER_DATA(output), codesize, - NULL); - if (consumed <= 0) - break; - - /* we will reuse the same caps object */ - if (dec->outcaps == NULL) { - caps = gst_caps_new_simple("audio/x-raw-int", - "rate", G_TYPE_INT, - gst_sbc_parse_rate_from_sbc( - dec->sbc.frequency), - "channels", G_TYPE_INT, - gst_sbc_get_channel_number( - dec->sbc.mode), - 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) - goto done; - - offset += consumed; - } - - if (offset < size) - dec->buffer = gst_buffer_create_sub(buffer, - offset, size - offset); - -done: - gst_buffer_unref(buffer); - gst_object_unref(dec); - - return res; -} - -static GstStateChangeReturn sbc_dec_change_state(GstElement *element, - GstStateChange transition) -{ - GstSbcDec *dec = GST_SBC_DEC(element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG("Setup subband codec"); - if (dec->buffer) { - gst_buffer_unref(dec->buffer); - dec->buffer = NULL; - } - sbc_init(&dec->sbc, 0); - dec->outcaps = NULL; - break; - - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG("Finish subband codec"); - if (dec->buffer) { - gst_buffer_unref(dec->buffer); - dec->buffer = NULL; - } - sbc_finish(&dec->sbc); - if (dec->outcaps) { - gst_caps_unref(dec->outcaps); - dec->outcaps = NULL; - } - break; - - default: - break; - } - - return parent_class->change_state(element, transition); -} - -static void gst_sbc_dec_base_init(gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_dec_sink_factory)); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_dec_src_factory)); - - gst_element_class_set_details(element_class, &sbc_dec_details); -} - -static void gst_sbc_dec_class_init(GstSbcDecClass *klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - element_class->change_state = GST_DEBUG_FUNCPTR(sbc_dec_change_state); - - GST_DEBUG_CATEGORY_INIT(sbc_dec_debug, "sbcdec", 0, - "SBC decoding element"); -} - -static void gst_sbc_dec_init(GstSbcDec *self, GstSbcDecClass *klass) -{ - self->sinkpad = gst_pad_new_from_static_template( - &sbc_dec_sink_factory, "sink"); - gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR( - sbc_dec_chain)); - gst_element_add_pad(GST_ELEMENT(self), self->sinkpad); - - 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) -{ - return gst_element_register(plugin, "sbcdec", GST_RANK_PRIMARY, - GST_TYPE_SBC_DEC); -} diff --git a/audio/gstsbcdec.h b/audio/gstsbcdec.h deleted file mode 100644 index c77feaed3..000000000 --- a/audio/gstsbcdec.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -#include "sbc.h" - -G_BEGIN_DECLS - -#define GST_TYPE_SBC_DEC \ - (gst_sbc_dec_get_type()) -#define GST_SBC_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SBC_DEC,GstSbcDec)) -#define GST_SBC_DEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SBC_DEC,GstSbcDecClass)) -#define GST_IS_SBC_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SBC_DEC)) -#define GST_IS_SBC_DEC_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SBC_DEC)) - -typedef struct _GstSbcDec GstSbcDec; -typedef struct _GstSbcDecClass GstSbcDecClass; - -struct _GstSbcDec { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - GstBuffer *buffer; - - /* caps for outgoing buffers */ - GstCaps *outcaps; - - sbc_t sbc; -}; - -struct _GstSbcDecClass { - GstElementClass parent_class; -}; - -GType gst_sbc_dec_get_type(void); - -gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin); - -G_END_DECLS diff --git a/audio/gstsbcenc.c b/audio/gstsbcenc.c deleted file mode 100644 index 894837145..000000000 --- a/audio/gstsbcenc.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "gstpragma.h" -#include "gstsbcutil.h" -#include "gstsbcenc.h" - -#define SBC_ENC_DEFAULT_MODE SBC_MODE_AUTO -#define SBC_ENC_DEFAULT_BLOCKS 0 -#define SBC_ENC_DEFAULT_SUB_BANDS 0 -#define SBC_ENC_DEFAULT_ALLOCATION SBC_AM_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 - -#define GST_TYPE_SBC_MODE (gst_sbc_mode_get_type()) - -static GType gst_sbc_mode_get_type(void) -{ - static GType sbc_mode_type = 0; - static GEnumValue sbc_modes[] = { - { SBC_MODE_MONO, "Mono", "mono" }, - { SBC_MODE_DUAL_CHANNEL, "Dual Channel", "dual" }, - { SBC_MODE_STEREO, "Stereo", "stereo"}, - { SBC_MODE_JOINT_STEREO, "Joint Stereo", "joint" }, - { SBC_MODE_AUTO, "Auto", "auto" }, - { -1, NULL, NULL} - }; - - if (!sbc_mode_type) - sbc_mode_type = g_enum_register_static("GstSbcMode", sbc_modes); - - return sbc_mode_type; -} - -#define GST_TYPE_SBC_ALLOCATION (gst_sbc_allocation_get_type()) - -static GType gst_sbc_allocation_get_type(void) -{ - static GType sbc_allocation_type = 0; - static GEnumValue sbc_allocations[] = { - { SBC_AM_LOUDNESS, "Loudness", "loudness" }, - { SBC_AM_SNR, "SNR", "snr" }, - { SBC_AM_AUTO, "Auto", "auto" }, - { -1, NULL, NULL} - }; - - if (!sbc_allocation_type) - sbc_allocation_type = g_enum_register_static( - "GstSbcAllocation", sbc_allocations); - - 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_BITPOOL -}; - -GST_BOILERPLATE(GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); - -static const GstElementDetails sbc_enc_details = - GST_ELEMENT_DETAILS("Bluetooth SBC encoder", - "Codec/Encoder/Audio", - "Encode a SBC audio stream", - "Marcel Holtmann "); - -static GstStaticPadTemplate sbc_enc_sink_factory = - GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS("audio/x-raw-int, " - "rate = (int) { 16000, 32000, 44100, 48000 }, " - "channels = (int) [ 1, 2 ], " - "endianness = (int) BYTE_ORDER, " - "signed = (boolean) true, " - "width = (int) 16, " - "depth = (int) 16")); - -static GstStaticPadTemplate sbc_enc_src_factory = - GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS("audio/x-sbc, " - "rate = (int) { 16000, 32000, 44100, 48000 }, " - "channels = (int) [ 1, 2 ], " - "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, " - "blocks = (int) { 4, 8, 12, 16 }, " - "subbands = (int) { 4, 8 }, " - "allocation = (string) { \"snr\", \"loudness\" }, " - "bitpool = (int) [ " SBC_ENC_BITPOOL_MIN_STR - ", " SBC_ENC_BITPOOL_MAX_STR " ]")); - -gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps); - -static GstCaps *sbc_enc_generate_srcpad_caps(GstSbcEnc *enc) -{ - GstCaps *src_caps; - GstStructure *structure; - GEnumValue *enum_value; - GEnumClass *enum_class; - GValue *value; - - src_caps = gst_caps_copy(gst_pad_get_pad_template_caps(enc->srcpad)); - structure = gst_caps_get_structure(src_caps, 0); - - value = g_new0(GValue, 1); - - if (enc->rate != 0) - gst_sbc_util_set_structure_int_param(structure, "rate", - enc->rate, value); - - if (enc->channels != 0) - gst_sbc_util_set_structure_int_param(structure, "channels", - enc->channels, value); - - if (enc->subbands != 0) - gst_sbc_util_set_structure_int_param(structure, "subbands", - enc->subbands, value); - - if (enc->blocks != 0) - 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 != SBC_ENC_DEFAULT_MODE) { - enum_class = g_type_class_ref(GST_TYPE_SBC_MODE); - enum_value = g_enum_get_value(enum_class, enc->mode); - gst_sbc_util_set_structure_string_param(structure, "mode", - enum_value->value_nick, value); - g_type_class_unref(enum_class); - } - - if (enc->allocation != SBC_AM_AUTO) { - enum_class = g_type_class_ref(GST_TYPE_SBC_ALLOCATION); - enum_value = g_enum_get_value(enum_class, enc->allocation); - gst_sbc_util_set_structure_string_param(structure, "allocation", - enum_value->value_nick, value); - g_type_class_unref(enum_class); - } - - g_free(value); - - return src_caps; -} - -static GstCaps *sbc_enc_src_getcaps(GstPad *pad) -{ - GstSbcEnc *enc; - - enc = GST_SBC_ENC(GST_PAD_PARENT(pad)); - - return sbc_enc_generate_srcpad_caps(enc); -} - -static gboolean sbc_enc_src_setcaps(GstPad *pad, GstCaps *caps) -{ - GstSbcEnc *enc = GST_SBC_ENC(GST_PAD_PARENT(pad)); - - GST_LOG_OBJECT(enc, "setting srcpad caps"); - - return gst_sbc_enc_fill_sbc_params(enc, caps); -} - -static GstCaps *sbc_enc_src_caps_fixate(GstSbcEnc *enc, GstCaps *caps) -{ - gchar *error_message = NULL; - GstCaps *result; - - result = gst_sbc_util_caps_fixate(caps, &error_message); - - if (!result) { - GST_WARNING_OBJECT(enc, "Invalid input caps caused parsing " - "error: %s", error_message); - g_free(error_message); - return NULL; - } - - return result; -} - -static GstCaps *sbc_enc_get_fixed_srcpad_caps(GstSbcEnc *enc) -{ - GstCaps *caps; - gboolean res = TRUE; - GstCaps *result_caps = NULL; - - 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; - goto done; - } - - result_caps = sbc_enc_src_caps_fixate(enc, caps); - -done: - gst_caps_unref(caps); - - if (!res) - return NULL; - - return result_caps; -} - -static gboolean sbc_enc_sink_setcaps(GstPad *pad, GstCaps *caps) -{ - GstSbcEnc *enc; - GstStructure *structure; - GstCaps *src_caps; - gint rate, channels; - gboolean res; - - enc = GST_SBC_ENC(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; - - enc->rate = rate; - enc->channels = channels; - - src_caps = sbc_enc_get_fixed_srcpad_caps(enc); - if (!src_caps) - return FALSE; - res = gst_pad_set_caps(enc->srcpad, src_caps); - gst_caps_unref(src_caps); - - return res; -} - -gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps) -{ - 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; - - if (enc->rate != 0 && gst_sbc_parse_rate_from_sbc(enc->sbc.frequency) - != enc->rate) - goto fail; - - if (enc->channels != 0 && gst_sbc_get_channel_number(enc->sbc.mode) - != enc->channels) - goto fail; - - if (enc->blocks != 0 && gst_sbc_parse_blocks_from_sbc(enc->sbc.blocks) - != enc->blocks) - goto fail; - - if (enc->subbands != 0 && gst_sbc_parse_subbands_from_sbc( - enc->sbc.subbands) != enc->subbands) - goto fail; - - if (enc->mode != SBC_ENC_DEFAULT_MODE && enc->sbc.mode != enc->mode) - goto fail; - - if (enc->allocation != SBC_AM_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_OBJECT(enc, "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) -{ - GstSbcEnc *enc = GST_SBC_ENC(gst_pad_get_parent(pad)); - GstAdapter *adapter = enc->adapter; - GstFlowReturn res = GST_FLOW_OK; - - gst_adapter_push(adapter, buffer); - - while (gst_adapter_available(adapter) >= enc->codesize && - res == GST_FLOW_OK) { - GstBuffer *output; - GstCaps *caps; - const guint8 *data; - gint consumed; - - caps = GST_PAD_CAPS(enc->srcpad); - res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad, - GST_BUFFER_OFFSET_NONE, - enc->frame_length, caps, - &output); - if (res != GST_FLOW_OK) - goto done; - - data = gst_adapter_peek(adapter, enc->codesize); - - consumed = sbc_encode(&enc->sbc, (gpointer) data, - enc->codesize, - GST_BUFFER_DATA(output), - GST_BUFFER_SIZE(output), NULL); - if (consumed <= 0) { - GST_DEBUG_OBJECT(enc, "comsumed < 0, codesize: %d", - enc->codesize); - break; - } - gst_adapter_flush(adapter, consumed); - - GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer); - /* we have only 1 frame */ - GST_BUFFER_DURATION(output) = enc->frame_duration; - - res = gst_pad_push(enc->srcpad, output); - - if (res != GST_FLOW_OK) - goto done; - } - -done: - gst_object_unref(enc); - - return res; -} - -static GstStateChangeReturn sbc_enc_change_state(GstElement *element, - GstStateChange transition) -{ - GstSbcEnc *enc = GST_SBC_ENC(element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG("Setup subband codec"); - sbc_init(&enc->sbc, 0); - break; - - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG("Finish subband codec"); - sbc_finish(&enc->sbc); - break; - - default: - break; - } - - return parent_class->change_state(element, transition); -} - -static void gst_sbc_enc_dispose(GObject *object) -{ - GstSbcEnc *enc = GST_SBC_ENC(object); - - if (enc->adapter != NULL) - g_object_unref(G_OBJECT(enc->adapter)); - - enc->adapter = NULL; -} - -static void gst_sbc_enc_base_init(gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_enc_sink_factory)); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_enc_src_factory)); - - gst_element_class_set_details(element_class, &sbc_enc_details); -} - -static void gst_sbc_enc_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GstSbcEnc *enc = GST_SBC_ENC(object); - - /* changes to those properties will only happen on the next caps - * negotiation */ - - switch (prop_id) { - case PROP_MODE: - enc->mode = g_value_get_enum(value); - break; - case PROP_ALLOCATION: - enc->allocation = g_value_get_enum(value); - break; - case PROP_BLOCKS: - enc->blocks = g_value_get_enum(value); - break; - case PROP_SUBBANDS: - 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); - break; - } -} - -static void gst_sbc_enc_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GstSbcEnc *enc = GST_SBC_ENC(object); - - switch (prop_id) { - case PROP_MODE: - g_value_set_enum(value, enc->mode); - break; - case PROP_ALLOCATION: - g_value_set_enum(value, enc->allocation); - break; - case PROP_BLOCKS: - g_value_set_enum(value, enc->blocks); - break; - case PROP_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); - break; - } -} - -static void gst_sbc_enc_class_init(GstSbcEncClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GstElementClass *element_class = GST_ELEMENT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - object_class->set_property = GST_DEBUG_FUNCPTR(gst_sbc_enc_set_property); - object_class->get_property = GST_DEBUG_FUNCPTR(gst_sbc_enc_get_property); - object_class->dispose = GST_DEBUG_FUNCPTR(gst_sbc_enc_dispose); - - element_class->change_state = GST_DEBUG_FUNCPTR(sbc_enc_change_state); - - g_object_class_install_property(object_class, PROP_MODE, - g_param_spec_enum("mode", "Mode", - "Encoding mode", GST_TYPE_SBC_MODE, - SBC_ENC_DEFAULT_MODE, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_ALLOCATION, - g_param_spec_enum("allocation", "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_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_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"); -} - -static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass) -{ - self->sinkpad = gst_pad_new_from_static_template( - &sbc_enc_sink_factory, "sink"); - gst_pad_set_setcaps_function(self->sinkpad, - GST_DEBUG_FUNCPTR(sbc_enc_sink_setcaps)); - gst_element_add_pad(GST_ELEMENT(self), self->sinkpad); - - self->srcpad = gst_pad_new_from_static_template( - &sbc_enc_src_factory, "src"); - gst_pad_set_getcaps_function(self->srcpad, - GST_DEBUG_FUNCPTR(sbc_enc_src_getcaps)); - gst_pad_set_setcaps_function(self->srcpad, - GST_DEBUG_FUNCPTR(sbc_enc_src_setcaps)); - gst_element_add_pad(GST_ELEMENT(self), self->srcpad); - - gst_pad_set_chain_function(self->sinkpad, - GST_DEBUG_FUNCPTR(sbc_enc_chain)); - - self->subbands = SBC_ENC_DEFAULT_SUB_BANDS; - self->blocks = SBC_ENC_DEFAULT_BLOCKS; - self->mode = SBC_ENC_DEFAULT_MODE; - 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; - - self->adapter = gst_adapter_new(); -} - -gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin) -{ - return gst_element_register(plugin, "sbcenc", - GST_RANK_NONE, GST_TYPE_SBC_ENC); -} diff --git a/audio/gstsbcenc.h b/audio/gstsbcenc.h deleted file mode 100644 index 0329351fa..000000000 --- a/audio/gstsbcenc.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include -#include - -#include "sbc.h" - -G_BEGIN_DECLS - -#define GST_TYPE_SBC_ENC \ - (gst_sbc_enc_get_type()) -#define GST_SBC_ENC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SBC_ENC,GstSbcEnc)) -#define GST_SBC_ENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SBC_ENC,GstSbcEncClass)) -#define GST_IS_SBC_ENC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SBC_ENC)) -#define GST_IS_SBC_ENC_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SBC_ENC)) - -typedef struct _GstSbcEnc GstSbcEnc; -typedef struct _GstSbcEncClass GstSbcEncClass; - -struct _GstSbcEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - GstAdapter *adapter; - - gint rate; - gint channels; - gint mode; - gint blocks; - gint allocation; - gint subbands; - gint bitpool; - - guint codesize; - gint frame_length; - gint frame_duration; - - sbc_t sbc; -}; - -struct _GstSbcEncClass { - GstElementClass parent_class; -}; - -GType gst_sbc_enc_get_type(void); - -gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin); - -G_END_DECLS diff --git a/audio/gstsbcparse.c b/audio/gstsbcparse.c deleted file mode 100644 index bc4c0c7c6..000000000 --- a/audio/gstsbcparse.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "gstpragma.h" -#include "gstsbcutil.h" -#include "gstsbcparse.h" - -GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug); -#define GST_CAT_DEFAULT sbc_parse_debug - -GST_BOILERPLATE(GstSbcParse, gst_sbc_parse, GstElement, GST_TYPE_ELEMENT); - -static const GstElementDetails sbc_parse_details = - GST_ELEMENT_DETAILS("Bluetooth SBC parser", - "Codec/Parser/Audio", - "Parse a SBC audio stream", - "Marcel Holtmann "); - -static GstStaticPadTemplate sbc_parse_sink_factory = - GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - 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, - GST_STATIC_CAPS("audio/x-sbc, " - "rate = (int) { 16000, 32000, 44100, 48000 }, " - "channels = (int) [ 1, 2 ], " - "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, " - "blocks = (int) { 4, 8, 12, 16 }, " - "subbands = (int) { 4, 8 }, " - "allocation = (string) { \"snr\", \"loudness\" }," - "bitpool = (int) [ 2, 64 ]," - "parsed = (boolean) true")); - -static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer) -{ - GstSbcParse *parse = GST_SBC_PARSE(gst_pad_get_parent(pad)); - GstFlowReturn res = GST_FLOW_OK; - guint size, offset = 0; - guint8 *data; - - /* FIXME use a gstadpter */ - if (parse->buffer) { - GstBuffer *temp; - temp = buffer; - buffer = gst_buffer_span(parse->buffer, 0, buffer, - GST_BUFFER_SIZE(parse->buffer) - + GST_BUFFER_SIZE(buffer)); - gst_buffer_unref(parse->buffer); - gst_buffer_unref(temp); - parse->buffer = NULL; - } - - data = GST_BUFFER_DATA(buffer); - size = GST_BUFFER_SIZE(buffer); - - while (offset < size) { - GstBuffer *output; - int consumed; - - consumed = sbc_parse(&parse->new_sbc, data + offset, - size - offset); - if (consumed <= 0) - break; - - if (parse->first_parsing || (memcmp(&parse->sbc, - &parse->new_sbc, sizeof(sbc_t)) != 0)) { - - memcpy(&parse->sbc, &parse->new_sbc, sizeof(sbc_t)); - if (parse->outcaps != NULL) - gst_caps_unref(parse->outcaps); - - parse->outcaps = gst_sbc_parse_caps_from_sbc( - &parse->sbc); - - parse->first_parsing = FALSE; - } - - res = gst_pad_alloc_buffer_and_set_caps(parse->srcpad, - GST_BUFFER_OFFSET_NONE, - consumed, parse->outcaps, &output); - - if (res != GST_FLOW_OK) - goto done; - - memcpy(GST_BUFFER_DATA(output), data + offset, consumed); - - res = gst_pad_push(parse->srcpad, output); - if (res != GST_FLOW_OK) - goto done; - - offset += consumed; - } - - if (offset < size) - parse->buffer = gst_buffer_create_sub(buffer, - offset, size - offset); - -done: - gst_buffer_unref(buffer); - gst_object_unref(parse); - - return res; -} - -static GstStateChangeReturn sbc_parse_change_state(GstElement *element, - GstStateChange transition) -{ - GstSbcParse *parse = GST_SBC_PARSE(element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG("Setup subband codec"); - - parse->channels = -1; - parse->rate = -1; - parse->first_parsing = TRUE; - - sbc_init(&parse->sbc, 0); - break; - - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG("Finish subband codec"); - - if (parse->buffer) { - gst_buffer_unref(parse->buffer); - parse->buffer = NULL; - } - if (parse->outcaps != NULL) { - gst_caps_unref(parse->outcaps); - parse->outcaps = NULL; - } - - sbc_finish(&parse->sbc); - break; - - default: - break; - } - - return parent_class->change_state(element, transition); -} - -static void gst_sbc_parse_base_init(gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_parse_sink_factory)); - - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_parse_src_factory)); - - gst_element_class_set_details(element_class, &sbc_parse_details); -} - -static void gst_sbc_parse_class_init(GstSbcParseClass *klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - element_class->change_state = GST_DEBUG_FUNCPTR(sbc_parse_change_state); - - GST_DEBUG_CATEGORY_INIT(sbc_parse_debug, "sbcparse", 0, - "SBC parsing element"); -} - -static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass) -{ - self->sinkpad = gst_pad_new_from_static_template( - &sbc_parse_sink_factory, "sink"); - gst_pad_set_chain_function(self->sinkpad, - GST_DEBUG_FUNCPTR(sbc_parse_chain)); - gst_element_add_pad(GST_ELEMENT(self), self->sinkpad); - - self->srcpad = gst_pad_new_from_static_template( - &sbc_parse_src_factory, "src"); - gst_element_add_pad(GST_ELEMENT(self), self->srcpad); - - self->outcaps = NULL; - self->buffer = NULL; - self->channels = -1; - self->rate = -1; - self->first_parsing = TRUE; -} - -gboolean gst_sbc_parse_plugin_init(GstPlugin *plugin) -{ - return gst_element_register(plugin, "sbcparse", GST_RANK_NONE, - GST_TYPE_SBC_PARSE); -} diff --git a/audio/gstsbcparse.h b/audio/gstsbcparse.h deleted file mode 100644 index ecb8be426..000000000 --- a/audio/gstsbcparse.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -#include "sbc.h" - -G_BEGIN_DECLS - -#define GST_TYPE_SBC_PARSE \ - (gst_sbc_parse_get_type()) -#define GST_SBC_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SBC_PARSE,GstSbcParse)) -#define GST_SBC_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SBC_PARSE,GstSbcParseClass)) -#define GST_IS_SBC_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SBC_PARSE)) -#define GST_IS_SBC_PARSE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SBC_PARSE)) - -typedef struct _GstSbcParse GstSbcParse; -typedef struct _GstSbcParseClass GstSbcParseClass; - -struct _GstSbcParse { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - GstBuffer *buffer; - - sbc_t sbc; - sbc_t new_sbc; - GstCaps *outcaps; - gboolean first_parsing; - - gint channels; - gint rate; -}; - -struct _GstSbcParseClass { - GstElementClass parent_class; -}; - -GType gst_sbc_parse_get_type(void); - -gboolean gst_sbc_parse_plugin_init(GstPlugin *plugin); - -G_END_DECLS diff --git a/audio/gstsbcutil.c b/audio/gstsbcutil.c deleted file mode 100644 index f596b410a..000000000 --- a/audio/gstsbcutil.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "gstsbcutil.h" - -/* - * Selects one rate from a list of possible rates - * TODO - use a better approach to this (it is selecting the last element) - */ -gint gst_sbc_select_rate_from_list(const GValue *value) -{ - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); -} - -/* - * Selects one number of channels option from a range of possible numbers - * TODO - use a better approach to this (it is selecting the maximum value) - */ -gint gst_sbc_select_channels_from_range(const GValue *value) -{ - return gst_value_get_int_range_max(value); -} - -/* - * Selects one number of blocks from a list of possible blocks - * TODO - use a better approach to this (it is selecting the last element) - */ -gint gst_sbc_select_blocks_from_list(const GValue *value) -{ - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); -} - -/* - * Selects one number of subbands from a list - * TODO - use a better approach to this (it is selecting the last element) - */ -gint gst_sbc_select_subbands_from_list(const GValue *value) -{ - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); -} - -/* - * Selects one bitpool option from a range - * TODO - use a better approach to this (it is selecting the maximum value) - */ -gint gst_sbc_select_bitpool_from_range(const GValue *value) -{ - return gst_value_get_int_range_max(value); -} - -/* - * Selects one allocation mode from the ones on the list - * TODO - use a better approach - */ -const gchar *gst_sbc_get_allocation_from_list(const GValue *value) -{ - guint size = gst_value_list_get_size(value); - return g_value_get_string(gst_value_list_get_value(value, size-1)); -} - -/* - * Selects one mode from the ones on the list - */ -const gchar *gst_sbc_get_mode_from_list(const GValue *list, gint channels) -{ - unsigned int i; - const GValue *value; - const gchar *aux; - gboolean joint, stereo, dual, mono; - guint size = gst_value_list_get_size(list); - - joint = stereo = dual = mono = FALSE; - - for (i = 0; i < size; i++) { - value = gst_value_list_get_value(list, i); - aux = g_value_get_string(value); - if (strcmp("joint", aux) == 0) - joint = TRUE; - else if (strcmp("stereo", aux) == 0) - stereo = TRUE; - else if (strcmp("dual", aux) == 0) - dual = TRUE; - else if (strcmp("mono", aux) == 0) - mono = TRUE; - } - - if (channels == 1 && mono) - return "mono"; - else if (channels == 2) { - if (joint) - return "joint"; - else if (stereo) - return "stereo"; - else if (dual) - return "dual"; - } - - return NULL; -} - -gint gst_sbc_parse_rate_from_sbc(gint frequency) -{ - switch (frequency) { - case SBC_FREQ_16000: - return 16000; - case SBC_FREQ_32000: - return 32000; - case SBC_FREQ_44100: - return 44100; - case SBC_FREQ_48000: - return 48000; - default: - return 0; - } -} - -gint gst_sbc_parse_rate_to_sbc(gint rate) -{ - switch (rate) { - case 16000: - return SBC_FREQ_16000; - case 32000: - return SBC_FREQ_32000; - case 44100: - return SBC_FREQ_44100; - case 48000: - return SBC_FREQ_48000; - default: - return -1; - } -} - -gint gst_sbc_get_channel_number(gint mode) -{ - switch (mode) { - case SBC_MODE_JOINT_STEREO: - case SBC_MODE_STEREO: - case SBC_MODE_DUAL_CHANNEL: - return 2; - case SBC_MODE_MONO: - return 1; - default: - return 0; - } -} - -gint gst_sbc_parse_subbands_from_sbc(gint subbands) -{ - switch (subbands) { - case SBC_SB_4: - return 4; - case SBC_SB_8: - return 8; - default: - return 0; - } -} - -gint gst_sbc_parse_subbands_to_sbc(gint subbands) -{ - switch (subbands) { - case 4: - return SBC_SB_4; - case 8: - return SBC_SB_8; - default: - return -1; - } -} - -gint gst_sbc_parse_blocks_from_sbc(gint blocks) -{ - switch (blocks) { - case SBC_BLK_4: - return 4; - case SBC_BLK_8: - return 8; - case SBC_BLK_12: - return 12; - case SBC_BLK_16: - return 16; - default: - return 0; - } -} - -gint gst_sbc_parse_blocks_to_sbc(gint blocks) -{ - switch (blocks) { - case 4: - return SBC_BLK_4; - case 8: - return SBC_BLK_8; - case 12: - return SBC_BLK_12; - case 16: - return SBC_BLK_16; - default: - return -1; - } -} - -const gchar *gst_sbc_parse_mode_from_sbc(gint mode) -{ - switch (mode) { - case SBC_MODE_MONO: - return "mono"; - case SBC_MODE_DUAL_CHANNEL: - return "dual"; - case SBC_MODE_STEREO: - return "stereo"; - case SBC_MODE_JOINT_STEREO: - case SBC_MODE_AUTO: - return "joint"; - default: - return NULL; - } -} - -gint gst_sbc_parse_mode_to_sbc(const gchar *mode) -{ - if (g_ascii_strcasecmp(mode, "joint") == 0) - return SBC_MODE_JOINT_STEREO; - else if (g_ascii_strcasecmp(mode, "stereo") == 0) - return SBC_MODE_STEREO; - else if (g_ascii_strcasecmp(mode, "dual") == 0) - return SBC_MODE_DUAL_CHANNEL; - else if (g_ascii_strcasecmp(mode, "mono") == 0) - return SBC_MODE_MONO; - else if (g_ascii_strcasecmp(mode, "auto") == 0) - return SBC_MODE_JOINT_STEREO; - else - return -1; -} - -const gchar *gst_sbc_parse_allocation_from_sbc(gint alloc) -{ - switch (alloc) { - case SBC_AM_LOUDNESS: - return "loudness"; - case SBC_AM_SNR: - return "snr"; - case SBC_AM_AUTO: - return "loudness"; - default: - return NULL; - } -} - -gint gst_sbc_parse_allocation_to_sbc(const gchar *allocation) -{ - if (g_ascii_strcasecmp(allocation, "loudness") == 0) - return SBC_AM_LOUDNESS; - else if (g_ascii_strcasecmp(allocation, "snr") == 0) - return SBC_AM_SNR; - else - return SBC_AM_LOUDNESS; -} - -GstCaps *gst_sbc_parse_caps_from_sbc(sbc_t *sbc) -{ - GstCaps *caps; - const gchar *mode_str; - const gchar *allocation_str; - - mode_str = gst_sbc_parse_mode_from_sbc(sbc->mode); - allocation_str = gst_sbc_parse_allocation_from_sbc(sbc->allocation); - caps = gst_caps_new_simple("audio/x-sbc", - "rate", G_TYPE_INT, - gst_sbc_parse_rate_from_sbc(sbc->frequency), - "channels", G_TYPE_INT, - gst_sbc_get_channel_number(sbc->mode), - "mode", G_TYPE_STRING, mode_str, - "subbands", G_TYPE_INT, - gst_sbc_parse_subbands_from_sbc(sbc->subbands), - "blocks", G_TYPE_INT, - gst_sbc_parse_blocks_from_sbc(sbc->blocks), - "allocation", G_TYPE_STRING, allocation_str, - "bitpool", G_TYPE_INT, sbc->bitpool, - NULL); - - return caps; -} - -/* - * Given a GstCaps, this will return a fixed GstCaps on successful conversion. - * If an error occurs, it will return NULL and error_message will contain the - * error message. - * - * error_message must be passed NULL, if an error occurs, the caller has the - * ownership of the error_message, it must be freed after use. - */ -GstCaps *gst_sbc_util_caps_fixate(GstCaps *caps, gchar **error_message) -{ - GstCaps *result; - GstStructure *structure; - const GValue *value; - gboolean error = FALSE; - gint temp, rate, channels, blocks, subbands, bitpool; - const gchar *allocation = NULL; - const gchar *mode = NULL; - - g_assert(*error_message == NULL); - - structure = gst_caps_get_structure(caps, 0); - - if (!gst_structure_has_field(structure, "rate")) { - error = TRUE; - *error_message = g_strdup("no rate"); - goto error; - } else { - value = gst_structure_get_value(structure, "rate"); - if (GST_VALUE_HOLDS_LIST(value)) - temp = gst_sbc_select_rate_from_list(value); - else - temp = g_value_get_int(value); - rate = temp; - } - - if (!gst_structure_has_field(structure, "channels")) { - error = TRUE; - *error_message = g_strdup("no channels"); - goto error; - } else { - value = gst_structure_get_value(structure, "channels"); - if (GST_VALUE_HOLDS_INT_RANGE(value)) - temp = gst_sbc_select_channels_from_range(value); - else - temp = g_value_get_int(value); - channels = temp; - } - - if (!gst_structure_has_field(structure, "blocks")) { - error = TRUE; - *error_message = g_strdup("no blocks."); - goto error; - } else { - value = gst_structure_get_value(structure, "blocks"); - if (GST_VALUE_HOLDS_LIST(value)) - temp = gst_sbc_select_blocks_from_list(value); - else - temp = g_value_get_int(value); - blocks = temp; - } - - if (!gst_structure_has_field(structure, "subbands")) { - error = TRUE; - *error_message = g_strdup("no subbands"); - goto error; - } else { - value = gst_structure_get_value(structure, "subbands"); - if (GST_VALUE_HOLDS_LIST(value)) - temp = gst_sbc_select_subbands_from_list(value); - else - temp = g_value_get_int(value); - subbands = temp; - } - - if (!gst_structure_has_field(structure, "bitpool")) { - error = TRUE; - *error_message = g_strdup("no bitpool"); - goto error; - } else { - value = gst_structure_get_value(structure, "bitpool"); - if (GST_VALUE_HOLDS_INT_RANGE(value)) - temp = gst_sbc_select_bitpool_from_range(value); - else - temp = g_value_get_int(value); - bitpool = temp; - } - - if (!gst_structure_has_field(structure, "allocation")) { - error = TRUE; - *error_message = g_strdup("no allocation"); - goto error; - } else { - value = gst_structure_get_value(structure, "allocation"); - if (GST_VALUE_HOLDS_LIST(value)) - allocation = gst_sbc_get_allocation_from_list(value); - else - allocation = g_value_get_string(value); - } - - if (!gst_structure_has_field(structure, "mode")) { - error = TRUE; - *error_message = g_strdup("no mode"); - goto error; - } else { - value = gst_structure_get_value(structure, "mode"); - if (GST_VALUE_HOLDS_LIST(value)) { - mode = gst_sbc_get_mode_from_list(value, channels); - } else - mode = g_value_get_string(value); - } - - /* perform validation - * if channels is 1, we must have channel mode = mono - * if channels is 2, we can't have channel mode = mono */ - if ( (channels == 1 && (strcmp(mode, "mono") != 0) ) || - ( channels == 2 && ( strcmp(mode, "mono") == 0))) { - *error_message = g_strdup_printf("Invalid combination of " - "channels (%d) and channel mode (%s)", - channels, mode); - error = TRUE; - } - -error: - if (error) - return NULL; - - result = gst_caps_new_simple("audio/x-sbc", - "rate", G_TYPE_INT, rate, - "channels", G_TYPE_INT, channels, - "mode", G_TYPE_STRING, mode, - "blocks", G_TYPE_INT, blocks, - "subbands", G_TYPE_INT, subbands, - "allocation", G_TYPE_STRING, allocation, - "bitpool", G_TYPE_INT, bitpool, - NULL); - - return result; -} - -/** - * Sets the int field_value to the param "field" on the structure. - * value is used to do the operation, it must be a uninitialized (zero-filled) - * GValue, it will be left unitialized at the end of the function. - */ -void gst_sbc_util_set_structure_int_param(GstStructure *structure, - const gchar *field, gint field_value, - GValue *value) -{ - value = g_value_init(value, G_TYPE_INT); - g_value_set_int(value, field_value); - gst_structure_set_value(structure, field, value); - g_value_unset(value); -} - -/** - * Sets the string field_value to the param "field" on the structure. - * value is used to do the operation, it must be a uninitialized (zero-filled) - * GValue, it will be left unitialized at the end of the function. - */ -void gst_sbc_util_set_structure_string_param(GstStructure *structure, - const gchar *field, const gchar *field_value, - GValue *value) -{ - value = g_value_init(value, G_TYPE_STRING); - g_value_set_string(value, field_value); - gst_structure_set_value(structure, field, value); - g_value_unset(value); -} - -gboolean gst_sbc_util_fill_sbc_params(sbc_t *sbc, GstCaps *caps) -{ - GstStructure *structure; - gint rate, channels, subbands, blocks, bitpool; - const gchar *mode; - const gchar *allocation; - - g_assert(gst_caps_is_fixed(caps)); - - 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 (!gst_structure_get_int(structure, "subbands", &subbands)) - return FALSE; - if (!gst_structure_get_int(structure, "blocks", &blocks)) - return FALSE; - if (!gst_structure_get_int(structure, "bitpool", &bitpool)) - return FALSE; - - if (!(mode = gst_structure_get_string(structure, "mode"))) - return FALSE; - if (!(allocation = gst_structure_get_string(structure, "allocation"))) - return FALSE; - - if (channels == 1 && strcmp(mode, "mono") != 0) - return FALSE; - - sbc->frequency = gst_sbc_parse_rate_to_sbc(rate); - sbc->blocks = gst_sbc_parse_blocks_to_sbc(blocks); - sbc->subbands = gst_sbc_parse_subbands_to_sbc(subbands); - sbc->bitpool = bitpool; - sbc->mode = gst_sbc_parse_mode_to_sbc(mode); - sbc->allocation = gst_sbc_parse_allocation_to_sbc(allocation); - - return TRUE; -} diff --git a/audio/gstsbcutil.h b/audio/gstsbcutil.h deleted file mode 100644 index 962532f78..000000000 --- a/audio/gstsbcutil.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2010 Marcel Holtmann - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -#include "sbc.h" -#include - -#define SBC_AM_AUTO 0x02 -#define SBC_MODE_AUTO 0x04 - -gint gst_sbc_select_rate_from_list(const GValue *value); - -gint gst_sbc_select_channels_from_range(const GValue *value); - -gint gst_sbc_select_blocks_from_list(const GValue *value); - -gint gst_sbc_select_subbands_from_list(const GValue *value); - -gint gst_sbc_select_bitpool_from_range(const GValue *value); - -const gchar *gst_sbc_get_allocation_from_list(const GValue *value); - -const gchar *gst_sbc_get_mode_from_list(const GValue *value, gint channels); - -gint gst_sbc_get_channel_number(gint mode); -gint gst_sbc_parse_rate_from_sbc(gint frequency); -gint gst_sbc_parse_rate_to_sbc(gint rate); - -gint gst_sbc_parse_subbands_from_sbc(gint subbands); -gint gst_sbc_parse_subbands_to_sbc(gint subbands); - -gint gst_sbc_parse_blocks_from_sbc(gint blocks); -gint gst_sbc_parse_blocks_to_sbc(gint blocks); - -const gchar *gst_sbc_parse_mode_from_sbc(gint mode); -gint gst_sbc_parse_mode_to_sbc(const gchar *mode); - -const gchar *gst_sbc_parse_allocation_from_sbc(gint alloc); -gint gst_sbc_parse_allocation_to_sbc(const gchar *allocation); - -GstCaps *gst_sbc_parse_caps_from_sbc(sbc_t *sbc); - -GstCaps *gst_sbc_util_caps_fixate(GstCaps *caps, gchar **error_message); - -void gst_sbc_util_set_structure_int_param(GstStructure *structure, - const gchar *field, gint field_value, - GValue *value); - -void gst_sbc_util_set_structure_string_param(GstStructure *structure, - const gchar *field, const gchar *field_value, - GValue *value); - -gboolean gst_sbc_util_fill_sbc_params(sbc_t *sbc, GstCaps *caps); -- 2.47.3