ff3f05b4f662a833073548bd66cba4d308d36331
[platform/upstream/gstreamer.git] / gst / dtmf / gstrtpdtmfsrc.c
1 /* GStreamer RTP DTMF source
2  *
3  * gstrtpdtmfsrc.c:
4  *
5  * Copyright (C) <2007> Nokia Corporation.
6  *   Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
7  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
8  *               2000,2005 Wim Taymans <wim@fluendo.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 /**
27  * SECTION:element-rtpdtmfsrc
28  * @short_description: Generates RTP DTMF packets
29  *
30  * <refsect2>
31  *
32  * <para>
33  * The RTPDTMFSrc element generates RTP DTMF (RFC 2833) event packets on request
34  * from application. The application communicates the beginning and end of a
35  * DTMF event using custom upstream gstreamer events. To report a DTMF event, an
36  * application must send an event of type GST_EVENT_CUSTOM_UPSTREAM, having a
37  * structure of name "dtmf-event" with fields set according to the following
38  * table:
39  * </para>
40  *
41  * <para>
42  * <informaltable>
43  * <tgroup cols='4'>
44  * <colspec colname='Name' />
45  * <colspec colname='Type' />
46  * <colspec colname='Possible values' />
47  * <colspec colname='Purpose' />
48  *
49  * <thead>
50  * <row>
51  * <entry>Name</entry>
52  * <entry>GType</entry>
53  * <entry>Possible values</entry>
54  * <entry>Purpose</entry>
55  * </row>
56  * </thead>
57  *
58  * <tbody>
59  * <row>
60  * <entry>type</entry>
61  * <entry>G_TYPE_INT</entry>
62  * <entry>0-1</entry>
63  * <entry>The application uses this field to specify which of the two methods
64  * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
65  * named events. This element is only capable of generating named events.
66  * </entry>
67  * </row>
68  * <row>
69  * <entry>number</entry>
70  * <entry>G_TYPE_INT</entry>
71  * <entry>0-16</entry>
72  * <entry>The event number.</entry>
73  * </row>
74  * <row>
75  * <entry>volume</entry>
76  * <entry>G_TYPE_INT</entry>
77  * <entry>0-36</entry>
78  * <entry>This field describes the power level of the tone, expressed in dBm0
79  * after dropping the sign. Power levels range from 0 to -63 dBm0. The range of
80  * valid DTMF is from 0 to -36 dBm0. Can be omitted if start is set to FALSE.
81  * </entry>
82  * </row>
83  * <row>
84  * <entry>start</entry>
85  * <entry>G_TYPE_BOOLEAN</entry>
86  * <entry>True or False</entry>
87  * <entry>Whether the event is starting or ending.</entry>
88  * </row>
89  * <row>
90  * <entry>method</entry>
91  * <entry>G_TYPE_INT</entry>
92  * <entry>1</entry>
93  * <entry>The method used for sending event, this element will react if this
94  * field is absent or 1.
95  * </entry>
96  * </row>
97  * </tbody>
98  * </tgroup>
99  * </informaltable>
100  * </para>
101  *
102  * <para>For example, the following code informs the pipeline (and in turn, the
103  * RTPDTMFSrc element inside the pipeline) about the start of an RTP DTMF named
104  * event '1' of volume -25 dBm0:
105  * </para>
106  *
107  * <para>
108  * <programlisting>
109  * structure = gst_structure_new ("dtmf-event",
110  *                    "type", G_TYPE_INT, 1,
111  *                    "number", G_TYPE_INT, 1,
112  *                    "volume", G_TYPE_INT, 25,
113  *                    "start", G_TYPE_BOOLEAN, TRUE, NULL);
114  *
115  * event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
116  * gst_element_send_event (pipeline, event);
117  * </programlisting>
118  * </para>
119  *
120  * </refsect2>
121  */
122
123 #ifdef HAVE_CONFIG_H
124 #  include "config.h"
125 #endif
126
127 #include <stdlib.h>
128 #include <string.h>
129
130 #include <glib.h>
131
132 #include "gstrtpdtmfsrc.h"
133
134 #define GST_RTP_DTMF_TYPE_EVENT  1
135 #define DEFAULT_PACKET_INTERVAL  50 /* ms */
136 #define MIN_PACKET_INTERVAL      10 /* ms */
137 #define MAX_PACKET_INTERVAL      50 /* ms */
138 #define DEFAULT_SSRC             -1
139 #define DEFAULT_PT               96
140 #define DEFAULT_TIMESTAMP_OFFSET -1
141 #define DEFAULT_SEQNUM_OFFSET    -1
142 #define DEFAULT_CLOCK_RATE       8000
143 #define MIN_EVENT                0
144 #define MAX_EVENT                16
145 #define MIN_EVENT_STRING         "0"
146 #define MAX_EVENT_STRING         "16"
147 #define MIN_VOLUME               0
148 #define MAX_VOLUME               36
149 #define MIN_EVENT_DURATION       50
150
151 #define MIN_INTER_DIGIT_INTERVAL 50
152 #define MIN_PULSE_DURATION       70
153 #define MIN_DUTY_CYCLE           (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION)
154
155 #define DEFAULT_PACKET_REDUNDANCY 1
156 #define MIN_PACKET_REDUNDANCY 1
157 #define MAX_PACKET_REDUNDANCY 5
158
159 /* elementfactory information */
160 static const GstElementDetails gst_rtp_dtmf_src_details =
161 GST_ELEMENT_DETAILS ("RTP DTMF packet generator",
162     "Source/Network",
163     "Generates RTP DTMF packets",
164     "Zeeshan Ali <zeeshan.ali@nokia.com>");
165
166 GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_src_debug);
167 #define GST_CAT_DEFAULT gst_rtp_dtmf_src_debug
168
169 /* signals and args */
170 enum
171 {
172   /* FILL ME */
173   LAST_SIGNAL
174 };
175
176 enum
177 {
178   PROP_0,
179   PROP_SSRC,
180   PROP_TIMESTAMP_OFFSET,
181   PROP_SEQNUM_OFFSET,
182   PROP_PT,
183   PROP_CLOCK_RATE,
184   PROP_TIMESTAMP,
185   PROP_SEQNUM,
186   PROP_INTERVAL,
187   PROP_REDUNDANCY
188 };
189
190 static GstStaticPadTemplate gst_rtp_dtmf_src_template =
191 GST_STATIC_PAD_TEMPLATE ("src",
192     GST_PAD_SRC,
193     GST_PAD_ALWAYS,
194     GST_STATIC_CAPS ("application/x-rtp, "
195         "media = (string) \"audio\", "
196         "payload = (int) [ 96, 127 ], "
197         "clock-rate = (int) [ 0, MAX ], "
198         "ssrc = (int) [ 0, MAX ], "
199         "events = (int) [ " MIN_EVENT_STRING ", " MAX_EVENT_STRING " ], "
200         "encoding-name = (string) \"telephone-event\"")
201     );
202
203 static GstElementClass *parent_class = NULL;
204
205 static void gst_rtp_dtmf_src_base_init (gpointer g_class);
206 static void gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass);
207 static void gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class);
208 static void gst_rtp_dtmf_src_finalize (GObject * object);
209
210 GType
211 gst_rtp_dtmf_src_get_type (void)
212 {
213   static GType base_src_type = 0;
214
215   if (G_UNLIKELY (base_src_type == 0)) {
216     static const GTypeInfo base_src_info = {
217       sizeof (GstRTPDTMFSrcClass),
218       (GBaseInitFunc) gst_rtp_dtmf_src_base_init,
219       NULL,
220       (GClassInitFunc) gst_rtp_dtmf_src_class_init,
221       NULL,
222       NULL,
223       sizeof (GstRTPDTMFSrc),
224       0,
225       (GInstanceInitFunc) gst_rtp_dtmf_src_init,
226     };
227
228     base_src_type = g_type_register_static (GST_TYPE_ELEMENT,
229         "GstRTPDTMFSrc", &base_src_info, 0);
230   }
231   return base_src_type;
232 }
233
234 static void gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id,
235     const GValue * value, GParamSpec * pspec);
236 static void gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id,
237     GValue * value, GParamSpec * pspec);
238 static gboolean gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event);
239 static GstStateChangeReturn gst_rtp_dtmf_src_change_state (GstElement * element,
240     GstStateChange transition);
241 static void gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc);
242 static void gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc);
243 static void gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc);
244 static void gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc,
245     gint event_number, gint event_volume);
246 static void gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc);
247 static void gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc);
248
249
250 static void
251 gst_rtp_dtmf_src_base_init (gpointer g_class)
252 {
253   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
254
255   GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug,
256           "rtpdtmfsrc", 0, "rtpdtmfsrc element");
257
258   gst_element_class_add_pad_template (element_class,
259       gst_static_pad_template_get (&gst_rtp_dtmf_src_template));
260
261   gst_element_class_set_details (element_class, &gst_rtp_dtmf_src_details);
262 }
263
264 static void
265 gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass)
266 {
267   GObjectClass *gobject_class;
268   GstElementClass *gstelement_class;
269
270   gobject_class = G_OBJECT_CLASS (klass);
271   gstelement_class = GST_ELEMENT_CLASS (klass);
272
273   parent_class = g_type_class_peek_parent (klass);
274
275   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_finalize);
276   gobject_class->set_property =
277       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_set_property);
278   gobject_class->get_property =
279       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_get_property);
280
281   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
282       g_param_spec_uint ("timestamp", "Timestamp",
283           "The RTP timestamp of the last processed packet",
284           0, G_MAXUINT, 0, G_PARAM_READABLE));
285   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
286       g_param_spec_uint ("seqnum", "Sequence number",
287           "The RTP sequence number of the last processed packet",
288           0, G_MAXUINT, 0, G_PARAM_READABLE));
289   g_object_class_install_property (G_OBJECT_CLASS (klass),
290       PROP_TIMESTAMP_OFFSET, g_param_spec_int ("timestamp-offset",
291           "Timestamp Offset",
292           "Offset to add to all outgoing timestamps (-1 = random)", -1,
293           G_MAXINT, DEFAULT_TIMESTAMP_OFFSET, G_PARAM_READWRITE));
294   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
295       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
296           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXINT,
297           DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE));
298   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CLOCK_RATE,
299       g_param_spec_uint ("clock-rate", "clockrate",
300           "The clock-rate at which to generate the dtmf packets",
301           0, G_MAXUINT, DEFAULT_CLOCK_RATE, G_PARAM_READWRITE));
302   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
303       g_param_spec_uint ("ssrc", "SSRC",
304           "The SSRC of the packets (-1 == random)",
305           0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE));
306   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
307       g_param_spec_uint ("pt", "payload type",
308           "The payload type of the packets",
309           0, 0x80, DEFAULT_PT, G_PARAM_READWRITE));
310   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL,
311       g_param_spec_int ("interval", "Interval between rtp packets",
312           "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL,
313           MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, G_PARAM_READWRITE));
314   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY,
315       g_param_spec_int ("packet-redundancy", "Packet Redundancy",
316           "Number of packets to send to indicate start and stop dtmf events",
317           MIN_PACKET_REDUNDANCY, MAX_PACKET_REDUNDANCY,
318           DEFAULT_PACKET_REDUNDANCY, G_PARAM_READWRITE));
319
320   gstelement_class->change_state =
321       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_change_state);
322 }
323
324 static void
325 gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class)
326 {
327   dtmfsrc->srcpad =
328       gst_pad_new_from_static_template (&gst_rtp_dtmf_src_template, "src");
329   GST_DEBUG_OBJECT (dtmfsrc, "adding src pad");
330   gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad);
331
332   gst_pad_set_event_function (dtmfsrc->srcpad, gst_rtp_dtmf_src_handle_event);
333
334   dtmfsrc->ssrc = DEFAULT_SSRC;
335   dtmfsrc->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
336   dtmfsrc->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
337   dtmfsrc->pt = DEFAULT_PT;
338   dtmfsrc->clock_rate = DEFAULT_CLOCK_RATE;
339   dtmfsrc->interval = DEFAULT_PACKET_INTERVAL;
340   dtmfsrc->packet_redundancy = DEFAULT_PACKET_REDUNDANCY;
341
342
343   dtmfsrc->event_queue = g_async_queue_new ();
344   dtmfsrc->last_event = NULL;
345   dtmfsrc->clock_id = NULL;
346
347   GST_DEBUG_OBJECT (dtmfsrc, "init done");
348 }
349
350 static void
351 gst_rtp_dtmf_src_finalize (GObject * object)
352 {
353   GstRTPDTMFSrc *dtmfsrc;
354
355   dtmfsrc = GST_RTP_DTMF_SRC (object);
356
357   if (dtmfsrc->event_queue) {
358     g_async_queue_unref (dtmfsrc->event_queue);
359     dtmfsrc->event_queue = NULL;
360   }
361
362
363   G_OBJECT_CLASS (parent_class)->finalize (object);
364 }
365
366 static gboolean
367 gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc *dtmfsrc,
368         const GstStructure * event_structure)
369 {
370   gint event_type;
371   gboolean start;
372   gint method;
373
374   if (!gst_structure_get_int (event_structure, "type", &event_type) ||
375           !gst_structure_get_boolean (event_structure, "start", &start) ||
376           event_type != GST_RTP_DTMF_TYPE_EVENT)
377     goto failure;
378
379   if (gst_structure_get_int (event_structure, "method", &method)) {
380     if (method != 1) {
381       goto failure;
382     }
383   }
384
385   if (start) {
386     gint event_number;
387     gint event_volume;
388
389     if (!gst_structure_get_int (event_structure, "number", &event_number) ||
390             !gst_structure_get_int (event_structure, "volume", &event_volume))
391       goto failure;
392
393     GST_DEBUG_OBJECT (dtmfsrc, "Received start event %d with volume %d",
394             event_number, event_volume);
395     gst_rtp_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume);
396   }
397
398   else {
399     GST_DEBUG_OBJECT (dtmfsrc, "Received stop event");
400     gst_rtp_dtmf_src_add_stop_event (dtmfsrc);
401   }
402
403   return TRUE;
404 failure:
405   return FALSE;
406 }
407
408 static gboolean
409 gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc,
410     GstEvent * event)
411 {
412   gboolean result = FALSE;
413   gchar *struct_str;
414   const GstStructure *structure;
415
416   GstState state;
417   GstStateChangeReturn ret;
418
419   ret = gst_element_get_state (GST_ELEMENT (dtmfsrc), &state, NULL, 0);
420   if (ret != GST_STATE_CHANGE_SUCCESS || state != GST_STATE_PLAYING) {
421     GST_DEBUG_OBJECT (dtmfsrc, "Received event while not in PLAYING state");
422     goto ret;
423   }
424
425   GST_DEBUG_OBJECT (dtmfsrc, "Received event is of our interest");
426   structure = gst_event_get_structure (event);
427   struct_str = gst_structure_to_string (structure);
428   GST_DEBUG_OBJECT (dtmfsrc, "Event has structure %s", struct_str);
429   g_free (struct_str);
430   if (structure && gst_structure_has_name (structure, "dtmf-event"))
431     result = gst_rtp_dtmf_src_handle_dtmf_event (dtmfsrc, structure);
432
433 ret:
434   return result;
435 }
436
437 static gboolean
438 gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event)
439 {
440   GstRTPDTMFSrc *dtmfsrc;
441   gboolean result = FALSE;
442   GstElement *parent = gst_pad_get_parent_element (pad);
443   dtmfsrc = GST_RTP_DTMF_SRC (parent);
444
445
446   GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad");
447   switch (GST_EVENT_TYPE (event)) {
448     case GST_EVENT_CUSTOM_UPSTREAM:
449     {
450       result = gst_rtp_dtmf_src_handle_custom_upstream (dtmfsrc, event);
451       break;
452     }
453     /* Ideally this element should not be flushed but let's handle the event
454      * just in case it is */
455     case GST_EVENT_FLUSH_START:
456       gst_rtp_dtmf_src_stop (dtmfsrc);
457       result = TRUE;
458       break;
459     case GST_EVENT_FLUSH_STOP:
460       gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED);
461       break;
462     default:
463       result = gst_pad_event_default (pad, event);
464       break;
465   }
466
467   gst_object_unref (parent);
468   gst_event_unref (event);
469   return result;
470 }
471
472 static void
473 gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id,
474     const GValue * value, GParamSpec * pspec)
475 {
476   GstRTPDTMFSrc *dtmfsrc;
477
478   dtmfsrc = GST_RTP_DTMF_SRC (object);
479
480   switch (prop_id) {
481     case PROP_TIMESTAMP_OFFSET:
482       dtmfsrc->ts_offset = g_value_get_int (value);
483       break;
484     case PROP_SEQNUM_OFFSET:
485       dtmfsrc->seqnum_offset = g_value_get_int (value);
486       break;
487     case PROP_CLOCK_RATE:
488       dtmfsrc->clock_rate = g_value_get_uint (value);
489       gst_rtp_dtmf_src_set_caps (dtmfsrc);
490       break;
491     case PROP_SSRC:
492       dtmfsrc->ssrc = g_value_get_uint (value);
493       break;
494     case PROP_PT:
495       dtmfsrc->pt = g_value_get_uint (value);
496       gst_rtp_dtmf_src_set_caps (dtmfsrc);
497       break;
498     case PROP_INTERVAL:
499       dtmfsrc->interval = g_value_get_int (value);
500       break;
501     case PROP_REDUNDANCY:
502       dtmfsrc->packet_redundancy = g_value_get_int (value);
503       break;
504     default:
505       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
506       break;
507   }
508 }
509
510 static void
511 gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value,
512     GParamSpec * pspec)
513 {
514   GstRTPDTMFSrc *dtmfsrc;
515
516   dtmfsrc = GST_RTP_DTMF_SRC (object);
517
518   switch (prop_id) {
519     case PROP_TIMESTAMP_OFFSET:
520       g_value_set_int (value, dtmfsrc->ts_offset);
521       break;
522     case PROP_SEQNUM_OFFSET:
523       g_value_set_int (value, dtmfsrc->seqnum_offset);
524       break;
525     case PROP_CLOCK_RATE:
526       g_value_set_uint (value, dtmfsrc->clock_rate);
527       break;
528     case PROP_SSRC:
529       g_value_set_uint (value, dtmfsrc->ssrc);
530       break;
531     case PROP_PT:
532       g_value_set_uint (value, dtmfsrc->pt);
533       break;
534     case PROP_TIMESTAMP:
535       g_value_set_uint (value, dtmfsrc->rtp_timestamp);
536       break;
537     case PROP_SEQNUM:
538       g_value_set_uint (value, dtmfsrc->seqnum);
539       break;
540     case PROP_INTERVAL:
541       g_value_set_uint (value, dtmfsrc->interval);
542       break;
543     case PROP_REDUNDANCY:
544       g_value_set_uint (value, dtmfsrc->packet_redundancy);
545       break;
546     default:
547       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
548       break;
549   }
550 }
551
552 static void
553 gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc *dtmfsrc, gboolean lock)
554 {
555    GstEvent *event;
556    GstStructure *structure;
557
558    structure = gst_structure_new ("stream-lock",
559                       "lock", G_TYPE_BOOLEAN, lock, NULL);
560
561    event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure);
562    if (!gst_pad_push_event (dtmfsrc->srcpad, event)) {
563      GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled");
564    }
565
566 }
567
568 static void
569 gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc)
570 {
571   GstClock *clock;
572
573   clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
574   if (clock != NULL) {
575     dtmfsrc->timestamp = gst_clock_get_time (clock)
576         + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND);
577     gst_object_unref (clock);
578   } else {
579     gchar *dtmf_name = gst_element_get_name (dtmfsrc);
580     GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
581     dtmfsrc->timestamp = GST_CLOCK_TIME_NONE;
582     g_free (dtmf_name);
583   }
584
585   dtmfsrc->rtp_timestamp = dtmfsrc->ts_base +
586       gst_util_uint64_scale_int (
587           gst_segment_to_running_time (&dtmfsrc->segment, GST_FORMAT_TIME,
588               dtmfsrc->timestamp),
589           dtmfsrc->clock_rate, GST_SECOND);
590 }
591
592 static void
593 gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc)
594 {
595   gst_rtp_dtmf_src_set_caps (dtmfsrc);
596
597   if (!gst_pad_start_task (dtmfsrc->srcpad,
598       (GstTaskFunction) gst_rtp_dtmf_src_push_next_rtp_packet, dtmfsrc)) {
599     GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad");
600   }
601 }
602
603 static void
604 gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc)
605 {
606
607   GstRTPDTMFSrcEvent *event = NULL;
608
609   if (dtmfsrc->clock_id != NULL) {
610     gst_clock_id_unschedule(dtmfsrc->clock_id);
611     gst_clock_id_unref (dtmfsrc->clock_id);
612     dtmfsrc->clock_id = NULL;
613   }
614
615   g_async_queue_lock (dtmfsrc->event_queue);
616   event = g_malloc (sizeof(GstRTPDTMFSrcEvent));
617   event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK;
618   g_async_queue_push_unlocked (dtmfsrc->event_queue, event);
619   g_async_queue_unlock (dtmfsrc->event_queue);
620
621   event = NULL;
622
623   if (!gst_pad_pause_task (dtmfsrc->srcpad)) {
624     GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad");
625     return;
626   }
627
628
629   if (dtmfsrc->last_event) {
630     /* Don't forget to release the stream lock */
631     gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE);
632     g_free (dtmfsrc->last_event);
633     dtmfsrc->last_event = NULL;
634   }
635
636   /* Flushing the event queue */
637   event = g_async_queue_try_pop (dtmfsrc->event_queue);
638
639   while (event != NULL) {
640     g_free (event);
641     event = g_async_queue_try_pop (dtmfsrc->event_queue);
642   }
643
644
645 }
646
647
648
649 static void
650 gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number,
651     gint event_volume)
652 {
653
654   GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent));
655   event->event_type = RTP_DTMF_EVENT_TYPE_START;
656
657   event->payload = g_new0 (GstRTPDTMFPayload, 1);
658   event->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT);
659   event->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME);
660
661   g_async_queue_push (dtmfsrc->event_queue, event);
662 }
663
664 static void
665 gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc)
666 {
667
668   GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent));
669   event->event_type = RTP_DTMF_EVENT_TYPE_STOP;
670   event->payload = g_new0 (GstRTPDTMFPayload, 1);
671   event->payload->event = 0;
672   event->payload->volume = 0;
673
674   g_async_queue_push (dtmfsrc->event_queue, event);
675 }
676
677
678 static void
679 gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf)
680 {
681   GstClock *clock;
682
683   clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
684   if (clock != NULL) {
685     GstClockReturn clock_ret;
686
687     dtmfsrc->clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf));
688     gst_object_unref (clock);
689
690     clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL);
691     if (clock_ret == GST_CLOCK_UNSCHEDULED) {
692       GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled");
693       /* we don't free anything in case of an unscheduled, because it would be unscheduled
694        * by the stop function which will do the free itself. We can't handle it here
695        * in case we stop the task before the unref is done
696        */
697     } else {
698       if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) {
699         gchar *clock_name = NULL;
700
701         clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
702         clock_name = gst_element_get_name (clock);
703         gst_object_unref (clock);
704
705         GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name);
706         g_free (clock_name);
707       }
708       gst_clock_id_unref (dtmfsrc->clock_id);
709     }
710   }
711
712   else {
713     gchar *dtmf_name = gst_element_get_name (dtmfsrc);
714     GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
715     g_free (dtmf_name);
716   }
717 }
718
719 static void
720 gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc,
721     GstRTPDTMFSrcEvent *event, GstBuffer *buf)
722 {
723   gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc);
724   gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt);
725   if (dtmfsrc->first_packet) {
726     gst_rtp_buffer_set_marker (buf, TRUE);
727     dtmfsrc->first_packet = FALSE;
728   } else if (dtmfsrc->last_packet) {
729     event->payload->e = 1;
730     dtmfsrc->last_packet = FALSE;
731   }
732
733   dtmfsrc->seqnum++;
734   gst_rtp_buffer_set_seq (buf, dtmfsrc->seqnum);
735
736   /* timestamp of RTP header */
737   gst_rtp_buffer_set_timestamp (buf, dtmfsrc->rtp_timestamp);
738 }
739
740 static void
741 gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc,
742     GstRTPDTMFSrcEvent *event,GstBuffer *buf)
743 {
744   GstRTPDTMFPayload *payload;
745
746   gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc,event,  buf);
747
748   /* duration of DTMF payload */
749   event->payload->duration +=
750       dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
751
752   /* timestamp and duration of GstBuffer */
753   GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND;
754   GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp;
755   dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
756
757   payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf);
758
759   /* copy payload and convert to network-byte order */
760   g_memmove (payload, event->payload, sizeof (GstRTPDTMFPayload));
761   /* Force the packet duration to a certain minumum
762    * if its the end of the event
763    */
764   if (payload->e &&
765       payload->duration < MIN_EVENT_DURATION * dtmfsrc->clock_rate / 1000)
766     payload->duration = MIN_EVENT_DURATION * dtmfsrc->clock_rate / 1000;
767
768   payload->duration = g_htons (payload->duration);
769 }
770
771 static GstBuffer *
772 gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc,
773     GstRTPDTMFSrcEvent *event)
774 {
775   GstBuffer *buf = NULL;
776
777   /* create buffer to hold the payload */
778   buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0);
779
780   gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, event, buf);
781
782   /* FIXME: Should we sync to clock ourselves or leave it to sink */
783   gst_rtp_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf);
784
785   event->sent_packets++;
786
787   /* Set caps on the buffer before pushing it */
788   gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad));
789
790   return buf;
791 }
792
793 static void
794 gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc)
795 {
796   GstBuffer *buf = NULL;
797   GstFlowReturn ret;
798   gint redundancy_count = 1;
799   GstRTPDTMFSrcEvent *event;
800
801   g_async_queue_ref (dtmfsrc->event_queue);
802
803   if (dtmfsrc->last_event == NULL) {
804     event = g_async_queue_pop (dtmfsrc->event_queue);
805
806     if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) {
807       GST_WARNING_OBJECT (dtmfsrc,
808           "Received a DTMF stop event when already stopped");
809     } else if (event->event_type == RTP_DTMF_EVENT_TYPE_START) {
810
811       dtmfsrc->first_packet = TRUE;
812       dtmfsrc->last_packet = FALSE;
813       gst_rtp_dtmf_prepare_timestamps (dtmfsrc);
814
815       /* Don't forget to get exclusive access to the stream */
816       gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE);
817
818       event->sent_packets = 0;
819
820       dtmfsrc->last_event = event;
821     } else if (event->event_type == RTP_DTMF_EVENT_TYPE_PAUSE_TASK) {
822       g_free (event);
823       g_async_queue_unref (dtmfsrc->event_queue);
824       return;
825     }
826   } else if (dtmfsrc->last_event->sent_packets * dtmfsrc->interval >=
827       MIN_PULSE_DURATION){
828     event = g_async_queue_try_pop (dtmfsrc->event_queue);
829
830     if (event != NULL) {
831       if (event->event_type == RTP_DTMF_EVENT_TYPE_START) {
832         GST_WARNING_OBJECT (dtmfsrc,
833             "Received two consecutive DTMF start events");
834       } else if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) {
835         dtmfsrc->first_packet = FALSE;
836         dtmfsrc->last_packet = TRUE;
837       }
838     }
839   }
840   g_async_queue_unref (dtmfsrc->event_queue);
841
842   if (dtmfsrc->last_event) {
843
844     if (dtmfsrc->first_packet == TRUE || dtmfsrc->last_packet == TRUE) {
845       redundancy_count = dtmfsrc->packet_redundancy;
846
847       if(dtmfsrc->first_packet == TRUE) {
848         GST_DEBUG_OBJECT (dtmfsrc,
849             "redundancy count set to %d due to dtmf start",
850             redundancy_count);
851       } else if(dtmfsrc->last_packet == TRUE) {
852         GST_DEBUG_OBJECT (dtmfsrc,
853             "redundancy count set to %d due to dtmf stop",
854             redundancy_count);
855       }
856
857     }
858
859     /* create buffer to hold the payload */
860     buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc,
861         dtmfsrc->last_event);
862
863     while ( redundancy_count-- ) {
864       gst_buffer_ref(buf);
865
866       GST_DEBUG_OBJECT (dtmfsrc,
867           "pushing buffer on src pad of size %d with redundancy count %d",
868           GST_BUFFER_SIZE (buf), redundancy_count);
869       ret = gst_pad_push (dtmfsrc->srcpad, buf);
870       if (ret != GST_FLOW_OK)
871         GST_ERROR_OBJECT (dtmfsrc,
872             "Failed to push buffer on src pad");
873
874       /* Make sure only the first packet sent has the marker set */
875       gst_rtp_buffer_set_marker (buf, FALSE);
876     }
877
878     gst_buffer_unref(buf);
879     GST_DEBUG_OBJECT (dtmfsrc,
880         "pushed DTMF event '%d' on src pad", dtmfsrc->last_event->payload->event);
881
882     if (dtmfsrc->last_event->payload->e) {
883       /* Don't forget to release the stream lock */
884       gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE);
885
886       g_free (dtmfsrc->last_event->payload);
887       dtmfsrc->last_event->payload = NULL;
888
889       g_free (dtmfsrc->last_event);
890       dtmfsrc->last_event = NULL;
891
892     }
893   }
894 }
895
896 static void
897 gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc)
898 {
899   GstCaps *caps;
900
901   caps = gst_caps_new_simple ("application/x-rtp",
902       "media", G_TYPE_STRING, "audio",
903       "payload", G_TYPE_INT, dtmfsrc->pt,
904       "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate,
905       "encoding-name", G_TYPE_STRING, "telephone-event",
906       "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc,
907       "clock-base", G_TYPE_UINT, dtmfsrc->ts_base,
908       "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base, NULL);
909
910   if (!gst_pad_set_caps (dtmfsrc->srcpad, caps))
911     GST_ERROR_OBJECT (dtmfsrc,
912             "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps);
913   else
914     GST_DEBUG_OBJECT (dtmfsrc,
915             "caps %" GST_PTR_FORMAT " set on src pad", caps);
916
917   gst_caps_unref (caps);
918 }
919
920 static void
921 gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc)
922 {
923   gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED);
924
925   if (dtmfsrc->ssrc == -1)
926     dtmfsrc->current_ssrc = g_random_int ();
927   else
928     dtmfsrc->current_ssrc = dtmfsrc->ssrc;
929
930   if (dtmfsrc->seqnum_offset == -1)
931     dtmfsrc->seqnum_base = g_random_int_range (0, G_MAXUINT16);
932   else
933     dtmfsrc->seqnum_base = dtmfsrc->seqnum_offset;
934   dtmfsrc->seqnum = dtmfsrc->seqnum_base;
935
936   if (dtmfsrc->ts_offset == -1)
937     dtmfsrc->ts_base = g_random_int ();
938   else
939     dtmfsrc->ts_base = dtmfsrc->ts_offset;
940 }
941
942 static GstStateChangeReturn
943 gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition)
944 {
945   GstRTPDTMFSrc *dtmfsrc;
946   GstStateChangeReturn result;
947   gboolean no_preroll = FALSE;
948
949   dtmfsrc = GST_RTP_DTMF_SRC (element);
950
951   switch (transition) {
952     case GST_STATE_CHANGE_READY_TO_PAUSED:
953       gst_rtp_dtmf_src_ready_to_paused (dtmfsrc);
954       /* Indicate that we don't do PRE_ROLL */
955       no_preroll = TRUE;
956       break;
957     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
958       gst_rtp_dtmf_src_start (dtmfsrc);
959       break;
960     default:
961       break;
962   }
963
964   if ((result =
965           GST_ELEMENT_CLASS (parent_class)->change_state (element,
966               transition)) == GST_STATE_CHANGE_FAILURE)
967     goto failure;
968
969   switch (transition) {
970     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
971       /* Indicate that we don't do PRE_ROLL */
972       no_preroll = TRUE;
973       gst_rtp_dtmf_src_stop (dtmfsrc);
974       break;
975     default:
976       break;
977   }
978
979   if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
980     result = GST_STATE_CHANGE_NO_PREROLL;
981
982   return result;
983
984   /* ERRORS */
985 failure:
986   {
987     GST_ERROR_OBJECT (dtmfsrc, "parent failed state change");
988     return result;
989   }
990 }
991
992 gboolean
993 gst_rtp_dtmf_src_plugin_init (GstPlugin * plugin)
994 {
995   return gst_element_register (plugin, "rtpdtmfsrc",
996       GST_RANK_NONE, GST_TYPE_RTP_DTMF_SRC);
997 }