docs: Port all docstring to gtk-doc markdown
[platform/upstream/gstreamer.git] / gst / dtmf / gstrtpdtmfdepay.c
1 /* GstRtpDtmfDepay
2  *
3  * Copyright (C) 2008 Collabora Limited
4  * Copyright (C) 2008 Nokia Corporation
5  *   Contact: Youness Alaoui <youness.alaoui@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 /**
23  * SECTION:element-rtpdtmfdepay
24  * @title: rtpdtmfdepay
25  * @see_also: rtpdtmfsrc, rtpdtmfmux
26  *
27  * This element takes RTP DTMF packets and produces sound. It also emits a
28  * message on the #GstBus.
29  *
30  * The message is called "dtmf-event" and has the following fields
31  * <informaltable>
32  * <tgroup cols='4'>
33  * <colspec colname='Name' />
34  * <colspec colname='Type' />
35  * <colspec colname='Possible values' />
36  * <colspec colname='Purpose' />
37  * <thead>
38  * <row>
39  * <entry>Name</entry>
40  * <entry>GType</entry>
41  * <entry>Possible values</entry>
42  * <entry>Purpose</entry>
43  * </row>
44  * </thead>
45  * <tbody>
46  * <row>
47  * <entry>type</entry>
48  * <entry>G_TYPE_INT</entry>
49  * <entry>0-1</entry>
50  * <entry>Which of the two methods
51  * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
52  * named events. Tones are specified by their frequencies and events are specied
53  * by their number. This element currently only recognizes events.
54  * Do not confuse with "method" which specified the output.
55  * </entry>
56  * </row>
57  * <row>
58  * <entry>number</entry>
59  * <entry>G_TYPE_INT</entry>
60  * <entry>0-16</entry>
61  * <entry>The event number.</entry>
62  * </row>
63  * <row>
64  * <entry>volume</entry>
65  * <entry>G_TYPE_INT</entry>
66  * <entry>0-36</entry>
67  * <entry>This field describes the power level of the tone, expressed in dBm0
68  * after dropping the sign. Power levels range from 0 to -63 dBm0. The range of
69  * valid DTMF is from 0 to -36 dBm0.
70  * </entry>
71  * </row>
72  * <row>
73  * <entry>method</entry>
74  * <entry>G_TYPE_INT</entry>
75  * <entry>1</entry>
76  * <entry>This field will always been 1 (ie RTP event) from this element.
77  * </entry>
78  * </row>
79  * </tbody>
80  * </tgroup>
81  * </informaltable>
82  */
83
84 #ifdef HAVE_CONFIG_H
85 #include "config.h"
86 #endif
87
88 #include "gstrtpdtmfdepay.h"
89
90 #include <string.h>
91 #include <math.h>
92
93 #include <gst/audio/audio.h>
94 #include <gst/rtp/gstrtpbuffer.h>
95
96 #define DEFAULT_PACKET_INTERVAL  50     /* ms */
97 #define MIN_PACKET_INTERVAL      10     /* ms */
98 #define MAX_PACKET_INTERVAL      50     /* ms */
99 #define SAMPLE_RATE              8000
100 #define SAMPLE_SIZE              16
101 #define CHANNELS                 1
102 #define MIN_DUTY_CYCLE           (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION)
103
104 #define MIN_UNIT_TIME            0
105 #define MAX_UNIT_TIME            1000
106 #define DEFAULT_UNIT_TIME        0
107
108 #define DEFAULT_MAX_DURATION     0
109
110 typedef struct st_dtmf_key
111 {
112   float low_frequency;
113   float high_frequency;
114 } DTMF_KEY;
115
116 static const DTMF_KEY DTMF_KEYS[] = {
117   {941, 1336},
118   {697, 1209},
119   {697, 1336},
120   {697, 1477},
121   {770, 1209},
122   {770, 1336},
123   {770, 1477},
124   {852, 1209},
125   {852, 1336},
126   {852, 1477},
127   {941, 1209},
128   {941, 1477},
129   {697, 1633},
130   {770, 1633},
131   {852, 1633},
132   {941, 1633},
133 };
134
135 #define MAX_DTMF_EVENTS 16
136
137 enum
138 {
139   DTMF_KEY_EVENT_1 = 1,
140   DTMF_KEY_EVENT_2 = 2,
141   DTMF_KEY_EVENT_3 = 3,
142   DTMF_KEY_EVENT_4 = 4,
143   DTMF_KEY_EVENT_5 = 5,
144   DTMF_KEY_EVENT_6 = 6,
145   DTMF_KEY_EVENT_7 = 7,
146   DTMF_KEY_EVENT_8 = 8,
147   DTMF_KEY_EVENT_9 = 9,
148   DTMF_KEY_EVENT_0 = 0,
149   DTMF_KEY_EVENT_STAR = 10,
150   DTMF_KEY_EVENT_POUND = 11,
151   DTMF_KEY_EVENT_A = 12,
152   DTMF_KEY_EVENT_B = 13,
153   DTMF_KEY_EVENT_C = 14,
154   DTMF_KEY_EVENT_D = 15,
155 };
156
157 GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_depay_debug);
158 #define GST_CAT_DEFAULT gst_rtp_dtmf_depay_debug
159
160 enum
161 {
162   /* FILL ME */
163   LAST_SIGNAL
164 };
165
166 enum
167 {
168   PROP_0,
169   PROP_UNIT_TIME,
170   PROP_MAX_DURATION
171 };
172
173 static GstStaticPadTemplate gst_rtp_dtmf_depay_src_template =
174 GST_STATIC_PAD_TEMPLATE ("src",
175     GST_PAD_SRC,
176     GST_PAD_ALWAYS,
177     GST_STATIC_CAPS ("audio/x-raw, "
178         "format = (string) \"" GST_AUDIO_NE (S16) "\", "
179         "rate = " GST_AUDIO_RATE_RANGE ", " "channels = (int) 1")
180     );
181
182 static GstStaticPadTemplate gst_rtp_dtmf_depay_sink_template =
183 GST_STATIC_PAD_TEMPLATE ("sink",
184     GST_PAD_SINK,
185     GST_PAD_ALWAYS,
186     GST_STATIC_CAPS ("application/x-rtp, "
187         "media = (string) \"audio\", "
188         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
189         "clock-rate = (int) [ 0, MAX ], "
190         "encoding-name = (string) \"TELEPHONE-EVENT\"")
191     );
192
193 G_DEFINE_TYPE (GstRtpDTMFDepay, gst_rtp_dtmf_depay,
194     GST_TYPE_RTP_BASE_DEPAYLOAD);
195
196 static void gst_rtp_dtmf_depay_set_property (GObject * object, guint prop_id,
197     const GValue * value, GParamSpec * pspec);
198 static void gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id,
199     GValue * value, GParamSpec * pspec);
200 static GstBuffer *gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload,
201     GstBuffer * buf);
202 gboolean gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter,
203     GstCaps * caps);
204
205 static void
206 gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass)
207 {
208   GObjectClass *gobject_class;
209   GstElementClass *gstelement_class;
210   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
211
212   gobject_class = G_OBJECT_CLASS (klass);
213   gstelement_class = GST_ELEMENT_CLASS (klass);
214   gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
215
216   gst_element_class_add_static_pad_template (gstelement_class,
217       &gst_rtp_dtmf_depay_src_template);
218   gst_element_class_add_static_pad_template (gstelement_class,
219       &gst_rtp_dtmf_depay_sink_template);
220
221   GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug,
222       "rtpdtmfdepay", 0, "rtpdtmfdepay element");
223   gst_element_class_set_static_metadata (gstelement_class,
224       "RTP DTMF packet depayloader", "Codec/Depayloader/Network",
225       "Generates DTMF Sound from telephone-event RTP packets",
226       "Youness Alaoui <youness.alaoui@collabora.co.uk>");
227
228   gobject_class->set_property =
229       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_set_property);
230   gobject_class->get_property =
231       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_get_property);
232
233   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_UNIT_TIME,
234       g_param_spec_uint ("unit-time", "Duration unittime",
235           "The smallest unit (ms) the duration must be a multiple of (0 disables it)",
236           MIN_UNIT_TIME, MAX_UNIT_TIME, DEFAULT_UNIT_TIME,
237           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
238
239   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_DURATION,
240       g_param_spec_uint ("max-duration", "Maximum duration",
241           "The maxumimum duration (ms) of the outgoing soundpacket. "
242           "(0 = no limit)", 0, G_MAXUINT, DEFAULT_MAX_DURATION,
243           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
244
245   gstrtpbasedepayload_class->process =
246       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process);
247   gstrtpbasedepayload_class->set_caps =
248       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_setcaps);
249
250 }
251
252 static void
253 gst_rtp_dtmf_depay_init (GstRtpDTMFDepay * rtpdtmfdepay)
254 {
255   rtpdtmfdepay->unit_time = DEFAULT_UNIT_TIME;
256 }
257
258 static void
259 gst_rtp_dtmf_depay_set_property (GObject * object, guint prop_id,
260     const GValue * value, GParamSpec * pspec)
261 {
262   GstRtpDTMFDepay *rtpdtmfdepay;
263
264   rtpdtmfdepay = GST_RTP_DTMF_DEPAY (object);
265
266   switch (prop_id) {
267     case PROP_UNIT_TIME:
268       rtpdtmfdepay->unit_time = g_value_get_uint (value);
269       break;
270     case PROP_MAX_DURATION:
271       rtpdtmfdepay->max_duration = g_value_get_uint (value);
272       break;
273     default:
274       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275       break;
276   }
277 }
278
279 static void
280 gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id,
281     GValue * value, GParamSpec * pspec)
282 {
283   GstRtpDTMFDepay *rtpdtmfdepay;
284
285   rtpdtmfdepay = GST_RTP_DTMF_DEPAY (object);
286
287   switch (prop_id) {
288     case PROP_UNIT_TIME:
289       g_value_set_uint (value, rtpdtmfdepay->unit_time);
290       break;
291     case PROP_MAX_DURATION:
292       g_value_set_uint (value, rtpdtmfdepay->max_duration);
293       break;
294     default:
295       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
296       break;
297   }
298 }
299
300 gboolean
301 gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps)
302 {
303   GstCaps *filtercaps, *srccaps;
304   GstStructure *structure = gst_caps_get_structure (caps, 0);
305   gint clock_rate = 8000;       /* default */
306
307   gst_structure_get_int (structure, "clock-rate", &clock_rate);
308   filter->clock_rate = clock_rate;
309
310   filtercaps =
311       gst_pad_get_pad_template_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter));
312
313   filtercaps = gst_caps_make_writable (filtercaps);
314   gst_caps_set_simple (filtercaps, "rate", G_TYPE_INT, clock_rate, NULL);
315
316   srccaps = gst_pad_peer_query_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter),
317       filtercaps);
318   gst_caps_unref (filtercaps);
319
320   gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter), srccaps);
321   gst_caps_unref (srccaps);
322
323   return TRUE;
324 }
325
326 static GstBuffer *
327 gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay,
328     GstRTPDTMFPayload payload)
329 {
330   GstBuffer *buf;
331   GstMapInfo map;
332   gint16 *p;
333   gint tone_size;
334   double i = 0;
335   double amplitude, f1, f2;
336   double volume_factor;
337   DTMF_KEY key = DTMF_KEYS[payload.event];
338   guint32 clock_rate;
339   GstRTPBaseDepayload *depayload = GST_RTP_BASE_DEPAYLOAD (rtpdtmfdepay);
340   gint volume;
341   static GstAllocationParams params = { 0, 1, 0, 0, };
342
343   clock_rate = depayload->clock_rate;
344
345   /* Create a buffer for the tone */
346   tone_size = (payload.duration * SAMPLE_SIZE * CHANNELS) / 8;
347   buf = gst_buffer_new_allocate (NULL, tone_size, &params);
348   GST_BUFFER_DURATION (buf) = payload.duration * GST_SECOND / clock_rate;
349   volume = payload.volume;
350
351   gst_buffer_map (buf, &map, GST_MAP_WRITE);
352   p = (gint16 *) map.data;
353
354   volume_factor = pow (10, (-volume) / 20);
355
356   /*
357    * For each sample point we calculate 'x' as the
358    * the amplitude value.
359    */
360   for (i = 0; i < (tone_size / (SAMPLE_SIZE / 8)); i++) {
361     /*
362      * We add the fundamental frequencies together.
363      */
364     f1 = sin (2 * M_PI * key.low_frequency * (rtpdtmfdepay->sample /
365             clock_rate));
366     f2 = sin (2 * M_PI * key.high_frequency * (rtpdtmfdepay->sample /
367             clock_rate));
368
369     amplitude = (f1 + f2) / 2;
370
371     /* Adjust the volume */
372     amplitude *= volume_factor;
373
374     /* Make the [-1:1] interval into a [-32767:32767] interval */
375     amplitude *= 32767;
376
377     /* Store it in the data buffer */
378     *(p++) = (gint16) amplitude;
379
380     (rtpdtmfdepay->sample)++;
381   }
382
383   gst_buffer_unmap (buf, &map);
384
385   return buf;
386 }
387
388
389 static GstBuffer *
390 gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
391 {
392
393   GstRtpDTMFDepay *rtpdtmfdepay = NULL;
394   GstBuffer *outbuf = NULL;
395   gint payload_len;
396   guint8 *payload = NULL;
397   guint32 timestamp;
398   GstRTPDTMFPayload dtmf_payload;
399   gboolean marker;
400   GstStructure *structure = NULL;
401   GstMessage *dtmf_message = NULL;
402   GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
403
404   rtpdtmfdepay = GST_RTP_DTMF_DEPAY (depayload);
405
406   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuffer);
407
408   payload_len = gst_rtp_buffer_get_payload_len (&rtpbuffer);
409   payload = gst_rtp_buffer_get_payload (&rtpbuffer);
410
411   if (payload_len != sizeof (GstRTPDTMFPayload))
412     goto bad_packet;
413
414   memcpy (&dtmf_payload, payload, sizeof (GstRTPDTMFPayload));
415
416   if (dtmf_payload.event > MAX_EVENT)
417     goto bad_packet;
418
419   marker = gst_rtp_buffer_get_marker (&rtpbuffer);
420
421   timestamp = gst_rtp_buffer_get_timestamp (&rtpbuffer);
422
423   dtmf_payload.duration = g_ntohs (dtmf_payload.duration);
424
425   /* clip to whole units of unit_time */
426   if (rtpdtmfdepay->unit_time) {
427     guint unit_time_clock =
428         (rtpdtmfdepay->unit_time * depayload->clock_rate) / 1000;
429     if (dtmf_payload.duration % unit_time_clock) {
430       /* Make sure we don't overflow the duration */
431       if (dtmf_payload.duration < G_MAXUINT16 - unit_time_clock)
432         dtmf_payload.duration += unit_time_clock -
433             (dtmf_payload.duration % unit_time_clock);
434       else
435         dtmf_payload.duration -= dtmf_payload.duration % unit_time_clock;
436     }
437   }
438
439   /* clip to max duration */
440   if (rtpdtmfdepay->max_duration) {
441     guint max_duration_clock =
442         (rtpdtmfdepay->max_duration * depayload->clock_rate) / 1000;
443
444     if (max_duration_clock < G_MAXUINT16 &&
445         dtmf_payload.duration > max_duration_clock)
446       dtmf_payload.duration = max_duration_clock;
447   }
448
449   GST_DEBUG_OBJECT (depayload, "Received new RTP DTMF packet : "
450       "marker=%d - timestamp=%u - event=%d - duration=%d",
451       marker, timestamp, dtmf_payload.event, dtmf_payload.duration);
452
453   GST_DEBUG_OBJECT (depayload,
454       "Previous information : timestamp=%u - duration=%d",
455       rtpdtmfdepay->previous_ts, rtpdtmfdepay->previous_duration);
456
457   /* First packet */
458   if (marker || rtpdtmfdepay->previous_ts != timestamp) {
459     rtpdtmfdepay->sample = 0;
460     rtpdtmfdepay->previous_ts = timestamp;
461     rtpdtmfdepay->previous_duration = dtmf_payload.duration;
462     rtpdtmfdepay->first_gst_ts = GST_BUFFER_PTS (buf);
463
464     structure = gst_structure_new ("dtmf-event",
465         "number", G_TYPE_INT, dtmf_payload.event,
466         "volume", G_TYPE_INT, dtmf_payload.volume,
467         "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1, NULL);
468     if (structure) {
469       dtmf_message =
470           gst_message_new_element (GST_OBJECT (depayload), structure);
471       if (dtmf_message) {
472         if (!gst_element_post_message (GST_ELEMENT (depayload), dtmf_message)) {
473           GST_ERROR_OBJECT (depayload,
474               "Unable to send dtmf-event message to bus");
475         }
476       } else {
477         GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event message");
478       }
479     } else {
480       GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event structure");
481     }
482   } else {
483     guint16 duration = dtmf_payload.duration;
484     dtmf_payload.duration -= rtpdtmfdepay->previous_duration;
485     /* If late buffer, ignore */
486     if (duration > rtpdtmfdepay->previous_duration)
487       rtpdtmfdepay->previous_duration = duration;
488   }
489
490   GST_DEBUG_OBJECT (depayload, "new previous duration : %d - new duration : %d"
491       " - diff  : %d - clock rate : %d - timestamp : %" G_GUINT64_FORMAT,
492       rtpdtmfdepay->previous_duration, dtmf_payload.duration,
493       (rtpdtmfdepay->previous_duration - dtmf_payload.duration),
494       depayload->clock_rate, GST_BUFFER_TIMESTAMP (buf));
495
496   /* If late or duplicate packet (like the redundant end packet). Ignore */
497   if (dtmf_payload.duration > 0) {
498     outbuf = gst_dtmf_src_generate_tone (rtpdtmfdepay, dtmf_payload);
499
500
501     GST_BUFFER_PTS (outbuf) = rtpdtmfdepay->first_gst_ts +
502         (rtpdtmfdepay->previous_duration - dtmf_payload.duration) *
503         GST_SECOND / depayload->clock_rate;
504     GST_BUFFER_OFFSET (outbuf) =
505         (rtpdtmfdepay->previous_duration - dtmf_payload.duration) *
506         GST_SECOND / depayload->clock_rate;
507     GST_BUFFER_OFFSET_END (outbuf) = rtpdtmfdepay->previous_duration *
508         GST_SECOND / depayload->clock_rate;
509
510     GST_DEBUG_OBJECT (depayload,
511         "timestamp : %" G_GUINT64_FORMAT " - time %" GST_TIME_FORMAT,
512         GST_BUFFER_TIMESTAMP (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
513
514   }
515
516   gst_rtp_buffer_unmap (&rtpbuffer);
517
518   return outbuf;
519
520 bad_packet:
521   GST_ELEMENT_WARNING (rtpdtmfdepay, STREAM, DECODE,
522       ("Packet did not validate"), (NULL));
523
524   if (rtpbuffer.buffer != NULL)
525     gst_rtp_buffer_unmap (&rtpbuffer);
526
527   return NULL;
528 }
529
530 gboolean
531 gst_rtp_dtmf_depay_plugin_init (GstPlugin * plugin)
532 {
533   return gst_element_register (plugin, "rtpdtmfdepay",
534       GST_RANK_MARGINAL, GST_TYPE_RTP_DTMF_DEPAY);
535 }