From c2446a70f65e5483327a6596eb28ee3a255ab0eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 9 Mar 2013 01:06:31 +0000 Subject: [PATCH] Remove DTMF plugin, moved to -good https://bugzilla.gnome.org/show_bug.cgi?id=687416 --- Android.mk | 2 - configure.ac | 2 - docs/plugins/Makefile.am | 3 - .../plugins/gst-plugins-bad-plugins-docs.sgml | 3 - .../gst-plugins-bad-plugins-sections.txt | 53 - docs/plugins/inspect/plugin-dtmf.xml | 85 -- gst-plugins-bad.spec.in | 1 - gst/dtmf/Makefile.am | 31 - gst/dtmf/gstdtmf.c | 29 - gst/dtmf/gstdtmfcommon.h | 37 - gst/dtmf/gstdtmfsrc.c | 969 -------------- gst/dtmf/gstdtmfsrc.h | 101 -- gst/dtmf/gstrtpdtmfdepay.c | 543 -------- gst/dtmf/gstrtpdtmfdepay.h | 68 - gst/dtmf/gstrtpdtmfsrc.c | 1156 ----------------- gst/dtmf/gstrtpdtmfsrc.h | 115 -- tests/check/Makefile.am | 5 - tests/check/elements/.gitignore | 1 - tests/check/elements/dtmf.c | 588 --------- 19 files changed, 3792 deletions(-) delete mode 100644 docs/plugins/inspect/plugin-dtmf.xml delete mode 100644 gst/dtmf/Makefile.am delete mode 100644 gst/dtmf/gstdtmf.c delete mode 100644 gst/dtmf/gstdtmfcommon.h delete mode 100644 gst/dtmf/gstdtmfsrc.c delete mode 100644 gst/dtmf/gstdtmfsrc.h delete mode 100644 gst/dtmf/gstrtpdtmfdepay.c delete mode 100644 gst/dtmf/gstrtpdtmfdepay.h delete mode 100644 gst/dtmf/gstrtpdtmfsrc.c delete mode 100644 gst/dtmf/gstrtpdtmfsrc.h delete mode 100644 tests/check/elements/dtmf.c diff --git a/Android.mk b/Android.mk index b53166d3d8..02cc5e1f05 100644 --- a/Android.mk +++ b/Android.mk @@ -25,7 +25,6 @@ GST_PLUGINS_BAD_BUILT_SOURCES := \ 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 \ @@ -117,7 +116,6 @@ CONFIGURE_TARGETS += gst-plugins-bad-configure -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 diff --git a/configure.ac b/configure.ac index ab23418731..5064586429 100644 --- a/configure.ac +++ b/configure.ac @@ -346,7 +346,6 @@ AG_GST_CHECK_PLUGIN(coloreffects) 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) @@ -2282,7 +2281,6 @@ gst/coloreffects/Makefile gst/dataurisrc/Makefile gst/dccp/Makefile gst/debugutils/Makefile -gst/dtmf/Makefile gst/dvbsuboverlay/Makefile gst/dvdspu/Makefile gst/faceoverlay/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 1269355cf0..6e0fc594f5 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -129,9 +129,6 @@ EXTRA_HFILES = \ $(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 \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index 14acf82fee..c836d32a2d 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -40,7 +40,6 @@ - @@ -71,7 +70,6 @@ - @@ -109,7 +107,6 @@ - diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 7feecb7cac..bb231a5ed4 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -475,25 +475,6 @@ gst_dodge_get_type gst_dodge_plugin_init -
-element-dtmfsrc -dtmfsrc -GstDTMFSrc - -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 -
-
element-dtmfdetect dtmfdetect @@ -1174,40 +1155,6 @@ GST_RTMP_SRC_CLASS GST_IS_RTMP_SRC_CLASS
-
-element-rtpdtmfdepay -rtpdtmfdepay -GstRtpDTMFDepay - -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 -
- -
-element-rtpdtmfsrc -rtpdtmfsrc -GstRTPDTMFSrc - -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 -
-
element-sdlaudiosink sdlaudiosink diff --git a/docs/plugins/inspect/plugin-dtmf.xml b/docs/plugins/inspect/plugin-dtmf.xml deleted file mode 100644 index 0fe45fd3ad..0000000000 --- a/docs/plugins/inspect/plugin-dtmf.xml +++ /dev/null @@ -1,85 +0,0 @@ - - dtmf - DTMF plugins - ../../gst/dtmf/.libs/libgstdtmf.so - libgstdtmf.so - 1.1.0.1 - LGPL - gst-plugins-bad - GStreamer Bad Plug-ins git - Unknown package origin - - - dtmfdetect - DTMF detector element - Filter/Analyzer/Audio - This element detects DTMF tones - Olivier Crete <olivier.crete@collabora.com> - - - sink - sink - always -
audio/x-raw, format=(string)S16LE, rate=(int)8000, channels=(int)1
-
- - src - source - always -
audio/x-raw, format=(string)S16LE, rate=(int)8000, channels=(int)1
-
-
-
- - dtmfsrc - DTMF tone generator - Source/Audio - Generates DTMF tones - Youness Alaoui <youness.alaoui@collabora.co.uk> - - - src - source - always -
audio/x-raw, format=(string)S16LE, rate=(int)[ 1, 2147483647 ], channels=(int)1
-
-
-
- - rtpdtmfdepay - RTP DTMF packet depayloader - Codec/Depayloader/Network - Generates DTMF Sound from telephone-event RTP packets - Youness Alaoui <youness.alaoui@collabora.co.uk> - - - sink - sink - always -
application/x-rtp, media=(string)audio, payload=(int)[ 96, 127 ], clock-rate=(int)[ 0, 2147483647 ], encoding-name=(string)TELEPHONE-EVENT
-
- - src - source - always -
audio/x-raw, format=(string)S16LE, rate=(int)[ 1, 2147483647 ], channels=(int)1
-
-
-
- - rtpdtmfsrc - RTP DTMF packet generator - Source/Network - Generates RTP DTMF packets - Zeeshan Ali <zeeshan.ali@nokia.com> - - - src - source - always -
application/x-rtp, media=(string)audio, payload=(int)[ 96, 127 ], clock-rate=(int)[ 0, 2147483647 ], ssrc=(int)[ 0, 2147483647 ], encoding-name=(string)TELEPHONE-EVENT
-
-
-
-
-
\ No newline at end of file diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index fa38ab95ef..bb03b58e21 100644 --- a/gst-plugins-bad.spec.in +++ b/gst-plugins-bad.spec.in @@ -213,7 +213,6 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS='' # %{_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 diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am deleted file mode 100644 index 56eda1669d..0000000000 --- a/gst/dtmf/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -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' \ - > $@ diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c deleted file mode 100644 index 7fd5ee84f1..0000000000 --- a/gst/dtmf/gstdtmf.c +++ /dev/null @@ -1,29 +0,0 @@ - -#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) diff --git a/gst/dtmf/gstdtmfcommon.h b/gst/dtmf/gstdtmfcommon.h deleted file mode 100644 index 82617d72fd..0000000000 --- a/gst/dtmf/gstdtmfcommon.h +++ /dev/null @@ -1,37 +0,0 @@ - -#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__ */ diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c deleted file mode 100644 index a77e3ba8b8..0000000000 --- a/gst/dtmf/gstdtmfsrc.c +++ /dev/null @@ -1,969 +0,0 @@ -/* GStreamer DTMF source - * - * gstdtmfsrc.c: - * - * Copyright (C) <2007> Collabora. - * Contact: Youness Alaoui - * Copyright (C) <2007> Nokia Corporation. - * Contact: Zeeshan Ali - * Copyright (C) 1999,2000 Erik Walthinsen - * 2000,2005 Wim Taymans - * - * 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: - * - * - * - * - * - * - * - * - * - * Name - * GType - * Possible values - * Purpose - * - * - * - * - * type - * G_TYPE_INT - * 0-1 - * 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. - * - * - * - * number - * G_TYPE_INT - * 0-15 - * The event number. - * - * - * volume - * G_TYPE_INT - * 0-36 - * 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. - * - * - * - * start - * G_TYPE_BOOLEAN - * True or False - * Whether the event is starting or ending. - * - * - * method - * G_TYPE_INT - * 2 - * The method used for sending event, this element will react if this - * field is absent or 2. - * - * - * - * - * - * - * 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: - * - * - * 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); - * - * - * 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 -#include -#include - -#include - -#include "gstdtmfcommon.h" - -#include "gstdtmfsrc.h" - -#include - -#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 "); - - - 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); -} diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h deleted file mode 100644 index 04440bc185..0000000000 --- a/gst/dtmf/gstdtmfsrc.h +++ /dev/null @@ -1,101 +0,0 @@ -/* GStreamer DTMF source - * - * gstdtmfsrc.h: - * - * Copyright (C) <2007> Collabora. - * Contact: Youness Alaoui - * Copyright (C) <2007> Nokia Corporation. - * Contact: Zeeshan Ali - * Copyright (C) <2005> Wim Taymans - * - * 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 -#include -#include - -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__ */ diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c deleted file mode 100644 index d66f24a24d..0000000000 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ /dev/null @@ -1,543 +0,0 @@ -/* GstRtpDtmfDepay - * - * Copyright (C) 2008 Collabora Limited - * Copyright (C) 2008 Nokia Corporation - * Contact: Youness Alaoui - * - * 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 - * - * - * - * - * - * - * - * - * Name - * GType - * Possible values - * Purpose - * - * - * - * - * type - * G_TYPE_INT - * 0-1 - * 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. - * - * - * - * number - * G_TYPE_INT - * 0-16 - * The event number. - * - * - * volume - * G_TYPE_INT - * 0-36 - * 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. - * - * - * - * method - * G_TYPE_INT - * 1 - * This field will always been 1 (ie RTP event) from this element. - * - * - * - * - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstrtpdtmfdepay.h" - -#include -#include - -#include -#include - -#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 "); - - 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); -} diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h deleted file mode 100644 index c5ed189409..0000000000 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ /dev/null @@ -1,68 +0,0 @@ -/* GstRtpDtmfDepay - * - * Copyright (C) 2008 Collabora Limited - * Copyright (C) 2008 Nokia Corporation - * Contact: Youness Alaoui - * - * 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 -#include -#include - -#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__ */ diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c deleted file mode 100644 index 2a0b4a3bb4..0000000000 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* GStreamer RTP DTMF source - * - * gstrtpdtmfsrc.c: - * - * Copyright (C) <2007> Nokia Corporation. - * Contact: Zeeshan Ali - * Copyright (C) 1999,2000 Erik Walthinsen - * 2000,2005 Wim Taymans - * - * 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: - * - * - * - * - * - * - * - * - * - * Name - * GType - * Possible values - * Purpose - * - * - * - * - * type - * G_TYPE_INT - * 0-1 - * 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. - * - * - * - * number - * G_TYPE_INT - * 0-15 - * The event number. - * - * - * volume - * G_TYPE_INT - * 0-36 - * 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. - * - * - * - * start - * G_TYPE_BOOLEAN - * True or False - * Whether the event is starting or ending. - * - * - * method - * G_TYPE_INT - * 1 - * The method used for sending event, this element will react if this - * field is absent or 1. - * - * - * - * - * - * - * 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: - * - * - * 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); - * - * - * 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 -#include - -#include - -#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 "); - - 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); -} diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h deleted file mode 100644 index 3e9256ce58..0000000000 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ /dev/null @@ -1,115 +0,0 @@ -/* GStreamer RTP DTMF source - * - * gstrtpdtmfsrc.h: - * - * Copyright (C) <2007> Nokia Corporation. - * Contact: Zeeshan Ali - * Copyright (C) <2005> Wim Taymans - * - * 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 -#include -#include - -#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__ */ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index c7990b0904..51dd266cd3 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -207,7 +207,6 @@ check_PROGRAMS = \ elements/baseaudiovisualizer \ elements/camerabin \ elements/dataurisrc \ - elements/dtmf \ elements/gdppay \ elements/gdpdepay \ $(check_jifmux) \ @@ -338,10 +337,6 @@ elements_camerabin_LDADD = \ $(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 diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index da7a86a518..9d354b0b80 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -12,7 +12,6 @@ curlhttpsink curlsmtpsink deinterleave dataurisrc -dtmf faac faad gdpdepay diff --git a/tests/check/elements/dtmf.c b/tests/check/elements/dtmf.c deleted file mode 100644 index 454a3209ed..0000000000 --- a/tests/check/elements/dtmf.c +++ /dev/null @@ -1,588 +0,0 @@ -/* GStreamer - * - * unit test for dtmf elements - * Copyright (C) 2013 Collabora Ltd - * @author: Olivier Crete - * - * 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 -#include -#include -#include -#include - - -/* 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); -- 2.34.1