From 974757b2f714fa2104e96bd52026d670997eb1e5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 23 Aug 2007 19:12:23 +0000 Subject: [PATCH 01/57] sbc: Add SBC encoder and decoder skeletons for GStreamer --- ext/sbc/gstsbcdec.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ ext/sbc/gstsbcdec.h | 55 ++++++++++++++++++++++++++++++++++++++++ ext/sbc/gstsbcenc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ ext/sbc/gstsbcenc.h | 55 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 ext/sbc/gstsbcdec.c create mode 100644 ext/sbc/gstsbcdec.h create mode 100644 ext/sbc/gstsbcenc.c create mode 100644 ext/sbc/gstsbcenc.h diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c new file mode 100644 index 0000000000..f7067a9b2e --- /dev/null +++ b/ext/sbc/gstsbcdec.c @@ -0,0 +1,62 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 "sbc.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 void +gst_sbc_dec_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details (element_class, &sbc_dec_details); +} + +static void +gst_sbc_dec_class_init (GstSbcDecClass * klass) +{ + parent_class = g_type_class_peek_parent (klass); + + GST_DEBUG_CATEGORY_INIT (sbc_dec_debug, "sbcdec", 0, "SBC decoding element"); +} + +static void +gst_sbc_dec_init (GstSbcDec * sbcdec, GstSbcDecClass * klass) +{ +} diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h new file mode 100644 index 0000000000..0737b9d96a --- /dev/null +++ b/ext/sbc/gstsbcdec.h @@ -0,0 +1,55 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 + +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; +}; + +struct _GstSbcDecClass { + GstElementClass parent_class; +}; + +GType gst_sbc_dec_get_type(void); + +G_END_DECLS diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c new file mode 100644 index 0000000000..07f1628c23 --- /dev/null +++ b/ext/sbc/gstsbcenc.c @@ -0,0 +1,62 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 "sbc.h" + +#include "gstsbcenc.h" + +GST_DEBUG_CATEGORY_STATIC (sbc_enc_debug); +#define GST_CAT_DEFAULT sbc_enc_debug + +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 void +gst_sbc_enc_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details (element_class, &sbc_enc_details); +} + +static void +gst_sbc_enc_class_init (GstSbcEncClass * klass) +{ + parent_class = g_type_class_peek_parent (klass); + + GST_DEBUG_CATEGORY_INIT (sbc_enc_debug, "sbcenc", 0, "SBC encoding element"); +} + +static void +gst_sbc_enc_init (GstSbcEnc * sbcenc, GstSbcEncClass * klass) +{ +} diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h new file mode 100644 index 0000000000..64457d2131 --- /dev/null +++ b/ext/sbc/gstsbcenc.h @@ -0,0 +1,55 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 + +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; +}; + +struct _GstSbcEncClass { + GstElementClass parent_class; +}; + +GType gst_sbc_enc_get_type(void); + +G_END_DECLS From 36f952b627de6c7f1339a4be95923579d4ea825f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 17:03:03 +0000 Subject: [PATCH 02/57] sbc: Implement full decoding support --- ext/sbc/gstsbcdec.c | 134 +++++++++++++++++++++++++++++++++++++++++++- ext/sbc/gstsbcdec.h | 6 ++ 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index f7067a9b2e..1f75e384f4 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -25,7 +25,7 @@ #include #endif -#include "sbc.h" +#include #include "gstsbcdec.h" @@ -40,23 +40,153 @@ GST_ELEMENT_DETAILS ("Bluetooth SBC decoder", "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) [ 6000, 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, offset = 0; + guint8 *data; + GstClockTime timestamp; + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + + 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, *temp; + int consumed; + + consumed = sbc_decode (&dec->sbc, data + offset, size - offset); + if (consumed <= 0) + break; + + caps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, dec->sbc.rate, + "channels", G_TYPE_INT, dec->sbc.channels, NULL); + + template = gst_static_pad_template_get (&sbc_dec_src_factory); + + temp = gst_caps_intersect (caps, gst_pad_template_get_caps (template)); + + gst_caps_unref (caps); + + res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, + GST_BUFFER_OFFSET_NONE, dec->sbc.len, temp, &output); + + gst_caps_unref (temp); + + if (res != GST_FLOW_OK) + goto done; + + memcpy (GST_BUFFER_DATA (output), dec->sbc.data, dec->sbc.len); + + 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); + 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); + 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 *gstelement_class = GST_ELEMENT_CLASS (klass); + parent_class = g_type_class_peek_parent (klass); + gstelement_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 * sbcdec, GstSbcDecClass * klass) +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); } diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index 0737b9d96a..4a6922a090 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -23,6 +23,8 @@ #include +#include "sbc.h" + G_BEGIN_DECLS #define GST_TYPE_SBC_DEC \ @@ -44,6 +46,10 @@ struct _GstSbcDec { GstPad *sinkpad; GstPad *srcpad; + + GstBuffer *buffer; + + sbc_t sbc; }; struct _GstSbcDecClass { From 7a231ada0761720ff4120798b16e81b3919e2193 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 17:37:05 +0000 Subject: [PATCH 03/57] sbc: Limit the supported output rates --- ext/sbc/gstsbcdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 1f75e384f4..092883ab61 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -47,7 +47,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, 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) [ 6000, 48000 ], " + "rate = (int) { 16000, 32000, 44100, 48000 }, " "channels = (int) [ 1, 2 ], " "endianness = (int) BYTE_ORDER, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")); From 1f88ce2dcad02e21d41083afb089056fa71df2cc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 18:50:28 +0000 Subject: [PATCH 04/57] sbc: Fix class variable naming --- ext/sbc/gstsbcdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 092883ab61..1f6545b65c 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -170,11 +170,11 @@ gst_sbc_dec_base_init (gpointer g_class) static void gst_sbc_dec_class_init (GstSbcDecClass * klass) { - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); - gstelement_class->change_state = GST_DEBUG_FUNCPTR (sbc_dec_change_state); + element_class->change_state = GST_DEBUG_FUNCPTR (sbc_dec_change_state); GST_DEBUG_CATEGORY_INIT (sbc_dec_debug, "sbcdec", 0, "SBC decoding element"); } From fa031b3fe0eeddbabc2004b7c020221d2802d458 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 19:32:03 +0000 Subject: [PATCH 05/57] sbc: Implement full encoding support --- ext/sbc/gstsbcenc.c | 114 +++++++++++++++++++++++++++++++++++++++++++- ext/sbc/gstsbcenc.h | 4 ++ 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 07f1628c23..05596ef2e6 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -25,7 +25,7 @@ #include #endif -#include "sbc.h" +#include #include "gstsbcenc.h" @@ -40,23 +40,133 @@ GST_ELEMENT_DETAILS ("Bluetooth SBC encoder", "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")); + +static GstFlowReturn +sbc_enc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstSbcEnc *enc = GST_SBC_ENC (gst_pad_get_parent (pad)); + GstFlowReturn res = GST_FLOW_OK; + GstStructure *structure; + gint rate, channels; + guint size, offset = 0; + guint8 *data; + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + structure = gst_caps_get_structure (GST_PAD_CAPS (pad), 0); + gst_structure_get_int (structure, "rate", &rate); + gst_structure_get_int (structure, "channels", &channels); + + enc->sbc.rate = rate; + enc->sbc.channels = channels; + enc->sbc.subbands = 8; + enc->sbc.joint = 0; + + while (offset < size) { + GstBuffer *output; + GstCaps *caps; + int consumed; + + consumed = sbc_encode (&enc->sbc, data + offset, size - offset); + if (consumed <= 0) + break; + + caps = GST_PAD_CAPS (enc->srcpad); + + res = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, + GST_BUFFER_OFFSET_NONE, enc->sbc.len, caps, &output); + + if (res != GST_FLOW_OK) + goto done; + + memcpy (GST_BUFFER_DATA (output), enc->sbc.data, enc->sbc.len); + + res = gst_pad_push (enc->srcpad, output); + if (res != GST_FLOW_OK) + goto done; + + offset += consumed; + } + + if (offset < size) + res = GST_FLOW_ERROR; + +done: + gst_buffer_unref (buffer); + 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_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_class_init (GstSbcEncClass * klass) { + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + parent_class = g_type_class_peek_parent (klass); + element_class->change_state = GST_DEBUG_FUNCPTR (sbc_enc_change_state); + GST_DEBUG_CATEGORY_INIT (sbc_enc_debug, "sbcenc", 0, "SBC encoding element"); } static void -gst_sbc_enc_init (GstSbcEnc * sbcenc, GstSbcEncClass * klass) +gst_sbc_enc_init (GstSbcEnc * self, GstSbcEncClass * klass) { + self->sinkpad = + gst_pad_new_from_static_template (&sbc_enc_sink_factory, "sink"); + 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_chain_function (self->sinkpad, GST_DEBUG_FUNCPTR (sbc_enc_chain)); + gst_element_add_pad (GST_ELEMENT (self), self->srcpad); } diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 64457d2131..491135c16a 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -23,6 +23,8 @@ #include +#include "sbc.h" + G_BEGIN_DECLS #define GST_TYPE_SBC_ENC \ @@ -44,6 +46,8 @@ struct _GstSbcEnc { GstPad *sinkpad; GstPad *srcpad; + + sbc_t sbc; }; struct _GstSbcEncClass { From 5488f2bf134a7b67502c9a044e61e0d6e1c30d01 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 26 Aug 2007 13:12:47 +0000 Subject: [PATCH 06/57] sbc: Add mode property to the encoder --- ext/sbc/gstsbcenc.c | 77 ++++++++++++++++++++++++++++++++++++++++++++- ext/sbc/gstsbcenc.h | 2 ++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 05596ef2e6..46369b0141 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -32,6 +32,33 @@ 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[] = { + {0, "Auto", "auto"}, + {1, "Mono", "mono"}, + {2, "Dual Channel", "dual"}, + {3, "Stereo", "stereo"}, + {4, "Joint Stereo", "joint"}, + {-1, NULL, NULL} + }; + + if (!sbc_mode_type) + sbc_mode_type = g_enum_register_static ("GstSbcMode", sbc_modes); + + return sbc_mode_type; +} + +enum +{ + PROP_0, + PROP_MODE, +}; + GST_BOILERPLATE (GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); static const GstElementDetails sbc_enc_details = @@ -50,7 +77,13 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, static GstStaticPadTemplate sbc_enc_src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-sbc")); + 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 }")); static GstFlowReturn sbc_enc_chain (GstPad * pad, GstBuffer * buffer) @@ -147,15 +180,57 @@ gst_sbc_enc_base_init (gpointer g_class) 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); + + switch (prop_id) { + case PROP_MODE: + enc->mode = g_value_get_enum (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; + + 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); + 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, 0, G_PARAM_READWRITE)); + GST_DEBUG_CATEGORY_INIT (sbc_enc_debug, "sbcenc", 0, "SBC encoding element"); } diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 491135c16a..e7daf2d3af 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -47,6 +47,8 @@ struct _GstSbcEnc { GstPad *sinkpad; GstPad *srcpad; + gint mode; + sbc_t sbc; }; From 85874338ff6421de9e9997e144a5517ec9aaeecf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 26 Aug 2007 13:59:05 +0000 Subject: [PATCH 07/57] sbc: Implement full parsing support --- ext/sbc/gstsbcparse.c | 194 ++++++++++++++++++++++++++++++++++++++++++ ext/sbc/gstsbcparse.h | 61 +++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 ext/sbc/gstsbcparse.c create mode 100644 ext/sbc/gstsbcparse.h diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c new file mode 100644 index 0000000000..5097a85ffe --- /dev/null +++ b/ext/sbc/gstsbcparse.c @@ -0,0 +1,194 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 "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")); + +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 }")); + +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; + GstClockTime timestamp; + + timestamp = GST_BUFFER_TIMESTAMP(buffer); + + if (parse->buffer) { + GstBuffer *temp = buffer; + buffer = gst_buffer_span(parse->buffer, 0, buffer, + GST_BUFFER_SIZE(parse->buffer) + GST_BUFFER_SIZE(buffer)); + gst_buffer_unref(temp); + gst_buffer_unref(parse->buffer); + parse->buffer = NULL; + } + + data = GST_BUFFER_DATA(buffer); + size = GST_BUFFER_SIZE(buffer); + + while (offset < size) { + GstBuffer *output; + GstPadTemplate *template; + GstCaps *caps, *temp; + int consumed; + + consumed = sbc_parse(&parse->sbc, data + offset, size - offset); + if (consumed <= 0) + break; + + caps = gst_caps_new_simple("audio/x-sbc", + "rate", G_TYPE_INT, parse->sbc.rate, + "channels", G_TYPE_INT, parse->sbc.channels, + NULL); + + template = gst_static_pad_template_get(&sbc_parse_src_factory); + + temp = gst_caps_intersect(caps, + gst_pad_template_get_caps(template)); + + gst_caps_unref(caps); + + res = gst_pad_alloc_buffer_and_set_caps(parse->srcpad, + GST_BUFFER_OFFSET_NONE, + consumed, temp, &output); + + gst_caps_unref(temp); + + 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"); + if (parse->buffer) { + gst_buffer_unref(parse->buffer); + parse->buffer = NULL; + } + 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; + } + 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); +} diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h new file mode 100644 index 0000000000..ceaf21977f --- /dev/null +++ b/ext/sbc/gstsbcparse.h @@ -0,0 +1,61 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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; +}; + +struct _GstSbcParseClass { + GstElementClass parent_class; +}; + +GType gst_sbc_parse_get_type(void); + +G_END_DECLS From e590dc56dca446179ae83586e80d1ce129dfe24e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 27 Aug 2007 14:10:00 +0000 Subject: [PATCH 08/57] sbc: Force LITTLE_ENDIAN instead of BYTE_ORDER for now --- ext/sbc/gstsbcdec.c | 2 +- ext/sbc/gstsbcenc.c | 2 +- ext/sbc/gstsbcparse.c | 223 +++++++++++++++++++++--------------------- 3 files changed, 115 insertions(+), 112 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 1f6545b65c..a857032383 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -49,7 +49,7 @@ 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, " + "endianness = (int) LITTLE_ENDIAN, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")); static GstFlowReturn diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 46369b0141..c911eb5385 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -72,7 +72,7 @@ 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, " + "endianness = (int) LITTLE_ENDIAN, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")); static GstStaticPadTemplate sbc_enc_src_factory = diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 5097a85ffe..f140dc5ab2 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -29,166 +29,169 @@ #include "gstsbcparse.h" -GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug); +GST_DEBUG_CATEGORY_STATIC (sbc_parse_debug); #define GST_CAT_DEFAULT sbc_parse_debug -GST_BOILERPLATE(GstSbcParse, gst_sbc_parse, GstElement, GST_TYPE_ELEMENT); +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 "); +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")); +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-sbc")); 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 }")); +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 }")); -static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer) +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; - GstClockTime timestamp; + GstSbcParse *parse = GST_SBC_PARSE (gst_pad_get_parent (pad)); + GstFlowReturn res = GST_FLOW_OK; + guint size, offset = 0; + guint8 *data; + GstClockTime timestamp; - timestamp = GST_BUFFER_TIMESTAMP(buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); - if (parse->buffer) { - GstBuffer *temp = buffer; - buffer = gst_buffer_span(parse->buffer, 0, buffer, - GST_BUFFER_SIZE(parse->buffer) + GST_BUFFER_SIZE(buffer)); - gst_buffer_unref(temp); - gst_buffer_unref(parse->buffer); - parse->buffer = NULL; - } + if (parse->buffer) { + GstBuffer *temp = buffer; + buffer = gst_buffer_span (parse->buffer, 0, buffer, + GST_BUFFER_SIZE (parse->buffer) + GST_BUFFER_SIZE (buffer)); + gst_buffer_unref (temp); + gst_buffer_unref (parse->buffer); + parse->buffer = NULL; + } - data = GST_BUFFER_DATA(buffer); - size = GST_BUFFER_SIZE(buffer); + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); - while (offset < size) { - GstBuffer *output; - GstPadTemplate *template; - GstCaps *caps, *temp; - int consumed; + while (offset < size) { + GstBuffer *output; + GstPadTemplate *template; + GstCaps *caps, *temp; + int consumed; - consumed = sbc_parse(&parse->sbc, data + offset, size - offset); - if (consumed <= 0) - break; + consumed = sbc_parse (&parse->sbc, data + offset, size - offset); + if (consumed <= 0) + break; - caps = gst_caps_new_simple("audio/x-sbc", - "rate", G_TYPE_INT, parse->sbc.rate, - "channels", G_TYPE_INT, parse->sbc.channels, - NULL); + caps = gst_caps_new_simple ("audio/x-sbc", + "rate", G_TYPE_INT, parse->sbc.rate, + "channels", G_TYPE_INT, parse->sbc.channels, NULL); - template = gst_static_pad_template_get(&sbc_parse_src_factory); + template = gst_static_pad_template_get (&sbc_parse_src_factory); - temp = gst_caps_intersect(caps, - gst_pad_template_get_caps(template)); + temp = gst_caps_intersect (caps, gst_pad_template_get_caps (template)); - gst_caps_unref(caps); + gst_caps_unref (caps); - res = gst_pad_alloc_buffer_and_set_caps(parse->srcpad, - GST_BUFFER_OFFSET_NONE, - consumed, temp, &output); + res = gst_pad_alloc_buffer_and_set_caps (parse->srcpad, + GST_BUFFER_OFFSET_NONE, consumed, temp, &output); - gst_caps_unref(temp); + gst_caps_unref (temp); - if (res != GST_FLOW_OK) - goto done; + if (res != GST_FLOW_OK) + goto done; - memcpy(GST_BUFFER_DATA(output), data + offset, consumed); + memcpy (GST_BUFFER_DATA (output), data + offset, consumed); - res = gst_pad_push(parse->srcpad, output); - if (res != GST_FLOW_OK) - goto done; + res = gst_pad_push (parse->srcpad, output); + if (res != GST_FLOW_OK) + goto done; - offset += consumed; - } + offset += consumed; + } - if (offset < size) - parse->buffer = gst_buffer_create_sub(buffer, - offset, size - offset); + if (offset < size) + parse->buffer = gst_buffer_create_sub (buffer, offset, size - offset); done: - gst_buffer_unref(buffer); - gst_object_unref(parse); + gst_buffer_unref (buffer); + gst_object_unref (parse); - return res; + return res; } -static GstStateChangeReturn sbc_parse_change_state(GstElement *element, - GstStateChange transition) +static GstStateChangeReturn +sbc_parse_change_state (GstElement * element, GstStateChange transition) { - GstSbcParse *parse = GST_SBC_PARSE(element); + GstSbcParse *parse = GST_SBC_PARSE (element); - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG("Setup subband codec"); - if (parse->buffer) { - gst_buffer_unref(parse->buffer); - parse->buffer = NULL; - } - sbc_init(&parse->sbc, 0); - break; + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG ("Setup subband codec"); + if (parse->buffer) { + gst_buffer_unref (parse->buffer); + parse->buffer = NULL; + } + 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; - } - sbc_finish(&parse->sbc); - break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG ("Finish subband codec"); + if (parse->buffer) { + gst_buffer_unref (parse->buffer); + parse->buffer = NULL; + } + sbc_finish (&parse->sbc); + break; - default: - break; - } + default: + break; + } - return parent_class->change_state(element, transition); + return parent_class->change_state (element, transition); } -static void gst_sbc_parse_base_init(gpointer g_class) +static void +gst_sbc_parse_base_init (gpointer g_class) { - GstElementClass *element_class = GST_ELEMENT_CLASS(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_sink_factory)); - gst_element_class_add_pad_template(element_class, - gst_static_pad_template_get(&sbc_parse_src_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); + gst_element_class_set_details (element_class, &sbc_parse_details); } -static void gst_sbc_parse_class_init(GstSbcParseClass *klass) +static void +gst_sbc_parse_class_init (GstSbcParseClass * klass) { - GstElementClass *element_class = GST_ELEMENT_CLASS(klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - parent_class = g_type_class_peek_parent(klass); + parent_class = g_type_class_peek_parent (klass); - element_class->change_state = GST_DEBUG_FUNCPTR(sbc_parse_change_state); + element_class->change_state = GST_DEBUG_FUNCPTR (sbc_parse_change_state); - GST_DEBUG_CATEGORY_INIT(sbc_parse_debug, "sbcparse", 0, - "SBC parsing element"); + GST_DEBUG_CATEGORY_INIT (sbc_parse_debug, "sbcparse", 0, + "SBC parsing element"); } -static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass) +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->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->srcpad = + gst_pad_new_from_static_template (&sbc_parse_src_factory, "src"); + gst_element_add_pad (GST_ELEMENT (self), self->srcpad); } From c5668f1e4580b5a651cb175c4627d5572c607c44 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 18 Oct 2007 21:45:14 +0000 Subject: [PATCH 09/57] sbc: Add gstsbcutil.c and gstsbcutil.h. --- ext/sbc/gstsbcutil.c | 185 +++++++++++++++++++++++++++++++++++++++++++ ext/sbc/gstsbcutil.h | 47 +++++++++++ 2 files changed, 232 insertions(+) create mode 100644 ext/sbc/gstsbcutil.c create mode 100644 ext/sbc/gstsbcutil.h diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c new file mode 100644 index 0000000000..706e7f5487 --- /dev/null +++ b/ext/sbc/gstsbcutil.c @@ -0,0 +1,185 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 + * + */ + + +/* common functions for gstreamer sbc related plugins */ + + +#include "gstsbcutil.h" +#include "ipc.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 rate from a range of possible rates + * TODO - use a better approach to this (it is selecting the maximum value) + */ +gint gst_sbc_select_rate_from_range(const GValue *value) +{ + return gst_value_get_int_range_max(value); +} + +/* + * Selects one number of channels from a list of possible numbers + * TODO - use a better approach to this (it is selecting the last element) + */ +gint gst_sbc_select_channels_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 blocks option from a range of possible blocks + * TODO - use a better approach to this (it is selecting the maximum value) + */ +gint gst_sbc_select_blocks_from_range(const GValue *value) +{ + return gst_value_get_int_range_max(value); +} + +/* + * 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 subbands option from a range + * TODO - use a better approach to this (it is selecting the maximum value) + */ +gint gst_sbc_select_subbands_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 + * TODO - use a better aproach + */ +const gchar* gst_sbc_get_mode_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)); +} + +gint gst_sbc_get_allocation_mode_int(const gchar* allocation) +{ + if (g_ascii_strcasecmp(allocation, "loudness") == 0) + return CFG_ALLOCATION_LOUDNESS; + else if (g_ascii_strcasecmp(allocation, "snr") == 0) + return CFG_ALLOCATION_SNR; + else if (g_ascii_strcasecmp(allocation, "auto") == 0) + return CFG_ALLOCATION_AUTO; + else + return -1; +} + +gint gst_sbc_get_mode_int(const gchar* mode) +{ + if (g_ascii_strcasecmp(mode, "joint") == 0) + return CFG_MODE_JOINT_STEREO; + else if (g_ascii_strcasecmp(mode, "stereo") == 0) + return CFG_MODE_STEREO; + else if (g_ascii_strcasecmp(mode, "dual") == 0) + return CFG_MODE_DUAL_CHANNEL; + else if (g_ascii_strcasecmp(mode, "mono") == 0) + return CFG_MODE_MONO; + else if (g_ascii_strcasecmp(mode, "auto") == 0) + return CFG_MODE_AUTO; + else + return -1; +} + +const gchar* gst_sbc_get_mode_string(int joint) +{ + switch (joint) { + case CFG_MODE_MONO: + return "mono"; + case CFG_MODE_DUAL_CHANNEL: + return "dual"; + case CFG_MODE_STEREO: + return "stereo"; + case CFG_MODE_JOINT_STEREO: + return "joint"; + case CFG_MODE_AUTO: + return NULL; /* TODO what should be selected here? */ + default: + return NULL; + } +} + +const gchar* gst_sbc_get_allocation_string(int alloc) +{ + switch (alloc) { + case CFG_ALLOCATION_LOUDNESS: + return "loudness"; + case CFG_ALLOCATION_SNR: + return "snr"; + case CFG_ALLOCATION_AUTO: + return NULL; /* TODO what should be selected here? */ + default: + return NULL; + } +} diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h new file mode 100644 index 0000000000..84161d8569 --- /dev/null +++ b/ext/sbc/gstsbcutil.h @@ -0,0 +1,47 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 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 + * + */ + + +/* common functions for gstreamer sbc related plugins */ + +#include + +gint gst_sbc_select_rate_from_list(const GValue *value); +gint gst_sbc_select_rate_from_range(const GValue *value); + +gint gst_sbc_select_channels_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_blocks_from_range(const GValue *value); + +gint gst_sbc_select_subbands_from_list(const GValue *value); +gint gst_sbc_select_subbands_from_range(const GValue *value); + +const gchar* gst_sbc_get_allocation_from_list(const GValue *value); +gint gst_sbc_get_allocation_mode_int(const gchar* allocation); +const gchar* gst_sbc_get_allocation_string(int alloc); + +const gchar* gst_sbc_get_mode_from_list(const GValue *value); +gint gst_sbc_get_mode_int(const gchar* mode); +const gchar* gst_sbc_get_mode_string(int joint); From f88c9d555516c7a4fde152827db2ddcc5c56ccf9 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 18 Oct 2007 21:46:49 +0000 Subject: [PATCH 10/57] sbc: Fixes for gstsbcenc. --- ext/sbc/gstsbcenc.c | 157 +++++++++++++++++++++++++++++++++++++---- ext/sbc/gstsbcenc.h | 5 ++ ext/sbc/gstsbcutil.c | 162 +++++++++++++++++++++++-------------------- 3 files changed, 235 insertions(+), 89 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index c911eb5385..e6c4d1f1e9 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -28,6 +28,13 @@ #include #include "gstsbcenc.h" +#include "gstsbcutil.h" + + +#define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO +#define SBC_ENC_DEFAULT_BLOCKS 16 +#define SBC_ENC_DEFAULT_SUB_BANDS 8 +#define SBC_ENC_DEFAULT_ALLOCATION CFG_ALLOCATION_AUTO GST_DEBUG_CATEGORY_STATIC (sbc_enc_debug); #define GST_CAT_DEFAULT sbc_enc_debug @@ -53,10 +60,33 @@ gst_sbc_mode_get_type (void) 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[] = { + {CFG_ALLOCATION_AUTO, "Auto", "auto"}, + {CFG_ALLOCATION_LOUDNESS, "Loudness", "loudness"}, + {CFG_ALLOCATION_SNR, "SNR", "snr"}, + {-1, NULL, NULL} + }; + + if (!sbc_allocation_type) + sbc_allocation_type = + g_enum_register_static ("GstSbcAllocation", sbc_allocations); + + return sbc_allocation_type; +} + enum { PROP_0, PROP_MODE, + PROP_ALLOCATION, + PROP_BLOCKS, + PROP_SUB_BANDS }; GST_BOILERPLATE (GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); @@ -85,28 +115,83 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }")); + +static GstCaps * +sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) +{ + gint rate; + gint channels; + GstCaps *src_caps; + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "rate", &rate)) + return NULL; + if (!gst_structure_get_int (structure, "channels", &channels)) + return NULL; + + enc->sbc.rate = rate; + enc->sbc.channels = channels; + + if (enc->mode == 0) + enc->sbc.joint = CFG_MODE_JOINT_STEREO; + else + enc->sbc.joint = enc->mode; + + enc->sbc.blocks = enc->blocks; + enc->sbc.subbands = enc->subbands; + if (enc->allocation == 0) + enc->sbc.allocation = CFG_ALLOCATION_LOUDNESS; + else + enc->sbc.allocation = enc->allocation; + + src_caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, + enc->sbc.rate, "channels", G_TYPE_INT, + enc->sbc.channels, "mode", G_TYPE_STRING, + gst_sbc_get_mode_string (enc->sbc.joint), "subbands", + G_TYPE_INT, enc->sbc.subbands, "blocks", G_TYPE_INT, + enc->sbc.blocks, "allocation", G_TYPE_STRING, + gst_sbc_get_allocation_string (enc->sbc.allocation), NULL); + + return src_caps; +} + +static gboolean +sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSbcEnc *enc; + GstStructure *structure; + GstCaps *othercaps; + + enc = GST_SBC_ENC (GST_PAD_PARENT (pad)); + structure = gst_caps_get_structure (caps, 0); + + othercaps = sbc_enc_generate_srcpad_caps (enc, caps); + if (othercaps == NULL) + goto error; + + gst_pad_set_caps (enc->srcpad, othercaps); + gst_caps_unref (othercaps); + + return TRUE; + +error: + GST_ERROR_OBJECT (enc, "invalid input caps"); + return FALSE; +} + static GstFlowReturn sbc_enc_chain (GstPad * pad, GstBuffer * buffer) { GstSbcEnc *enc = GST_SBC_ENC (gst_pad_get_parent (pad)); GstFlowReturn res = GST_FLOW_OK; - GstStructure *structure; - gint rate, channels; guint size, offset = 0; guint8 *data; data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); - structure = gst_caps_get_structure (GST_PAD_CAPS (pad), 0); - gst_structure_get_int (structure, "rate", &rate); - gst_structure_get_int (structure, "channels", &channels); - - enc->sbc.rate = rate; - enc->sbc.channels = channels; - enc->sbc.subbands = 8; - enc->sbc.joint = 0; - while (offset < size) { GstBuffer *output; GstCaps *caps; @@ -186,11 +271,23 @@ gst_sbc_enc_set_property (GObject * object, guint prop_id, { GstSbcEnc *enc = GST_SBC_ENC (object); + /* TODO - CAN ONLY BE CHANGED ON READY AND BELOW */ + 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: + /* TODO - verify consistency */ + enc->blocks = g_value_get_int (value); + break; + case PROP_SUB_BANDS: + /* TODO - verify consistency */ + enc->subbands = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -207,7 +304,15 @@ gst_sbc_enc_get_property (GObject * object, guint 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_int (value, enc->blocks); + break; + case PROP_SUB_BANDS: + g_value_set_int (value, enc->subbands); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -228,8 +333,23 @@ gst_sbc_enc_class_init (GstSbcEncClass * klass) 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, 0, G_PARAM_READWRITE)); + 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 mode", GST_TYPE_SBC_ALLOCATION, + SBC_ENC_DEFAULT_ALLOCATION, G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_BLOCKS, + g_param_spec_int ("blocks", "Blocks", + "Blocks", 0, G_MAXINT, SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SUB_BANDS, + g_param_spec_int ("subbands", "Sub Bands", + "Sub Bands", 0, G_MAXINT, + SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE)); GST_DEBUG_CATEGORY_INIT (sbc_enc_debug, "sbcenc", 0, "SBC encoding element"); } @@ -239,9 +359,16 @@ 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_chain_function (self->sinkpad, GST_DEBUG_FUNCPTR (sbc_enc_chain)); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + + 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; } diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index e7daf2d3af..0a95bcef2c 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -24,6 +24,8 @@ #include #include "sbc.h" +#include "ipc.h" + G_BEGIN_DECLS @@ -48,6 +50,9 @@ struct _GstSbcEnc { GstPad *srcpad; gint mode; + gint blocks; + gint allocation; + gint subbands; sbc_t sbc; }; diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 706e7f5487..b0175b433d 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -32,154 +32,168 @@ * 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) +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)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one rate from a range of possible rates * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_rate_from_range(const GValue *value) +gint +gst_sbc_select_rate_from_range (const GValue * value) { - return gst_value_get_int_range_max(value); + return gst_value_get_int_range_max (value); } /* * Selects one number of channels from a list of possible numbers * TODO - use a better approach to this (it is selecting the last element) */ -gint gst_sbc_select_channels_from_list(const GValue *value) +gint +gst_sbc_select_channels_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)); + 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) +gint +gst_sbc_select_channels_from_range (const GValue * value) { - return gst_value_get_int_range_max(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) +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)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one blocks option from a range of possible blocks * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_blocks_from_range(const GValue *value) +gint +gst_sbc_select_blocks_from_range (const GValue * value) { - return gst_value_get_int_range_max(value); + return gst_value_get_int_range_max (value); } /* * 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) +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)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one subbands option from a range * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_subbands_from_range(const GValue *value) +gint +gst_sbc_select_subbands_from_range (const GValue * value) { - return gst_value_get_int_range_max(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) +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)); + 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 * TODO - use a better aproach */ -const gchar* gst_sbc_get_mode_from_list(const GValue *value) +const gchar * +gst_sbc_get_mode_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)); + guint size = gst_value_list_get_size (value); + return g_value_get_string (gst_value_list_get_value (value, size - 1)); } -gint gst_sbc_get_allocation_mode_int(const gchar* allocation) +gint +gst_sbc_get_allocation_mode_int (const gchar * allocation) { - if (g_ascii_strcasecmp(allocation, "loudness") == 0) - return CFG_ALLOCATION_LOUDNESS; - else if (g_ascii_strcasecmp(allocation, "snr") == 0) - return CFG_ALLOCATION_SNR; - else if (g_ascii_strcasecmp(allocation, "auto") == 0) - return CFG_ALLOCATION_AUTO; - else - return -1; + if (g_ascii_strcasecmp (allocation, "loudness") == 0) + return CFG_ALLOCATION_LOUDNESS; + else if (g_ascii_strcasecmp (allocation, "snr") == 0) + return CFG_ALLOCATION_SNR; + else if (g_ascii_strcasecmp (allocation, "auto") == 0) + return CFG_ALLOCATION_AUTO; + else + return -1; } -gint gst_sbc_get_mode_int(const gchar* mode) +gint +gst_sbc_get_mode_int (const gchar * mode) { - if (g_ascii_strcasecmp(mode, "joint") == 0) - return CFG_MODE_JOINT_STEREO; - else if (g_ascii_strcasecmp(mode, "stereo") == 0) - return CFG_MODE_STEREO; - else if (g_ascii_strcasecmp(mode, "dual") == 0) - return CFG_MODE_DUAL_CHANNEL; - else if (g_ascii_strcasecmp(mode, "mono") == 0) - return CFG_MODE_MONO; - else if (g_ascii_strcasecmp(mode, "auto") == 0) - return CFG_MODE_AUTO; - else - return -1; + if (g_ascii_strcasecmp (mode, "joint") == 0) + return CFG_MODE_JOINT_STEREO; + else if (g_ascii_strcasecmp (mode, "stereo") == 0) + return CFG_MODE_STEREO; + else if (g_ascii_strcasecmp (mode, "dual") == 0) + return CFG_MODE_DUAL_CHANNEL; + else if (g_ascii_strcasecmp (mode, "mono") == 0) + return CFG_MODE_MONO; + else if (g_ascii_strcasecmp (mode, "auto") == 0) + return CFG_MODE_AUTO; + else + return -1; } -const gchar* gst_sbc_get_mode_string(int joint) +const gchar * +gst_sbc_get_mode_string (int joint) { - switch (joint) { - case CFG_MODE_MONO: - return "mono"; - case CFG_MODE_DUAL_CHANNEL: - return "dual"; - case CFG_MODE_STEREO: - return "stereo"; - case CFG_MODE_JOINT_STEREO: - return "joint"; - case CFG_MODE_AUTO: - return NULL; /* TODO what should be selected here? */ - default: - return NULL; - } + switch (joint) { + case CFG_MODE_MONO: + return "mono"; + case CFG_MODE_DUAL_CHANNEL: + return "dual"; + case CFG_MODE_STEREO: + return "stereo"; + case CFG_MODE_JOINT_STEREO: + return "joint"; + case CFG_MODE_AUTO: + return NULL; /* TODO what should be selected here? */ + default: + return NULL; + } } -const gchar* gst_sbc_get_allocation_string(int alloc) +const gchar * +gst_sbc_get_allocation_string (int alloc) { - switch (alloc) { - case CFG_ALLOCATION_LOUDNESS: - return "loudness"; - case CFG_ALLOCATION_SNR: - return "snr"; - case CFG_ALLOCATION_AUTO: - return NULL; /* TODO what should be selected here? */ - default: - return NULL; - } + switch (alloc) { + case CFG_ALLOCATION_LOUDNESS: + return "loudness"; + case CFG_ALLOCATION_SNR: + return "snr"; + case CFG_ALLOCATION_AUTO: + return NULL; /* TODO what should be selected here? */ + default: + return NULL; + } } From 01b05306639f386efbf54467dc92af0fae20ecbf Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 18 Oct 2007 21:47:53 +0000 Subject: [PATCH 11/57] sbc: Fixes sbcparser element. --- ext/sbc/gstsbcparse.c | 182 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 169 insertions(+), 13 deletions(-) diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index f140dc5ab2..f320962fe8 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -28,6 +28,7 @@ #include #include "gstsbcparse.h" +#include "gstsbcutil.h" GST_DEBUG_CATEGORY_STATIC (sbc_parse_debug); #define GST_CAT_DEFAULT sbc_parse_debug @@ -54,6 +55,170 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }")); +/* + Creates a fixed caps from the caps given. + +*/ +static GstCaps * +sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) +{ + GstCaps *result; + GstStructure *structure; + const GValue *value; + gboolean error = FALSE; + gint temp, rate, channels, blocks, subbands; + const gchar *allocation = NULL; + const gchar *mode = NULL; + const gchar *error_message = NULL; + + structure = gst_caps_get_structure (caps, 0); + + /* rate */ + if (!gst_structure_has_field (structure, "rate")) { + error = TRUE; + error_message = "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 if (GST_VALUE_HOLDS_INT_RANGE (value)) { + temp = gst_sbc_select_rate_from_range (value); + } else { + temp = g_value_get_int (value); + } + rate = temp; + } + + /* channels */ + if (!gst_structure_has_field (structure, "channels")) { + error = TRUE; + error_message = "no channels."; + goto error; + } else { + value = gst_structure_get_value (structure, "channels"); + if (GST_VALUE_HOLDS_LIST (value)) { + temp = gst_sbc_select_channels_from_list (value); + } else if (GST_VALUE_HOLDS_INT_RANGE (value)) { + temp = gst_sbc_select_channels_from_range (value); + } else { + temp = g_value_get_int (value); + } + channels = temp; + } + + /* blocks */ + if (!gst_structure_has_field (structure, "blocks")) { + error = TRUE; + error_message = "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 if (GST_VALUE_HOLDS_INT_RANGE (value)) { + temp = gst_sbc_select_blocks_from_range (value); + } else { + temp = g_value_get_int (value); + } + blocks = temp; + } + + /* subbands */ + if (!gst_structure_has_field (structure, "subbands")) { + error = TRUE; + error_message = "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 if (GST_VALUE_HOLDS_INT_RANGE (value)) { + temp = gst_sbc_select_subbands_from_range (value); + } else { + temp = g_value_get_int (value); + } + subbands = temp; + } + + /* allocation */ + if (!gst_structure_has_field (structure, "allocation")) { + error = TRUE; + error_message = "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); + } + } + + /* mode */ + if (!gst_structure_has_field (structure, "mode")) { + error = TRUE; + error_message = "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); + } else { + mode = g_value_get_string (value); + } + } + +error: + if (error) { + GST_ERROR_OBJECT (parse, "Invalid input caps: %s", error_message); + 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, NULL); + parse->sbc.rate = rate; + parse->sbc.channels = channels; + parse->sbc.blocks = blocks; + parse->sbc.subbands = subbands; + parse->sbc.joint = gst_sbc_get_mode_int (mode); + parse->sbc.allocation = gst_sbc_get_allocation_mode_int (allocation); + + return result; +} + +static gboolean +sbc_parse_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSbcParse *parse; + GstCaps *inter, *other, *srccaps; + + parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); + + other = gst_pad_peer_get_caps (parse->srcpad); + if (other == NULL) + other = gst_caps_new_any (); + + inter = gst_caps_intersect (caps, other); + srccaps = sbc_parse_select_caps (parse, inter); + if (srccaps == NULL) + return FALSE; + + gst_pad_set_caps (parse->srcpad, srccaps); + + gst_caps_unref (inter); + gst_caps_unref (other); + gst_caps_unref (srccaps); + + return TRUE; +} + static GstFlowReturn sbc_parse_chain (GstPad * pad, GstBuffer * buffer) { @@ -79,28 +244,19 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) while (offset < size) { GstBuffer *output; - GstPadTemplate *template; - GstCaps *caps, *temp; + GstCaps *temp; int consumed; consumed = sbc_parse (&parse->sbc, data + offset, size - offset); if (consumed <= 0) break; - caps = gst_caps_new_simple ("audio/x-sbc", - "rate", G_TYPE_INT, parse->sbc.rate, - "channels", G_TYPE_INT, parse->sbc.channels, NULL); - template = gst_static_pad_template_get (&sbc_parse_src_factory); - - temp = gst_caps_intersect (caps, gst_pad_template_get_caps (template)); - - gst_caps_unref (caps); + temp = GST_PAD_CAPS (parse->srcpad); res = gst_pad_alloc_buffer_and_set_caps (parse->srcpad, GST_BUFFER_OFFSET_NONE, consumed, temp, &output); - gst_caps_unref (temp); if (res != GST_FLOW_OK) goto done; @@ -138,7 +294,6 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) } sbc_init (&parse->sbc, 0); break; - case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG ("Finish subband codec"); if (parse->buffer) { @@ -147,7 +302,6 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) } sbc_finish (&parse->sbc); break; - default: break; } @@ -189,6 +343,8 @@ gst_sbc_parse_init (GstSbcParse * self, GstSbcParseClass * klass) 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_pad_set_setcaps_function (self->sinkpad, + GST_DEBUG_FUNCPTR (sbc_parse_sink_setcaps)); gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); self->srcpad = From 8f8ccc0f12da49adf2186a6d285b1e8e901d72c3 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 18 Oct 2007 22:46:12 +0000 Subject: [PATCH 12/57] sbc: Fix coding style issues. --- ext/sbc/gstsbcenc.c | 28 ++++++++++++++++------------ ext/sbc/gstsbcparse.c | 2 ++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index e6c4d1f1e9..c6f11553e6 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -30,7 +30,6 @@ #include "gstsbcenc.h" #include "gstsbcutil.h" - #define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO #define SBC_ENC_DEFAULT_BLOCKS 16 #define SBC_ENC_DEFAULT_SUB_BANDS 8 @@ -86,7 +85,7 @@ enum PROP_MODE, PROP_ALLOCATION, PROP_BLOCKS, - PROP_SUB_BANDS + PROP_SUBBANDS }; GST_BOILERPLATE (GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); @@ -123,6 +122,8 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) gint channels; GstCaps *src_caps; GstStructure *structure; + const gchar *mode; + const gchar *allocation; structure = gst_caps_get_structure (caps, 0); @@ -146,13 +147,16 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) else enc->sbc.allocation = enc->allocation; - src_caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, - enc->sbc.rate, "channels", G_TYPE_INT, - enc->sbc.channels, "mode", G_TYPE_STRING, - gst_sbc_get_mode_string (enc->sbc.joint), "subbands", - G_TYPE_INT, enc->sbc.subbands, "blocks", G_TYPE_INT, - enc->sbc.blocks, "allocation", G_TYPE_STRING, - gst_sbc_get_allocation_string (enc->sbc.allocation), NULL); + mode = gst_sbc_get_mode_string (enc->sbc.joint); + allocation = gst_sbc_get_allocation_string (enc->sbc.allocation); + + src_caps = gst_caps_new_simple ("audio/x-sbc", + "rate", G_TYPE_INT, enc->sbc.rate, + "channels", G_TYPE_INT, enc->sbc.channels, + "mode", G_TYPE_STRING, mode, + "subbands", G_TYPE_INT, enc->sbc.subbands, + "blocks", G_TYPE_INT, enc->sbc.blocks, + "allocation", G_TYPE_STRING, allocation, NULL); return src_caps; } @@ -284,7 +288,7 @@ gst_sbc_enc_set_property (GObject * object, guint prop_id, /* TODO - verify consistency */ enc->blocks = g_value_get_int (value); break; - case PROP_SUB_BANDS: + case PROP_SUBBANDS: /* TODO - verify consistency */ enc->subbands = g_value_get_int (value); break; @@ -310,7 +314,7 @@ gst_sbc_enc_get_property (GObject * object, guint prop_id, case PROP_BLOCKS: g_value_set_int (value, enc->blocks); break; - case PROP_SUB_BANDS: + case PROP_SUBBANDS: g_value_set_int (value, enc->subbands); break; default: @@ -346,7 +350,7 @@ gst_sbc_enc_class_init (GstSbcEncClass * klass) g_param_spec_int ("blocks", "Blocks", "Blocks", 0, G_MAXINT, SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE)); - g_object_class_install_property (object_class, PROP_SUB_BANDS, + g_object_class_install_property (object_class, PROP_SUBBANDS, g_param_spec_int ("subbands", "Sub Bands", "Sub Bands", 0, G_MAXINT, SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE)); diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index f320962fe8..4120d705fc 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -294,6 +294,7 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) } sbc_init (&parse->sbc, 0); break; + case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG ("Finish subband codec"); if (parse->buffer) { @@ -302,6 +303,7 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) } sbc_finish (&parse->sbc); break; + default: break; } From cd3e730aeb01a866d7b98c3f2e06a7b9892e8f11 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 24 Oct 2007 21:33:18 +0000 Subject: [PATCH 13/57] sbc: Fix coding style issues --- ext/sbc/gstsbcutil.c | 6 +----- ext/sbc/gstsbcutil.h | 15 ++++++--------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index b0175b433d..b8c764be6a 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -21,12 +21,8 @@ * */ - -/* common functions for gstreamer sbc related plugins */ - - -#include "gstsbcutil.h" #include "ipc.h" +#include "gstsbcutil.h" /* * Selects one rate from a list of possible rates diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 84161d8569..70169a7436 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -21,9 +21,6 @@ * */ - -/* common functions for gstreamer sbc related plugins */ - #include gint gst_sbc_select_rate_from_list(const GValue *value); @@ -38,10 +35,10 @@ gint gst_sbc_select_blocks_from_range(const GValue *value); gint gst_sbc_select_subbands_from_list(const GValue *value); gint gst_sbc_select_subbands_from_range(const GValue *value); -const gchar* gst_sbc_get_allocation_from_list(const GValue *value); -gint gst_sbc_get_allocation_mode_int(const gchar* allocation); -const gchar* gst_sbc_get_allocation_string(int alloc); +const gchar *gst_sbc_get_allocation_from_list(const GValue *value); +gint gst_sbc_get_allocation_mode_int(const gchar *allocation); +const gchar *gst_sbc_get_allocation_string(int alloc); -const gchar* gst_sbc_get_mode_from_list(const GValue *value); -gint gst_sbc_get_mode_int(const gchar* mode); -const gchar* gst_sbc_get_mode_string(int joint); +const gchar *gst_sbc_get_mode_from_list(const GValue *value); +gint gst_sbc_get_mode_int(const gchar *mode); +const gchar *gst_sbc_get_mode_string(int joint); From d1062c97d186229fb9039b38609ad2c3236a4d0b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 24 Oct 2007 21:36:29 +0000 Subject: [PATCH 14/57] sbc: Don't forget to include the config options --- ext/sbc/gstsbcutil.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index b8c764be6a..170ef0d463 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -21,6 +21,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "ipc.h" #include "gstsbcutil.h" From f2441fe65422a1bd0d18422f74c383cd18adc28d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 24 Oct 2007 21:51:37 +0000 Subject: [PATCH 15/57] sbc: Some more coding style changes --- ext/sbc/gstsbcparse.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 4120d705fc..2bc85584b1 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -55,10 +55,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }")); -/* - Creates a fixed caps from the caps given. - -*/ +/* reates a fixed caps from the caps given. */ static GstCaps * sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) { @@ -73,7 +70,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) structure = gst_caps_get_structure (caps, 0); - /* rate */ if (!gst_structure_has_field (structure, "rate")) { error = TRUE; error_message = "no rate."; @@ -90,7 +86,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) rate = temp; } - /* channels */ if (!gst_structure_has_field (structure, "channels")) { error = TRUE; error_message = "no channels."; @@ -107,7 +102,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) channels = temp; } - /* blocks */ if (!gst_structure_has_field (structure, "blocks")) { error = TRUE; error_message = "no blocks."; @@ -124,7 +118,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) blocks = temp; } - /* subbands */ if (!gst_structure_has_field (structure, "subbands")) { error = TRUE; error_message = "no subbands."; @@ -141,7 +134,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) subbands = temp; } - /* allocation */ if (!gst_structure_has_field (structure, "allocation")) { error = TRUE; error_message = "no allocation."; @@ -155,7 +147,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) } } - /* mode */ if (!gst_structure_has_field (structure, "mode")) { error = TRUE; error_message = "no mode."; @@ -175,7 +166,6 @@ error: return NULL; } - result = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, @@ -251,13 +241,11 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) if (consumed <= 0) break; - temp = GST_PAD_CAPS (parse->srcpad); res = gst_pad_alloc_buffer_and_set_caps (parse->srcpad, GST_BUFFER_OFFSET_NONE, consumed, temp, &output); - if (res != GST_FLOW_OK) goto done; From a2152f6c1279b827b7e740f6ebed6b3a6110cff6 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 29 Oct 2007 15:02:26 +0000 Subject: [PATCH 16/57] sbc: Add bitpool capability. --- ext/sbc/gstsbcenc.c | 9 +++++++-- ext/sbc/gstsbcparse.c | 25 +++++++++++++++++++++---- ext/sbc/gstsbcutil.c | 10 ++++++++++ ext/sbc/gstsbcutil.h | 2 ++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index c6f11553e6..245cf4250f 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -33,6 +33,7 @@ #define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO #define SBC_ENC_DEFAULT_BLOCKS 16 #define SBC_ENC_DEFAULT_SUB_BANDS 8 +#define SBC_ENC_DEFAULT_BITPOOL 53 #define SBC_ENC_DEFAULT_ALLOCATION CFG_ALLOCATION_AUTO GST_DEBUG_CATEGORY_STATIC (sbc_enc_debug); @@ -112,7 +113,8 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "mode = (string) { mono, dual, stereo, joint }, " "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " - "allocation = (string) { snr, loudness }")); + "allocation = (string) { snr, loudness }," + "bitpool = (int) [ 2, 64 ]")); static GstCaps * @@ -147,6 +149,8 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) else enc->sbc.allocation = enc->allocation; + enc->sbc.bitpool = SBC_ENC_DEFAULT_BITPOOL; + mode = gst_sbc_get_mode_string (enc->sbc.joint); allocation = gst_sbc_get_allocation_string (enc->sbc.allocation); @@ -156,7 +160,8 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) "mode", G_TYPE_STRING, mode, "subbands", G_TYPE_INT, enc->sbc.subbands, "blocks", G_TYPE_INT, enc->sbc.blocks, - "allocation", G_TYPE_STRING, allocation, NULL); + "allocation", G_TYPE_STRING, allocation, + "bitpool", G_TYPE_INT, enc->sbc.bitpool, NULL); return src_caps; } diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 2bc85584b1..c876958d81 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -53,9 +53,10 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "mode = (string) { mono, dual, stereo, joint }, " "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " - "allocation = (string) { snr, loudness }")); + "allocation = (string) { snr, loudness }," + "bitpool = (int) [ 2, 64 ]")); -/* reates a fixed caps from the caps given. */ +/* Creates a fixed caps from the caps given. */ static GstCaps * sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) { @@ -63,7 +64,7 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) GstStructure *structure; const GValue *value; gboolean error = FALSE; - gint temp, rate, channels, blocks, subbands; + gint temp, rate, channels, blocks, subbands, bitpool; const gchar *allocation = NULL; const gchar *mode = NULL; const gchar *error_message = NULL; @@ -134,6 +135,20 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) subbands = temp; } + if (!gst_structure_has_field (structure, "bitpool")) { + error = TRUE; + error_message = "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 = "no allocation."; @@ -172,11 +187,13 @@ error: "mode", G_TYPE_STRING, mode, "blocks", G_TYPE_INT, blocks, "subbands", G_TYPE_INT, subbands, - "allocation", G_TYPE_STRING, allocation, NULL); + "allocation", G_TYPE_STRING, allocation, + "bitpool", G_TYPE_INT, bitpool, NULL); parse->sbc.rate = rate; parse->sbc.channels = channels; parse->sbc.blocks = blocks; parse->sbc.subbands = subbands; + parse->sbc.bitpool = bitpool; parse->sbc.joint = gst_sbc_get_mode_int (mode); parse->sbc.allocation = gst_sbc_get_allocation_mode_int (allocation); diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 170ef0d463..63f20fce86 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -112,6 +112,16 @@ gst_sbc_select_subbands_from_range (const GValue * value) return gst_value_get_int_range_max (value); } +/* + * 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 diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 70169a7436..98f202f03b 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -35,6 +35,8 @@ gint gst_sbc_select_blocks_from_range(const GValue *value); gint gst_sbc_select_subbands_from_list(const GValue *value); gint gst_sbc_select_subbands_from_range(const GValue *value); +gint gst_sbc_select_bitpool_from_range(const GValue *value); + const gchar *gst_sbc_get_allocation_from_list(const GValue *value); gint gst_sbc_get_allocation_mode_int(const gchar *allocation); const gchar *gst_sbc_get_allocation_string(int alloc); From 5672836c61bd8639fdcb90f6a30a4a2e04f9699d Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 1 Nov 2007 13:56:51 +0000 Subject: [PATCH 17/57] sbc: Fix buffers timestamps in sbcenc. --- ext/sbc/gstsbcenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 245cf4250f..95c8091d62 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -219,6 +219,7 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) goto done; memcpy (GST_BUFFER_DATA (output), enc->sbc.data, enc->sbc.len); + GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); res = gst_pad_push (enc->srcpad, output); if (res != GST_FLOW_OK) From 6f87580cfa28639fb9a952513089555d414aa726 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 1 Nov 2007 19:45:00 +0000 Subject: [PATCH 18/57] sbc: Fix sbc negotiation and improves buffer handling by using GstAdapter. --- ext/sbc/gstsbcenc.c | 106 ++++++++++++++++++++++++++++++++++++------ ext/sbc/gstsbcenc.h | 2 + ext/sbc/gstsbcparse.c | 10 +--- ext/sbc/gstsbcutil.c | 66 ++++++++++---------------- ext/sbc/gstsbcutil.h | 13 ++++-- 5 files changed, 128 insertions(+), 69 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 95c8091d62..7b11d60f0b 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -116,7 +116,6 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "allocation = (string) { snr, loudness }," "bitpool = (int) [ 2, 64 ]")); - static GstCaps * sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) { @@ -190,25 +189,86 @@ error: return FALSE; } +gboolean +gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, 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; + + enc->sbc.rate = rate; + enc->sbc.channels = channels; + enc->blocks = blocks; + enc->sbc.subbands = subbands; + enc->sbc.bitpool = bitpool; + enc->mode = gst_sbc_get_mode_int (mode); + enc->allocation = gst_sbc_get_allocation_mode_int (allocation); + + return TRUE; +} + +static gboolean +gst_sbc_enc_change_caps (GstSbcEnc * enc, GstCaps * caps) +{ + GST_INFO_OBJECT (enc, "Changing srcpad caps (renegotiation)"); + + if (!gst_pad_accept_caps (enc->srcpad, caps)) { + GST_WARNING_OBJECT (enc, "Src pad refused caps"); + return FALSE; + } + + if (!gst_sbc_enc_fill_sbc_params (enc, caps)) { + GST_ERROR_OBJECT (enc, "couldn't get sbc parameters from caps"); + return FALSE; + } + + return TRUE; +} + 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; - guint size, offset = 0; - guint8 *data; + gint codesize = enc->sbc.subbands * enc->sbc.blocks * enc->sbc.channels * 2; - data = GST_BUFFER_DATA (buffer); - size = GST_BUFFER_SIZE (buffer); + gst_adapter_push (adapter, buffer); - while (offset < size) { + while (gst_adapter_available (adapter) >= codesize && res == GST_FLOW_OK) { GstBuffer *output; GstCaps *caps; + const guint8 *data; int consumed; - consumed = sbc_encode (&enc->sbc, data + offset, size - offset); - if (consumed <= 0) + data = gst_adapter_peek (adapter, codesize); + consumed = sbc_encode (&enc->sbc, (gpointer) data, codesize); + if (consumed <= 0) { + GST_ERROR ("comsumed < 0, codesize: %d", codesize); break; + } + gst_adapter_flush (adapter, consumed); caps = GST_PAD_CAPS (enc->srcpad); @@ -218,21 +278,25 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) if (res != GST_FLOW_OK) goto done; + if (!gst_caps_is_equal (caps, GST_BUFFER_CAPS (output))) + if (!gst_sbc_enc_change_caps (enc, GST_BUFFER_CAPS (output))) { + res = GST_FLOW_ERROR; + GST_ERROR_OBJECT (enc, "couldn't renegotiate caps"); + goto done; + } + memcpy (GST_BUFFER_DATA (output), enc->sbc.data, enc->sbc.len); GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); res = gst_pad_push (enc->srcpad, output); - if (res != GST_FLOW_OK) + if (res != GST_FLOW_OK) { + GST_ERROR_OBJECT (enc, "pad pushing failed"); goto done; + } - offset += consumed; } - if (offset < size) - res = GST_FLOW_ERROR; - done: - gst_buffer_unref (buffer); gst_object_unref (enc); return res; @@ -261,6 +325,17 @@ sbc_enc_change_state (GstElement * element, GstStateChange transition) 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) { @@ -339,6 +414,7 @@ gst_sbc_enc_class_init (GstSbcEncClass * 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); @@ -381,4 +457,6 @@ gst_sbc_enc_init (GstSbcEnc * self, GstSbcEncClass * klass) self->blocks = SBC_ENC_DEFAULT_BLOCKS; self->mode = SBC_ENC_DEFAULT_MODE; self->allocation = SBC_ENC_DEFAULT_ALLOCATION; + + self->adapter = gst_adapter_new (); } diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 0a95bcef2c..c5fc6bcc21 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -22,6 +22,7 @@ */ #include +#include #include "sbc.h" #include "ipc.h" @@ -48,6 +49,7 @@ struct _GstSbcEnc { GstPad *sinkpad; GstPad *srcpad; + GstAdapter *adapter; gint mode; gint blocks; diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index c876958d81..95af253e86 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -79,8 +79,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) value = gst_structure_get_value (structure, "rate"); if (GST_VALUE_HOLDS_LIST (value)) { temp = gst_sbc_select_rate_from_list (value); - } else if (GST_VALUE_HOLDS_INT_RANGE (value)) { - temp = gst_sbc_select_rate_from_range (value); } else { temp = g_value_get_int (value); } @@ -93,9 +91,7 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "channels"); - if (GST_VALUE_HOLDS_LIST (value)) { - temp = gst_sbc_select_channels_from_list (value); - } else if (GST_VALUE_HOLDS_INT_RANGE (value)) { + if (GST_VALUE_HOLDS_INT_RANGE (value)) { temp = gst_sbc_select_channels_from_range (value); } else { temp = g_value_get_int (value); @@ -111,8 +107,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) value = gst_structure_get_value (structure, "blocks"); if (GST_VALUE_HOLDS_LIST (value)) { temp = gst_sbc_select_blocks_from_list (value); - } else if (GST_VALUE_HOLDS_INT_RANGE (value)) { - temp = gst_sbc_select_blocks_from_range (value); } else { temp = g_value_get_int (value); } @@ -127,8 +121,6 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) value = gst_structure_get_value (structure, "subbands"); if (GST_VALUE_HOLDS_LIST (value)) { temp = gst_sbc_select_subbands_from_list (value); - } else if (GST_VALUE_HOLDS_INT_RANGE (value)) { - temp = gst_sbc_select_subbands_from_range (value); } else { temp = g_value_get_int (value); } diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 63f20fce86..6394799140 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -39,27 +39,6 @@ gst_sbc_select_rate_from_list (const GValue * value) return g_value_get_int (gst_value_list_get_value (value, size - 1)); } -/* - * Selects one rate from a range of possible rates - * TODO - use a better approach to this (it is selecting the maximum value) - */ -gint -gst_sbc_select_rate_from_range (const GValue * value) -{ - return gst_value_get_int_range_max (value); -} - -/* - * Selects one number of channels from a list of possible numbers - * TODO - use a better approach to this (it is selecting the last element) - */ -gint -gst_sbc_select_channels_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) @@ -81,16 +60,6 @@ gst_sbc_select_blocks_from_list (const GValue * value) return g_value_get_int (gst_value_list_get_value (value, size - 1)); } -/* - * Selects one blocks option from a range of possible blocks - * TODO - use a better approach to this (it is selecting the maximum value) - */ -gint -gst_sbc_select_blocks_from_range (const GValue * value) -{ - return gst_value_get_int_range_max (value); -} - /* * Selects one number of subbands from a list * TODO - use a better approach to this (it is selecting the last element) @@ -102,16 +71,6 @@ gst_sbc_select_subbands_from_list (const GValue * value) return g_value_get_int (gst_value_list_get_value (value, size - 1)); } -/* - * Selects one subbands option from a range - * TODO - use a better approach to this (it is selecting the maximum value) - */ -gint -gst_sbc_select_subbands_from_range (const GValue * value) -{ - return gst_value_get_int_range_max (value); -} - /* * Selects one bitpool option from a range * TODO - use a better approach to this (it is selecting the maximum value) @@ -202,8 +161,31 @@ gst_sbc_get_allocation_string (int alloc) case CFG_ALLOCATION_SNR: return "snr"; case CFG_ALLOCATION_AUTO: - return NULL; /* TODO what should be selected here? */ + return "loudness"; /* TODO what should be selected here? */ default: return NULL; } } + +GstCaps * +gst_sbc_caps_from_sbc (struct ipc_data_cfg * cfg, + struct ipc_codec_sbc * sbc, gint channels) +{ + GstCaps *caps; + const gchar *mode_str; + const gchar *allocation_str; + + mode_str = gst_sbc_get_mode_string (cfg->mode); + allocation_str = gst_sbc_get_allocation_string (sbc->allocation); + + caps = gst_caps_new_simple ("audio/x-sbc", + "rate", G_TYPE_INT, cfg->rate, + "channels", G_TYPE_INT, channels, + "mode", G_TYPE_STRING, mode_str, + "subbands", G_TYPE_INT, sbc->subbands, + "blocks", G_TYPE_INT, sbc->blocks, + "allocation", G_TYPE_STRING, allocation_str, + "bitpool", G_TYPE_INT, sbc->bitpool, NULL); + + return caps; +} diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 98f202f03b..33464a96d1 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -22,18 +22,20 @@ */ #include +#include "sbc.h" + +struct ipc_data_cfg; /* FIXME can't include ipc.h */ +struct ipc_codec_sbc; gint gst_sbc_select_rate_from_list(const GValue *value); -gint gst_sbc_select_rate_from_range(const GValue *value); -gint gst_sbc_select_channels_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_blocks_from_range(const GValue *value); gint gst_sbc_select_subbands_from_list(const GValue *value); -gint gst_sbc_select_subbands_from_range(const GValue *value); + +gint gst_sbc_select_bitpool_from_range(const GValue *value); gint gst_sbc_select_bitpool_from_range(const GValue *value); @@ -44,3 +46,6 @@ const gchar *gst_sbc_get_allocation_string(int alloc); const gchar *gst_sbc_get_mode_from_list(const GValue *value); gint gst_sbc_get_mode_int(const gchar *mode); const gchar *gst_sbc_get_mode_string(int joint); + +GstCaps* gst_sbc_caps_from_sbc(struct ipc_data_cfg *cfg, struct ipc_codec_sbc *sbc, + gint channels); From 97fcf537cd70a17777ea197dd1ccdfbc2227994d Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 12 Nov 2007 18:15:59 +0000 Subject: [PATCH 19/57] sbc: Make sbc codec to write directly in application buffers and so avoiding memcpys. --- ext/sbc/gstsbcdec.c | 16 +++++++++------- ext/sbc/gstsbcenc.c | 27 +++++++++++++++------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index a857032383..27386dd9e2 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -57,10 +57,11 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) { GstSbcDec *dec = GST_SBC_DEC (gst_pad_get_parent (pad)); GstFlowReturn res = GST_FLOW_OK; - guint size, offset = 0; + guint size, codesize, offset = 0; guint8 *data; GstClockTime timestamp; + codesize = sbc_get_codesize (&dec->sbc); timestamp = GST_BUFFER_TIMESTAMP (buffer); if (dec->buffer) { @@ -81,10 +82,6 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) GstCaps *caps, *temp; int consumed; - consumed = sbc_decode (&dec->sbc, data + offset, size - offset); - if (consumed <= 0) - break; - caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, dec->sbc.rate, "channels", G_TYPE_INT, dec->sbc.channels, NULL); @@ -96,14 +93,19 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) gst_caps_unref (caps); res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, - GST_BUFFER_OFFSET_NONE, dec->sbc.len, temp, &output); + GST_BUFFER_OFFSET_NONE, codesize, temp, &output); gst_caps_unref (temp); if (res != GST_FLOW_OK) goto done; - memcpy (GST_BUFFER_DATA (output), dec->sbc.data, dec->sbc.len); + consumed = sbc_decode (&dec->sbc, data + offset, size - offset, + GST_BUFFER_DATA (output), codesize, NULL); + if (consumed <= 0) + break; + + GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); res = gst_pad_push (dec->srcpad, output); if (res != GST_FLOW_OK) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 7b11d60f0b..2558fd1d0e 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -136,10 +136,11 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) enc->sbc.rate = rate; enc->sbc.channels = channels; - if (enc->mode == 0) - enc->sbc.joint = CFG_MODE_JOINT_STEREO; - else - enc->sbc.joint = enc->mode; + if (enc->mode == CFG_MODE_AUTO) + enc->mode = CFG_MODE_JOINT_STEREO; + + if (enc->mode == CFG_MODE_MONO || enc->mode == CFG_MODE_JOINT_STEREO) + enc->sbc.joint = 1; enc->sbc.blocks = enc->blocks; enc->sbc.subbands = enc->subbands; @@ -252,8 +253,10 @@ 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; - gint codesize = enc->sbc.subbands * enc->sbc.blocks * enc->sbc.channels * 2; + gint codesize, frame_len; + codesize = sbc_get_codesize (&enc->sbc); + frame_len = sbc_get_frame_length (&enc->sbc); gst_adapter_push (adapter, buffer); while (gst_adapter_available (adapter) >= codesize && res == GST_FLOW_OK) { @@ -262,19 +265,20 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) const guint8 *data; int consumed; + caps = GST_PAD_CAPS (enc->srcpad); + + res = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, + GST_BUFFER_OFFSET_NONE, frame_len, caps, &output); + data = gst_adapter_peek (adapter, codesize); - consumed = sbc_encode (&enc->sbc, (gpointer) data, codesize); + consumed = sbc_encode (&enc->sbc, (gpointer) data, codesize, + GST_BUFFER_DATA (output), frame_len, NULL); if (consumed <= 0) { GST_ERROR ("comsumed < 0, codesize: %d", codesize); break; } gst_adapter_flush (adapter, consumed); - caps = GST_PAD_CAPS (enc->srcpad); - - res = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, - GST_BUFFER_OFFSET_NONE, enc->sbc.len, caps, &output); - if (res != GST_FLOW_OK) goto done; @@ -285,7 +289,6 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) goto done; } - memcpy (GST_BUFFER_DATA (output), enc->sbc.data, enc->sbc.len); GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); res = gst_pad_push (enc->srcpad, output); From 946d5642925cd35b02946911aa98ed6fa2d6889a Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 12 Nov 2007 22:21:45 +0000 Subject: [PATCH 20/57] sbc: Fix bug in sbcenc when changing encoder parameters. --- ext/sbc/gstsbcenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 2558fd1d0e..45bc7213d4 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -218,6 +218,8 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) if (!(allocation = gst_structure_get_string (structure, "allocation"))) return FALSE; + sbc_finish (&enc->sbc); + sbc_init (&enc->sbc, 0); enc->sbc.rate = rate; enc->sbc.channels = channels; enc->blocks = blocks; From 2a21d83ce023f53bdef54b1ae1ec73e286a1a75f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 13 Nov 2007 20:04:12 +0000 Subject: [PATCH 21/57] sbc: Add sbc_reinit. --- ext/sbc/gstsbcenc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 45bc7213d4..d97794542d 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -218,8 +218,7 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) if (!(allocation = gst_structure_get_string (structure, "allocation"))) return FALSE; - sbc_finish (&enc->sbc); - sbc_init (&enc->sbc, 0); + sbc_reinit (&enc->sbc, 0); enc->sbc.rate = rate; enc->sbc.channels = channels; enc->blocks = blocks; From 742f9526881c6752b7d9a8cca824299f8468539b Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 21 Nov 2007 20:24:11 +0000 Subject: [PATCH 22/57] sbc: Integrate new ipc API implementation. --- ext/sbc/gstsbcenc.c | 281 ++++++++++++++++++++++++++++++++---------- ext/sbc/gstsbcenc.h | 4 +- ext/sbc/gstsbcparse.c | 51 ++++---- ext/sbc/gstsbcutil.c | 173 ++++++++++++++++++++++---- ext/sbc/gstsbcutil.h | 10 +- 5 files changed, 400 insertions(+), 119 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index d97794542d..51ea3f11f8 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -27,14 +27,17 @@ #include +#include "ipc.h" #include "gstsbcenc.h" #include "gstsbcutil.h" -#define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO -#define SBC_ENC_DEFAULT_BLOCKS 16 -#define SBC_ENC_DEFAULT_SUB_BANDS 8 -#define SBC_ENC_DEFAULT_BITPOOL 53 -#define SBC_ENC_DEFAULT_ALLOCATION CFG_ALLOCATION_AUTO +#define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_AUTO +#define SBC_ENC_DEFAULT_BLOCKS 0 +#define SBC_ENC_DEFAULT_SUB_BANDS 0 +#define SBC_ENC_DEFAULT_BITPOOL 0 +#define SBC_ENC_DEFAULT_ALLOCATION BT_A2DP_ALLOCATION_AUTO +#define SBC_ENC_DEFAULT_RATE 0 +#define SBC_ENC_DEFAULT_CHANNELS 0 GST_DEBUG_CATEGORY_STATIC (sbc_enc_debug); #define GST_CAT_DEFAULT sbc_enc_debug @@ -67,9 +70,9 @@ gst_sbc_allocation_get_type (void) { static GType sbc_allocation_type = 0; static GEnumValue sbc_allocations[] = { - {CFG_ALLOCATION_AUTO, "Auto", "auto"}, - {CFG_ALLOCATION_LOUDNESS, "Loudness", "loudness"}, - {CFG_ALLOCATION_SNR, "SNR", "snr"}, + {BT_A2DP_ALLOCATION_AUTO, "Auto", "auto"}, + {BT_A2DP_ALLOCATION_LOUDNESS, "Loudness", "loudness"}, + {BT_A2DP_ALLOCATION_SNR, "SNR", "snr"}, {-1, NULL, NULL} }; @@ -116,74 +119,195 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "allocation = (string) { snr, loudness }," "bitpool = (int) [ 2, 64 ]")); -static GstCaps * -sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) +gboolean gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps); + +static void +sbc_enc_set_structure_int_param (GstSbcEnc * enc, + GstStructure * structure, const gchar * field, gint field_value) +{ + GValue *value; + + value = g_new0 (GValue, 1); + value = g_value_init (value, G_TYPE_INT); + g_value_set_int (value, field_value); + gst_structure_set_value (structure, field, value); + g_free (value); +} + +static void +sbc_enc_set_structure_string_param (GstSbcEnc * enc, + GstStructure * structure, const gchar * field, const gchar * field_value) +{ + GValue *value; + + value = g_new0 (GValue, 1); + value = g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, field_value); + gst_structure_set_value (structure, field, value); + g_free (value); +} + +static GstCaps * +sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) { - gint rate; - gint channels; GstCaps *src_caps; GstStructure *structure; - const gchar *mode; - const gchar *allocation; + GEnumValue *enum_value; + GEnumClass *enum_class; + gchar *temp; - structure = gst_caps_get_structure (caps, 0); + src_caps = gst_caps_copy (gst_pad_get_pad_template_caps (enc->srcpad)); + structure = gst_caps_get_structure (src_caps, 0); - if (!gst_structure_get_int (structure, "rate", &rate)) - return NULL; - if (!gst_structure_get_int (structure, "channels", &channels)) - return NULL; + if (enc->rate != 0) + sbc_enc_set_structure_int_param (enc, structure, "rate", enc->rate); - enc->sbc.rate = rate; - enc->sbc.channels = channels; + if (enc->channels != 0) + sbc_enc_set_structure_int_param (enc, structure, "channels", enc->channels); - if (enc->mode == CFG_MODE_AUTO) - enc->mode = CFG_MODE_JOINT_STEREO; + if (enc->subbands != 0) + sbc_enc_set_structure_int_param (enc, structure, "subbands", enc->subbands); - if (enc->mode == CFG_MODE_MONO || enc->mode == CFG_MODE_JOINT_STEREO) - enc->sbc.joint = 1; + if (enc->blocks != 0) + sbc_enc_set_structure_int_param (enc, structure, "blocks", enc->blocks); - enc->sbc.blocks = enc->blocks; - enc->sbc.subbands = enc->subbands; - if (enc->allocation == 0) - enc->sbc.allocation = CFG_ALLOCATION_LOUDNESS; - else - enc->sbc.allocation = enc->allocation; + if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO) { + enum_class = g_type_class_ref (GST_TYPE_SBC_MODE); + enum_value = g_enum_get_value (enum_class, enc->mode); + sbc_enc_set_structure_string_param (enc, structure, "mode", + enum_value->value_nick); + g_type_class_unref (enum_class); + } - enc->sbc.bitpool = SBC_ENC_DEFAULT_BITPOOL; + if (enc->allocation != BT_A2DP_ALLOCATION_AUTO) { + enum_class = g_type_class_ref (GST_TYPE_SBC_ALLOCATION); + enum_value = g_enum_get_value (enum_class, enc->allocation); + sbc_enc_set_structure_string_param (enc, structure, "allocation", + enum_value->value_nick); + g_type_class_unref (enum_class); + } - mode = gst_sbc_get_mode_string (enc->sbc.joint); - allocation = gst_sbc_get_allocation_string (enc->sbc.allocation); - - src_caps = gst_caps_new_simple ("audio/x-sbc", - "rate", G_TYPE_INT, enc->sbc.rate, - "channels", G_TYPE_INT, enc->sbc.channels, - "mode", G_TYPE_STRING, mode, - "subbands", G_TYPE_INT, enc->sbc.subbands, - "blocks", G_TYPE_INT, enc->sbc.blocks, - "allocation", G_TYPE_STRING, allocation, - "bitpool", G_TYPE_INT, enc->sbc.bitpool, NULL); + temp = gst_caps_to_string (src_caps); + GST_DEBUG_OBJECT (enc, "Srcpad caps: %s", temp); + g_free (temp); 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) +{ + GstCaps *srcpad_caps; + GstCaps *temp_caps; + gboolean res = TRUE; + GstSbcEnc *enc = GST_SBC_ENC (GST_PAD_PARENT (pad)); + + GST_LOG_OBJECT (enc, "setting srcpad caps"); + + srcpad_caps = sbc_enc_generate_srcpad_caps (enc); + temp_caps = gst_caps_intersect (srcpad_caps, caps); + if (temp_caps == GST_CAPS_NONE) + res = FALSE; + + gst_caps_unref (temp_caps); + gst_caps_unref (srcpad_caps); + + g_return_val_if_fail (res, FALSE); + + 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_ERROR_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 *peer_caps; + GstCaps *src_caps; + GstCaps *caps; + gboolean res = TRUE; + GstCaps *result_caps = NULL; + + peer_caps = gst_pad_peer_get_caps (enc->srcpad); + if (!peer_caps) + return NULL; + + src_caps = sbc_enc_generate_srcpad_caps (enc); + caps = gst_caps_intersect (src_caps, peer_caps); + + 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 (src_caps); + gst_caps_unref (peer_caps); + 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 *othercaps; + GstCaps *src_caps; + gint rate, channels; + gboolean res; enc = GST_SBC_ENC (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); - othercaps = sbc_enc_generate_srcpad_caps (enc, caps); - if (othercaps == NULL) + if (!gst_structure_get_int (structure, "rate", &rate)) + goto error; + if (!gst_structure_get_int (structure, "channels", &channels)) goto error; - gst_pad_set_caps (enc->srcpad, othercaps); - gst_caps_unref (othercaps); + enc->rate = rate; + enc->channels = channels; - return TRUE; + src_caps = sbc_enc_get_fixed_srcpad_caps (enc); + if (!src_caps) + goto error; + res = gst_pad_set_caps (enc->srcpad, src_caps); + gst_caps_unref (src_caps); + + return res; error: GST_ERROR_OBJECT (enc, "invalid input caps"); @@ -218,14 +342,14 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) if (!(allocation = gst_structure_get_string (structure, "allocation"))) return FALSE; - sbc_reinit (&enc->sbc, 0); - enc->sbc.rate = rate; - enc->sbc.channels = channels; - enc->blocks = blocks; - enc->sbc.subbands = subbands; + enc->rate = enc->sbc.rate = rate; + enc->channels = enc->sbc.channels = channels; + enc->blocks = enc->sbc.blocks = blocks; + enc->subbands = enc->sbc.subbands = subbands; enc->sbc.bitpool = bitpool; - enc->mode = gst_sbc_get_mode_int (mode); - enc->allocation = gst_sbc_get_allocation_mode_int (allocation); + enc->mode = enc->sbc.joint = gst_sbc_get_mode_int (mode); + enc->allocation = enc->sbc.allocation = + gst_sbc_get_allocation_mode_int (allocation); return TRUE; } @@ -293,11 +417,8 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); res = gst_pad_push (enc->srcpad, output); - if (res != GST_FLOW_OK) { - GST_ERROR_OBJECT (enc, "pad pushing failed"); + if (res != GST_FLOW_OK) goto done; - } - } done: @@ -354,13 +475,32 @@ gst_sbc_enc_base_init (gpointer g_class) gst_element_class_set_details (element_class, &sbc_enc_details); } +static gboolean +sbc_enc_set_blocks (GstSbcEnc * enc, gint value) +{ + if (value != 4 && value != 8 && value != 12 && value != 16 && value != 0) + return FALSE; + enc->blocks = value; + return TRUE; +} + +static gboolean +sbc_enc_set_subbands (GstSbcEnc * enc, gint value) +{ + if (value != 4 && value != 8 && value != 0) + return FALSE; + enc->subbands = value; + return TRUE; +} + static void gst_sbc_enc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstSbcEnc *enc = GST_SBC_ENC (object); - /* TODO - CAN ONLY BE CHANGED ON READY AND BELOW */ + /* changes to those properties will only happen on the next caps + * negotiation */ switch (prop_id) { case PROP_MODE: @@ -370,12 +510,14 @@ gst_sbc_enc_set_property (GObject * object, guint prop_id, enc->allocation = g_value_get_enum (value); break; case PROP_BLOCKS: - /* TODO - verify consistency */ - enc->blocks = g_value_get_int (value); + if (!sbc_enc_set_blocks (enc, g_value_get_int (value))) + GST_WARNING_OBJECT (enc, "invalid value %d for " + "blocks property", g_value_get_int (value)); break; case PROP_SUBBANDS: - /* TODO - verify consistency */ - enc->subbands = g_value_get_int (value); + if (!sbc_enc_set_subbands (enc, g_value_get_int (value))) + GST_WARNING_OBJECT (enc, "invalid value %d for " + "subbands property", g_value_get_int (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -454,13 +596,20 @@ gst_sbc_enc_init (GstSbcEnc * self, GstSbcEncClass * klass) 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_chain_function (self->sinkpad, GST_DEBUG_FUNCPTR (sbc_enc_chain)); + 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->adapter = gst_adapter_new (); } diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index c5fc6bcc21..f65bcc9459 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -25,8 +25,6 @@ #include #include "sbc.h" -#include "ipc.h" - G_BEGIN_DECLS @@ -51,6 +49,8 @@ struct _GstSbcEnc { GstPad *srcpad; GstAdapter *adapter; + gint rate; + gint channels; gint mode; gint blocks; gint allocation; diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 95af253e86..93bae3aeee 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -57,6 +57,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "bitpool = (int) [ 2, 64 ]")); /* Creates a fixed caps from the caps given. */ +/* FIXME use gstsbcutil caps fixating function */ static GstCaps * sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) { @@ -68,6 +69,11 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) const gchar *allocation = NULL; const gchar *mode = NULL; const gchar *error_message = NULL; + gchar *str; + + str = gst_caps_to_string (caps); + GST_DEBUG_OBJECT (parse, "Parsing caps: %s", str); + g_free (str); structure = gst_caps_get_structure (caps, 0); @@ -77,11 +83,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "rate"); - if (GST_VALUE_HOLDS_LIST (value)) { + if (GST_VALUE_HOLDS_LIST (value)) temp = gst_sbc_select_rate_from_list (value); - } else { + else temp = g_value_get_int (value); - } rate = temp; } @@ -91,11 +96,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "channels"); - if (GST_VALUE_HOLDS_INT_RANGE (value)) { + if (GST_VALUE_HOLDS_INT_RANGE (value)) temp = gst_sbc_select_channels_from_range (value); - } else { + else temp = g_value_get_int (value); - } channels = temp; } @@ -105,11 +109,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "blocks"); - if (GST_VALUE_HOLDS_LIST (value)) { + if (GST_VALUE_HOLDS_LIST (value)) temp = gst_sbc_select_blocks_from_list (value); - } else { + else temp = g_value_get_int (value); - } blocks = temp; } @@ -119,11 +122,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "subbands"); - if (GST_VALUE_HOLDS_LIST (value)) { + if (GST_VALUE_HOLDS_LIST (value)) temp = gst_sbc_select_subbands_from_list (value); - } else { + else temp = g_value_get_int (value); - } subbands = temp; } @@ -133,11 +135,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "bitpool"); - if (GST_VALUE_HOLDS_INT_RANGE (value)) { + if (GST_VALUE_HOLDS_INT_RANGE (value)) temp = gst_sbc_select_bitpool_from_range (value); - } else { + else temp = g_value_get_int (value); - } bitpool = temp; } @@ -147,11 +148,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "allocation"); - if (GST_VALUE_HOLDS_LIST (value)) { + if (GST_VALUE_HOLDS_LIST (value)) allocation = gst_sbc_get_allocation_from_list (value); - } else { + else allocation = g_value_get_string (value); - } } if (!gst_structure_has_field (structure, "mode")) { @@ -160,11 +160,10 @@ sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) goto error; } else { value = gst_structure_get_value (structure, "mode"); - if (GST_VALUE_HOLDS_LIST (value)) { + if (GST_VALUE_HOLDS_LIST (value)) mode = gst_sbc_get_mode_from_list (value); - } else { + else mode = g_value_get_string (value); - } } error: @@ -205,9 +204,15 @@ sbc_parse_sink_setcaps (GstPad * pad, GstCaps * caps) other = gst_caps_new_any (); inter = gst_caps_intersect (caps, other); - srccaps = sbc_parse_select_caps (parse, inter); - if (srccaps == NULL) + if (gst_caps_is_empty (inter)) { + gst_caps_unref (inter); return FALSE; + } + srccaps = sbc_parse_select_caps (parse, inter); + if (srccaps == NULL) { + gst_caps_unref (inter); + return FALSE; + } gst_pad_set_caps (parse->srcpad, srccaps); diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 6394799140..b66a63be62 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -107,11 +107,11 @@ gint gst_sbc_get_allocation_mode_int (const gchar * allocation) { if (g_ascii_strcasecmp (allocation, "loudness") == 0) - return CFG_ALLOCATION_LOUDNESS; + return BT_A2DP_ALLOCATION_LOUDNESS; else if (g_ascii_strcasecmp (allocation, "snr") == 0) - return CFG_ALLOCATION_SNR; + return BT_A2DP_ALLOCATION_SNR; else if (g_ascii_strcasecmp (allocation, "auto") == 0) - return CFG_ALLOCATION_AUTO; + return BT_A2DP_ALLOCATION_AUTO; else return -1; } @@ -120,15 +120,15 @@ gint gst_sbc_get_mode_int (const gchar * mode) { if (g_ascii_strcasecmp (mode, "joint") == 0) - return CFG_MODE_JOINT_STEREO; + return BT_A2DP_CHANNEL_MODE_JOINT_STEREO; else if (g_ascii_strcasecmp (mode, "stereo") == 0) - return CFG_MODE_STEREO; + return BT_A2DP_CHANNEL_MODE_STEREO; else if (g_ascii_strcasecmp (mode, "dual") == 0) - return CFG_MODE_DUAL_CHANNEL; + return BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; else if (g_ascii_strcasecmp (mode, "mono") == 0) - return CFG_MODE_MONO; + return BT_A2DP_CHANNEL_MODE_MONO; else if (g_ascii_strcasecmp (mode, "auto") == 0) - return CFG_MODE_AUTO; + return BT_A2DP_CHANNEL_MODE_AUTO; else return -1; } @@ -137,15 +137,15 @@ const gchar * gst_sbc_get_mode_string (int joint) { switch (joint) { - case CFG_MODE_MONO: + case BT_A2DP_CHANNEL_MODE_MONO: return "mono"; - case CFG_MODE_DUAL_CHANNEL: + case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: return "dual"; - case CFG_MODE_STEREO: + case BT_A2DP_CHANNEL_MODE_STEREO: return "stereo"; - case CFG_MODE_JOINT_STEREO: + case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: return "joint"; - case CFG_MODE_AUTO: + case BT_A2DP_CHANNEL_MODE_AUTO: return NULL; /* TODO what should be selected here? */ default: return NULL; @@ -156,11 +156,11 @@ const gchar * gst_sbc_get_allocation_string (int alloc) { switch (alloc) { - case CFG_ALLOCATION_LOUDNESS: + case BT_A2DP_ALLOCATION_LOUDNESS: return "loudness"; - case CFG_ALLOCATION_SNR: + case BT_A2DP_ALLOCATION_SNR: return "snr"; - case CFG_ALLOCATION_AUTO: + case BT_A2DP_ALLOCATION_AUTO: return "loudness"; /* TODO what should be selected here? */ default: return NULL; @@ -168,24 +168,151 @@ gst_sbc_get_allocation_string (int alloc) } GstCaps * -gst_sbc_caps_from_sbc (struct ipc_data_cfg * cfg, - struct ipc_codec_sbc * sbc, gint channels) +gst_sbc_caps_from_sbc (sbc_capabilities_t * sbc, gint channels) { GstCaps *caps; const gchar *mode_str; const gchar *allocation_str; - mode_str = gst_sbc_get_mode_string (cfg->mode); - allocation_str = gst_sbc_get_allocation_string (sbc->allocation); + mode_str = gst_sbc_get_mode_string (sbc->channel_mode); + allocation_str = gst_sbc_get_allocation_string (sbc->allocation_method); caps = gst_caps_new_simple ("audio/x-sbc", - "rate", G_TYPE_INT, cfg->rate, + "rate", G_TYPE_INT, sbc->frequency, "channels", G_TYPE_INT, channels, "mode", G_TYPE_STRING, mode_str, "subbands", G_TYPE_INT, sbc->subbands, - "blocks", G_TYPE_INT, sbc->blocks, + "blocks", G_TYPE_INT, sbc->block_length, "allocation", G_TYPE_STRING, allocation_str, - "bitpool", G_TYPE_INT, sbc->bitpool, NULL); + "bitpool", G_TYPE_INT, sbc->max_bitpool, NULL); return caps; } + +/* + * Given a GstCaps, this will return a fixed GstCaps on sucessfull 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); + else + mode = g_value_get_string (value); + } + +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; +} diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 33464a96d1..4581abf720 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -22,10 +22,9 @@ */ #include -#include "sbc.h" -struct ipc_data_cfg; /* FIXME can't include ipc.h */ -struct ipc_codec_sbc; +#include "sbc.h" +#include "ipc.h" gint gst_sbc_select_rate_from_list(const GValue *value); @@ -47,5 +46,6 @@ const gchar *gst_sbc_get_mode_from_list(const GValue *value); gint gst_sbc_get_mode_int(const gchar *mode); const gchar *gst_sbc_get_mode_string(int joint); -GstCaps* gst_sbc_caps_from_sbc(struct ipc_data_cfg *cfg, struct ipc_codec_sbc *sbc, - gint channels); +GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels); + +GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message); From 6a34433dd8091f161435bb3caa6424f9f633d078 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 23 Nov 2007 17:00:13 +0000 Subject: [PATCH 23/57] sbc: Code cleanup. --- ext/sbc/gstsbcenc.c | 56 +++++++++++++-------------------------------- ext/sbc/gstsbcenc.h | 3 +++ 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 51ea3f11f8..5d7a804506 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -350,24 +350,11 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) enc->mode = enc->sbc.joint = gst_sbc_get_mode_int (mode); enc->allocation = enc->sbc.allocation = gst_sbc_get_allocation_mode_int (allocation); - - return TRUE; -} - -static gboolean -gst_sbc_enc_change_caps (GstSbcEnc * enc, GstCaps * caps) -{ - GST_INFO_OBJECT (enc, "Changing srcpad caps (renegotiation)"); - - if (!gst_pad_accept_caps (enc->srcpad, caps)) { - GST_WARNING_OBJECT (enc, "Src pad refused caps"); - return FALSE; - } - - if (!gst_sbc_enc_fill_sbc_params (enc, caps)) { - GST_ERROR_OBJECT (enc, "couldn't get sbc parameters from caps"); - return FALSE; - } + 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 ("codesize: %d, frame_length: %d, frame_duration: %d", + enc->codesize, enc->frame_length, enc->frame_duration); return TRUE; } @@ -378,41 +365,30 @@ 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; - gint codesize, frame_len; - codesize = sbc_get_codesize (&enc->sbc); - frame_len = sbc_get_frame_length (&enc->sbc); gst_adapter_push (adapter, buffer); - while (gst_adapter_available (adapter) >= codesize && res == GST_FLOW_OK) { + while (gst_adapter_available (adapter) >= enc->codesize && res == GST_FLOW_OK) { GstBuffer *output; GstCaps *caps; const guint8 *data; int consumed; caps = GST_PAD_CAPS (enc->srcpad); - res = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, - GST_BUFFER_OFFSET_NONE, frame_len, caps, &output); - - data = gst_adapter_peek (adapter, codesize); - consumed = sbc_encode (&enc->sbc, (gpointer) data, codesize, - GST_BUFFER_DATA (output), frame_len, NULL); - if (consumed <= 0) { - GST_ERROR ("comsumed < 0, codesize: %d", codesize); - break; - } - gst_adapter_flush (adapter, consumed); - + GST_BUFFER_OFFSET_NONE, enc->frame_length, caps, &output); if (res != GST_FLOW_OK) goto done; - if (!gst_caps_is_equal (caps, GST_BUFFER_CAPS (output))) - if (!gst_sbc_enc_change_caps (enc, GST_BUFFER_CAPS (output))) { - res = GST_FLOW_ERROR; - GST_ERROR_OBJECT (enc, "couldn't renegotiate caps"); - 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_ERROR ("comsumed < 0, codesize: %d", enc->codesize); + break; + } + gst_adapter_flush (adapter, consumed); GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index f65bcc9459..d81428c914 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -55,6 +55,9 @@ struct _GstSbcEnc { gint blocks; gint allocation; gint subbands; + gint codesize; + gint frame_length; + gint frame_duration; sbc_t sbc; }; From 76c77b1c60ec9e19afd0255fa57d0db2769b1d2e Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 23 Jan 2008 13:14:02 +0000 Subject: [PATCH 24/57] sbc: Make a2dpsink to act like a bin and split the payloader. --- ext/sbc/gstsbcdec.c | 7 ++ ext/sbc/gstsbcdec.h | 2 + ext/sbc/gstsbcenc.c | 111 ++++++------------- ext/sbc/gstsbcenc.h | 2 + ext/sbc/gstsbcparse.c | 241 +++++++++++++++--------------------------- ext/sbc/gstsbcparse.h | 5 + ext/sbc/gstsbcutil.c | 103 ++++++++++++++++++ ext/sbc/gstsbcutil.h | 18 ++++ 8 files changed, 257 insertions(+), 232 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 27386dd9e2..b3378580c6 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -192,3 +192,10 @@ gst_sbc_dec_init (GstSbcDec * self, GstSbcDecClass * klass) self->srcpad = gst_pad_new_from_static_template (&sbc_dec_src_factory, "src"); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); } + +gboolean +gst_sbc_dec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "sbcdec", + GST_RANK_PRIMARY, GST_TYPE_SBC_DEC); +} diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index 4a6922a090..0bb0b57e2d 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -58,4 +58,6 @@ struct _GstSbcDecClass { GType gst_sbc_dec_get_type(void); +gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin); + G_END_DECLS diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 5d7a804506..325a956943 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -121,32 +121,6 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, gboolean gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps); -static void -sbc_enc_set_structure_int_param (GstSbcEnc * enc, - GstStructure * structure, const gchar * field, gint field_value) -{ - GValue *value; - - value = g_new0 (GValue, 1); - value = g_value_init (value, G_TYPE_INT); - g_value_set_int (value, field_value); - gst_structure_set_value (structure, field, value); - g_free (value); -} - -static void -sbc_enc_set_structure_string_param (GstSbcEnc * enc, - GstStructure * structure, const gchar * field, const gchar * field_value) -{ - GValue *value; - - value = g_new0 (GValue, 1); - value = g_value_init (value, G_TYPE_STRING); - g_value_set_string (value, field_value); - gst_structure_set_value (structure, field, value); - g_free (value); -} - static GstCaps * sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) { @@ -155,41 +129,48 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) GEnumValue *enum_value; GEnumClass *enum_class; gchar *temp; + 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) - sbc_enc_set_structure_int_param (enc, structure, "rate", enc->rate); + gst_sbc_util_set_structure_int_param (structure, "rate", enc->rate, value); if (enc->channels != 0) - sbc_enc_set_structure_int_param (enc, structure, "channels", enc->channels); + gst_sbc_util_set_structure_int_param (structure, "channels", + enc->channels, value); if (enc->subbands != 0) - sbc_enc_set_structure_int_param (enc, structure, "subbands", enc->subbands); + gst_sbc_util_set_structure_int_param (structure, "subbands", + enc->subbands, value); if (enc->blocks != 0) - sbc_enc_set_structure_int_param (enc, structure, "blocks", enc->blocks); + gst_sbc_util_set_structure_int_param (structure, "blocks", + enc->blocks, value); if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO) { enum_class = g_type_class_ref (GST_TYPE_SBC_MODE); enum_value = g_enum_get_value (enum_class, enc->mode); - sbc_enc_set_structure_string_param (enc, structure, "mode", - enum_value->value_nick); + gst_sbc_util_set_structure_string_param (structure, "mode", + enum_value->value_nick, value); g_type_class_unref (enum_class); } if (enc->allocation != BT_A2DP_ALLOCATION_AUTO) { enum_class = g_type_class_ref (GST_TYPE_SBC_ALLOCATION); enum_value = g_enum_get_value (enum_class, enc->allocation); - sbc_enc_set_structure_string_param (enc, structure, "allocation", - enum_value->value_nick); + gst_sbc_util_set_structure_string_param (structure, "allocation", + enum_value->value_nick, value); g_type_class_unref (enum_class); } temp = gst_caps_to_string (src_caps); GST_DEBUG_OBJECT (enc, "Srcpad caps: %s", temp); g_free (temp); + g_free (value); return src_caps; } @@ -207,23 +188,10 @@ sbc_enc_src_getcaps (GstPad * pad) static gboolean sbc_enc_src_setcaps (GstPad * pad, GstCaps * caps) { - GstCaps *srcpad_caps; - GstCaps *temp_caps; - gboolean res = TRUE; GstSbcEnc *enc = GST_SBC_ENC (GST_PAD_PARENT (pad)); GST_LOG_OBJECT (enc, "setting srcpad caps"); - srcpad_caps = sbc_enc_generate_srcpad_caps (enc); - temp_caps = gst_caps_intersect (srcpad_caps, caps); - if (temp_caps == GST_CAPS_NONE) - res = FALSE; - - gst_caps_unref (temp_caps); - gst_caps_unref (srcpad_caps); - - g_return_val_if_fail (res, FALSE); - return gst_sbc_enc_fill_sbc_params (enc, caps); } @@ -317,39 +285,16 @@ error: gboolean gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, 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)) + if (!gst_sbc_util_fill_sbc_params (&enc->sbc, caps)) return FALSE; - if (!(mode = gst_structure_get_string (structure, "mode"))) - return FALSE; - if (!(allocation = gst_structure_get_string (structure, "allocation"))) - return FALSE; - - enc->rate = enc->sbc.rate = rate; - enc->channels = enc->sbc.channels = channels; - enc->blocks = enc->sbc.blocks = blocks; - enc->subbands = enc->sbc.subbands = subbands; - enc->sbc.bitpool = bitpool; - enc->mode = enc->sbc.joint = gst_sbc_get_mode_int (mode); - enc->allocation = enc->sbc.allocation = - gst_sbc_get_allocation_mode_int (allocation); + enc->rate = enc->sbc.rate; + enc->channels = enc->sbc.channels; + enc->blocks = enc->sbc.blocks; + enc->subbands = enc->sbc.subbands; + enc->mode = enc->sbc.joint; + enc->allocation = enc->sbc.allocation; 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); @@ -391,6 +336,8 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) 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) @@ -587,5 +534,15 @@ gst_sbc_enc_init (GstSbcEnc * self, GstSbcEncClass * klass) self->rate = SBC_ENC_DEFAULT_RATE; self->channels = SBC_ENC_DEFAULT_CHANNELS; + 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/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index d81428c914..c7b216385f 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -68,4 +68,6 @@ struct _GstSbcEncClass { GType gst_sbc_enc_get_type(void); +gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin); + G_END_DECLS diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 93bae3aeee..acc002c9d5 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -56,171 +56,86 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "allocation = (string) { snr, loudness }," "bitpool = (int) [ 2, 64 ]")); -/* Creates a fixed caps from the caps given. */ -/* FIXME use gstsbcutil caps fixating function */ -static GstCaps * -sbc_parse_select_caps (GstSbcParse * parse, GstCaps * caps) -{ - 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; - const gchar *error_message = NULL; - gchar *str; - - str = gst_caps_to_string (caps); - GST_DEBUG_OBJECT (parse, "Parsing caps: %s", str); - g_free (str); - - structure = gst_caps_get_structure (caps, 0); - - if (!gst_structure_has_field (structure, "rate")) { - error = TRUE; - error_message = "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 = "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 = "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 = "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 = "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 = "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 = "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); - else - mode = g_value_get_string (value); - } - -error: - if (error) { - GST_ERROR_OBJECT (parse, "Invalid input caps: %s", error_message); - 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); - parse->sbc.rate = rate; - parse->sbc.channels = channels; - parse->sbc.blocks = blocks; - parse->sbc.subbands = subbands; - parse->sbc.bitpool = bitpool; - parse->sbc.joint = gst_sbc_get_mode_int (mode); - parse->sbc.allocation = gst_sbc_get_allocation_mode_int (allocation); - - return result; -} - static gboolean sbc_parse_sink_setcaps (GstPad * pad, GstCaps * caps) { GstSbcParse *parse; - GstCaps *inter, *other, *srccaps; + GstStructure *structure; + gint rate, channels; parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); - other = gst_pad_peer_get_caps (parse->srcpad); - if (other == NULL) - other = gst_caps_new_any (); + structure = gst_caps_get_structure (caps, 0); - inter = gst_caps_intersect (caps, other); - if (gst_caps_is_empty (inter)) { - gst_caps_unref (inter); + if (!gst_structure_get_int (structure, "rate", &rate)) return FALSE; - } - srccaps = sbc_parse_select_caps (parse, inter); - if (srccaps == NULL) { - gst_caps_unref (inter); + + if (!gst_structure_get_int (structure, "channels", &channels)) return FALSE; - } - gst_pad_set_caps (parse->srcpad, srccaps); + if (!(parse->rate == 0 || rate == parse->rate)) + return FALSE; - gst_caps_unref (inter); - gst_caps_unref (other); - gst_caps_unref (srccaps); + if (!(parse->channels == 0 || channels == parse->channels)) + return FALSE; - return TRUE; + parse->rate = rate; + parse->channels = channels; + + return gst_sbc_util_fill_sbc_params (&parse->sbc, caps); +} + +static GstCaps * +sbc_parse_src_getcaps (GstPad * pad) +{ + GstCaps *caps; + const GstCaps *allowed_caps; + GstStructure *structure; + GValue *value; + GstSbcParse *parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); + + allowed_caps = gst_pad_get_allowed_caps (pad); + if (allowed_caps == NULL) + allowed_caps = gst_pad_get_pad_template_caps (pad); + caps = gst_caps_copy (allowed_caps); + + value = g_new0 (GValue, 1); + + structure = gst_caps_get_structure (caps, 0); + + if (parse->rate != 0) + gst_sbc_util_set_structure_int_param (structure, "rate", + parse->rate, value); + if (parse->channels != 0) + gst_sbc_util_set_structure_int_param (structure, "channels", + parse->channels, value); + + g_free (value); + + return caps; +} + +static gboolean +sbc_parse_src_acceptcaps (GstPad * pad, GstCaps * caps) +{ + GstStructure *structure; + GstSbcParse *parse; + gint rate, channels; + + parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "rate", &rate)) + return FALSE; + if (!gst_structure_get_int (structure, "channels", &channels)) + return FALSE; + + if ((parse->rate == 0 || parse->rate == rate) + && (parse->channels == 0 || parse->channels == channels)) + return TRUE; + + return FALSE; } static GstFlowReturn @@ -235,11 +150,13 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) timestamp = GST_BUFFER_TIMESTAMP (buffer); if (parse->buffer) { - GstBuffer *temp = 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 (temp); + GST_BUFFER_SIZE (parse->buffer) + + GST_BUFFER_SIZE (buffer)); gst_buffer_unref (parse->buffer); + gst_buffer_unref (temp); parse->buffer = NULL; } @@ -299,11 +216,13 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG ("Finish subband codec"); + if (parse->buffer) { gst_buffer_unref (parse->buffer); parse->buffer = NULL; } sbc_finish (&parse->sbc); + break; default: @@ -353,5 +272,17 @@ gst_sbc_parse_init (GstSbcParse * self, GstSbcParseClass * klass) self->srcpad = gst_pad_new_from_static_template (&sbc_parse_src_factory, "src"); + gst_pad_set_getcaps_function (self->srcpad, + GST_DEBUG_FUNCPTR (sbc_parse_src_getcaps)); + gst_pad_set_acceptcaps_function (self->srcpad, + GST_DEBUG_FUNCPTR (sbc_parse_src_acceptcaps)); + /* FIXME get encoding parameters on set caps */ gst_element_add_pad (GST_ELEMENT (self), self->srcpad); } + +gboolean +gst_sbc_parse_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "sbcparse", + GST_RANK_NONE, GST_TYPE_SBC_PARSE); +} diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index ceaf21977f..eb9ca4418f 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -50,6 +50,9 @@ struct _GstSbcParse { GstBuffer *buffer; sbc_t sbc; + + gint channels; + gint rate; }; struct _GstSbcParseClass { @@ -58,4 +61,6 @@ struct _GstSbcParseClass { GType gst_sbc_parse_get_type(void); +gboolean gst_sbc_parse_plugin_init(GstPlugin *plugin); + G_END_DECLS diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index b66a63be62..a63fe9ded3 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -26,6 +26,7 @@ #endif #include "ipc.h" +#include #include "gstsbcutil.h" /* @@ -316,3 +317,105 @@ error: 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; + + sbc->rate = rate; + sbc->channels = channels; + sbc->blocks = blocks; + sbc->subbands = subbands; + sbc->bitpool = bitpool; + sbc->joint = gst_sbc_get_mode_int (mode); + sbc->allocation = gst_sbc_get_allocation_mode_int (allocation); + + return TRUE; +} + +gint +gst_sbc_util_calc_frame_len (gint subbands, gint channels, + gint blocks, gint bitpool, gint channel_mode) +{ + gint len; + gint join; + len = 4 + (4 * subbands * channels) / 8; + + if (channel_mode == BT_A2DP_CHANNEL_MODE_MONO || + channel_mode == BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) + len += ((blocks * channels * bitpool) + 7) / 8; + else { + join = channel_mode == BT_A2DP_CHANNEL_MODE_JOINT_STEREO ? 1 : 0; + len += ((join * subbands + blocks * bitpool) + 7) / 8; + } + + return len; +} + +gint +gst_sbc_util_calc_bitrate (gint frame_len, gint rate, gint subbands, + gint blocks) +{ + return (((frame_len * 8 * rate / subbands) / blocks) / 1000); +} + +gint64 +gst_sbc_util_calc_frame_duration (gint rate, gint blocks, gint subbands) +{ + gint64 res = 1000000; + return res * blocks * subbands / rate; +} diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 4581abf720..40b9eae73e 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -49,3 +49,21 @@ const gchar *gst_sbc_get_mode_string(int joint); GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels); 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); + +gint gst_sbc_util_calc_frame_len(gint subbands, gint channels, + gint blocks, gint bitpool, gint channel_mode); + +gint gst_sbc_util_calc_bitrate(gint frame_len, gint rate, gint subbands, + gint blocks); + +gint64 gst_sbc_util_calc_frame_duration(gint rate, gint blocks, gint subbands); From 84dcb6bb349d9ff825735416a878182d29bc9d20 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 23 Jan 2008 13:19:32 +0000 Subject: [PATCH 25/57] sbc: Add mp3 support for gstreamer plugin. --- ext/sbc/gstsbcutil.c | 73 +++++++++++++++++++++++++++++++++++++++++--- ext/sbc/gstsbcutil.h | 1 + 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index a63fe9ded3..0ecd848099 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -95,13 +95,23 @@ gst_sbc_get_allocation_from_list (const GValue * value) /* * Selects one mode from the ones on the list - * TODO - use a better aproach */ const gchar * -gst_sbc_get_mode_from_list (const GValue * value) +gst_sbc_get_mode_from_list (const GValue * list) { - guint size = gst_value_list_get_size (value); - return g_value_get_string (gst_value_list_get_value (value, size - 1)); + int i; + const GValue *value; + const gchar *aux; + + guint size = gst_value_list_get_size (list); + for (i = 0; i < size; i++) { + value = gst_value_list_get_value (list, i); + aux = g_value_get_string (value); + if (strcmp ("stereo", aux) == 0) { + return "stereo"; + } + } + return g_value_get_string (gst_value_list_get_value (list, size - 1)); } gint @@ -168,6 +178,61 @@ gst_sbc_get_allocation_string (int alloc) } } +/* channel mode */ +#define SBC_CM_MONO 0x00 +#define SBC_CM_DUAL_CHANNEL 0x01 +#define SBC_CM_STEREO 0x02 +#define SBC_CM_JOINT_STEREO 0x03 + +/* allocation mode */ +#define SBC_AM_LOUDNESS 0x00 +#define SBC_AM_SNR 0x01 + +const gchar * +gst_sbc_get_mode_string_from_sbc_t (int channels, int joint) +{ + if (channels == 2 && joint == 1) + return "joint"; + else if (channels == 2 && joint == 0) + return "stereo"; + else + return NULL; +} + +const gchar * +gst_sbc_get_allocation_string_from_sbc_t (int alloc) +{ + switch (alloc) { + case SBC_AM_LOUDNESS: + return "loudness"; + case SBC_AM_SNR: + return "snr"; + default: + return NULL; + } +} + +GstCaps * +gst_sbc_parse_caps_from_sbc (sbc_t * sbc) +{ + GstCaps *caps; + const gchar *mode_str; + const gchar *allocation_str; + + mode_str = gst_sbc_get_mode_string_from_sbc_t (sbc->channels, sbc->joint); + allocation_str = gst_sbc_get_allocation_string_from_sbc_t (sbc->allocation); + caps = gst_caps_new_simple ("audio/x-sbc", + "rate", G_TYPE_INT, sbc->rate, + "channels", G_TYPE_INT, sbc->channels, + "mode", G_TYPE_STRING, mode_str, + "subbands", G_TYPE_INT, sbc->subbands, + "blocks", G_TYPE_INT, sbc->blocks, + "allocation", G_TYPE_STRING, allocation_str, + "bitpool", G_TYPE_INT, sbc->bitpool, NULL); + + return caps; +} + GstCaps * gst_sbc_caps_from_sbc (sbc_capabilities_t * sbc, gint channels) { diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 40b9eae73e..47ec349398 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -47,6 +47,7 @@ gint gst_sbc_get_mode_int(const gchar *mode); const gchar *gst_sbc_get_mode_string(int joint); GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels); +GstCaps* gst_sbc_parse_caps_from_sbc(sbc_t *sbc); GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message); From ad24bafb6230037dfb3cd21cbce75419e83838f2 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 24 Jan 2008 14:25:29 +0000 Subject: [PATCH 26/57] sbc: Fix gtreamer payloader sending fragmented frames. --- ext/sbc/gstsbcutil.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 0ecd848099..98ed7bc595 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -107,8 +107,8 @@ gst_sbc_get_mode_from_list (const GValue * list) for (i = 0; i < size; i++) { value = gst_value_list_get_value (list, i); aux = g_value_get_string (value); - if (strcmp ("stereo", aux) == 0) { - return "stereo"; + if (strcmp ("joint", aux) == 0) { + return "joint"; } } return g_value_get_string (gst_value_list_get_value (list, size - 1)); @@ -144,6 +144,20 @@ gst_sbc_get_mode_int (const gchar * mode) return -1; } +/* FIXME add dual when sbc_t supports it */ +gboolean +gst_sbc_get_mode_int_for_sbc_t (const gchar * mode) +{ + if (g_ascii_strcasecmp (mode, "joint") == 0) + return TRUE; + else if (g_ascii_strcasecmp (mode, "stereo") == 0) + return FALSE; + else if (g_ascii_strcasecmp (mode, "mono") == 0) + return FALSE; + else + return -1; +} + const gchar * gst_sbc_get_mode_string (int joint) { @@ -195,6 +209,8 @@ gst_sbc_get_mode_string_from_sbc_t (int channels, int joint) return "joint"; else if (channels == 2 && joint == 0) return "stereo"; + else if (channels == 1 && joint == 0) + return "mono"; else return NULL; } @@ -446,7 +462,7 @@ gst_sbc_util_fill_sbc_params (sbc_t * sbc, GstCaps * caps) sbc->blocks = blocks; sbc->subbands = subbands; sbc->bitpool = bitpool; - sbc->joint = gst_sbc_get_mode_int (mode); + sbc->joint = gst_sbc_get_mode_int_for_sbc_t (mode); sbc->allocation = gst_sbc_get_allocation_mode_int (allocation); return TRUE; From 2a5e58f44fcb18aef9b37991cbb8e5c257bbe83b Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 30 Jan 2008 14:21:43 +0000 Subject: [PATCH 27/57] sbc: Fixes gstreamer caps and code cleanup. --- ext/sbc/gstsbcdec.c | 42 ++++++++++++------- ext/sbc/gstsbcdec.h | 3 ++ ext/sbc/gstsbcparse.c | 93 +------------------------------------------ ext/sbc/gstsbcutil.c | 9 +++-- 4 files changed, 38 insertions(+), 109 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index b3378580c6..2005d6870d 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -79,23 +79,11 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) while (offset < size) { GstBuffer *output; GstPadTemplate *template; - GstCaps *caps, *temp; + GstCaps *caps; int consumed; - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, dec->sbc.rate, - "channels", G_TYPE_INT, dec->sbc.channels, NULL); - - template = gst_static_pad_template_get (&sbc_dec_src_factory); - - temp = gst_caps_intersect (caps, gst_pad_template_get_caps (template)); - - gst_caps_unref (caps); - res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, - GST_BUFFER_OFFSET_NONE, codesize, temp, &output); - - gst_caps_unref (temp); + GST_BUFFER_OFFSET_NONE, codesize, NULL, &output); if (res != GST_FLOW_OK) goto done; @@ -105,7 +93,24 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) if (consumed <= 0) break; - GST_BUFFER_TIMESTAMP (output) = GST_BUFFER_TIMESTAMP (buffer); + /* we will reuse the same caps object */ + if (dec->outcaps == NULL) { + caps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, dec->sbc.rate, + "channels", G_TYPE_INT, dec->sbc.channels, NULL); + + template = gst_static_pad_template_get (&sbc_dec_src_factory); + + dec->outcaps = gst_caps_intersect (caps, + gst_pad_template_get_caps (template)); + + gst_caps_unref (caps); + } + + gst_buffer_set_caps (output, dec->outcaps); + + /* FIXME get a real timestamp */ + GST_BUFFER_TIMESTAMP (output) = GST_CLOCK_TIME_NONE; res = gst_pad_push (dec->srcpad, output); if (res != GST_FLOW_OK) @@ -137,6 +142,7 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) dec->buffer = NULL; } sbc_init (&dec->sbc, 0); + dec->outcaps = NULL; break; case GST_STATE_CHANGE_PAUSED_TO_READY: @@ -146,6 +152,10 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) dec->buffer = NULL; } sbc_finish (&dec->sbc); + if (dec->outcaps) { + gst_caps_unref (dec->outcaps); + dec->outcaps = NULL; + } break; default: @@ -191,6 +201,8 @@ gst_sbc_dec_init (GstSbcDec * self, GstSbcDecClass * klass) self->srcpad = gst_pad_new_from_static_template (&sbc_dec_src_factory, "src"); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + + self->outcaps = NULL; } gboolean diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index 0bb0b57e2d..a88f8da540 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -49,6 +49,9 @@ struct _GstSbcDec { GstBuffer *buffer; + /* caps for outgoing buffers */ + GstCaps *outcaps; + sbc_t sbc; }; diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index acc002c9d5..16507abcde 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -43,7 +43,7 @@ GST_ELEMENT_DETAILS ("Bluetooth SBC parser", static GstStaticPadTemplate sbc_parse_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-sbc")); + GST_STATIC_CAPS ("audio/x-sbc," "parsed = (boolean) false")); static GstStaticPadTemplate sbc_parse_src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -54,89 +54,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }," - "bitpool = (int) [ 2, 64 ]")); - -static gboolean -sbc_parse_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstSbcParse *parse; - GstStructure *structure; - gint rate, channels; - - parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); - - structure = gst_caps_get_structure (caps, 0); - - if (!gst_structure_get_int (structure, "rate", &rate)) - return FALSE; - - if (!gst_structure_get_int (structure, "channels", &channels)) - return FALSE; - - if (!(parse->rate == 0 || rate == parse->rate)) - return FALSE; - - if (!(parse->channels == 0 || channels == parse->channels)) - return FALSE; - - parse->rate = rate; - parse->channels = channels; - - return gst_sbc_util_fill_sbc_params (&parse->sbc, caps); -} - -static GstCaps * -sbc_parse_src_getcaps (GstPad * pad) -{ - GstCaps *caps; - const GstCaps *allowed_caps; - GstStructure *structure; - GValue *value; - GstSbcParse *parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); - - allowed_caps = gst_pad_get_allowed_caps (pad); - if (allowed_caps == NULL) - allowed_caps = gst_pad_get_pad_template_caps (pad); - caps = gst_caps_copy (allowed_caps); - - value = g_new0 (GValue, 1); - - structure = gst_caps_get_structure (caps, 0); - - if (parse->rate != 0) - gst_sbc_util_set_structure_int_param (structure, "rate", - parse->rate, value); - if (parse->channels != 0) - gst_sbc_util_set_structure_int_param (structure, "channels", - parse->channels, value); - - g_free (value); - - return caps; -} - -static gboolean -sbc_parse_src_acceptcaps (GstPad * pad, GstCaps * caps) -{ - GstStructure *structure; - GstSbcParse *parse; - gint rate, channels; - - parse = GST_SBC_PARSE (GST_PAD_PARENT (pad)); - - structure = gst_caps_get_structure (caps, 0); - - if (!gst_structure_get_int (structure, "rate", &rate)) - return FALSE; - if (!gst_structure_get_int (structure, "channels", &channels)) - return FALSE; - - if ((parse->rate == 0 || parse->rate == rate) - && (parse->channels == 0 || parse->channels == channels)) - return TRUE; - - return FALSE; -} + "bitpool = (int) [ 2, 64 ]," "parsed = (boolean) true")); static GstFlowReturn sbc_parse_chain (GstPad * pad, GstBuffer * buffer) @@ -266,17 +184,10 @@ gst_sbc_parse_init (GstSbcParse * self, GstSbcParseClass * klass) 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_pad_set_setcaps_function (self->sinkpad, - GST_DEBUG_FUNCPTR (sbc_parse_sink_setcaps)); gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); self->srcpad = gst_pad_new_from_static_template (&sbc_parse_src_factory, "src"); - gst_pad_set_getcaps_function (self->srcpad, - GST_DEBUG_FUNCPTR (sbc_parse_src_getcaps)); - gst_pad_set_acceptcaps_function (self->srcpad, - GST_DEBUG_FUNCPTR (sbc_parse_src_acceptcaps)); - /* FIXME get encoding parameters on set caps */ gst_element_add_pad (GST_ELEMENT (self), self->srcpad); } diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 98ed7bc595..2bebdcb7f7 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -377,9 +377,12 @@ gst_sbc_util_caps_fixate (GstCaps * caps, gchar ** error_message) goto error; } else { value = gst_structure_get_value (structure, "mode"); - if (GST_VALUE_HOLDS_LIST (value)) - mode = gst_sbc_get_mode_from_list (value); - else + if (GST_VALUE_HOLDS_LIST (value)) { + if (channels == 1) + mode = "mono"; + else + mode = gst_sbc_get_mode_from_list (value); + } else mode = g_value_get_string (value); } From 10325f3604cbdc9a2f0e15ff0b9d0fe1774bfe58 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 30 Jan 2008 17:30:27 +0000 Subject: [PATCH 28/57] sbc: Enable gstreamer plugin to use autoconnect flag. --- ext/sbc/gstsbcparse.c | 39 ++++++++++++++++++++++++++++++--------- ext/sbc/gstsbcparse.h | 3 +++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 16507abcde..446fb98652 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -67,6 +67,7 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) timestamp = GST_BUFFER_TIMESTAMP (buffer); + /* FIXME use a gstadpter */ if (parse->buffer) { GstBuffer *temp; temp = buffer; @@ -83,17 +84,26 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) while (offset < size) { GstBuffer *output; - GstCaps *temp; int consumed; - consumed = sbc_parse (&parse->sbc, data + offset, size - offset); + consumed = sbc_parse (&parse->new_sbc, data + offset, size - offset); if (consumed <= 0) break; - temp = GST_PAD_CAPS (parse->srcpad); + 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, temp, &output); + GST_BUFFER_OFFSET_NONE, consumed, parse->outcaps, &output); if (res != GST_FLOW_OK) goto done; @@ -125,10 +135,11 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: GST_DEBUG ("Setup subband codec"); - if (parse->buffer) { - gst_buffer_unref (parse->buffer); - parse->buffer = NULL; - } + + parse->channels = -1; + parse->rate = -1; + parse->first_parsing = TRUE; + sbc_init (&parse->sbc, 0); break; @@ -139,8 +150,12 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) gst_buffer_unref (parse->buffer); parse->buffer = NULL; } - sbc_finish (&parse->sbc); + if (parse->outcaps != NULL) { + gst_caps_unref (parse->outcaps); + parse->outcaps = NULL; + } + sbc_finish (&parse->sbc); break; default: @@ -189,6 +204,12 @@ gst_sbc_parse_init (GstSbcParse * self, GstSbcParseClass * klass) 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 diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index eb9ca4418f..a71aea729e 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -50,6 +50,9 @@ struct _GstSbcParse { GstBuffer *buffer; sbc_t sbc; + sbc_t new_sbc; + GstCaps *outcaps; + gboolean first_parsing; gint channels; gint rate; From 937066575a24556687e47aef27a7f8993484e2ba Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 1 Feb 2008 19:28:37 +0000 Subject: [PATCH 29/57] sbc: Add bitpool property and others fixes for gstreamer plugin. --- ext/sbc/gstsbcenc.c | 177 ++++++++++++++++++++++++++++--------------- ext/sbc/gstsbcenc.h | 2 + ext/sbc/gstsbcutil.c | 66 ++++++++++++---- ext/sbc/gstsbcutil.h | 3 +- 4 files changed, 175 insertions(+), 73 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 325a956943..3970b5dcf5 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -34,11 +34,16 @@ #define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_AUTO #define SBC_ENC_DEFAULT_BLOCKS 0 #define SBC_ENC_DEFAULT_SUB_BANDS 0 -#define SBC_ENC_DEFAULT_BITPOOL 0 #define SBC_ENC_DEFAULT_ALLOCATION BT_A2DP_ALLOCATION_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 @@ -83,13 +88,54 @@ gst_sbc_allocation_get_type (void) 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_SUBBANDS, + PROP_BITPOOL }; GST_BOILERPLATE (GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); @@ -117,7 +163,8 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }," - "bitpool = (int) [ 2, 64 ]")); + "bitpool = (int) [ " SBC_ENC_BITPOOL_MIN_STR + ", " SBC_ENC_BITPOOL_MAX_STR " ]")); gboolean gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps); @@ -151,6 +198,10 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) 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 != BT_A2DP_CHANNEL_MODE_AUTO) { enum_class = g_type_class_ref (GST_TYPE_SBC_MODE); enum_value = g_enum_get_value (enum_class, enc->mode); @@ -205,7 +256,7 @@ sbc_enc_src_caps_fixate (GstSbcEnc * enc, GstCaps * caps) result = gst_sbc_util_caps_fixate (caps, &error_message); if (!result) { - GST_ERROR_OBJECT (enc, "Invalid input caps caused parsing " + GST_WARNING_OBJECT (enc, "Invalid input caps caused parsing " "error: %s", error_message); g_free (error_message); return NULL; @@ -217,18 +268,13 @@ sbc_enc_src_caps_fixate (GstSbcEnc * enc, GstCaps * caps) static GstCaps * sbc_enc_get_fixed_srcpad_caps (GstSbcEnc * enc) { - GstCaps *peer_caps; - GstCaps *src_caps; GstCaps *caps; gboolean res = TRUE; GstCaps *result_caps = NULL; - peer_caps = gst_pad_peer_get_caps (enc->srcpad); - if (!peer_caps) - return NULL; - - src_caps = sbc_enc_generate_srcpad_caps (enc); - caps = gst_caps_intersect (src_caps, peer_caps); + 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; @@ -238,9 +284,6 @@ sbc_enc_get_fixed_srcpad_caps (GstSbcEnc * enc) result_caps = sbc_enc_src_caps_fixate (enc, caps); done: - - gst_caps_unref (src_caps); - gst_caps_unref (peer_caps); gst_caps_unref (caps); if (!res) @@ -262,46 +305,70 @@ sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps) structure = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (structure, "rate", &rate)) - goto error; + return FALSE; if (!gst_structure_get_int (structure, "channels", &channels)) - goto error; + return FALSE; enc->rate = rate; enc->channels = channels; src_caps = sbc_enc_get_fixed_srcpad_caps (enc); if (!src_caps) - goto error; + return FALSE; res = gst_pad_set_caps (enc->srcpad, src_caps); gst_caps_unref (src_caps); return res; - -error: - GST_ERROR_OBJECT (enc, "invalid input caps"); - return FALSE; } gboolean gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) { + gint mode; + + 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; - enc->rate = enc->sbc.rate; - enc->channels = enc->sbc.channels; - enc->blocks = enc->sbc.blocks; - enc->subbands = enc->sbc.subbands; - enc->mode = enc->sbc.joint; - enc->allocation = enc->sbc.allocation; + if (enc->rate != 0 && enc->sbc.rate != enc->rate) + goto fail; + + if (enc->channels != 0 && enc->sbc.channels != enc->channels) + goto fail; + + if (enc->blocks != 0 && enc->sbc.blocks != enc->blocks) + goto fail; + + if (enc->subbands != 0 && enc->sbc.subbands != enc->subbands) + goto fail; + + mode = gst_sbc_get_mode_int_from_sbc_t (&enc->sbc); + if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO && mode != enc->mode) + goto fail; + + if (enc->allocation != BT_A2DP_ALLOCATION_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 ("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 @@ -398,24 +465,6 @@ gst_sbc_enc_base_init (gpointer g_class) gst_element_class_set_details (element_class, &sbc_enc_details); } -static gboolean -sbc_enc_set_blocks (GstSbcEnc * enc, gint value) -{ - if (value != 4 && value != 8 && value != 12 && value != 16 && value != 0) - return FALSE; - enc->blocks = value; - return TRUE; -} - -static gboolean -sbc_enc_set_subbands (GstSbcEnc * enc, gint value) -{ - if (value != 4 && value != 8 && value != 0) - return FALSE; - enc->subbands = value; - return TRUE; -} - static void gst_sbc_enc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -433,14 +482,13 @@ gst_sbc_enc_set_property (GObject * object, guint prop_id, enc->allocation = g_value_get_enum (value); break; case PROP_BLOCKS: - if (!sbc_enc_set_blocks (enc, g_value_get_int (value))) - GST_WARNING_OBJECT (enc, "invalid value %d for " - "blocks property", g_value_get_int (value)); + enc->blocks = g_value_get_enum (value); break; case PROP_SUBBANDS: - if (!sbc_enc_set_subbands (enc, g_value_get_int (value))) - GST_WARNING_OBJECT (enc, "invalid value %d for " - "subbands property", g_value_get_int (value)); + 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); @@ -462,10 +510,13 @@ gst_sbc_enc_get_property (GObject * object, guint prop_id, g_value_set_enum (value, enc->allocation); break; case PROP_BLOCKS: - g_value_set_int (value, enc->blocks); + g_value_set_enum (value, enc->blocks); break; case PROP_SUBBANDS: - g_value_set_int (value, enc->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); @@ -494,18 +545,25 @@ gst_sbc_enc_class_init (GstSbcEncClass * klass) g_object_class_install_property (object_class, PROP_ALLOCATION, g_param_spec_enum ("allocation", "Allocation", - "Allocation mode", GST_TYPE_SBC_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_int ("blocks", "Blocks", - "Blocks", 0, G_MAXINT, SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE)); + 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_int ("subbands", "Sub Bands", - "Sub Bands", 0, G_MAXINT, + 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"); } @@ -533,6 +591,7 @@ gst_sbc_enc_init (GstSbcEnc * self, GstSbcEncClass * klass) 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; diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index c7b216385f..4141750745 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -55,6 +55,8 @@ struct _GstSbcEnc { gint blocks; gint allocation; gint subbands; + gint bitpool; + gint codesize; gint frame_length; gint frame_duration; diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 2bebdcb7f7..60ad99cba4 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -97,21 +97,39 @@ gst_sbc_get_allocation_from_list (const GValue * value) * Selects one mode from the ones on the list */ const gchar * -gst_sbc_get_mode_from_list (const GValue * list) +gst_sbc_get_mode_from_list (const GValue * list, gint channels) { int i; const GValue *value; const gchar *aux; + gboolean joint, stereo, dual, mono; + joint = stereo = dual = mono = FALSE; guint size = gst_value_list_get_size (list); + 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) { - return "joint"; - } + 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; } - return g_value_get_string (gst_value_list_get_value (list, size - 1)); + + if (channels == 1 && mono) + return "mono"; + else if (channels == 2) { + if (joint) + return "joint"; + else if (stereo) + return "stereo"; + } + + return NULL; } gint @@ -158,8 +176,22 @@ gst_sbc_get_mode_int_for_sbc_t (const gchar * mode) return -1; } +gint +gst_sbc_get_mode_int_from_sbc_t (const sbc_t * sbc) +{ + /* TODO define constants */ + if (sbc->channels == 2 && sbc->joint == 1) + return 4; + else if (sbc->channels == 2 && sbc->joint == 0) + return 3; + else if (sbc->channels == 1) + return 1; + else + return -1; +} + const gchar * -gst_sbc_get_mode_string (int joint) +gst_sbc_get_mode_string (gint joint) { switch (joint) { case BT_A2DP_CHANNEL_MODE_MONO: @@ -178,7 +210,7 @@ gst_sbc_get_mode_string (int joint) } const gchar * -gst_sbc_get_allocation_string (int alloc) +gst_sbc_get_allocation_string (gint alloc) { switch (alloc) { case BT_A2DP_ALLOCATION_LOUDNESS: @@ -203,7 +235,7 @@ gst_sbc_get_allocation_string (int alloc) #define SBC_AM_SNR 0x01 const gchar * -gst_sbc_get_mode_string_from_sbc_t (int channels, int joint) +gst_sbc_get_mode_string_from_sbc_t (gint channels, gint joint) { if (channels == 2 && joint == 1) return "joint"; @@ -216,7 +248,7 @@ gst_sbc_get_mode_string_from_sbc_t (int channels, int joint) } const gchar * -gst_sbc_get_allocation_string_from_sbc_t (int alloc) +gst_sbc_get_allocation_string_from_sbc_t (gint alloc) { switch (alloc) { case SBC_AM_LOUDNESS: @@ -378,14 +410,22 @@ gst_sbc_util_caps_fixate (GstCaps * caps, gchar ** error_message) } else { value = gst_structure_get_value (structure, "mode"); if (GST_VALUE_HOLDS_LIST (value)) { - if (channels == 1) - mode = "mono"; - else - mode = gst_sbc_get_mode_from_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, dual */ + if ((channels == 1 && (strcmp (mode, "mono") != 0)) || + (channels == 2 && (strcmp (mode, "mono") == 0 || + strcmp (mode, "dual") == 0))) { + *error_message = g_strdup_printf ("Invalid combination of " + "channels (%d) and channel mode (%s)", channels, mode); + error = TRUE; + } + error: if (error) return NULL; diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 47ec349398..d7c1ce79ca 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -42,8 +42,9 @@ const gchar *gst_sbc_get_allocation_from_list(const GValue *value); gint gst_sbc_get_allocation_mode_int(const gchar *allocation); const gchar *gst_sbc_get_allocation_string(int alloc); -const gchar *gst_sbc_get_mode_from_list(const GValue *value); +const gchar *gst_sbc_get_mode_from_list(const GValue *value, gint channels); gint gst_sbc_get_mode_int(const gchar *mode); +gint gst_sbc_get_mode_int_from_sbc_t(const sbc_t *sbc); const gchar *gst_sbc_get_mode_string(int joint); GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels); From 5be53d24ab7f3a05ca5eda50bd7cfc536e214e6d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: [PATCH 30/57] sbc: Update copyright information --- ext/sbc/gstsbcdec.c | 2 +- ext/sbc/gstsbcdec.h | 2 +- ext/sbc/gstsbcenc.c | 2 +- ext/sbc/gstsbcenc.h | 2 +- ext/sbc/gstsbcparse.c | 2 +- ext/sbc/gstsbcparse.h | 2 +- ext/sbc/gstsbcutil.c | 2 +- ext/sbc/gstsbcutil.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 2005d6870d..b4e7d6d0cf 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index a88f8da540..e8ff9cf5cd 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 3970b5dcf5..3fcd8555bf 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 4141750745..17e89549a2 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 446fb98652..0c3dc8024d 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index a71aea729e..eceeeea134 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 60ad99cba4..08cd8a1d46 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index d7c1ce79ca..71831c36d9 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This library is free software; you can redistribute it and/or From ccf5d9ea7e3a676723174934a33c7bb7fd4168b2 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 14 Feb 2008 21:22:38 +0000 Subject: [PATCH 31/57] sbc: Make use of parameters selected in alsa plugin and fix auto selection. --- ext/sbc/gstsbcenc.c | 13 ++++++------- ext/sbc/gstsbcutil.c | 8 -------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 3fcd8555bf..d78ac7a8d5 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -31,10 +31,10 @@ #include "gstsbcenc.h" #include "gstsbcutil.h" -#define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_AUTO +#define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_JOINT_STEREO #define SBC_ENC_DEFAULT_BLOCKS 0 #define SBC_ENC_DEFAULT_SUB_BANDS 0 -#define SBC_ENC_DEFAULT_ALLOCATION BT_A2DP_ALLOCATION_AUTO +#define SBC_ENC_DEFAULT_ALLOCATION BT_A2DP_ALLOCATION_LOUDNESS #define SBC_ENC_DEFAULT_RATE 0 #define SBC_ENC_DEFAULT_CHANNELS 0 @@ -75,7 +75,6 @@ gst_sbc_allocation_get_type (void) { static GType sbc_allocation_type = 0; static GEnumValue sbc_allocations[] = { - {BT_A2DP_ALLOCATION_AUTO, "Auto", "auto"}, {BT_A2DP_ALLOCATION_LOUDNESS, "Loudness", "loudness"}, {BT_A2DP_ALLOCATION_SNR, "SNR", "snr"}, {-1, NULL, NULL} @@ -202,7 +201,7 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) gst_sbc_util_set_structure_int_param (structure, "bitpool", enc->bitpool, value); - if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO) { + 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", @@ -210,7 +209,7 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) g_type_class_unref (enum_class); } - if (enc->allocation != BT_A2DP_ALLOCATION_AUTO) { + if (enc->allocation != SBC_ENC_DEFAULT_ALLOCATION) { 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", @@ -347,10 +346,10 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) goto fail; mode = gst_sbc_get_mode_int_from_sbc_t (&enc->sbc); - if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO && mode != enc->mode) + if (enc->mode != SBC_ENC_DEFAULT_MODE && mode != enc->mode) goto fail; - if (enc->allocation != BT_A2DP_ALLOCATION_AUTO && + if (enc->allocation != SBC_ENC_DEFAULT_ALLOCATION && enc->sbc.allocation != enc->allocation) goto fail; diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 08cd8a1d46..6aa7d878f0 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -139,8 +139,6 @@ gst_sbc_get_allocation_mode_int (const gchar * allocation) return BT_A2DP_ALLOCATION_LOUDNESS; else if (g_ascii_strcasecmp (allocation, "snr") == 0) return BT_A2DP_ALLOCATION_SNR; - else if (g_ascii_strcasecmp (allocation, "auto") == 0) - return BT_A2DP_ALLOCATION_AUTO; else return -1; } @@ -156,8 +154,6 @@ gst_sbc_get_mode_int (const gchar * mode) return BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; else if (g_ascii_strcasecmp (mode, "mono") == 0) return BT_A2DP_CHANNEL_MODE_MONO; - else if (g_ascii_strcasecmp (mode, "auto") == 0) - return BT_A2DP_CHANNEL_MODE_AUTO; else return -1; } @@ -202,8 +198,6 @@ gst_sbc_get_mode_string (gint joint) return "stereo"; case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: return "joint"; - case BT_A2DP_CHANNEL_MODE_AUTO: - return NULL; /* TODO what should be selected here? */ default: return NULL; } @@ -217,8 +211,6 @@ gst_sbc_get_allocation_string (gint alloc) return "loudness"; case BT_A2DP_ALLOCATION_SNR: return "snr"; - case BT_A2DP_ALLOCATION_AUTO: - return "loudness"; /* TODO what should be selected here? */ default: return NULL; } From 834a9b193b8306b27aa74dbe6e1ac0b211765e4f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 19 Feb 2008 19:49:24 +0000 Subject: [PATCH 32/57] sbc: Update gstreamer plugin to use new sbc API. --- ext/sbc/gstsbcdec.c | 6 +- ext/sbc/gstsbcdec.h | 1 + ext/sbc/gstsbcenc.c | 57 ++++---- ext/sbc/gstsbcutil.c | 305 ++++++++++++++++++++++--------------------- ext/sbc/gstsbcutil.h | 34 +++-- 5 files changed, 205 insertions(+), 198 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index b4e7d6d0cf..bcdaab789a 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -96,8 +96,10 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) /* we will reuse the same caps object */ if (dec->outcaps == NULL) { caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, dec->sbc.rate, - "channels", G_TYPE_INT, dec->sbc.channels, NULL); + "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); diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index e8ff9cf5cd..df6879333e 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -24,6 +24,7 @@ #include #include "sbc.h" +#include "gstsbcutil.h" G_BEGIN_DECLS diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index d78ac7a8d5..bfb5c65efe 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -27,14 +27,13 @@ #include -#include "ipc.h" #include "gstsbcenc.h" #include "gstsbcutil.h" -#define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_JOINT_STEREO +#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 BT_A2DP_ALLOCATION_LOUDNESS +#define SBC_ENC_DEFAULT_ALLOCATION SBC_AM_AUTO #define SBC_ENC_DEFAULT_RATE 0 #define SBC_ENC_DEFAULT_CHANNELS 0 @@ -54,11 +53,11 @@ gst_sbc_mode_get_type (void) { static GType sbc_mode_type = 0; static GEnumValue sbc_modes[] = { - {0, "Auto", "auto"}, - {1, "Mono", "mono"}, - {2, "Dual Channel", "dual"}, - {3, "Stereo", "stereo"}, - {4, "Joint Stereo", "joint"}, + {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} }; @@ -75,8 +74,9 @@ gst_sbc_allocation_get_type (void) { static GType sbc_allocation_type = 0; static GEnumValue sbc_allocations[] = { - {BT_A2DP_ALLOCATION_LOUDNESS, "Loudness", "loudness"}, - {BT_A2DP_ALLOCATION_SNR, "SNR", "snr"}, + {SBC_AM_LOUDNESS, "Loudness", "loudness"}, + {SBC_AM_SNR, "SNR", "snr"}, + {SBC_AM_AUTO, "Auto", "auto"}, {-1, NULL, NULL} }; @@ -174,7 +174,6 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) GstStructure *structure; GEnumValue *enum_value; GEnumClass *enum_class; - gchar *temp; GValue *value; src_caps = gst_caps_copy (gst_pad_get_pad_template_caps (enc->srcpad)); @@ -209,7 +208,7 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) g_type_class_unref (enum_class); } - if (enc->allocation != SBC_ENC_DEFAULT_ALLOCATION) { + 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", @@ -217,9 +216,6 @@ sbc_enc_generate_srcpad_caps (GstSbcEnc * enc) g_type_class_unref (enum_class); } - temp = gst_caps_to_string (src_caps); - GST_DEBUG_OBJECT (enc, "Srcpad caps: %s", temp); - g_free (temp); g_free (value); return src_caps; @@ -248,7 +244,6 @@ sbc_enc_src_setcaps (GstPad * pad, GstCaps * caps) static GstCaps * sbc_enc_src_caps_fixate (GstSbcEnc * enc, GstCaps * caps) { - gchar *error_message = NULL; GstCaps *result; @@ -323,8 +318,6 @@ sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps) gboolean gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) { - gint mode; - if (!gst_caps_is_fixed (caps)) { GST_DEBUG_OBJECT (enc, "didn't receive fixed caps, " "returning false"); return FALSE; @@ -333,24 +326,26 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) if (!gst_sbc_util_fill_sbc_params (&enc->sbc, caps)) return FALSE; - if (enc->rate != 0 && enc->sbc.rate != enc->rate) + if (enc->rate != 0 && gst_sbc_parse_rate_from_sbc (enc->sbc.frequency) + != enc->rate) goto fail; - if (enc->channels != 0 && enc->sbc.channels != enc->channels) + if (enc->channels != 0 && gst_sbc_get_channel_number (enc->sbc.mode) + != enc->channels) goto fail; - if (enc->blocks != 0 && enc->sbc.blocks != enc->blocks) + if (enc->blocks != 0 && gst_sbc_parse_blocks_from_sbc (enc->sbc.blocks) + != enc->blocks) goto fail; - if (enc->subbands != 0 && enc->sbc.subbands != enc->subbands) + if (enc->subbands != 0 + && gst_sbc_parse_subbands_from_sbc (enc->sbc.subbands) != enc->subbands) goto fail; - mode = gst_sbc_get_mode_int_from_sbc_t (&enc->sbc); - if (enc->mode != SBC_ENC_DEFAULT_MODE && mode != enc->mode) + if (enc->mode != SBC_ENC_DEFAULT_MODE && enc->sbc.mode != enc->mode) goto fail; - if (enc->allocation != SBC_ENC_DEFAULT_ALLOCATION && - enc->sbc.allocation != enc->allocation) + 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) @@ -360,8 +355,8 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) enc->frame_length = sbc_get_frame_length (&enc->sbc); enc->frame_duration = sbc_get_frame_duration (&enc->sbc); - GST_DEBUG ("codesize: %d, frame_length: %d, frame_duration: %d", - enc->codesize, enc->frame_length, enc->frame_duration); + GST_DEBUG_OBJECT (enc, "codesize: %d, frame_length: %d, frame_duration:" + " %d", enc->codesize, enc->frame_length, enc->frame_duration); return TRUE; @@ -383,7 +378,7 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) GstBuffer *output; GstCaps *caps; const guint8 *data; - int consumed; + gint consumed; caps = GST_PAD_CAPS (enc->srcpad); res = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, @@ -392,11 +387,12 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) 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_ERROR ("comsumed < 0, codesize: %d", enc->codesize); + GST_DEBUG_OBJECT (enc, "comsumed < 0, codesize: %d", enc->codesize); break; } gst_adapter_flush (adapter, consumed); @@ -406,6 +402,7 @@ sbc_enc_chain (GstPad * pad, GstBuffer * buffer) GST_BUFFER_DURATION (output) = enc->frame_duration; res = gst_pad_push (enc->srcpad, output); + if (res != GST_FLOW_OK) goto done; } diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 6aa7d878f0..292b7de273 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -25,7 +25,6 @@ #include #endif -#include "ipc.h" #include #include "gstsbcutil.h" @@ -127,131 +126,183 @@ gst_sbc_get_mode_from_list (const GValue * list, gint channels) return "joint"; else if (stereo) return "stereo"; + else if (dual) + return "dual"; } return NULL; } gint -gst_sbc_get_allocation_mode_int (const gchar * allocation) +gst_sbc_parse_rate_from_sbc (gint frequency) { - if (g_ascii_strcasecmp (allocation, "loudness") == 0) - return BT_A2DP_ALLOCATION_LOUDNESS; - else if (g_ascii_strcasecmp (allocation, "snr") == 0) - return BT_A2DP_ALLOCATION_SNR; - else - return -1; + 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_get_mode_int (const gchar * mode) +gst_sbc_parse_rate_to_sbc (gint rate) { - if (g_ascii_strcasecmp (mode, "joint") == 0) - return BT_A2DP_CHANNEL_MODE_JOINT_STEREO; - else if (g_ascii_strcasecmp (mode, "stereo") == 0) - return BT_A2DP_CHANNEL_MODE_STEREO; - else if (g_ascii_strcasecmp (mode, "dual") == 0) - return BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; - else if (g_ascii_strcasecmp (mode, "mono") == 0) - return BT_A2DP_CHANNEL_MODE_MONO; - else - return -1; -} - -/* FIXME add dual when sbc_t supports it */ -gboolean -gst_sbc_get_mode_int_for_sbc_t (const gchar * mode) -{ - if (g_ascii_strcasecmp (mode, "joint") == 0) - return TRUE; - else if (g_ascii_strcasecmp (mode, "stereo") == 0) - return FALSE; - else if (g_ascii_strcasecmp (mode, "mono") == 0) - return FALSE; - else - return -1; + 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_mode_int_from_sbc_t (const sbc_t * sbc) +gst_sbc_get_channel_number (gint mode) { - /* TODO define constants */ - if (sbc->channels == 2 && sbc->joint == 1) - return 4; - else if (sbc->channels == 2 && sbc->joint == 0) - return 3; - else if (sbc->channels == 1) - return 1; - else - return -1; + 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_get_mode_string (gint joint) +gst_sbc_parse_mode_from_sbc (gint mode) { - switch (joint) { - case BT_A2DP_CHANNEL_MODE_MONO: + switch (mode) { + case SBC_MODE_MONO: return "mono"; - case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: + case SBC_MODE_DUAL_CHANNEL: return "dual"; - case BT_A2DP_CHANNEL_MODE_STEREO: + case SBC_MODE_STEREO: return "stereo"; - case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: + case SBC_MODE_JOINT_STEREO: + case SBC_MODE_AUTO: return "joint"; default: return NULL; } } -const gchar * -gst_sbc_get_allocation_string (gint alloc) +gint +gst_sbc_parse_mode_to_sbc (const gchar * mode) { - switch (alloc) { - case BT_A2DP_ALLOCATION_LOUDNESS: - return "loudness"; - case BT_A2DP_ALLOCATION_SNR: - return "snr"; - default: - return NULL; - } -} - -/* channel mode */ -#define SBC_CM_MONO 0x00 -#define SBC_CM_DUAL_CHANNEL 0x01 -#define SBC_CM_STEREO 0x02 -#define SBC_CM_JOINT_STEREO 0x03 - -/* allocation mode */ -#define SBC_AM_LOUDNESS 0x00 -#define SBC_AM_SNR 0x01 - -const gchar * -gst_sbc_get_mode_string_from_sbc_t (gint channels, gint joint) -{ - if (channels == 2 && joint == 1) - return "joint"; - else if (channels == 2 && joint == 0) - return "stereo"; - else if (channels == 1 && joint == 0) - return "mono"; + 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 NULL; + return -1; } const gchar * -gst_sbc_get_allocation_string_from_sbc_t (gint alloc) +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) { @@ -259,42 +310,24 @@ gst_sbc_parse_caps_from_sbc (sbc_t * sbc) const gchar *mode_str; const gchar *allocation_str; - mode_str = gst_sbc_get_mode_string_from_sbc_t (sbc->channels, sbc->joint); - allocation_str = gst_sbc_get_allocation_string_from_sbc_t (sbc->allocation); + 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, sbc->rate, - "channels", G_TYPE_INT, sbc->channels, + "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, sbc->subbands, - "blocks", G_TYPE_INT, sbc->blocks, + "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; } -GstCaps * -gst_sbc_caps_from_sbc (sbc_capabilities_t * sbc, gint channels) -{ - GstCaps *caps; - const gchar *mode_str; - const gchar *allocation_str; - - mode_str = gst_sbc_get_mode_string (sbc->channel_mode); - allocation_str = gst_sbc_get_allocation_string (sbc->allocation_method); - - caps = gst_caps_new_simple ("audio/x-sbc", - "rate", G_TYPE_INT, sbc->frequency, - "channels", G_TYPE_INT, channels, - "mode", G_TYPE_STRING, mode_str, - "subbands", G_TYPE_INT, sbc->subbands, - "blocks", G_TYPE_INT, sbc->block_length, - "allocation", G_TYPE_STRING, allocation_str, - "bitpool", G_TYPE_INT, sbc->max_bitpool, NULL); - - return caps; -} - /* * Given a GstCaps, this will return a fixed GstCaps on sucessfull conversion. * If an error occurs, it will return NULL and error_message will contain the @@ -409,10 +442,9 @@ gst_sbc_util_caps_fixate (GstCaps * caps, gchar ** error_message) /* perform validation * if channels is 1, we must have channel mode = mono - * if channels is 2, we can't have channel mode = mono, dual */ + * if channels is 2, we can't have channel mode = mono */ if ((channels == 1 && (strcmp (mode, "mono") != 0)) || - (channels == 2 && (strcmp (mode, "mono") == 0 || - strcmp (mode, "dual") == 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; @@ -492,46 +524,15 @@ gst_sbc_util_fill_sbc_params (sbc_t * sbc, GstCaps * caps) if (!(allocation = gst_structure_get_string (structure, "allocation"))) return FALSE; - sbc->rate = rate; - sbc->channels = channels; - sbc->blocks = blocks; - sbc->subbands = subbands; + 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->joint = gst_sbc_get_mode_int_for_sbc_t (mode); - sbc->allocation = gst_sbc_get_allocation_mode_int (allocation); + sbc->mode = gst_sbc_parse_mode_to_sbc (mode); + sbc->allocation = gst_sbc_parse_allocation_to_sbc (allocation); return TRUE; } - -gint -gst_sbc_util_calc_frame_len (gint subbands, gint channels, - gint blocks, gint bitpool, gint channel_mode) -{ - gint len; - gint join; - len = 4 + (4 * subbands * channels) / 8; - - if (channel_mode == BT_A2DP_CHANNEL_MODE_MONO || - channel_mode == BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) - len += ((blocks * channels * bitpool) + 7) / 8; - else { - join = channel_mode == BT_A2DP_CHANNEL_MODE_JOINT_STEREO ? 1 : 0; - len += ((join * subbands + blocks * bitpool) + 7) / 8; - } - - return len; -} - -gint -gst_sbc_util_calc_bitrate (gint frame_len, gint rate, gint subbands, - gint blocks) -{ - return (((frame_len * 8 * rate / subbands) / blocks) / 1000); -} - -gint64 -gst_sbc_util_calc_frame_duration (gint rate, gint blocks, gint subbands) -{ - gint64 res = 1000000; - return res * blocks * subbands / rate; -} diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 71831c36d9..a3cf937c41 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -24,7 +24,10 @@ #include #include "sbc.h" -#include "ipc.h" +#include + +#define SBC_AM_AUTO 0x02 +#define SBC_MODE_AUTO 0x04 gint gst_sbc_select_rate_from_list(const GValue *value); @@ -39,15 +42,25 @@ gint gst_sbc_select_bitpool_from_range(const GValue *value); gint gst_sbc_select_bitpool_from_range(const GValue *value); const gchar *gst_sbc_get_allocation_from_list(const GValue *value); -gint gst_sbc_get_allocation_mode_int(const gchar *allocation); -const gchar *gst_sbc_get_allocation_string(int alloc); const gchar *gst_sbc_get_mode_from_list(const GValue *value, gint channels); -gint gst_sbc_get_mode_int(const gchar *mode); -gint gst_sbc_get_mode_int_from_sbc_t(const sbc_t *sbc); -const gchar *gst_sbc_get_mode_string(int joint); -GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, 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); @@ -62,10 +75,3 @@ void gst_sbc_util_set_structure_string_param(GstStructure *structure, gboolean gst_sbc_util_fill_sbc_params(sbc_t *sbc, GstCaps *caps); -gint gst_sbc_util_calc_frame_len(gint subbands, gint channels, - gint blocks, gint bitpool, gint channel_mode); - -gint gst_sbc_util_calc_bitrate(gint frame_len, gint rate, gint subbands, - gint blocks); - -gint64 gst_sbc_util_calc_frame_duration(gint rate, gint blocks, gint subbands); From 266cfb11b4bb51a9177a349ff31a7e5f0d2376b4 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 20 Feb 2008 13:37:00 +0000 Subject: [PATCH 33/57] sbc: Fix runtime warnings of gstreamer plugin. --- ext/sbc/gstsbcenc.c | 4 ++-- ext/sbc/gstsbcparse.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index bfb5c65efe..9a2f3e294c 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -158,10 +158,10 @@ 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 }, " + "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, " "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " - "allocation = (string) { snr, loudness }," + "allocation = (string) { \"snr\", \"loudness\" }, " "bitpool = (int) [ " SBC_ENC_BITPOOL_MIN_STR ", " SBC_ENC_BITPOOL_MAX_STR " ]")); diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 0c3dc8024d..a688c6865b 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -50,10 +50,10 @@ 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 }, " + "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, " "blocks = (int) { 4, 8, 12, 16 }, " "subbands = (int) { 4, 8 }, " - "allocation = (string) { snr, loudness }," + "allocation = (string) { \"snr\", \"loudness\" }," "bitpool = (int) [ 2, 64 ]," "parsed = (boolean) true")); static GstFlowReturn From 7ae0c70682f986c9cb7f050291502e5738c7136d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Dec 2008 21:42:49 +0200 Subject: [PATCH 34/57] sbc: More coding style fixes --- ext/sbc/gstsbcdec.c | 4 ++-- ext/sbc/gstsbcparse.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index bcdaab789a..2d16d74f8a 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -210,6 +210,6 @@ gst_sbc_dec_init (GstSbcDec * self, GstSbcDecClass * klass) gboolean gst_sbc_dec_plugin_init (GstPlugin * plugin) { - return gst_element_register (plugin, "sbcdec", - GST_RANK_PRIMARY, GST_TYPE_SBC_DEC); + return gst_element_register (plugin, "sbcdec", GST_RANK_PRIMARY, + GST_TYPE_SBC_DEC); } diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index a688c6865b..0be78bdfd0 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -215,6 +215,6 @@ gst_sbc_parse_init (GstSbcParse * self, GstSbcParseClass * klass) gboolean gst_sbc_parse_plugin_init (GstPlugin * plugin) { - return gst_element_register (plugin, "sbcparse", - GST_RANK_NONE, GST_TYPE_SBC_PARSE); + return gst_element_register (plugin, "sbcparse", GST_RANK_NONE, + GST_TYPE_SBC_PARSE); } From 57f6f2655df20ab9d5ab312819641f75f21cb595 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Dec 2008 04:21:57 +0100 Subject: [PATCH 35/57] sbc: Assign variables after declarations --- ext/sbc/gstsbcutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 292b7de273..3d3f423530 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -102,9 +102,9 @@ gst_sbc_get_mode_from_list (const GValue * list, gint channels) const GValue *value; const gchar *aux; gboolean joint, stereo, dual, mono; + guint size = gst_value_list_get_size (list); joint = stereo = dual = mono = FALSE; - guint size = gst_value_list_get_size (list); for (i = 0; i < size; i++) { value = gst_value_list_get_value (list, i); From 54f6cd021852362dc5072b115e1c7d519caaa3b4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Dec 2008 05:25:50 +0100 Subject: [PATCH 36/57] sbc: First attempt in fixing compiler warnings (still needs cleanup) --- ext/sbc/gstsbcdec.c | 1 + ext/sbc/gstsbcdec.h | 3 +-- ext/sbc/gstsbcenc.c | 2 +- ext/sbc/gstsbcenc.h | 2 +- ext/sbc/gstsbcparse.c | 2 +- ext/sbc/gstsbcparse.h | 2 +- ext/sbc/gstsbcutil.h | 2 -- 7 files changed, 6 insertions(+), 8 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 2d16d74f8a..71b87c1667 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -27,6 +27,7 @@ #include +#include "gstsbcutil.h" #include "gstsbcdec.h" GST_DEBUG_CATEGORY_STATIC (sbc_dec_debug); diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index df6879333e..3fa7cd39f1 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -24,7 +24,6 @@ #include #include "sbc.h" -#include "gstsbcutil.h" G_BEGIN_DECLS @@ -60,7 +59,7 @@ struct _GstSbcDecClass { GstElementClass parent_class; }; -GType gst_sbc_dec_get_type(void); +//GType gst_sbc_dec_get_type(void); gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin); diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 9a2f3e294c..9ecde184ed 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -27,8 +27,8 @@ #include -#include "gstsbcenc.h" #include "gstsbcutil.h" +#include "gstsbcenc.h" #define SBC_ENC_DEFAULT_MODE SBC_MODE_AUTO #define SBC_ENC_DEFAULT_BLOCKS 0 diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 17e89549a2..0038f899bf 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -68,7 +68,7 @@ struct _GstSbcEncClass { GstElementClass parent_class; }; -GType gst_sbc_enc_get_type(void); +//GType gst_sbc_enc_get_type(void); gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin); diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 0be78bdfd0..80d2b71939 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -27,8 +27,8 @@ #include -#include "gstsbcparse.h" #include "gstsbcutil.h" +#include "gstsbcparse.h" GST_DEBUG_CATEGORY_STATIC (sbc_parse_debug); #define GST_CAT_DEFAULT sbc_parse_debug diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index eceeeea134..7a3f82661a 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -62,7 +62,7 @@ struct _GstSbcParseClass { GstElementClass parent_class; }; -GType gst_sbc_parse_get_type(void); +//GType gst_sbc_parse_get_type(void); gboolean gst_sbc_parse_plugin_init(GstPlugin *plugin); diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index a3cf937c41..1f5d3270f1 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -39,8 +39,6 @@ gint gst_sbc_select_subbands_from_list(const GValue *value); gint gst_sbc_select_bitpool_from_range(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); From a3bf74686a42b7e3b4d26d840a62bb7bdea4ae97 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 1 Jan 2009 19:33:20 +0100 Subject: [PATCH 37/57] sbc: Update copyright information --- ext/sbc/gstsbcdec.c | 2 +- ext/sbc/gstsbcdec.h | 2 +- ext/sbc/gstsbcenc.c | 2 +- ext/sbc/gstsbcenc.h | 2 +- ext/sbc/gstsbcparse.c | 2 +- ext/sbc/gstsbcparse.h | 2 +- ext/sbc/gstsbcutil.c | 2 +- ext/sbc/gstsbcutil.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 71b87c1667..17eb51cb1f 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index 3fa7cd39f1..383a3bf6f4 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 9ecde184ed..4f4f1677f5 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 0038f899bf..d84dace86e 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 80d2b71939..00fd7e0536 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index 7a3f82661a..ef3d1d8e31 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 3d3f423530..53f0feacb9 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 1f5d3270f1..b8f626b6b3 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2004-2009 Marcel Holtmann * * * This library is free software; you can redistribute it and/or From 3f994a84bb23a5cea4e8c3d2eedc164c0e7d67d3 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 19 Jan 2009 10:26:28 +0200 Subject: [PATCH 38/57] sbc: Use native byte order for audio in GStreamer and ALSA plugins This fixes endianness inconsistency between default SBC configuration and GStreamer/ALSA. --- ext/sbc/gstsbcdec.c | 2 +- ext/sbc/gstsbcenc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 17eb51cb1f..d4342df02a 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -50,7 +50,7 @@ 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) LITTLE_ENDIAN, " + "endianness = (int) BYTE_ORDER, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")); static GstFlowReturn diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 4f4f1677f5..ca47a7ad9a 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -150,7 +150,7 @@ 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) LITTLE_ENDIAN, " + "endianness = (int) BYTE_ORDER, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")); static GstStaticPadTemplate sbc_enc_src_factory = From db16c0332cf806f22ca155755dcf50bd2b7542dc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 30 Jan 2009 00:31:15 +0100 Subject: [PATCH 39/57] sbc: Fix signed/unsigned comparison issue within GStreamer plugin --- ext/sbc/gstsbcenc.h | 2 +- ext/sbc/gstsbcutil.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index d84dace86e..6d69922ae8 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -57,7 +57,7 @@ struct _GstSbcEnc { gint subbands; gint bitpool; - gint codesize; + guint codesize; gint frame_length; gint frame_duration; diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 53f0feacb9..0ae46885c5 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -98,7 +98,7 @@ gst_sbc_get_allocation_from_list (const GValue * value) const gchar * gst_sbc_get_mode_from_list (const GValue * list, gint channels) { - int i; + unsigned int i; const GValue *value; const gchar *aux; gboolean joint, stereo, dual, mono; From c985a85cf28af01b52109ddc8eeb04c7f852a8ad Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 1 Apr 2009 10:29:31 -0300 Subject: [PATCH 40/57] sbc: Remove unused variable. --- ext/sbc/gstsbcdec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index d4342df02a..066d6417e0 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -60,10 +60,8 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) GstFlowReturn res = GST_FLOW_OK; guint size, codesize, offset = 0; guint8 *data; - GstClockTime timestamp; codesize = sbc_get_codesize (&dec->sbc); - timestamp = GST_BUFFER_TIMESTAMP (buffer); if (dec->buffer) { GstBuffer *temp = buffer; From d4fd8f3ecdafec45700f18e6c7c00f62c1973180 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 1 Apr 2009 10:45:30 -0300 Subject: [PATCH 41/57] sbc: Remove unused variable. --- ext/sbc/gstsbcparse.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 00fd7e0536..805750caf8 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -63,9 +63,6 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) GstFlowReturn res = GST_FLOW_OK; guint size, offset = 0; guint8 *data; - GstClockTime timestamp; - - timestamp = GST_BUFFER_TIMESTAMP (buffer); /* FIXME use a gstadpter */ if (parse->buffer) { From 1ddbdc3e7ac5b9ab6a6d9f3df55a7b43377c1b7b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 1 Jan 2010 17:08:17 -0800 Subject: [PATCH 42/57] sbc: Update copyright information --- ext/sbc/gstsbcdec.c | 2 +- ext/sbc/gstsbcdec.h | 2 +- ext/sbc/gstsbcenc.c | 2 +- ext/sbc/gstsbcenc.h | 2 +- ext/sbc/gstsbcparse.c | 2 +- ext/sbc/gstsbcparse.h | 2 +- ext/sbc/gstsbcutil.c | 2 +- ext/sbc/gstsbcutil.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 066d6417e0..0c79c3872f 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index 383a3bf6f4..6a15fb0438 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index ca47a7ad9a..f6982868a7 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 6d69922ae8..0c8508b251 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 805750caf8..07544650fd 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index ef3d1d8e31..d7331adf8d 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 0ae46885c5..fe1449b49f 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index b8f626b6b3..a7f84d590c 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2010 Marcel Holtmann * * * This library is free software; you can redistribute it and/or From df140f78524900d4d1d453f536e63fcd06a9999d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 19 May 2010 16:59:30 +0200 Subject: [PATCH 43/57] sbc: Add pragma based workaround for GStreamer warnings --- ext/sbc/gstsbcdec.c | 1 + ext/sbc/gstsbcenc.c | 1 + ext/sbc/gstsbcparse.c | 1 + 3 files changed, 3 insertions(+) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 0c79c3872f..e70232b7e0 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -27,6 +27,7 @@ #include +#include "gstpragma.h" #include "gstsbcutil.h" #include "gstsbcdec.h" diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index f6982868a7..605ff93c28 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -27,6 +27,7 @@ #include +#include "gstpragma.h" #include "gstsbcutil.h" #include "gstsbcenc.h" diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 07544650fd..71c99d9204 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -27,6 +27,7 @@ #include +#include "gstpragma.h" #include "gstsbcutil.h" #include "gstsbcparse.h" From 5514d457a180b37949c47692ad9e2ecad31f9932 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Feb 2011 17:51:45 -0800 Subject: [PATCH 44/57] sbc: audio: Remove workaround for compiler warnings --- ext/sbc/gstsbcdec.h | 2 +- ext/sbc/gstsbcenc.h | 2 +- ext/sbc/gstsbcparse.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index 6a15fb0438..c77feaed30 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -59,7 +59,7 @@ struct _GstSbcDecClass { GstElementClass parent_class; }; -//GType gst_sbc_dec_get_type(void); +GType gst_sbc_dec_get_type(void); gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin); diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index 0c8508b251..0329351fa6 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -68,7 +68,7 @@ struct _GstSbcEncClass { GstElementClass parent_class; }; -//GType gst_sbc_enc_get_type(void); +GType gst_sbc_enc_get_type(void); gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin); diff --git a/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h index d7331adf8d..ecb8be426a 100644 --- a/ext/sbc/gstsbcparse.h +++ b/ext/sbc/gstsbcparse.h @@ -62,7 +62,7 @@ struct _GstSbcParseClass { GstElementClass parent_class; }; -//GType gst_sbc_parse_get_type(void); +GType gst_sbc_parse_get_type(void); gboolean gst_sbc_parse_plugin_init(GstPlugin *plugin); From b31ee7bffc36010f1cb6fb3a5bd9d95f9837e967 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Sat, 2 Jul 2011 12:32:40 -0300 Subject: [PATCH 45/57] sbc: Fix common misspelled words Accounting of misspelled words, as detected by codespell: acording 2 ancilliary 1 appropiate 1 atribute 1 cant 1 comming 2 gracefull 1 lenght 1 mispelled 1 occured 1 occurences 1 ocurred 3 prefered 1 presense 1 reponse 1 seperate 1 succesful 1 successully 1 sucessfull 1 sucessfully 1 --- ext/sbc/gstsbcutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index fe1449b49f..47e997cec9 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -329,7 +329,7 @@ gst_sbc_parse_caps_from_sbc (sbc_t * sbc) } /* - * Given a GstCaps, this will return a fixed GstCaps on sucessfull conversion. + * 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. * From 142a5fb63776f59594630ab55f12929b8d2e62e4 Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Thu, 12 Apr 2012 20:33:06 +0530 Subject: [PATCH 46/57] sbc: audio: Fix newline before EOF --- ext/sbc/gstsbcutil.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index a7f84d590c..5e47119516 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -72,4 +72,3 @@ void gst_sbc_util_set_structure_string_param(GstStructure *structure, GValue *value); gboolean gst_sbc_util_fill_sbc_params(sbc_t *sbc, GstCaps *caps); - From 6979975963e60f47dfd4a6ccffe3eb26913d64dc Mon Sep 17 00:00:00 2001 From: Anderson Lizardo Date: Tue, 21 Aug 2012 11:49:24 -0400 Subject: [PATCH 47/57] sbc: Fix trivial coding style issues on pointer declarations and casting Avoid using C++ style pointer declarations like "char* ptr", as most BlueZ code uses "char *ptr". --- ext/sbc/gstsbcutil.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/sbc/gstsbcutil.h b/ext/sbc/gstsbcutil.h index 5e47119516..962532f786 100644 --- a/ext/sbc/gstsbcutil.h +++ b/ext/sbc/gstsbcutil.h @@ -59,16 +59,16 @@ 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_parse_caps_from_sbc(sbc_t *sbc); -GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message); +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, + 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, + const gchar *field, const gchar *field_value, GValue *value); gboolean gst_sbc_util_fill_sbc_params(sbc_t *sbc, GstCaps *caps); From dace80cc41fbb58aaf489515304f7cf12e0c5fcb Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Wed, 26 Sep 2012 09:54:01 +0800 Subject: [PATCH 48/57] sbc: audio: Initialise SBC data before use in sbcparse element --- ext/sbc/gstsbcparse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index 71c99d9204..0777295ccd 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -84,6 +84,8 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) GstBuffer *output; int consumed; + sbc_init (&parse->new_sbc, 0); + consumed = sbc_parse (&parse->new_sbc, data + offset, size - offset); if (consumed <= 0) break; @@ -100,6 +102,8 @@ sbc_parse_chain (GstPad * pad, GstBuffer * buffer) parse->first_parsing = FALSE; } + sbc_finish (&parse->new_sbc); + res = gst_pad_alloc_buffer_and_set_caps (parse->srcpad, GST_BUFFER_OFFSET_NONE, consumed, parse->outcaps, &output); From c6f6cc736f73dad384843648d5667833a214f46c Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Fri, 12 Oct 2012 18:53:16 +0530 Subject: [PATCH 49/57] sbc: audio: Fix a leak in sbcdec --- ext/sbc/gstsbcdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index e70232b7e0..7f61a21a4d 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -107,6 +107,7 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) gst_pad_template_get_caps (template)); gst_caps_unref (caps); + gst_object_unref (template); } gst_buffer_set_caps (output, dec->outcaps); From 9581e704b67747c0460490db0c230850910872cc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 29 Oct 2012 12:37:09 +0000 Subject: [PATCH 50/57] sbc: dec: chain up to parent before downward state change --- ext/sbc/gstsbcdec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 7f61a21a4d..fe29259ffb 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -135,6 +135,7 @@ done: static GstStateChangeReturn sbc_dec_change_state (GstElement * element, GstStateChange transition) { + GstStateChangeReturn result; GstSbcDec *dec = GST_SBC_DEC (element); switch (transition) { @@ -147,7 +148,13 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) sbc_init (&dec->sbc, 0); dec->outcaps = NULL; break; + default: + break; + } + result = parent_class->change_state (element, transition); + + switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG ("Finish subband codec"); if (dec->buffer) { @@ -165,7 +172,7 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) break; } - return parent_class->change_state (element, transition); + return result; } static void From 7e65f96acb33ab0a7a2c42a433cd5d637df97a7f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 29 Oct 2012 12:49:53 +0000 Subject: [PATCH 51/57] sbc: enc: sbc_get_frame_duration is in milliseconds --- ext/sbc/gstsbcenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index 605ff93c28..6f80959d70 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -354,7 +354,7 @@ gst_sbc_enc_fill_sbc_params (GstSbcEnc * enc, GstCaps * caps) 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); + enc->frame_duration = sbc_get_frame_duration (&enc->sbc) * 1000; GST_DEBUG_OBJECT (enc, "codesize: %d, frame_length: %d, frame_duration:" " %d", enc->codesize, enc->frame_length, enc->frame_duration); From 32154c5ae696aa5368bab37eee1f7dbcd0788e94 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Wed, 3 Oct 2012 12:47:14 +0530 Subject: [PATCH 52/57] sbc: audio: Make the sbcdec element copy buffer metadata Makes sure we don't lose timestamps, etc. --- ext/sbc/gstsbcdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index fe29259ffb..12df308a3c 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -112,8 +112,7 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_set_caps (output, dec->outcaps); - /* FIXME get a real timestamp */ - GST_BUFFER_TIMESTAMP (output) = GST_CLOCK_TIME_NONE; + gst_buffer_copy_metadata (output, buffer, GST_BUFFER_COPY_TIMESTAMPS); res = gst_pad_push (dec->srcpad, output); if (res != GST_FLOW_OK) From beaeeafb4dbe2ce6493dd489a1374153e1cb067d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 29 Oct 2012 17:19:50 +0000 Subject: [PATCH 53/57] sbc: sbcdec: handle DISCONT and timestamps Reset state on discont. Interpollate timestamps. --- ext/sbc/gstsbcdec.c | 55 ++++++++++++++++++++++++++++++++++++++++----- ext/sbc/gstsbcdec.h | 1 + 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 12df308a3c..180c1379a8 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -61,9 +61,18 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) GstFlowReturn res = GST_FLOW_OK; guint size, codesize, offset = 0; guint8 *data; + GstClockTime timestamp; codesize = sbc_get_codesize (&dec->sbc); + if (GST_BUFFER_IS_DISCONT (buffer)) { + /* reset previous buffer */ + gst_buffer_unref (dec->buffer); + dec->buffer = NULL; + /* we need a new timestamp to lock onto */ + dec->next_sample = -1; + } + if (dec->buffer) { GstBuffer *temp = buffer; buffer = gst_buffer_span (dec->buffer, 0, buffer, @@ -76,11 +85,16 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); + + while (offset < size) { GstBuffer *output; GstPadTemplate *template; GstCaps *caps; int consumed; + GstClockTime duration; + gint rate, channels; res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, codesize, NULL, &output); @@ -90,16 +104,46 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) consumed = sbc_decode (&dec->sbc, data + offset, size - offset, GST_BUFFER_DATA (output), codesize, NULL); + GST_INFO_OBJECT (dec, "consumed %d bytes", consumed); + if (consumed <= 0) break; + rate = gst_sbc_parse_rate_from_sbc (dec->sbc.frequency); + channels = gst_sbc_get_channel_number (dec->sbc.mode); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* lock onto timestamp when we have one */ + dec->next_sample = gst_util_uint64_scale_int (timestamp, + rate, GST_SECOND); + } + if (dec->next_sample != (guint64) - 1) { + /* reconstruct timestamp from our sample counter otherwise */ + timestamp = gst_util_uint64_scale_int (dec->next_sample, + GST_SECOND, rate); + } + GST_BUFFER_TIMESTAMP (output) = timestamp; + + /* calculate the next sample */ + if (dec->next_sample != (guint64) - 1) { + /* we ave a valid sample, counter, increment it. */ + dec->next_sample += codesize / (2 * channels); + duration = gst_util_uint64_scale_int (dec->next_sample, + GST_SECOND, rate) - timestamp; + } else { + /* otherwise calculate duration based on output size */ + duration = gst_util_uint64_scale_int (codesize / (2 * channels), + GST_SECOND, rate) - timestamp; + } + GST_BUFFER_DURATION (output) = duration; + + /* reset timestamp for next round */ + timestamp = GST_CLOCK_TIME_NONE; + /* 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); + "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL); template = gst_static_pad_template_get (&sbc_dec_src_factory); @@ -112,8 +156,6 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_set_caps (output, dec->outcaps); - gst_buffer_copy_metadata (output, buffer, GST_BUFFER_COPY_TIMESTAMPS); - res = gst_pad_push (dec->srcpad, output); if (res != GST_FLOW_OK) goto done; @@ -146,6 +188,7 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) } sbc_init (&dec->sbc, 0); dec->outcaps = NULL; + dec->next_sample = -1; break; default: break; diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index c77feaed30..a62e61b2f8 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -53,6 +53,7 @@ struct _GstSbcDec { GstCaps *outcaps; sbc_t sbc; + guint64 next_sample; }; struct _GstSbcDecClass { From a559bb7060a68dff1fcc2e99fc7c67149a570ec4 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 29 Oct 2012 17:22:28 +0000 Subject: [PATCH 54/57] sbc: sbcdec: set DISCONT on outgoing buffers. --- ext/sbc/gstsbcdec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 180c1379a8..98aa94b6f3 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -62,10 +62,12 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) guint size, codesize, offset = 0; guint8 *data; GstClockTime timestamp; + gboolean discont; codesize = sbc_get_codesize (&dec->sbc); - if (GST_BUFFER_IS_DISCONT (buffer)) { + discont = GST_BUFFER_IS_DISCONT (buffer); + if (discont) { /* reset previous buffer */ gst_buffer_unref (dec->buffer); dec->buffer = NULL; @@ -156,6 +158,11 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_set_caps (output, dec->outcaps); + if (discont) { + GST_BUFFER_FLAG_SET (output, GST_BUFFER_FLAG_DISCONT); + discont = FALSE; + } + res = gst_pad_push (dec->srcpad, output); if (res != GST_FLOW_OK) goto done; From dcb57780efb9d4b63f59f7404f37a1756d942bf3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 30 Oct 2012 18:41:56 +0000 Subject: [PATCH 55/57] sbc: sbcdec: skip the frame on decoding error --- ext/sbc/gstsbcdec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 98aa94b6f3..808344617a 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -108,8 +108,10 @@ sbc_dec_chain (GstPad * pad, GstBuffer * buffer) GST_BUFFER_DATA (output), codesize, NULL); GST_INFO_OBJECT (dec, "consumed %d bytes", consumed); - if (consumed <= 0) - break; + if (consumed <= 0) { + offset += sbc_get_frame_length (&dec->sbc); + continue; + } rate = gst_sbc_parse_rate_from_sbc (dec->sbc.frequency); channels = gst_sbc_get_channel_number (dec->sbc.mode); From 91f4b15490d3006afaf91482e3af737acdba5e8b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 8 Jan 2013 10:19:39 +0100 Subject: [PATCH 56/57] sbc: sbcdec: make decoder more performant Use an adapter to accumulate input buffers. Decode all input in one output buffer when possible to reduce the amount of push operations. --- ext/sbc/gstsbcdec.c | 230 +++++++++++++++++++++++++++----------------- ext/sbc/gstsbcdec.h | 4 +- 2 files changed, 145 insertions(+), 89 deletions(-) diff --git a/ext/sbc/gstsbcdec.c b/ext/sbc/gstsbcdec.c index 808344617a..12245f9d7a 100644 --- a/ext/sbc/gstsbcdec.c +++ b/ext/sbc/gstsbcdec.c @@ -31,9 +31,13 @@ #include "gstsbcutil.h" #include "gstsbcdec.h" +#define BUF_SIZE 8192 + GST_DEBUG_CATEGORY_STATIC (sbc_dec_debug); #define GST_CAT_DEFAULT sbc_dec_debug +static void gst_sbc_dec_finalize (GObject * obj); + GST_BOILERPLATE (GstSbcDec, gst_sbc_dec, GstElement, GST_TYPE_ELEMENT); static const GstElementDetails sbc_dec_details = @@ -54,136 +58,178 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "endianness = (int) BYTE_ORDER, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")); +static GstFlowReturn +gst_sbc_dec_flush (GstSbcDec * dec, GstBuffer * outbuf, + gint outoffset, gint channels, gint rate) +{ + GstClockTime outtime, duration; + + /* we will reuse the same caps object */ + if (dec->outcaps == NULL) { + GstCaps *caps; + GstPadTemplate *template; + + caps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL); + + template = gst_static_pad_template_get (&sbc_dec_src_factory); + + dec->outcaps = gst_caps_intersect (caps, + gst_pad_template_get_caps (template)); + + gst_caps_unref (caps); + gst_object_unref (template); + } + + gst_buffer_set_caps (outbuf, dec->outcaps); + + /* calculate duration */ + outtime = GST_BUFFER_TIMESTAMP (outbuf); + if (dec->next_timestamp != (guint64) - 1 && outtime != (guint64) - 1) { + duration = dec->next_timestamp - outtime; + } else if (outtime != (guint64) - 1) { + /* otherwise calculate duration based on outbuf size */ + duration = gst_util_uint64_scale_int (outoffset / (2 * channels), + GST_SECOND, rate) - outtime; + } else { + duration = GST_CLOCK_TIME_NONE; + } + GST_BUFFER_DURATION (outbuf) = duration; + GST_BUFFER_SIZE (outbuf) = outoffset; + + return gst_pad_push (dec->srcpad, outbuf); + +} + 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; + const guint8 *indata; + guint insize; GstClockTime timestamp; gboolean discont; - - codesize = sbc_get_codesize (&dec->sbc); + GstBuffer *outbuf; + guint8 *outdata; + guint inoffset, outoffset; + gint rate, channels; discont = GST_BUFFER_IS_DISCONT (buffer); if (discont) { /* reset previous buffer */ - gst_buffer_unref (dec->buffer); - dec->buffer = NULL; + gst_adapter_clear (dec->adapter); /* we need a new timestamp to lock onto */ dec->next_sample = -1; } - 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); + gst_adapter_push (dec->adapter, buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); + if (GST_CLOCK_TIME_IS_VALID (timestamp)) + dec->next_timestamp = timestamp; + + insize = gst_adapter_available (dec->adapter); + indata = gst_adapter_peek (dec->adapter, insize); - while (offset < size) { - GstBuffer *output; - GstPadTemplate *template; - GstCaps *caps; - int consumed; - GstClockTime duration; - gint rate, channels; + inoffset = 0; + outbuf = NULL; + channels = rate = 0; - res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, - GST_BUFFER_OFFSET_NONE, codesize, NULL, &output); + while (insize > 0) { + gint inconsumed, outlen; + gint outsize; + size_t outconsumed; - if (res != GST_FLOW_OK) - goto done; + if (outbuf == NULL) { + res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, + GST_BUFFER_OFFSET_NONE, BUF_SIZE, NULL, &outbuf); - consumed = sbc_decode (&dec->sbc, data + offset, size - offset, - GST_BUFFER_DATA (output), codesize, NULL); - GST_INFO_OBJECT (dec, "consumed %d bytes", consumed); + if (res != GST_FLOW_OK) + goto done; - if (consumed <= 0) { - offset += sbc_get_frame_length (&dec->sbc); + if (discont) { + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); + discont = FALSE; + } + + GST_BUFFER_TIMESTAMP (outbuf) = dec->next_timestamp; + outdata = GST_BUFFER_DATA (outbuf); + outsize = GST_BUFFER_SIZE (outbuf); + outoffset = 0; + } + + GST_INFO_OBJECT (dec, "inoffset %d/%d, outoffset %d/%d", inoffset, + insize, outoffset, outsize); + + inconsumed = sbc_decode (&dec->sbc, indata + inoffset, insize, + outdata + outoffset, outsize, &outconsumed); + + GST_INFO_OBJECT (dec, "consumed %d, produced %d", inconsumed, outconsumed); + + if (inconsumed <= 0) { + guint frame_len = sbc_get_frame_length (&dec->sbc); + /* skip a frame */ + if (insize > frame_len) { + insize -= frame_len; + inoffset += frame_len; + } else { + insize = 0; + } continue; } + inoffset += inconsumed; + if ((gint) insize > inconsumed) + insize -= inconsumed; + else + insize = 0; + outoffset += outconsumed; + outsize -= outconsumed; + rate = gst_sbc_parse_rate_from_sbc (dec->sbc.frequency); channels = gst_sbc_get_channel_number (dec->sbc.mode); + /* calculate timestamp either from the incomming buffers or + * from our sample counter */ if (GST_CLOCK_TIME_IS_VALID (timestamp)) { /* lock onto timestamp when we have one */ dec->next_sample = gst_util_uint64_scale_int (timestamp, rate, GST_SECOND); + timestamp = GST_CLOCK_TIME_NONE; } if (dec->next_sample != (guint64) - 1) { - /* reconstruct timestamp from our sample counter otherwise */ - timestamp = gst_util_uint64_scale_int (dec->next_sample, + /* calculate the next sample */ + dec->next_sample += outconsumed / (2 * channels); + dec->next_timestamp = gst_util_uint64_scale_int (dec->next_sample, GST_SECOND, rate); } - GST_BUFFER_TIMESTAMP (output) = timestamp; - /* calculate the next sample */ - if (dec->next_sample != (guint64) - 1) { - /* we ave a valid sample, counter, increment it. */ - dec->next_sample += codesize / (2 * channels); - duration = gst_util_uint64_scale_int (dec->next_sample, - GST_SECOND, rate) - timestamp; - } else { - /* otherwise calculate duration based on output size */ - duration = gst_util_uint64_scale_int (codesize / (2 * channels), - GST_SECOND, rate) - timestamp; - } - GST_BUFFER_DURATION (output) = duration; + /* check for space, push outbuf buffer */ + outlen = sbc_get_codesize (&dec->sbc); + if (outsize < outlen) { + res = gst_sbc_dec_flush (dec, outbuf, outoffset, channels, rate); + if (res != GST_FLOW_OK) + goto done; - /* reset timestamp for next round */ - timestamp = GST_CLOCK_TIME_NONE; - - /* we will reuse the same caps object */ - if (dec->outcaps == NULL) { - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL); - - template = gst_static_pad_template_get (&sbc_dec_src_factory); - - dec->outcaps = gst_caps_intersect (caps, - gst_pad_template_get_caps (template)); - - gst_caps_unref (caps); - gst_object_unref (template); + outbuf = NULL; } - gst_buffer_set_caps (output, dec->outcaps); - - if (discont) { - GST_BUFFER_FLAG_SET (output, GST_BUFFER_FLAG_DISCONT); - discont = FALSE; - } - - 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); + if (outbuf) + res = gst_sbc_dec_flush (dec, outbuf, outoffset, channels, rate); + gst_adapter_flush (dec->adapter, inoffset); done: - gst_buffer_unref (buffer); gst_object_unref (dec); return res; } static GstStateChangeReturn -sbc_dec_change_state (GstElement * element, GstStateChange transition) +gst_sbc_dec_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn result; GstSbcDec *dec = GST_SBC_DEC (element); @@ -191,10 +237,6 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) 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; dec->next_sample = -1; @@ -208,10 +250,7 @@ sbc_dec_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG ("Finish subband codec"); - if (dec->buffer) { - gst_buffer_unref (dec->buffer); - dec->buffer = NULL; - } + gst_adapter_clear (dec->adapter); sbc_finish (&dec->sbc); if (dec->outcaps) { gst_caps_unref (dec->outcaps); @@ -243,11 +282,14 @@ gst_sbc_dec_base_init (gpointer g_class) static void gst_sbc_dec_class_init (GstSbcDecClass * klass) { + GObjectClass *object_class = G_OBJECT_CLASS (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); + object_class->finalize = GST_DEBUG_FUNCPTR (gst_sbc_dec_finalize); + + element_class->change_state = GST_DEBUG_FUNCPTR (gst_sbc_dec_change_state); GST_DEBUG_CATEGORY_INIT (sbc_dec_debug, "sbcdec", 0, "SBC decoding element"); } @@ -263,9 +305,21 @@ gst_sbc_dec_init (GstSbcDec * self, GstSbcDecClass * klass) self->srcpad = gst_pad_new_from_static_template (&sbc_dec_src_factory, "src"); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + self->adapter = gst_adapter_new (); self->outcaps = NULL; } +static void +gst_sbc_dec_finalize (GObject * obj) +{ + GstSbcDec *self = GST_SBC_DEC (obj); + + g_object_unref (self->adapter); + + G_OBJECT_CLASS (parent_class)->finalize (obj); + +} + gboolean gst_sbc_dec_plugin_init (GstPlugin * plugin) { diff --git a/ext/sbc/gstsbcdec.h b/ext/sbc/gstsbcdec.h index a62e61b2f8..f5b9416a98 100644 --- a/ext/sbc/gstsbcdec.h +++ b/ext/sbc/gstsbcdec.h @@ -22,6 +22,7 @@ */ #include +#include #include "sbc.h" @@ -47,13 +48,14 @@ struct _GstSbcDec { GstPad *sinkpad; GstPad *srcpad; - GstBuffer *buffer; + GstAdapter *adapter; /* caps for outgoing buffers */ GstCaps *outcaps; sbc_t sbc; guint64 next_sample; + guint64 next_timestamp; }; struct _GstSbcDecClass { From 50643d6192636d16771f39c78ac22b79a0b5d451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 27 Mar 2013 00:56:31 +0000 Subject: [PATCH 57/57] sbc: remove parser in favour of new GstBaseParse-based sbcparse in -good --- ext/sbc/gstsbcparse.c | 222 ------------------------------------------ ext/sbc/gstsbcparse.h | 69 ------------- 2 files changed, 291 deletions(-) delete mode 100644 ext/sbc/gstsbcparse.c delete mode 100644 ext/sbc/gstsbcparse.h diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c deleted file mode 100644 index 0777295ccd..0000000000 --- a/ext/sbc/gstsbcparse.c +++ /dev/null @@ -1,222 +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; - - sbc_init (&parse->new_sbc, 0); - - 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; - } - - sbc_finish (&parse->new_sbc); - - 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/ext/sbc/gstsbcparse.h b/ext/sbc/gstsbcparse.h deleted file mode 100644 index ecb8be426a..0000000000 --- a/ext/sbc/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