2 * GStreamer - DTMF Detection
4 * Copyright 2009 Nokia Corporation
5 * Copyright 2009 Collabora Ltd,
6 * @author: Olivier Crete <olivier.crete@collabora.co.uk>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 * SECTION:element-dtmfdetect
27 * @short_description: Detects DTMF tones
29 * This element will detect DTMF tones and emit messages.
31 * The message is called <classname>"dtmf-event"</classname> and has
32 * the following fields:
36 * gint <classname>type</classname> (0-1):
37 * The application uses this field to specify which of the two methods
38 * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
39 * named events. Tones are specified by their frequencies and events are
40 * specfied by their number. This element can only take events as input.
41 * Do not confuse with "method" which specified the output.
46 * gint <classname>number</classname> (0-16):
52 * gint <classname>method</classname> (2):
53 * This field will always been 2 (ie sound) from this element.
63 #include "gstdtmfdetect.h"
67 #include <gst/audio/audio.h>
69 GST_DEBUG_CATEGORY (dtmf_detect_debug);
70 #define GST_CAT_DEFAULT (dtmf_detect_debug)
72 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
75 GST_STATIC_CAPS ("audio/x-raw, "
76 "format = (string) \"" GST_AUDIO_NE (S16) "\", "
77 "rate = (int) 8000, " "channels = (int) 1")
81 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
84 GST_STATIC_CAPS ("audio/x-raw, "
85 "format = (string) \"" GST_AUDIO_NE (S16) "\", "
86 "rate = (int) 8000, " "channels = (int) 1")
89 /* signals and args */
101 static gboolean gst_dtmf_detect_set_caps (GstBaseTransform * trans,
102 GstCaps * incaps, GstCaps * outcaps);
103 static GstFlowReturn gst_dtmf_detect_transform_ip (GstBaseTransform * trans,
105 static gboolean gst_dtmf_detect_sink_event (GstBaseTransform * trans,
108 G_DEFINE_TYPE (GstDtmfDetect, gst_dtmf_detect, GST_TYPE_BASE_TRANSFORM);
111 gst_dtmf_detect_class_init (GstDtmfDetectClass * klass)
113 GstElementClass *gstelement_class;
114 GstBaseTransformClass *gstbasetransform_class;
116 gstelement_class = GST_ELEMENT_CLASS (klass);
117 gstbasetransform_class = (GstBaseTransformClass *) klass;
119 GST_DEBUG_CATEGORY_INIT (dtmf_detect_debug, "dtmfdetect", 0, "dtmfdetect");
121 gst_element_class_add_pad_template (gstelement_class,
122 gst_static_pad_template_get (&srctemplate));
123 gst_element_class_add_pad_template (gstelement_class,
124 gst_static_pad_template_get (&sinktemplate));
126 gst_element_class_set_metadata (gstelement_class, "DTMF detector element",
127 "Filter/Analyzer/Audio",
128 "This element detects DTMF tones",
129 "Olivier Crete <olivier.crete@collabora.com>");
131 gstbasetransform_class->set_caps =
132 GST_DEBUG_FUNCPTR (gst_dtmf_detect_set_caps);
133 gstbasetransform_class->transform_ip =
134 GST_DEBUG_FUNCPTR (gst_dtmf_detect_transform_ip);
135 gstbasetransform_class->sink_event =
136 GST_DEBUG_FUNCPTR (gst_dtmf_detect_sink_event);
140 gst_dtmf_detect_init (GstDtmfDetect * dtmfdetect)
142 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (dtmfdetect), TRUE);
143 gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (dtmfdetect), TRUE);
147 gst_dtmf_detect_set_caps (GstBaseTransform * trans, GstCaps * incaps,
150 GstDtmfDetect *self = GST_DTMF_DETECT (trans);
152 zap_dtmf_detect_init (&self->dtmf_state);
159 gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
161 GstDtmfDetect *self = GST_DTMF_DETECT (trans);
163 gchar dtmfbuf[MAX_DTMF_DIGITS] = "";
167 if (GST_BUFFER_IS_DISCONT (buf))
168 zap_dtmf_detect_init (&self->dtmf_state);
169 if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP))
172 gst_buffer_map (buf, &map, GST_MAP_READ);
174 zap_dtmf_detect (&self->dtmf_state, (gint16 *) map.data, map.size / 2, FALSE);
176 dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS);
179 GST_DEBUG_OBJECT (self, "Got %d DTMF events: %s", dtmf_count, dtmfbuf);
181 GST_LOG_OBJECT (self, "Got no DTMF events");
183 gst_buffer_unmap (buf, &map);
185 for (i = 0; i < dtmf_count; i++) {
186 GstMessage *dtmf_message = NULL;
187 GstStructure *structure;
188 gint dtmf_payload_event;
190 GST_DEBUG_OBJECT (self, "Got DTMF event %c", dtmfbuf[i]);
192 switch (dtmfbuf[i]) {
194 dtmf_payload_event = 0;
197 dtmf_payload_event = 1;
200 dtmf_payload_event = 2;
203 dtmf_payload_event = 3;
206 dtmf_payload_event = 4;
209 dtmf_payload_event = 5;
212 dtmf_payload_event = 6;
215 dtmf_payload_event = 7;
218 dtmf_payload_event = 8;
221 dtmf_payload_event = 9;
224 dtmf_payload_event = 10;
227 dtmf_payload_event = 11;
230 dtmf_payload_event = 12;
233 dtmf_payload_event = 13;
236 dtmf_payload_event = 14;
239 dtmf_payload_event = 15;
245 structure = gst_structure_new ("dtmf-event",
246 "type", G_TYPE_INT, 1,
247 "number", G_TYPE_INT, dtmf_payload_event,
248 "method", G_TYPE_INT, 2, NULL);
249 dtmf_message = gst_message_new_element (GST_OBJECT (self), structure);
250 gst_element_post_message (GST_ELEMENT (self), dtmf_message);
258 gst_dtmf_detect_sink_event (GstBaseTransform * trans, GstEvent * event)
260 GstDtmfDetect *self = GST_DTMF_DETECT (trans);
262 switch (GST_EVENT_TYPE (event)) {
263 case GST_EVENT_FLUSH_STOP:
264 zap_dtmf_detect_init (&self->dtmf_state);
270 return GST_BASE_TRANSFORM_CLASS (gst_dtmf_detect_parent_class)->sink_event
276 gst_dtmf_detect_plugin_init (GstPlugin * plugin)
278 return gst_element_register (plugin, "dtmfdetect",
279 GST_RANK_MARGINAL, GST_TYPE_DTMF_DETECT);