sbc: Make a2dpsink to act like a bin and split the payloader.
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>
Wed, 23 Jan 2008 13:14:02 +0000 (13:14 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Wed, 27 Mar 2013 22:21:15 +0000 (22:21 +0000)
ext/sbc/gstsbcdec.c
ext/sbc/gstsbcdec.h
ext/sbc/gstsbcenc.c
ext/sbc/gstsbcenc.h
ext/sbc/gstsbcparse.c
ext/sbc/gstsbcparse.h
ext/sbc/gstsbcutil.c
ext/sbc/gstsbcutil.h

index 27386dd..b337858 100644 (file)
@@ -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);
+}
index 4a6922a..0bb0b57 100644 (file)
@@ -58,4 +58,6 @@ struct _GstSbcDecClass {
 
 GType gst_sbc_dec_get_type(void);
 
+gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin);
+
 G_END_DECLS
index 5d7a804..325a956 100644 (file)
@@ -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))
-    return FALSE;
-
-  if (!(mode = gst_structure_get_string (structure, "mode")))
-    return FALSE;
-  if (!(allocation = gst_structure_get_string (structure, "allocation")))
+  if (!gst_sbc_util_fill_sbc_params (&enc->sbc, caps))
     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);
+}
index d81428c..c7b2163 100644 (file)
@@ -68,4 +68,6 @@ struct _GstSbcEncClass {
 
 GType gst_sbc_enc_get_type(void);
 
+gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin);
+
 G_END_DECLS
index 93bae3a..acc002c 100644 (file)
@@ -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)
+static gboolean
+sbc_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
 {
-  GstCaps *result;
+  GstSbcParse *parse;
   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);
+  gint rate, channels;
+
+  parse = GST_SBC_PARSE (GST_PAD_PARENT (pad));
 
   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_get_int (structure, "rate", &rate))
+    return FALSE;
 
-  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_get_int (structure, "channels", &channels))
+    return FALSE;
 
-  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 (!(parse->rate == 0 || rate == parse->rate))
+    return FALSE;
 
-  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 (!(parse->channels == 0 || channels == parse->channels))
+    return FALSE;
 
-  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;
-  }
+  parse->rate = rate;
+  parse->channels = channels;
 
-  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);
-  }
+  return gst_sbc_util_fill_sbc_params (&parse->sbc, caps);
+}
 
-  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);
-  }
+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));
 
-error:
-  if (error) {
-    GST_ERROR_OBJECT (parse, "Invalid input caps: %s", error_message);
-    return NULL;
-  }
+  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);
 
-  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;
+  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_sink_setcaps (GstPad * pad, GstCaps * caps)
+sbc_parse_src_acceptcaps (GstPad * pad, GstCaps * caps)
 {
+  GstStructure *structure;
   GstSbcParse *parse;
-  GstCaps *inter, *other, *srccaps;
+  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);
 
-  gst_caps_unref (inter);
-  gst_caps_unref (other);
-  gst_caps_unref (srccaps);
+  if ((parse->rate == 0 || parse->rate == rate)
+      && (parse->channels == 0 || parse->channels == channels))
+    return TRUE;
 
-  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);
+}
index ceaf219..eb9ca44 100644 (file)
@@ -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
index b66a63b..a63fe9d 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include "ipc.h"
+#include <math.h>
 #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;
+}
index 4581abf..40b9eae 100644 (file)
@@ -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);