* [Bluez-devel] patches fixing gstreamer plugins
@ 2007-09-25 14:18 thiagoss
2007-09-25 15:51 ` thiagoss
2007-09-26 22:10 ` Marcel Holtmann
0 siblings, 2 replies; 4+ messages in thread
From: thiagoss @ 2007-09-25 14:18 UTC (permalink / raw)
To: bluez-devel
[-- Attachment #1.1: Type: text/plain, Size: 971 bytes --]
Patches for Bluez utils, modifying the sbcenc and sbcparse gstreamer plugins
on utils/audio
The problem:
The pipeline "filesrc ! audioconvert ! sbcenc ! sbcparse ! fakesink" is not
working
The reason:
The caps negotiation from both sbcenc and sbcparse was not working properly,
it was not resulting in a "fixed caps" (that defines one and only one media
type)
The solution:
Implement on both elements the setcaps for the sink pads.
The patch gstsbc_util.patch has to be applied first, it creates 2 new files(
a gstsbcutil.c and a gstsbcutil.h) that the other 2 patches use. Those files
implement a set of functions that both sbcenc and sbcparse use, most of them
are still to be improved,
The gstsbcenc.patch and sbcparse.patch implement the sink setcaps function
on the plugins, this function selects the better encoding parameters from
the possible ones, resulting in a "fixed caps".
I'll be waiting any questions and modification to the patches.
[]s
Thiago
[-- Attachment #1.2: Type: text/html, Size: 1080 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gstsbcenc.patch --]
[-- Type: text/x-patch; name="gstsbcenc.patch", Size: 7289 bytes --]
Index: audio/gstsbcenc.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/gstsbcenc.c,v
retrieving revision 1.4
diff -u -r1.4 gstsbcenc.c
--- audio/gstsbcenc.c 27 Aug 2007 14:10:00 -0000 1.4
+++ audio/gstsbcenc.c 24 Sep 2007 19:40:30 -0000
@@ -28,6 +28,14 @@
#include <string.h>
#include "gstsbcenc.h"
+#include "gstsbc_util.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
@@ -52,9 +60,31 @@
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,27 +115,94 @@
"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;
@@ -184,11 +281,23 @@
{
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;
@@ -204,13 +313,23 @@
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;
}
}
+
+
static void gst_sbc_enc_class_init(GstSbcEncClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
@@ -224,8 +343,24 @@
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");
@@ -234,9 +369,17 @@
static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)
{
self->sinkpad = gst_pad_new_from_static_template(&sbc_enc_sink_factory, "sink");
+ gst_pad_set_setcaps_function (self->sinkpad,
+ GST_DEBUG_FUNCPTR (sbc_enc_sink_setcaps));
gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);
self->srcpad = gst_pad_new_from_static_template(&sbc_enc_src_factory, "src");
gst_pad_set_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;
+
}
Index: audio/gstsbcenc.h
===================================================================
RCS file: /cvsroot/bluez/utils/audio/gstsbcenc.h,v
retrieving revision 1.3
diff -u -r1.3 gstsbcenc.h
--- audio/gstsbcenc.h 26 Aug 2007 13:12:47 -0000 1.3
+++ audio/gstsbcenc.h 24 Sep 2007 19:40:32 -0000
@@ -24,6 +24,8 @@
#include <gst/gst.h>
#include "sbc.h"
+#include "ipc.h"
+
G_BEGIN_DECLS
@@ -48,6 +50,9 @@
GstPad *srcpad;
gint mode;
+ gint blocks;
+ gint allocation;
+ gint subbands;
sbc_t sbc;
};
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: gstsbcparse.patch --]
[-- Type: text/x-patch; name="gstsbcparse.patch", Size: 6270 bytes --]
Index: audio/gstsbcparse.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/gstsbcparse.c,v
retrieving revision 1.1
diff -u -r1.1 gstsbcparse.c
--- audio/gstsbcparse.c 26 Aug 2007 13:59:05 -0000 1.1
+++ audio/gstsbcparse.c 24 Sep 2007 19:22:59 -0000
@@ -28,6 +28,7 @@
#include <string.h>
#include "gstsbcparse.h"
+#include "gstsbc_util.h"
GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug);
#define GST_CAT_DEFAULT sbc_parse_debug
@@ -54,6 +55,173 @@
"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)
{
GstSbcParse *parse = GST_SBC_PARSE(gst_pad_get_parent(pad));
@@ -78,31 +246,20 @@
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;
@@ -187,6 +344,8 @@
{
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_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");
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: gstsbcutil.patch --]
[-- Type: text/x-patch; name="gstsbcutil.patch", Size: 7851 bytes --]
Index: audio/gstsbcutil.c
===================================================================
RCS file: audio/gstsbcutil.c
diff -N audio/gstsbcutil.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ audio/gstsbcutil.c 24 Sep 2007 19:07:24 -0000
@@ -0,0 +1,197 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 "gstsbc_util.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;
+ }
+
+}
+
+
+
Index: audio/gstsbcutil.h
===================================================================
RCS file: audio/gstsbcutil.h
diff -N audio/gstsbcutil.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ audio/gstsbcutil.h 24 Sep 2007 19:07:25 -0000
@@ -0,0 +1,55 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 <gst/gst.h>
+
+
+
+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);
+
+
+
+
+
+
[-- Attachment #5: Type: text/plain, Size: 228 bytes --]
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
[-- Attachment #6: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [Bluez-devel] patches fixing gstreamer plugins
2007-09-25 14:18 [Bluez-devel] patches fixing gstreamer plugins thiagoss
@ 2007-09-25 15:51 ` thiagoss
2007-09-26 22:10 ` Marcel Holtmann
1 sibling, 0 replies; 4+ messages in thread
From: thiagoss @ 2007-09-25 15:51 UTC (permalink / raw)
To: bluez-devel
[-- Attachment #1.1: Type: text/plain, Size: 1180 bytes --]
Sorry, I attached the wrong versions from the patches, I'm attaching the
correct versions now.
On 9/25/07, thiagoss <thiagossantos@gmail.com> wrote:
>
> Patches for Bluez utils, modifying the sbcenc and sbcparse gstreamer
> plugins on utils/audio
>
>
> The problem:
> The pipeline "filesrc ! audioconvert ! sbcenc ! sbcparse ! fakesink" is
> not working
>
> The reason:
> The caps negotiation from both sbcenc and sbcparse was not working
> properly, it was not resulting in a "fixed caps" (that defines one and only
> one media type)
>
> The solution:
> Implement on both elements the setcaps for the sink pads.
>
>
> The patch gstsbc_util.patch has to be applied first, it creates 2 new
> files( a gstsbcutil.c and a gstsbcutil.h) that the other 2 patches use.
> Those files implement a set of functions that both sbcenc and sbcparse use,
> most of them are still to be improved,
>
> The gstsbcenc.patch and sbcparse.patch implement the sink setcaps function
> on the plugins, this function selects the better encoding parameters from
> the possible ones, resulting in a "fixed caps".
>
> I'll be waiting any questions and modification to the patches.
>
>
> []s
>
> Thiago
>
>
[-- Attachment #1.2: Type: text/html, Size: 1531 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gstsbcenc.patch --]
[-- Type: text/x-patch; name="gstsbcenc.patch", Size: 7288 bytes --]
Index: audio/gstsbcenc.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/gstsbcenc.c,v
retrieving revision 1.4
diff -u -r1.4 gstsbcenc.c
--- audio/gstsbcenc.c 27 Aug 2007 14:10:00 -0000 1.4
+++ audio/gstsbcenc.c 24 Sep 2007 19:40:30 -0000
@@ -28,6 +28,14 @@
#include <string.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_ALLOCATION CFG_ALLOCATION_AUTO
+
GST_DEBUG_CATEGORY_STATIC(sbc_enc_debug);
#define GST_CAT_DEFAULT sbc_enc_debug
@@ -52,9 +60,31 @@
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,27 +115,94 @@
"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;
@@ -184,11 +281,23 @@
{
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;
@@ -204,13 +313,23 @@
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;
}
}
+
+
static void gst_sbc_enc_class_init(GstSbcEncClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
@@ -224,8 +343,24 @@
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");
@@ -234,9 +369,17 @@
static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)
{
self->sinkpad = gst_pad_new_from_static_template(&sbc_enc_sink_factory, "sink");
+ gst_pad_set_setcaps_function (self->sinkpad,
+ GST_DEBUG_FUNCPTR (sbc_enc_sink_setcaps));
gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);
self->srcpad = gst_pad_new_from_static_template(&sbc_enc_src_factory, "src");
gst_pad_set_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;
+
}
Index: audio/gstsbcenc.h
===================================================================
RCS file: /cvsroot/bluez/utils/audio/gstsbcenc.h,v
retrieving revision 1.3
diff -u -r1.3 gstsbcenc.h
--- audio/gstsbcenc.h 26 Aug 2007 13:12:47 -0000 1.3
+++ audio/gstsbcenc.h 24 Sep 2007 19:40:32 -0000
@@ -24,6 +24,8 @@
#include <gst/gst.h>
#include "sbc.h"
+#include "ipc.h"
+
G_BEGIN_DECLS
@@ -48,6 +50,9 @@
GstPad *srcpad;
gint mode;
+ gint blocks;
+ gint allocation;
+ gint subbands;
sbc_t sbc;
};
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: gstsbcparse.patch --]
[-- Type: text/x-patch; name="gstsbcparse.patch", Size: 6269 bytes --]
Index: audio/gstsbcparse.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/gstsbcparse.c,v
retrieving revision 1.1
diff -u -r1.1 gstsbcparse.c
--- audio/gstsbcparse.c 26 Aug 2007 13:59:05 -0000 1.1
+++ audio/gstsbcparse.c 24 Sep 2007 19:22:59 -0000
@@ -28,6 +28,7 @@
#include <string.h>
#include "gstsbcparse.h"
+#include "gstsbcutil.h"
GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug);
#define GST_CAT_DEFAULT sbc_parse_debug
@@ -54,6 +55,173 @@
"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)
{
GstSbcParse *parse = GST_SBC_PARSE(gst_pad_get_parent(pad));
@@ -78,31 +246,20 @@
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;
@@ -187,6 +344,8 @@
{
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_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");
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: gstsbcutil.patch --]
[-- Type: text/x-patch; name="gstsbcutil.patch", Size: 8588 bytes --]
Index: audio/Makefile.am
===================================================================
RCS file: /cvsroot/bluez/utils/audio/Makefile.am,v
retrieving revision 1.37
diff -u -r1.37 Makefile.am
--- audio/Makefile.am 29 Aug 2007 11:30:47 -0000 1.37
+++ audio/Makefile.am 25 Sep 2007 15:39:35 -0000
@@ -43,7 +43,8 @@
gstsbcenc.h gstsbcenc.c \
gstsbcdec.h gstsbcdec.c \
gstsbcparse.h gstsbcparse.c \
- gsta2dpsink.h gsta2dpsink.c
+ gsta2dpsink.h gsta2dpsink.c \
+ gstsbcutil.h gstsbcutil.c
libgstbluetooth_la_LDFLAGS = -module -avoid-version -export-symbols-regex gst_plugin_desc
libgstbluetooth_la_LIBADD = @SBC_LIBS@ @GSTREAMER_LIBS@ -lgstaudio-0.10
libgstbluetooth_la_CFLAGS = @GSTREAMER_CFLAGS@ @SBC_CFLAGS@
Index: audio/gstsbcutil.c
===================================================================
RCS file: audio/gstsbcutil.c
diff -N audio/gstsbcutil.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ audio/gstsbcutil.c 25 Sep 2007 15:39:35 -0000
@@ -0,0 +1,197 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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;
+ }
+
+}
+
+
+
Index: audio/gstsbcutil.h
===================================================================
RCS file: audio/gstsbcutil.h
diff -N audio/gstsbcutil.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ audio/gstsbcutil.h 25 Sep 2007 15:39:35 -0000
@@ -0,0 +1,55 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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 <gst/gst.h>
+
+
+
+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);
+
+
+
+
+
+
[-- Attachment #5: Type: text/plain, Size: 228 bytes --]
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
[-- Attachment #6: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [Bluez-devel] patches fixing gstreamer plugins
2007-09-25 14:18 [Bluez-devel] patches fixing gstreamer plugins thiagoss
2007-09-25 15:51 ` thiagoss
@ 2007-09-26 22:10 ` Marcel Holtmann
2007-09-26 22:19 ` thiagoss
1 sibling, 1 reply; 4+ messages in thread
From: Marcel Holtmann @ 2007-09-26 22:10 UTC (permalink / raw)
To: BlueZ development
Hi Thiago,
> Patches for Bluez utils, modifying the sbcenc and sbcparse gstreamer
> plugins on utils/audio
>
>
> The problem:
> The pipeline "filesrc ! audioconvert ! sbcenc ! sbcparse ! fakesink"
> is not working
actually the sbcparse is only there for annotating an SBC stream. For
decoding the sbcdec should be used.
Regards
Marcel
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Bluez-devel] patches fixing gstreamer plugins
2007-09-26 22:10 ` Marcel Holtmann
@ 2007-09-26 22:19 ` thiagoss
0 siblings, 0 replies; 4+ messages in thread
From: thiagoss @ 2007-09-26 22:19 UTC (permalink / raw)
To: BlueZ development
[-- Attachment #1.1: Type: text/plain, Size: 1613 bytes --]
Hi Marcel
I know, the thing is the capabilities negotiation wasn't properly
implemented, some functions should have been overrided, sbcdec and sbcenc
should be enough to decode/encode, but since sbcparse was missing the same
thing sbcenc was, I did the work too.
If a use:
filesrc ! audioconvert ! sbcenc ! fakesink
it works, but that doesn't mean the problem isn't there, it just hasn't
ocurred, (the reason is that fakesink accept any kind of buffers, thus
negotiation is "everything is ok"), when I put sbcparse (even if its not
useful, it's just for testing) the negotiation should succeed, both of them
work with sbc, and it isn't succeeding.
Both sbcenc and sbcparse had a problem, the example I gave was only a
demonstration of the problem.
Regards
Thiago
On 9/26/07, Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Thiago,
>
> > Patches for Bluez utils, modifying the sbcenc and sbcparse gstreamer
> > plugins on utils/audio
> >
> >
> > The problem:
> > The pipeline "filesrc ! audioconvert ! sbcenc ! sbcparse ! fakesink"
> > is not working
>
> actually the sbcparse is only there for annotating an SBC stream. For
> decoding the sbcdec should be used.
>
> Regards
>
> Marcel
>
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2005.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel
>
[-- Attachment #1.2: Type: text/html, Size: 2226 bytes --]
[-- Attachment #2: Type: text/plain, Size: 228 bytes --]
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
[-- Attachment #3: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-09-26 22:19 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-25 14:18 [Bluez-devel] patches fixing gstreamer plugins thiagoss
2007-09-25 15:51 ` thiagoss
2007-09-26 22:10 ` Marcel Holtmann
2007-09-26 22:19 ` thiagoss
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox