gst/hls/Android.mk \
gst/jp2kdecimator/Android.mk \
gst/segmentclip/Android.mk \
- gst/dtmf/Android.mk \
gst/mpeg4videoparse/Android.mk \
gst/siren/Android.mk \
gst/dataurisrc/Android.mk \
-include $(GST_PLUGINS_BAD_TOP)/gst/hls/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/jp2kdecimator/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/segmentclip/Android.mk
--include $(GST_PLUGINS_BAD_TOP)/gst/dtmf/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/mpeg4videoparse/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/siren/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/dataurisrc/Android.mk
AG_GST_CHECK_PLUGIN(dataurisrc)
AG_GST_CHECK_PLUGIN(dccp)
AG_GST_CHECK_PLUGIN(debugutils)
-AG_GST_CHECK_PLUGIN(dtmf)
AG_GST_CHECK_PLUGIN(dvbsuboverlay)
AG_GST_CHECK_PLUGIN(dvdspu)
AG_GST_CHECK_PLUGIN(faceoverlay)
gst/dataurisrc/Makefile
gst/dccp/Makefile
gst/debugutils/Makefile
-gst/dtmf/Makefile
gst/dvbsuboverlay/Makefile
gst/dvdspu/Makefile
gst/faceoverlay/Makefile
$(top_srcdir)/gst/dccp/gstdccpserversink.h \
$(top_srcdir)/gst/dccp/gstdccpserversrc.h \
$(top_srcdir)/gst/debugutils/fpsdisplaysink.h \
- $(top_srcdir)/gst/dtmf/gstdtmfsrc.h \
- $(top_srcdir)/gst/dtmf/gstrtpdtmfsrc.h \
- $(top_srcdir)/gst/dtmf/gstrtpdtmfdepay.h \
$(top_srcdir)/gst/dvdspu/gstdvdspu.h \
$(top_srcdir)/gst/festival/gstfestival.h \
$(top_srcdir)/gst/gaudieffects/gstburn.h \
<xi:include href="xml/element-dilate.xml" />
<xi:include href="xml/element-dodge.xml" />
<xi:include href="xml/element-dtmfdetect.xml" />
- <xi:include href="xml/element-dtmfsrc.xml" />
<xi:include href="xml/element-dtsdec.xml" />
<xi:include href="xml/element-dvbsrc.xml" />
<xi:include href="xml/element-dvdspu.xml" />
<xi:include href="xml/element-pyramidsegment.xml" />
<xi:include href="xml/element-rtmpsink.xml" />
<xi:include href="xml/element-rtmpsrc.xml" />
- <xi:include href="xml/element-rtpdtmfsrc.xml" />
<xi:include href="xml/element-shmsink.xml" />
<xi:include href="xml/element-shmsrc.xml" />
<xi:include href="xml/element-sdpdemux.xml" />
<xi:include href="xml/plugin-dataurisrc.xml" />
<xi:include href="xml/plugin-debugutilsbad.xml" />
<xi:include href="xml/plugin-dirac.xml" />
- <xi:include href="xml/plugin-dtmf.xml" />
<xi:include href="xml/plugin-dtsdec.xml" />
<xi:include href="xml/plugin-dvb.xml" />
<xi:include href="xml/plugin-dvdspu.xml" />
gst_dodge_plugin_init
</SECTION>
-<SECTION>
-<FILE>element-dtmfsrc</FILE>
-<TITLE>dtmfsrc</TITLE>
-GstDTMFSrc
-<SUBSECTION Standard>
-GstDTMFEventType
-GstDTMFSrcEvent
-GstDTMFSrcClass
-GST_TYPE_DTMF_SRC
-GST_DTMF_SRC
-GST_DTMF_SRC_CAST
-GST_DTMF_SRC_CLASS
-GST_DTMF_SRC_GET_CLASS
-GST_IS_DTMF_SRC
-GST_IS_DTMF_SRC_CLASS
-gst_dtmf_src_get_type
-gst_dtmf_src_plugin_init
-</SECTION>
-
<SECTION>
<FILE>element-dtmfdetect</FILE>
<TITLE>dtmfdetect</TITLE>
GST_IS_RTMP_SRC_CLASS
</SECTION>
-<SECTION>
-<FILE>element-rtpdtmfdepay</FILE>
-<TITLE>rtpdtmfdepay</TITLE>
-GstRtpDTMFDepay
-<SUBSECTION Standard>
-GstRtpDTMFDepayClass
-GST_TYPE_RTP_DTMF_DEPAY
-GST_IS_RTP_DTMF_DEPAY
-GST_IS_RTP_DTMF_DEPAY_CLASS
-GST_RTP_DTMF_DEPAY
-GST_RTP_DTMF_DEPAY_CLASS
-gst_rtp_dtmf_depay_plugin_init
-</SECTION>
-
-<SECTION>
-<FILE>element-rtpdtmfsrc</FILE>
-<TITLE>rtpdtmfsrc</TITLE>
-GstRTPDTMFSrc
-<SUBSECTION Standard>
-GstRTPDTMFSrcClass
-GST_TYPE_RTP_DTMF_SRC
-GST_IS_RTP_DTMF_SRC
-GST_IS_RTP_DTMF_SRC_CLASS
-GST_RTP_DTMF_SRC
-GST_RTP_DTMF_SRC_CAST
-GST_RTP_DTMF_SRC_CLASS
-GST_RTP_DTMF_SRC_GET_CLASS
-gst_rtp_dtmf_src_get_type
-gst_rtp_dtmf_src_plugin_init
-GstRTPDTMFPayload
-GstRTPDTMFSrcEvent
-GstRTPDTMFEventType
-</SECTION>
-
<SECTION>
<FILE>element-sdlaudiosink</FILE>
<TITLE>sdlaudiosink</TITLE>
+++ /dev/null
-<plugin>
- <name>dtmf</name>
- <description>DTMF plugins</description>
- <filename>../../gst/dtmf/.libs/libgstdtmf.so</filename>
- <basename>libgstdtmf.so</basename>
- <version>1.1.0.1</version>
- <license>LGPL</license>
- <source>gst-plugins-bad</source>
- <package>GStreamer Bad Plug-ins git</package>
- <origin>Unknown package origin</origin>
- <elements>
- <element>
- <name>dtmfdetect</name>
- <longname>DTMF detector element</longname>
- <class>Filter/Analyzer/Audio</class>
- <description>This element detects DTMF tones</description>
- <author>Olivier Crete <olivier.crete@collabora.com></author>
- <pads>
- <caps>
- <name>sink</name>
- <direction>sink</direction>
- <presence>always</presence>
- <details>audio/x-raw, format=(string)S16LE, rate=(int)8000, channels=(int)1</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>audio/x-raw, format=(string)S16LE, rate=(int)8000, channels=(int)1</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>dtmfsrc</name>
- <longname>DTMF tone generator</longname>
- <class>Source/Audio</class>
- <description>Generates DTMF tones</description>
- <author>Youness Alaoui <youness.alaoui@collabora.co.uk></author>
- <pads>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>audio/x-raw, format=(string)S16LE, rate=(int)[ 1, 2147483647 ], channels=(int)1</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>rtpdtmfdepay</name>
- <longname>RTP DTMF packet depayloader</longname>
- <class>Codec/Depayloader/Network</class>
- <description>Generates DTMF Sound from telephone-event RTP packets</description>
- <author>Youness Alaoui <youness.alaoui@collabora.co.uk></author>
- <pads>
- <caps>
- <name>sink</name>
- <direction>sink</direction>
- <presence>always</presence>
- <details>application/x-rtp, media=(string)audio, payload=(int)[ 96, 127 ], clock-rate=(int)[ 0, 2147483647 ], encoding-name=(string)TELEPHONE-EVENT</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>audio/x-raw, format=(string)S16LE, rate=(int)[ 1, 2147483647 ], channels=(int)1</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>rtpdtmfsrc</name>
- <longname>RTP DTMF packet generator</longname>
- <class>Source/Network</class>
- <description>Generates RTP DTMF packets</description>
- <author>Zeeshan Ali <zeeshan.ali@nokia.com></author>
- <pads>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>application/x-rtp, media=(string)audio, payload=(int)[ 96, 127 ], clock-rate=(int)[ 0, 2147483647 ], ssrc=(int)[ 0, 2147483647 ], encoding-name=(string)TELEPHONE-EVENT</details>
- </caps>
- </pads>
- </element>
- </elements>
-</plugin>
\ No newline at end of file
# %{_libdir}/gstreamer-%{majorminor}/libgstcoloreffects.so
%{_libdir}/gstreamer-%{majorminor}/libgstdataurisrc.so
# %{_libdir}/gstreamer-%{majorminor}/libgstdccp.so
-%{_libdir}/gstreamer-%{majorminor}/libgstdtmf.so
# %{_libdir}/gstreamer-%{majorminor}/libgstfestival.so
# %{_libdir}/gstreamer-%{majorminor}/libgstfrei0r.so
# %{_libdir}/gstreamer-%{majorminor}/libgstgaudieffects.so
+++ /dev/null
-plugin_LTLIBRARIES = libgstdtmf.la
-
-libgstdtmf_la_SOURCES = gstdtmfsrc.c \
- gstrtpdtmfsrc.c \
- gstrtpdtmfdepay.c \
- gstdtmf.c
-
-noinst_HEADERS = gstdtmfsrc.h \
- gstrtpdtmfsrc.h \
- gstrtpdtmfdepay.h \
- gstdtmfcommon.h
-
-libgstdtmf_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
-libgstdtmf_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_API_VERSION@ \
- $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
-libgstdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstdtmf_la_LIBTOOLFLAGS = --tag=disable-static
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
- androgenizer \
- -:PROJECT libgstdtmf -:SHARED libgstdtmf \
- -:TAGS eng debug \
- -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
- -:SOURCES $(libgstdtmf_la_SOURCES) \
- -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstdtmf_la_CFLAGS) \
- -:LDFLAGS $(libgstdtmf_la_LDFLAGS) \
- $(libgstdtmf_la_LIBADD) \
- -ldl \
- -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
- LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
- > $@
+++ /dev/null
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstdtmfsrc.h"
-#include "gstrtpdtmfsrc.h"
-#include "gstrtpdtmfdepay.h"
-
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_dtmf_src_plugin_init (plugin))
- return FALSE;
-
- if (!gst_rtp_dtmf_src_plugin_init (plugin))
- return FALSE;
-
- if (!gst_rtp_dtmf_depay_plugin_init (plugin))
- return FALSE;
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- dtmf, "DTMF plugins",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+++ /dev/null
-
-#ifndef __GST_RTP_DTMF_COMMON_H__
-#define __GST_RTP_DTMF_COMMON_H__
-
-#define MIN_INTER_DIGIT_INTERVAL 100 /* ms */
-#define MIN_PULSE_DURATION 250 /* ms */
-
-#define MIN_VOLUME 0
-#define MAX_VOLUME 36
-
-#define MIN_EVENT 0
-#define MAX_EVENT 15
-#define MIN_EVENT_STRING "0"
-#define MAX_EVENT_STRING "15"
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846 /* pi */
-#endif
-
-typedef struct
-{
- unsigned event:8; /* Current DTMF event */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- unsigned volume:6; /* power level of the tone, in dBm0 */
- unsigned r:1; /* Reserved-bit */
- unsigned e:1; /* End-bit */
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
- unsigned e:1; /* End-bit */
- unsigned r:1; /* Reserved-bit */
- unsigned volume:6; /* power level of the tone, in dBm0 */
-#else
-#error "G_BYTE_ORDER should be big or little endian."
-#endif
- unsigned duration:16; /* Duration of digit, in timestamp units */
-} GstRTPDTMFPayload;
-
-#endif /* __GST_RTP_DTMF_COMMON_H__ */
+++ /dev/null
-/* GStreamer DTMF source
- *
- * gstdtmfsrc.c:
- *
- * Copyright (C) <2007> Collabora.
- * Contact: Youness Alaoui <youness.alaoui@collabora.co.uk>
- * Copyright (C) <2007> Nokia Corporation.
- * Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000,2005 Wim Taymans <wim@fluendo.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-
-/**
- * SECTION:element-dtmfsrc
- * @see_also: rtpdtmsrc, rtpdtmfmuxx
- *
- * The DTMFSrc element generates DTMF (ITU-T Q.23 Specification) tone packets on request
- * from application. The application communicates the beginning and end of a
- * DTMF event using custom upstream gstreamer events. To report a DTMF event, an
- * application must send an event of type GST_EVENT_CUSTOM_UPSTREAM, having a
- * structure of name "dtmf-event" with fields set according to the following
- * table:
- *
- * <informaltable>
- * <tgroup cols='4'>
- * <colspec colname='Name' />
- * <colspec colname='Type' />
- * <colspec colname='Possible values' />
- * <colspec colname='Purpose' />
- * <thead>
- * <row>
- * <entry>Name</entry>
- * <entry>GType</entry>
- * <entry>Possible values</entry>
- * <entry>Purpose</entry>
- * </row>
- * </thead>
- * <tbody>
- * <row>
- * <entry>type</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-1</entry>
- * <entry>The application uses this field to specify which of the two methods
- * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
- * named events. Tones are specified by their frequencies and events are specied
- * by their number. This element can only take events as input. Do not confuse
- * with "method" which specified the output.
- * </entry>
- * </row>
- * <row>
- * <entry>number</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-15</entry>
- * <entry>The event number.</entry>
- * </row>
- * <row>
- * <entry>volume</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-36</entry>
- * <entry>This field describes the power level of the tone, expressed in dBm0
- * after dropping the sign. Power levels range from 0 to -63 dBm0. The range of
- * valid DTMF is from 0 to -36 dBm0. Can be omitted if start is set to FALSE.
- * </entry>
- * </row>
- * <row>
- * <entry>start</entry>
- * <entry>G_TYPE_BOOLEAN</entry>
- * <entry>True or False</entry>
- * <entry>Whether the event is starting or ending.</entry>
- * </row>
- * <row>
- * <entry>method</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>2</entry>
- * <entry>The method used for sending event, this element will react if this
- * field is absent or 2.
- * </entry>
- * </row>
- * </tbody>
- * </tgroup>
- * </informaltable>
- *
- * For example, the following code informs the pipeline (and in turn, the
- * DTMFSrc element inside the pipeline) about the start of a DTMF named
- * event '1' of volume -25 dBm0:
- *
- * <programlisting>
- * structure = gst_structure_new ("dtmf-event",
- * "type", G_TYPE_INT, 1,
- * "number", G_TYPE_INT, 1,
- * "volume", G_TYPE_INT, 25,
- * "start", G_TYPE_BOOLEAN, TRUE, NULL);
- *
- * event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
- * gst_element_send_event (pipeline, event);
- * </programlisting>
- *
- * When a DTMF tone actually starts or stop, a "dtmf-event-processed"
- * element #GstMessage with the same fields as the "dtmf-event"
- * #GstEvent that was used to request the event. Also, if any event
- * has not been processed when the element goes from the PAUSED to the
- * READY state, then a "dtmf-event-dropped" message is posted on the
- * #GstBus in the order that they were received.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include <glib.h>
-
-#include "gstdtmfcommon.h"
-
-#include "gstdtmfsrc.h"
-
-#include <gst/audio/audio.h>
-
-#define GST_TONE_DTMF_TYPE_EVENT 1
-#define DEFAULT_PACKET_INTERVAL 50 /* ms */
-#define MIN_PACKET_INTERVAL 10 /* ms */
-#define MAX_PACKET_INTERVAL 50 /* ms */
-#define DEFAULT_SAMPLE_RATE 8000
-#define SAMPLE_SIZE 16
-#define CHANNELS 1
-#define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION)
-
-
-typedef struct st_dtmf_key
-{
- const char *event_name;
- int event_encoding;
- float low_frequency;
- float high_frequency;
-} DTMF_KEY;
-
-static const DTMF_KEY DTMF_KEYS[] = {
- {"DTMF_KEY_EVENT_0", 0, 941, 1336},
- {"DTMF_KEY_EVENT_1", 1, 697, 1209},
- {"DTMF_KEY_EVENT_2", 2, 697, 1336},
- {"DTMF_KEY_EVENT_3", 3, 697, 1477},
- {"DTMF_KEY_EVENT_4", 4, 770, 1209},
- {"DTMF_KEY_EVENT_5", 5, 770, 1336},
- {"DTMF_KEY_EVENT_6", 6, 770, 1477},
- {"DTMF_KEY_EVENT_7", 7, 852, 1209},
- {"DTMF_KEY_EVENT_8", 8, 852, 1336},
- {"DTMF_KEY_EVENT_9", 9, 852, 1477},
- {"DTMF_KEY_EVENT_S", 10, 941, 1209},
- {"DTMF_KEY_EVENT_P", 11, 941, 1477},
- {"DTMF_KEY_EVENT_A", 12, 697, 1633},
- {"DTMF_KEY_EVENT_B", 13, 770, 1633},
- {"DTMF_KEY_EVENT_C", 14, 852, 1633},
- {"DTMF_KEY_EVENT_D", 15, 941, 1633},
-};
-
-#define MAX_DTMF_EVENTS 16
-
-enum
-{
- DTMF_KEY_EVENT_1 = 1,
- DTMF_KEY_EVENT_2 = 2,
- DTMF_KEY_EVENT_3 = 3,
- DTMF_KEY_EVENT_4 = 4,
- DTMF_KEY_EVENT_5 = 5,
- DTMF_KEY_EVENT_6 = 6,
- DTMF_KEY_EVENT_7 = 7,
- DTMF_KEY_EVENT_8 = 8,
- DTMF_KEY_EVENT_9 = 9,
- DTMF_KEY_EVENT_0 = 0,
- DTMF_KEY_EVENT_STAR = 10,
- DTMF_KEY_EVENT_POUND = 11,
- DTMF_KEY_EVENT_A = 12,
- DTMF_KEY_EVENT_B = 13,
- DTMF_KEY_EVENT_C = 14,
- DTMF_KEY_EVENT_D = 15,
-};
-
-GST_DEBUG_CATEGORY_STATIC (gst_dtmf_src_debug);
-#define GST_CAT_DEFAULT gst_dtmf_src_debug
-
-enum
-{
- PROP_0,
- PROP_INTERVAL,
-};
-
-static GstStaticPadTemplate gst_dtmf_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw, "
- "format = (string) \"" GST_AUDIO_NE (S16) "\", "
- "rate = " GST_AUDIO_RATE_RANGE ", " "channels = (int) 1")
- );
-
-#define parent_class gst_dtmf_src_parent_class
-G_DEFINE_TYPE (GstDTMFSrc, gst_dtmf_src, GST_TYPE_BASE_SRC);
-
-static void gst_dtmf_src_finalize (GObject * object);
-
-static void gst_dtmf_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_dtmf_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static gboolean gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event);
-static gboolean gst_dtmf_src_send_event (GstElement * src, GstEvent * event);
-static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element,
- GstStateChange transition);
-static GstFlowReturn gst_dtmf_src_create (GstBaseSrc * basesrc,
- guint64 offset, guint length, GstBuffer ** buffer);
-static void gst_dtmf_src_add_start_event (GstDTMFSrc * dtmfsrc,
- gint event_number, gint event_volume);
-static void gst_dtmf_src_add_stop_event (GstDTMFSrc * dtmfsrc);
-
-static gboolean gst_dtmf_src_unlock (GstBaseSrc * src);
-
-static gboolean gst_dtmf_src_unlock_stop (GstBaseSrc * src);
-static gboolean gst_dtmf_src_negotiate (GstBaseSrc * basesrc);
-
-
-static void
-gst_dtmf_src_class_init (GstDTMFSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstBaseSrcClass *gstbasesrc_class;
- GstElementClass *gstelement_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
-
-
- GST_DEBUG_CATEGORY_INIT (gst_dtmf_src_debug, "dtmfsrc", 0, "dtmfsrc element");
-
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_dtmf_src_template));
-
- gst_element_class_set_static_metadata (gstelement_class,
- "DTMF tone generator", "Source/Audio", "Generates DTMF tones",
- "Youness Alaoui <youness.alaoui@collabora.co.uk>");
-
-
- gobject_class->finalize = gst_dtmf_src_finalize;
- gobject_class->set_property = gst_dtmf_src_set_property;
- gobject_class->get_property = gst_dtmf_src_get_property;
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL,
- g_param_spec_uint ("interval", "Interval between tone packets",
- "Interval in ms between two tone packets", MIN_PACKET_INTERVAL,
- MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state);
- gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_dtmf_src_send_event);
- gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_dtmf_src_unlock);
- gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_dtmf_src_unlock_stop);
-
- gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_dtmf_src_handle_event);
- gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_dtmf_src_create);
- gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_dtmf_src_negotiate);
-}
-
-static void
-event_free (GstDTMFSrcEvent * event)
-{
- if (event)
- g_slice_free (GstDTMFSrcEvent, event);
-}
-
-static void
-gst_dtmf_src_init (GstDTMFSrc * dtmfsrc)
-{
- /* we operate in time */
- gst_base_src_set_format (GST_BASE_SRC (dtmfsrc), GST_FORMAT_TIME);
- gst_base_src_set_live (GST_BASE_SRC (dtmfsrc), TRUE);
-
- dtmfsrc->interval = DEFAULT_PACKET_INTERVAL;
-
- dtmfsrc->event_queue = g_async_queue_new_full ((GDestroyNotify) event_free);
- dtmfsrc->last_event = NULL;
-
- dtmfsrc->sample_rate = DEFAULT_SAMPLE_RATE;
-
- GST_DEBUG_OBJECT (dtmfsrc, "init done");
-}
-
-static void
-gst_dtmf_src_finalize (GObject * object)
-{
- GstDTMFSrc *dtmfsrc;
-
- dtmfsrc = GST_DTMF_SRC (object);
-
- if (dtmfsrc->event_queue) {
- g_async_queue_unref (dtmfsrc->event_queue);
- dtmfsrc->event_queue = NULL;
- }
-
- G_OBJECT_CLASS (gst_dtmf_src_parent_class)->finalize (object);
-}
-
-static gboolean
-gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, GstEvent * event)
-{
- const GstStructure *event_structure;
- GstStateChangeReturn sret;
- GstState state;
- gint event_type;
- gboolean start;
- gint method;
- GstClockTime last_stop;
- gint event_number;
- gint event_volume;
- gboolean correct_order;
-
- sret = gst_element_get_state (GST_ELEMENT (dtmfsrc), &state, NULL, 0);
- if (sret != GST_STATE_CHANGE_SUCCESS || state != GST_STATE_PLAYING) {
- GST_DEBUG_OBJECT (dtmfsrc, "dtmf-event, but not in PLAYING state");
- goto failure;
- }
-
- event_structure = gst_event_get_structure (event);
-
- if (!gst_structure_get_int (event_structure, "type", &event_type) ||
- !gst_structure_get_boolean (event_structure, "start", &start) ||
- (start == TRUE && event_type != GST_TONE_DTMF_TYPE_EVENT))
- goto failure;
-
- if (gst_structure_get_int (event_structure, "method", &method)) {
- if (method != 2) {
- goto failure;
- }
- }
-
- if (start)
- if (!gst_structure_get_int (event_structure, "number", &event_number) ||
- !gst_structure_get_int (event_structure, "volume", &event_volume))
- goto failure;
-
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (gst_structure_get_clock_time (event_structure, "last-stop", &last_stop))
- dtmfsrc->last_stop = last_stop;
- else
- dtmfsrc->last_stop = GST_CLOCK_TIME_NONE;
- correct_order = (start != dtmfsrc->last_event_was_start);
- dtmfsrc->last_event_was_start = start;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- if (!correct_order)
- goto failure;
-
- if (start) {
- GST_DEBUG_OBJECT (dtmfsrc, "Received start event %d with volume %d",
- event_number, event_volume);
- gst_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume);
- }
-
- else {
- GST_DEBUG_OBJECT (dtmfsrc, "Received stop event");
- gst_dtmf_src_add_stop_event (dtmfsrc);
- }
-
- return TRUE;
-failure:
- return FALSE;
-}
-
-static gboolean
-gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event)
-{
- GstDTMFSrc *dtmfsrc;
- gboolean result = FALSE;
-
- dtmfsrc = GST_DTMF_SRC (src);
-
- GST_LOG_OBJECT (dtmfsrc, "Received an %s event on the src pad",
- GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_CUSTOM_UPSTREAM:
- if (gst_event_has_name (event, "dtmf-event")) {
- result = gst_dtmf_src_handle_dtmf_event (dtmfsrc, event);
- break;
- }
- /* fall through */
- default:
- result = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
- break;
- }
-
- return result;
-}
-
-
-static gboolean
-gst_dtmf_src_send_event (GstElement * element, GstEvent * event)
-{
- GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (element);
- gboolean ret;
-
- GST_LOG_OBJECT (dtmfsrc, "Received an %s event via send_event",
- GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_CUSTOM_BOTH:
- case GST_EVENT_CUSTOM_BOTH_OOB:
- case GST_EVENT_CUSTOM_UPSTREAM:
- case GST_EVENT_CUSTOM_DOWNSTREAM:
- case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
- if (gst_event_has_name (event, "dtmf-event")) {
- ret = gst_dtmf_src_handle_dtmf_event (dtmfsrc, event);
- break;
- }
- /* fall through */
- default:
- ret = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
- break;
- }
-
- return ret;
-}
-
-static void
-gst_dtmf_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstDTMFSrc *dtmfsrc;
-
- dtmfsrc = GST_DTMF_SRC (object);
-
- switch (prop_id) {
- case PROP_INTERVAL:
- dtmfsrc->interval = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstDTMFSrc *dtmfsrc;
-
- dtmfsrc = GST_DTMF_SRC (object);
-
- switch (prop_id) {
- case PROP_INTERVAL:
- g_value_set_uint (value, dtmfsrc->interval);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_dtmf_prepare_timestamps (GstDTMFSrc * dtmfsrc)
-{
- GstClockTime last_stop;
- GstClockTime timestamp;
-
- GST_OBJECT_LOCK (dtmfsrc);
- last_stop = dtmfsrc->last_stop;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- if (GST_CLOCK_TIME_IS_VALID (last_stop)) {
- timestamp = last_stop;
- } else {
- GstClock *clock;
-
- /* If there is no valid start time, lets use now as the start time */
-
- clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
- if (clock != NULL) {
- timestamp = gst_clock_get_time (clock)
- - gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
- gst_object_unref (clock);
- } else {
- gchar *dtmf_name = gst_element_get_name (dtmfsrc);
- GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
- dtmfsrc->timestamp = GST_CLOCK_TIME_NONE;
- g_free (dtmf_name);
- return;
- }
- }
-
- /* Make sure the timestamp always goes forward */
- if (timestamp > dtmfsrc->timestamp)
- dtmfsrc->timestamp = timestamp;
-}
-
-static void
-gst_dtmf_src_add_start_event (GstDTMFSrc * dtmfsrc, gint event_number,
- gint event_volume)
-{
-
- GstDTMFSrcEvent *event = g_slice_new0 (GstDTMFSrcEvent);
- event->event_type = DTMF_EVENT_TYPE_START;
- event->sample = 0;
- event->event_number = CLAMP (event_number, MIN_EVENT, MAX_EVENT);
- event->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME);
-
- g_async_queue_push (dtmfsrc->event_queue, event);
-}
-
-static void
-gst_dtmf_src_add_stop_event (GstDTMFSrc * dtmfsrc)
-{
-
- GstDTMFSrcEvent *event = g_slice_new0 (GstDTMFSrcEvent);
- event->event_type = DTMF_EVENT_TYPE_STOP;
- event->sample = 0;
- event->event_number = 0;
- event->volume = 0;
-
- g_async_queue_push (dtmfsrc->event_queue, event);
-}
-
-static GstBuffer *
-gst_dtmf_src_generate_silence (float duration, gint sample_rate)
-{
- gint buf_size;
-
- /* Create a buffer with data set to 0 */
- buf_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8;
-
- return gst_buffer_new_wrapped (g_malloc0 (buf_size), buf_size);
-}
-
-static GstBuffer *
-gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key,
- float duration, gint sample_rate)
-{
- GstBuffer *buffer;
- GstMapInfo map;
- gint16 *p;
- gint tone_size;
- double i = 0;
- double amplitude, f1, f2;
- double volume_factor;
- static GstAllocationParams params = { 0, 1, 0, 0, };
-
- /* Create a buffer for the tone */
- tone_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8;
-
- buffer = gst_buffer_new_allocate (NULL, tone_size, ¶ms);
-
- gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
- p = (gint16 *) map.data;
-
- volume_factor = pow (10, (-event->volume) / 20);
-
- /*
- * For each sample point we calculate 'x' as the
- * the amplitude value.
- */
- for (i = 0; i < (tone_size / (SAMPLE_SIZE / 8)); i++) {
- /*
- * We add the fundamental frequencies together.
- */
- f1 = sin (2 * M_PI * key.low_frequency * (event->sample / sample_rate));
- f2 = sin (2 * M_PI * key.high_frequency * (event->sample / sample_rate));
-
- amplitude = (f1 + f2) / 2;
-
- /* Adjust the volume */
- amplitude *= volume_factor;
-
- /* Make the [-1:1] interval into a [-32767:32767] interval */
- amplitude *= 32767;
-
- /* Store it in the data buffer */
- *(p++) = (gint16) amplitude;
-
- (event->sample)++;
- }
-
- gst_buffer_unmap (buffer, &map);
-
- return buffer;
-}
-
-
-
-static GstBuffer *
-gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc,
- GstDTMFSrcEvent * event)
-{
- GstBuffer *buf = NULL;
- gboolean send_silence = FALSE;
-
- GST_LOG_OBJECT (dtmfsrc, "Creating buffer for tone %s",
- DTMF_KEYS[event->event_number].event_name);
-
- if (event->packet_count * dtmfsrc->interval < MIN_INTER_DIGIT_INTERVAL) {
- send_silence = TRUE;
- }
-
- if (send_silence) {
- GST_LOG_OBJECT (dtmfsrc, "Generating silence");
- buf = gst_dtmf_src_generate_silence (dtmfsrc->interval,
- dtmfsrc->sample_rate);
- } else {
- GST_LOG_OBJECT (dtmfsrc, "Generating tone");
- buf = gst_dtmf_src_generate_tone (event, DTMF_KEYS[event->event_number],
- dtmfsrc->interval, dtmfsrc->sample_rate);
- }
- event->packet_count++;
-
-
- /* timestamp and duration of GstBuffer */
- GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND;
- GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp;
-
- GST_LOG_OBJECT (dtmfsrc, "Creating new buffer with event %u duration "
- " gst: %" GST_TIME_FORMAT " at %" GST_TIME_FORMAT,
- event->event_number, GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
- dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
-
- return buf;
-}
-
-static void
-gst_dtmf_src_post_message (GstDTMFSrc * dtmfsrc, const gchar * message_name,
- GstDTMFSrcEvent * event)
-{
- GstStructure *s = NULL;
-
- switch (event->event_type) {
- case DTMF_EVENT_TYPE_START:
- s = gst_structure_new (message_name,
- "type", G_TYPE_INT, 1,
- "method", G_TYPE_INT, 2,
- "start", G_TYPE_BOOLEAN, TRUE,
- "number", G_TYPE_INT, event->event_number,
- "volume", G_TYPE_INT, event->volume, NULL);
- break;
- case DTMF_EVENT_TYPE_STOP:
- s = gst_structure_new (message_name,
- "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 2,
- "start", G_TYPE_BOOLEAN, FALSE, NULL);
- break;
- case DTMF_EVENT_TYPE_PAUSE_TASK:
- return;
- }
-
- if (s)
- gst_element_post_message (GST_ELEMENT (dtmfsrc),
- gst_message_new_element (GST_OBJECT (dtmfsrc), s));
-}
-
-static GstFlowReturn
-gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset,
- guint length, GstBuffer ** buffer)
-{
- GstBuffer *buf = NULL;
- GstDTMFSrcEvent *event;
- GstDTMFSrc *dtmfsrc;
- GstClock *clock;
- GstClockID *clockid;
- GstClockReturn clockret;
-
- dtmfsrc = GST_DTMF_SRC (basesrc);
-
- do {
-
- if (dtmfsrc->last_event == NULL) {
- GST_DEBUG_OBJECT (dtmfsrc, "popping");
- event = g_async_queue_pop (dtmfsrc->event_queue);
-
- GST_DEBUG_OBJECT (dtmfsrc, "popped %d", event->event_type);
-
- switch (event->event_type) {
- case DTMF_EVENT_TYPE_STOP:
- GST_WARNING_OBJECT (dtmfsrc,
- "Received a DTMF stop event when already stopped");
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- break;
- case DTMF_EVENT_TYPE_START:
- gst_dtmf_prepare_timestamps (dtmfsrc);
-
- event->packet_count = 0;
- dtmfsrc->last_event = event;
- event = NULL;
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed",
- dtmfsrc->last_event);
- break;
- case DTMF_EVENT_TYPE_PAUSE_TASK:
- /*
- * We're pushing it back because it has to stay in there until
- * the task is really paused (and the queue will then be flushed)
- */
- GST_DEBUG_OBJECT (dtmfsrc, "pushing pause_task...");
- GST_OBJECT_LOCK (dtmfsrc);
- if (dtmfsrc->paused) {
- g_async_queue_push (dtmfsrc->event_queue, event);
- goto paused_locked;
- }
- GST_OBJECT_UNLOCK (dtmfsrc);
- break;
- }
- if (event)
- g_slice_free (GstDTMFSrcEvent, event);
- } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >=
- MIN_DUTY_CYCLE) {
- event = g_async_queue_try_pop (dtmfsrc->event_queue);
-
- if (event != NULL) {
-
- switch (event->event_type) {
- case DTMF_EVENT_TYPE_START:
- GST_WARNING_OBJECT (dtmfsrc,
- "Received two consecutive DTMF start events");
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- break;
- case DTMF_EVENT_TYPE_STOP:
- g_slice_free (GstDTMFSrcEvent, dtmfsrc->last_event);
- dtmfsrc->last_event = NULL;
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event);
- break;
- case DTMF_EVENT_TYPE_PAUSE_TASK:
- /*
- * We're pushing it back because it has to stay in there until
- * the task is really paused (and the queue will then be flushed)
- */
- GST_DEBUG_OBJECT (dtmfsrc, "pushing pause_task...");
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (dtmfsrc->paused) {
- g_async_queue_push (dtmfsrc->event_queue, event);
- goto paused_locked;
- }
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- break;
- }
- g_slice_free (GstDTMFSrcEvent, event);
- }
- }
- } while (dtmfsrc->last_event == NULL);
-
- GST_LOG_OBJECT (dtmfsrc, "end event check, now wait for the proper time");
-
- clock = gst_element_get_clock (GST_ELEMENT (basesrc));
-
- clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp +
- gst_element_get_base_time (GST_ELEMENT (dtmfsrc)));
- gst_object_unref (clock);
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (!dtmfsrc->paused) {
- dtmfsrc->clockid = clockid;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- clockret = gst_clock_id_wait (clockid, NULL);
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (dtmfsrc->paused)
- clockret = GST_CLOCK_UNSCHEDULED;
- } else {
- clockret = GST_CLOCK_UNSCHEDULED;
- }
- gst_clock_id_unref (clockid);
- dtmfsrc->clockid = NULL;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- if (clockret == GST_CLOCK_UNSCHEDULED) {
- goto paused;
- }
-
- buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event);
-
- GST_LOG_OBJECT (dtmfsrc, "Created buffer of size %" G_GSIZE_FORMAT,
- gst_buffer_get_size (buf));
- *buffer = buf;
-
- return GST_FLOW_OK;
-
-paused_locked:
- GST_OBJECT_UNLOCK (dtmfsrc);
-
-paused:
-
- if (dtmfsrc->last_event) {
- GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event");
- /* Don't forget to release the stream lock */
- g_slice_free (GstDTMFSrcEvent, dtmfsrc->last_event);
- dtmfsrc->last_event = NULL;
- }
-
- return GST_FLOW_FLUSHING;
-
-}
-
-static gboolean
-gst_dtmf_src_unlock (GstBaseSrc * src)
-{
- GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (src);
- GstDTMFSrcEvent *event = NULL;
-
- GST_DEBUG_OBJECT (dtmfsrc, "Called unlock");
-
- GST_OBJECT_LOCK (dtmfsrc);
- dtmfsrc->paused = TRUE;
- if (dtmfsrc->clockid) {
- gst_clock_id_unschedule (dtmfsrc->clockid);
- }
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request");
- event = g_slice_new0 (GstDTMFSrcEvent);
- event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK;
- g_async_queue_push (dtmfsrc->event_queue, event);
-
- return TRUE;
-}
-
-
-static gboolean
-gst_dtmf_src_unlock_stop (GstBaseSrc * src)
-{
- GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (src);
-
- GST_DEBUG_OBJECT (dtmfsrc, "Unlock stopped");
-
- GST_OBJECT_LOCK (dtmfsrc);
- dtmfsrc->paused = FALSE;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- return TRUE;
-}
-
-
-static gboolean
-gst_dtmf_src_negotiate (GstBaseSrc * basesrc)
-{
- GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (basesrc);
- GstCaps *caps;
- GstStructure *s;
- gboolean ret;
-
- caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc));
-
- if (!caps)
- caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (basesrc));
-
- if (gst_caps_is_empty (caps)) {
- gst_caps_unref (caps);
- return FALSE;
- }
-
- caps = gst_caps_truncate (caps);
-
- caps = gst_caps_make_writable (caps);
- s = gst_caps_get_structure (caps, 0);
-
- gst_structure_fixate_field_nearest_int (s, "rate", DEFAULT_SAMPLE_RATE);
-
- if (!gst_structure_get_int (s, "rate", &dtmfsrc->sample_rate)) {
- GST_ERROR_OBJECT (dtmfsrc, "Could not get rate");
- gst_caps_unref (caps);
- return FALSE;
- }
-
- ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
-
- gst_caps_unref (caps);
-
- return ret;
-}
-
-static GstStateChangeReturn
-gst_dtmf_src_change_state (GstElement * element, GstStateChange transition)
-{
- GstDTMFSrc *dtmfsrc;
- GstStateChangeReturn result;
- gboolean no_preroll = FALSE;
- GstDTMFSrcEvent *event = NULL;
-
- dtmfsrc = GST_DTMF_SRC (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- /* Flushing the event queue */
- event = g_async_queue_try_pop (dtmfsrc->event_queue);
-
- while (event != NULL) {
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- g_slice_free (GstDTMFSrcEvent, event);
- event = g_async_queue_try_pop (dtmfsrc->event_queue);
- }
- dtmfsrc->last_event_was_start = FALSE;
- dtmfsrc->timestamp = 0;
- no_preroll = TRUE;
- break;
- default:
- break;
- }
-
- if ((result =
- GST_ELEMENT_CLASS (gst_dtmf_src_parent_class)->change_state (element,
- transition)) == GST_STATE_CHANGE_FAILURE)
- goto failure;
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- no_preroll = TRUE;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- GST_DEBUG_OBJECT (dtmfsrc, "Flushing event queue");
- /* Flushing the event queue */
- event = g_async_queue_try_pop (dtmfsrc->event_queue);
-
- while (event != NULL) {
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- g_slice_free (GstDTMFSrcEvent, event);
- event = g_async_queue_try_pop (dtmfsrc->event_queue);
- }
- dtmfsrc->last_event_was_start = FALSE;
-
- break;
- default:
- break;
- }
-
- if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
- result = GST_STATE_CHANGE_NO_PREROLL;
-
- return result;
-
- /* ERRORS */
-failure:
- {
- GST_ERROR_OBJECT (dtmfsrc, "parent failed state change");
- return result;
- }
-}
-
-gboolean
-gst_dtmf_src_plugin_init (GstPlugin * plugin)
-{
- return gst_element_register (plugin, "dtmfsrc",
- GST_RANK_NONE, GST_TYPE_DTMF_SRC);
-}
+++ /dev/null
-/* GStreamer DTMF source
- *
- * gstdtmfsrc.h:
- *
- * Copyright (C) <2007> Collabora.
- * Contact: Youness Alaoui <youness.alaoui@collabora.co.uk>
- * Copyright (C) <2007> Nokia Corporation.
- * Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
- * Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-
-#ifndef __GST_DTMF_SRC_H__
-#define __GST_DTMF_SRC_H__
-
-#include <gst/gst.h>
-#include <gst/gstbuffer.h>
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-#define GST_TYPE_DTMF_SRC (gst_dtmf_src_get_type())
-#define GST_DTMF_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DTMF_SRC,GstDTMFSrc))
-#define GST_DTMF_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DTMF_SRC,GstDTMFSrcClass))
-#define GST_DTMF_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DTMF_SRC, GstDTMFSrcClass))
-#define GST_IS_DTMF_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DTMF_SRC))
-#define GST_IS_DTMF_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DTMF_SRC))
-#define GST_DTMF_SRC_CAST(obj) ((GstDTMFSrc *)(obj))
-typedef struct _GstDTMFSrc GstDTMFSrc;
-typedef struct _GstDTMFSrcClass GstDTMFSrcClass;
-
-enum _GstDTMFEventType
-{
- DTMF_EVENT_TYPE_START,
- DTMF_EVENT_TYPE_STOP,
- DTMF_EVENT_TYPE_PAUSE_TASK
-};
-
-typedef enum _GstDTMFEventType GstDTMFEventType;
-
-struct _GstDTMFSrcEvent
-{
- GstDTMFEventType event_type;
- double sample;
- guint16 event_number;
- guint16 volume;
- guint32 packet_count;
-};
-
-typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent;
-
-/**
- * GstDTMFSrc:
- * @element: the parent element.
- *
- * The opaque #GstDTMFSrc data structure.
- */
-struct _GstDTMFSrc
-{
- /*< private >*/
- GstBaseSrc parent;
- GAsyncQueue *event_queue;
- GstDTMFSrcEvent *last_event;
- gboolean last_event_was_start;
-
- guint16 interval;
- GstClockTime timestamp;
-
- gboolean paused;
- GstClockID clockid;
-
- GstClockTime last_stop;
-
- gint sample_rate;
-};
-
-
-struct _GstDTMFSrcClass
-{
- GstBaseSrcClass parent_class;
-};
-
-GType gst_dtmf_src_get_type (void);
-
-gboolean gst_dtmf_src_plugin_init (GstPlugin * plugin);
-
-G_END_DECLS
-#endif /* __GST_DTMF_SRC_H__ */
+++ /dev/null
-/* GstRtpDtmfDepay
- *
- * Copyright (C) 2008 Collabora Limited
- * Copyright (C) 2008 Nokia Corporation
- * Contact: Youness Alaoui <youness.alaoui@collabora.co.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-/**
- * SECTION:element-rtpdtmfdepay
- * @see_also: rtpdtmfsrc, rtpdtmfmux
- *
- * This element takes RTP DTMF packets and produces sound. It also emits a
- * message on the #GstBus.
- *
- * The message is called "dtmf-event" and has the following fields
- * <informaltable>
- * <tgroup cols='4'>
- * <colspec colname='Name' />
- * <colspec colname='Type' />
- * <colspec colname='Possible values' />
- * <colspec colname='Purpose' />
- * <thead>
- * <row>
- * <entry>Name</entry>
- * <entry>GType</entry>
- * <entry>Possible values</entry>
- * <entry>Purpose</entry>
- * </row>
- * </thead>
- * <tbody>
- * <row>
- * <entry>type</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-1</entry>
- * <entry>Which of the two methods
- * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
- * named events. Tones are specified by their frequencies and events are specied
- * by their number. This element currently only recognizes events.
- * Do not confuse with "method" which specified the output.
- * </entry>
- * </row>
- * <row>
- * <entry>number</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-16</entry>
- * <entry>The event number.</entry>
- * </row>
- * <row>
- * <entry>volume</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-36</entry>
- * <entry>This field describes the power level of the tone, expressed in dBm0
- * after dropping the sign. Power levels range from 0 to -63 dBm0. The range of
- * valid DTMF is from 0 to -36 dBm0.
- * </entry>
- * </row>
- * <row>
- * <entry>method</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>1</entry>
- * <entry>This field will always been 1 (ie RTP event) from this element.
- * </entry>
- * </row>
- * </tbody>
- * </tgroup>
- * </informaltable>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstrtpdtmfdepay.h"
-
-#include <string.h>
-#include <math.h>
-
-#include <gst/audio/audio.h>
-#include <gst/rtp/gstrtpbuffer.h>
-
-#define DEFAULT_PACKET_INTERVAL 50 /* ms */
-#define MIN_PACKET_INTERVAL 10 /* ms */
-#define MAX_PACKET_INTERVAL 50 /* ms */
-#define SAMPLE_RATE 8000
-#define SAMPLE_SIZE 16
-#define CHANNELS 1
-#define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION)
-
-#define MIN_UNIT_TIME 0
-#define MAX_UNIT_TIME 1000
-#define DEFAULT_UNIT_TIME 0
-
-#define DEFAULT_MAX_DURATION 0
-
-typedef struct st_dtmf_key
-{
- const char *event_name;
- int event_encoding;
- float low_frequency;
- float high_frequency;
-} DTMF_KEY;
-
-static const DTMF_KEY DTMF_KEYS[] = {
- {"DTMF_KEY_EVENT_0", 0, 941, 1336},
- {"DTMF_KEY_EVENT_1", 1, 697, 1209},
- {"DTMF_KEY_EVENT_2", 2, 697, 1336},
- {"DTMF_KEY_EVENT_3", 3, 697, 1477},
- {"DTMF_KEY_EVENT_4", 4, 770, 1209},
- {"DTMF_KEY_EVENT_5", 5, 770, 1336},
- {"DTMF_KEY_EVENT_6", 6, 770, 1477},
- {"DTMF_KEY_EVENT_7", 7, 852, 1209},
- {"DTMF_KEY_EVENT_8", 8, 852, 1336},
- {"DTMF_KEY_EVENT_9", 9, 852, 1477},
- {"DTMF_KEY_EVENT_S", 10, 941, 1209},
- {"DTMF_KEY_EVENT_P", 11, 941, 1477},
- {"DTMF_KEY_EVENT_A", 12, 697, 1633},
- {"DTMF_KEY_EVENT_B", 13, 770, 1633},
- {"DTMF_KEY_EVENT_C", 14, 852, 1633},
- {"DTMF_KEY_EVENT_D", 15, 941, 1633},
-};
-
-#define MAX_DTMF_EVENTS 16
-
-enum
-{
- DTMF_KEY_EVENT_1 = 1,
- DTMF_KEY_EVENT_2 = 2,
- DTMF_KEY_EVENT_3 = 3,
- DTMF_KEY_EVENT_4 = 4,
- DTMF_KEY_EVENT_5 = 5,
- DTMF_KEY_EVENT_6 = 6,
- DTMF_KEY_EVENT_7 = 7,
- DTMF_KEY_EVENT_8 = 8,
- DTMF_KEY_EVENT_9 = 9,
- DTMF_KEY_EVENT_0 = 0,
- DTMF_KEY_EVENT_STAR = 10,
- DTMF_KEY_EVENT_POUND = 11,
- DTMF_KEY_EVENT_A = 12,
- DTMF_KEY_EVENT_B = 13,
- DTMF_KEY_EVENT_C = 14,
- DTMF_KEY_EVENT_D = 15,
-};
-
-GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_depay_debug);
-#define GST_CAT_DEFAULT gst_rtp_dtmf_depay_debug
-
-enum
-{
-
-
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_UNIT_TIME,
- PROP_MAX_DURATION
-};
-
-enum
-{
- ARG_0
-};
-
-static GstStaticPadTemplate gst_rtp_dtmf_depay_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw, "
- "format = (string) \"" GST_AUDIO_NE (S16) "\", "
- "rate = " GST_AUDIO_RATE_RANGE ", " "channels = (int) 1")
- );
-
-static GstStaticPadTemplate gst_rtp_dtmf_depay_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-rtp, "
- "media = (string) \"audio\", "
- "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
- "clock-rate = (int) [ 0, MAX ], "
- "encoding-name = (string) \"TELEPHONE-EVENT\"")
- );
-
-G_DEFINE_TYPE (GstRtpDTMFDepay, gst_rtp_dtmf_depay,
- GST_TYPE_RTP_BASE_DEPAYLOAD);
-
-static void gst_rtp_dtmf_depay_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static GstBuffer *gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload,
- GstBuffer * buf);
-gboolean gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter,
- GstCaps * caps);
-
-static void
-gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
- gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
-
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_rtp_dtmf_depay_src_template));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_rtp_dtmf_depay_sink_template));
-
- GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug,
- "rtpdtmfdepay", 0, "rtpdtmfdepay element");
- gst_element_class_set_static_metadata (gstelement_class,
- "RTP DTMF packet depayloader", "Codec/Depayloader/Network",
- "Generates DTMF Sound from telephone-event RTP packets",
- "Youness Alaoui <youness.alaoui@collabora.co.uk>");
-
- gobject_class->set_property =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_set_property);
- gobject_class->get_property =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_get_property);
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_UNIT_TIME,
- g_param_spec_uint ("unit-time", "Duration unittime",
- "The smallest unit (ms) the duration must be a multiple of (0 disables it)",
- MIN_UNIT_TIME, MAX_UNIT_TIME, DEFAULT_UNIT_TIME,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_DURATION,
- g_param_spec_uint ("max-duration", "Maximum duration",
- "The maxumimum duration (ms) of the outgoing soundpacket. "
- "(0 = no limit)", 0, G_MAXUINT, DEFAULT_MAX_DURATION,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- gstrtpbasedepayload_class->process =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process);
- gstrtpbasedepayload_class->set_caps =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_setcaps);
-
-}
-
-static void
-gst_rtp_dtmf_depay_init (GstRtpDTMFDepay * rtpdtmfdepay)
-{
- rtpdtmfdepay->unit_time = DEFAULT_UNIT_TIME;
-}
-
-static void
-gst_rtp_dtmf_depay_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstRtpDTMFDepay *rtpdtmfdepay;
-
- rtpdtmfdepay = GST_RTP_DTMF_DEPAY (object);
-
- switch (prop_id) {
- case PROP_UNIT_TIME:
- rtpdtmfdepay->unit_time = g_value_get_uint (value);
- break;
- case PROP_MAX_DURATION:
- rtpdtmfdepay->max_duration = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstRtpDTMFDepay *rtpdtmfdepay;
-
- rtpdtmfdepay = GST_RTP_DTMF_DEPAY (object);
-
- switch (prop_id) {
- case PROP_UNIT_TIME:
- g_value_set_uint (value, rtpdtmfdepay->unit_time);
- break;
- case PROP_MAX_DURATION:
- g_value_set_uint (value, rtpdtmfdepay->max_duration);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-gboolean
-gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps)
-{
- GstCaps *filtercaps, *srccaps;
- GstStructure *structure = gst_caps_get_structure (caps, 0);
- gint clock_rate = 8000; /* default */
-
- gst_structure_get_int (structure, "clock-rate", &clock_rate);
- filter->clock_rate = clock_rate;
-
- filtercaps =
- gst_pad_get_pad_template_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter));
-
- filtercaps = gst_caps_make_writable (filtercaps);
- gst_caps_set_simple (filtercaps, "rate", G_TYPE_INT, clock_rate, NULL);
-
- srccaps = gst_pad_peer_query_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter),
- filtercaps);
- gst_caps_unref (filtercaps);
-
- gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter), srccaps);
- gst_caps_unref (srccaps);
-
- return TRUE;
-}
-
-static GstBuffer *
-gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay,
- GstRTPDTMFPayload payload)
-{
- GstBuffer *buf;
- GstMapInfo map;
- gint16 *p;
- gint tone_size;
- double i = 0;
- double amplitude, f1, f2;
- double volume_factor;
- DTMF_KEY key = DTMF_KEYS[payload.event];
- guint32 clock_rate = 8000 /* default */ ;
- GstRTPBaseDepayload *depayload = GST_RTP_BASE_DEPAYLOAD (rtpdtmfdepay);
- gint volume;
- static GstAllocationParams params = { 0, 1, 0, 0, };
-
- clock_rate = depayload->clock_rate;
-
- /* Create a buffer for the tone */
- tone_size = (payload.duration * SAMPLE_SIZE * CHANNELS) / 8;
- buf = gst_buffer_new_allocate (NULL, tone_size, ¶ms);
- GST_BUFFER_DURATION (buf) = payload.duration * GST_SECOND / clock_rate;
- volume = payload.volume;
-
- gst_buffer_map (buf, &map, GST_MAP_WRITE);
- p = (gint16 *) map.data;
-
- volume_factor = pow (10, (-volume) / 20);
-
- /*
- * For each sample point we calculate 'x' as the
- * the amplitude value.
- */
- for (i = 0; i < (tone_size / (SAMPLE_SIZE / 8)); i++) {
- /*
- * We add the fundamental frequencies together.
- */
- f1 = sin (2 * M_PI * key.low_frequency * (rtpdtmfdepay->sample /
- clock_rate));
- f2 = sin (2 * M_PI * key.high_frequency * (rtpdtmfdepay->sample /
- clock_rate));
-
- amplitude = (f1 + f2) / 2;
-
- /* Adjust the volume */
- amplitude *= volume_factor;
-
- /* Make the [-1:1] interval into a [-32767:32767] interval */
- amplitude *= 32767;
-
- /* Store it in the data buffer */
- *(p++) = (gint16) amplitude;
-
- (rtpdtmfdepay->sample)++;
- }
-
- gst_buffer_unmap (buf, &map);
-
- return buf;
-}
-
-
-static GstBuffer *
-gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
-{
-
- GstRtpDTMFDepay *rtpdtmfdepay = NULL;
- GstBuffer *outbuf = NULL;
- gint payload_len;
- guint8 *payload = NULL;
- guint32 timestamp;
- GstRTPDTMFPayload dtmf_payload;
- gboolean marker;
- GstStructure *structure = NULL;
- GstMessage *dtmf_message = NULL;
- GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
-
- rtpdtmfdepay = GST_RTP_DTMF_DEPAY (depayload);
-
- gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuffer);
-
- payload_len = gst_rtp_buffer_get_payload_len (&rtpbuffer);
- payload = gst_rtp_buffer_get_payload (&rtpbuffer);
-
- if (payload_len != sizeof (GstRTPDTMFPayload))
- goto bad_packet;
-
- memcpy (&dtmf_payload, payload, sizeof (GstRTPDTMFPayload));
-
- if (dtmf_payload.event > MAX_EVENT)
- goto bad_packet;
-
- marker = gst_rtp_buffer_get_marker (&rtpbuffer);
-
- timestamp = gst_rtp_buffer_get_timestamp (&rtpbuffer);
-
- dtmf_payload.duration = g_ntohs (dtmf_payload.duration);
-
- /* clip to whole units of unit_time */
- if (rtpdtmfdepay->unit_time) {
- guint unit_time_clock =
- (rtpdtmfdepay->unit_time * depayload->clock_rate) / 1000;
- if (dtmf_payload.duration % unit_time_clock) {
- /* Make sure we don't overflow the duration */
- if (dtmf_payload.duration < G_MAXUINT16 - unit_time_clock)
- dtmf_payload.duration += unit_time_clock -
- (dtmf_payload.duration % unit_time_clock);
- else
- dtmf_payload.duration -= dtmf_payload.duration % unit_time_clock;
- }
- }
-
- /* clip to max duration */
- if (rtpdtmfdepay->max_duration) {
- guint max_duration_clock =
- (rtpdtmfdepay->max_duration * depayload->clock_rate) / 1000;
-
- if (max_duration_clock < G_MAXUINT16 &&
- dtmf_payload.duration > max_duration_clock)
- dtmf_payload.duration = max_duration_clock;
- }
-
- GST_DEBUG_OBJECT (depayload, "Received new RTP DTMF packet : "
- "marker=%d - timestamp=%u - event=%d - duration=%d",
- marker, timestamp, dtmf_payload.event, dtmf_payload.duration);
-
- GST_DEBUG_OBJECT (depayload,
- "Previous information : timestamp=%u - duration=%d",
- rtpdtmfdepay->previous_ts, rtpdtmfdepay->previous_duration);
-
- /* First packet */
- if (marker || rtpdtmfdepay->previous_ts != timestamp) {
- rtpdtmfdepay->sample = 0;
- rtpdtmfdepay->previous_ts = timestamp;
- rtpdtmfdepay->previous_duration = dtmf_payload.duration;
- rtpdtmfdepay->first_gst_ts = GST_BUFFER_PTS (buf);
-
- structure = gst_structure_new ("dtmf-event",
- "number", G_TYPE_INT, dtmf_payload.event,
- "volume", G_TYPE_INT, dtmf_payload.volume,
- "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1, NULL);
- if (structure) {
- dtmf_message =
- gst_message_new_element (GST_OBJECT (depayload), structure);
- if (dtmf_message) {
- if (!gst_element_post_message (GST_ELEMENT (depayload), dtmf_message)) {
- GST_ERROR_OBJECT (depayload,
- "Unable to send dtmf-event message to bus");
- }
- } else {
- GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event message");
- }
- } else {
- GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event structure");
- }
- } else {
- guint16 duration = dtmf_payload.duration;
- dtmf_payload.duration -= rtpdtmfdepay->previous_duration;
- /* If late buffer, ignore */
- if (duration > rtpdtmfdepay->previous_duration)
- rtpdtmfdepay->previous_duration = duration;
- }
-
- GST_DEBUG_OBJECT (depayload, "new previous duration : %d - new duration : %d"
- " - diff : %d - clock rate : %d - timestamp : %" G_GUINT64_FORMAT,
- rtpdtmfdepay->previous_duration, dtmf_payload.duration,
- (rtpdtmfdepay->previous_duration - dtmf_payload.duration),
- depayload->clock_rate, GST_BUFFER_TIMESTAMP (buf));
-
- /* If late or duplicate packet (like the redundant end packet). Ignore */
- if (dtmf_payload.duration > 0) {
- outbuf = gst_dtmf_src_generate_tone (rtpdtmfdepay, dtmf_payload);
-
-
- GST_BUFFER_PTS (outbuf) = rtpdtmfdepay->first_gst_ts +
- (rtpdtmfdepay->previous_duration - dtmf_payload.duration) *
- GST_SECOND / depayload->clock_rate;
- GST_BUFFER_OFFSET (outbuf) =
- (rtpdtmfdepay->previous_duration - dtmf_payload.duration) *
- GST_SECOND / depayload->clock_rate;
- GST_BUFFER_OFFSET_END (outbuf) = rtpdtmfdepay->previous_duration *
- GST_SECOND / depayload->clock_rate;
-
- GST_DEBUG_OBJECT (depayload,
- "timestamp : %" G_GUINT64_FORMAT " - time %" GST_TIME_FORMAT,
- GST_BUFFER_TIMESTAMP (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
- }
-
- gst_rtp_buffer_unmap (&rtpbuffer);
-
- return outbuf;
-
-bad_packet:
- GST_ELEMENT_WARNING (rtpdtmfdepay, STREAM, DECODE,
- ("Packet did not validate"), (NULL));
-
- if (rtpbuffer.buffer != NULL)
- gst_rtp_buffer_unmap (&rtpbuffer);
-
- return NULL;
-}
-
-gboolean
-gst_rtp_dtmf_depay_plugin_init (GstPlugin * plugin)
-{
- return gst_element_register (plugin, "rtpdtmfdepay",
- GST_RANK_MARGINAL, GST_TYPE_RTP_DTMF_DEPAY);
-}
+++ /dev/null
-/* GstRtpDtmfDepay
- *
- * Copyright (C) 2008 Collabora Limited
- * Copyright (C) 2008 Nokia Corporation
- * Contact: Youness Alaoui <youness.alaoui@collabora.co.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-
-#ifndef __GST_RTP_DTMF_DEPAY_H__
-#define __GST_RTP_DTMF_DEPAY_H__
-
-#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
-#include <gst/rtp/gstrtpbasedepayload.h>
-
-#include "gstdtmfcommon.h"
-
-G_BEGIN_DECLS
-#define GST_TYPE_RTP_DTMF_DEPAY \
- (gst_rtp_dtmf_depay_get_type())
-#define GST_RTP_DTMF_DEPAY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DTMF_DEPAY,GstRtpDTMFDepay))
-#define GST_RTP_DTMF_DEPAY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DTMF_DEPAY,GstRtpDTMFDepayClass))
-#define GST_IS_RTP_DTMF_DEPAY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DTMF_DEPAY))
-#define GST_IS_RTP_DTMF_DEPAY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DTMF_DEPAY))
-typedef struct _GstRtpDTMFDepay GstRtpDTMFDepay;
-typedef struct _GstRtpDTMFDepayClass GstRtpDTMFDepayClass;
-
-struct _GstRtpDTMFDepay
-{
- /*< private >*/
- GstRTPBaseDepayload depayload;
- double sample;
- guint32 previous_ts;
- guint16 previous_duration;
- GstClockTime first_gst_ts;
- guint unit_time;
- guint max_duration;
-};
-
-struct _GstRtpDTMFDepayClass
-{
- GstRTPBaseDepayloadClass parent_class;
-};
-
-GType gst_rtp_dtmf_depay_get_type (void);
-
-gboolean gst_rtp_dtmf_depay_plugin_init (GstPlugin * plugin);
-
-G_END_DECLS
-#endif /* __GST_RTP_DTMF_DEPAY_H__ */
+++ /dev/null
-/* GStreamer RTP DTMF source
- *
- * gstrtpdtmfsrc.c:
- *
- * Copyright (C) <2007> Nokia Corporation.
- * Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000,2005 Wim Taymans <wim@fluendo.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-
-/**
- * SECTION:element-rtpdtmfsrc
- * @see_also: dtmfsrc, rtpdtmfdepay, rtpdtmfmux
- *
- * The RTPDTMFSrc element generates RTP DTMF (RFC 2833) event packets on request
- * from application. The application communicates the beginning and end of a
- * DTMF event using custom upstream gstreamer events. To report a DTMF event, an
- * application must send an event of type GST_EVENT_CUSTOM_UPSTREAM, having a
- * structure of name "dtmf-event" with fields set according to the following
- * table:
- *
- * <informaltable>
- * <tgroup cols='4'>
- * <colspec colname='Name' />
- * <colspec colname='Type' />
- * <colspec colname='Possible values' />
- * <colspec colname='Purpose' />
- * <thead>
- * <row>
- * <entry>Name</entry>
- * <entry>GType</entry>
- * <entry>Possible values</entry>
- * <entry>Purpose</entry>
- * </row>
- * </thead>
- * <tbody>
- * <row>
- * <entry>type</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-1</entry>
- * <entry>The application uses this field to specify which of the two methods
- * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
- * named events. Tones are specified by their frequencies and events are specied
- * by their number. This element can only take events as input. Do not confuse
- * with "method" which specified the output.
- * </entry>
- * </row>
- * <row>
- * <entry>number</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-15</entry>
- * <entry>The event number.</entry>
- * </row>
- * <row>
- * <entry>volume</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>0-36</entry>
- * <entry>This field describes the power level of the tone, expressed in dBm0
- * after dropping the sign. Power levels range from 0 to -63 dBm0. The range of
- * valid DTMF is from 0 to -36 dBm0. Can be omitted if start is set to FALSE.
- * </entry>
- * </row>
- * <row>
- * <entry>start</entry>
- * <entry>G_TYPE_BOOLEAN</entry>
- * <entry>True or False</entry>
- * <entry>Whether the event is starting or ending.</entry>
- * </row>
- * <row>
- * <entry>method</entry>
- * <entry>G_TYPE_INT</entry>
- * <entry>1</entry>
- * <entry>The method used for sending event, this element will react if this
- * field is absent or 1.
- * </entry>
- * </row>
- * </tbody>
- * </tgroup>
- * </informaltable>
- *
- * For example, the following code informs the pipeline (and in turn, the
- * RTPDTMFSrc element inside the pipeline) about the start of an RTP DTMF named
- * event '1' of volume -25 dBm0:
- *
- * <programlisting>
- * structure = gst_structure_new ("dtmf-event",
- * "type", G_TYPE_INT, 1,
- * "number", G_TYPE_INT, 1,
- * "volume", G_TYPE_INT, 25,
- * "start", G_TYPE_BOOLEAN, TRUE, NULL);
- *
- * event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
- * gst_element_send_event (pipeline, event);
- * </programlisting>
- *
- * When a DTMF tone actually starts or stop, a "dtmf-event-processed"
- * element #GstMessage with the same fields as the "dtmf-event"
- * #GstEvent that was used to request the event. Also, if any event
- * has not been processed when the element goes from the PAUSED to the
- * READY state, then a "dtmf-event-dropped" message is posted on the
- * #GstBus in the order that they were received.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "gstrtpdtmfsrc.h"
-
-#define GST_RTP_DTMF_TYPE_EVENT 1
-#define DEFAULT_PTIME 40 /* ms */
-#define DEFAULT_SSRC -1
-#define DEFAULT_PT 96
-#define DEFAULT_TIMESTAMP_OFFSET -1
-#define DEFAULT_SEQNUM_OFFSET -1
-#define DEFAULT_CLOCK_RATE 8000
-
-#define DEFAULT_PACKET_REDUNDANCY 1
-#define MIN_PACKET_REDUNDANCY 1
-#define MAX_PACKET_REDUNDANCY 5
-
-GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_src_debug);
-#define GST_CAT_DEFAULT gst_rtp_dtmf_src_debug
-
-/* signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_SSRC,
- PROP_TIMESTAMP_OFFSET,
- PROP_SEQNUM_OFFSET,
- PROP_PT,
- PROP_CLOCK_RATE,
- PROP_TIMESTAMP,
- PROP_SEQNUM,
- PROP_REDUNDANCY
-};
-
-static GstStaticPadTemplate gst_rtp_dtmf_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-rtp, "
- "media = (string) \"audio\", "
- "payload = (int) [ 96, 127 ], "
- "clock-rate = (int) [ 0, MAX ], "
- "encoding-name = (string) \"TELEPHONE-EVENT\"")
- /* "events = (string) \"0-15\" */
- );
-
-
-G_DEFINE_TYPE (GstRTPDTMFSrc, gst_rtp_dtmf_src, GST_TYPE_BASE_SRC);
-
-static void gst_rtp_dtmf_src_finalize (GObject * object);
-
-static void gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static gboolean gst_rtp_dtmf_src_handle_event (GstBaseSrc * basesrc,
- GstEvent * event);
-static GstStateChangeReturn gst_rtp_dtmf_src_change_state (GstElement * element,
- GstStateChange transition);
-static void gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc * dtmfsrc,
- gint event_number, gint event_volume);
-static void gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc * dtmfsrc);
-
-static gboolean gst_rtp_dtmf_src_unlock (GstBaseSrc * src);
-static gboolean gst_rtp_dtmf_src_unlock_stop (GstBaseSrc * src);
-static GstFlowReturn gst_rtp_dtmf_src_create (GstBaseSrc * basesrc,
- guint64 offset, guint length, GstBuffer ** buffer);
-static gboolean gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc);
-
-
-static void
-gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstBaseSrcClass *gstbasesrc_class;
- GstElementClass *gstelement_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
-
- GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug,
- "rtpdtmfsrc", 0, "rtpdtmfsrc element");
-
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_rtp_dtmf_src_template));
-
- gst_element_class_set_static_metadata (gstelement_class,
- "RTP DTMF packet generator", "Source/Network",
- "Generates RTP DTMF packets", "Zeeshan Ali <zeeshan.ali@nokia.com>");
-
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_finalize);
- gobject_class->set_property =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_set_property);
- gobject_class->get_property =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_get_property);
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
- g_param_spec_uint ("timestamp", "Timestamp",
- "The RTP timestamp of the last processed packet",
- 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
- g_param_spec_uint ("seqnum", "Sequence number",
- "The RTP sequence number of the last processed packet",
- 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass),
- PROP_TIMESTAMP_OFFSET, g_param_spec_int ("timestamp-offset",
- "Timestamp Offset",
- "Offset to add to all outgoing timestamps (-1 = random)", -1,
- G_MAXINT, DEFAULT_TIMESTAMP_OFFSET,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
- g_param_spec_int ("seqnum-offset", "Sequence number Offset",
- "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXINT,
- DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CLOCK_RATE,
- g_param_spec_uint ("clock-rate", "clockrate",
- "The clock-rate at which to generate the dtmf packets",
- 0, G_MAXUINT, DEFAULT_CLOCK_RATE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
- g_param_spec_uint ("ssrc", "SSRC",
- "The SSRC of the packets (-1 == random)",
- 0, G_MAXUINT, DEFAULT_SSRC,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
- g_param_spec_uint ("pt", "payload type",
- "The payload type of the packets",
- 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY,
- g_param_spec_uint ("packet-redundancy", "Packet Redundancy",
- "Number of packets to send to indicate start and stop dtmf events",
- MIN_PACKET_REDUNDANCY, MAX_PACKET_REDUNDANCY,
- DEFAULT_PACKET_REDUNDANCY,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_change_state);
-
- gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_unlock);
- gstbasesrc_class->unlock_stop =
- GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_unlock_stop);
-
- gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_handle_event);
- gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_create);
- gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_negotiate);
-}
-
-static void
-gst_rtp_dtmf_src_event_free (GstRTPDTMFSrcEvent * event)
-{
- if (event) {
- if (event->payload)
- g_slice_free (GstRTPDTMFPayload, event->payload);
- g_slice_free (GstRTPDTMFSrcEvent, event);
- }
-}
-
-static void
-gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object)
-{
- gst_base_src_set_format (GST_BASE_SRC (object), GST_FORMAT_TIME);
- gst_base_src_set_live (GST_BASE_SRC (object), TRUE);
-
- object->ssrc = DEFAULT_SSRC;
- object->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
- object->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
- object->pt = DEFAULT_PT;
- object->clock_rate = DEFAULT_CLOCK_RATE;
- object->ptime = DEFAULT_PTIME;
- object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY;
-
- object->event_queue =
- g_async_queue_new_full ((GDestroyNotify) gst_rtp_dtmf_src_event_free);
- object->payload = NULL;
-
- GST_DEBUG_OBJECT (object, "init done");
-}
-
-static void
-gst_rtp_dtmf_src_finalize (GObject * object)
-{
- GstRTPDTMFSrc *dtmfsrc;
-
- dtmfsrc = GST_RTP_DTMF_SRC (object);
-
- if (dtmfsrc->event_queue) {
- g_async_queue_unref (dtmfsrc->event_queue);
- dtmfsrc->event_queue = NULL;
- }
-
-
- G_OBJECT_CLASS (gst_rtp_dtmf_src_parent_class)->finalize (object);
-}
-
-static gboolean
-gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc * dtmfsrc,
- const GstStructure * event_structure)
-{
- gint event_type;
- gboolean start;
- gint method;
- GstClockTime last_stop;
- gint event_number;
- gint event_volume;
- gboolean correct_order;
-
- if (!gst_structure_get_int (event_structure, "type", &event_type) ||
- !gst_structure_get_boolean (event_structure, "start", &start) ||
- event_type != GST_RTP_DTMF_TYPE_EVENT)
- goto failure;
-
- if (gst_structure_get_int (event_structure, "method", &method)) {
- if (method != 1) {
- goto failure;
- }
- }
-
- if (start)
- if (!gst_structure_get_int (event_structure, "number", &event_number) ||
- !gst_structure_get_int (event_structure, "volume", &event_volume))
- goto failure;
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (gst_structure_get_clock_time (event_structure, "last-stop", &last_stop))
- dtmfsrc->last_stop = last_stop;
- else
- dtmfsrc->last_stop = GST_CLOCK_TIME_NONE;
- correct_order = (start != dtmfsrc->last_event_was_start);
- dtmfsrc->last_event_was_start = start;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- if (!correct_order)
- goto failure;
-
- if (start) {
- if (!gst_structure_get_int (event_structure, "number", &event_number) ||
- !gst_structure_get_int (event_structure, "volume", &event_volume))
- goto failure;
-
- GST_DEBUG_OBJECT (dtmfsrc, "Received start event %d with volume %d",
- event_number, event_volume);
- gst_rtp_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume);
- }
-
- else {
- GST_DEBUG_OBJECT (dtmfsrc, "Received stop event");
- gst_rtp_dtmf_src_add_stop_event (dtmfsrc);
- }
-
- return TRUE;
-failure:
- return FALSE;
-}
-
-static gboolean
-gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc * dtmfsrc,
- GstEvent * event)
-{
- gboolean result = FALSE;
- gchar *struct_str;
- const GstStructure *structure;
-
- GstState state;
- GstStateChangeReturn ret;
-
- ret = gst_element_get_state (GST_ELEMENT (dtmfsrc), &state, NULL, 0);
- if (ret != GST_STATE_CHANGE_SUCCESS || state != GST_STATE_PLAYING) {
- GST_DEBUG_OBJECT (dtmfsrc, "Received event while not in PLAYING state");
- goto ret;
- }
-
- GST_DEBUG_OBJECT (dtmfsrc, "Received event is of our interest");
- structure = gst_event_get_structure (event);
- struct_str = gst_structure_to_string (structure);
- GST_DEBUG_OBJECT (dtmfsrc, "Event has structure %s", struct_str);
- g_free (struct_str);
- if (structure && gst_structure_has_name (structure, "dtmf-event"))
- result = gst_rtp_dtmf_src_handle_dtmf_event (dtmfsrc, structure);
-
-ret:
- return result;
-}
-
-static gboolean
-gst_rtp_dtmf_src_handle_event (GstBaseSrc * basesrc, GstEvent * event)
-{
- GstRTPDTMFSrc *dtmfsrc;
- gboolean result = FALSE;
-
- dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
-
- GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad");
- if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) {
- result = gst_rtp_dtmf_src_handle_custom_upstream (dtmfsrc, event);
- }
-
- return result;
-}
-
-static void
-gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstRTPDTMFSrc *dtmfsrc;
-
- dtmfsrc = GST_RTP_DTMF_SRC (object);
-
- switch (prop_id) {
- case PROP_TIMESTAMP_OFFSET:
- dtmfsrc->ts_offset = g_value_get_int (value);
- break;
- case PROP_SEQNUM_OFFSET:
- dtmfsrc->seqnum_offset = g_value_get_int (value);
- break;
- case PROP_CLOCK_RATE:
- dtmfsrc->clock_rate = g_value_get_uint (value);
- dtmfsrc->dirty = TRUE;
- break;
- case PROP_SSRC:
- dtmfsrc->ssrc = g_value_get_uint (value);
- break;
- case PROP_PT:
- dtmfsrc->pt = g_value_get_uint (value);
- dtmfsrc->dirty = TRUE;
- break;
- case PROP_REDUNDANCY:
- dtmfsrc->packet_redundancy = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstRTPDTMFSrc *dtmfsrc;
-
- dtmfsrc = GST_RTP_DTMF_SRC (object);
-
- switch (prop_id) {
- case PROP_TIMESTAMP_OFFSET:
- g_value_set_int (value, dtmfsrc->ts_offset);
- break;
- case PROP_SEQNUM_OFFSET:
- g_value_set_int (value, dtmfsrc->seqnum_offset);
- break;
- case PROP_CLOCK_RATE:
- g_value_set_uint (value, dtmfsrc->clock_rate);
- break;
- case PROP_SSRC:
- g_value_set_uint (value, dtmfsrc->ssrc);
- break;
- case PROP_PT:
- g_value_set_uint (value, dtmfsrc->pt);
- break;
- case PROP_TIMESTAMP:
- g_value_set_uint (value, dtmfsrc->rtp_timestamp);
- break;
- case PROP_SEQNUM:
- g_value_set_uint (value, dtmfsrc->seqnum);
- break;
- case PROP_REDUNDANCY:
- g_value_set_uint (value, dtmfsrc->packet_redundancy);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc)
-{
- GstClockTime last_stop;
-
- GST_OBJECT_LOCK (dtmfsrc);
- last_stop = dtmfsrc->last_stop;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- if (GST_CLOCK_TIME_IS_VALID (last_stop)) {
- dtmfsrc->start_timestamp = last_stop;
- } else {
- GstClock *clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
-
- if (clock == NULL)
- return FALSE;
-
- dtmfsrc->start_timestamp = gst_clock_get_time (clock)
- - gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
- gst_object_unref (clock);
- }
-
- /* If the last stop was in the past, then lets add the buffers together */
- if (dtmfsrc->start_timestamp < dtmfsrc->timestamp)
- dtmfsrc->start_timestamp = dtmfsrc->timestamp;
-
- dtmfsrc->timestamp = dtmfsrc->start_timestamp;
-
- dtmfsrc->rtp_timestamp = dtmfsrc->ts_base +
- gst_util_uint64_scale_int (gst_segment_to_running_time (&GST_BASE_SRC
- (dtmfsrc)->segment, GST_FORMAT_TIME, dtmfsrc->timestamp),
- dtmfsrc->clock_rate, GST_SECOND);
-
- return TRUE;
-}
-
-
-static void
-gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc * dtmfsrc, gint event_number,
- gint event_volume)
-{
-
- GstRTPDTMFSrcEvent *event = g_slice_new0 (GstRTPDTMFSrcEvent);
- event->event_type = RTP_DTMF_EVENT_TYPE_START;
-
- event->payload = g_slice_new0 (GstRTPDTMFPayload);
- event->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT);
- event->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME);
-
- g_async_queue_push (dtmfsrc->event_queue, event);
-}
-
-static void
-gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc * dtmfsrc)
-{
-
- GstRTPDTMFSrcEvent *event = g_slice_new0 (GstRTPDTMFSrcEvent);
- event->event_type = RTP_DTMF_EVENT_TYPE_STOP;
-
- g_async_queue_push (dtmfsrc->event_queue, event);
-}
-
-
-static void
-gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc * dtmfsrc,
- GstRTPBuffer * rtpbuf)
-{
- gst_rtp_buffer_set_ssrc (rtpbuf, dtmfsrc->current_ssrc);
- gst_rtp_buffer_set_payload_type (rtpbuf, dtmfsrc->pt);
- /* Only the very first packet gets a marker */
- if (dtmfsrc->first_packet) {
- gst_rtp_buffer_set_marker (rtpbuf, TRUE);
- } else if (dtmfsrc->last_packet) {
- dtmfsrc->payload->e = 1;
- }
-
- dtmfsrc->seqnum++;
- gst_rtp_buffer_set_seq (rtpbuf, dtmfsrc->seqnum);
-
- /* timestamp of RTP header */
- gst_rtp_buffer_set_timestamp (rtpbuf, dtmfsrc->rtp_timestamp);
-}
-
-static GstBuffer *
-gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc)
-{
- GstBuffer *buf;
- GstRTPDTMFPayload *payload;
- GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
-
- buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0);
-
- gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtpbuffer);
-
- gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, &rtpbuffer);
-
- /* timestamp and duration of GstBuffer */
- /* Redundant buffer have no duration ... */
- if (dtmfsrc->redundancy_count > 1)
- GST_BUFFER_DURATION (buf) = 0;
- else
- GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND;
- GST_BUFFER_PTS (buf) = dtmfsrc->timestamp;
-
- payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (&rtpbuffer);
-
- /* copy payload and convert to network-byte order */
- g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload));
-
- payload->duration = g_htons (payload->duration);
-
- if (dtmfsrc->redundancy_count <= 1 && dtmfsrc->last_packet) {
- GstClockTime inter_digit_interval = MIN_INTER_DIGIT_INTERVAL;
-
- if (inter_digit_interval % dtmfsrc->ptime != 0)
- inter_digit_interval += dtmfsrc->ptime -
- (MIN_INTER_DIGIT_INTERVAL % dtmfsrc->ptime);
-
- GST_BUFFER_DURATION (buf) += inter_digit_interval * GST_MSECOND;
- }
-
- GST_LOG_OBJECT (dtmfsrc, "Creating new buffer with event %u duration "
- " gst: %" GST_TIME_FORMAT " at %" GST_TIME_FORMAT "(rtp ts:%u dur:%u)",
- dtmfsrc->payload->event, GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), dtmfsrc->rtp_timestamp,
- dtmfsrc->payload->duration);
-
- /* duration of DTMF payloadfor the NEXT packet */
- /* not updated for redundant packets */
- if (dtmfsrc->redundancy_count <= 1)
- dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000;
-
- if (GST_CLOCK_TIME_IS_VALID (dtmfsrc->timestamp))
- dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
-
- gst_rtp_buffer_unmap (&rtpbuffer);
-
- return buf;
-}
-
-static GstMessage *
-gst_dtmf_src_prepare_message (GstRTPDTMFSrc * dtmfsrc,
- const gchar * message_name, GstRTPDTMFSrcEvent * event)
-{
- GstStructure *s;
-
- switch (event->event_type) {
- case RTP_DTMF_EVENT_TYPE_START:
- s = gst_structure_new (message_name,
- "type", G_TYPE_INT, 1,
- "method", G_TYPE_INT, 1,
- "start", G_TYPE_BOOLEAN, TRUE,
- "number", G_TYPE_INT, event->payload->event,
- "volume", G_TYPE_INT, event->payload->volume, NULL);
- break;
- case RTP_DTMF_EVENT_TYPE_STOP:
- s = gst_structure_new (message_name,
- "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1,
- "start", G_TYPE_BOOLEAN, FALSE, NULL);
- break;
- case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
- return NULL;
- default:
- return NULL;
- }
-
- return gst_message_new_element (GST_OBJECT (dtmfsrc), s);
-}
-
-static void
-gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name,
- GstRTPDTMFSrcEvent * event)
-{
- GstMessage *m = gst_dtmf_src_prepare_message (dtmfsrc, message_name, event);
-
-
- if (m)
- gst_element_post_message (GST_ELEMENT (dtmfsrc), m);
-}
-
-
-static GstFlowReturn
-gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset,
- guint length, GstBuffer ** buffer)
-{
- GstRTPDTMFSrcEvent *event;
- GstRTPDTMFSrc *dtmfsrc;
- GstClock *clock;
- GstClockID *clockid;
- GstClockReturn clockret;
- GstMessage *message;
- GQueue messages = G_QUEUE_INIT;
-
- dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
-
- do {
-
- if (dtmfsrc->payload == NULL) {
- GST_DEBUG_OBJECT (dtmfsrc, "popping");
- event = g_async_queue_pop (dtmfsrc->event_queue);
-
- GST_DEBUG_OBJECT (dtmfsrc, "popped %d", event->event_type);
-
- switch (event->event_type) {
- case RTP_DTMF_EVENT_TYPE_STOP:
- GST_WARNING_OBJECT (dtmfsrc,
- "Received a DTMF stop event when already stopped");
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- break;
-
- case RTP_DTMF_EVENT_TYPE_START:
- dtmfsrc->first_packet = TRUE;
- dtmfsrc->last_packet = FALSE;
- /* Set the redundancy on the first packet */
- dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
- if (!gst_rtp_dtmf_prepare_timestamps (dtmfsrc))
- goto no_clock;
-
- g_queue_push_tail (&messages,
- gst_dtmf_src_prepare_message (dtmfsrc, "dtmf-event-processed",
- event));
- dtmfsrc->payload = event->payload;
- dtmfsrc->payload->duration =
- dtmfsrc->ptime * dtmfsrc->clock_rate / 1000;
- event->payload = NULL;
- break;
-
- case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
- /*
- * We're pushing it back because it has to stay in there until
- * the task is really paused (and the queue will then be flushed
- */
- GST_OBJECT_LOCK (dtmfsrc);
- if (dtmfsrc->paused) {
- g_async_queue_push (dtmfsrc->event_queue, event);
- goto paused_locked;
- }
- GST_OBJECT_UNLOCK (dtmfsrc);
- break;
- }
-
- gst_rtp_dtmf_src_event_free (event);
- } else if (!dtmfsrc->first_packet && !dtmfsrc->last_packet &&
- (dtmfsrc->timestamp - dtmfsrc->start_timestamp) / GST_MSECOND >=
- MIN_PULSE_DURATION) {
- GST_DEBUG_OBJECT (dtmfsrc, "try popping");
- event = g_async_queue_try_pop (dtmfsrc->event_queue);
-
-
- if (event != NULL) {
- GST_DEBUG_OBJECT (dtmfsrc, "try popped %d", event->event_type);
-
- switch (event->event_type) {
- case RTP_DTMF_EVENT_TYPE_START:
- GST_WARNING_OBJECT (dtmfsrc,
- "Received two consecutive DTMF start events");
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- break;
-
- case RTP_DTMF_EVENT_TYPE_STOP:
- dtmfsrc->first_packet = FALSE;
- dtmfsrc->last_packet = TRUE;
- /* Set the redundancy on the last packet */
- dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
- g_queue_push_tail (&messages,
- gst_dtmf_src_prepare_message (dtmfsrc, "dtmf-event-processed",
- event));
- break;
-
- case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
- /*
- * We're pushing it back because it has to stay in there until
- * the task is really paused (and the queue will then be flushed)
- */
- GST_DEBUG_OBJECT (dtmfsrc, "pushing pause_task...");
- GST_OBJECT_LOCK (dtmfsrc);
- if (dtmfsrc->paused) {
- g_async_queue_push (dtmfsrc->event_queue, event);
- goto paused_locked;
- }
- GST_OBJECT_UNLOCK (dtmfsrc);
- break;
- }
- gst_rtp_dtmf_src_event_free (event);
- }
- }
- } while (dtmfsrc->payload == NULL);
-
-
- GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock");
-
- clock = gst_element_get_clock (GST_ELEMENT (basesrc));
- if (!clock)
- goto no_clock;
- clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp +
- gst_element_get_base_time (GST_ELEMENT (dtmfsrc)));
- gst_object_unref (clock);
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (!dtmfsrc->paused) {
- dtmfsrc->clockid = clockid;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- clockret = gst_clock_id_wait (clockid, NULL);
-
- GST_OBJECT_LOCK (dtmfsrc);
- if (dtmfsrc->paused)
- clockret = GST_CLOCK_UNSCHEDULED;
- } else {
- clockret = GST_CLOCK_UNSCHEDULED;
- }
- gst_clock_id_unref (clockid);
- dtmfsrc->clockid = NULL;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- while ((message = g_queue_pop_head (&messages)) != NULL)
- gst_element_post_message (GST_ELEMENT (dtmfsrc), message);
-
- if (clockret == GST_CLOCK_UNSCHEDULED) {
- goto paused;
- }
-
-send_last:
-
- if (dtmfsrc->dirty)
- if (!gst_rtp_dtmf_src_negotiate (basesrc))
- return GST_FLOW_NOT_NEGOTIATED;
-
- /* create buffer to hold the payload */
- *buffer = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc);
-
- if (dtmfsrc->redundancy_count)
- dtmfsrc->redundancy_count--;
-
- /* Only the very first one has a marker */
- dtmfsrc->first_packet = FALSE;
-
- /* This is the end of the event */
- if (dtmfsrc->last_packet == TRUE && dtmfsrc->redundancy_count == 0) {
-
- g_slice_free (GstRTPDTMFPayload, dtmfsrc->payload);
- dtmfsrc->payload = NULL;
-
- dtmfsrc->last_packet = FALSE;
- }
-
- return GST_FLOW_OK;
-
-paused_locked:
-
- GST_OBJECT_UNLOCK (dtmfsrc);
-
-paused:
-
- if (dtmfsrc->payload) {
- dtmfsrc->first_packet = FALSE;
- dtmfsrc->last_packet = TRUE;
- /* Set the redundanc on the last packet */
- dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
- goto send_last;
- } else {
- return GST_FLOW_FLUSHING;
- }
-
-no_clock:
- GST_ELEMENT_ERROR (dtmfsrc, STREAM, MUX, ("No available clock"),
- ("No available clock"));
- gst_pad_pause_task (GST_BASE_SRC_PAD (dtmfsrc));
- return GST_FLOW_ERROR;
-}
-
-
-static gboolean
-gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc)
-{
- GstCaps *srccaps, *peercaps;
- GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
- gboolean ret;
-
- /* fill in the defaults, there properties cannot be negotiated. */
- srccaps = gst_caps_new_simple ("application/x-rtp",
- "media", G_TYPE_STRING, "audio",
- "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT", NULL);
-
- /* the peer caps can override some of the defaults */
- peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
- if (peercaps == NULL) {
- /* no peer caps, just add the other properties */
- gst_caps_set_simple (srccaps,
- "payload", G_TYPE_INT, dtmfsrc->pt,
- "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc,
- "clock-base", G_TYPE_UINT, dtmfsrc->ts_base,
- "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate,
- "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base, NULL);
-
- GST_DEBUG_OBJECT (dtmfsrc, "no peer caps: %" GST_PTR_FORMAT, srccaps);
- } else {
- GstCaps *temp;
- GstStructure *s;
- const GValue *value;
- gint pt;
- gint clock_rate;
-
- /* peer provides caps we can use to fixate, intersect. This always returns a
- * writable caps. */
- temp = gst_caps_intersect (srccaps, peercaps);
- gst_caps_unref (srccaps);
- gst_caps_unref (peercaps);
-
- if (!temp) {
- GST_DEBUG_OBJECT (dtmfsrc, "Could not get intersection with peer caps");
- return FALSE;
- }
-
- if (gst_caps_is_empty (temp)) {
- GST_DEBUG_OBJECT (dtmfsrc, "Intersection with peer caps is empty");
- gst_caps_unref (temp);
- return FALSE;
- }
-
- /* now fixate, start by taking the first caps */
- temp = gst_caps_truncate (temp);
- temp = gst_caps_make_writable (temp);
- srccaps = temp;
-
- /* get first structure */
- s = gst_caps_get_structure (srccaps, 0);
-
- if (gst_structure_get_int (s, "payload", &pt)) {
- /* use peer pt */
- dtmfsrc->pt = pt;
- GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt);
- } else {
- if (gst_structure_has_field (s, "payload")) {
- /* can only fixate if there is a field */
- gst_structure_fixate_field_nearest_int (s, "payload", dtmfsrc->pt);
- gst_structure_get_int (s, "payload", &pt);
- GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt);
- } else {
- /* no pt field, use the internal pt */
- pt = dtmfsrc->pt;
- gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
- GST_LOG_OBJECT (dtmfsrc, "using internal pt %d", pt);
- }
- }
-
- if (gst_structure_get_int (s, "clock-rate", &clock_rate)) {
- dtmfsrc->clock_rate = clock_rate;
- GST_LOG_OBJECT (dtmfsrc, "using clock-rate from caps %d",
- dtmfsrc->clock_rate);
- } else {
- GST_LOG_OBJECT (dtmfsrc, "using existing clock-rate %d",
- dtmfsrc->clock_rate);
- }
- gst_structure_set (s, "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, NULL);
-
-
- if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
- value = gst_structure_get_value (s, "ssrc");
- dtmfsrc->current_ssrc = g_value_get_uint (value);
- GST_LOG_OBJECT (dtmfsrc, "using peer ssrc %08x", dtmfsrc->current_ssrc);
- } else {
- /* FIXME, fixate_nearest_uint would be even better */
- gst_structure_set (s, "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc, NULL);
- GST_LOG_OBJECT (dtmfsrc, "using internal ssrc %08x",
- dtmfsrc->current_ssrc);
- }
-
- if (gst_structure_has_field_typed (s, "clock-base", G_TYPE_UINT)) {
- value = gst_structure_get_value (s, "clock-base");
- dtmfsrc->ts_base = g_value_get_uint (value);
- GST_LOG_OBJECT (dtmfsrc, "using peer clock-base %u", dtmfsrc->ts_base);
- } else {
- /* FIXME, fixate_nearest_uint would be even better */
- gst_structure_set (s, "clock-base", G_TYPE_UINT, dtmfsrc->ts_base, NULL);
- GST_LOG_OBJECT (dtmfsrc, "using internal clock-base %u",
- dtmfsrc->ts_base);
- }
- if (gst_structure_has_field_typed (s, "seqnum-base", G_TYPE_UINT)) {
- value = gst_structure_get_value (s, "seqnum-base");
- dtmfsrc->seqnum_base = g_value_get_uint (value);
- GST_LOG_OBJECT (dtmfsrc, "using peer seqnum-base %u",
- dtmfsrc->seqnum_base);
- } else {
- /* FIXME, fixate_nearest_uint would be even better */
- gst_structure_set (s, "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base,
- NULL);
- GST_LOG_OBJECT (dtmfsrc, "using internal seqnum-base %u",
- dtmfsrc->seqnum_base);
- }
-
- if (gst_structure_has_field_typed (s, "ptime", G_TYPE_UINT)) {
- value = gst_structure_get_value (s, "ptime");
- dtmfsrc->ptime = g_value_get_uint (value);
- GST_LOG_OBJECT (dtmfsrc, "using peer ptime %u", dtmfsrc->ptime);
- } else if (gst_structure_has_field_typed (s, "maxptime", G_TYPE_UINT)) {
- value = gst_structure_get_value (s, "maxptime");
- dtmfsrc->ptime = g_value_get_uint (value);
- GST_LOG_OBJECT (dtmfsrc, "using peer maxptime as ptime %u",
- dtmfsrc->ptime);
- } else {
- /* FIXME, fixate_nearest_uint would be even better */
- gst_structure_set (s, "ptime", G_TYPE_UINT, dtmfsrc->ptime, NULL);
- GST_LOG_OBJECT (dtmfsrc, "using internal ptime %u", dtmfsrc->ptime);
- }
-
-
- GST_DEBUG_OBJECT (dtmfsrc, "with peer caps: %" GST_PTR_FORMAT, srccaps);
- }
-
- ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), srccaps);
- gst_caps_unref (srccaps);
-
- dtmfsrc->dirty = FALSE;
-
- return ret;
-
-}
-
-
-static void
-gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc * dtmfsrc)
-{
- if (dtmfsrc->ssrc == -1)
- dtmfsrc->current_ssrc = g_random_int ();
- else
- dtmfsrc->current_ssrc = dtmfsrc->ssrc;
-
- if (dtmfsrc->seqnum_offset == -1)
- dtmfsrc->seqnum_base = g_random_int_range (0, G_MAXUINT16);
- else
- dtmfsrc->seqnum_base = dtmfsrc->seqnum_offset;
- dtmfsrc->seqnum = dtmfsrc->seqnum_base;
-
- if (dtmfsrc->ts_offset == -1)
- dtmfsrc->ts_base = g_random_int ();
- else
- dtmfsrc->ts_base = dtmfsrc->ts_offset;
-
- dtmfsrc->timestamp = 0;
-}
-
-static GstStateChangeReturn
-gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition)
-{
- GstRTPDTMFSrc *dtmfsrc;
- GstStateChangeReturn result;
- gboolean no_preroll = FALSE;
- GstRTPDTMFSrcEvent *event = NULL;
-
- dtmfsrc = GST_RTP_DTMF_SRC (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_rtp_dtmf_src_ready_to_paused (dtmfsrc);
-
- /* Flushing the event queue */
- while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) {
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- gst_rtp_dtmf_src_event_free (event);
- }
- dtmfsrc->last_event_was_start = FALSE;
-
- no_preroll = TRUE;
- break;
- default:
- break;
- }
-
- if ((result =
- GST_ELEMENT_CLASS (gst_rtp_dtmf_src_parent_class)->change_state
- (element, transition)) == GST_STATE_CHANGE_FAILURE)
- goto failure;
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- no_preroll = TRUE;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
-
- /* Flushing the event queue */
- while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) {
- gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
- gst_rtp_dtmf_src_event_free (event);
- }
- dtmfsrc->last_event_was_start = FALSE;
-
- /* Indicate that we don't do PRE_ROLL */
- break;
-
- default:
- break;
- }
-
- if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
- result = GST_STATE_CHANGE_NO_PREROLL;
-
- return result;
-
- /* ERRORS */
-failure:
- {
- GST_ERROR_OBJECT (dtmfsrc, "parent failed state change");
- return result;
- }
-}
-
-
-static gboolean
-gst_rtp_dtmf_src_unlock (GstBaseSrc * src)
-{
- GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (src);
- GstRTPDTMFSrcEvent *event = NULL;
-
- GST_DEBUG_OBJECT (dtmfsrc, "Called unlock");
-
- GST_OBJECT_LOCK (dtmfsrc);
- dtmfsrc->paused = TRUE;
- if (dtmfsrc->clockid) {
- gst_clock_id_unschedule (dtmfsrc->clockid);
- }
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request");
- event = g_slice_new0 (GstRTPDTMFSrcEvent);
- event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK;
- g_async_queue_push (dtmfsrc->event_queue, event);
-
- return TRUE;
-}
-
-
-static gboolean
-gst_rtp_dtmf_src_unlock_stop (GstBaseSrc * src)
-{
- GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (src);
-
- GST_DEBUG_OBJECT (dtmfsrc, "Unlock stopped");
-
- GST_OBJECT_LOCK (dtmfsrc);
- dtmfsrc->paused = FALSE;
- GST_OBJECT_UNLOCK (dtmfsrc);
-
- return TRUE;
-}
-
-gboolean
-gst_rtp_dtmf_src_plugin_init (GstPlugin * plugin)
-{
- return gst_element_register (plugin, "rtpdtmfsrc",
- GST_RANK_NONE, GST_TYPE_RTP_DTMF_SRC);
-}
+++ /dev/null
-/* GStreamer RTP DTMF source
- *
- * gstrtpdtmfsrc.h:
- *
- * Copyright (C) <2007> Nokia Corporation.
- * Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
- * Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-
-#ifndef __GST_RTP_DTMF_SRC_H__
-#define __GST_RTP_DTMF_SRC_H__
-
-#include <gst/gst.h>
-#include <gst/base/gstbasesrc.h>
-#include <gst/rtp/gstrtpbuffer.h>
-
-#include "gstdtmfcommon.h"
-
-G_BEGIN_DECLS
-#define GST_TYPE_RTP_DTMF_SRC (gst_rtp_dtmf_src_get_type())
-#define GST_RTP_DTMF_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DTMF_SRC,GstRTPDTMFSrc))
-#define GST_RTP_DTMF_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DTMF_SRC,GstRTPDTMFSrcClass))
-#define GST_RTP_DTMF_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTP_DTMF_SRC, GstRTPDTMFSrcClass))
-#define GST_IS_RTP_DTMF_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DTMF_SRC))
-#define GST_IS_RTP_DTMF_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DTMF_SRC))
-#define GST_RTP_DTMF_SRC_CAST(obj) ((GstRTPDTMFSrc *)(obj))
-typedef struct _GstRTPDTMFSrc GstRTPDTMFSrc;
-typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass;
-
-
-
-enum _GstRTPDTMFEventType
-{
- RTP_DTMF_EVENT_TYPE_START,
- RTP_DTMF_EVENT_TYPE_STOP,
- RTP_DTMF_EVENT_TYPE_PAUSE_TASK
-};
-
-typedef enum _GstRTPDTMFEventType GstRTPDTMFEventType;
-
-struct _GstRTPDTMFSrcEvent
-{
- GstRTPDTMFEventType event_type;
- GstRTPDTMFPayload *payload;
-};
-
-typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent;
-
-/**
- * GstRTPDTMFSrc:
- * @element: the parent element.
- *
- * The opaque #GstRTPDTMFSrc data structure.
- */
-struct _GstRTPDTMFSrc
-{
- /*< private >*/
- GstBaseSrc basesrc;
-
- GAsyncQueue *event_queue;
- GstClockID clockid;
- gboolean paused;
- GstRTPDTMFPayload *payload;
-
- GstClockTime timestamp;
- GstClockTime start_timestamp;
- gboolean first_packet;
- gboolean last_packet;
- guint32 ts_base;
- guint16 seqnum_base;
- gint16 seqnum_offset;
- guint16 seqnum;
- gint32 ts_offset;
- guint32 rtp_timestamp;
- guint pt;
- guint ssrc;
- guint current_ssrc;
- guint16 ptime;
- guint16 packet_redundancy;
- guint32 clock_rate;
- gboolean last_event_was_start;
-
- GstClockTime last_stop;
-
- gboolean dirty;
- guint16 redundancy_count;
-};
-
-struct _GstRTPDTMFSrcClass
-{
- GstBaseSrcClass parent_class;
-};
-
-GType gst_rtp_dtmf_src_get_type (void);
-
-gboolean gst_rtp_dtmf_src_plugin_init (GstPlugin * plugin);
-
-
-G_END_DECLS
-#endif /* __GST_RTP_DTMF_SRC_H__ */
elements/baseaudiovisualizer \
elements/camerabin \
elements/dataurisrc \
- elements/dtmf \
elements/gdppay \
elements/gdpdepay \
$(check_jifmux) \
$(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
elements_camerabin_SOURCES = elements/camerabin.c
-elements_dtmf_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
- $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
-elements_dtmf_LDADD = $(GST_BASE_LIBS) $(LDADD) -lgstrtp-@GST_API_VERSION@
-
elements_jifmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(EXIF_CFLAGS) $(AM_CFLAGS)
elements_jifmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_API_VERSION) $(GST_CHECK_LIBS) $(EXIF_LIBS) $(LDADD)
elements_jifmux_SOURCES = elements/jifmux.c
curlsmtpsink
deinterleave
dataurisrc
-dtmf
faac
faad
gdpdepay
+++ /dev/null
-/* GStreamer
- *
- * unit test for dtmf elements
- * Copyright (C) 2013 Collabora Ltd
- * @author: Olivier Crete <olivier.crete@collabora.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/audio/audio.h>
-#include <gst/check/gstcheck.h>
-#include <gst/check/gsttestclock.h>
-#include <gst/rtp/gstrtpbuffer.h>
-
-
-/* Include this from the plugin to get the defines */
-
-#include "../../gst/dtmf/gstdtmfcommon.h"
-
-#define END_BIT (1<<7)
-
-static GstStaticPadTemplate audio_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw, "
- "format = (string) \"" GST_AUDIO_NE (S16) "\", "
- "rate = " GST_AUDIO_RATE_RANGE ", " "channels = (int) 1")
- );
-
-static GstStaticPadTemplate rtp_dtmf_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-rtp, "
- "media = (string) \"audio\", "
- "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
- "clock-rate = (int) [ 0, MAX ], "
- "encoding-name = (string) \"TELEPHONE-EVENT\"")
- );
-
-
-static void
-check_get_dtmf_event_message (GstBus * bus, gint number, gint volume)
-{
- GstMessage *message;
- gboolean have_message = FALSE;
-
- while (!have_message &&
- (message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT)) != NULL) {
- if (gst_message_has_name (message, "dtmf-event")) {
- const GstStructure *s = gst_message_get_structure (message);
- gint stype, snumber, smethod, svolume;
-
- fail_unless (gst_structure_get (s,
- "type", G_TYPE_INT, &stype,
- "number", G_TYPE_INT, &snumber,
- "method", G_TYPE_INT, &smethod,
- "volume", G_TYPE_INT, &svolume, NULL));
-
- fail_unless (stype == 1);
- fail_unless (smethod == 1);
- fail_unless (snumber == number);
- fail_unless (svolume == volume);
- have_message = TRUE;
- }
- gst_message_unref (message);
- }
-
- fail_unless (have_message);
-}
-
-static void
-check_no_dtmf_event_message (GstBus * bus)
-{
- GstMessage *message;
- gboolean have_message = FALSE;
-
- while (!have_message &&
- (message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT)) != NULL) {
- if (gst_message_has_name (message, "dtmf-event") ||
- gst_message_has_name (message, "dtmf-event-processed") ||
- gst_message_has_name (message, "dtmf-event-dropped")) {
- have_message = TRUE;
- }
- gst_message_unref (message);
- }
-
- fail_unless (!have_message);
-}
-
-static void
-check_buffers_duration (GstClockTime expected_duration)
-{
- GstClockTime duration = 0;
-
- while (buffers) {
- GstBuffer *buf = buffers->data;
-
- buffers = g_list_delete_link (buffers, buffers);
-
- fail_unless (GST_BUFFER_DURATION_IS_VALID (buf));
- duration += GST_BUFFER_DURATION (buf);
- gst_buffer_unref (buf);
- }
-
- fail_unless (duration == expected_duration);
-}
-
-static void
-send_rtp_packet (GstPad * src, guint timestamp, gboolean marker, gboolean end,
- guint number, guint volume, guint duration)
-{
- GstBuffer *buf;
- GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
- gchar *payload;
- static guint seqnum = 1;
-
- buf = gst_rtp_buffer_new_allocate (4, 0, 0);
- fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtpbuf));
- gst_rtp_buffer_set_seq (&rtpbuf, seqnum++);
- gst_rtp_buffer_set_timestamp (&rtpbuf, timestamp);
- gst_rtp_buffer_set_marker (&rtpbuf, marker);
- payload = gst_rtp_buffer_get_payload (&rtpbuf);
- payload[0] = number;
- payload[1] = volume | (end ? END_BIT : 0);
- GST_WRITE_UINT16_BE (payload + 2, duration);
- gst_rtp_buffer_unmap (&rtpbuf);
- fail_unless (gst_pad_push (src, buf) == GST_FLOW_OK);
-}
-
-GST_START_TEST (test_rtpdtmfdepay)
-{
- GstElement *dtmfdepay;
- GstPad *src, *sink;
- GstBus *bus;
- GstCaps *caps_in;
- GstCaps *expected_caps_out;
- GstCaps *caps_out;
-
- dtmfdepay = gst_check_setup_element ("rtpdtmfdepay");
- sink = gst_check_setup_sink_pad (dtmfdepay, &audio_sink_template);
- src = gst_check_setup_src_pad (dtmfdepay, &rtp_dtmf_src_template);
-
- bus = gst_bus_new ();
- gst_element_set_bus (dtmfdepay, bus);
-
- gst_pad_set_active (src, TRUE);
- gst_pad_set_active (sink, TRUE);
- gst_element_set_state (dtmfdepay, GST_STATE_PLAYING);
-
-
- caps_in = gst_caps_new_simple ("application/x-rtp",
- "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT",
- "media", G_TYPE_STRING, "audio",
- "clock-rate", G_TYPE_INT, 1000, "payload", G_TYPE_INT, 99, NULL);
- fail_unless (gst_pad_set_caps (src, caps_in));
- gst_caps_unref (caps_in);
-
- caps_out = gst_pad_get_current_caps (sink);
- expected_caps_out = gst_caps_new_simple ("audio/x-raw",
- "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
- "rate", G_TYPE_INT, 1000, "channels", G_TYPE_INT, 1, NULL);
- fail_unless (gst_caps_is_equal_fixed (caps_out, expected_caps_out));
- gst_caps_unref (expected_caps_out);
- gst_caps_unref (caps_out);
-
- /* Single packet DTMF */
- send_rtp_packet (src, 200, TRUE, TRUE, 1, 5, 250);
- check_get_dtmf_event_message (bus, 1, 5);
- check_buffers_duration (250 * GST_MSECOND);
-
- /* Two packet DTMF */
- send_rtp_packet (src, 800, TRUE, FALSE, 1, 5, 200);
- send_rtp_packet (src, 800, FALSE, TRUE, 1, 5, 400);
- check_buffers_duration (400 * GST_MSECOND);
- check_get_dtmf_event_message (bus, 1, 5);
-
- /* Long DTMF */
- send_rtp_packet (src, 3000, TRUE, FALSE, 1, 5, 200);
- check_get_dtmf_event_message (bus, 1, 5);
- check_buffers_duration (200 * GST_MSECOND);
- send_rtp_packet (src, 3000, FALSE, FALSE, 1, 5, 400);
- check_no_dtmf_event_message (bus);
- check_buffers_duration (200 * GST_MSECOND);
- send_rtp_packet (src, 3000, FALSE, FALSE, 1, 5, 600);
- check_no_dtmf_event_message (bus);
- check_buffers_duration (200 * GST_MSECOND);
-
- /* New without end to last */
- send_rtp_packet (src, 4000, TRUE, TRUE, 1, 5, 250);
- check_get_dtmf_event_message (bus, 1, 5);
- check_buffers_duration (250 * GST_MSECOND);
-
- check_no_dtmf_event_message (bus);
- fail_unless (buffers == NULL);
- gst_element_set_bus (dtmfdepay, NULL);
- gst_object_unref (bus);
-
- gst_pad_set_active (src, FALSE);
- gst_pad_set_active (sink, FALSE);
- gst_check_teardown_sink_pad (dtmfdepay);
- gst_check_teardown_src_pad (dtmfdepay);
- gst_check_teardown_element (dtmfdepay);
-}
-
-GST_END_TEST;
-
-
-static GstStaticPadTemplate rtp_dtmf_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-rtp, "
- "media = (string) \"audio\", "
- "payload = (int) 99, "
- "clock-rate = (int) 1000, "
- "seqnum-base = (uint) 333, "
- "clock-base = (uint) 666, "
- "ssrc = (uint) 999, "
- "maxptime = (uint) 20, encoding-name = (string) \"TELEPHONE-EVENT\"")
- );
-
-GstElement *dtmfsrc;
-GstPad *sink;
-GstClock *testclock;
-GstBus *bus;
-
-static void
-check_message_structure (GstStructure * expected_s)
-{
- GstMessage *message;
- gboolean have_message = FALSE;
-
- while (!have_message &&
- (message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
- GST_MESSAGE_ELEMENT)) != NULL) {
- if (gst_message_has_name (message, gst_structure_get_name (expected_s))) {
- const GstStructure *s = gst_message_get_structure (message);
-
- fail_unless (gst_structure_is_equal (s, expected_s));
- have_message = TRUE;
- }
- gst_message_unref (message);
- }
-
- fail_unless (have_message);
-
- gst_structure_free (expected_s);
-}
-
-static void
-check_rtp_buffer (GstClockTime ts, GstClockTime duration, gboolean start,
- gboolean end, guint rtpts, guint ssrc, guint volume, guint number,
- guint rtpduration)
-{
- GstBuffer *buffer;
- GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
- gchar *payload;
-
- g_mutex_lock (&check_mutex);
- while (buffers == NULL)
- g_cond_wait (&check_cond, &check_mutex);
- g_mutex_unlock (&check_mutex);
- fail_unless (buffers != NULL);
-
- buffer = buffers->data;
- buffers = g_list_delete_link (buffers, buffers);
-
- fail_unless (GST_BUFFER_PTS (buffer) == ts);
- fail_unless (GST_BUFFER_DURATION (buffer) == duration);
-
- fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtpbuffer));
- fail_unless (gst_rtp_buffer_get_marker (&rtpbuffer) == start);
- fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) == rtpts);
- payload = gst_rtp_buffer_get_payload (&rtpbuffer);
-
- fail_unless (payload[0] == number);
- fail_unless ((payload[1] & 0x7F) == volume);
- fail_unless (! !(payload[1] & 0x80) == end);
- fail_unless (GST_READ_UINT16_BE (payload + 2) == rtpduration);
-
- gst_rtp_buffer_unmap (&rtpbuffer);
- gst_buffer_unref (buffer);
-}
-
-gint method;
-
-static void
-setup_rtpdtmfsrc (void)
-{
- testclock = gst_test_clock_new ();
- bus = gst_bus_new ();
-
- method = 1;
- dtmfsrc = gst_check_setup_element ("rtpdtmfsrc");
- sink = gst_check_setup_sink_pad (dtmfsrc, &rtp_dtmf_sink_template);
- gst_element_set_bus (dtmfsrc, bus);
- fail_unless (gst_element_set_clock (dtmfsrc, testclock));
-
- gst_pad_set_active (sink, TRUE);
- fail_unless (gst_element_set_state (dtmfsrc, GST_STATE_PLAYING) ==
- GST_STATE_CHANGE_SUCCESS);
-}
-
-static void
-teardown_dtmfsrc (void)
-{
- gst_object_unref (testclock);
- gst_pad_set_active (sink, FALSE);
- gst_element_set_bus (dtmfsrc, NULL);
- gst_object_unref (bus);
- gst_check_teardown_sink_pad (dtmfsrc);
- gst_check_teardown_element (dtmfsrc);
-}
-
-GST_START_TEST (test_dtmfsrc_invalid_events)
-{
- GstStructure *s;
-
- /* Missing start */
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
- "method", G_TYPE_INT, method, "volume", G_TYPE_INT, 8, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)) == FALSE);
-
- /* Missing volume */
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
- "method", G_TYPE_INT, method, "start", G_TYPE_BOOLEAN, TRUE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)) == FALSE);
-
- /* Missing number */
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "method", G_TYPE_INT, method,
- "volume", G_TYPE_INT, 8, "start", G_TYPE_BOOLEAN, TRUE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)) == FALSE);
-
- /* Missing type */
- s = gst_structure_new ("dtmf-event",
- "number", G_TYPE_INT, 3, "method", G_TYPE_INT, method,
- "volume", G_TYPE_INT, 8, "start", G_TYPE_BOOLEAN, TRUE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)) == FALSE);
-
- /* Stop before start */
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
- "method", G_TYPE_INT, method, "volume", G_TYPE_INT, 8,
- "start", G_TYPE_BOOLEAN, FALSE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)) == FALSE);
-
- gst_element_set_state (dtmfsrc, GST_STATE_NULL);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_rtpdtmfsrc_min_duration)
-{
- GstStructure *s;
- GstClockID id;
- guint timestamp = 0;
- GstCaps *expected_caps, *caps;
-
- /* Minimum duration dtmf */
-
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
- "method", G_TYPE_INT, 1, "volume", G_TYPE_INT, 8,
- "start", G_TYPE_BOOLEAN, TRUE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
- gst_structure_copy (s))));
- check_no_dtmf_event_message (bus);
- gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (testclock), NULL);
- fail_unless (buffers == NULL);
- id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (testclock));
- fail_unless (gst_clock_id_get_time (id) == 0);
- gst_clock_id_unref (id);
- gst_structure_set_name (s, "dtmf-event-processed");
- check_message_structure (s);
-
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1,
- "start", G_TYPE_BOOLEAN, FALSE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
- gst_structure_copy (s))));
-
- check_rtp_buffer (0, 20 * GST_MSECOND, TRUE, FALSE, 666, 999, 8, 3, 20);
-
- for (timestamp = 20; timestamp < MIN_PULSE_DURATION + 20; timestamp += 20) {
- gst_test_clock_advance_time (GST_TEST_CLOCK (testclock),
- 20 * GST_MSECOND + 1);
- gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (testclock), NULL);
- fail_unless (buffers == NULL);
- id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (testclock));
- fail_unless (gst_clock_id_get_time (id) == timestamp * GST_MSECOND);
- gst_clock_id_unref (id);
-
- if (timestamp < MIN_PULSE_DURATION) {
- check_rtp_buffer (timestamp * GST_MSECOND, 20 * GST_MSECOND, FALSE,
- FALSE, 666, 999, 8, 3, timestamp + 20);
- check_no_dtmf_event_message (bus);
- } else {
- gst_structure_set_name (s, "dtmf-event-processed");
- check_message_structure (s);
- check_rtp_buffer (timestamp * GST_MSECOND,
- (20 + MIN_INTER_DIGIT_INTERVAL) * GST_MSECOND, FALSE, TRUE, 666,
- 999, 8, 3, timestamp + 20);
- }
-
- fail_unless (buffers == NULL);
- }
-
-
- fail_unless (gst_test_clock_peek_id_count (GST_TEST_CLOCK (testclock)) == 0);
-
- /* caps check */
-
- expected_caps = gst_caps_new_simple ("application/x-rtp",
- "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT",
- "media", G_TYPE_STRING, "audio",
- "clock-rate", G_TYPE_INT, 1000, "payload", G_TYPE_INT, 99,
- "seqnum-base", G_TYPE_UINT, 333,
- "clock-base", G_TYPE_UINT, 666,
- "ssrc", G_TYPE_UINT, 999, "ptime", G_TYPE_UINT, 20, NULL);
- caps = gst_pad_get_current_caps (sink);
- fail_unless (gst_caps_can_intersect (caps, expected_caps));
- gst_caps_unref (caps);
- gst_caps_unref (expected_caps);
-
- gst_element_set_state (dtmfsrc, GST_STATE_NULL);
-
- check_no_dtmf_event_message (bus);
-}
-
-GST_END_TEST;
-
-static GstStaticPadTemplate audio_dtmfsrc_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw, "
- "format = (string) \"" GST_AUDIO_NE (S16) "\", "
- "rate = (int) 8003, " "channels = (int) 1")
- );
-static void
-setup_dtmfsrc (void)
-{
- testclock = gst_test_clock_new ();
- bus = gst_bus_new ();
-
- method = 2;
- dtmfsrc = gst_check_setup_element ("dtmfsrc");
- sink = gst_check_setup_sink_pad (dtmfsrc, &audio_dtmfsrc_sink_template);
- gst_element_set_bus (dtmfsrc, bus);
- fail_unless (gst_element_set_clock (dtmfsrc, testclock));
-
- gst_pad_set_active (sink, TRUE);
- fail_unless (gst_element_set_state (dtmfsrc, GST_STATE_PLAYING) ==
- GST_STATE_CHANGE_SUCCESS);
-}
-
-
-GST_START_TEST (test_dtmfsrc_min_duration)
-{
- GstStructure *s;
- GstClockID id;
- GstClockTime timestamp = 0;
- GstCaps *expected_caps, *caps;
- guint interval;
-
- g_object_get (dtmfsrc, "interval", &interval, NULL);
- fail_unless (interval == 50);
-
- /* Minimum duration dtmf */
- gst_test_clock_set_time (GST_TEST_CLOCK (testclock), 0);
-
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
- "method", G_TYPE_INT, 2, "volume", G_TYPE_INT, 8,
- "start", G_TYPE_BOOLEAN, TRUE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
- gst_structure_copy (s))));
-
- gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (testclock), NULL);
- id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (testclock));
- fail_unless (gst_clock_id_get_time (id) == 0);
- gst_clock_id_unref (id);
-
- gst_structure_set_name (s, "dtmf-event-processed");
- check_message_structure (s);
-
- s = gst_structure_new ("dtmf-event",
- "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 2,
- "start", G_TYPE_BOOLEAN, FALSE, NULL);
- fail_unless (gst_pad_push_event (sink,
- gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
- gst_structure_copy (s))));
-
- for (timestamp = interval * GST_MSECOND;
- timestamp < (MIN_PULSE_DURATION + MIN_INTER_DIGIT_INTERVAL) *
- GST_MSECOND; timestamp += GST_MSECOND * interval) {
- gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (testclock), NULL);
- gst_test_clock_advance_time (GST_TEST_CLOCK (testclock),
- interval * GST_MSECOND);
-
- id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (testclock));
- fail_unless (gst_clock_id_get_time (id) == timestamp);
- gst_clock_id_unref (id);
- }
-
- gst_structure_set_name (s, "dtmf-event-processed");
- check_message_structure (s);
-
- check_buffers_duration ((MIN_PULSE_DURATION + MIN_INTER_DIGIT_INTERVAL) *
- GST_MSECOND);
-
- fail_unless (gst_test_clock_peek_id_count (GST_TEST_CLOCK (testclock)) == 0);
-
- /* caps check */
-
- expected_caps = gst_caps_new_simple ("audio/x-raw",
- "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
- "rate", G_TYPE_INT, 8003, "channels", G_TYPE_INT, 1, NULL);
- caps = gst_pad_get_current_caps (sink);
- fail_unless (gst_caps_can_intersect (caps, expected_caps));
- gst_caps_unref (caps);
- gst_caps_unref (expected_caps);
-
- gst_element_set_state (dtmfsrc, GST_STATE_NULL);
-
- check_no_dtmf_event_message (bus);
-}
-
-GST_END_TEST;
-
-static Suite *
-dtmf_suite (void)
-{
- Suite *s = suite_create ("dtmf");
- TCase *tc;
-
- tc = tcase_create ("rtpdtmfdepay");
- tcase_add_test (tc, test_rtpdtmfdepay);
- suite_add_tcase (s, tc);
-
- tc = tcase_create ("rtpdtmfsrc");
- tcase_add_checked_fixture (tc, setup_rtpdtmfsrc, teardown_dtmfsrc);
- tcase_add_test (tc, test_dtmfsrc_invalid_events);
- tcase_add_test (tc, test_rtpdtmfsrc_min_duration);
- suite_add_tcase (s, tc);
-
- tc = tcase_create ("dtmfsrc");
- tcase_add_checked_fixture (tc, setup_dtmfsrc, teardown_dtmfsrc);
- tcase_add_test (tc, test_dtmfsrc_invalid_events);
- tcase_add_test (tc, test_dtmfsrc_min_duration);
- suite_add_tcase (s, tc);
-
- return s;
-}
-
-
-GST_CHECK_MAIN (dtmf);