[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