108
108
* gst_element_send_event (pipeline, event);
109
109
* </programlisting>
111
* When a DTMF tone actually starts or stop, a "dtmf-event-processed"
112
* element #GstMessage with the same fields as the "dtmf-event"
113
* #GstEvent that was used to request the event. Also, if any event
114
* has not been processed when the element goes from the PAUSED to the
115
* READY state, then a "dtmf-event-dropped" message is posted on the
116
* #GstBus in the order that they were received.
113
119
#ifdef HAVE_CONFIG_H
117
123
#include <stdlib.h>
122
128
#include "gstrtpdtmfsrc.h"
124
130
#define GST_RTP_DTMF_TYPE_EVENT 1
125
#define DEFAULT_PACKET_INTERVAL 50 /* ms */
126
#define MIN_PACKET_INTERVAL 10 /* ms */
127
#define MAX_PACKET_INTERVAL 50 /* ms */
131
#define DEFAULT_PTIME 40 /* ms */
128
132
#define DEFAULT_SSRC -1
129
133
#define DEFAULT_PT 96
130
134
#define DEFAULT_TIMESTAMP_OFFSET -1
131
135
#define DEFAULT_SEQNUM_OFFSET -1
132
136
#define DEFAULT_CLOCK_RATE 8000
135
#define MIN_EVENT_STRING "0"
136
#define MAX_EVENT_STRING "16"
138
#define MAX_VOLUME 36
140
#define MIN_INTER_DIGIT_INTERVAL 50 /* ms */
141
#define MIN_PULSE_DURATION 70 /* ms */
143
138
#define DEFAULT_PACKET_REDUNDANCY 1
144
139
#define MIN_PACKET_REDUNDANCY 1
214
208
GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug,
215
209
"rtpdtmfsrc", 0, "rtpdtmfsrc element");
217
gst_element_class_add_pad_template (element_class,
218
gst_static_pad_template_get (&gst_rtp_dtmf_src_template));
211
gst_element_class_add_static_pad_template (element_class,
212
&gst_rtp_dtmf_src_template);
220
214
gst_element_class_set_details_simple (element_class,
221
215
"RTP DTMF packet generator", "Source/Network",
273
267
g_param_spec_uint ("pt", "payload type",
274
268
"The payload type of the packets",
275
269
0, 0x80, DEFAULT_PT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
276
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL,
277
g_param_spec_uint ("interval", "Interval between rtp packets",
278
"Interval in ms between two rtp packets", MIN_PACKET_INTERVAL,
279
MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL,
280
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
281
270
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY,
282
271
g_param_spec_uint ("packet-redundancy", "Packet Redundancy",
283
272
"Number of packets to send to indicate start and stop dtmf events",
318
307
object->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
319
308
object->pt = DEFAULT_PT;
320
309
object->clock_rate = DEFAULT_CLOCK_RATE;
321
object->interval = DEFAULT_PACKET_INTERVAL;
310
object->ptime = DEFAULT_PTIME;
322
311
object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY;
324
313
object->event_queue =
360
if (!gst_structure_get_int (event_structure, "number", &event_number) ||
361
!gst_structure_get_int (event_structure, "volume", &event_volume))
364
GST_OBJECT_LOCK (dtmfsrc);
365
if (gst_structure_get_clock_time (event_structure, "last-stop", &last_stop))
366
dtmfsrc->last_stop = last_stop;
368
dtmfsrc->last_stop = GST_CLOCK_TIME_NONE;
369
correct_order = (start != dtmfsrc->last_event_was_start);
370
dtmfsrc->last_event_was_start = start;
371
GST_OBJECT_UNLOCK (dtmfsrc);
370
377
if (!gst_structure_get_int (event_structure, "number", &event_number) ||
371
378
!gst_structure_get_int (event_structure, "volume", &event_volume))
515
516
gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc)
518
GstClockTime base_time;
523
base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
526
clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
528
dtmfsrc->timestamp = gst_clock_get_time (clock)
529
+ (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - base_time;
518
GstClockTime last_stop;
520
GST_OBJECT_LOCK (dtmfsrc);
521
last_stop = dtmfsrc->last_stop;
522
GST_OBJECT_UNLOCK (dtmfsrc);
524
if (GST_CLOCK_TIME_IS_VALID (last_stop)) {
525
dtmfsrc->start_timestamp = last_stop;
527
GstClock *clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
532
dtmfsrc->start_timestamp = gst_clock_get_time (clock)
533
- gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
534
gst_object_unref (clock);
537
/* If the last stop was in the past, then lets add the buffers together */
538
if (dtmfsrc->start_timestamp < dtmfsrc->timestamp)
530
539
dtmfsrc->start_timestamp = dtmfsrc->timestamp;
531
gst_object_unref (clock);
533
gchar *dtmf_name = gst_element_get_name (dtmfsrc);
534
GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
535
dtmfsrc->timestamp = GST_CLOCK_TIME_NONE;
541
dtmfsrc->timestamp = dtmfsrc->start_timestamp;
539
543
dtmfsrc->rtp_timestamp = dtmfsrc->ts_base +
540
544
gst_util_uint64_scale_int (gst_segment_to_running_time (&GST_BASE_SRC
541
545
(dtmfsrc)->segment, GST_FORMAT_TIME, dtmfsrc->timestamp),
542
546
dtmfsrc->clock_rate, GST_SECOND);
554
560
event->payload = g_slice_new0 (GstRTPDTMFPayload);
555
561
event->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT);
556
562
event->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME);
557
event->payload->duration = dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
563
event->payload->duration = dtmfsrc->ptime * dtmfsrc->clock_rate / 1000;
559
565
g_async_queue_push (dtmfsrc->event_queue, event);
601
607
if (dtmfsrc->redundancy_count > 1)
602
608
GST_BUFFER_DURATION (buf) = 0;
604
GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND;
610
GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND;
605
611
GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp;
607
dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
609
614
payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf);
611
616
/* copy payload and convert to network-byte order */
612
617
g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload));
613
/* Force the packet duration to a certain minumum
614
* if its the end of the event
617
payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000)
618
payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000;
620
619
payload->duration = g_htons (payload->duration);
621
if (dtmfsrc->redundancy_count <= 1 && dtmfsrc->last_packet) {
622
GstClockTime inter_digit_interval = MIN_INTER_DIGIT_INTERVAL;
624
if (inter_digit_interval % dtmfsrc->ptime != 0)
625
inter_digit_interval += dtmfsrc->ptime -
626
(MIN_INTER_DIGIT_INTERVAL % dtmfsrc->ptime);
628
GST_BUFFER_DURATION (buf) += inter_digit_interval * GST_MSECOND;
631
GST_LOG_OBJECT (dtmfsrc, "Creating new buffer with event %u duration "
632
" gst: %" GST_TIME_FORMAT " at %" GST_TIME_FORMAT "(rtp ts:%u dur:%u)",
633
dtmfsrc->payload->event, GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
634
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), dtmfsrc->rtp_timestamp,
635
dtmfsrc->payload->duration);
623
637
/* duration of DTMF payloadfor the NEXT packet */
624
638
/* not updated for redundant packets */
625
if (dtmfsrc->redundancy_count == 0)
626
dtmfsrc->payload->duration +=
627
dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
639
if (dtmfsrc->redundancy_count <= 1)
640
dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000;
642
if (GST_CLOCK_TIME_IS_VALID (dtmfsrc->timestamp))
643
dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
665
gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name,
666
GstRTPDTMFSrcEvent * event)
668
GstStructure *s = NULL;
670
switch (event->event_type) {
671
case RTP_DTMF_EVENT_TYPE_START:
672
s = gst_structure_new (message_name,
673
"type", G_TYPE_INT, 1,
674
"method", G_TYPE_INT, 1,
675
"start", G_TYPE_BOOLEAN, TRUE,
676
"number", G_TYPE_INT, event->payload->event,
677
"volume", G_TYPE_INT, event->payload->volume, NULL);
679
case RTP_DTMF_EVENT_TYPE_STOP:
680
s = gst_structure_new (message_name,
681
"type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1,
682
"start", G_TYPE_BOOLEAN, FALSE, NULL);
684
case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
689
gst_element_post_message (GST_ELEMENT (dtmfsrc),
690
gst_message_new_element (GST_OBJECT (dtmfsrc), s));
647
694
static GstFlowReturn
648
695
gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset,
649
696
guint length, GstBuffer ** buffer)
668
715
case RTP_DTMF_EVENT_TYPE_STOP:
669
716
GST_WARNING_OBJECT (dtmfsrc,
670
717
"Received a DTMF stop event when already stopped");
718
gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
673
721
case RTP_DTMF_EVENT_TYPE_START:
675
723
dtmfsrc->last_packet = FALSE;
676
724
/* Set the redundancy on the first packet */
677
725
dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
678
gst_rtp_dtmf_prepare_timestamps (dtmfsrc);
726
if (!gst_rtp_dtmf_prepare_timestamps (dtmfsrc))
729
gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event);
680
730
dtmfsrc->payload = event->payload;
681
731
event->payload = NULL;
710
760
case RTP_DTMF_EVENT_TYPE_START:
711
761
GST_WARNING_OBJECT (dtmfsrc,
712
762
"Received two consecutive DTMF start events");
763
gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
715
766
case RTP_DTMF_EVENT_TYPE_STOP:
717
768
dtmfsrc->last_packet = TRUE;
718
769
/* Set the redundancy on the last packet */
719
770
dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
771
gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event);
722
774
case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
742
794
GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock");
744
796
clock = gst_element_get_clock (GST_ELEMENT (basesrc));
747
clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp);
749
799
clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp +
750
800
gst_element_get_base_time (GST_ELEMENT (dtmfsrc)));
752
801
gst_object_unref (clock);
754
803
GST_OBJECT_LOCK (dtmfsrc);
814
863
return GST_FLOW_WRONG_STATE;
867
GST_ELEMENT_ERROR (dtmfsrc, STREAM, MUX, ("No available clock"),
868
("No available clock"));
869
gst_pad_pause_task (GST_BASE_SRC_PAD (dtmfsrc));
870
return GST_FLOW_ERROR;
933
988
GST_LOG_OBJECT (dtmfsrc, "using internal seqnum-base %u",
934
989
dtmfsrc->seqnum_base);
992
if (gst_structure_has_field_typed (s, "ptime", G_TYPE_UINT)) {
993
value = gst_structure_get_value (s, "ptime");
994
dtmfsrc->ptime = g_value_get_uint (value);
995
GST_LOG_OBJECT (dtmfsrc, "using peer ptime %u", dtmfsrc->ptime);
996
} else if (gst_structure_has_field_typed (s, "maxptime", G_TYPE_UINT)) {
997
value = gst_structure_get_value (s, "maxptime");
998
dtmfsrc->ptime = g_value_get_uint (value);
999
GST_LOG_OBJECT (dtmfsrc, "using peer maxptime as ptime %u",
1002
/* FIXME, fixate_nearest_uint would be even better */
1003
gst_structure_set (s, "ptime", G_TYPE_UINT, dtmfsrc->ptime, NULL);
1004
GST_LOG_OBJECT (dtmfsrc, "using internal ptime %u", dtmfsrc->ptime);
936
1008
GST_DEBUG_OBJECT (dtmfsrc, "with peer caps: %" GST_PTR_FORMAT, srccaps);
982
1055
gst_rtp_dtmf_src_ready_to_paused (dtmfsrc);
984
1057
/* Flushing the event queue */
985
while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL)
1058
while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) {
1059
gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
986
1060
gst_rtp_dtmf_src_event_free (event);
1062
dtmfsrc->last_event_was_start = FALSE;
988
1064
no_preroll = TRUE;
1003
1079
case GST_STATE_CHANGE_PAUSED_TO_READY:
1005
1081
/* Flushing the event queue */
1006
while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL)
1082
while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) {
1083
gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
1007
1084
gst_rtp_dtmf_src_event_free (event);
1086
dtmfsrc->last_event_was_start = FALSE;
1009
1088
/* Indicate that we don't do PRE_ROLL */