[farsight2/master] Add special source for Dtmf as sound

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:21:42 PST 2008


---
 gst/fsrtpconference/Makefile.am                |    6 +-
 gst/fsrtpconference/fs-rtp-dtmf-sound-source.c |  336 ++++++++++++++++++++++++
 gst/fsrtpconference/fs-rtp-dtmf-sound-source.h |   74 ++++++
 gst/fsrtpconference/fs-rtp-special-source.c    |    3 +
 tests/rtp/Makefile.am                          |    3 +-
 5 files changed, 419 insertions(+), 3 deletions(-)
 create mode 100644 gst/fsrtpconference/fs-rtp-dtmf-sound-source.c
 create mode 100644 gst/fsrtpconference/fs-rtp-dtmf-sound-source.h

diff --git a/gst/fsrtpconference/Makefile.am b/gst/fsrtpconference/Makefile.am
index b185b57..8d24bed 100644
--- a/gst/fsrtpconference/Makefile.am
+++ b/gst/fsrtpconference/Makefile.am
@@ -11,7 +11,8 @@ libfsrtpconference_la_SOURCES = gstfsrtpconference.c \
 	fs-rtp-codec-negotiation.c \
 	fs-rtp-specific-nego.c \
 	fs-rtp-special-source.c \
-	fs-rtp-dtmf-event-source.c
+	fs-rtp-dtmf-event-source.c \
+	fs-rtp-dtmf-sound-source.c
 
 libfsrtpconference_la_CFLAGS = $(FS2_INTERNAL_CFLAGS) $(FS2_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
 libfsrtpconference_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
@@ -31,4 +32,5 @@ noinst_HEADERS = \
 	fs-rtp-codec-negotiation.h \
 	fs-rtp-specific-nego.h \
 	fs-rtp-special-source.h \
-	fs-rtp-dtmf-event-source.h
+	fs-rtp-dtmf-event-source.h \
+	fs-rtp-dtmf-sound-source.h
diff --git a/gst/fsrtpconference/fs-rtp-dtmf-sound-source.c b/gst/fsrtpconference/fs-rtp-dtmf-sound-source.c
new file mode 100644
index 0000000..a0c08eb
--- /dev/null
+++ b/gst/fsrtpconference/fs-rtp-dtmf-sound-source.c
@@ -0,0 +1,336 @@
+/*
+ * Farsight2 - Farsight RTP DTMF Sound Source
+ *
+ * Copyright 2007 Collabora Ltd.
+ *  @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ * Copyright 2007 Nokia Corp.
+ *
+ * fs-rtp-dtmf-sound-source.c - A Farsight RTP Sound Source gobject
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/farsight/fs-base-conference.h>
+
+#include "fs-rtp-conference.h"
+#include "fs-rtp-discover-codecs.h"
+
+#include "fs-rtp-dtmf-sound-source.h"
+
+#define GST_CAT_DEFAULT fsrtpconference_debug
+
+/**
+ * SECTION:fs-rtp-dtmf-sound-source
+ * @short_description: Class to create the source of DTMF sounds
+ *
+ * This class is manages the DTMF Sound source and related matters
+ *
+ */
+
+
+/* all privates variables are protected by the mutex */
+struct _FsRtpDtmfSoundSourcePrivate {
+  gboolean disposed;
+};
+
+static FsRtpSpecialSourceClass *parent_class = NULL;
+
+G_DEFINE_TYPE(FsRtpDtmfSoundSource, fs_rtp_dtmf_sound_source,
+    FS_TYPE_RTP_SPECIAL_SOURCE);
+
+#define FS_RTP_DTMF_SOUND_SOURCE_GET_PRIVATE(o)                         \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_RTP_DTMF_SOUND_SOURCE,     \
+   FsRtpDtmfSoundSourcePrivate))
+
+
+static GstElement *
+fs_rtp_dtmf_sound_source_build (FsRtpSpecialSource *source,
+    GList *negotiated_codecs,
+    FsCodec *selected_codec,
+    GError **error);
+
+
+static gboolean fs_rtp_dtmf_sound_source_class_want_source (
+    FsRtpSpecialSourceClass *klass,
+    GList *negotiated_codecs,
+    FsCodec *selected_codec);
+
+static void
+fs_rtp_dtmf_sound_source_class_init (FsRtpDtmfSoundSourceClass *klass)
+{
+  FsRtpSpecialSourceClass *spsource_class = FS_RTP_SPECIAL_SOURCE_CLASS (klass);
+  parent_class = fs_rtp_dtmf_sound_source_parent_class;
+
+  spsource_class->build = fs_rtp_dtmf_sound_source_build;
+  spsource_class->want_source = fs_rtp_dtmf_sound_source_class_want_source;
+
+  g_type_class_add_private (klass, sizeof (FsRtpDtmfSoundSourcePrivate));
+}
+
+static void
+fs_rtp_dtmf_sound_source_init (FsRtpDtmfSoundSource *self)
+{
+  FsRtpSpecialSource *source = FS_RTP_SPECIAL_SOURCE (self);
+
+  self->priv = FS_RTP_DTMF_SOUND_SOURCE_GET_PRIVATE (self);
+
+  source->order = 2;
+}
+
+/**
+ * get_telephone_sound_codec:
+ * @codecs: a #GList of #FsCodec
+ *
+ * Find the first occurence of PCMA or PCMU codecs
+ *
+ * Returns: The #FsCodec of type PCMA/U from the list or %NULL
+ */
+static FsCodec *
+get_pcm_law_sound_codec (GList *codecs,
+    gchar **encoder_name,
+    gchar **payloader_name)
+{
+  GList *item = NULL;
+  for (item = g_list_first (codecs);
+       item;
+       item = g_list_next (item))
+  {
+    FsCodec *codec = item->data;
+
+    if (codec->media_type == FS_MEDIA_TYPE_AUDIO &&
+        (codec->id == 0 || codec->id == 8))
+    {
+
+      if (codec->id == 0)
+      {
+        if (encoder_name)
+          *encoder_name = "mulawenc";
+        if (payloader_name)
+          *payloader_name = "rtppcmupay";
+      }
+      else if (codec->id == 8)
+      {
+        if (encoder_name)
+          *encoder_name = "alawenc";
+        if (payloader_name)
+          *payloader_name = "rtppcmapay";
+      }
+
+      return codec;
+    }
+  }
+
+  return NULL;
+}
+
+static gboolean
+_check_element_factory (gchar *name)
+{
+  GstElementFactory *fact = NULL;
+
+  g_return_val_if_fail (name, FALSE);
+
+  fact = gst_element_factory_find ("dtmfsrc");
+  if (fact)
+    gst_object_unref (fact);
+
+  return (fact != NULL);
+}
+
+static gboolean
+fs_rtp_dtmf_sound_source_class_want_source (FsRtpSpecialSourceClass *klass,
+    GList *negotiated_codecs,
+    FsCodec *selected_codec)
+{
+  FsCodec *codec = NULL;
+  gchar *encoder_name = NULL;
+  gchar *payloader_name = NULL;
+
+  if (selected_codec->media_type != FS_MEDIA_TYPE_AUDIO)
+    return FALSE;
+
+  codec = get_pcm_law_sound_codec (negotiated_codecs,
+      &encoder_name, &payloader_name);
+  if (!codec)
+    return FALSE;
+
+
+  if (!_check_element_factory ("dtmfsrc"))
+    return FALSE;
+
+  if (!_check_element_factory (encoder_name))
+    return FALSE;
+  if (!_check_element_factory (payloader_name))
+      return FALSE;
+
+  return TRUE;
+}
+
+static GstElement *
+fs_rtp_dtmf_sound_source_build (FsRtpSpecialSource *source,
+    GList *negotiated_codecs,
+    FsCodec *selected_codec,
+    GError **error)
+{
+  FsCodec *telephony_codec = NULL;
+  GstCaps *caps = NULL;
+  GstPad *pad = NULL;
+  GstElement *dtmfsrc = NULL;
+  GstElement *capsfilter = NULL;
+  GstPad *ghostpad = NULL;
+  GstElement *bin = NULL;
+  GstElement *encoder = NULL;
+  GstElement *payloader = NULL;
+  gchar *encoder_name = NULL;
+  gchar *payloader_name = NULL;
+
+  telephony_codec = get_pcm_law_sound_codec (negotiated_codecs,
+      &encoder_name, &payloader_name);
+
+  if (!telephony_codec)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL,
+        "Could not find a pcma/pcmu to send dtmf on");
+    return NULL;
+  }
+
+  bin = gst_bin_new (NULL);
+
+  dtmfsrc = gst_element_factory_make ("dtmfsrc", NULL);
+  if (!dtmfsrc)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not make rtpdtmfsrc");
+    goto error;
+  }
+  if (!gst_bin_add (GST_BIN (bin), dtmfsrc))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not add rtpdtmfsrc to bin");
+    gst_object_unref (dtmfsrc);
+    goto error;
+  }
+
+  encoder = gst_element_factory_make (encoder_name, NULL);
+  if (!encoder)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not make %s", encoder_name);
+    goto error;
+  }
+  if (!gst_bin_add (GST_BIN (bin), encoder))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not add %s to bin", encoder_name);
+    gst_object_unref (dtmfsrc);
+    goto error;
+  }
+
+  if (!gst_element_link_pads (dtmfsrc, "src", encoder, "sink"))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not link the rtpdtmfsrc and %s", encoder_name);
+    goto error;
+  }
+
+  payloader = gst_element_factory_make (payloader_name, NULL);
+  if (!payloader)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not make %s", payloader_name);
+    goto error;
+  }
+  if (!gst_bin_add (GST_BIN (bin), payloader))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not add %s to bin", payloader_name);
+    gst_object_unref (dtmfsrc);
+    goto error;
+  }
+
+  if (!gst_element_link_pads (encoder, "src", payloader, "sink"))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not link the %s and %s", encoder_name, payloader_name);
+    goto error;
+  }
+
+  capsfilter = gst_element_factory_make ("capsfilter", NULL);
+  if (!capsfilter)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not make capsfilter");
+    goto error;
+  }
+  if (!gst_bin_add (GST_BIN (bin), capsfilter))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not add capsfilter to bin");
+    gst_object_unref (capsfilter);
+    goto error;
+  }
+
+  caps = fs_codec_to_gst_caps (telephony_codec);
+  g_object_set (capsfilter, "caps", caps, NULL);
+  {
+    gchar *str = gst_caps_to_string (caps);
+    GST_DEBUG ("Using caps %s for dtmf", str);
+    g_free (str);
+  }
+  gst_caps_unref (caps);
+
+  if (!gst_element_link_pads (payloader, "src", capsfilter, "sink"))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not link the %s and its capsfilter", payloader_name);
+    goto error;
+  }
+
+  pad = gst_element_get_static_pad (capsfilter, "src");
+  if (!pad)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not get \"src\" pad from capsfilter");
+    goto error;
+  }
+  ghostpad = gst_ghost_pad_new ("src", pad);
+  if (!ghostpad)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not create a ghostpad for capsfilter src pad for dtmfsrc");
+    goto error;
+  }
+  if (!gst_element_add_pad (bin, ghostpad))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not get \"src\" ghostpad to dtmf sound source bin");
+    gst_object_unref (pad);
+    goto error;
+  }
+  gst_object_unref (pad);
+
+  return bin;
+
+ error:
+  gst_object_unref (bin);
+
+  return NULL;
+}
+
diff --git a/gst/fsrtpconference/fs-rtp-dtmf-sound-source.h b/gst/fsrtpconference/fs-rtp-dtmf-sound-source.h
new file mode 100644
index 0000000..f85dc7b
--- /dev/null
+++ b/gst/fsrtpconference/fs-rtp-dtmf-sound-source.h
@@ -0,0 +1,74 @@
+/*
+ * Farsight2 - Farsight RTP DTMF Sound Source
+ *
+ * Copyright 2007 Collabora Ltd.
+ *  @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ * Copyright 2007 Nokia Corp.
+ *
+ * fs-rtp-dtmf-sound-source.h - A Farsight RTP Sound Source gobject
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+#ifndef __FS_RTP_DTMF_SOUND_SOURCE_H__
+#define __FS_RTP_DTMF_SOUND_SOURCE_H__
+
+#include "fs-rtp-special-source.h"
+
+G_BEGIN_DECLS
+
+/* TYPE MACROS */
+#define FS_TYPE_RTP_DTMF_SOUND_SOURCE \
+  (fs_rtp_dtmf_sound_source_get_type())
+#define FS_RTP_DTMF_SOUND_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_RTP_DTMF_SOUND_SOURCE, \
+      FsRtpDtmfSoundSource))
+#define FS_RTP_DTMF_SOUND_SOURCE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_RTP_DTMF_SOUND_SOURCE, \
+     FsRtpDtmfSoundSourceClass))
+#define FS_IS_RTP_DTMF_SOUND_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_RTP_DTMF_SOUND_SOURCE))
+#define FS_IS_RTP_DTMF_SOUND_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_RTP_DTMF_SOUND_SOURCE))
+#define FS_RTP_DTMF_SOUND_SOURCE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_RTP_DTMF_SOUND_SOURCE,   \
+    FsRtpDtmfSoundSourceClass))
+#define FS_RTP_DTMF_SOUND_SOURCE_CAST(obj) ((FsRtpDtmfSoundSource*) (obj))
+
+typedef struct _FsRtpDtmfSoundSource FsRtpDtmfSoundSource;
+typedef struct _FsRtpDtmfSoundSourceClass FsRtpDtmfSoundSourceClass;
+typedef struct _FsRtpDtmfSoundSourcePrivate FsRtpDtmfSoundSourcePrivate;
+
+struct _FsRtpDtmfSoundSourceClass
+{
+  FsRtpSpecialSourceClass parent_class;
+};
+
+/**
+ * FsRtpDtmfSoundSource:
+ *
+ */
+struct _FsRtpDtmfSoundSource
+{
+  FsRtpSpecialSource parent;
+  FsRtpDtmfSoundSourcePrivate *priv;
+};
+
+GType fs_rtp_dtmf_sound_source_get_type (void);
+
+G_END_DECLS
+
+#endif /* __FS_RTP_DTMF_SOUND_SOURCE_H__ */
diff --git a/gst/fsrtpconference/fs-rtp-special-source.c b/gst/fsrtpconference/fs-rtp-special-source.c
index 1da6a0d..7d3e50c 100644
--- a/gst/fsrtpconference/fs-rtp-special-source.c
+++ b/gst/fsrtpconference/fs-rtp-special-source.c
@@ -34,6 +34,7 @@
 #include "fs-rtp-special-source.h"
 
 #include "fs-rtp-dtmf-event-source.h"
+#include "fs-rtp-dtmf-sound-source.h"
 
 #define GST_CAT_DEFAULT fsrtpconference_debug
 
@@ -114,6 +115,8 @@ register_classes (gpointer data)
 
   my_classes = g_list_prepend (my_classes,
       g_type_class_ref (FS_TYPE_RTP_DTMF_EVENT_SOURCE));
+  my_classes = g_list_prepend (my_classes,
+      g_type_class_ref (FS_TYPE_RTP_DTMF_SOUND_SOURCE));
 
   return my_classes;
 }
diff --git a/tests/rtp/Makefile.am b/tests/rtp/Makefile.am
index 47969cd..35bb18a 100644
--- a/tests/rtp/Makefile.am
+++ b/tests/rtp/Makefile.am
@@ -5,7 +5,8 @@ codec_discovery_SOURCES = codec-discovery.c \
 		$(top_srcdir)/gst/fsrtpconference/fs-rtp-discover-codecs.c \
 		$(top_srcdir)/gst/fsrtpconference/fs-rtp-codec-cache.c \
 		$(top_srcdir)/gst/fsrtpconference/fs-rtp-special-source.c \
-		$(top_srcdir)/gst/fsrtpconference/fs-rtp-dtmf-event-source.c
+		$(top_srcdir)/gst/fsrtpconference/fs-rtp-dtmf-event-source.c \
+		$(top_srcdir)/gst/fsrtpconference/fs-rtp-dtmf-sound-source.c
 codec_discovery_CFLAGS = -I$(top_srcdir)/gst/fsrtpconference/ \
 	$(FS2_INTERNAL_CFLAGS) $(FS2_CFLAGS) $(GST_CFLAGS)  $(CFLAGS)
 LDADD = $(GST_LIBS) $(GST_CHECK_LIBS) \
-- 
1.5.6.5




More information about the farsight-commits mailing list