From 9d1a8605ddd4fe7f6fa17322a057770d84a67de4 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 20 Aug 2007 18:48:00 +0000 Subject: [PATCH 001/138] [MOVED FROM GST-P-FARSIGHT] Moved rtpdtmf to dtmf directory 20070820184800-4f0f6-fa33ea974510161de8c9951c39087af3613b65a4.gz --- gst/dtmf/.git-darcs-dir | 0 gst/dtmf/Makefile.am | 9 + gst/dtmf/gstrtpdtmfsrc.c | 872 +++++++++++++++++++++++++++++++++++++++ gst/dtmf/gstrtpdtmfsrc.h | 101 +++++ 4 files changed, 982 insertions(+) create mode 100644 gst/dtmf/.git-darcs-dir create mode 100644 gst/dtmf/Makefile.am create mode 100644 gst/dtmf/gstrtpdtmfsrc.c create mode 100644 gst/dtmf/gstrtpdtmfsrc.h diff --git a/gst/dtmf/.git-darcs-dir b/gst/dtmf/.git-darcs-dir new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am new file mode 100644 index 0000000000..603b32c28e --- /dev/null +++ b/gst/dtmf/Makefile.am @@ -0,0 +1,9 @@ +plugin_LTLIBRARIES = libgstrtpdtmf.la + +libgstrtpdtmf_la_SOURCES = gstrtpdtmfsrc.c + +libgstrtpdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT +libgstrtpdtmf_la_LIBADD = $(GST_LIBS_LIBS) +libgstrtpdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ + +noinst_HEADERS = gstrtpdtmfsrc.h diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c new file mode 100644 index 0000000000..8e4f31b545 --- /dev/null +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -0,0 +1,872 @@ +/* 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-rtpdtmfsrc + * @short_description: Generates RTP DTMF packets + * + * + * + * + * 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. This element is only capable of generating named events. + * + * + * + * 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. 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); + * + * + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gstrtpdtmfsrc.h" + +#define GST_RTP_DTMF_TYPE_EVENT 1 +#define DEFAULT_PACKET_INTERVAL 50 /* ms */ +#define MIN_PACKET_INTERVAL 10 /* ms */ +#define MAX_PACKET_INTERVAL 50 /* 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 MIN_EVENT 0 +#define MAX_EVENT 16 +#define MIN_EVENT_STRING "0" +#define MAX_EVENT_STRING "16" +#define MIN_VOLUME 0 +#define MAX_VOLUME 36 +#define MIN_EVENT_DURATION 50 + +#define DEFAULT_PACKET_REDUNDANCY 1 +#define MIN_PACKET_REDUNDANCY 1 +#define MAX_PACKET_REDUNDANCY 5 + +/* elementfactory information */ +static const GstElementDetails gst_rtp_dtmf_src_details = +GST_ELEMENT_DETAILS ("RTP DTMF packet generator", + "Source/Network", + "Generates RTP DTMF packets", + "Zeeshan Ali "); + +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_INTERVAL, + 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 ], " + "ssrc = (int) [ 0, MAX ], " + "events = (int) [ " MIN_EVENT_STRING ", " MAX_EVENT_STRING " ], " + "encoding-name = (string) \"telephone-event\"") + ); + +static GstElementClass *parent_class = NULL; + +static void gst_rtp_dtmf_src_base_init (gpointer g_class); +static void gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass); +static void gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class); +static void gst_rtp_dtmf_src_finalize (GObject * object); + +GType +gst_rtp_dtmf_src_get_type (void) +{ + static GType base_src_type = 0; + + if (G_UNLIKELY (base_src_type == 0)) { + static const GTypeInfo base_src_info = { + sizeof (GstRTPDTMFSrcClass), + (GBaseInitFunc) gst_rtp_dtmf_src_base_init, + NULL, + (GClassInitFunc) gst_rtp_dtmf_src_class_init, + NULL, + NULL, + sizeof (GstRTPDTMFSrc), + 0, + (GInstanceInitFunc) gst_rtp_dtmf_src_init, + }; + + base_src_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstRTPDTMFSrc", &base_src_info, 0); + } + return base_src_type; +} + +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 (GstPad * pad, GstEvent * event); +static GstStateChangeReturn gst_rtp_dtmf_src_change_state (GstElement * element, + GstStateChange transition); +static void gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc); +static void gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc, gint event_number, + gint event_volume); +static void gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc); +static void gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc); + +static void +gst_rtp_dtmf_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug, + "dtmfsrc", 0, "dtmfsrc element"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); + + gst_element_class_set_details (element_class, &gst_rtp_dtmf_src_details); +} + +static void +gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + 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_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_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_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_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_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_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_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL, + g_param_spec_int ("interval", "Interval between rtp packets", + "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL, + MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY, + g_param_spec_int ("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)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_change_state); +} + +static void +gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class) +{ + dtmfsrc->srcpad = + gst_pad_new_from_static_template (&gst_rtp_dtmf_src_template, "src"); + GST_DEBUG_OBJECT (dtmfsrc, "adding src pad"); + gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad); + + gst_pad_set_event_function (dtmfsrc->srcpad, gst_rtp_dtmf_src_handle_event); + + dtmfsrc->ssrc = DEFAULT_SSRC; + dtmfsrc->seqnum_offset = DEFAULT_SEQNUM_OFFSET; + dtmfsrc->ts_offset = DEFAULT_TIMESTAMP_OFFSET; + dtmfsrc->pt = DEFAULT_PT; + dtmfsrc->clock_rate = DEFAULT_CLOCK_RATE; + dtmfsrc->payload = NULL; + dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; + dtmfsrc->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; + + GST_DEBUG_OBJECT (dtmfsrc, "init done"); +} + +static void +gst_rtp_dtmf_src_finalize (GObject * object) +{ + GstRTPDTMFSrc *dtmfsrc; + + dtmfsrc = GST_RTP_DTMF_SRC (object); + + G_OBJECT_CLASS (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; + + 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) { + gint event_number; + gint event_volume; + + 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_start (dtmfsrc, event_number, event_volume); + } + + else { + GST_DEBUG_OBJECT (dtmfsrc, "Received stop event"); + gst_rtp_dtmf_src_stop (dtmfsrc); + } + + return TRUE; +failure: + return FALSE; +} + +static gboolean +gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc, + GstEvent * event) +{ + gboolean result = FALSE; + const GstStructure *structure; + + if (GST_STATE (dtmfsrc) != 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); + 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 (GstPad * pad, GstEvent * event) +{ + GstRTPDTMFSrc *dtmfsrc; + gboolean result = FALSE; + + dtmfsrc = GST_RTP_DTMF_SRC (GST_PAD_PARENT (pad)); + + GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_UPSTREAM: + { + result = gst_rtp_dtmf_src_handle_custom_upstream (dtmfsrc, event); + break; + } + /* Ideally this element should not be flushed but let's handle the event + * just in case it is */ + case GST_EVENT_FLUSH_START: + gst_rtp_dtmf_src_stop (dtmfsrc); + result = TRUE; + break; + case GST_EVENT_FLUSH_STOP: + gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate; + GstFormat fmt; + gint64 start, stop, position; + + gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, + &stop, &position); + gst_segment_set_newsegment (&dtmfsrc->segment, update, rate, fmt, + start, stop, position); + } + /* fallthrough */ + default: + result = gst_pad_event_default (pad, event); + break; + } + + gst_event_unref (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); + gst_rtp_dtmf_src_set_caps (dtmfsrc); + break; + case PROP_SSRC: + dtmfsrc->ssrc = g_value_get_uint (value); + break; + case PROP_PT: + dtmfsrc->pt = g_value_get_uint (value); + gst_rtp_dtmf_src_set_caps (dtmfsrc); + break; + case PROP_INTERVAL: + dtmfsrc->interval = g_value_get_int (value); + break; + case PROP_REDUNDANCY: + dtmfsrc->packet_redundancy = g_value_get_int (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_INTERVAL: + g_value_set_uint (value, dtmfsrc->interval); + 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 void +gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc *dtmfsrc, gboolean lock) +{ + GstEvent *event; + GstStructure *structure; + + structure = gst_structure_new ("stream-lock", + "lock", G_TYPE_BOOLEAN, lock, NULL); + + event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); + gst_pad_push_event (dtmfsrc->srcpad, event); +} + +static void +gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) +{ + GstClock *clock; + + clock = GST_ELEMENT_CLOCK (dtmfsrc); + if (clock != NULL) + dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); + + else { + GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", + GST_ELEMENT_NAME (dtmfsrc)); + dtmfsrc->timestamp = GST_CLOCK_TIME_NONE; + } + + dtmfsrc->rtp_timestamp = dtmfsrc->ts_base + + gst_util_uint64_scale_int ( + gst_segment_to_running_time (&dtmfsrc->segment, GST_FORMAT_TIME, + dtmfsrc->timestamp), + dtmfsrc->clock_rate, GST_SECOND); +} + +static void +gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc, + gint event_number, gint event_volume) +{ + g_return_if_fail (dtmfsrc->payload == NULL); + + dtmfsrc->payload = g_new0 (GstRTPDTMFPayload, 1); + dtmfsrc->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT); + dtmfsrc->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME); + dtmfsrc->first_packet = TRUE; + dtmfsrc->last_packet = FALSE; + + gst_rtp_dtmf_prepare_timestamps (dtmfsrc); + gst_rtp_dtmf_src_set_caps (dtmfsrc); + + /* Don't forget to get exclusive access to the stream */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + + if (!gst_pad_start_task (dtmfsrc->srcpad, + (GstTaskFunction) gst_rtp_dtmf_src_push_next_rtp_packet, dtmfsrc)) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); + } +} + +static void +gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) +{ + g_return_if_fail (dtmfsrc->payload != NULL); + + /* Push the last packet with e-bit set */ + /* Next packet sent will be the last */ + dtmfsrc->last_packet = TRUE; + +} + +static void +gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) +{ + GstClock *clock; + + clock = GST_ELEMENT_CLOCK (dtmfsrc); + if (clock != NULL) { + GstClockID clock_id; + GstClockReturn clock_ret; + + clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); + clock_ret = gst_clock_id_wait (clock_id, NULL); + if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", + GST_ELEMENT_NAME (clock)); + } + gst_clock_id_unref (clock_id); + } + + else { + GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", + GST_ELEMENT_NAME (dtmfsrc)); + } +} + +static void +gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) +{ + gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc); + gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt); + if (dtmfsrc->first_packet) { + gst_rtp_buffer_set_marker (buf, TRUE); + dtmfsrc->first_packet = FALSE; + } else if (dtmfsrc->last_packet) { + dtmfsrc->payload->e = 1; + dtmfsrc->last_packet = FALSE; + } + + dtmfsrc->seqnum++; + gst_rtp_buffer_set_seq (buf, dtmfsrc->seqnum); + + /* timestamp of RTP header */ + gst_rtp_buffer_set_timestamp (buf, dtmfsrc->rtp_timestamp); +} + +static void +gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) +{ + GstRTPDTMFPayload *payload; + + gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, buf); + + /* duration of DTMF payload */ + dtmfsrc->payload->duration += + dtmfsrc->interval * dtmfsrc->clock_rate / 1000; + + /* timestamp and duration of GstBuffer */ + GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; + GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; + dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); + + payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf); + + /* copy payload and convert to network-byte order */ + g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload)); + /* Force the packet duration to a certain minumum + * if its the end of the event + */ + if (payload->e && + payload->duration < MIN_EVENT_DURATION * dtmfsrc->clock_rate / 1000) + payload->duration = MIN_EVENT_DURATION * dtmfsrc->clock_rate / 1000; + + payload->duration = g_htons (payload->duration); +} + +static GstBuffer * +gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) +{ + GstBuffer *buf = NULL; + + /* create buffer to hold the payload */ + buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0); + + gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, buf); + + /* FIXME: Should we sync to clock ourselves or leave it to sink */ + gst_rtp_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); + + /* Set caps on the buffer before pushing it */ + gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad)); + + return buf; +} + +static void +gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) +{ + GstBuffer *buf = NULL; + GstFlowReturn ret; + gint redundancy_count = 1; + + if (dtmfsrc->first_packet == TRUE || dtmfsrc->last_packet == TRUE) { + redundancy_count = dtmfsrc->packet_redundancy; + + if(dtmfsrc->first_packet == TRUE) { + GST_DEBUG_OBJECT (dtmfsrc, + "redundancy count set to %d due to dtmf start", + redundancy_count); + } else if(dtmfsrc->last_packet == TRUE) { + GST_DEBUG_OBJECT (dtmfsrc, + "redundancy count set to %d due to dtmf stop", + redundancy_count); + } + + } + + /* create buffer to hold the payload */ + buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc); + + while ( redundancy_count-- ) { + gst_buffer_ref(buf); + + GST_DEBUG_OBJECT (dtmfsrc, + "pushing buffer on src pad of size %d with redundancy count %d", + GST_BUFFER_SIZE (buf), redundancy_count); + ret = gst_pad_push (dtmfsrc->srcpad, buf); + if (ret != GST_FLOW_OK) + GST_ERROR_OBJECT (dtmfsrc, + "Failed to push buffer on src pad", GST_BUFFER_SIZE (buf)); + + /* Make sure only the first packet sent has the marker set */ + gst_rtp_buffer_set_marker (buf, FALSE); + } + + gst_buffer_unref(buf); + GST_DEBUG_OBJECT (dtmfsrc, + "pushed DTMF event '%d' on src pad", dtmfsrc->payload->event); + + if (dtmfsrc->payload->e) { + /* Don't forget to release the stream lock */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + + g_free (dtmfsrc->payload); + dtmfsrc->payload = NULL; + + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); + return; + } + + } + +} + +static void +gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc) +{ + GstCaps *caps; + + caps = gst_caps_new_simple ("application/x-rtp", + "media", G_TYPE_STRING, "audio", + "payload", G_TYPE_INT, dtmfsrc->pt, + "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, + "encoding-name", G_TYPE_STRING, "telephone-event", + "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc, + "clock-base", G_TYPE_UINT, dtmfsrc->ts_base, + "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base, NULL); + + if (!gst_pad_set_caps (dtmfsrc->srcpad, caps)) + GST_ERROR_OBJECT (dtmfsrc, + "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps); + else + GST_DEBUG_OBJECT (dtmfsrc, + "caps %" GST_PTR_FORMAT " set on src pad", caps); + + gst_caps_unref (caps); +} + +static void +gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) +{ + gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); + + 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; +} + +static GstStateChangeReturn +gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) +{ + GstRTPDTMFSrc *dtmfsrc; + GstStateChangeReturn result; + gboolean no_preroll = FALSE; + + dtmfsrc = GST_RTP_DTMF_SRC (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_rtp_dtmf_src_ready_to_paused (dtmfsrc); + /* Indicate that we don't do PRE_ROLL */ + no_preroll = TRUE; + break; + default: + break; + } + + if ((result = + GST_ELEMENT_CLASS (parent_class)->change_state (element, + transition)) == GST_STATE_CHANGE_FAILURE) + goto failure; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* Indicate that we don't do PRE_ROLL */ + no_preroll = TRUE; + 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_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpdtmfsrc", + GST_RANK_NONE, GST_TYPE_RTP_DTMF_SRC); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_rtp_dtmf_src_plugin_init (plugin)) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "dtmf", + "DTMF plugins", + plugin_init, "0.1" , "LGPL", "DTMF", ""); diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h new file mode 100644 index 0000000000..797526ea95 --- /dev/null +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -0,0 +1,101 @@ +/* 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_DTMF_SRC_H__ +#define __GST_RTP_DTMF_SRC_H__ + +#include +#include + +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 { + 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; + +typedef struct _GstRTPDTMFSrc GstRTPDTMFSrc; +typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass; + +/** + * GstRTPDTMFSrc: + * @element: the parent element. + * + * The opaque #GstRTPDTMFSrc data structure. + */ +struct _GstRTPDTMFSrc { + GstElement element; + + GstPad *srcpad; + GstRTPDTMFPayload *payload; + + guint32 ts_base; + guint16 seqnum_base; + + gint16 seqnum_offset; + guint16 seqnum; + gint32 ts_offset; + guint32 rtp_timestamp; + guint32 clock_rate; + guint pt; + guint ssrc; + guint current_ssrc; + gboolean first_packet; + gboolean last_packet; + + GstClockTime timestamp; + GstSegment segment; + + guint16 interval; + guint16 packet_redundancy; +}; + +struct _GstRTPDTMFSrcClass { + GstElementClass parent_class; +}; + +GType gst_rtp_dtmf_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_RTP_DTMF_SRC_H__ */ From 4aff57476c38b5058e2627a31dcb18db0237e51d Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 20 Aug 2007 18:48:52 +0000 Subject: [PATCH 002/138] [MOVED FROM GST-P-FARSIGHT] Added dtmfsrc, a DTMF Tone Generator, and made it part of the 'dtmf' plugin. 20070820184852-4f0f6-a0d85e67708290aebafa89ab79d3cedd5815b620.gz --- gst/dtmf/Makefile.am | 16 +- gst/dtmf/gstdtmf.c | 27 ++ gst/dtmf/gstdtmfsrc.c | 729 +++++++++++++++++++++++++++++++++++++++ gst/dtmf/gstdtmfsrc.h | 74 ++++ gst/dtmf/gstrtpdtmfsrc.c | 19 +- gst/dtmf/gstrtpdtmfsrc.h | 3 + 6 files changed, 845 insertions(+), 23 deletions(-) create mode 100644 gst/dtmf/gstdtmf.c create mode 100644 gst/dtmf/gstdtmfsrc.c create mode 100644 gst/dtmf/gstdtmfsrc.h diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index 603b32c28e..210dcadeae 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -1,9 +1,13 @@ -plugin_LTLIBRARIES = libgstrtpdtmf.la +plugin_LTLIBRARIES = libgstdtmf.la -libgstrtpdtmf_la_SOURCES = gstrtpdtmfsrc.c +libgstdtmf_la_SOURCES = gstdtmfsrc.c \ + gstrtpdtmfsrc.c \ + gstdtmf.c -libgstrtpdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT -libgstrtpdtmf_la_LIBADD = $(GST_LIBS_LIBS) -libgstrtpdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ +noinst_HEADERS = gstdtmfsrc.h \ + gstrtpdtmfsrc.h + +libgstdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT +libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) +libgstdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ -noinst_HEADERS = gstrtpdtmfsrc.h diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c new file mode 100644 index 0000000000..3086885748 --- /dev/null +++ b/gst/dtmf/gstdtmf.c @@ -0,0 +1,27 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdtmfsrc.h" +#include "gstrtpdtmfsrc.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; + + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "dtmf", + "DTMF plugins", + plugin_init, "0.1" , "LGPL", "DTMF", ""); diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c new file mode 100644 index 0000000000..523419db47 --- /dev/null +++ b/gst/dtmf/gstdtmfsrc.c @@ -0,0 +1,729 @@ +/* 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-dtmfsrc + * @short_description: Generates DTMF packets + * + * + * + * + * 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. This element is only capable of generating tones. + * + * + * + * 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. 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 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, 0, + * "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); + * + * + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifndef M_PI +# define M_PI 3.14159265358979323846 /* pi */ +#endif + + +#include "gstdtmfsrc.h" + +#define GST_TONE_DTMF_TYPE_EVENT 0 +#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_EVENT 0 +#define MAX_EVENT 16 +#define MIN_VOLUME 0 +#define MAX_VOLUME 36 + + + +typedef struct st_dtmf_key { + 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, +}; + +/* elementfactory information */ +static const GstElementDetails gst_dtmf_src_details = +GST_ELEMENT_DETAILS ("DTMF tone generator", + "Source/Audio", + "Generates DTMF tones", + "Youness Alaoui "); + +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-int, " + "width = (int) 16, " + "depth = (int) 16, " + "endianness = (int) 1234, " + "signed = (bool) true, " + "rate = (int) 8000, " + "channels = (int) 1") + ); + +static GstElementClass *parent_class = NULL; + +static void gst_dtmf_src_base_init (gpointer g_class); +static void gst_dtmf_src_class_init (GstDTMFSrcClass * klass); +static void gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class); +static void gst_dtmf_src_finalize (GObject * object); + +GType +gst_dtmf_src_get_type (void) +{ + static GType base_src_type = 0; + + if (G_UNLIKELY (base_src_type == 0)) { + static const GTypeInfo base_src_info = { + sizeof (GstDTMFSrcClass), + (GBaseInitFunc) gst_dtmf_src_base_init, + NULL, + (GClassInitFunc) gst_dtmf_src_class_init, + NULL, + NULL, + sizeof (GstDTMFSrc), + 0, + (GInstanceInitFunc) gst_dtmf_src_init, + }; + + base_src_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstDTMFSrc", &base_src_info, 0); + } + return base_src_type; +} + +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 (GstPad * pad, GstEvent * event); +static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, + GstStateChange transition); +static void gst_dtmf_src_generate_tone(GstDTMFSrc *dtmfsrc, DTMF_KEY key, float duration, + GstBuffer * buffer); +static void gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc); +static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc, gint event_number, + gint event_volume); +static void gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc); + +static void +gst_dtmf_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (gst_dtmf_src_debug, + "dtmfsrc", 0, "dtmfsrc element"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_dtmf_src_template)); + + gst_element_class_set_details (element_class, &gst_dtmf_src_details); +} + +static void +gst_dtmf_src_class_init (GstDTMFSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_dtmf_src_finalize); + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_dtmf_src_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_dtmf_src_get_property); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL, + g_param_spec_int ("interval", "Interval between tone packets", + "Interval in ms between two tone packets", MIN_PACKET_INTERVAL, + MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, G_PARAM_READWRITE)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state); +} + +static void +gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class) +{ + dtmfsrc->srcpad = + gst_pad_new_from_static_template (&gst_dtmf_src_template, "src"); + GST_DEBUG_OBJECT (dtmfsrc, "adding src pad"); + gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad); + + gst_pad_set_event_function (dtmfsrc->srcpad, gst_dtmf_src_handle_event); + + dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; + + dtmfsrc->sample = 0; + + GST_DEBUG_OBJECT (dtmfsrc, "init done"); +} + +static void +gst_dtmf_src_finalize (GObject * object) +{ + GstDTMFSrc *dtmfsrc; + + dtmfsrc = GST_DTMF_SRC (object); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_dtmf_src_handle_dtmf_event (GstDTMFSrc *dtmfsrc, + const GstStructure * event_structure) +{ + gint event_type; + gboolean start; + gint method; + + 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) { + gint event_number; + gint event_volume; + + 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_dtmf_src_start (dtmfsrc, event_number, event_volume); + } + + else { + GST_DEBUG_OBJECT (dtmfsrc, "Received stop event"); + gst_dtmf_src_stop (dtmfsrc); + } + + return TRUE; +failure: + return FALSE; +} + +static gboolean +gst_dtmf_src_handle_custom_upstream (GstDTMFSrc *dtmfsrc, + GstEvent * event) +{ + gboolean result = FALSE; + const GstStructure *structure; + + if (GST_STATE (dtmfsrc) != 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); + if (structure && gst_structure_has_name (structure, "dtmf-event")) + result = gst_dtmf_src_handle_dtmf_event (dtmfsrc, structure); + +ret: + return result; +} + +static gboolean +gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event) +{ + GstDTMFSrc *dtmfsrc; + gboolean result = FALSE; + + dtmfsrc = GST_DTMF_SRC (GST_PAD_PARENT (pad)); + + GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_UPSTREAM: + { + result = gst_dtmf_src_handle_custom_upstream (dtmfsrc, event); + break; + } + /* Ideally this element should not be flushed but let's handle the event + * just in case it is */ + case GST_EVENT_FLUSH_START: + gst_dtmf_src_stop (dtmfsrc); + result = TRUE; + break; + case GST_EVENT_FLUSH_STOP: + gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate; + GstFormat fmt; + gint64 start, stop, position; + + gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, + &stop, &position); + gst_segment_set_newsegment (&dtmfsrc->segment, update, rate, fmt, + start, stop, position); + } + /* fallthrough */ + default: + result = gst_pad_event_default (pad, event); + break; + } + + gst_event_unref (event); + return result; +} + +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_int (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_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) +{ + GstEvent *event; + GstStructure *structure; + + structure = gst_structure_new ("stream-lock", + "lock", G_TYPE_BOOLEAN, lock, NULL); + + event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); + gst_pad_push_event (dtmfsrc->srcpad, event); +} + +static void +gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) +{ + GstClock *clock; + + clock = GST_ELEMENT_CLOCK (dtmfsrc); + if (clock != NULL) + dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); + + else { + GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", + GST_ELEMENT_NAME (dtmfsrc)); + dtmfsrc->timestamp = GST_CLOCK_TIME_NONE; + } +} + +static void +gst_dtmf_src_start (GstDTMFSrc *dtmfsrc, + gint event_number, gint event_volume) +{ + GstCaps * caps = gst_pad_get_pad_template_caps (dtmfsrc->srcpad); + + dtmfsrc->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT); + dtmfsrc->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME); + + gst_dtmf_prepare_timestamps (dtmfsrc); + + /* Don't forget to get exclusive access to the stream */ + gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + + if (!gst_pad_set_caps (dtmfsrc->srcpad, caps)) + GST_ERROR_OBJECT (dtmfsrc, + "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps); + else + GST_DEBUG_OBJECT (dtmfsrc, + "caps %" GST_PTR_FORMAT " set on src pad", caps); + + + if (!gst_pad_start_task (dtmfsrc->srcpad, + (GstTaskFunction) gst_dtmf_src_push_next_tone_packet, dtmfsrc)) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); + } +} + +static void +gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) +{ + /* Don't forget to release the stream lock */ + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); + return; + } + +} + +static void +gst_dtmf_src_generate_tone(GstDTMFSrc *dtmfsrc, DTMF_KEY key, float duration, GstBuffer * buffer) +{ + gint16 *p; + gint tone_size; + double i = 0; + double amplitude, f1, f2; + + /* Create a buffer for the tone */ + tone_size = ((duration/1000)*SAMPLE_RATE*SAMPLE_SIZE*CHANNELS)/8; + GST_BUFFER_SIZE (buffer) = tone_size; + GST_BUFFER_MALLOCDATA (buffer) = g_malloc(tone_size); + GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); + + p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); + + /* + * 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 * (dtmfsrc->sample / SAMPLE_RATE)); + f2 = sin(2 * M_PI * key.high_frequency * (dtmfsrc->sample / SAMPLE_RATE)); + + amplitude = (f1 + f2) / 2; + + /* Make the [-1:1] interval into a [-32767:32767] interval */ + amplitude *= 32767; + + /* Store it in the data buffer */ + *(p++) = (gint16) amplitude; + + (dtmfsrc->sample)++; + } +} + +static void +gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) +{ + GstClock *clock; + + clock = GST_ELEMENT_CLOCK (dtmfsrc); + if (clock != NULL) { + GstClockID clock_id; + GstClockReturn clock_ret; + + clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); + clock_ret = gst_clock_id_wait (clock_id, NULL); + if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", + GST_ELEMENT_NAME (clock)); + } + gst_clock_id_unref (clock_id); + } + + else { + GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", + GST_ELEMENT_NAME (dtmfsrc)); + } +} + + +static GstBuffer * +gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc) +{ + GstBuffer *buf = NULL; + + + GST_DEBUG_OBJECT (dtmfsrc, + "Creating buffer for tone"); + + /* create buffer to hold the tone */ + buf = gst_buffer_new (); + + /* Generate the tone */ + gst_dtmf_src_generate_tone(dtmfsrc, DTMF_KEYS[dtmfsrc->event], dtmfsrc->interval, buf); + + + /* timestamp and duration of GstBuffer */ + GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; + GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; + dtmfsrc->timestamp += GST_BUFFER_DURATION (buf) /2; + + /* FIXME: Should we sync to clock ourselves or leave it to sink */ + gst_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); + + /* Set caps on the buffer before pushing it */ + gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad)); + + return buf; +} + +static void +gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) +{ + GstBuffer *buf = NULL; + GstFlowReturn ret; + + buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc); + + gst_buffer_ref(buf); + + GST_DEBUG_OBJECT (dtmfsrc, + "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); + ret = gst_pad_push (dtmfsrc->srcpad, buf); + if (ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad", GST_BUFFER_SIZE (buf)); + } + + gst_buffer_unref(buf); + GST_DEBUG_OBJECT (dtmfsrc, "pushed DTMF tone on src pad"); + +} + +static GstStateChangeReturn +gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) +{ + GstDTMFSrc *dtmfsrc; + GstStateChangeReturn result; + gboolean no_preroll = FALSE; + + dtmfsrc = GST_DTMF_SRC (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); + /* Indicate that we don't do PRE_ROLL */ + no_preroll = TRUE; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + /* gst_dtmf_src_start (dtmfsrc, 6, 30); */ + break; + default: + break; + } + + if ((result = + GST_ELEMENT_CLASS (parent_class)->change_state (element, + transition)) == GST_STATE_CHANGE_FAILURE) + goto failure; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* Indicate that we don't do PRE_ROLL */ + /* gst_dtmf_src_stop (dtmfsrc); */ + no_preroll = TRUE; + 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 new file mode 100644 index 0000000000..234120e967 --- /dev/null +++ b/gst/dtmf/gstdtmfsrc.h @@ -0,0 +1,74 @@ +/* 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_DTMF_SRC_H__ +#define __GST_DTMF_SRC_H__ + +#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; + +/** + * GstDTMFSrc: + * @element: the parent element. + * + * The opaque #GstDTMFSrc data structure. + */ +struct _GstDTMFSrc { + GstElement element; + GstPad *srcpad; + GstClockTime timestamp; + GstSegment segment; + double sample; + + guint16 event; + guint16 volume; + guint16 interval; +}; + +struct _GstDTMFSrcClass { + GstElementClass 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/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 8e4f31b545..11bff78686 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -244,7 +244,7 @@ gst_rtp_dtmf_src_base_init (gpointer g_class) GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug, - "dtmfsrc", 0, "dtmfsrc element"); + "rtpdtmfsrc", 0, "rtpdtmfsrc element"); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); @@ -849,24 +849,9 @@ failure: } } -static gboolean +gboolean gst_rtp_dtmf_src_plugin_init (GstPlugin * plugin) { return gst_element_register (plugin, "rtpdtmfsrc", GST_RANK_NONE, GST_TYPE_RTP_DTMF_SRC); } - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_rtp_dtmf_src_plugin_init (plugin)) - return FALSE; - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "dtmf", - "DTMF plugins", - plugin_init, "0.1" , "LGPL", "DTMF", ""); diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 797526ea95..8a763cce0c 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -96,6 +96,9 @@ struct _GstRTPDTMFSrcClass { 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__ */ From e7d5bdc4e81aa79debf88dea1a5beabc649ad068 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 20 Aug 2007 20:38:26 +0000 Subject: [PATCH 003/138] [MOVED FROM GST-P-FARSIGHT] Added a queue based system for the dtmfsrc. Now it waits for start/stop messages on the queue, and makes sure that the minimum duty cycle (120ms) is respected between each tone, including inter-digit silence. 20070820203826-4f0f6-750a22b612a5e495e767666934465c34fe32074b.gz --- gst/dtmf/gstdtmfsrc.c | 196 +++++++++++++++++++++++++++++++++--------- gst/dtmf/gstdtmfsrc.h | 26 +++++- 2 files changed, 177 insertions(+), 45 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 523419db47..0959e6d471 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -130,6 +130,8 @@ #include #include +#include + #ifndef M_PI # define M_PI 3.14159265358979323846 /* pi */ #endif @@ -148,7 +150,9 @@ #define MAX_EVENT 16 #define MIN_VOLUME 0 #define MAX_VOLUME 36 - +#define MIN_INTER_DIGIT_INTERVAL 50 +#define MIN_PULSE_DURATION 70 +#define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) typedef struct st_dtmf_key { @@ -265,12 +269,14 @@ static void gst_dtmf_src_get_property (GObject * object, guint prop_id, static gboolean gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition); -static void gst_dtmf_src_generate_tone(GstDTMFSrc *dtmfsrc, DTMF_KEY key, float duration, +static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, GstBuffer * buffer); static void gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc); -static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc, gint event_number, - gint event_volume); +static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc); static void gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc); +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 void gst_dtmf_src_base_init (gpointer g_class) @@ -324,7 +330,8 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class) dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; - dtmfsrc->sample = 0; + dtmfsrc->event_queue = g_async_queue_new (); + dtmfsrc->last_event = NULL; GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -336,6 +343,14 @@ gst_dtmf_src_finalize (GObject * object) dtmfsrc = GST_DTMF_SRC (object); + + gst_dtmf_src_stop (dtmfsrc); + + if (dtmfsrc->event_queue) { + g_async_queue_unref (dtmfsrc->event_queue); + dtmfsrc->event_queue = NULL; + } + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -368,12 +383,12 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc *dtmfsrc, GST_DEBUG_OBJECT (dtmfsrc, "Received start event %d with volume %d", event_number, event_volume); - gst_dtmf_src_start (dtmfsrc, 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_stop (dtmfsrc); + gst_dtmf_src_add_stop_event (dtmfsrc); } return TRUE; @@ -498,35 +513,26 @@ gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) } static void -gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) +gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *event) { GstClock *clock; clock = GST_ELEMENT_CLOCK (dtmfsrc); if (clock != NULL) - dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); + event->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); else { GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", GST_ELEMENT_NAME (dtmfsrc)); - dtmfsrc->timestamp = GST_CLOCK_TIME_NONE; + event->timestamp = GST_CLOCK_TIME_NONE; } } static void -gst_dtmf_src_start (GstDTMFSrc *dtmfsrc, - gint event_number, gint event_volume) +gst_dtmf_src_start (GstDTMFSrc *dtmfsrc) { GstCaps * caps = gst_pad_get_pad_template_caps (dtmfsrc->srcpad); - dtmfsrc->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT); - dtmfsrc->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME); - - gst_dtmf_prepare_timestamps (dtmfsrc); - - /* Don't forget to get exclusive access to the stream */ - gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - if (!gst_pad_set_caps (dtmfsrc->srcpad, caps)) GST_ERROR_OBJECT (dtmfsrc, "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps); @@ -547,6 +553,20 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) /* Don't forget to release the stream lock */ gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + + /* Flushing the event queue */ + GstDTMFSrcEvent *event = g_async_queue_try_pop (dtmfsrc->event_queue); + + while (event != NULL) { + g_free (event); + event = g_async_queue_try_pop (dtmfsrc->event_queue); + } + + if (dtmfsrc->last_event) { + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); return; @@ -555,7 +575,47 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) } static void -gst_dtmf_src_generate_tone(GstDTMFSrc *dtmfsrc, DTMF_KEY key, float duration, GstBuffer * buffer) +gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, gint event_number, + gint event_volume) +{ + + GstDTMFSrcEvent * event = g_malloc (sizeof(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_malloc (sizeof(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 void +gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration) +{ + gint buf_size; + + /* Create a buffer with data set to 0 */ + buf_size = ((duration/1000)*SAMPLE_RATE*SAMPLE_SIZE*CHANNELS)/8; + GST_BUFFER_SIZE (buffer) = buf_size; + GST_BUFFER_MALLOCDATA (buffer) = g_malloc0(buf_size); + GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); + +} + +static void +gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, GstBuffer * buffer) { gint16 *p; gint tone_size; @@ -578,8 +638,8 @@ gst_dtmf_src_generate_tone(GstDTMFSrc *dtmfsrc, DTMF_KEY key, float duration, Gs /* * We add the fundamental frequencies together. */ - f1 = sin(2 * M_PI * key.low_frequency * (dtmfsrc->sample / SAMPLE_RATE)); - f2 = sin(2 * M_PI * key.high_frequency * (dtmfsrc->sample / SAMPLE_RATE)); + 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; @@ -589,7 +649,7 @@ gst_dtmf_src_generate_tone(GstDTMFSrc *dtmfsrc, DTMF_KEY key, float duration, Gs /* Store it in the data buffer */ *(p++) = (gint16) amplitude; - (dtmfsrc->sample)++; + (event->sample)++; } } @@ -620,9 +680,10 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) static GstBuffer * -gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc) +gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *event) { GstBuffer *buf = NULL; + guint32 duration; GST_DEBUG_OBJECT (dtmfsrc, @@ -631,14 +692,32 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc) /* create buffer to hold the tone */ buf = gst_buffer_new (); - /* Generate the tone */ - gst_dtmf_src_generate_tone(dtmfsrc, DTMF_KEYS[dtmfsrc->event], dtmfsrc->interval, buf); + /* The first packet must be inter digit silence, then the second and third must be the + * minimal pulse duration divided into two packets to make it small + */ + switch(event->packet_count) { + case 0: + duration = MIN_INTER_DIGIT_INTERVAL; + gst_dtmf_src_generate_silence (buf, duration); + break; + case 1: + case 2: + /* Generate the tone */ + duration = MIN_PULSE_DURATION / 2; + gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], duration, buf); + break; + default: + duration = dtmfsrc->interval; + gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], duration, buf); + break; + } + event->packet_count++; /* timestamp and duration of GstBuffer */ - GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; - GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; - dtmfsrc->timestamp += GST_BUFFER_DURATION (buf) /2; + GST_BUFFER_DURATION (buf) = duration * GST_MSECOND; + GST_BUFFER_TIMESTAMP (buf) = event->timestamp; + event->timestamp += GST_BUFFER_DURATION (buf); /* FIXME: Should we sync to clock ourselves or leave it to sink */ gst_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); @@ -654,20 +733,54 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) { GstBuffer *buf = NULL; GstFlowReturn ret; + GstDTMFSrcEvent *event; - buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc); + g_async_queue_ref (dtmfsrc->event_queue); - gst_buffer_ref(buf); + if (dtmfsrc->last_event == NULL) { + event = g_async_queue_pop (dtmfsrc->event_queue); - GST_DEBUG_OBJECT (dtmfsrc, - "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); - ret = gst_pad_push (dtmfsrc->srcpad, buf); - if (ret != GST_FLOW_OK) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad", GST_BUFFER_SIZE (buf)); + if (event->event_type == DTMF_EVENT_TYPE_STOP) { + GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped", GST_BUFFER_SIZE (buf)); + } else if (event->event_type == DTMF_EVENT_TYPE_START) { + gst_dtmf_prepare_timestamps (dtmfsrc, event); + + /* Don't forget to get exclusive access to the stream */ + gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + + event->packet_count = 0; + dtmfsrc->last_event = event; + } + } else if (dtmfsrc->last_event->packet_count >= 3) { + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + if (event != NULL) { + if (event->event_type == DTMF_EVENT_TYPE_START) { + GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events", GST_BUFFER_SIZE (buf)); + } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } + } } + g_async_queue_unref (dtmfsrc->event_queue); - gst_buffer_unref(buf); - GST_DEBUG_OBJECT (dtmfsrc, "pushed DTMF tone on src pad"); + if (dtmfsrc->last_event) { + buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); + + gst_buffer_ref(buf); + + GST_DEBUG_OBJECT (dtmfsrc, + "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); + ret = gst_pad_push (dtmfsrc->srcpad, buf); + if (ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad", GST_BUFFER_SIZE (buf)); + } + + gst_buffer_unref(buf); + GST_DEBUG_OBJECT (dtmfsrc, "pushed DTMF tone on src pad"); + } } @@ -687,7 +800,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) no_preroll = TRUE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - /* gst_dtmf_src_start (dtmfsrc, 6, 30); */ + gst_dtmf_src_start (dtmfsrc); break; default: break; @@ -701,7 +814,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: /* Indicate that we don't do PRE_ROLL */ - /* gst_dtmf_src_stop (dtmfsrc); */ + gst_dtmf_src_stop (dtmfsrc); no_preroll = TRUE; break; default: @@ -727,3 +840,4 @@ 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 index 234120e967..544b66e554 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -49,18 +49,36 @@ typedef struct _GstDTMFSrcClass GstDTMFSrcClass; * * The opaque #GstDTMFSrc data structure. */ + +enum _GstDTMFEventType { + DTMF_EVENT_TYPE_START, + DTMF_EVENT_TYPE_STOP +}; + +typedef enum _GstDTMFEventType GstDTMFEventType; + +struct _GstDTMFSrcEvent { + GstClockTime timestamp; + GstDTMFEventType event_type; + double sample; + guint16 event_number; + guint16 volume; + guint32 packet_count; +}; + +typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent; + struct _GstDTMFSrc { GstElement element; GstPad *srcpad; - GstClockTime timestamp; GstSegment segment; - double sample; + GAsyncQueue* event_queue; + GstDTMFSrcEvent* last_event; - guint16 event; - guint16 volume; guint16 interval; }; + struct _GstDTMFSrcClass { GstElementClass parent_class; }; From f73fb17b344173684c3f22ca2c6de4de094ec2f9 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Wed, 22 Aug 2007 17:51:26 +0000 Subject: [PATCH 004/138] [MOVED FROM GST-P-FARSIGHT] Moved the timestamp from the event to dtmfsrc structure since we have only one event at a time, so let's keep it stored in the dtmfsrc struct 20070822175126-4f0f6-53bcda2bd8ae8c56d29e62e69ac19a30e08ad350.gz --- gst/dtmf/gstdtmfsrc.c | 12 ++++++------ gst/dtmf/gstdtmfsrc.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 0959e6d471..2d5d92dbed 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -513,18 +513,18 @@ gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) } static void -gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *event) +gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) { GstClock *clock; clock = GST_ELEMENT_CLOCK (dtmfsrc); if (clock != NULL) - event->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); + dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); else { GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", GST_ELEMENT_NAME (dtmfsrc)); - event->timestamp = GST_CLOCK_TIME_NONE; + dtmfsrc->timestamp = GST_CLOCK_TIME_NONE; } } @@ -716,8 +716,8 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *even /* timestamp and duration of GstBuffer */ GST_BUFFER_DURATION (buf) = duration * GST_MSECOND; - GST_BUFFER_TIMESTAMP (buf) = event->timestamp; - event->timestamp += GST_BUFFER_DURATION (buf); + GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; + dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); /* FIXME: Should we sync to clock ourselves or leave it to sink */ gst_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); @@ -743,7 +743,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) if (event->event_type == DTMF_EVENT_TYPE_STOP) { GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped", GST_BUFFER_SIZE (buf)); } else if (event->event_type == DTMF_EVENT_TYPE_START) { - gst_dtmf_prepare_timestamps (dtmfsrc, event); + gst_dtmf_prepare_timestamps (dtmfsrc); /* Don't forget to get exclusive access to the stream */ gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 544b66e554..1e341fdc4f 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -58,7 +58,6 @@ enum _GstDTMFEventType { typedef enum _GstDTMFEventType GstDTMFEventType; struct _GstDTMFSrcEvent { - GstClockTime timestamp; GstDTMFEventType event_type; double sample; guint16 event_number; @@ -76,6 +75,7 @@ struct _GstDTMFSrc { GstDTMFSrcEvent* last_event; guint16 interval; + GstClockTime timestamp; }; From 01f5b39eb23bff7c817d1c4dacb2f7bca3a1a933 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Wed, 22 Aug 2007 17:54:44 +0000 Subject: [PATCH 005/138] [MOVED FROM GST-P-FARSIGHT] ouch, printing with arguments but without %s.. that made it segfault a few times... 20070822175444-4f0f6-445ea6ce7a9668d04cf999af772a504ec74fb67a.gz --- gst/dtmf/gstdtmfsrc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 2d5d92dbed..6a3e6e6519 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -741,7 +741,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event = g_async_queue_pop (dtmfsrc->event_queue); if (event->event_type == DTMF_EVENT_TYPE_STOP) { - GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped", GST_BUFFER_SIZE (buf)); + GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped"); } else if (event->event_type == DTMF_EVENT_TYPE_START) { gst_dtmf_prepare_timestamps (dtmfsrc); @@ -756,7 +756,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) if (event != NULL) { if (event->event_type == DTMF_EVENT_TYPE_START) { - GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events", GST_BUFFER_SIZE (buf)); + GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events"); } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); g_free (dtmfsrc->last_event); @@ -775,7 +775,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); ret = gst_pad_push (dtmfsrc->srcpad, buf); if (ret != GST_FLOW_OK) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad", GST_BUFFER_SIZE (buf)); + GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad"); } gst_buffer_unref(buf); From 26a8292d83b353f785c00d5e178db9a2edae4c06 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Wed, 22 Aug 2007 17:55:33 +0000 Subject: [PATCH 006/138] [MOVED FROM GST-P-FARSIGHT] Ported the event queue work from dtmfsrc to rtpdtmfsrc Added a queue based system for the rtpdtmfsrc. Now it waits for start/stop messages on the queue, and makes sure that the minimum duty cycle (120ms) is respected between each tone, including inter-digit silence. 20070822175533-4f0f6-f27414c406f1f7b00c9a9084a988cf3a7930fe5c.gz --- gst/dtmf/gstrtpdtmfsrc.c | 281 ++++++++++++++++++++++++++------------- gst/dtmf/gstrtpdtmfsrc.h | 37 ++++-- 2 files changed, 215 insertions(+), 103 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 11bff78686..26c8d0aa65 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -45,7 +45,7 @@ * * * - * + * * * * Name @@ -54,7 +54,7 @@ * Purpose * * - * + * * * * type @@ -98,12 +98,12 @@ * * * - * + * * 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", @@ -111,7 +111,7 @@ * "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); * @@ -127,6 +127,8 @@ #include #include +#include + #include "gstrtpdtmfsrc.h" #define GST_RTP_DTMF_TYPE_EVENT 1 @@ -146,6 +148,10 @@ #define MAX_VOLUME 36 #define MIN_EVENT_DURATION 50 +#define MIN_INTER_DIGIT_INTERVAL 50 +#define MIN_PULSE_DURATION 70 +#define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) + #define DEFAULT_PACKET_REDUNDANCY 1 #define MIN_PACKET_REDUNDANCY 1 #define MAX_PACKET_REDUNDANCY 5 @@ -188,8 +194,8 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " "payload = (int) [ 96, 127 ], " - "clock-rate = (int) [ 0, MAX ], " - "ssrc = (int) [ 0, MAX ], " + "clock-rate = (int) [ 0, MAX ], " + "ssrc = (int) [ 0, MAX ], " "events = (int) [ " MIN_EVENT_STRING ", " MAX_EVENT_STRING " ], " "encoding-name = (string) \"telephone-event\"") ); @@ -233,22 +239,25 @@ static gboolean gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition); static void gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc); -static void gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc, gint event_number, - gint event_volume); +static void gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc); static void gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc); +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 void gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc); + static void gst_rtp_dtmf_src_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - + GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug, "rtpdtmfsrc", 0, "rtpdtmfsrc element"); - + gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); - + gst_element_class_set_details (element_class, &gst_rtp_dtmf_src_details); } @@ -264,7 +273,7 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) parent_class = g_type_class_peek_parent (klass); gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_finalize); - gobject_class->set_property = + 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); @@ -321,16 +330,19 @@ gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class) gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad); gst_pad_set_event_function (dtmfsrc->srcpad, gst_rtp_dtmf_src_handle_event); - + dtmfsrc->ssrc = DEFAULT_SSRC; dtmfsrc->seqnum_offset = DEFAULT_SEQNUM_OFFSET; dtmfsrc->ts_offset = DEFAULT_TIMESTAMP_OFFSET; dtmfsrc->pt = DEFAULT_PT; dtmfsrc->clock_rate = DEFAULT_CLOCK_RATE; - dtmfsrc->payload = NULL; dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; dtmfsrc->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; - + + + dtmfsrc->event_queue = g_async_queue_new (); + dtmfsrc->last_event = NULL; + GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -339,6 +351,12 @@ gst_rtp_dtmf_src_finalize (GObject * object) { GstRTPDTMFSrc *dtmfsrc; + + if (dtmfsrc->event_queue) { + g_async_queue_unref (dtmfsrc->event_queue); + dtmfsrc->event_queue = NULL; + } + dtmfsrc = GST_RTP_DTMF_SRC (object); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -373,12 +391,12 @@ gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc *dtmfsrc, GST_DEBUG_OBJECT (dtmfsrc, "Received start event %d with volume %d", event_number, event_volume); - gst_rtp_dtmf_src_start (dtmfsrc, 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_stop (dtmfsrc); + gst_rtp_dtmf_src_add_stop_event (dtmfsrc); } return TRUE; @@ -391,6 +409,7 @@ gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc, GstEvent * event) { gboolean result = FALSE; + gchar *struct_str; const GstStructure *structure; if (GST_STATE (dtmfsrc) != GST_STATE_PLAYING) { @@ -400,6 +419,9 @@ gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc, 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); @@ -553,7 +575,8 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) clock = GST_ELEMENT_CLOCK (dtmfsrc); if (clock != NULL) - dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); + dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)) + + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND); else { GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", @@ -569,23 +592,10 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) } static void -gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc, - gint event_number, gint event_volume) +gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc) { - g_return_if_fail (dtmfsrc->payload == NULL); - - dtmfsrc->payload = g_new0 (GstRTPDTMFPayload, 1); - dtmfsrc->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT); - dtmfsrc->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME); - dtmfsrc->first_packet = TRUE; - dtmfsrc->last_packet = FALSE; - - gst_rtp_dtmf_prepare_timestamps (dtmfsrc); gst_rtp_dtmf_src_set_caps (dtmfsrc); - /* Don't forget to get exclusive access to the stream */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - if (!gst_pad_start_task (dtmfsrc->srcpad, (GstTaskFunction) gst_rtp_dtmf_src_push_next_rtp_packet, dtmfsrc)) { GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); @@ -595,19 +605,65 @@ gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc, static void gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) { - g_return_if_fail (dtmfsrc->payload != NULL); + /* Don't forget to release the stream lock */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - /* Push the last packet with e-bit set */ - /* Next packet sent will be the last */ - dtmfsrc->last_packet = TRUE; + /* Flushing the event queue */ + GstRTPDTMFSrcEvent *event = g_async_queue_try_pop (dtmfsrc->event_queue); + + while (event != NULL) { + g_free (event); + event = g_async_queue_try_pop (dtmfsrc->event_queue); + } + + if (dtmfsrc->last_event) { + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } + + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); + return; + } } + + +static void +gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number, + gint event_volume) +{ + + GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); + event->event_type = RTP_DTMF_EVENT_TYPE_START; + + event->payload = g_new0 (GstRTPDTMFPayload, 1); + 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_malloc (sizeof(GstRTPDTMFSrcEvent)); + event->event_type = RTP_DTMF_EVENT_TYPE_STOP; + event->payload = g_new0 (GstRTPDTMFPayload, 1); + event->payload->event = 0; + event->payload->volume = 0; + + g_async_queue_push (dtmfsrc->event_queue, event); +} + + static void gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) { GstClock *clock; - + clock = GST_ELEMENT_CLOCK (dtmfsrc); if (clock != NULL) { GstClockID clock_id; @@ -629,7 +685,7 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) } static void -gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) +gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event, GstBuffer *buf) { gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc); gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt); @@ -637,37 +693,37 @@ gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) gst_rtp_buffer_set_marker (buf, TRUE); dtmfsrc->first_packet = FALSE; } else if (dtmfsrc->last_packet) { - dtmfsrc->payload->e = 1; + event->payload->e = 1; dtmfsrc->last_packet = FALSE; } dtmfsrc->seqnum++; gst_rtp_buffer_set_seq (buf, dtmfsrc->seqnum); - + /* timestamp of RTP header */ gst_rtp_buffer_set_timestamp (buf, dtmfsrc->rtp_timestamp); } static void -gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) +gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event,GstBuffer *buf) { GstRTPDTMFPayload *payload; - - gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, buf); + + gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc,event, buf); /* duration of DTMF payload */ - dtmfsrc->payload->duration += + event->payload->duration += dtmfsrc->interval * dtmfsrc->clock_rate / 1000; - /* timestamp and duration of GstBuffer */ + /* timestamp and duration of GstBuffer */ GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); - + payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf); - + /* copy payload and convert to network-byte order */ - g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload)); + g_memmove (payload, event->payload, sizeof (GstRTPDTMFPayload)); /* Force the packet duration to a certain minumum * if its the end of the event */ @@ -679,18 +735,20 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) } static GstBuffer * -gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) +gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event) { GstBuffer *buf = NULL; - + /* create buffer to hold the payload */ buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0); - gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, buf); + gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, event, buf); /* FIXME: Should we sync to clock ourselves or leave it to sink */ gst_rtp_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); + event->sent_packets++; + /* Set caps on the buffer before pushing it */ gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad)); @@ -703,58 +761,93 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) GstBuffer *buf = NULL; GstFlowReturn ret; gint redundancy_count = 1; + GstRTPDTMFSrcEvent *event; - if (dtmfsrc->first_packet == TRUE || dtmfsrc->last_packet == TRUE) { - redundancy_count = dtmfsrc->packet_redundancy; + g_async_queue_ref (dtmfsrc->event_queue); + + if (dtmfsrc->last_event == NULL) { + event = g_async_queue_pop (dtmfsrc->event_queue); + + if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) { + GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped"); + } else if (event->event_type == RTP_DTMF_EVENT_TYPE_START) { + + dtmfsrc->first_packet = TRUE; + dtmfsrc->last_packet = FALSE; + gst_rtp_dtmf_prepare_timestamps (dtmfsrc); + + /* Don't forget to get exclusive access to the stream */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + + event->sent_packets = 0; + + dtmfsrc->last_event = event; + } + } else if (dtmfsrc->last_event->sent_packets * dtmfsrc->interval >= MIN_PULSE_DURATION){ + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + if (event != NULL) { + if (event->event_type == RTP_DTMF_EVENT_TYPE_START) { + GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events"); + } else if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) { + dtmfsrc->first_packet = FALSE; + dtmfsrc->last_packet = TRUE; + } + } + } + g_async_queue_unref (dtmfsrc->event_queue); + + if (dtmfsrc->last_event) { + + if (dtmfsrc->first_packet == TRUE || dtmfsrc->last_packet == TRUE) { + redundancy_count = dtmfsrc->packet_redundancy; + + if(dtmfsrc->first_packet == TRUE) { + GST_DEBUG_OBJECT (dtmfsrc, + "redundancy count set to %d due to dtmf start", + redundancy_count); + } else if(dtmfsrc->last_packet == TRUE) { + GST_DEBUG_OBJECT (dtmfsrc, + "redundancy count set to %d due to dtmf stop", + redundancy_count); + } - if(dtmfsrc->first_packet == TRUE) { - GST_DEBUG_OBJECT (dtmfsrc, - "redundancy count set to %d due to dtmf start", - redundancy_count); - } else if(dtmfsrc->last_packet == TRUE) { - GST_DEBUG_OBJECT (dtmfsrc, - "redundancy count set to %d due to dtmf stop", - redundancy_count); } - } + /* create buffer to hold the payload */ + buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc, dtmfsrc->last_event); - /* create buffer to hold the payload */ - buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc); + while ( redundancy_count-- ) { + gst_buffer_ref(buf); - while ( redundancy_count-- ) { - gst_buffer_ref(buf); + GST_DEBUG_OBJECT (dtmfsrc, + "pushing buffer on src pad of size %d with redundancy count %d", + GST_BUFFER_SIZE (buf), redundancy_count); + ret = gst_pad_push (dtmfsrc->srcpad, buf); + if (ret != GST_FLOW_OK) + GST_ERROR_OBJECT (dtmfsrc, + "Failed to push buffer on src pad"); + /* Make sure only the first packet sent has the marker set */ + gst_rtp_buffer_set_marker (buf, FALSE); + } + + gst_buffer_unref(buf); GST_DEBUG_OBJECT (dtmfsrc, - "pushing buffer on src pad of size %d with redundancy count %d", - GST_BUFFER_SIZE (buf), redundancy_count); - ret = gst_pad_push (dtmfsrc->srcpad, buf); - if (ret != GST_FLOW_OK) - GST_ERROR_OBJECT (dtmfsrc, - "Failed to push buffer on src pad", GST_BUFFER_SIZE (buf)); + "pushed DTMF event '%d' on src pad", event->payload->event); - /* Make sure only the first packet sent has the marker set */ - gst_rtp_buffer_set_marker (buf, FALSE); - } + if (dtmfsrc->last_event->payload->e) { + /* Don't forget to release the stream lock */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - gst_buffer_unref(buf); - GST_DEBUG_OBJECT (dtmfsrc, - "pushed DTMF event '%d' on src pad", dtmfsrc->payload->event); + g_free (dtmfsrc->last_event->payload); + event->payload = NULL; - if (dtmfsrc->payload->e) { - /* Don't forget to release the stream lock */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; - g_free (dtmfsrc->payload); - dtmfsrc->payload = NULL; - - if (!gst_pad_pause_task (dtmfsrc->srcpad)) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); - return; } - } - } static void @@ -785,7 +878,7 @@ static void gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) { gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); - + if (dtmfsrc->ssrc == -1) dtmfsrc->current_ssrc = g_random_int (); else @@ -796,7 +889,7 @@ gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) else dtmfsrc->seqnum_base = dtmfsrc->seqnum_offset; dtmfsrc->seqnum = dtmfsrc->seqnum_base; - + if (dtmfsrc->ts_offset == -1) dtmfsrc->ts_base = g_random_int (); else @@ -818,6 +911,9 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) /* Indicate that we don't do PRE_ROLL */ no_preroll = TRUE; break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + gst_rtp_dtmf_src_start (dtmfsrc); + break; default: break; } @@ -831,6 +927,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PLAYING_TO_PAUSED: /* Indicate that we don't do PRE_ROLL */ no_preroll = TRUE; + gst_rtp_dtmf_src_stop (dtmfsrc); break; default: break; diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 8a763cce0c..2bbfb9db88 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -57,6 +57,23 @@ typedef struct { typedef struct _GstRTPDTMFSrc GstRTPDTMFSrc; typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass; + + +static enum _GstRTPDTMFEventType { + RTP_DTMF_EVENT_TYPE_START, + RTP_DTMF_EVENT_TYPE_STOP +}; + +typedef enum _GstRTPDTMFEventType GstRTPDTMFEventType; + +struct _GstRTPDTMFSrcEvent { + GstRTPDTMFEventType event_type; + GstRTPDTMFPayload* payload; + guint32 sent_packets; +}; + +typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; + /** * GstRTPDTMFSrc: * @element: the parent element. @@ -64,30 +81,28 @@ typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass; * The opaque #GstRTPDTMFSrc data structure. */ struct _GstRTPDTMFSrc { - GstElement element; + GstElement element; - GstPad *srcpad; - GstRTPDTMFPayload *payload; + GstPad* srcpad; + GstSegment segment; + GAsyncQueue* event_queue; + GstRTPDTMFSrcEvent* last_event; + GstClockTime timestamp; + gboolean first_packet; + gboolean last_packet; guint32 ts_base; guint16 seqnum_base; - gint16 seqnum_offset; guint16 seqnum; gint32 ts_offset; guint32 rtp_timestamp; - guint32 clock_rate; guint pt; guint ssrc; guint current_ssrc; - gboolean first_packet; - gboolean last_packet; - - GstClockTime timestamp; - GstSegment segment; - guint16 interval; guint16 packet_redundancy; + guint32 clock_rate; }; struct _GstRTPDTMFSrcClass { From 82072435f80a401d3e4262f145a210b6b4228445 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Wed, 22 Aug 2007 18:01:33 +0000 Subject: [PATCH 007/138] [MOVED FROM GST-P-FARSIGHT] don't know why I did that... 20070822180133-4f0f6-6a7382f6c7d3630f91da384e1904763c7ea6fa1a.gz --- gst/dtmf/gstdtmfsrc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 1e341fdc4f..e1a9cdffba 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -50,7 +50,7 @@ typedef struct _GstDTMFSrcClass GstDTMFSrcClass; * The opaque #GstDTMFSrc data structure. */ -enum _GstDTMFEventType { +static enum _GstDTMFEventType { DTMF_EVENT_TYPE_START, DTMF_EVENT_TYPE_STOP }; From 16a5d7d91cc153c2daf246dcdc332988ea47e0ee Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Wed, 22 Aug 2007 20:16:53 +0000 Subject: [PATCH 008/138] [MOVED FROM GST-P-FARSIGHT] The DTMF tone generator now respects the volume argument passed in the event 20070822201653-4f0f6-8b7ff874006e11f5a74d0fd91e5a9a43cd082ada.gz --- gst/dtmf/gstdtmfsrc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 6a3e6e6519..f04119c167 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -621,6 +621,7 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, gint tone_size; double i = 0; double amplitude, f1, f2; + double volume_factor; /* Create a buffer for the tone */ tone_size = ((duration/1000)*SAMPLE_RATE*SAMPLE_SIZE*CHANNELS)/8; @@ -630,6 +631,8 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); + volume_factor = pow (10, (-event->volume) / 20); + /* * For each sample point we calculate 'x' as the * the amplitude value. @@ -643,6 +646,9 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, amplitude = (f1 + f2) / 2; + /* Adjust the volume */ + amplitude *= volume_factor; + /* Make the [-1:1] interval into a [-32767:32767] interval */ amplitude *= 32767; From d5110d76e9d08e337bf705b37e3fe2d8b1c7af8c Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 27 Aug 2007 17:23:22 +0000 Subject: [PATCH 009/138] [MOVED FROM GST-P-FARSIGHT] Changing minimum values to work better on some gateways 20070827172322-4f0f6-5bf2bffa59a8244538dced795fa7d7649452ca91.gz --- gst/dtmf/gstdtmfsrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index f04119c167..caac6d6f47 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -150,8 +150,8 @@ #define MAX_EVENT 16 #define MIN_VOLUME 0 #define MAX_VOLUME 36 -#define MIN_INTER_DIGIT_INTERVAL 50 -#define MIN_PULSE_DURATION 70 +#define MIN_INTER_DIGIT_INTERVAL 100 +#define MIN_PULSE_DURATION 250 #define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) From bb4f9fa47760836ffccce72ebb206a1e57ca8e12 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 27 Aug 2007 17:23:39 +0000 Subject: [PATCH 010/138] [MOVED FROM GST-P-FARSIGHT] Better handling of packets, we send the same duration for all packets to avoid huge packets when min duration defines are modified. 20070827172339-4f0f6-cc93304437ea376fff6458c74c46c19f6920d329.gz --- gst/dtmf/gstdtmfsrc.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index caac6d6f47..3cefa651b4 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -689,39 +689,30 @@ static GstBuffer * gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *event) { GstBuffer *buf = NULL; - guint32 duration; + gboolean send_silence = FALSE; - - GST_DEBUG_OBJECT (dtmfsrc, - "Creating buffer for tone"); + GST_DEBUG_OBJECT (dtmfsrc, "Creating buffer for tone %s", DTMF_KEYS[event->event_number].event_name); /* create buffer to hold the tone */ buf = gst_buffer_new (); - /* The first packet must be inter digit silence, then the second and third must be the - * minimal pulse duration divided into two packets to make it small - */ - switch(event->packet_count) { - case 0: - duration = MIN_INTER_DIGIT_INTERVAL; - gst_dtmf_src_generate_silence (buf, duration); - break; - case 1: - case 2: - /* Generate the tone */ - duration = MIN_PULSE_DURATION / 2; - gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], duration, buf); - break; - default: - duration = dtmfsrc->interval; - gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], duration, buf); - break; + if (event->packet_count * dtmfsrc->interval < MIN_INTER_DIGIT_INTERVAL) { + send_silence = TRUE; + } + + if (send_silence) { + GST_DEBUG_OBJECT (dtmfsrc, "Generating silence"); + gst_dtmf_src_generate_silence (buf, dtmfsrc->interval); + } else { + GST_DEBUG_OBJECT (dtmfsrc, "Generating tone"); + gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], + dtmfsrc->interval, buf); } event->packet_count++; /* timestamp and duration of GstBuffer */ - GST_BUFFER_DURATION (buf) = duration * GST_MSECOND; + GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); @@ -757,7 +748,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event->packet_count = 0; dtmfsrc->last_event = event; } - } else if (dtmfsrc->last_event->packet_count >= 3) { + } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { event = g_async_queue_try_pop (dtmfsrc->event_queue); if (event != NULL) { From 09c6290b072e144b4f9599f8ca94965a59aed4f5 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 27 Aug 2007 17:24:24 +0000 Subject: [PATCH 011/138] [MOVED FROM GST-P-FARSIGHT] Fix RTP timestamps by sending a new_segment event to the payloader 20070827172424-4f0f6-d20907e3d436d50bfe74eb4fc3d2d6d7b6b6dbc5.gz --- gst/dtmf/gstdtmfsrc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 3cefa651b4..ae6fb74ad7 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -792,7 +792,10 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); + gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); + gst_pad_push_event (dtmfsrc->srcpad, gst_event_new_new_segment (FALSE, + dtmfsrc->segment.rate, dtmfsrc->segment.format, + dtmfsrc->segment.start, dtmfsrc->segment.stop, dtmfsrc->segment.time)); /* Indicate that we don't do PRE_ROLL */ no_preroll = TRUE; break; From cbf73c0d69279caa701eeb9788e8d10419854f25 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Mon, 27 Aug 2007 19:26:18 +0000 Subject: [PATCH 012/138] [MOVED FROM GST-P-FARSIGHT] untabbified dtmfsrc 20070827192618-4f0f6-77d68070464f1b5f9a46cb6eec2d922340143c04.gz --- gst/dtmf/gstdtmfsrc.c | 22 +++++++++++----------- gst/dtmf/gstdtmfsrc.h | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index ae6fb74ad7..713325a88e 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -225,10 +225,10 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("audio/x-raw-int, " "width = (int) 16, " "depth = (int) 16, " - "endianness = (int) 1234, " - "signed = (bool) true, " + "endianness = (int) 1234, " + "signed = (bool) true, " "rate = (int) 8000, " - "channels = (int) 1") + "channels = (int) 1") ); static GstElementClass *parent_class = NULL; @@ -706,7 +706,7 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *even } else { GST_DEBUG_OBJECT (dtmfsrc, "Generating tone"); gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], - dtmfsrc->interval, buf); + dtmfsrc->interval, buf); } event->packet_count++; @@ -753,11 +753,11 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) if (event != NULL) { if (event->event_type == DTMF_EVENT_TYPE_START) { - GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events"); + GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events"); } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; } } } @@ -769,7 +769,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) gst_buffer_ref(buf); GST_DEBUG_OBJECT (dtmfsrc, - "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); + "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); ret = gst_pad_push (dtmfsrc->srcpad, buf); if (ret != GST_FLOW_OK) { GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad"); @@ -794,8 +794,8 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); gst_pad_push_event (dtmfsrc->srcpad, gst_event_new_new_segment (FALSE, - dtmfsrc->segment.rate, dtmfsrc->segment.format, - dtmfsrc->segment.start, dtmfsrc->segment.stop, dtmfsrc->segment.time)); + dtmfsrc->segment.rate, dtmfsrc->segment.format, + dtmfsrc->segment.start, dtmfsrc->segment.stop, dtmfsrc->segment.time)); /* Indicate that we don't do PRE_ROLL */ no_preroll = TRUE; break; diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index e1a9cdffba..45f3a2a3c1 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -32,13 +32,13 @@ 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_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)) +#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; @@ -60,8 +60,8 @@ typedef enum _GstDTMFEventType GstDTMFEventType; struct _GstDTMFSrcEvent { GstDTMFEventType event_type; double sample; - guint16 event_number; - guint16 volume; + guint16 event_number; + guint16 volume; guint32 packet_count; }; @@ -69,12 +69,12 @@ typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent; struct _GstDTMFSrc { GstElement element; - GstPad *srcpad; + GstPad *srcpad; GstSegment segment; - GAsyncQueue* event_queue; + GAsyncQueue* event_queue; GstDTMFSrcEvent* last_event; - guint16 interval; + guint16 interval; GstClockTime timestamp; }; From a8e4a3007ef0d19b5a24f11798c57630f8f88cf0 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 27 Aug 2007 19:56:10 +0000 Subject: [PATCH 013/138] [MOVED FROM GST-P-FARSIGHT] Fix overly long lines and tabs 20070827195610-3e2dc-396a3fa01e16f184e4109c71fe2deb6e516bdf0d.gz --- gst/dtmf/gstdtmfsrc.c | 31 ++++++++++++++--------- gst/dtmf/gstrtpdtmfsrc.c | 53 +++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 713325a88e..5cfaa53ffc 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -269,13 +269,13 @@ static void gst_dtmf_src_get_property (GObject * object, guint prop_id, static gboolean gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition); -static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, - GstBuffer * buffer); +static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, + float duration, GstBuffer * buffer); static void gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc); static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc); static void gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc); -static void gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, gint event_number, - gint event_volume); +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 void @@ -615,7 +615,8 @@ gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration) } static void -gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, GstBuffer * buffer) +gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, + GstBuffer * buffer) { gint16 *p; gint tone_size; @@ -686,12 +687,14 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) static GstBuffer * -gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, GstDTMFSrcEvent *event) +gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, + GstDTMFSrcEvent *event) { GstBuffer *buf = NULL; gboolean send_silence = FALSE; - GST_DEBUG_OBJECT (dtmfsrc, "Creating buffer for tone %s", DTMF_KEYS[event->event_number].event_name); + GST_DEBUG_OBJECT (dtmfsrc, "Creating buffer for tone %s", + DTMF_KEYS[event->event_number].event_name); /* create buffer to hold the tone */ buf = gst_buffer_new (); @@ -738,7 +741,8 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event = g_async_queue_pop (dtmfsrc->event_queue); if (event->event_type == DTMF_EVENT_TYPE_STOP) { - GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped"); + GST_WARNING_OBJECT (dtmfsrc, + "Received a DTMF stop event when already stopped"); } else if (event->event_type == DTMF_EVENT_TYPE_START) { gst_dtmf_prepare_timestamps (dtmfsrc); @@ -748,12 +752,14 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event->packet_count = 0; dtmfsrc->last_event = event; } - } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { + } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= + MIN_DUTY_CYCLE) { event = g_async_queue_try_pop (dtmfsrc->event_queue); if (event != NULL) { if (event->event_type == DTMF_EVENT_TYPE_START) { - GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events"); + GST_WARNING_OBJECT (dtmfsrc, + "Received two consecutive DTMF start events"); } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); g_free (dtmfsrc->last_event); @@ -794,8 +800,9 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); gst_pad_push_event (dtmfsrc->srcpad, gst_event_new_new_segment (FALSE, - dtmfsrc->segment.rate, dtmfsrc->segment.format, - dtmfsrc->segment.start, dtmfsrc->segment.stop, dtmfsrc->segment.time)); + dtmfsrc->segment.rate, dtmfsrc->segment.format, + dtmfsrc->segment.start, dtmfsrc->segment.stop, + dtmfsrc->segment.time)); /* Indicate that we don't do PRE_ROLL */ no_preroll = TRUE; break; diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 26c8d0aa65..138c498fe9 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -90,8 +90,8 @@ * method * G_TYPE_INT * 1 - * The method used for sending event, this element will react if this field - * is absent or 1. + * The method used for sending event, this element will react if this + * field is absent or 1. * * * @@ -576,7 +576,7 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) clock = GST_ELEMENT_CLOCK (dtmfsrc); if (clock != NULL) dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)) - + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND); + + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND); else { GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", @@ -685,7 +685,8 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) } static void -gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event, GstBuffer *buf) +gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, + GstRTPDTMFSrcEvent *event, GstBuffer *buf) { gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc); gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt); @@ -705,7 +706,8 @@ gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *ev } static void -gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event,GstBuffer *buf) +gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, + GstRTPDTMFSrcEvent *event,GstBuffer *buf) { GstRTPDTMFPayload *payload; @@ -735,7 +737,8 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *ev } static GstBuffer * -gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event) +gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc, + GstRTPDTMFSrcEvent *event) { GstBuffer *buf = NULL; @@ -769,7 +772,8 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) event = g_async_queue_pop (dtmfsrc->event_queue); if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) { - GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped"); + GST_WARNING_OBJECT (dtmfsrc, + "Received a DTMF stop event when already stopped"); } else if (event->event_type == RTP_DTMF_EVENT_TYPE_START) { dtmfsrc->first_packet = TRUE; @@ -783,15 +787,17 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->last_event = event; } - } else if (dtmfsrc->last_event->sent_packets * dtmfsrc->interval >= MIN_PULSE_DURATION){ + } else if (dtmfsrc->last_event->sent_packets * dtmfsrc->interval >= + MIN_PULSE_DURATION){ event = g_async_queue_try_pop (dtmfsrc->event_queue); if (event != NULL) { if (event->event_type == RTP_DTMF_EVENT_TYPE_START) { - GST_WARNING_OBJECT (dtmfsrc, "Received two consecutive DTMF start events"); + GST_WARNING_OBJECT (dtmfsrc, + "Received two consecutive DTMF start events"); } else if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) { - dtmfsrc->first_packet = FALSE; - dtmfsrc->last_packet = TRUE; + dtmfsrc->first_packet = FALSE; + dtmfsrc->last_packet = TRUE; } } } @@ -803,30 +809,31 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) redundancy_count = dtmfsrc->packet_redundancy; if(dtmfsrc->first_packet == TRUE) { - GST_DEBUG_OBJECT (dtmfsrc, - "redundancy count set to %d due to dtmf start", - redundancy_count); + GST_DEBUG_OBJECT (dtmfsrc, + "redundancy count set to %d due to dtmf start", + redundancy_count); } else if(dtmfsrc->last_packet == TRUE) { - GST_DEBUG_OBJECT (dtmfsrc, - "redundancy count set to %d due to dtmf stop", - redundancy_count); + GST_DEBUG_OBJECT (dtmfsrc, + "redundancy count set to %d due to dtmf stop", + redundancy_count); } } /* create buffer to hold the payload */ - buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc, dtmfsrc->last_event); + buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc, + dtmfsrc->last_event); while ( redundancy_count-- ) { gst_buffer_ref(buf); GST_DEBUG_OBJECT (dtmfsrc, - "pushing buffer on src pad of size %d with redundancy count %d", - GST_BUFFER_SIZE (buf), redundancy_count); + "pushing buffer on src pad of size %d with redundancy count %d", + GST_BUFFER_SIZE (buf), redundancy_count); ret = gst_pad_push (dtmfsrc->srcpad, buf); if (ret != GST_FLOW_OK) - GST_ERROR_OBJECT (dtmfsrc, - "Failed to push buffer on src pad"); + GST_ERROR_OBJECT (dtmfsrc, + "Failed to push buffer on src pad"); /* Make sure only the first packet sent has the marker set */ gst_rtp_buffer_set_marker (buf, FALSE); @@ -834,7 +841,7 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) gst_buffer_unref(buf); GST_DEBUG_OBJECT (dtmfsrc, - "pushed DTMF event '%d' on src pad", event->payload->event); + "pushed DTMF event '%d' on src pad", event->payload->event); if (dtmfsrc->last_event->payload->e) { /* Don't forget to release the stream lock */ From 681dc405d50e6fcb83ed56e814d3ceb08b8b63b7 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Tue, 28 Aug 2007 17:15:46 +0000 Subject: [PATCH 014/138] [MOVED FROM GST-P-FARSIGHT] Cleaned up the code a bit, no use of GST_* and return value verification from gst_* 20070828171546-4f0f6-bdeb4b1b7f99f9464aabe5c43bd4a4d2025262b6.gz --- gst/dtmf/gstdtmfsrc.c | 44 ++++++++++++++++++++++++---------------- gst/dtmf/gstrtpdtmfsrc.c | 43 +++++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 5cfaa53ffc..7befc5441c 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -402,8 +402,11 @@ gst_dtmf_src_handle_custom_upstream (GstDTMFSrc *dtmfsrc, { gboolean result = FALSE; const GstStructure *structure; + GstState state; + GstStateChangeReturn ret; - if (GST_STATE (dtmfsrc) != GST_STATE_PLAYING) { + ret = gst_element_get_state (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; } @@ -422,8 +425,8 @@ gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event) { GstDTMFSrc *dtmfsrc; gboolean result = FALSE; - - dtmfsrc = GST_DTMF_SRC (GST_PAD_PARENT (pad)); + GstElement *parent = gst_pad_get_parent_element (pad); + dtmfsrc = GST_DTMF_SRC (parent); GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); switch (GST_EVENT_TYPE (event)) { @@ -439,7 +442,7 @@ gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event) result = TRUE; break; case GST_EVENT_FLUSH_STOP: - gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); + gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); break; case GST_EVENT_NEWSEGMENT: { @@ -459,6 +462,7 @@ gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event) break; } + gst_object_unref (parent); gst_event_unref (event); return result; } @@ -509,7 +513,9 @@ gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) "lock", G_TYPE_BOOLEAN, lock, NULL); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - gst_pad_push_event (dtmfsrc->srcpad, event); + if (!gst_pad_push_event (dtmfsrc->srcpad, event)) { + GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); + } } static void @@ -517,14 +523,15 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) { GstClock *clock; - clock = GST_ELEMENT_CLOCK (dtmfsrc); - if (clock != NULL) - dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)); - - else { - GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", - GST_ELEMENT_NAME (dtmfsrc)); + clock = gst_element_get_clock (dtmfsrc); + if (clock != NULL) { + dtmfsrc->timestamp = gst_clock_get_time (clock); + 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); } } @@ -665,7 +672,7 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) { GstClock *clock; - clock = GST_ELEMENT_CLOCK (dtmfsrc); + clock = gst_element_get_clock (dtmfsrc); if (clock != NULL) { GstClockID clock_id; GstClockReturn clock_ret; @@ -673,15 +680,18 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); clock_ret = gst_clock_id_wait (clock_id, NULL); if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", - GST_ELEMENT_NAME (clock)); + gchar *clock_name = gst_element_get_name (clock); + GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); + g_free (clock_name); } gst_clock_id_unref (clock_id); + gst_object_unref (clock); } else { - GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", - GST_ELEMENT_NAME (dtmfsrc)); + gchar *dtmf_name = gst_element_get_name (dtmfsrc); + GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name); + g_free (dtmf_name); } } diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 138c498fe9..3115d5428d 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -412,7 +412,11 @@ gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc, gchar *struct_str; const GstStructure *structure; - if (GST_STATE (dtmfsrc) != GST_STATE_PLAYING) { + GstState state; + GstStateChangeReturn ret; + + ret = gst_element_get_state (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; } @@ -434,8 +438,9 @@ gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event) { GstRTPDTMFSrc *dtmfsrc; gboolean result = FALSE; + GstElement *parent = gst_pad_get_parent_element (pad); + dtmfsrc = GST_DTMF_SRC (parent); - dtmfsrc = GST_RTP_DTMF_SRC (GST_PAD_PARENT (pad)); GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); switch (GST_EVENT_TYPE (event)) { @@ -471,6 +476,7 @@ gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event) break; } + gst_object_unref (parent); gst_event_unref (event); return result; } @@ -565,7 +571,10 @@ gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc *dtmfsrc, gboolean lock) "lock", G_TYPE_BOOLEAN, lock, NULL); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - gst_pad_push_event (dtmfsrc->srcpad, event); + if (!gst_pad_push_event (dtmfsrc->srcpad, event)) { + GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); + } + } static void @@ -573,15 +582,16 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) { GstClock *clock; - clock = GST_ELEMENT_CLOCK (dtmfsrc); - if (clock != NULL) - dtmfsrc->timestamp = gst_clock_get_time (GST_ELEMENT_CLOCK (dtmfsrc)) + clock = gst_element_get_clock (dtmfsrc); + if (clock != NULL) { + dtmfsrc->timestamp = gst_clock_get_time (clock) + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND); - - else { - GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", - GST_ELEMENT_NAME (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); } dtmfsrc->rtp_timestamp = dtmfsrc->ts_base + @@ -664,7 +674,7 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) { GstClock *clock; - clock = GST_ELEMENT_CLOCK (dtmfsrc); + clock = gst_element_get_clock (dtmfsrc); if (clock != NULL) { GstClockID clock_id; GstClockReturn clock_ret; @@ -672,15 +682,18 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); clock_ret = gst_clock_id_wait (clock_id, NULL); if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", - GST_ELEMENT_NAME (clock)); + gchar *clock_name = gst_element_get_name (clock); + GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); + g_free (clock_name); } gst_clock_id_unref (clock_id); + gst_object_unref (clock); } else { - GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", - GST_ELEMENT_NAME (dtmfsrc)); + gchar *dtmf_name = gst_element_get_name (dtmfsrc); + GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name); + g_free (dtmf_name); } } From e71056ff6a4dab5ed3e0bc41b6ad584df19d3eca Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Tue, 28 Aug 2007 22:15:34 +0000 Subject: [PATCH 015/138] [MOVED FROM GST-P-FARSIGHT] ClockID when waiting for buffer is now unscheduled when stopping the task. Various fixes to avoid bugs (thanks to -Wall -Werror). Fixes to allow the merge of the branch. 20070828221534-4f0f6-b0d6a4fe48c4e2a16b9ff69cb310087c970ce48e.gz --- gst/dtmf/gstdtmfsrc.c | 93 +++++++++++++++++++++------------------- gst/dtmf/gstdtmfsrc.h | 3 +- gst/dtmf/gstrtpdtmfsrc.c | 86 +++++++++++++++++++++---------------- gst/dtmf/gstrtpdtmfsrc.h | 3 +- 4 files changed, 104 insertions(+), 81 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 7befc5441c..1dd123f407 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -333,6 +333,8 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class) dtmfsrc->event_queue = g_async_queue_new (); dtmfsrc->last_event = NULL; + dtmfsrc->clock_id = NULL; + GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -405,7 +407,7 @@ gst_dtmf_src_handle_custom_upstream (GstDTMFSrc *dtmfsrc, GstState state; GstStateChangeReturn ret; - ret = gst_element_get_state (dtmfsrc, &state, NULL, 0); + 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; @@ -444,19 +446,6 @@ gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event) case GST_EVENT_FLUSH_STOP: gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); break; - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - gdouble rate; - GstFormat fmt; - gint64 start, stop, position; - - gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, - &stop, &position); - gst_segment_set_newsegment (&dtmfsrc->segment, update, rate, fmt, - start, stop, position); - } - /* fallthrough */ default: result = gst_pad_event_default (pad, event); break; @@ -523,7 +512,7 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) { GstClock *clock; - clock = gst_element_get_clock (dtmfsrc); + clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { dtmfsrc->timestamp = gst_clock_get_time (clock); gst_object_unref (clock); @@ -538,9 +527,9 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc) { - GstCaps * caps = gst_pad_get_pad_template_caps (dtmfsrc->srcpad); + const GstCaps * caps = gst_pad_get_pad_template_caps (dtmfsrc->srcpad); - if (!gst_pad_set_caps (dtmfsrc->srcpad, caps)) + if (!gst_pad_set_caps (dtmfsrc->srcpad, (GstCaps *)caps)) GST_ERROR_OBJECT (dtmfsrc, "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps); else @@ -557,21 +546,12 @@ gst_dtmf_src_start (GstDTMFSrc *dtmfsrc) static void gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) { - /* Don't forget to release the stream lock */ - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + GstDTMFSrcEvent *event = NULL; - - /* Flushing the event queue */ - GstDTMFSrcEvent *event = g_async_queue_try_pop (dtmfsrc->event_queue); - - while (event != NULL) { - g_free (event); - event = g_async_queue_try_pop (dtmfsrc->event_queue); - } - - if (dtmfsrc->last_event) { - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; + if (dtmfsrc->clock_id != NULL) { + gst_clock_id_unschedule(dtmfsrc->clock_id); + gst_clock_id_unref (dtmfsrc->clock_id); + dtmfsrc->clock_id = NULL; } if (!gst_pad_pause_task (dtmfsrc->srcpad)) { @@ -579,6 +559,21 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) return; } + if (dtmfsrc->last_event) { + /* Don't forget to release the stream lock */ + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } + + /* Flushing the event queue */ + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + while (event != NULL) { + g_free (event); + event = g_async_queue_try_pop (dtmfsrc->event_queue); + } + } static void @@ -672,23 +667,35 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) { GstClock *clock; - clock = gst_element_get_clock (dtmfsrc); + clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { - GstClockID clock_id; GstClockReturn clock_ret; - clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); - clock_ret = gst_clock_id_wait (clock_id, NULL); - if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { - gchar *clock_name = gst_element_get_name (clock); - GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); - g_free (clock_name); - } - gst_clock_id_unref (clock_id); + dtmfsrc->clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); gst_object_unref (clock); - } - else { + clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + if (clock_ret == GST_CLOCK_UNSCHEDULED) { + GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled"); + /* we don't free anything in case of an unscheduled, because it would be unscheduled + * by the stop function which will do the free itself. We can't handle it here + * in case we stop the task before the unref is done + */ + } else { + if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { + gchar *clock_name = NULL; + + clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); + clock_name = gst_element_get_name (clock); + gst_object_unref (clock); + + GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); + g_free (clock_name); + } + gst_clock_id_unref (dtmfsrc->clock_id); + dtmfsrc->clock_id = NULL; + } + } else { gchar *dtmf_name = gst_element_get_name (dtmfsrc); GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name); g_free (dtmf_name); diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 45f3a2a3c1..5a9427024f 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -50,7 +50,7 @@ typedef struct _GstDTMFSrcClass GstDTMFSrcClass; * The opaque #GstDTMFSrc data structure. */ -static enum _GstDTMFEventType { +enum _GstDTMFEventType { DTMF_EVENT_TYPE_START, DTMF_EVENT_TYPE_STOP }; @@ -73,6 +73,7 @@ struct _GstDTMFSrc { GstSegment segment; GAsyncQueue* event_queue; GstDTMFSrcEvent* last_event; + GstClockID clock_id; guint16 interval; GstClockTime timestamp; diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 3115d5428d..c2a6d1f2b3 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -342,6 +342,7 @@ gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class) dtmfsrc->event_queue = g_async_queue_new (); dtmfsrc->last_event = NULL; + dtmfsrc->clock_id = NULL; GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -351,13 +352,13 @@ 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; } - dtmfsrc = GST_RTP_DTMF_SRC (object); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -415,7 +416,7 @@ gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc, GstState state; GstStateChangeReturn ret; - ret = gst_element_get_state (dtmfsrc, &state, NULL, 0); + 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; @@ -439,7 +440,7 @@ gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event) GstRTPDTMFSrc *dtmfsrc; gboolean result = FALSE; GstElement *parent = gst_pad_get_parent_element (pad); - dtmfsrc = GST_DTMF_SRC (parent); + dtmfsrc = GST_RTP_DTMF_SRC (parent); GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); @@ -458,19 +459,6 @@ gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event) case GST_EVENT_FLUSH_STOP: gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); break; - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - gdouble rate; - GstFormat fmt; - gint64 start, stop, position; - - gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, - &stop, &position); - gst_segment_set_newsegment (&dtmfsrc->segment, update, rate, fmt, - start, stop, position); - } - /* fallthrough */ default: result = gst_pad_event_default (pad, event); break; @@ -582,7 +570,7 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) { GstClock *clock; - clock = gst_element_get_clock (dtmfsrc); + clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { dtmfsrc->timestamp = gst_clock_get_time (clock) + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND); @@ -615,12 +603,29 @@ gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc) static void gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) { - /* Don't forget to release the stream lock */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + GstRTPDTMFSrcEvent *event = NULL; + + if (dtmfsrc->clock_id != NULL) { + gst_clock_id_unschedule(dtmfsrc->clock_id); + gst_clock_id_unref (dtmfsrc->clock_id); + dtmfsrc->clock_id = NULL; + } + + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { + GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); + return; + } + + if (dtmfsrc->last_event) { + /* Don't forget to release the stream lock */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } /* Flushing the event queue */ - GstRTPDTMFSrcEvent *event = g_async_queue_try_pop (dtmfsrc->event_queue); + event = g_async_queue_try_pop (dtmfsrc->event_queue); while (event != NULL) { g_free (event); @@ -632,10 +637,6 @@ gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->last_event = NULL; } - if (!gst_pad_pause_task (dtmfsrc->srcpad)) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); - return; - } } @@ -674,20 +675,33 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) { GstClock *clock; - clock = gst_element_get_clock (dtmfsrc); + clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { - GstClockID clock_id; GstClockReturn clock_ret; - clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); - clock_ret = gst_clock_id_wait (clock_id, NULL); - if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { - gchar *clock_name = gst_element_get_name (clock); - GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); - g_free (clock_name); - } - gst_clock_id_unref (clock_id); + dtmfsrc->clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); gst_object_unref (clock); + + clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + if (clock_ret == GST_CLOCK_UNSCHEDULED) { + GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled"); + /* we don't free anything in case of an unscheduled, because it would be unscheduled + * by the stop function which will do the free itself. We can't handle it here + * in case we stop the task before the unref is done + */ + } else { + if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { + gchar *clock_name = NULL; + + clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); + clock_name = gst_element_get_name (clock); + gst_object_unref (clock); + + GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); + g_free (clock_name); + } + gst_clock_id_unref (dtmfsrc->clock_id); + } } else { @@ -854,14 +868,14 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) gst_buffer_unref(buf); GST_DEBUG_OBJECT (dtmfsrc, - "pushed DTMF event '%d' on src pad", event->payload->event); + "pushed DTMF event '%d' on src pad", dtmfsrc->last_event->payload->event); if (dtmfsrc->last_event->payload->e) { /* Don't forget to release the stream lock */ gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); g_free (dtmfsrc->last_event->payload); - event->payload = NULL; + dtmfsrc->last_event->payload = NULL; g_free (dtmfsrc->last_event); dtmfsrc->last_event = NULL; diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 2bbfb9db88..c5e2b11b6c 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -59,7 +59,7 @@ typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass; -static enum _GstRTPDTMFEventType { +enum _GstRTPDTMFEventType { RTP_DTMF_EVENT_TYPE_START, RTP_DTMF_EVENT_TYPE_STOP }; @@ -87,6 +87,7 @@ struct _GstRTPDTMFSrc { GstSegment segment; GAsyncQueue* event_queue; GstRTPDTMFSrcEvent* last_event; + GstClockID clock_id; GstClockTime timestamp; gboolean first_packet; From ab95b70fdfa9197bb491dab80e7e832c85c60f29 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Fri, 31 Aug 2007 23:44:13 +0000 Subject: [PATCH 016/138] [MOVED FROM GST-P-FARSIGHT] Fixes the deadlock when pausing the dtmfsrc and rtpdtmfsrc. Had to push something on the async queue to release the blocking async_queue_pop(). Thanks to Olivier for the solution. 20070831234413-4f0f6-793cf35fc43636e7275258cc7063fc068f5efa0a.gz --- gst/dtmf/gstdtmfsrc.c | 14 ++++++++++++++ gst/dtmf/gstdtmfsrc.h | 3 ++- gst/dtmf/gstrtpdtmfsrc.c | 17 +++++++++++++---- gst/dtmf/gstrtpdtmfsrc.h | 3 ++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 1dd123f407..0c13775307 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -554,6 +554,16 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) dtmfsrc->clock_id = NULL; } + + + g_async_queue_lock (dtmfsrc->event_queue); + event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); + event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; + g_async_queue_push_unlocked (dtmfsrc->event_queue, event); + g_async_queue_unlock (dtmfsrc->event_queue); + + event = NULL; + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); return; @@ -768,6 +778,10 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event->packet_count = 0; dtmfsrc->last_event = event; + } else if (event->event_type == RTP_DTMF_EVENT_TYPE_PAUSE_TASK) { + g_free (event); + g_async_queue_unref (dtmfsrc->event_queue); + return; } } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 5a9427024f..15a16758ed 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -52,7 +52,8 @@ typedef struct _GstDTMFSrcClass GstDTMFSrcClass; enum _GstDTMFEventType { DTMF_EVENT_TYPE_START, - DTMF_EVENT_TYPE_STOP + DTMF_EVENT_TYPE_STOP, + DTMF_EVENT_TYPE_PAUSE_TASK }; typedef enum _GstDTMFEventType GstDTMFEventType; diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index c2a6d1f2b3..ff3f05b4f6 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -612,11 +612,20 @@ gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->clock_id = NULL; } + g_async_queue_lock (dtmfsrc->event_queue); + event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); + event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; + g_async_queue_push_unlocked (dtmfsrc->event_queue, event); + g_async_queue_unlock (dtmfsrc->event_queue); + + event = NULL; + if (!gst_pad_pause_task (dtmfsrc->srcpad)) { GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); return; } + if (dtmfsrc->last_event) { /* Don't forget to release the stream lock */ gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); @@ -632,10 +641,6 @@ gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) event = g_async_queue_try_pop (dtmfsrc->event_queue); } - if (dtmfsrc->last_event) { - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - } } @@ -813,6 +818,10 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) event->sent_packets = 0; dtmfsrc->last_event = event; + } else if (event->event_type == RTP_DTMF_EVENT_TYPE_PAUSE_TASK) { + g_free (event); + g_async_queue_unref (dtmfsrc->event_queue); + return; } } else if (dtmfsrc->last_event->sent_packets * dtmfsrc->interval >= MIN_PULSE_DURATION){ diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index c5e2b11b6c..66225baca9 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -61,7 +61,8 @@ typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass; enum _GstRTPDTMFEventType { RTP_DTMF_EVENT_TYPE_START, - RTP_DTMF_EVENT_TYPE_STOP + RTP_DTMF_EVENT_TYPE_STOP, + RTP_DTMF_EVENT_TYPE_PAUSE_TASK }; typedef enum _GstRTPDTMFEventType GstRTPDTMFEventType; From 2554a342081b6577882ccad987f0ae2f99baabcb Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Fri, 31 Aug 2007 23:54:28 +0000 Subject: [PATCH 017/138] [MOVED FROM GST-P-FARSIGHT] oups, sorry.. DTMF, not RTP_DTMF for this file... 20070831235428-4f0f6-00b606bfb4892e4f217c440b611cc794ab0de55a.gz --- gst/dtmf/gstdtmfsrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 0c13775307..884026c15a 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -557,8 +557,8 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) g_async_queue_lock (dtmfsrc->event_queue); - event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); - event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; + event = g_malloc (sizeof(GstDTMFSrcEvent)); + event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push_unlocked (dtmfsrc->event_queue, event); g_async_queue_unlock (dtmfsrc->event_queue); From bd1d78312d92bbe089b185df957d120874fe238b Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Sat, 1 Sep 2007 00:03:24 +0000 Subject: [PATCH 018/138] [MOVED FROM GST-P-FARSIGHT] oups, I did it again... 20070901000324-4f0f6-3d8b46691ee520537b06c511a5e732f5b812b844.gz --- gst/dtmf/gstdtmfsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 884026c15a..6a1a830b2f 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -778,7 +778,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event->packet_count = 0; dtmfsrc->last_event = event; - } else if (event->event_type == RTP_DTMF_EVENT_TYPE_PAUSE_TASK) { + } else if (event->event_type == DTMF_EVENT_TYPE_PAUSE_TASK) { g_free (event); g_async_queue_unref (dtmfsrc->event_queue); return; From 71cd3422fdaa6a9dcfaaf0256cf9113648065fee Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Tue, 4 Sep 2007 20:55:09 +0000 Subject: [PATCH 019/138] [MOVED FROM GST-P-FARSIGHT] Properly do the locking to avoid race conditions with clock unscheduling 20070904205509-3e2dc-da19900b51af6aedb6547f4f392bef4d1061dec2.gz --- gst/dtmf/gstdtmfsrc.c | 30 +++++++++++++++--------------- gst/dtmf/gstrtpdtmfsrc.c | 32 ++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 6a1a830b2f..0232b723cc 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -548,19 +548,15 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) { GstDTMFSrcEvent *event = NULL; + GST_OBJECT_LOCK (dtmfsrc); if (dtmfsrc->clock_id != NULL) { gst_clock_id_unschedule(dtmfsrc->clock_id); - gst_clock_id_unref (dtmfsrc->clock_id); - dtmfsrc->clock_id = NULL; } + GST_OBJECT_UNLOCK (dtmfsrc); - - - g_async_queue_lock (dtmfsrc->event_queue); event = g_malloc (sizeof(GstDTMFSrcEvent)); event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; - g_async_queue_push_unlocked (dtmfsrc->event_queue, event); - g_async_queue_unlock (dtmfsrc->event_queue); + g_async_queue_push (dtmfsrc->event_queue, event); event = NULL; @@ -680,17 +676,23 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { GstClockReturn clock_ret; + GstClockID clock_id; - dtmfsrc->clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); + clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); gst_object_unref (clock); + GST_OBJECT_LOCK (dtmfsrc); + dtmfsrc->clock_id = clock_id; + GST_OBJECT_UNLOCK (dtmfsrc); clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + + GST_OBJECT_LOCK (dtmfsrc); + dtmfsrc->clock_id = NULL; + gst_clock_id_unref (clock_id); + GST_OBJECT_UNLOCK (dtmfsrc); + if (clock_ret == GST_CLOCK_UNSCHEDULED) { GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled"); - /* we don't free anything in case of an unscheduled, because it would be unscheduled - * by the stop function which will do the free itself. We can't handle it here - * in case we stop the task before the unref is done - */ } else { if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { gchar *clock_name = NULL; @@ -702,8 +704,6 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); g_free (clock_name); } - gst_clock_id_unref (dtmfsrc->clock_id); - dtmfsrc->clock_id = NULL; } } else { gchar *dtmf_name = gst_element_get_name (dtmfsrc); @@ -779,7 +779,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event->packet_count = 0; dtmfsrc->last_event = event; } else if (event->event_type == DTMF_EVENT_TYPE_PAUSE_TASK) { - g_free (event); + g_async_queue_push (dtmfsrc->event_queue, event); g_async_queue_unref (dtmfsrc->event_queue); return; } diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ff3f05b4f6..ba061f6274 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -606,17 +606,15 @@ gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) GstRTPDTMFSrcEvent *event = NULL; + GST_OBJECT_LOCK (dtmfsrc); if (dtmfsrc->clock_id != NULL) { gst_clock_id_unschedule(dtmfsrc->clock_id); - gst_clock_id_unref (dtmfsrc->clock_id); - dtmfsrc->clock_id = NULL; } + GST_OBJECT_UNLOCK (dtmfsrc); - g_async_queue_lock (dtmfsrc->event_queue); event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; - g_async_queue_push_unlocked (dtmfsrc->event_queue, event); - g_async_queue_unlock (dtmfsrc->event_queue); + g_async_queue_push (dtmfsrc->event_queue, event); event = NULL; @@ -683,17 +681,24 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { GstClockReturn clock_ret; + GstClockID clock_id; - dtmfsrc->clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); + clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); gst_object_unref (clock); + GST_OBJECT_LOCK (dtmfsrc); + dtmfsrc->clock_id = clock_id; + GST_OBJECT_UNLOCK (dtmfsrc); + clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + + GST_OBJECT_LOCK (dtmfsrc); + dtmfsrc->clock_id = NULL; + gst_clock_id_unref (clock_id); + GST_OBJECT_UNLOCK (dtmfsrc); + if (clock_ret == GST_CLOCK_UNSCHEDULED) { GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled"); - /* we don't free anything in case of an unscheduled, because it would be unscheduled - * by the stop function which will do the free itself. We can't handle it here - * in case we stop the task before the unref is done - */ } else { if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { gchar *clock_name = NULL; @@ -705,7 +710,6 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); g_free (clock_name); } - gst_clock_id_unref (dtmfsrc->clock_id); } } @@ -819,7 +823,11 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->last_event = event; } else if (event->event_type == RTP_DTMF_EVENT_TYPE_PAUSE_TASK) { - g_free (event); + /* + * 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 + */ + g_async_queue_push (dtmfsrc->event_queue, event); g_async_queue_unref (dtmfsrc->event_queue); return; } From f6652f2ef99b3fe5988610c45e2e32f0508e8768 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Tue, 4 Sep 2007 21:52:24 +0000 Subject: [PATCH 020/138] [MOVED FROM GST-P-FARSIGHT] Add comment to explain push back 20070904215224-3e2dc-d92ac1f403dcf571546a7c53f18809f840eea51d.gz --- gst/dtmf/gstdtmfsrc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 0232b723cc..7f22482057 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -779,6 +779,10 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) event->packet_count = 0; dtmfsrc->last_event = event; } else if (event->event_type == 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 + */ g_async_queue_push (dtmfsrc->event_queue, event); g_async_queue_unref (dtmfsrc->event_queue); return; From da9d38b487bc7ea52816cf7d1d4f53dff07a52c3 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Tue, 4 Sep 2007 22:57:53 +0000 Subject: [PATCH 021/138] [MOVED FROM GST-P-FARSIGHT] Add another fix for a possible race condition 20070904225753-4f0f6-5ba8c4260c002bb27eb98e9faba3c15799357b57.gz --- gst/dtmf/gstdtmfsrc.c | 11 +++++++++-- gst/dtmf/gstdtmfsrc.h | 1 + gst/dtmf/gstrtpdtmfsrc.c | 10 ++++++++-- gst/dtmf/gstrtpdtmfsrc.h | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 7f22482057..94987de881 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -334,6 +334,7 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class) dtmfsrc->last_event = NULL; dtmfsrc->clock_id = NULL; + dtmfsrc->task_paused = TRUE; GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -536,7 +537,7 @@ gst_dtmf_src_start (GstDTMFSrc *dtmfsrc) GST_DEBUG_OBJECT (dtmfsrc, "caps %" GST_PTR_FORMAT " set on src pad", caps); - + dtmfsrc->task_paused = FALSE; if (!gst_pad_start_task (dtmfsrc->srcpad, (GstTaskFunction) gst_dtmf_src_push_next_tone_packet, dtmfsrc)) { GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); @@ -548,6 +549,7 @@ gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) { GstDTMFSrcEvent *event = NULL; + dtmfsrc->task_paused = TRUE; GST_OBJECT_LOCK (dtmfsrc); if (dtmfsrc->clock_id != NULL) { gst_clock_id_unschedule(dtmfsrc->clock_id); @@ -684,7 +686,12 @@ gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) GST_OBJECT_LOCK (dtmfsrc); dtmfsrc->clock_id = clock_id; GST_OBJECT_UNLOCK (dtmfsrc); - clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + + if (dtmfsrc->task_paused) { + clock_ret = GST_CLOCK_UNSCHEDULED; + } else { + clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + } GST_OBJECT_LOCK (dtmfsrc); dtmfsrc->clock_id = NULL; diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 15a16758ed..27e91a0021 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -75,6 +75,7 @@ struct _GstDTMFSrc { GAsyncQueue* event_queue; GstDTMFSrcEvent* last_event; GstClockID clock_id; + gboolean task_paused; guint16 interval; GstClockTime timestamp; diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ba061f6274..1a03da66ae 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -338,7 +338,7 @@ gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class) dtmfsrc->clock_rate = DEFAULT_CLOCK_RATE; dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; dtmfsrc->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; - + dtmfsrc->task_paused = TRUE; dtmfsrc->event_queue = g_async_queue_new (); dtmfsrc->last_event = NULL; @@ -594,6 +594,7 @@ gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc) { gst_rtp_dtmf_src_set_caps (dtmfsrc); + dtmfsrc->task_paused = FALSE; if (!gst_pad_start_task (dtmfsrc->srcpad, (GstTaskFunction) gst_rtp_dtmf_src_push_next_rtp_packet, dtmfsrc)) { GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); @@ -606,6 +607,7 @@ gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) GstRTPDTMFSrcEvent *event = NULL; + dtmfsrc->task_paused = TRUE; GST_OBJECT_LOCK (dtmfsrc); if (dtmfsrc->clock_id != NULL) { gst_clock_id_unschedule(dtmfsrc->clock_id); @@ -690,7 +692,11 @@ gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) dtmfsrc->clock_id = clock_id; GST_OBJECT_UNLOCK (dtmfsrc); - clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + if (dtmfsrc->task_paused) { + clock_ret = GST_CLOCK_UNSCHEDULED; + } else { + clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); + } GST_OBJECT_LOCK (dtmfsrc); dtmfsrc->clock_id = NULL; diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 66225baca9..895115088f 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -89,6 +89,7 @@ struct _GstRTPDTMFSrc { GAsyncQueue* event_queue; GstRTPDTMFSrcEvent* last_event; GstClockID clock_id; + gboolean task_paused; GstClockTime timestamp; gboolean first_packet; From 1ab6c9c1ea1de329c7fa81830bbb7853507ef875 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 13 Sep 2007 17:55:20 +0000 Subject: [PATCH 022/138] [MOVED FROM GST-P-FARSIGHT] Changed dtmfsrc into a subclass of GstBaseSrc 20070913175520-4f0f6-16ca4bf93690072f3e836d1c8a5b52cf7a421916.gz --- gst/dtmf/gstdtmfsrc.c | 299 +++++++++++++----------------------------- gst/dtmf/gstdtmfsrc.h | 7 +- 2 files changed, 94 insertions(+), 212 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 94987de881..f642558737 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -231,53 +231,30 @@ GST_STATIC_PAD_TEMPLATE ("src", "channels = (int) 1") ); -static GstElementClass *parent_class = NULL; +GST_BOILERPLATE (GstDTMFSrc, gst_dtmf_src, GstBaseSrc, GST_TYPE_BASE_SRC); -static void gst_dtmf_src_base_init (gpointer g_class); -static void gst_dtmf_src_class_init (GstDTMFSrcClass * klass); -static void gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class); static void gst_dtmf_src_finalize (GObject * object); -GType -gst_dtmf_src_get_type (void) -{ - static GType base_src_type = 0; - - if (G_UNLIKELY (base_src_type == 0)) { - static const GTypeInfo base_src_info = { - sizeof (GstDTMFSrcClass), - (GBaseInitFunc) gst_dtmf_src_base_init, - NULL, - (GClassInitFunc) gst_dtmf_src_class_init, - NULL, - NULL, - sizeof (GstDTMFSrc), - 0, - (GInstanceInitFunc) gst_dtmf_src_init, - }; - - base_src_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstDTMFSrc", &base_src_info, 0); - } - return base_src_type; -} - 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 (GstPad * pad, GstEvent * event); +static gboolean gst_dtmf_src_handle_event (GstBaseSrc *src, GstEvent * event); static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition); static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, GstBuffer * buffer); -static void gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc); -static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc); -static void gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc); +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 void gst_dtmf_src_get_times (GstBaseSrc * basesrc, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); + + + static void gst_dtmf_src_base_init (gpointer g_class) { @@ -296,12 +273,13 @@ 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); - parent_class = g_type_class_peek_parent (klass); gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_dtmf_src_finalize); gobject_class->set_property = @@ -316,17 +294,22 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state); + + gstbasesrc_class->event = + GST_DEBUG_FUNCPTR (gst_dtmf_src_handle_event); + gstbasesrc_class->get_times = + GST_DEBUG_FUNCPTR (gst_dtmf_src_get_times); + gstbasesrc_class->create = + GST_DEBUG_FUNCPTR (gst_dtmf_src_create); } -static void -gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class) -{ - dtmfsrc->srcpad = - gst_pad_new_from_static_template (&gst_dtmf_src_template, "src"); - GST_DEBUG_OBJECT (dtmfsrc, "adding src pad"); - gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad); - gst_pad_set_event_function (dtmfsrc->srcpad, gst_dtmf_src_handle_event); +static void +gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass *g_class) +{ + /* 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; @@ -334,7 +317,6 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class) dtmfsrc->last_event = NULL; dtmfsrc->clock_id = NULL; - dtmfsrc->task_paused = TRUE; GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -346,9 +328,6 @@ gst_dtmf_src_finalize (GObject * object) dtmfsrc = GST_DTMF_SRC (object); - - gst_dtmf_src_stop (dtmfsrc); - if (dtmfsrc->event_queue) { g_async_queue_unref (dtmfsrc->event_queue); dtmfsrc->event_queue = NULL; @@ -424,36 +403,18 @@ ret: } static gboolean -gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event) +gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event) { GstDTMFSrc *dtmfsrc; gboolean result = FALSE; - GstElement *parent = gst_pad_get_parent_element (pad); - dtmfsrc = GST_DTMF_SRC (parent); + + dtmfsrc = GST_DTMF_SRC (src); GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CUSTOM_UPSTREAM: - { - result = gst_dtmf_src_handle_custom_upstream (dtmfsrc, event); - break; - } - /* Ideally this element should not be flushed but let's handle the event - * just in case it is */ - case GST_EVENT_FLUSH_START: - gst_dtmf_src_stop (dtmfsrc); - result = TRUE; - break; - case GST_EVENT_FLUSH_STOP: - gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); - break; - default: - result = gst_pad_event_default (pad, event); - break; + if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) { + result = gst_dtmf_src_handle_custom_upstream (dtmfsrc, event); } - gst_object_unref (parent); - gst_event_unref (event); return result; } @@ -496,6 +457,7 @@ gst_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, static void gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) { + GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); GstEvent *event; GstStructure *structure; @@ -503,7 +465,7 @@ gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) "lock", G_TYPE_BOOLEAN, lock, NULL); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - if (!gst_pad_push_event (dtmfsrc->srcpad, event)) { + if (!gst_pad_push_event (srcpad, event)) { GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); } } @@ -512,10 +474,13 @@ static void gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) { GstClock *clock; + GstClockTime base_time; + + base_time = GST_ELEMENT_CAST (dtmfsrc)->base_time; clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { - dtmfsrc->timestamp = gst_clock_get_time (clock); + dtmfsrc->timestamp = gst_clock_get_time (clock) - base_time; gst_object_unref (clock); } else { gchar *dtmf_name = gst_element_get_name (dtmfsrc); @@ -525,65 +490,6 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) } } -static void -gst_dtmf_src_start (GstDTMFSrc *dtmfsrc) -{ - const GstCaps * caps = gst_pad_get_pad_template_caps (dtmfsrc->srcpad); - - if (!gst_pad_set_caps (dtmfsrc->srcpad, (GstCaps *)caps)) - GST_ERROR_OBJECT (dtmfsrc, - "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps); - else - GST_DEBUG_OBJECT (dtmfsrc, - "caps %" GST_PTR_FORMAT " set on src pad", caps); - - dtmfsrc->task_paused = FALSE; - if (!gst_pad_start_task (dtmfsrc->srcpad, - (GstTaskFunction) gst_dtmf_src_push_next_tone_packet, dtmfsrc)) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); - } -} - -static void -gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc) -{ - GstDTMFSrcEvent *event = NULL; - - dtmfsrc->task_paused = TRUE; - GST_OBJECT_LOCK (dtmfsrc); - if (dtmfsrc->clock_id != NULL) { - gst_clock_id_unschedule(dtmfsrc->clock_id); - } - GST_OBJECT_UNLOCK (dtmfsrc); - - event = g_malloc (sizeof(GstDTMFSrcEvent)); - event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; - g_async_queue_push (dtmfsrc->event_queue, event); - - event = NULL; - - if (!gst_pad_pause_task (dtmfsrc->srcpad)) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); - return; - } - - if (dtmfsrc->last_event) { - /* Don't forget to release the stream lock */ - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - } - - /* Flushing the event queue */ - event = g_async_queue_try_pop (dtmfsrc->event_queue); - - while (event != NULL) { - g_free (event); - event = g_async_queue_try_pop (dtmfsrc->event_queue); - } - -} - static void gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, gint event_number, gint event_volume) @@ -671,51 +577,25 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, } static void -gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf) +gst_dtmf_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) { - GstClock *clock; + /* for live sources, sync on the timestamp of the buffer */ + if (gst_base_src_is_live (basesrc)) { + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); - clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - if (clock != NULL) { - GstClockReturn clock_ret; - GstClockID clock_id; + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + GstClockTime duration = GST_BUFFER_DURATION (buffer); - clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); - gst_object_unref (clock); - - GST_OBJECT_LOCK (dtmfsrc); - dtmfsrc->clock_id = clock_id; - GST_OBJECT_UNLOCK (dtmfsrc); - - if (dtmfsrc->task_paused) { - clock_ret = GST_CLOCK_UNSCHEDULED; - } else { - clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); - } - - GST_OBJECT_LOCK (dtmfsrc); - dtmfsrc->clock_id = NULL; - gst_clock_id_unref (clock_id); - GST_OBJECT_UNLOCK (dtmfsrc); - - if (clock_ret == GST_CLOCK_UNSCHEDULED) { - GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled"); - } else { - if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { - gchar *clock_name = NULL; - - clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - clock_name = gst_element_get_name (clock); - gst_object_unref (clock); - - GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); - g_free (clock_name); + *start = timestamp; + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = *start + duration; } } } else { - gchar *dtmf_name = gst_element_get_name (dtmfsrc); - GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name); - g_free (dtmf_name); + *start = -1; + *end = -1; } } @@ -726,6 +606,7 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, { GstBuffer *buf = NULL; gboolean send_silence = FALSE; + GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); GST_DEBUG_OBJECT (dtmfsrc, "Creating buffer for tone %s", DTMF_KEYS[event->event_number].event_name); @@ -753,24 +634,26 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); - /* FIXME: Should we sync to clock ourselves or leave it to sink */ - gst_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); - /* Set caps on the buffer before pushing it */ - gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad)); + gst_buffer_set_caps (buf, GST_PAD_CAPS (srcpad)); return buf; } -static void -gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) +static GstFlowReturn +gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, + guint length, GstBuffer ** buffer) { GstBuffer *buf = NULL; GstFlowReturn ret; GstDTMFSrcEvent *event; + GstDTMFSrc * dtmfsrc; + + dtmfsrc = GST_DTMF_SRC (basesrc); g_async_queue_ref (dtmfsrc->event_queue); + start: if (dtmfsrc->last_event == NULL) { event = g_async_queue_pop (dtmfsrc->event_queue); @@ -788,11 +671,10 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) } else if (event->event_type == 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 + * the task is really paused (and the queue will then be flushed) */ g_async_queue_push (dtmfsrc->event_queue, event); g_async_queue_unref (dtmfsrc->event_queue); - return; } } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { @@ -806,6 +688,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); g_free (dtmfsrc->last_event); dtmfsrc->last_event = NULL; + goto start; } } } @@ -814,19 +697,16 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc) if (dtmfsrc->last_event) { buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); - gst_buffer_ref(buf); - - GST_DEBUG_OBJECT (dtmfsrc, - "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf)); - ret = gst_pad_push (dtmfsrc->srcpad, buf); - if (ret != GST_FLOW_OK) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad"); - } - - gst_buffer_unref(buf); - GST_DEBUG_OBJECT (dtmfsrc, "pushed DTMF tone on src pad"); + GST_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf)); + *buffer = buf; + ret = GST_FLOW_OK; + } else { + *buffer = NULL; + ret = GST_FLOW_WRONG_STATE; } + return ret; + } static GstStateChangeReturn @@ -838,23 +718,6 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) dtmfsrc = GST_DTMF_SRC (element); - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME); - gst_pad_push_event (dtmfsrc->srcpad, gst_event_new_new_segment (FALSE, - dtmfsrc->segment.rate, dtmfsrc->segment.format, - dtmfsrc->segment.start, dtmfsrc->segment.stop, - dtmfsrc->segment.time)); - /* Indicate that we don't do PRE_ROLL */ - no_preroll = TRUE; - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - gst_dtmf_src_start (dtmfsrc); - break; - default: - break; - } - if ((result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition)) == GST_STATE_CHANGE_FAILURE) @@ -862,10 +725,30 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - /* Indicate that we don't do PRE_ROLL */ - gst_dtmf_src_stop (dtmfsrc); - no_preroll = TRUE; - break; + { + GstDTMFSrcEvent *event = NULL; + + /* TODO lock the element */ + + if (dtmfsrc->last_event) { + /* Don't forget to release the stream lock */ + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } + + /* Flushing the event queue */ + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + while (event != NULL) { + g_free (event); + event = g_async_queue_try_pop (dtmfsrc->event_queue); + } + + /* Indicate that we don't do PRE_ROLL */ + no_preroll = TRUE; + break; + } default: break; } diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 27e91a0021..1ca44643ce 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -29,6 +29,7 @@ #include #include +#include G_BEGIN_DECLS @@ -69,9 +70,7 @@ struct _GstDTMFSrcEvent { typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent; struct _GstDTMFSrc { - GstElement element; - GstPad *srcpad; - GstSegment segment; + GstBaseSrc parent; GAsyncQueue* event_queue; GstDTMFSrcEvent* last_event; GstClockID clock_id; @@ -83,7 +82,7 @@ struct _GstDTMFSrc { struct _GstDTMFSrcClass { - GstElementClass parent_class; + GstBaseSrcClass parent_class; }; GType gst_dtmf_src_get_type (void); From de61d9c5337d3e0fd2cffbdb2ff39c7e11c299d0 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 13 Sep 2007 19:20:53 +0000 Subject: [PATCH 023/138] [MOVED FROM GST-P-FARSIGHT] Make sure to unlock the thread when going to ready and to flush the queue when moving to paused or playing 20070913192053-4f0f6-76c3925380d1a30988286170535a65dea64a5583.gz --- gst/dtmf/gstdtmfsrc.c | 62 +++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index f642558737..06fc50278d 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -715,9 +715,25 @@ 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: + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + /* Flushing the event queue */ + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + while (event != NULL) { + g_free (event); + event = g_async_queue_try_pop (dtmfsrc->event_queue); + } + break; + default: + break; + } + if ((result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition)) == GST_STATE_CHANGE_FAILURE) @@ -725,30 +741,30 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - { - GstDTMFSrcEvent *event = NULL; - - /* TODO lock the element */ - - if (dtmfsrc->last_event) { - /* Don't forget to release the stream lock */ - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - } - - /* Flushing the event queue */ - event = g_async_queue_try_pop (dtmfsrc->event_queue); - - while (event != NULL) { - g_free (event); - event = g_async_queue_try_pop (dtmfsrc->event_queue); - } - - /* Indicate that we don't do PRE_ROLL */ - no_preroll = TRUE; - break; + if (dtmfsrc->last_event) { + /* Don't forget to release the stream lock */ + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; } + + /* Flushing the event queue */ + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + while (event != NULL) { + g_free (event); + event = g_async_queue_try_pop (dtmfsrc->event_queue); + } + + /* Indicate that we don't do PRE_ROLL */ + no_preroll = TRUE; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + event = g_malloc (sizeof(GstDTMFSrcEvent)); + event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; + g_async_queue_push (dtmfsrc->event_queue, event); + + event = NULL; default: break; } From 1265489b59f0f1450ae74f34408795ad380b3881 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 13 Sep 2007 20:46:14 +0000 Subject: [PATCH 024/138] [MOVED FROM GST-P-FARSIGHT] added debugs 20070913204614-4f0f6-68c2a69ae7a1efca6e13c116dbad7f9b686f0242.gz --- gst/dtmf/gstdtmfsrc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 06fc50278d..9dca9a4909 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -655,8 +655,11 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, start: 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); + if (event->event_type == DTMF_EVENT_TYPE_STOP) { GST_WARNING_OBJECT (dtmfsrc, "Received a DTMF stop event when already stopped"); @@ -673,6 +676,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, * 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..."); g_async_queue_push (dtmfsrc->event_queue, event); g_async_queue_unref (dtmfsrc->event_queue); } @@ -689,11 +693,21 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, g_free (dtmfsrc->last_event); dtmfsrc->last_event = NULL; goto start; + } else if (event->event_type == 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..."); + g_async_queue_push (dtmfsrc->event_queue, event); + g_async_queue_unref (dtmfsrc->event_queue); } } } g_async_queue_unref (dtmfsrc->event_queue); + GST_DEBUG_OBJECT (dtmfsrc, "end event check"); + if (dtmfsrc->last_event) { buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); @@ -705,6 +719,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, ret = GST_FLOW_WRONG_STATE; } + GST_DEBUG_OBJECT (dtmfsrc, "returning"); return ret; } From 1b38cedd809d432849aa66af676c95d55b5e6bf9 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 13 Sep 2007 21:12:26 +0000 Subject: [PATCH 025/138] [MOVED FROM GST-P-FARSIGHT] more debug 20070913211226-4f0f6-bc32b5828fc8e0323c8a6eee779a38145aacd593.gz --- gst/dtmf/gstdtmfsrc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 9dca9a4909..a6cbabec15 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -775,6 +775,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) no_preroll = TRUE; break; case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK even on PAUSED_TO_READY change"); event = g_malloc (sizeof(GstDTMFSrcEvent)); event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); From 7c7d210fd09cbe3f316e2112811349bdd70d31c5 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 13 Sep 2007 21:21:45 +0000 Subject: [PATCH 026/138] [MOVED FROM GST-P-FARSIGHT] using the unlock method of basesrc 20070913212145-4f0f6-0e438a681bf1651c0cc0d8fa3269aed3f1668b6b.gz --- gst/dtmf/gstdtmfsrc.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index a6cbabec15..23803e0152 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -253,6 +253,7 @@ static void gst_dtmf_src_add_stop_event (GstDTMFSrc *dtmfsrc); static void gst_dtmf_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static gboolean gst_dtmf_src_unlock (GstBaseSrc *src); static void @@ -294,6 +295,8 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state); + gstbasesrc_class->unlock = + GST_DEBUG_FUNCPTR (gst_dtmf_src_unlock); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_dtmf_src_handle_event); @@ -301,6 +304,7 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) GST_DEBUG_FUNCPTR (gst_dtmf_src_get_times); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_dtmf_src_create); + } @@ -724,6 +728,19 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, } +static gboolean +gst_dtmf_src_unlock (GstBaseSrc *src) { + GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (src); + GstDTMFSrcEvent *event = NULL; + + GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK even on PAUSED_TO_READY change"); + event = g_malloc (sizeof(GstDTMFSrcEvent)); + event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; + g_async_queue_push (dtmfsrc->event_queue, event); + + return TRUE; +} + static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) { @@ -756,13 +773,17 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_DEBUG_OBJECT (dtmfsrc, "PLAYING TO PAUSED"); + if (dtmfsrc->last_event) { + GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event"); /* Don't forget to release the stream lock */ gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); g_free (dtmfsrc->last_event); dtmfsrc->last_event = NULL; } + GST_DEBUG_OBJECT (dtmfsrc, "Flushing event queue"); /* Flushing the event queue */ event = g_async_queue_try_pop (dtmfsrc->event_queue); @@ -774,13 +795,6 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) /* Indicate that we don't do PRE_ROLL */ no_preroll = TRUE; break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK even on PAUSED_TO_READY change"); - event = g_malloc (sizeof(GstDTMFSrcEvent)); - event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; - g_async_queue_push (dtmfsrc->event_queue, event); - - event = NULL; default: break; } From 37c9187fd4bf59d466ca08bb615bab45ab048643 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Fri, 14 Sep 2007 04:18:34 +0000 Subject: [PATCH 027/138] [MOVED FROM GST-P-FARSIGHT] Remove get_times (Wim says its only good for really fake sources) 20070914041834-3e2dc-fff4d5da2a145f19e7b610a1027d2c4d4bc5eae0.gz --- gst/dtmf/gstdtmfsrc.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 23803e0152..8c373ea3ef 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -250,9 +250,6 @@ 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 void gst_dtmf_src_get_times (GstBaseSrc * basesrc, - GstBuffer * buffer, GstClockTime * start, GstClockTime * end); - static gboolean gst_dtmf_src_unlock (GstBaseSrc *src); @@ -300,8 +297,6 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_dtmf_src_handle_event); - gstbasesrc_class->get_times = - GST_DEBUG_FUNCPTR (gst_dtmf_src_get_times); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_dtmf_src_create); @@ -580,28 +575,6 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, } } -static void -gst_dtmf_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, - GstClockTime * start, GstClockTime * end) -{ - /* for live sources, sync on the timestamp of the buffer */ - if (gst_base_src_is_live (basesrc)) { - GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); - - if (GST_CLOCK_TIME_IS_VALID (timestamp)) { - /* get duration to calculate end time */ - GstClockTime duration = GST_BUFFER_DURATION (buffer); - - *start = timestamp; - if (GST_CLOCK_TIME_IS_VALID (duration)) { - *end = *start + duration; - } - } - } else { - *start = -1; - *end = -1; - } -} static GstBuffer * From 1da5ed6a906212a4afc1c0c08af746a08ca908ec Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Fri, 14 Sep 2007 04:20:42 +0000 Subject: [PATCH 028/138] [MOVED FROM GST-P-FARSIGHT] Implement stopping in a nice thread safe way 20070914042042-3e2dc-1fe257ff4b72aca4b0eb5f285a14650b8df268c3.gz --- gst/dtmf/gstdtmfsrc.c | 194 ++++++++++++++++++++++++++++-------------- gst/dtmf/gstdtmfsrc.h | 5 +- 2 files changed, 131 insertions(+), 68 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 8c373ea3ef..35e6813f4c 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -252,6 +252,7 @@ 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 void gst_dtmf_src_base_init (gpointer g_class) @@ -294,6 +295,8 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state); 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); @@ -315,8 +318,6 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass *g_class) dtmfsrc->event_queue = g_async_queue_new (); dtmfsrc->last_event = NULL; - dtmfsrc->clock_id = NULL; - GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -475,7 +476,7 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) GstClock *clock; GstClockTime base_time; - base_time = GST_ELEMENT_CAST (dtmfsrc)->base_time; + base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { @@ -622,82 +623,124 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer) { GstBuffer *buf = NULL; - GstFlowReturn ret; GstDTMFSrcEvent *event; GstDTMFSrc * dtmfsrc; + GstClock *clock; + GstClockID *clockid; + GstClockReturn clockret; dtmfsrc = GST_DTMF_SRC (basesrc); - g_async_queue_ref (dtmfsrc->event_queue); + do { - start: - if (dtmfsrc->last_event == NULL) { - GST_DEBUG_OBJECT (dtmfsrc, "popping"); - event = g_async_queue_pop (dtmfsrc->event_queue); + if (dtmfsrc->paused) + goto paused; - GST_DEBUG_OBJECT (dtmfsrc, "popped %d", event->event_type); + if (dtmfsrc->last_event == NULL) { + GST_DEBUG_OBJECT (dtmfsrc, "popping"); + event = g_async_queue_pop (dtmfsrc->event_queue); - if (event->event_type == DTMF_EVENT_TYPE_STOP) { - GST_WARNING_OBJECT (dtmfsrc, - "Received a DTMF stop event when already stopped"); - } else if (event->event_type == DTMF_EVENT_TYPE_START) { - gst_dtmf_prepare_timestamps (dtmfsrc); + GST_DEBUG_OBJECT (dtmfsrc, "popped %d", event->event_type); - /* Don't forget to get exclusive access to the stream */ - gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - - event->packet_count = 0; - dtmfsrc->last_event = event; - } else if (event->event_type == 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..."); - g_async_queue_push (dtmfsrc->event_queue, event); - g_async_queue_unref (dtmfsrc->event_queue); - } - } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= - MIN_DUTY_CYCLE) { - event = g_async_queue_try_pop (dtmfsrc->event_queue); - - if (event != NULL) { - if (event->event_type == DTMF_EVENT_TYPE_START) { + if (event->event_type == DTMF_EVENT_TYPE_STOP) { GST_WARNING_OBJECT (dtmfsrc, - "Received two consecutive DTMF start events"); - } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - goto start; + "Received a DTMF stop event when already stopped"); + } else if (event->event_type == DTMF_EVENT_TYPE_START) { + gst_dtmf_prepare_timestamps (dtmfsrc); + + /* Don't forget to get exclusive access to the stream */ + gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + + event->packet_count = 0; + dtmfsrc->last_event = event; } else if (event->event_type == 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..."); - g_async_queue_push (dtmfsrc->event_queue, event); - g_async_queue_unref (dtmfsrc->event_queue); + if (dtmfsrc->paused) { + + g_async_queue_push (dtmfsrc->event_queue, event); + goto paused; + } + } + } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= + MIN_DUTY_CYCLE) { + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + if (event != NULL) { + if (event->event_type == DTMF_EVENT_TYPE_START) { + GST_WARNING_OBJECT (dtmfsrc, + "Received two consecutive DTMF start events"); + } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + } else if (event->event_type == 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..."); + if (dtmfsrc->paused) { + g_async_queue_push (dtmfsrc->event_queue, event); + goto paused; + } + } } } - } - g_async_queue_unref (dtmfsrc->event_queue); + } while (dtmfsrc->last_event == NULL); - GST_DEBUG_OBJECT (dtmfsrc, "end event check"); + GST_DEBUG_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_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf)); + *buffer = buf; + + GST_DEBUG_OBJECT (dtmfsrc, "returning a buffer"); + return GST_FLOW_OK; + + paused: if (dtmfsrc->last_event) { - buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); - - GST_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf)); - *buffer = buf; - ret = GST_FLOW_OK; - } else { - *buffer = NULL; - ret = GST_FLOW_WRONG_STATE; + GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event"); + /* Don't forget to release the stream lock */ + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; } - GST_DEBUG_OBJECT (dtmfsrc, "returning"); - return ret; + return GST_FLOW_WRONG_STATE; } @@ -706,7 +749,16 @@ gst_dtmf_src_unlock (GstBaseSrc *src) { GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (src); GstDTMFSrcEvent *event = NULL; - GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK even on PAUSED_TO_READY change"); + 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_malloc (sizeof(GstDTMFSrcEvent)); event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); @@ -714,6 +766,20 @@ gst_dtmf_src_unlock (GstBaseSrc *src) { 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 GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) { @@ -726,7 +792,6 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: /* Flushing the event queue */ event = g_async_queue_try_pop (dtmfsrc->event_queue); @@ -734,6 +799,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) g_free (event); event = g_async_queue_try_pop (dtmfsrc->event_queue); } + no_preroll = TRUE; break; default: break; @@ -746,16 +812,12 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_DEBUG_OBJECT (dtmfsrc, "PLAYING TO PAUSED"); - if (dtmfsrc->last_event) { - GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event"); - /* Don't forget to release the stream lock */ - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - } - + 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); diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 1ca44643ce..0340a7c2b2 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -73,11 +73,12 @@ struct _GstDTMFSrc { GstBaseSrc parent; GAsyncQueue* event_queue; GstDTMFSrcEvent* last_event; - GstClockID clock_id; - gboolean task_paused; guint16 interval; GstClockTime timestamp; + + gboolean paused; + GstClockID clockid; }; From 482e8a4c72385e7b6e01ee698379fa780003e130 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Sun, 16 Sep 2007 19:41:01 +0000 Subject: [PATCH 029/138] [MOVED FROM GST-P-FARSIGHT] Make dtmf src code nicer 20070916194101-3e2dc-a8be8c509c65400d1d3962da02e67d15d2054316.gz --- gst/dtmf/gstdtmfsrc.c | 102 ++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 35e6813f4c..7680086749 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -633,61 +633,72 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, do { - if (dtmfsrc->paused) - goto paused; - 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); - if (event->event_type == DTMF_EVENT_TYPE_STOP) { - GST_WARNING_OBJECT (dtmfsrc, - "Received a DTMF stop event when already stopped"); - } else if (event->event_type == DTMF_EVENT_TYPE_START) { - gst_dtmf_prepare_timestamps (dtmfsrc); + switch (event->event_type) { + case DTMF_EVENT_TYPE_STOP: + GST_WARNING_OBJECT (dtmfsrc, + "Received a DTMF stop event when already stopped"); + break; + case DTMF_EVENT_TYPE_START: + gst_dtmf_prepare_timestamps (dtmfsrc); - /* Don't forget to get exclusive access to the stream */ - gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + /* Don't forget to get exclusive access to the stream */ + gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - event->packet_count = 0; - dtmfsrc->last_event = event; - } else if (event->event_type == 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..."); - if (dtmfsrc->paused) { - - g_async_queue_push (dtmfsrc->event_queue, event); - goto paused; - } + event->packet_count = 0; + dtmfsrc->last_event = 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; } } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { event = g_async_queue_try_pop (dtmfsrc->event_queue); if (event != NULL) { - if (event->event_type == DTMF_EVENT_TYPE_START) { - GST_WARNING_OBJECT (dtmfsrc, - "Received two consecutive DTMF start events"); - } else if (event->event_type == DTMF_EVENT_TYPE_STOP) { - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - } else if (event->event_type == 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..."); - if (dtmfsrc->paused) { - g_async_queue_push (dtmfsrc->event_queue, event); - goto paused; - } + switch (event->event_type) { + case DTMF_EVENT_TYPE_START: + GST_WARNING_OBJECT (dtmfsrc, + "Received two consecutive DTMF start events"); + break; + case DTMF_EVENT_TYPE_STOP: + gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + + g_free (dtmfsrc->last_event); + dtmfsrc->last_event = NULL; + 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; } } } @@ -730,6 +741,9 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_DEBUG_OBJECT (dtmfsrc, "returning a buffer"); return GST_FLOW_OK; + paused_locked: + GST_OBJECT_UNLOCK (dtmfsrc); + paused: if (dtmfsrc->last_event) { @@ -811,12 +825,6 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) goto failure; switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - - GST_DEBUG_OBJECT (dtmfsrc, "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 */ @@ -827,8 +835,6 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) event = g_async_queue_try_pop (dtmfsrc->event_queue); } - /* Indicate that we don't do PRE_ROLL */ - no_preroll = TRUE; break; default: break; From 8ba0818e18869e559aea9919bfb96271077d5a7e Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Sun, 16 Sep 2007 19:44:08 +0000 Subject: [PATCH 030/138] [MOVED FROM GST-P-FARSIGHT] Make the rtp dtmf src use basesrc 20070916194408-3e2dc-734000130dce2434a014acf843d641ff0e60aa5a.gz --- gst/dtmf/gstrtpdtmfsrc.c | 477 +++++++++++++++++++-------------------- gst/dtmf/gstrtpdtmfsrc.h | 13 +- 2 files changed, 237 insertions(+), 253 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 1a03da66ae..a75f4b0e7a 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -146,11 +146,9 @@ #define MAX_EVENT_STRING "16" #define MIN_VOLUME 0 #define MAX_VOLUME 36 -#define MIN_EVENT_DURATION 50 -#define MIN_INTER_DIGIT_INTERVAL 50 -#define MIN_PULSE_DURATION 70 -#define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) +#define MIN_INTER_DIGIT_INTERVAL (50 * GST_MSECOND) +#define MIN_PULSE_DURATION (70 * GST_MSECOND) #define DEFAULT_PACKET_REDUNDANCY 1 #define MIN_PACKET_REDUNDANCY 1 @@ -200,52 +198,35 @@ GST_STATIC_PAD_TEMPLATE ("src", "encoding-name = (string) \"telephone-event\"") ); -static GstElementClass *parent_class = NULL; + +GST_BOILERPLATE (GstRTPDTMFSrc, gst_rtp_dtmf_src, GstBaseSrc, + GST_TYPE_BASE_SRC); + static void gst_rtp_dtmf_src_base_init (gpointer g_class); static void gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass); -static void gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class); static void gst_rtp_dtmf_src_finalize (GObject * object); -GType -gst_rtp_dtmf_src_get_type (void) -{ - static GType base_src_type = 0; - - if (G_UNLIKELY (base_src_type == 0)) { - static const GTypeInfo base_src_info = { - sizeof (GstRTPDTMFSrcClass), - (GBaseInitFunc) gst_rtp_dtmf_src_base_init, - NULL, - (GClassInitFunc) gst_rtp_dtmf_src_class_init, - NULL, - NULL, - sizeof (GstRTPDTMFSrc), - 0, - (GInstanceInitFunc) gst_rtp_dtmf_src_init, - }; - - base_src_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstRTPDTMFSrc", &base_src_info, 0); - } - return base_src_type; -} 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 (GstPad * pad, GstEvent * event); +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_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc); -static void gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc); -static void gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc); 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 void gst_rtp_dtmf_src_set_caps (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 void gst_rtp_dtmf_src_base_init (gpointer g_class) @@ -265,9 +246,11 @@ 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); parent_class = g_type_class_peek_parent (klass); @@ -319,32 +302,37 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) 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); + } static void -gst_rtp_dtmf_src_init (GstRTPDTMFSrc * dtmfsrc, gpointer g_class) +gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class) { - dtmfsrc->srcpad = - gst_pad_new_from_static_template (&gst_rtp_dtmf_src_template, "src"); - GST_DEBUG_OBJECT (dtmfsrc, "adding src pad"); - gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad); + gst_base_src_set_format (GST_BASE_SRC (object), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (object), TRUE); - gst_pad_set_event_function (dtmfsrc->srcpad, gst_rtp_dtmf_src_handle_event); + 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->interval = DEFAULT_PACKET_INTERVAL; + object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; - dtmfsrc->ssrc = DEFAULT_SSRC; - dtmfsrc->seqnum_offset = DEFAULT_SEQNUM_OFFSET; - dtmfsrc->ts_offset = DEFAULT_TIMESTAMP_OFFSET; - dtmfsrc->pt = DEFAULT_PT; - dtmfsrc->clock_rate = DEFAULT_CLOCK_RATE; - dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; - dtmfsrc->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; - dtmfsrc->task_paused = TRUE; + object->event_queue = g_async_queue_new (); + object->last_event = NULL; - dtmfsrc->event_queue = g_async_queue_new (); - dtmfsrc->last_event = NULL; - dtmfsrc->clock_id = NULL; - - GST_DEBUG_OBJECT (dtmfsrc, "init done"); + GST_DEBUG_OBJECT (object, "init done"); } static void @@ -435,37 +423,18 @@ ret: } static gboolean -gst_rtp_dtmf_src_handle_event (GstPad * pad, GstEvent * event) +gst_rtp_dtmf_src_handle_event (GstBaseSrc *basesrc, GstEvent * event) { GstRTPDTMFSrc *dtmfsrc; gboolean result = FALSE; - GstElement *parent = gst_pad_get_parent_element (pad); - dtmfsrc = GST_RTP_DTMF_SRC (parent); + dtmfsrc = GST_RTP_DTMF_SRC (basesrc); GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CUSTOM_UPSTREAM: - { - result = gst_rtp_dtmf_src_handle_custom_upstream (dtmfsrc, event); - break; - } - /* Ideally this element should not be flushed but let's handle the event - * just in case it is */ - case GST_EVENT_FLUSH_START: - gst_rtp_dtmf_src_stop (dtmfsrc); - result = TRUE; - break; - case GST_EVENT_FLUSH_STOP: - gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); - break; - default: - result = gst_pad_event_default (pad, event); - break; + if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) { + result = gst_rtp_dtmf_src_handle_custom_upstream (dtmfsrc, event); } - gst_object_unref (parent); - gst_event_unref (event); return result; } @@ -569,11 +538,15 @@ static void gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) { GstClock *clock; + GstClockTime base_time; + + base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { dtmfsrc->timestamp = gst_clock_get_time (clock) - + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND); + + MIN_INTER_DIGIT_INTERVAL - base_time; + dtmfsrc->start_timestamp = dtmfsrc->timestamp; gst_object_unref (clock); } else { gchar *dtmf_name = gst_element_get_name (dtmfsrc); @@ -589,6 +562,8 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->clock_rate, GST_SECOND); } +#if 0 + static void gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc) { @@ -601,50 +576,7 @@ gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc) } } -static void -gst_rtp_dtmf_src_stop (GstRTPDTMFSrc *dtmfsrc) -{ - - GstRTPDTMFSrcEvent *event = NULL; - - dtmfsrc->task_paused = TRUE; - GST_OBJECT_LOCK (dtmfsrc); - if (dtmfsrc->clock_id != NULL) { - gst_clock_id_unschedule(dtmfsrc->clock_id); - } - GST_OBJECT_UNLOCK (dtmfsrc); - - event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); - event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; - g_async_queue_push (dtmfsrc->event_queue, event); - - event = NULL; - - if (!gst_pad_pause_task (dtmfsrc->srcpad)) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad"); - return; - } - - - if (dtmfsrc->last_event) { - /* Don't forget to release the stream lock */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - } - - /* Flushing the event queue */ - event = g_async_queue_try_pop (dtmfsrc->event_queue); - - while (event != NULL) { - g_free (event); - event = g_async_queue_try_pop (dtmfsrc->event_queue); - } - - -} - - +#endif static void gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number, @@ -675,57 +607,6 @@ gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc) } -static void -gst_rtp_dtmf_src_wait_for_buffer_ts (GstRTPDTMFSrc *dtmfsrc, GstBuffer * buf) -{ - GstClock *clock; - - clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - if (clock != NULL) { - GstClockReturn clock_ret; - GstClockID clock_id; - - clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf)); - gst_object_unref (clock); - - GST_OBJECT_LOCK (dtmfsrc); - dtmfsrc->clock_id = clock_id; - GST_OBJECT_UNLOCK (dtmfsrc); - - if (dtmfsrc->task_paused) { - clock_ret = GST_CLOCK_UNSCHEDULED; - } else { - clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL); - } - - GST_OBJECT_LOCK (dtmfsrc); - dtmfsrc->clock_id = NULL; - gst_clock_id_unref (clock_id); - GST_OBJECT_UNLOCK (dtmfsrc); - - if (clock_ret == GST_CLOCK_UNSCHEDULED) { - GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled"); - } else { - if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) { - gchar *clock_name = NULL; - - clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - clock_name = gst_element_get_name (clock); - gst_object_unref (clock); - - GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name); - g_free (clock_name); - } - } - } - - else { - gchar *dtmf_name = gst_element_get_name (dtmfsrc); - GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name); - g_free (dtmf_name); - } -} - static void gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstRTPDTMFSrcEvent *event, GstBuffer *buf) @@ -772,8 +653,8 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, * if its the end of the event */ if (payload->e && - payload->duration < MIN_EVENT_DURATION * dtmfsrc->clock_rate / 1000) - payload->duration = MIN_EVENT_DURATION * dtmfsrc->clock_rate / 1000; + payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / GST_MSECOND) + payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / GST_MSECOND; payload->duration = g_htons (payload->duration); } @@ -789,110 +670,147 @@ gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc, gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, event, buf); - /* FIXME: Should we sync to clock ourselves or leave it to sink */ - gst_rtp_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf); - - event->sent_packets++; - /* Set caps on the buffer before pushing it */ gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad)); return buf; } -static void -gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) + +static GstFlowReturn +gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, + guint length, GstBuffer ** buffer) { - GstBuffer *buf = NULL; - GstFlowReturn ret; - gint redundancy_count = 1; GstRTPDTMFSrcEvent *event; + GstRTPDTMFSrc * dtmfsrc; + GstClock *clock; + GstClockID *clockid; + GstClockReturn clockret; - g_async_queue_ref (dtmfsrc->event_queue); + dtmfsrc = GST_RTP_DTMF_SRC (basesrc); - if (dtmfsrc->last_event == NULL) { - event = g_async_queue_pop (dtmfsrc->event_queue); + do { - if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) { - GST_WARNING_OBJECT (dtmfsrc, - "Received a DTMF stop event when already stopped"); - } else if (event->event_type == RTP_DTMF_EVENT_TYPE_START) { + if (dtmfsrc->last_event == NULL) { + event = g_async_queue_pop (dtmfsrc->event_queue); - dtmfsrc->first_packet = TRUE; - dtmfsrc->last_packet = FALSE; - gst_rtp_dtmf_prepare_timestamps (dtmfsrc); + switch (event->event_type) { + case RTP_DTMF_EVENT_TYPE_STOP: + GST_WARNING_OBJECT (dtmfsrc, + "Received a DTMF stop event when already stopped"); + break; - /* Don't forget to get exclusive access to the stream */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); + case RTP_DTMF_EVENT_TYPE_START: + dtmfsrc->first_packet = TRUE; + dtmfsrc->last_packet = FALSE; + gst_rtp_dtmf_prepare_timestamps (dtmfsrc); - event->sent_packets = 0; + /* Don't forget to get exclusive access to the stream */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - dtmfsrc->last_event = event; - } else if (event->event_type == 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 - */ - g_async_queue_push (dtmfsrc->event_queue, event); - g_async_queue_unref (dtmfsrc->event_queue); - return; - } - } else if (dtmfsrc->last_event->sent_packets * dtmfsrc->interval >= - MIN_PULSE_DURATION){ - event = g_async_queue_try_pop (dtmfsrc->event_queue); + dtmfsrc->last_event = event; + break; - if (event != NULL) { - if (event->event_type == RTP_DTMF_EVENT_TYPE_START) { - GST_WARNING_OBJECT (dtmfsrc, - "Received two consecutive DTMF start events"); - } else if (event->event_type == RTP_DTMF_EVENT_TYPE_STOP) { - dtmfsrc->first_packet = FALSE; - dtmfsrc->last_packet = TRUE; + 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; + } + } else if (dtmfsrc->timestamp - dtmfsrc->start_timestamp >= + MIN_PULSE_DURATION) { + event = g_async_queue_try_pop (dtmfsrc->event_queue); + + if (event != NULL) { + switch (event->event_type) { + case RTP_DTMF_EVENT_TYPE_START: + GST_WARNING_OBJECT (dtmfsrc, + "Received two consecutive DTMF start events"); + break; + + case RTP_DTMF_EVENT_TYPE_STOP: + dtmfsrc->first_packet = FALSE; + dtmfsrc->last_packet = TRUE; + 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; + } } } + } while (dtmfsrc->last_event == NULL); + + + GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock"); + + 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; } - g_async_queue_unref (dtmfsrc->event_queue); + gst_clock_id_unref (clockid); + dtmfsrc->clockid = NULL; + GST_OBJECT_UNLOCK (dtmfsrc); + + if (clockret == GST_CLOCK_UNSCHEDULED) { + goto paused; + } + + send_last: if (dtmfsrc->last_event) { if (dtmfsrc->first_packet == TRUE || dtmfsrc->last_packet == TRUE) { - redundancy_count = dtmfsrc->packet_redundancy; + dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; if(dtmfsrc->first_packet == TRUE) { GST_DEBUG_OBJECT (dtmfsrc, "redundancy count set to %d due to dtmf start", - redundancy_count); + dtmfsrc->redundancy_count); } else if(dtmfsrc->last_packet == TRUE) { GST_DEBUG_OBJECT (dtmfsrc, "redundancy count set to %d due to dtmf stop", - redundancy_count); + dtmfsrc->redundancy_count); } - } + /* create buffer to hold the payload */ - buf = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc, + *buffer = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc, dtmfsrc->last_event); - while ( redundancy_count-- ) { - gst_buffer_ref(buf); - - GST_DEBUG_OBJECT (dtmfsrc, - "pushing buffer on src pad of size %d with redundancy count %d", - GST_BUFFER_SIZE (buf), redundancy_count); - ret = gst_pad_push (dtmfsrc->srcpad, buf); - if (ret != GST_FLOW_OK) - GST_ERROR_OBJECT (dtmfsrc, - "Failed to push buffer on src pad"); - - /* Make sure only the first packet sent has the marker set */ - gst_rtp_buffer_set_marker (buf, FALSE); - } - - gst_buffer_unref(buf); - GST_DEBUG_OBJECT (dtmfsrc, - "pushed DTMF event '%d' on src pad", dtmfsrc->last_event->payload->event); - if (dtmfsrc->last_event->payload->e) { /* Don't forget to release the stream lock */ gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); @@ -905,8 +823,27 @@ gst_rtp_dtmf_src_push_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) } } + + + return GST_FLOW_OK; + + paused_locked: + + GST_OBJECT_UNLOCK (dtmfsrc); + + paused: + + if (dtmfsrc->last_event) { + dtmfsrc->first_packet = FALSE; + dtmfsrc->last_packet = TRUE; + goto send_last; + } + + return GST_FLOW_WRONG_STATE; } + + static void gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc) { @@ -951,6 +888,7 @@ gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->ts_base = g_random_int (); else dtmfsrc->ts_base = dtmfsrc->ts_offset; + } static GstStateChangeReturn @@ -959,18 +897,20 @@ 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); - /* Indicate that we don't do PRE_ROLL */ + + /* Flushing the event queue */ + while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) + g_free (event); + no_preroll = TRUE; break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - gst_rtp_dtmf_src_start (dtmfsrc); - break; default: break; } @@ -981,11 +921,15 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) goto failure; switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + case GST_STATE_CHANGE_PAUSED_TO_READY: + + /* Flushing the event queue */ + while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) + g_free (event); + /* Indicate that we don't do PRE_ROLL */ - no_preroll = TRUE; - gst_rtp_dtmf_src_stop (dtmfsrc); break; + default: break; } @@ -1003,6 +947,43 @@ failure: } } + +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_malloc (sizeof(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) { diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 895115088f..5438738a0b 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -26,6 +26,7 @@ #define __GST_RTP_DTMF_SRC_H__ #include +#include #include G_BEGIN_DECLS @@ -70,7 +71,6 @@ typedef enum _GstRTPDTMFEventType GstRTPDTMFEventType; struct _GstRTPDTMFSrcEvent { GstRTPDTMFEventType event_type; GstRTPDTMFPayload* payload; - guint32 sent_packets; }; typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; @@ -82,16 +82,17 @@ typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; * The opaque #GstRTPDTMFSrc data structure. */ struct _GstRTPDTMFSrc { - GstElement element; + GstBaseSrc basesrc; GstPad* srcpad; GstSegment segment; GAsyncQueue* event_queue; GstRTPDTMFSrcEvent* last_event; - GstClockID clock_id; - gboolean task_paused; + GstClockID clockid; + gboolean paused; GstClockTime timestamp; + GstClockTime start_timestamp; gboolean first_packet; gboolean last_packet; guint32 ts_base; @@ -106,10 +107,12 @@ struct _GstRTPDTMFSrc { guint16 interval; guint16 packet_redundancy; guint32 clock_rate; + + guint16 redundancy_count; }; struct _GstRTPDTMFSrcClass { - GstElementClass parent_class; + GstBaseSrcClass parent_class; }; GType gst_rtp_dtmf_src_get_type (void); From 5b7ae694d0fe11c8146dd3170a7aa1f0c5cb11b3 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 00:15:52 +0000 Subject: [PATCH 031/138] [MOVED FROM GST-P-FARSIGHT] Make interval and packet_redundancy into uint 20070917001552-3e2dc-60032e547b3669b87317c981d985c156aab91b40.gz --- gst/dtmf/gstdtmfsrc.c | 4 ++-- gst/dtmf/gstrtpdtmfsrc.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 7680086749..866a719113 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -287,7 +287,7 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) GST_DEBUG_FUNCPTR (gst_dtmf_src_get_property); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL, - g_param_spec_int ("interval", "Interval between tone packets", + 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)); @@ -428,7 +428,7 @@ gst_dtmf_src_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_INTERVAL: - dtmfsrc->interval = g_value_get_int (value); + dtmfsrc->interval = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index a75f4b0e7a..e0a946d638 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -291,11 +291,11 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) "The payload type of the packets", 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL, - g_param_spec_int ("interval", "Interval between rtp packets", + g_param_spec_uint ("interval", "Interval between rtp packets", "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL, MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY, - g_param_spec_int ("packet-redundancy", "Packet 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)); @@ -465,10 +465,10 @@ gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id, gst_rtp_dtmf_src_set_caps (dtmfsrc); break; case PROP_INTERVAL: - dtmfsrc->interval = g_value_get_int (value); + dtmfsrc->interval = g_value_get_uint (value); break; case PROP_REDUNDANCY: - dtmfsrc->packet_redundancy = g_value_get_int (value); + dtmfsrc->packet_redundancy = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); From fce9b071f5a3a1433984da0fb53ae5cae1472c3c Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 00:16:59 +0000 Subject: [PATCH 032/138] [MOVED FROM GST-P-FARSIGHT] Properly free non-start events 20070917001659-3e2dc-a571777e3ecfb90989f87412f554aa10a31cc2ca.gz --- gst/dtmf/gstdtmfsrc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 866a719113..0b8fb20391 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -652,6 +652,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, event->packet_count = 0; dtmfsrc->last_event = event; + event = NULL; break; case DTMF_EVENT_TYPE_PAUSE_TASK: /* @@ -667,6 +668,8 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_OBJECT_UNLOCK (dtmfsrc); break; } + if (event) + g_free (event); } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { event = g_async_queue_try_pop (dtmfsrc->event_queue); @@ -700,6 +703,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, break; } + g_free (event); } } } while (dtmfsrc->last_event == NULL); From f135a43de2c38e18a75faa7b0e44f3841889ede6 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 00:24:12 +0000 Subject: [PATCH 033/138] [MOVED FROM GST-P-FARSIGHT] Add caps negotiation function 20070917002412-3e2dc-ca266816e9629746e9083c5bb8b7f73b94a9b2b0.gz --- gst/dtmf/gstrtpdtmfsrc.c | 153 +++++++++++++++++++++++++++++---------- gst/dtmf/gstrtpdtmfsrc.h | 1 + 2 files changed, 117 insertions(+), 37 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index e0a946d638..79929706fe 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -219,13 +219,12 @@ static GstStateChangeReturn gst_rtp_dtmf_src_change_state (GstElement * element, 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 void gst_rtp_dtmf_src_set_caps (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 @@ -312,7 +311,8 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) 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 @@ -455,14 +455,14 @@ gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id, break; case PROP_CLOCK_RATE: dtmfsrc->clock_rate = g_value_get_uint (value); - gst_rtp_dtmf_src_set_caps (dtmfsrc); + 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); - gst_rtp_dtmf_src_set_caps (dtmfsrc); + dtmfsrc->dirty = TRUE; break; case PROP_INTERVAL: dtmfsrc->interval = g_value_get_uint (value); @@ -562,21 +562,6 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->clock_rate, GST_SECOND); } -#if 0 - -static void -gst_rtp_dtmf_src_start (GstRTPDTMFSrc *dtmfsrc) -{ - gst_rtp_dtmf_src_set_caps (dtmfsrc); - - dtmfsrc->task_paused = FALSE; - if (!gst_pad_start_task (dtmfsrc->srcpad, - (GstTaskFunction) gst_rtp_dtmf_src_push_next_rtp_packet, dtmfsrc)) { - GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad"); - } -} - -#endif static void gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number, @@ -843,31 +828,125 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, } - -static void -gst_rtp_dtmf_src_set_caps (GstRTPDTMFSrc *dtmfsrc) +static gboolean +gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) { - GstCaps *caps; + GstCaps *srccaps, *peercaps; + GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (basesrc); + gboolean ret; - caps = gst_caps_new_simple ("application/x-rtp", + /* fill in the defaults, there properties cannot be negotiated. */ + srccaps = gst_caps_new_simple ("application/x-rtp", "media", G_TYPE_STRING, "audio", - "payload", G_TYPE_INT, dtmfsrc->pt, "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, - "encoding-name", G_TYPE_STRING, "telephone-event", - "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc, - "clock-base", G_TYPE_UINT, dtmfsrc->ts_base, - "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base, NULL); + "encoding-name", G_TYPE_STRING, "telephone-event", NULL); - if (!gst_pad_set_caps (dtmfsrc->srcpad, caps)) - GST_ERROR_OBJECT (dtmfsrc, - "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps); - else - GST_DEBUG_OBJECT (dtmfsrc, - "caps %" GST_PTR_FORMAT " set on src pad", caps); + /* the peer caps can override some of the defaults */ + peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc)); + 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, + "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; + + /* 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 */ + gst_caps_truncate (temp); + srccaps = temp; + + /* get first structure */ + s = gst_caps_get_structure (srccaps, 0); + + if (gst_structure_get_int (s, "dtmfsrc", &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", pt); + } + } + + 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); + } + 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; - gst_caps_unref (caps); } + static void gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) { diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 5438738a0b..9202310a6e 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -108,6 +108,7 @@ struct _GstRTPDTMFSrc { guint16 packet_redundancy; guint32 clock_rate; + gboolean dirty; guint16 redundancy_count; }; From b55bec0a966edb712126b12e4712140ba9829089 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 00:36:54 +0000 Subject: [PATCH 034/138] [MOVED FROM GST-P-FARSIGHT] Complete port to basesrc 20070917003654-3e2dc-db0f84dabd9dd1ac929a0461865b8aaa8ef91a77.gz --- gst/dtmf/gstrtpdtmfsrc.c | 141 ++++++++++++++++++++------------------- gst/dtmf/gstrtpdtmfsrc.h | 4 +- 2 files changed, 75 insertions(+), 70 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 79929706fe..db4d3f9153 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -147,8 +147,8 @@ #define MIN_VOLUME 0 #define MAX_VOLUME 36 -#define MIN_INTER_DIGIT_INTERVAL (50 * GST_MSECOND) -#define MIN_PULSE_DURATION (70 * GST_MSECOND) +#define MIN_INTER_DIGIT_INTERVAL 50 /* ms */ +#define MIN_PULSE_DURATION 70 /* ms */ #define DEFAULT_PACKET_REDUNDANCY 1 #define MIN_PACKET_REDUNDANCY 1 @@ -330,7 +330,7 @@ gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class) object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; object->event_queue = g_async_queue_new (); - object->last_event = NULL; + object->payload = NULL; GST_DEBUG_OBJECT (object, "init done"); } @@ -528,7 +528,7 @@ gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc *dtmfsrc, gboolean lock) "lock", G_TYPE_BOOLEAN, lock, NULL); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - if (!gst_pad_push_event (dtmfsrc->srcpad, event)) { + if (!gst_pad_push_event (GST_BASE_SRC_PAD (dtmfsrc), event)) { GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); } @@ -545,7 +545,7 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { dtmfsrc->timestamp = gst_clock_get_time (clock) - + MIN_INTER_DIGIT_INTERVAL - base_time; + + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - base_time; dtmfsrc->start_timestamp = dtmfsrc->timestamp; gst_object_unref (clock); } else { @@ -557,8 +557,8 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) dtmfsrc->rtp_timestamp = dtmfsrc->ts_base + gst_util_uint64_scale_int ( - gst_segment_to_running_time (&dtmfsrc->segment, GST_FORMAT_TIME, - dtmfsrc->timestamp), + gst_segment_to_running_time (&GST_BASE_SRC (dtmfsrc)->segment, + GST_FORMAT_TIME, dtmfsrc->timestamp), dtmfsrc->clock_rate, GST_SECOND); } @@ -574,6 +574,7 @@ gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number, event->payload = g_new0 (GstRTPDTMFPayload, 1); event->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT); event->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME); + event->payload->duration = dtmfsrc->interval * dtmfsrc->clock_rate / 1000; g_async_queue_push (dtmfsrc->event_queue, event); } @@ -584,26 +585,21 @@ gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc) GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); event->event_type = RTP_DTMF_EVENT_TYPE_STOP; - event->payload = g_new0 (GstRTPDTMFPayload, 1); - event->payload->event = 0; - event->payload->volume = 0; g_async_queue_push (dtmfsrc->event_queue, event); } static void -gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, - GstRTPDTMFSrcEvent *event, GstBuffer *buf) +gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) { gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc); gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt); + /* Only the very first packet gets a marker */ if (dtmfsrc->first_packet) { gst_rtp_buffer_set_marker (buf, TRUE); - dtmfsrc->first_packet = FALSE; } else if (dtmfsrc->last_packet) { - event->payload->e = 1; - dtmfsrc->last_packet = FALSE; + dtmfsrc->payload->e = 1; } dtmfsrc->seqnum++; @@ -614,54 +610,60 @@ gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, } static void -gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, - GstRTPDTMFSrcEvent *event,GstBuffer *buf) +gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) { GstRTPDTMFPayload *payload; - gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc,event, buf); - - /* duration of DTMF payload */ - event->payload->duration += - dtmfsrc->interval * dtmfsrc->clock_rate / 1000; + gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, buf); /* timestamp and duration of GstBuffer */ - GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; + /* Redundant buffer have no duration ... */ + if (dtmfsrc->redundancy_count > 1) + GST_BUFFER_DURATION (buf) = 0; + else + GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; + dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf); /* copy payload and convert to network-byte order */ - g_memmove (payload, event->payload, sizeof (GstRTPDTMFPayload)); + g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload)); /* Force the packet duration to a certain minumum * if its the end of the event */ if (payload->e && - payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / GST_MSECOND) - payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / GST_MSECOND; + payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000 ) + payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000; payload->duration = g_htons (payload->duration); + + + /* duration of DTMF payloadfor the NEXT packet */ + /* not updated for redundant packets */ + if (dtmfsrc->redundancy_count == 0) + dtmfsrc->payload->duration += + dtmfsrc->interval * dtmfsrc->clock_rate / 1000; + } static GstBuffer * -gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc, - GstRTPDTMFSrcEvent *event) +gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) { GstBuffer *buf = NULL; /* create buffer to hold the payload */ buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0); - gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, event, buf); + gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, buf); /* Set caps on the buffer before pushing it */ - gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad)); + gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (dtmfsrc))); return buf; } - static GstFlowReturn gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer) @@ -676,9 +678,12 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, do { - if (dtmfsrc->last_event == NULL) { + 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, @@ -688,12 +693,14 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, case RTP_DTMF_EVENT_TYPE_START: dtmfsrc->first_packet = TRUE; dtmfsrc->last_packet = FALSE; + /* Set the redundanc on the first packet */ + dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; gst_rtp_dtmf_prepare_timestamps (dtmfsrc); /* Don't forget to get exclusive access to the stream */ gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - dtmfsrc->last_event = event; + dtmfsrc->payload = event->payload; break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: @@ -709,11 +716,18 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_OBJECT_UNLOCK (dtmfsrc); break; } - } else if (dtmfsrc->timestamp - dtmfsrc->start_timestamp >= + + g_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, @@ -723,6 +737,8 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, case RTP_DTMF_EVENT_TYPE_STOP: dtmfsrc->first_packet = FALSE; dtmfsrc->last_packet = TRUE; + /* Set the redundanc on the last packet */ + dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: @@ -739,16 +755,17 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_OBJECT_UNLOCK (dtmfsrc); break; } + g_free (event); } } - } while (dtmfsrc->last_event == NULL); + } while (dtmfsrc->payload == NULL); GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock"); clock = gst_element_get_clock (GST_ELEMENT (basesrc)); - clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp - + clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp + gst_element_get_base_time (GST_ELEMENT (dtmfsrc))); gst_object_unref (clock); @@ -775,41 +792,31 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, send_last: - if (dtmfsrc->last_event) { + if (dtmfsrc->dirty) + if (!gst_rtp_dtmf_src_negotiate (basesrc)) + return GST_FLOW_NOT_NEGOTIATED; - if (dtmfsrc->first_packet == TRUE || dtmfsrc->last_packet == TRUE) { - dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; + /* create buffer to hold the payload */ + *buffer = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc); - if(dtmfsrc->first_packet == TRUE) { - GST_DEBUG_OBJECT (dtmfsrc, - "redundancy count set to %d due to dtmf start", - dtmfsrc->redundancy_count); - } else if(dtmfsrc->last_packet == TRUE) { - GST_DEBUG_OBJECT (dtmfsrc, - "redundancy count set to %d due to dtmf stop", - dtmfsrc->redundancy_count); - } - } + if (dtmfsrc->redundancy_count) + dtmfsrc->redundancy_count--; + /* Only the very first one has a marker */ + dtmfsrc->first_packet = FALSE; - /* create buffer to hold the payload */ - *buffer = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc, - dtmfsrc->last_event); + /* This is the end of the event */ + if (dtmfsrc->last_packet == TRUE && dtmfsrc->redundancy_count == 0) { - if (dtmfsrc->last_event->payload->e) { - /* Don't forget to release the stream lock */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); + /* Don't forget to release the stream lock */ + gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event->payload); - dtmfsrc->last_event->payload = NULL; + g_free (dtmfsrc->payload); + dtmfsrc->payload = NULL; - g_free (dtmfsrc->last_event); - dtmfsrc->last_event = NULL; - - } + dtmfsrc->last_packet = FALSE; } - return GST_FLOW_OK; paused_locked: @@ -818,13 +825,15 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, paused: - if (dtmfsrc->last_event) { + 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_WRONG_STATE; } - - return GST_FLOW_WRONG_STATE; } @@ -950,8 +959,6 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) static void gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) { - gst_segment_init (&dtmfsrc->segment, GST_FORMAT_UNDEFINED); - if (dtmfsrc->ssrc == -1) dtmfsrc->current_ssrc = g_random_int (); else diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 9202310a6e..4114f23c09 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -84,12 +84,10 @@ typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; struct _GstRTPDTMFSrc { GstBaseSrc basesrc; - GstPad* srcpad; - GstSegment segment; GAsyncQueue* event_queue; - GstRTPDTMFSrcEvent* last_event; GstClockID clockid; gboolean paused; + GstRTPDTMFPayload* payload; GstClockTime timestamp; GstClockTime start_timestamp; From 292816f5cc3068b720cdbfb214dcc4bc375805c2 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 04:26:49 +0000 Subject: [PATCH 035/138] [MOVED FROM GST-P-FARSIGHT] Oops, set to no preroll when playing->paused too 20070917042649-3e2dc-94adb6aa0617e815a6e233232dabb4bbc48dc82c.gz --- gst/dtmf/gstdtmfsrc.c | 3 +++ gst/dtmf/gstrtpdtmfsrc.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 0b8fb20391..2429a71c66 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -829,6 +829,9 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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 */ diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index db4d3f9153..9c796fff4a 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -1007,6 +1007,9 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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 */ From 47c38ea723fadb8352d3141637a4afde74dacfd5 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 16:08:20 +0000 Subject: [PATCH 036/138] [MOVED FROM GST-P-FARSIGHT] Add patch to make it work with maemo dsp sources that payload incorrectly 20070917160820-3e2dc-06b1b1d1b0918b30dabea5a0714cb732b3b8d8dd.gz --- gst/dtmf/gstdtmfsrc.c | 8 ++++++++ gst/dtmf/gstrtpdtmfsrc.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 2429a71c66..e0a73dd1ed 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -480,7 +480,11 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { +#ifdef MAEMO_BROKEN + dtmfsrc->timestamp = gst_clock_get_time (clock); +#else dtmfsrc->timestamp = gst_clock_get_time (clock) - base_time; +#endif gst_object_unref (clock); } else { gchar *dtmf_name = gst_element_get_name (dtmfsrc); @@ -712,8 +716,12 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, clock = gst_element_get_clock (GST_ELEMENT (basesrc)); +#ifdef MAEMO_BROKEN + clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp); +#else clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp + gst_element_get_base_time (GST_ELEMENT (dtmfsrc))); +#endif gst_object_unref (clock); GST_OBJECT_LOCK (dtmfsrc); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 9c796fff4a..5c979cf124 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -540,7 +540,11 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) GstClock *clock; GstClockTime base_time; +#ifdef MAEMO_BROKEN + base_time = 0; +#else base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); +#endif clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { @@ -765,8 +769,12 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, clock = gst_element_get_clock (GST_ELEMENT (basesrc)); +#ifdef MAEMO_BROKEN + clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp); +#else clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp + gst_element_get_base_time (GST_ELEMENT (dtmfsrc))); +#endif gst_object_unref (clock); GST_OBJECT_LOCK (dtmfsrc); From f120296e53c1866c45de2a5c8b8d8a70afed1b59 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 17:51:33 +0000 Subject: [PATCH 037/138] [MOVED FROM GST-P-FARSIGHT] events dont yet belong in the caps 20070917175133-3e2dc-fd1d83b7826b898110fc571ae7c3440f1887434d.gz --- gst/dtmf/gstrtpdtmfsrc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 5c979cf124..faa4c3e1da 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -194,8 +194,9 @@ GST_STATIC_PAD_TEMPLATE ("src", "payload = (int) [ 96, 127 ], " "clock-rate = (int) [ 0, MAX ], " "ssrc = (int) [ 0, MAX ], " - "events = (int) [ " MIN_EVENT_STRING ", " MAX_EVENT_STRING " ], " "encoding-name = (string) \"telephone-event\"") + /* "events = (string) \"1-16\" */ + ); From 8780522c5d0895db93bb32a27b3407e350f4917d Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 17 Sep 2007 17:52:33 +0000 Subject: [PATCH 038/138] [MOVED FROM GST-P-FARSIGHT] Search&Replace oops 20070917175233-3e2dc-57f579c4b890993f49fa8e9e6470a3eb79d2b922.gz --- gst/dtmf/gstrtpdtmfsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index faa4c3e1da..21919a264e 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -900,7 +900,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) /* get first structure */ s = gst_caps_get_structure (srccaps, 0); - if (gst_structure_get_int (s, "dtmfsrc", &pt)) { + if (gst_structure_get_int (s, "payload", &pt)) { /* use peer pt */ dtmfsrc->pt = pt; GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt); From 5ae478a6449d3f4b5b7d1e38449bec56dac23195 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sat, 16 Feb 2008 13:41:40 +0000 Subject: [PATCH 039/138] [MOVED FROM GST-P-FARSIGHT] dtmfsrc: Correctly set the endianess in the caps to the machines endianess 20080216134140-93b9a-40a3a9d7ac1679c5e0dfd24a6b91e4aba6cc6496.gz --- gst/dtmf/gstdtmfsrc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index e0a73dd1ed..444a79df6f 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -225,7 +225,11 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("audio/x-raw-int, " "width = (int) 16, " "depth = (int) 16, " +#if G_BYTE_ORDER == G_LITTLE_ENDIAN "endianness = (int) 1234, " +#else + "endianness = (int) 4321, " +#endif "signed = (bool) true, " "rate = (int) 8000, " "channels = (int) 1") From 4ec9f3fdfc5c4a4b4fcda2e3492fdd5ae7c82270 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 00:50:41 +0000 Subject: [PATCH 040/138] [MOVED FROM GST-P-FARSIGHT] Fix typos 20080320005041-4f0f6-9d22fa5d155e35b605ea85b1fd9e7197a882a1f0.gz --- gst/dtmf/gstrtpdtmfsrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 21919a264e..0fcce3faba 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -698,7 +698,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, case RTP_DTMF_EVENT_TYPE_START: dtmfsrc->first_packet = TRUE; dtmfsrc->last_packet = FALSE; - /* Set the redundanc on the first packet */ + /* Set the redundancy on the first packet */ dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; gst_rtp_dtmf_prepare_timestamps (dtmfsrc); @@ -742,7 +742,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, case RTP_DTMF_EVENT_TYPE_STOP: dtmfsrc->first_packet = FALSE; dtmfsrc->last_packet = TRUE; - /* Set the redundanc on the last packet */ + /* Set the redundancy on the last packet */ dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; break; From da5a98e09221bf2a0da7b1eb51ae046f773cf70e Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 00:51:47 +0000 Subject: [PATCH 041/138] [MOVED FROM GST-P-FARSIGHT] Adding necessary files for rtpdtmfdepay 20080320005147-4f0f6-550fe22f70152f3aab3dcd7a6b02cbf81e89232d.gz --- gst/dtmf/gstrtpdtmfcommon.h | 22 ++ gst/dtmf/gstrtpdtmfdepay.c | 444 ++++++++++++++++++++++++++++++++++++ gst/dtmf/gstrtpdtmfdepay.h | 67 ++++++ 3 files changed, 533 insertions(+) create mode 100644 gst/dtmf/gstrtpdtmfcommon.h create mode 100644 gst/dtmf/gstrtpdtmfdepay.c create mode 100644 gst/dtmf/gstrtpdtmfdepay.h diff --git a/gst/dtmf/gstrtpdtmfcommon.h b/gst/dtmf/gstrtpdtmfcommon.h new file mode 100644 index 0000000000..097afa9012 --- /dev/null +++ b/gst/dtmf/gstrtpdtmfcommon.h @@ -0,0 +1,22 @@ + +#ifndef __GST_RTP_DTMF_COMMON_H__ +#define __GST_RTP_DTMF_COMMON_H__ + + +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/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c new file mode 100644 index 0000000000..bf90a12fe7 --- /dev/null +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -0,0 +1,444 @@ +/* GStreamer + * + * Copyright 2007 Nokia Corporation + * Copyright 2007 Collabora Ltd, + * @author: Philippe Kalaf + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include "gstrtpdtmfdepay.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 /* pi */ +#endif + + +#define GST_TONE_DTMF_TYPE_EVENT 0 +#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_EVENT 0 +#define MAX_EVENT 16 +#define MIN_VOLUME 0 +#define MAX_VOLUME 36 +#define MIN_INTER_DIGIT_INTERVAL 100 +#define MIN_PULSE_DURATION 250 +#define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) + + +typedef struct st_dtmf_key { + 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, +}; + +/* elementfactory information */ +static const GstElementDetails gst_rtp_dtmfdepay_details = +GST_ELEMENT_DETAILS ("RTP DTMF packet depayloader", + "Codec/Depayloader/Network", + "Generates DTMF Sound from telephone-event RTP packets", + "Youness Alaoui "); + +GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_depay_debug); +#define GST_CAT_DEFAULT gst_rtp_dtmf_depay_debug + +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +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-int, " + "width = (int) 16, " + "depth = (int) 16, " + "endianness = (int) 1234, " + "signed = (boolean) true, " + "rate = (int) [0, MAX], " + "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\"") + ); + +GST_BOILERPLATE (GstRtpDTMFDepay, gst_rtp_dtmf_depay, GstBaseRTPDepayload, + GST_TYPE_BASE_RTP_DEPAYLOAD); + + +static GstBuffer *gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, + GstBuffer * buf); +gboolean gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, + GstCaps * caps); + +/*static void +gst_rtp_dtmf_depay_set_gst_timestamp (GstBaseRTPDepayload * filter, + guint32 rtptime, GstBuffer * buf); +*/ + +static void +gst_rtp_dtmf_depay_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_dtmf_depay_src_template)); + gst_element_class_add_pad_template (element_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_details (element_class, &gst_rtp_dtmfdepay_details); +} + +static void +gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gstbasertpdepayload_class->process = gst_rtp_dtmf_depay_process; + gstbasertpdepayload_class->set_caps = gst_rtp_dtmf_depay_setcaps; + // gstbasertpdepayload_class->set_gst_timestamp = gst_rtp_dtmf_depay_set_gst_timestamp; + +} + +static void +gst_rtp_dtmf_depay_init (GstRtpDTMFDepay * rtpdtmfdepay, + GstRtpDTMFDepayClass * klass) +{ + +} + + +gboolean +gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) +{ + GstCaps *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; + + srccaps = gst_caps_new_simple ("audio/x-raw-int", + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, 1234, + "signed", G_TYPE_BOOLEAN, TRUE, + "channels", G_TYPE_INT, 1, + "rate", G_TYPE_INT, clock_rate, NULL); + gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (filter), srccaps); + gst_caps_unref (srccaps); + + return TRUE; +} + +void +gst_rtp_dtmf_depay_set_gst_timestamp (GstBaseRTPDepayload * filter, + guint32 rtptime, GstBuffer * buf) +{ + GstClockTime timestamp, duration; + + + timestamp = GST_BUFFER_TIMESTAMP (buf); + duration = GST_BUFFER_DURATION (buf); + + /* if this is the first buffer send a NEWSEGMENT */ + if (filter->need_newsegment) { + GstEvent *event; + GstClockTime stop, position; + + stop = -1; + + position = 0; + + event = + gst_event_new_new_segment_full (FALSE, 1.0, + 1.0, GST_FORMAT_TIME, 0, stop, position); + + gst_pad_push_event (filter->srcpad, event); + + filter->need_newsegment = FALSE; + GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer"); + } +} + +#if 0 +static void +gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration) +{ + gint buf_size; + + /* Create a buffer with data set to 0 */ + buf_size = ((duration/1000)*SAMPLE_RATE*SAMPLE_SIZE*CHANNELS)/8; + GST_BUFFER_SIZE (buffer) = buf_size; + GST_BUFFER_MALLOCDATA (buffer) = g_malloc0(buf_size); + GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); + +} +#endif + +static void +gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, + GstRTPDTMFPayload payload, GstBuffer * buffer) +{ + 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 */; + GstBaseRTPDepayload * depayload = GST_BASE_RTP_DEPAYLOAD (rtpdtmfdepay); + + clock_rate = depayload->clock_rate; + + /* Create a buffer for the tone */ + tone_size = (payload.duration*SAMPLE_SIZE*CHANNELS)/8; + GST_BUFFER_SIZE (buffer) = tone_size; + GST_BUFFER_MALLOCDATA (buffer) = g_malloc(tone_size); + GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); + GST_BUFFER_DURATION (buffer) = payload.duration * GST_SECOND / clock_rate; + + p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); + + volume_factor = pow (10, (-payload.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)++; + } +} + + +static GstBuffer * +gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * 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; + + rtpdtmfdepay = GST_RTP_DTMF_DEPAY (depayload); + + if (!gst_rtp_buffer_validate (buf)) + goto bad_packet; + + payload_len = gst_rtp_buffer_get_payload_len (buf); + payload = gst_rtp_buffer_get_payload (buf); + + 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 (buf); + + timestamp = gst_rtp_buffer_get_timestamp (buf); + + dtmf_payload.duration = g_ntohs (dtmf_payload.duration); + + 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_TIMESTAMP (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_DEBUG_OBJECT (depayload, "Unable to send dtmf-event message to bus"); + } + } else { + GST_DEBUG_OBJECT (depayload, "Unable to create dtmf-event message"); + } + } else { + GST_DEBUG_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 : %llu", + 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_buffer_new (); + gst_dtmf_src_generate_tone(rtpdtmfdepay, dtmf_payload, outbuf); + + + GST_BUFFER_TIMESTAMP (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 : %llu - time %" GST_TIME_FORMAT, + GST_BUFFER_TIMESTAMP (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + } + + return outbuf; + + +bad_packet: + GST_ELEMENT_WARNING (rtpdtmfdepay, STREAM, DECODE, + ("Packet did not validate"), (NULL)); + 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 new file mode 100644 index 0000000000..68313ad27d --- /dev/null +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans + * Copyright (C) <2008> Collabora. + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_DTMF_DEPAY_H__ +#define __GST_RTP_DTMF_DEPAY_H__ + +#include +#include +#include + +#include "gstrtpdtmfcommon.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 +{ + GstBaseRTPDepayload depayload; + double sample; + guint32 previous_ts; + guint16 previous_duration; + GstClockTime first_gst_ts; + +}; + +struct _GstRtpDTMFDepayClass +{ + GstBaseRTPDepayloadClass parent_class; +}; + +gboolean gst_rtp_dtmf_depay_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_DTMF_DEPAY_H__ */ From b7bb5cd6a0ff49b58e30e31f70797f9559c73934 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Wed, 19 Mar 2008 19:32:51 +0000 Subject: [PATCH 042/138] [MOVED FROM GST-P-FARSIGHT] encoding name has to be upper-case 20080319193251-3e2dc-1581b33be9b486e35ec4948009677ccd5ffdc098.gz --- gst/dtmf/gstrtpdtmfsrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 0fcce3faba..76c2b0e77f 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -194,7 +194,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "payload = (int) [ 96, 127 ], " "clock-rate = (int) [ 0, MAX ], " "ssrc = (int) [ 0, MAX ], " - "encoding-name = (string) \"telephone-event\"") + "encoding-name = (string) \"TELEPHONE-EVENT\"") /* "events = (string) \"1-16\" */ ); @@ -857,7 +857,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) srccaps = gst_caps_new_simple ("application/x-rtp", "media", G_TYPE_STRING, "audio", "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, - "encoding-name", G_TYPE_STRING, "telephone-event", NULL); + "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT", NULL); /* the peer caps can override some of the defaults */ peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc)); From ea50b44330175dbeee46e0db817e42da73d6e2cb Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 01:13:01 +0000 Subject: [PATCH 043/138] [MOVED FROM GST-P-FARSIGHT] Adding support for rtpdtmfdepay 20080320011301-4f0f6-d36a5d24be20336e36c4796d75476c9b5ee1a7e1.gz --- gst/dtmf/Makefile.am | 5 ++++- gst/dtmf/gstdtmf.c | 4 ++++ gst/dtmf/gstrtpdtmfsrc.h | 17 ++--------------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index 210dcadeae..abc471848d 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -2,10 +2,13 @@ plugin_LTLIBRARIES = libgstdtmf.la libgstdtmf_la_SOURCES = gstdtmfsrc.c \ gstrtpdtmfsrc.c \ + gstrtpdtmfdepay.c \ gstdtmf.c noinst_HEADERS = gstdtmfsrc.h \ - gstrtpdtmfsrc.h + gstrtpdtmfsrc.h \ + gstrtpdtmfdepay.h \ + gstrtpdtmfcommon.h libgstdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c index 3086885748..86bbafa584 100644 --- a/gst/dtmf/gstdtmf.c +++ b/gst/dtmf/gstdtmf.c @@ -5,6 +5,7 @@ #include "gstdtmfsrc.h" #include "gstrtpdtmfsrc.h" +#include "gstrtpdtmfdepay.h" static gboolean @@ -17,6 +18,9 @@ plugin_init (GstPlugin * plugin) return FALSE; + if (!gst_rtp_dtmf_depay_plugin_init (plugin)) + return FALSE; + return TRUE; } diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 4114f23c09..ade3a67a46 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -29,6 +29,8 @@ #include #include +#include "gstrtpdtmfcommon.h" + G_BEGIN_DECLS #define GST_TYPE_RTP_DTMF_SRC (gst_rtp_dtmf_src_get_type()) @@ -39,21 +41,6 @@ G_BEGIN_DECLS #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 { - 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; typedef struct _GstRTPDTMFSrc GstRTPDTMFSrc; typedef struct _GstRTPDTMFSrcClass GstRTPDTMFSrcClass; From 0fe93241295635a2324f66abf176e8a0086dc28d Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 18:39:12 +0000 Subject: [PATCH 044/138] [MOVED FROM GST-P-FARSIGHT] Fix copyrights 20080320183912-4f0f6-689365d5a406632e3d088fac74e4fb6f8a4eb0ea.gz --- gst/dtmf/gstrtpdtmfdepay.c | 10 ++++------ gst/dtmf/gstrtpdtmfdepay.h | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index bf90a12fe7..b2c676d88d 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -1,10 +1,8 @@ -/* GStreamer +/* GstRtpDtmfDepay * - * Copyright 2007 Nokia Corporation - * Copyright 2007 Collabora Ltd, - * @author: Philippe Kalaf - * - * Copyright (C) <2005> Wim Taymans + * Copyright (C) <2008> Collabora. + * Copyright (C) <2008> Nokia. + * 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 diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index 68313ad27d..63c4d22f47 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -1,6 +1,7 @@ -/* GStreamer - * Copyright (C) <2005> Wim Taymans +/* GstRtpDtmfDepay + * * Copyright (C) <2008> Collabora. + * Copyright (C) <2008> Nokia. * Contact: Youness Alaoui * * This library is free software; you can redistribute it and/or From f3bcdb3a297a739348b377b3ec4fa8c023aff386 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 18:39:37 +0000 Subject: [PATCH 045/138] [MOVED FROM GST-P-FARSIGHT] Clean unused stuff... 20080320183937-4f0f6-bcb841cdc07f9e9677512f4b50b4b659a58c6783.gz --- gst/dtmf/gstrtpdtmfdepay.c | 52 -------------------------------------- 1 file changed, 52 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index b2c676d88d..1f714cc791 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -35,7 +35,6 @@ #endif -#define GST_TONE_DTMF_TYPE_EVENT 0 #define DEFAULT_PACKET_INTERVAL 50 /* ms */ #define MIN_PACKET_INTERVAL 10 /* ms */ #define MAX_PACKET_INTERVAL 50 /* ms */ @@ -152,11 +151,6 @@ static GstBuffer *gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, gboolean gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps); -/*static void -gst_rtp_dtmf_depay_set_gst_timestamp (GstBaseRTPDepayload * filter, - guint32 rtptime, GstBuffer * buf); -*/ - static void gst_rtp_dtmf_depay_base_init (gpointer klass) { @@ -188,7 +182,6 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) gstbasertpdepayload_class->process = gst_rtp_dtmf_depay_process; gstbasertpdepayload_class->set_caps = gst_rtp_dtmf_depay_setcaps; - // gstbasertpdepayload_class->set_gst_timestamp = gst_rtp_dtmf_depay_set_gst_timestamp; } @@ -223,51 +216,6 @@ gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) return TRUE; } -void -gst_rtp_dtmf_depay_set_gst_timestamp (GstBaseRTPDepayload * filter, - guint32 rtptime, GstBuffer * buf) -{ - GstClockTime timestamp, duration; - - - timestamp = GST_BUFFER_TIMESTAMP (buf); - duration = GST_BUFFER_DURATION (buf); - - /* if this is the first buffer send a NEWSEGMENT */ - if (filter->need_newsegment) { - GstEvent *event; - GstClockTime stop, position; - - stop = -1; - - position = 0; - - event = - gst_event_new_new_segment_full (FALSE, 1.0, - 1.0, GST_FORMAT_TIME, 0, stop, position); - - gst_pad_push_event (filter->srcpad, event); - - filter->need_newsegment = FALSE; - GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer"); - } -} - -#if 0 -static void -gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration) -{ - gint buf_size; - - /* Create a buffer with data set to 0 */ - buf_size = ((duration/1000)*SAMPLE_RATE*SAMPLE_SIZE*CHANNELS)/8; - GST_BUFFER_SIZE (buffer) = buf_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc0(buf_size); - GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); - -} -#endif - static void gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, GstRTPDTMFPayload payload, GstBuffer * buffer) From c8be507679048e9173f424a420cb183a53b845a2 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 18:48:41 +0000 Subject: [PATCH 046/138] [MOVED FROM GST-P-FARSIGHT] debug message made into errors because that's what they are... 20080320184841-4f0f6-8a2d283297b02713dade0ae4acaa5f6e0f67eace.gz --- gst/dtmf/gstrtpdtmfdepay.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 1f714cc791..4350f22179 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -330,13 +330,13 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) dtmf_message = gst_message_new_element (GST_OBJECT (depayload), structure); if (dtmf_message) { if (!gst_element_post_message (GST_ELEMENT (depayload), dtmf_message)) { - GST_DEBUG_OBJECT (depayload, "Unable to send dtmf-event message to bus"); + GST_ERROR_OBJECT (depayload, "Unable to send dtmf-event message to bus"); } } else { - GST_DEBUG_OBJECT (depayload, "Unable to create dtmf-event message"); + GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event message"); } } else { - GST_DEBUG_OBJECT (depayload, "Unable to create dtmf-event structure"); + GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event structure"); } } else { guint16 duration = dtmf_payload.duration; From f819f80e808c52fcfd3cfb9760ddfc59e7e239e9 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Wed, 19 Mar 2008 21:17:31 +0000 Subject: [PATCH 047/138] [MOVED FROM GST-P-FARSIGHT] Make it clear that dtmfsrc also takes named events as input 20080319211731-3e2dc-26c729f6dc8db27e71cf6b22646a81530dbf862f.gz --- gst/dtmf/gstdtmfsrc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 444a79df6f..71e5dbb91c 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -64,7 +64,7 @@ * 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. This element is only capable of generating tones. + * named events. This element is only capable of generating named events. * * * @@ -91,9 +91,9 @@ * * method * G_TYPE_INT - * 1 - * The method used for sending event, this element will react if this field - * is absent or 2. + * 2 + * The method used for sending event, this element will react if this + * field is absent or 2. * * * @@ -109,7 +109,7 @@ * * * structure = gst_structure_new ("dtmf-event", - * "type", G_TYPE_INT, 0, + * "type", G_TYPE_INT, 1, * "number", G_TYPE_INT, 1, * "volume", G_TYPE_INT, 25, * "start", G_TYPE_BOOLEAN, TRUE, NULL); @@ -139,7 +139,7 @@ #include "gstdtmfsrc.h" -#define GST_TONE_DTMF_TYPE_EVENT 0 +#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 */ From 41e8f4658b071834a20b886e0b193fe00c04ef8d Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 20 Mar 2008 19:14:38 +0000 Subject: [PATCH 048/138] [MOVED FROM GST-P-FARSIGHT] Fix copyrights again, per smcv's advice.. 20080320191438-4f0f6-671c9db5d996a4601df017ceab4af6d16469c966.gz --- gst/dtmf/gstrtpdtmfdepay.c | 4 ++-- gst/dtmf/gstrtpdtmfdepay.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 4350f22179..f90978a20a 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -1,7 +1,7 @@ /* GstRtpDtmfDepay * - * Copyright (C) <2008> Collabora. - * Copyright (C) <2008> Nokia. + * Copyright (C) 2008 Collabora Limited + * Copyright (C) 2008 Nokia Corporation * Contact: Youness Alaoui * * This library is free software; you can redistribute it and/or diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index 63c4d22f47..9a1953febf 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -1,7 +1,7 @@ /* GstRtpDtmfDepay * - * Copyright (C) <2008> Collabora. - * Copyright (C) <2008> Nokia. + * Copyright (C) 2008 Collabora Limited + * Copyright (C) 2008 Nokia Corporation * Contact: Youness Alaoui * * This library is free software; you can redistribute it and/or From 4bc6ae9570165f55c48d9f16509b444e4e0a40dc Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Sat, 12 Apr 2008 23:44:18 +0000 Subject: [PATCH 049/138] [MOVED FROM GST-P-FARSIGHT] Fix byte ordering issues with dtmfsrc and rtpdtmfdepay.. use of G_STRINGIFY to avoid error on MSVC 20080412234418-4f0f6-4828d1613dfcd564afd236dfc8fb57a299092f83.gz --- gst/dtmf/gstdtmfsrc.c | 6 +----- gst/dtmf/gstrtpdtmfdepay.c | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 71e5dbb91c..38470a00e4 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -225,11 +225,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("audio/x-raw-int, " "width = (int) 16, " "depth = (int) 16, " -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - "endianness = (int) 1234, " -#else - "endianness = (int) 4321, " -#endif + "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " "signed = (bool) true, " "rate = (int) 8000, " "channels = (int) 1") diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index f90978a20a..d1096c8777 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -125,7 +125,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("audio/x-raw-int, " "width = (int) 16, " "depth = (int) 16, " - "endianness = (int) 1234, " + "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " "signed = (boolean) true, " "rate = (int) [0, MAX], " "channels = (int) 1") @@ -206,7 +206,7 @@ gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) srccaps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, 1234, + "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, clock_rate, NULL); From 26e8fb13611c8fdc626f4eb76999786ced0ae9f8 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Mon, 28 Apr 2008 22:22:37 +0000 Subject: [PATCH 050/138] [MOVED FROM GST-P-FARSIGHT] Link modules with libm where required 20080428222237-3e2dc-b1e9120c1e9ca1a510bfd7c27e2d45f0d4a12504.gz --- gst/dtmf/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index abc471848d..c96a3a4129 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -11,6 +11,6 @@ noinst_HEADERS = gstdtmfsrc.h \ gstrtpdtmfcommon.h libgstdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT -libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) +libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) -lm libgstdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ From de1e6bb778a92f1705d8ba5efb2991de0954f7c6 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Fri, 13 Jun 2008 23:30:06 +0000 Subject: [PATCH 051/138] [MOVED FROM GST-P-FARSIGHT] Take the clock-rate from the caps in rtpdtmfsrc 20080613233006-3e2dc-a7d4e918643f4f8c1bb2cc2678558c654025920e.gz --- gst/dtmf/gstrtpdtmfsrc.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 76c2b0e77f..58dceb4661 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -195,7 +195,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "clock-rate = (int) [ 0, MAX ], " "ssrc = (int) [ 0, MAX ], " "encoding-name = (string) \"TELEPHONE-EVENT\"") - /* "events = (string) \"1-16\" */ + /* "events = (string) \"0-15\" */ ); @@ -856,7 +856,6 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) /* fill in the defaults, there properties cannot be negotiated. */ srccaps = gst_caps_new_simple ("application/x-rtp", "media", G_TYPE_STRING, "audio", - "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT", NULL); /* the peer caps can override some of the defaults */ @@ -867,6 +866,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) "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); @@ -875,6 +875,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) 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. */ @@ -919,6 +920,19 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) } } + 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); From d881f34e0e2391c3273dee361e2a8dfa21fa5776 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Fri, 13 Jun 2008 23:41:44 +0000 Subject: [PATCH 052/138] [MOVED FROM GST-P-FARSIGHT] Put the sample rate in dtmfsrc into a variable 20080613234144-3e2dc-e60070943bec829b703b8821c7aa4351a02deebe.gz --- gst/dtmf/gstdtmfsrc.c | 25 ++++++++++++++----------- gst/dtmf/gstdtmfsrc.h | 2 ++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 38470a00e4..55c1a4aa92 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -143,7 +143,7 @@ #define DEFAULT_PACKET_INTERVAL 50 /* ms */ #define MIN_PACKET_INTERVAL 10 /* ms */ #define MAX_PACKET_INTERVAL 50 /* ms */ -#define SAMPLE_RATE 8000 +#define DEFAULT_SAMPLE_RATE 8000 #define SAMPLE_SIZE 16 #define CHANNELS 1 #define MIN_EVENT 0 @@ -242,8 +242,6 @@ static void gst_dtmf_src_get_property (GObject * object, guint prop_id, static gboolean gst_dtmf_src_handle_event (GstBaseSrc *src, GstEvent * event); static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition); -static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, - float duration, GstBuffer * buffer); static GstFlowReturn gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer); static void gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, @@ -318,6 +316,8 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass *g_class) dtmfsrc->event_queue = g_async_queue_new (); dtmfsrc->last_event = NULL; + dtmfsrc->sample_rate = DEFAULT_SAMPLE_RATE; + GST_DEBUG_OBJECT (dtmfsrc, "init done"); } @@ -522,12 +522,13 @@ gst_dtmf_src_add_stop_event (GstDTMFSrc *dtmfsrc) } static void -gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration) +gst_dtmf_src_generate_silence(GstBuffer * buffer, 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; + buf_size = ((duration/1000)*sample_rate*SAMPLE_SIZE*CHANNELS)/8; GST_BUFFER_SIZE (buffer) = buf_size; GST_BUFFER_MALLOCDATA (buffer) = g_malloc0(buf_size); GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); @@ -536,7 +537,7 @@ gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration) static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, - GstBuffer * buffer) + GstBuffer * buffer, gint sample_rate) { gint16 *p; gint tone_size; @@ -545,7 +546,7 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, double volume_factor; /* Create a buffer for the tone */ - tone_size = ((duration/1000)*SAMPLE_RATE*SAMPLE_SIZE*CHANNELS)/8; + tone_size = ((duration/1000)*sample_rate*SAMPLE_SIZE*CHANNELS)/8; GST_BUFFER_SIZE (buffer) = tone_size; GST_BUFFER_MALLOCDATA (buffer) = g_malloc(tone_size); GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); @@ -562,8 +563,8 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, /* * 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)); + 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; @@ -602,11 +603,12 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, if (send_silence) { GST_DEBUG_OBJECT (dtmfsrc, "Generating silence"); - gst_dtmf_src_generate_silence (buf, dtmfsrc->interval); + gst_dtmf_src_generate_silence (buf, dtmfsrc->interval, + dtmfsrc->sample_rate); } else { GST_DEBUG_OBJECT (dtmfsrc, "Generating tone"); gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], - dtmfsrc->interval, buf); + dtmfsrc->interval, buf, dtmfsrc->sample_rate); } event->packet_count++; @@ -806,6 +808,7 @@ gst_dtmf_src_unlock_stop (GstBaseSrc *src) { return TRUE; } + static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) { diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 0340a7c2b2..fdf6f50d9d 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -79,6 +79,8 @@ struct _GstDTMFSrc { gboolean paused; GstClockID clockid; + + gint sample_rate; }; From f0da427c6180687bbd22055a725d0f73e322fa87 Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Fri, 13 Jun 2008 23:57:23 +0000 Subject: [PATCH 053/138] [MOVED FROM GST-P-FARSIGHT] Take rate from the peers caps if possible 20080613235723-3e2dc-15690ee42708c539e1be12e20e076a5613faea96.gz --- gst/dtmf/gstdtmfsrc.c | 81 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 55c1a4aa92..19a1230ed1 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -251,6 +251,7 @@ 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_base_init (gpointer g_class) @@ -300,7 +301,8 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) 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); } @@ -809,6 +811,83 @@ gst_dtmf_src_unlock_stop (GstBaseSrc *src) { } +static gboolean +gst_dtmf_src_negotiate (GstBaseSrc * basesrc) +{ + GstCaps *srccaps, *peercaps; + GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (basesrc); + gboolean ret = FALSE; + + srccaps = gst_caps_new_simple ("audio/x-raw-int", + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "signed", G_TYPE_BOOLEAN, TRUE, + "channels", G_TYPE_INT, 1, + NULL); + + peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc)); + + if (peercaps == NULL) { + /* no peer caps, just add the other properties */ + gst_caps_set_simple (srccaps, + "rate", G_TYPE_INT, dtmfsrc->sample_rate, + NULL); + } else { + GstStructure *s; + gint sample_rate; + GstCaps *temp = NULL; + + g_debug ("HAS PEERCAPS %s", gst_caps_to_string (peercaps)); + + /* 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 */ + gst_caps_truncate (temp); + srccaps = temp; + + /* get first structure */ + s = gst_caps_get_structure (srccaps, 0); + + if (gst_structure_get_int (s, "rate", &sample_rate)) + { + dtmfsrc->sample_rate = sample_rate; + GST_LOG_OBJECT (dtmfsrc, "using rate from caps %d", + dtmfsrc->sample_rate); + } else { + GST_LOG_OBJECT (dtmfsrc, "using existing rate %d", + dtmfsrc->sample_rate); + } + gst_structure_set (s, "rate", G_TYPE_INT, dtmfsrc->sample_rate, + NULL); + } + + ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), srccaps); + + g_warning ("negotiated %s", gst_caps_to_string (srccaps)); + + + + gst_caps_unref (srccaps); + + return ret; +} + static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) { From 9154bb29ffe5e74cd779370a00f1cc788d2a337b Mon Sep 17 00:00:00 2001 From: Olivier Crete Date: Tue, 22 Jul 2008 21:39:38 +0000 Subject: [PATCH 054/138] [MOVED FROM GST-P-FARSIGHT] Remove g_debugs 20080722213938-3e2dc-44a82d017fe66f3112301c410aa0b543de6156ad.gz --- gst/dtmf/gstdtmfsrc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 19a1230ed1..07359361b9 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -838,8 +838,6 @@ gst_dtmf_src_negotiate (GstBaseSrc * basesrc) gint sample_rate; GstCaps *temp = NULL; - g_debug ("HAS PEERCAPS %s", gst_caps_to_string (peercaps)); - /* peer provides caps we can use to fixate, intersect. This always returns a * writable caps. */ temp = gst_caps_intersect (srccaps, peercaps); @@ -879,10 +877,6 @@ gst_dtmf_src_negotiate (GstBaseSrc * basesrc) ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), srccaps); - g_warning ("negotiated %s", gst_caps_to_string (srccaps)); - - - gst_caps_unref (srccaps); return ret; From 918d78dd2287b69ccf4eef5686462d2c85c85cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 15 Oct 2008 16:21:50 -0400 Subject: [PATCH 055/138] [MOVED FROM GST-P-FARSIGHT] Clarify the documentation of the "event-type" field when specifying dtmf events --- gst/dtmf/gstdtmfsrc.c | 4 +++- gst/dtmf/gstrtpdtmfsrc.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 07359361b9..4b2f9a2b5b 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -64,7 +64,9 @@ * 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. This element is only capable of generating named events. + * 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. * * * diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 58dceb4661..48db31337e 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -62,7 +62,9 @@ * 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. This element is only capable of generating named events. + * 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. * * * From 256bdeb4c4f3dc6c200798857999c4700a66fbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Graff?= Date: Mon, 1 Dec 2008 17:37:10 -0500 Subject: [PATCH 056/138] [MOVED FROM GST-P-FARSIGHT] Do wierd casting of the volume to make MSVC happy --- gst/dtmf/gstrtpdtmfdepay.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index d1096c8777..fad657920b 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -228,6 +228,7 @@ gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, DTMF_KEY key = DTMF_KEYS[payload.event]; guint32 clock_rate = 8000 /* default */; GstBaseRTPDepayload * depayload = GST_BASE_RTP_DEPAYLOAD (rtpdtmfdepay); + gint volume; clock_rate = depayload->clock_rate; @@ -237,10 +238,11 @@ gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, GST_BUFFER_MALLOCDATA (buffer) = g_malloc(tone_size); GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); GST_BUFFER_DURATION (buffer) = payload.duration * GST_SECOND / clock_rate; + volume = payload.volume; p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); - volume_factor = pow (10, (-payload.volume) / 20); + volume_factor = pow (10, (-volume) / 20); /* * For each sample point we calculate 'x' as the From fe9455bfde938e85bd20737388a31b56857c522f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 11 Dec 2008 17:54:18 -0500 Subject: [PATCH 057/138] [MOVED FROM GST-P-FARSIGHT] Remove .git-darcs-dir files --- gst/dtmf/.git-darcs-dir | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gst/dtmf/.git-darcs-dir diff --git a/gst/dtmf/.git-darcs-dir b/gst/dtmf/.git-darcs-dir deleted file mode 100644 index e69de29bb2..0000000000 From aa5cab8948bd03dd976b8213811c3607ed621536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 1 Dec 2008 18:31:48 -0500 Subject: [PATCH 058/138] [MOVED FROM GST-P-FARSIGHT] Allow setting a minimum size of a sound quanta in the dtmf depayloader --- gst/dtmf/gstrtpdtmfdepay.c | 74 +++++++++++++++++++++++++++++++++++--- gst/dtmf/gstrtpdtmfdepay.h | 1 + 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index fad657920b..8e82865a79 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -49,6 +49,9 @@ #define MIN_PULSE_DURATION 250 #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 typedef struct st_dtmf_key { char *event_name; @@ -109,10 +112,18 @@ GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_depay_debug); enum { + + /* FILL ME */ LAST_SIGNAL }; +enum +{ + PROP_0, + PROP_UNIT_TIME +}; + enum { ARG_0 @@ -145,7 +156,10 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_BOILERPLATE (GstRtpDTMFDepay, gst_rtp_dtmf_depay, GstBaseRTPDepayload, GST_TYPE_BASE_RTP_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 (GstBaseRTPDepayload * depayload, GstBuffer * buf); gboolean gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, @@ -180,8 +194,20 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) parent_class = g_type_class_peek_parent (klass); - gstbasertpdepayload_class->process = gst_rtp_dtmf_depay_process; - gstbasertpdepayload_class->set_caps = gst_rtp_dtmf_depay_setcaps; + 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)); + + gstbasertpdepayload_class->process = + GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process); + gstbasertpdepayload_class->set_caps = + GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_setcaps); } @@ -189,9 +215,44 @@ static void gst_rtp_dtmf_depay_init (GstRtpDTMFDepay * rtpdtmfdepay, GstRtpDTMFDepayClass * klass) { - + 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; + 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; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} gboolean gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) @@ -308,6 +369,11 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) dtmf_payload.duration = g_ntohs (dtmf_payload.duration); + /* clip to whole units of unit_time */ + if (rtpdtmfdepay->unit_time) + dtmf_payload.duration -= dtmf_payload.duration % + ((rtpdtmfdepay->unit_time * depayload->clock_rate) / 1000); + 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); diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index 9a1953febf..e679fbb568 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -53,6 +53,7 @@ struct _GstRtpDTMFDepay guint32 previous_ts; guint16 previous_duration; GstClockTime first_gst_ts; + guint unit_time; }; From 853337f1cc65aa8cfa9b1f9fb89de4175c2b64fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 4 Dec 2008 21:11:17 -0500 Subject: [PATCH 059/138] [MOVED FROM GST-P-FARSIGHT] Improve the minimum quanta to make it impossible for the duration to fall down to 0 --- gst/dtmf/gstrtpdtmfdepay.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 8e82865a79..85dac6fef9 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -371,8 +371,19 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) /* clip to whole units of unit_time */ if (rtpdtmfdepay->unit_time) - dtmf_payload.duration -= dtmf_payload.duration % - ((rtpdtmfdepay->unit_time * depayload->clock_rate) / 1000); + { + 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; + } + } GST_DEBUG_OBJECT (depayload, "Received new RTP DTMF packet : " "marker=%d - timestamp=%u - event=%d - duration=%d", From c50e962be0a84a6e0e4b322ceb81d09b42c20faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 4 Dec 2008 21:21:44 -0500 Subject: [PATCH 060/138] [MOVED FROM GST-P-FARSIGHT] Allow setting a maximum duration to a RTP DTMF event --- gst/dtmf/gstrtpdtmfdepay.c | 28 +++++++++++++++++++++++++++- gst/dtmf/gstrtpdtmfdepay.h | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 85dac6fef9..20321893f3 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -53,6 +53,8 @@ #define MAX_UNIT_TIME 1000 #define DEFAULT_UNIT_TIME 0 +#define DEFAULT_MAX_DURATION 0 + typedef struct st_dtmf_key { char *event_name; int event_encoding; @@ -121,7 +123,8 @@ enum enum { PROP_0, - PROP_UNIT_TIME + PROP_UNIT_TIME, + PROP_MAX_DURATION }; enum @@ -204,6 +207,12 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) "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_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)); + gstbasertpdepayload_class->process = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process); gstbasertpdepayload_class->set_caps = @@ -230,6 +239,9 @@ gst_rtp_dtmf_depay_set_property (GObject * object, guint 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; @@ -248,6 +260,9 @@ gst_rtp_dtmf_depay_get_property (GObject * object, guint 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; @@ -385,6 +400,17 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } } + /* 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); diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index e679fbb568..4fb31a0dcf 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -54,7 +54,7 @@ struct _GstRtpDTMFDepay guint16 previous_duration; GstClockTime first_gst_ts; guint unit_time; - + guint max_duration; }; struct _GstRtpDTMFDepayClass From d89e80f1c90e45b79c062adc18db54ca18dc0048 Mon Sep 17 00:00:00 2001 From: Laurent Glayal Date: Wed, 18 Feb 2009 13:30:44 -0500 Subject: [PATCH 061/138] [MOVED FROM GST-P-FARSIGHT] Missing format directive --- gst/dtmf/gstrtpdtmfsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 48db31337e..588cda493e 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -918,7 +918,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) /* 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", pt); + GST_LOG_OBJECT (dtmfsrc, "using internal pt %d", pt); } } From 22b1337ed70b0aeaa570307d19c5baa99bbe37b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 20 Feb 2009 17:37:43 -0500 Subject: [PATCH 062/138] Re-indent to Gst style --- gst/dtmf/gstdtmf.c | 4 +- gst/dtmf/gstdtmfsrc.c | 236 +++++++++++++++++------------------- gst/dtmf/gstdtmfsrc.h | 41 ++++--- gst/dtmf/gstrtpdtmfcommon.h | 19 +-- gst/dtmf/gstrtpdtmfdepay.c | 165 +++++++++++++------------ gst/dtmf/gstrtpdtmfdepay.h | 14 +-- gst/dtmf/gstrtpdtmfsrc.c | 129 ++++++++++---------- gst/dtmf/gstrtpdtmfsrc.h | 66 +++++----- 8 files changed, 324 insertions(+), 350 deletions(-) diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c index 86bbafa584..4d9d1a5922 100644 --- a/gst/dtmf/gstdtmf.c +++ b/gst/dtmf/gstdtmf.c @@ -26,6 +26,4 @@ plugin_init (GstPlugin * plugin) GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - "dtmf", - "DTMF plugins", - plugin_init, "0.1" , "LGPL", "DTMF", ""); + "dtmf", "DTMF plugins", plugin_init, "0.1", "LGPL", "DTMF", ""); diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 4b2f9a2b5b..06e27d4435 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -142,9 +142,9 @@ #include "gstdtmfsrc.h" #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_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 @@ -157,51 +157,53 @@ #define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) -typedef struct st_dtmf_key { - char *event_name; - int event_encoding; - float low_frequency; - float high_frequency; +typedef struct st_dtmf_key +{ + 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}, + {"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, +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, }; /* elementfactory information */ @@ -228,9 +230,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "width = (int) 16, " "depth = (int) 16, " "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, " - "rate = (int) 8000, " - "channels = (int) 1") + "signed = (bool) true, " "rate = (int) 8000, " "channels = (int) 1") ); GST_BOILERPLATE (GstDTMFSrc, gst_dtmf_src, GstBaseSrc, GST_TYPE_BASE_SRC); @@ -241,18 +241,18 @@ 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_handle_event (GstBaseSrc * 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, +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 void gst_dtmf_src_add_stop_event (GstDTMFSrc * dtmfsrc); -static gboolean gst_dtmf_src_unlock (GstBaseSrc *src); +static gboolean gst_dtmf_src_unlock (GstBaseSrc * src); -static gboolean gst_dtmf_src_unlock_stop (GstBaseSrc *src); +static gboolean gst_dtmf_src_unlock_stop (GstBaseSrc * src); static gboolean gst_dtmf_src_negotiate (GstBaseSrc * basesrc); static void @@ -260,8 +260,7 @@ gst_dtmf_src_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GST_DEBUG_CATEGORY_INIT (gst_dtmf_src_debug, - "dtmfsrc", 0, "dtmfsrc element"); + GST_DEBUG_CATEGORY_INIT (gst_dtmf_src_debug, "dtmfsrc", 0, "dtmfsrc element"); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_dtmf_src_template)); @@ -282,10 +281,8 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_dtmf_src_finalize); - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_dtmf_src_set_property); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_dtmf_src_get_property); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_dtmf_src_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (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", @@ -294,22 +291,17 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state); - gstbasesrc_class->unlock = - GST_DEBUG_FUNCPTR (gst_dtmf_src_unlock); - gstbasesrc_class->unlock_stop = - GST_DEBUG_FUNCPTR (gst_dtmf_src_unlock_stop); + 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); + 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 -gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass *g_class) +gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass * g_class) { /* we operate in time */ gst_base_src_set_format (GST_BASE_SRC (dtmfsrc), GST_FORMAT_TIME); @@ -341,8 +333,8 @@ gst_dtmf_src_finalize (GObject * object) } static gboolean -gst_dtmf_src_handle_dtmf_event (GstDTMFSrc *dtmfsrc, - const GstStructure * event_structure) +gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, + const GstStructure * event_structure) { gint event_type; gboolean start; @@ -364,11 +356,11 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc *dtmfsrc, gint event_volume; if (!gst_structure_get_int (event_structure, "number", &event_number) || - !gst_structure_get_int (event_structure, "volume", &event_volume)) + !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); + event_number, event_volume); gst_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume); } @@ -383,8 +375,7 @@ failure: } static gboolean -gst_dtmf_src_handle_custom_upstream (GstDTMFSrc *dtmfsrc, - GstEvent * event) +gst_dtmf_src_handle_custom_upstream (GstDTMFSrc * dtmfsrc, GstEvent * event) { gboolean result = FALSE; const GstStructure *structure; @@ -459,23 +450,23 @@ gst_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, } static void -gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock) +gst_dtmf_src_set_stream_lock (GstDTMFSrc * dtmfsrc, gboolean lock) { - GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); - GstEvent *event; - GstStructure *structure; + GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); + GstEvent *event; + GstStructure *structure; - structure = gst_structure_new ("stream-lock", - "lock", G_TYPE_BOOLEAN, lock, NULL); + structure = gst_structure_new ("stream-lock", + "lock", G_TYPE_BOOLEAN, lock, NULL); - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - if (!gst_pad_push_event (srcpad, event)) { - GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); - } + event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); + if (!gst_pad_push_event (srcpad, event)) { + GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); + } } static void -gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) +gst_dtmf_prepare_timestamps (GstDTMFSrc * dtmfsrc) { GstClock *clock; GstClockTime base_time; @@ -499,11 +490,11 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc) } static void -gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, gint event_number, +gst_dtmf_src_add_start_event (GstDTMFSrc * dtmfsrc, gint event_number, gint event_volume) { - GstDTMFSrcEvent * event = g_malloc (sizeof(GstDTMFSrcEvent)); + GstDTMFSrcEvent *event = g_malloc (sizeof (GstDTMFSrcEvent)); event->event_type = DTMF_EVENT_TYPE_START; event->sample = 0; event->event_number = CLAMP (event_number, MIN_EVENT, MAX_EVENT); @@ -513,10 +504,10 @@ gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, gint event_number, } static void -gst_dtmf_src_add_stop_event (GstDTMFSrc *dtmfsrc) +gst_dtmf_src_add_stop_event (GstDTMFSrc * dtmfsrc) { - GstDTMFSrcEvent * event = g_malloc (sizeof(GstDTMFSrcEvent)); + GstDTMFSrcEvent *event = g_malloc (sizeof (GstDTMFSrcEvent)); event->event_type = DTMF_EVENT_TYPE_STOP; event->sample = 0; event->event_number = 0; @@ -526,22 +517,22 @@ gst_dtmf_src_add_stop_event (GstDTMFSrc *dtmfsrc) } static void -gst_dtmf_src_generate_silence(GstBuffer * buffer, float duration, +gst_dtmf_src_generate_silence (GstBuffer * buffer, 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; + buf_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8; GST_BUFFER_SIZE (buffer) = buf_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc0(buf_size); + GST_BUFFER_MALLOCDATA (buffer) = g_malloc0 (buf_size); GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); } static void -gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, - GstBuffer * buffer, gint sample_rate) +gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, + float duration, GstBuffer * buffer, gint sample_rate) { gint16 *p; gint tone_size; @@ -550,9 +541,9 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, double volume_factor; /* Create a buffer for the tone */ - tone_size = ((duration/1000)*sample_rate*SAMPLE_SIZE*CHANNELS)/8; + tone_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8; GST_BUFFER_SIZE (buffer) = tone_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc(tone_size); + GST_BUFFER_MALLOCDATA (buffer) = g_malloc (tone_size); GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); @@ -563,12 +554,12 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, * For each sample point we calculate 'x' as the * the amplitude value. */ - for (i = 0; i < (tone_size / (SAMPLE_SIZE/8)); i++) { + 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)); + 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; @@ -588,8 +579,8 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration, static GstBuffer * -gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, - GstDTMFSrcEvent *event) +gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, + GstDTMFSrcEvent * event) { GstBuffer *buf = NULL; gboolean send_silence = FALSE; @@ -606,12 +597,12 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc, } if (send_silence) { - GST_DEBUG_OBJECT (dtmfsrc, "Generating silence"); + GST_DEBUG_OBJECT (dtmfsrc, "Generating silence"); gst_dtmf_src_generate_silence (buf, dtmfsrc->interval, dtmfsrc->sample_rate); } else { - GST_DEBUG_OBJECT (dtmfsrc, "Generating tone"); - gst_dtmf_src_generate_tone(event, DTMF_KEYS[event->event_number], + GST_DEBUG_OBJECT (dtmfsrc, "Generating tone"); + gst_dtmf_src_generate_tone (event, DTMF_KEYS[event->event_number], dtmfsrc->interval, buf, dtmfsrc->sample_rate); } event->packet_count++; @@ -634,7 +625,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, { GstBuffer *buf = NULL; GstDTMFSrcEvent *event; - GstDTMFSrc * dtmfsrc; + GstDTMFSrc *dtmfsrc; GstClock *clock; GstClockID *clockid; GstClockReturn clockret; @@ -680,7 +671,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, } if (event) g_free (event); - } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= + } else if (dtmfsrc->last_event->packet_count * dtmfsrc->interval >= MIN_DUTY_CYCLE) { event = g_async_queue_try_pop (dtmfsrc->event_queue); @@ -740,7 +731,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_OBJECT_LOCK (dtmfsrc); if (dtmfsrc->paused) clockret = GST_CLOCK_UNSCHEDULED; - } else { + } else { clockret = GST_CLOCK_UNSCHEDULED; } gst_clock_id_unref (clockid); @@ -753,16 +744,17 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); - GST_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf)); + GST_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", + GST_BUFFER_SIZE (buf)); *buffer = buf; GST_DEBUG_OBJECT (dtmfsrc, "returning a buffer"); return GST_FLOW_OK; - paused_locked: +paused_locked: GST_OBJECT_UNLOCK (dtmfsrc); - paused: +paused: if (dtmfsrc->last_event) { GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event"); @@ -777,7 +769,8 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, } static gboolean -gst_dtmf_src_unlock (GstBaseSrc *src) { +gst_dtmf_src_unlock (GstBaseSrc * src) +{ GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (src); GstDTMFSrcEvent *event = NULL; @@ -791,7 +784,7 @@ gst_dtmf_src_unlock (GstBaseSrc *src) { GST_OBJECT_UNLOCK (dtmfsrc); GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request"); - event = g_malloc (sizeof(GstDTMFSrcEvent)); + event = g_malloc (sizeof (GstDTMFSrcEvent)); event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); @@ -800,7 +793,8 @@ gst_dtmf_src_unlock (GstBaseSrc *src) { static gboolean -gst_dtmf_src_unlock_stop (GstBaseSrc *src) { +gst_dtmf_src_unlock_stop (GstBaseSrc * src) +{ GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (src); GST_DEBUG_OBJECT (dtmfsrc, "Unlock stopped"); @@ -824,17 +818,14 @@ gst_dtmf_src_negotiate (GstBaseSrc * basesrc) "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, - "channels", G_TYPE_INT, 1, - NULL); + "signed", G_TYPE_BOOLEAN, TRUE, "channels", G_TYPE_INT, 1, NULL); peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc)); if (peercaps == NULL) { /* no peer caps, just add the other properties */ gst_caps_set_simple (srccaps, - "rate", G_TYPE_INT, dtmfsrc->sample_rate, - NULL); + "rate", G_TYPE_INT, dtmfsrc->sample_rate, NULL); } else { GstStructure *s; gint sample_rate; @@ -864,17 +855,13 @@ gst_dtmf_src_negotiate (GstBaseSrc * basesrc) /* get first structure */ s = gst_caps_get_structure (srccaps, 0); - if (gst_structure_get_int (s, "rate", &sample_rate)) - { + if (gst_structure_get_int (s, "rate", &sample_rate)) { dtmfsrc->sample_rate = sample_rate; - GST_LOG_OBJECT (dtmfsrc, "using rate from caps %d", - dtmfsrc->sample_rate); + GST_LOG_OBJECT (dtmfsrc, "using rate from caps %d", dtmfsrc->sample_rate); } else { - GST_LOG_OBJECT (dtmfsrc, "using existing rate %d", - dtmfsrc->sample_rate); + GST_LOG_OBJECT (dtmfsrc, "using existing rate %d", dtmfsrc->sample_rate); } - gst_structure_set (s, "rate", G_TYPE_INT, dtmfsrc->sample_rate, - NULL); + gst_structure_set (s, "rate", G_TYPE_INT, dtmfsrc->sample_rate, NULL); } ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), srccaps); @@ -952,4 +939,3 @@ 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 index fdf6f50d9d..73970db155 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -32,7 +32,6 @@ #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)) @@ -40,7 +39,6 @@ G_BEGIN_DECLS #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; @@ -51,7 +49,8 @@ typedef struct _GstDTMFSrcClass GstDTMFSrcClass; * The opaque #GstDTMFSrc data structure. */ -enum _GstDTMFEventType { +enum _GstDTMFEventType +{ DTMF_EVENT_TYPE_START, DTMF_EVENT_TYPE_STOP, DTMF_EVENT_TYPE_PAUSE_TASK @@ -59,32 +58,35 @@ enum _GstDTMFEventType { typedef enum _GstDTMFEventType GstDTMFEventType; -struct _GstDTMFSrcEvent { - GstDTMFEventType event_type; - double sample; - guint16 event_number; - guint16 volume; - guint32 packet_count; +struct _GstDTMFSrcEvent +{ + GstDTMFEventType event_type; + double sample; + guint16 event_number; + guint16 volume; + guint32 packet_count; }; typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent; -struct _GstDTMFSrc { - GstBaseSrc parent; - GAsyncQueue* event_queue; - GstDTMFSrcEvent* last_event; +struct _GstDTMFSrc +{ + GstBaseSrc parent; + GAsyncQueue *event_queue; + GstDTMFSrcEvent *last_event; - guint16 interval; - GstClockTime timestamp; + guint16 interval; + GstClockTime timestamp; - gboolean paused; - GstClockID clockid; + gboolean paused; + GstClockID clockid; - gint sample_rate; + gint sample_rate; }; -struct _GstDTMFSrcClass { +struct _GstDTMFSrcClass +{ GstBaseSrcClass parent_class; }; @@ -93,5 +95,4 @@ 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/gstrtpdtmfcommon.h b/gst/dtmf/gstrtpdtmfcommon.h index 097afa9012..c1ab82e0a9 100644 --- a/gst/dtmf/gstrtpdtmfcommon.h +++ b/gst/dtmf/gstrtpdtmfcommon.h @@ -3,20 +3,21 @@ #define __GST_RTP_DTMF_COMMON_H__ -typedef struct { - unsigned event:8; /* Current DTMF event */ +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 */ + 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 */ + 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 */ + unsigned duration:16; /* Duration of digit, in timestamp units */ } GstRTPDTMFPayload; #endif /* __GST_RTP_DTMF_COMMON_H__ */ diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 20321893f3..3b2097a4a5 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -35,9 +35,9 @@ #endif -#define DEFAULT_PACKET_INTERVAL 50 /* ms */ -#define MIN_PACKET_INTERVAL 10 /* ms */ -#define MAX_PACKET_INTERVAL 50 /* ms */ +#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 @@ -55,51 +55,53 @@ #define DEFAULT_MAX_DURATION 0 -typedef struct st_dtmf_key { - char *event_name; - int event_encoding; - float low_frequency; - float high_frequency; +typedef struct st_dtmf_key +{ + 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}, + {"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, +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, }; /* elementfactory information */ @@ -141,8 +143,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "depth = (int) 16, " "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " "signed = (boolean) true, " - "rate = (int) [0, MAX], " - "channels = (int) 1") + "rate = (int) [0, MAX], " "channels = (int) 1") ); static GstStaticPadTemplate gst_rtp_dtmf_depay_sink_template = @@ -180,7 +181,7 @@ gst_rtp_dtmf_depay_base_init (gpointer klass) GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug, - "rtpdtmfdepay", 0, "rtpdtmfdepay element"); + "rtpdtmfdepay", 0, "rtpdtmfdepay element"); gst_element_class_set_details (element_class, &gst_rtp_dtmfdepay_details); } @@ -203,20 +204,20 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) 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_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_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_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)); gstbasertpdepayload_class->process = - GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process); + GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process); gstbasertpdepayload_class->set_caps = - GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_setcaps); + GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_setcaps); } @@ -231,7 +232,7 @@ static void gst_rtp_dtmf_depay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstRtpDTMFDepay * rtpdtmfdepay; + GstRtpDTMFDepay *rtpdtmfdepay; rtpdtmfdepay = GST_RTP_DTMF_DEPAY (object); @@ -252,7 +253,7 @@ static void gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstRtpDTMFDepay * rtpdtmfdepay; + GstRtpDTMFDepay *rtpdtmfdepay; rtpdtmfdepay = GST_RTP_DTMF_DEPAY (object); @@ -274,7 +275,7 @@ gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) { GstCaps *srccaps; GstStructure *structure = gst_caps_get_structure (caps, 0); - gint clock_rate = 8000; /* default */ + gint clock_rate = 8000; /* default */ gst_structure_get_int (structure, "clock-rate", &clock_rate); filter->clock_rate = clock_rate; @@ -284,8 +285,7 @@ gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) "depth", G_TYPE_INT, 16, "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "channels", G_TYPE_INT, 1, - "rate", G_TYPE_INT, clock_rate, NULL); + "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, clock_rate, NULL); gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (filter), srccaps); gst_caps_unref (srccaps); @@ -293,7 +293,7 @@ gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) } static void -gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, +gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, GstRTPDTMFPayload payload, GstBuffer * buffer) { gint16 *p; @@ -302,16 +302,16 @@ gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, double amplitude, f1, f2; double volume_factor; DTMF_KEY key = DTMF_KEYS[payload.event]; - guint32 clock_rate = 8000 /* default */; - GstBaseRTPDepayload * depayload = GST_BASE_RTP_DEPAYLOAD (rtpdtmfdepay); + guint32 clock_rate = 8000 /* default */ ; + GstBaseRTPDepayload *depayload = GST_BASE_RTP_DEPAYLOAD (rtpdtmfdepay); gint volume; clock_rate = depayload->clock_rate; /* Create a buffer for the tone */ - tone_size = (payload.duration*SAMPLE_SIZE*CHANNELS)/8; + tone_size = (payload.duration * SAMPLE_SIZE * CHANNELS) / 8; GST_BUFFER_SIZE (buffer) = tone_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc(tone_size); + GST_BUFFER_MALLOCDATA (buffer) = g_malloc (tone_size); GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); GST_BUFFER_DURATION (buffer) = payload.duration * GST_SECOND / clock_rate; volume = payload.volume; @@ -324,12 +324,14 @@ gst_dtmf_src_generate_tone(GstRtpDTMFDepay *rtpdtmfdepay, * For each sample point we calculate 'x' as the * the amplitude value. */ - for (i = 0; i < (tone_size / (SAMPLE_SIZE/8)); i++) { + 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)); + 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; @@ -369,7 +371,7 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) payload_len = gst_rtp_buffer_get_payload_len (buf); payload = gst_rtp_buffer_get_payload (buf); - if (payload_len != sizeof(GstRTPDTMFPayload) ) + if (payload_len != sizeof (GstRTPDTMFPayload)) goto bad_packet; memcpy (&dtmf_payload, payload, sizeof (GstRTPDTMFPayload)); @@ -385,12 +387,10 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) dtmf_payload.duration = g_ntohs (dtmf_payload.duration); /* clip to whole units of unit_time */ - if (rtpdtmfdepay->unit_time) - { + if (rtpdtmfdepay->unit_time) { guint unit_time_clock = (rtpdtmfdepay->unit_time * depayload->clock_rate) / 1000; - if (dtmf_payload.duration % unit_time_clock) - { + 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 - @@ -401,8 +401,7 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } /* clip to max duration */ - if (rtpdtmfdepay->max_duration) - { + if (rtpdtmfdepay->max_duration) { guint max_duration_clock = (rtpdtmfdepay->max_duration * depayload->clock_rate) / 1000; @@ -415,7 +414,8 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) "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", + GST_DEBUG_OBJECT (depayload, + "Previous information : timestamp=%u - duration=%d", rtpdtmfdepay->previous_ts, rtpdtmfdepay->previous_duration); /* First packet */ @@ -428,14 +428,14 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * 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); + "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1, NULL); if (structure) { - dtmf_message = gst_message_new_element (GST_OBJECT (depayload), 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"); + GST_ERROR_OBJECT (depayload, + "Unable to send dtmf-event message to bus"); } } else { GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event message"); @@ -460,7 +460,7 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) /* If late or duplicate packet (like the redundant end packet). Ignore */ if (dtmf_payload.duration > 0) { outbuf = gst_buffer_new (); - gst_dtmf_src_generate_tone(rtpdtmfdepay, dtmf_payload, outbuf); + gst_dtmf_src_generate_tone (rtpdtmfdepay, dtmf_payload, outbuf); GST_BUFFER_TIMESTAMP (outbuf) = rtpdtmfdepay->first_gst_ts + @@ -468,9 +468,9 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) GST_SECOND / depayload->clock_rate; GST_BUFFER_OFFSET (outbuf) = (rtpdtmfdepay->previous_duration - dtmf_payload.duration) * - GST_SECOND / depayload->clock_rate; + GST_SECOND / depayload->clock_rate; GST_BUFFER_OFFSET_END (outbuf) = rtpdtmfdepay->previous_duration * - GST_SECOND / depayload->clock_rate; + GST_SECOND / depayload->clock_rate; GST_DEBUG_OBJECT (depayload, "timestamp : %llu - time %" GST_TIME_FORMAT, GST_BUFFER_TIMESTAMP (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); @@ -492,4 +492,3 @@ 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 index 4fb31a0dcf..1fb8ff7cfb 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -30,7 +30,6 @@ #include "gstrtpdtmfcommon.h" G_BEGIN_DECLS - #define GST_TYPE_RTP_DTMF_DEPAY \ (gst_rtp_dtmf_depay_get_type()) #define GST_RTP_DTMF_DEPAY(obj) \ @@ -41,18 +40,16 @@ G_BEGIN_DECLS (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 { - GstBaseRTPDepayload depayload; - double sample; - guint32 previous_ts; - guint16 previous_duration; - GstClockTime first_gst_ts; + GstBaseRTPDepayload depayload; + double sample; + guint32 previous_ts; + guint16 previous_duration; + GstClockTime first_gst_ts; guint unit_time; guint max_duration; }; @@ -65,5 +62,4 @@ struct _GstRtpDTMFDepayClass 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 index 588cda493e..e1d252ba38 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -134,9 +134,9 @@ #include "gstrtpdtmfsrc.h" #define GST_RTP_DTMF_TYPE_EVENT 1 -#define DEFAULT_PACKET_INTERVAL 50 /* ms */ -#define MIN_PACKET_INTERVAL 10 /* ms */ -#define MAX_PACKET_INTERVAL 50 /* ms */ +#define DEFAULT_PACKET_INTERVAL 50 /* ms */ +#define MIN_PACKET_INTERVAL 10 /* ms */ +#define MAX_PACKET_INTERVAL 50 /* ms */ #define DEFAULT_SSRC -1 #define DEFAULT_PT 96 #define DEFAULT_TIMESTAMP_OFFSET -1 @@ -149,8 +149,8 @@ #define MIN_VOLUME 0 #define MAX_VOLUME 36 -#define MIN_INTER_DIGIT_INTERVAL 50 /* ms */ -#define MIN_PULSE_DURATION 70 /* ms */ +#define MIN_INTER_DIGIT_INTERVAL 50 /* ms */ +#define MIN_PULSE_DURATION 70 /* ms */ #define DEFAULT_PACKET_REDUNDANCY 1 #define MIN_PACKET_REDUNDANCY 1 @@ -198,7 +198,6 @@ GST_STATIC_PAD_TEMPLATE ("src", "ssrc = (int) [ 0, MAX ], " "encoding-name = (string) \"TELEPHONE-EVENT\"") /* "events = (string) \"0-15\" */ - ); @@ -215,16 +214,16 @@ 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, +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, +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 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 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); @@ -236,7 +235,7 @@ gst_rtp_dtmf_src_base_init (gpointer g_class) GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug, - "rtpdtmfsrc", 0, "rtpdtmfsrc element"); + "rtpdtmfsrc", 0, "rtpdtmfsrc element"); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); @@ -305,17 +304,13 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) 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 = 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); + 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 @@ -355,16 +350,16 @@ gst_rtp_dtmf_src_finalize (GObject * object) } static gboolean -gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc *dtmfsrc, - const GstStructure * event_structure) +gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc * dtmfsrc, + const GstStructure * event_structure) { gint event_type; gboolean start; gint method; 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) + !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)) { @@ -378,11 +373,11 @@ gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc *dtmfsrc, gint event_volume; if (!gst_structure_get_int (event_structure, "number", &event_number) || - !gst_structure_get_int (event_structure, "volume", &event_volume)) + !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); + event_number, event_volume); gst_rtp_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume); } @@ -397,7 +392,7 @@ failure: } static gboolean -gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc, +gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc * dtmfsrc, GstEvent * event) { gboolean result = FALSE; @@ -426,7 +421,7 @@ ret: } static gboolean -gst_rtp_dtmf_src_handle_event (GstBaseSrc *basesrc, GstEvent * event) +gst_rtp_dtmf_src_handle_event (GstBaseSrc * basesrc, GstEvent * event) { GstRTPDTMFSrc *dtmfsrc; gboolean result = FALSE; @@ -522,23 +517,23 @@ gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, } static void -gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc *dtmfsrc, gboolean lock) +gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc * dtmfsrc, gboolean lock) { - GstEvent *event; - GstStructure *structure; + GstEvent *event; + GstStructure *structure; - structure = gst_structure_new ("stream-lock", - "lock", G_TYPE_BOOLEAN, lock, NULL); + structure = gst_structure_new ("stream-lock", + "lock", G_TYPE_BOOLEAN, lock, NULL); - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - if (!gst_pad_push_event (GST_BASE_SRC_PAD (dtmfsrc), event)) { - GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); - } + event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); + if (!gst_pad_push_event (GST_BASE_SRC_PAD (dtmfsrc), event)) { + GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); + } } static void -gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) +gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) { GstClock *clock; GstClockTime base_time; @@ -563,19 +558,18 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc) } 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); + 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); } static void -gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number, +gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc * dtmfsrc, gint event_number, gint event_volume) { - GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); + GstRTPDTMFSrcEvent *event = g_malloc (sizeof (GstRTPDTMFSrcEvent)); event->event_type = RTP_DTMF_EVENT_TYPE_START; event->payload = g_new0 (GstRTPDTMFPayload, 1); @@ -587,10 +581,10 @@ gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number, } static void -gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc) +gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc * dtmfsrc) { - GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); + GstRTPDTMFSrcEvent *event = g_malloc (sizeof (GstRTPDTMFSrcEvent)); event->event_type = RTP_DTMF_EVENT_TYPE_STOP; g_async_queue_push (dtmfsrc->event_queue, event); @@ -598,7 +592,7 @@ gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc) static void -gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) +gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) { gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc); gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt); @@ -617,7 +611,7 @@ gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) } static void -gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) +gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) { GstRTPDTMFPayload *payload; @@ -641,7 +635,7 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) * if its the end of the event */ if (payload->e && - payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000 ) + payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000) payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000; payload->duration = g_htons (payload->duration); @@ -656,7 +650,7 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf) } static GstBuffer * -gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc) +gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc) { GstBuffer *buf = NULL; @@ -676,7 +670,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer) { GstRTPDTMFSrcEvent *event; - GstRTPDTMFSrc * dtmfsrc; + GstRTPDTMFSrc *dtmfsrc; GstClock *clock; GstClockID *clockid; GstClockReturn clockret; @@ -726,7 +720,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, g_free (event); } else if (!dtmfsrc->first_packet && !dtmfsrc->last_packet && - (dtmfsrc->timestamp - dtmfsrc->start_timestamp)/GST_MSECOND >= + (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); @@ -790,7 +784,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_OBJECT_LOCK (dtmfsrc); if (dtmfsrc->paused) clockret = GST_CLOCK_UNSCHEDULED; - } else { + } else { clockret = GST_CLOCK_UNSCHEDULED; } gst_clock_id_unref (clockid); @@ -801,7 +795,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, goto paused; } - send_last: +send_last: if (dtmfsrc->dirty) if (!gst_rtp_dtmf_src_negotiate (basesrc)) @@ -830,11 +824,11 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, return GST_FLOW_OK; - paused_locked: +paused_locked: GST_OBJECT_UNLOCK (dtmfsrc); - paused: +paused: if (dtmfsrc->payload) { dtmfsrc->first_packet = FALSE; @@ -910,8 +904,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) } 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_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 { @@ -922,8 +915,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) } } - if (gst_structure_get_int (s, "clock-rate", &clock_rate)) - { + 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); @@ -931,8 +923,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) 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); + gst_structure_set (s, "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, NULL); if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) { @@ -982,7 +973,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) static void -gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc) +gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc * dtmfsrc) { if (dtmfsrc->ssrc == -1) dtmfsrc->current_ssrc = g_random_int (); @@ -1008,7 +999,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) GstRTPDTMFSrc *dtmfsrc; GstStateChangeReturn result; gboolean no_preroll = FALSE; - GstRTPDTMFSrcEvent *event= NULL; + GstRTPDTMFSrcEvent *event = NULL; dtmfsrc = GST_RTP_DTMF_SRC (element); @@ -1037,7 +1028,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) break; case GST_STATE_CHANGE_PAUSED_TO_READY: - /* Flushing the event queue */ + /* Flushing the event queue */ while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) g_free (event); @@ -1063,7 +1054,8 @@ failure: static gboolean -gst_rtp_dtmf_src_unlock (GstBaseSrc *src) { +gst_rtp_dtmf_src_unlock (GstBaseSrc * src) +{ GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (src); GstRTPDTMFSrcEvent *event = NULL; @@ -1077,7 +1069,7 @@ gst_rtp_dtmf_src_unlock (GstBaseSrc *src) { GST_OBJECT_UNLOCK (dtmfsrc); GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request"); - event = g_malloc (sizeof(GstRTPDTMFSrcEvent)); + event = g_malloc (sizeof (GstRTPDTMFSrcEvent)); event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); @@ -1086,7 +1078,8 @@ gst_rtp_dtmf_src_unlock (GstBaseSrc *src) { static gboolean -gst_rtp_dtmf_src_unlock_stop (GstBaseSrc *src) { +gst_rtp_dtmf_src_unlock_stop (GstBaseSrc * src) +{ GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (src); GST_DEBUG_OBJECT (dtmfsrc, "Unlock stopped"); diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index ade3a67a46..1b40160f19 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -32,7 +32,6 @@ #include "gstrtpdtmfcommon.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)) @@ -40,14 +39,13 @@ G_BEGIN_DECLS #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 { +enum _GstRTPDTMFEventType +{ RTP_DTMF_EVENT_TYPE_START, RTP_DTMF_EVENT_TYPE_STOP, RTP_DTMF_EVENT_TYPE_PAUSE_TASK @@ -55,9 +53,10 @@ enum _GstRTPDTMFEventType { typedef enum _GstRTPDTMFEventType GstRTPDTMFEventType; -struct _GstRTPDTMFSrcEvent { - GstRTPDTMFEventType event_type; - GstRTPDTMFPayload* payload; +struct _GstRTPDTMFSrcEvent +{ + GstRTPDTMFEventType event_type; + GstRTPDTMFPayload *payload; }; typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; @@ -68,36 +67,38 @@ typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; * * The opaque #GstRTPDTMFSrc data structure. */ -struct _GstRTPDTMFSrc { - GstBaseSrc basesrc; +struct _GstRTPDTMFSrc +{ + GstBaseSrc basesrc; - GAsyncQueue* event_queue; - GstClockID clockid; - gboolean paused; - GstRTPDTMFPayload* payload; + 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 interval; - guint16 packet_redundancy; - guint32 clock_rate; + 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 interval; + guint16 packet_redundancy; + guint32 clock_rate; - gboolean dirty; - guint16 redundancy_count; + gboolean dirty; + guint16 redundancy_count; }; -struct _GstRTPDTMFSrcClass { +struct _GstRTPDTMFSrcClass +{ GstBaseSrcClass parent_class; }; @@ -107,5 +108,4 @@ gboolean gst_rtp_dtmf_src_plugin_init (GstPlugin * plugin); G_END_DECLS - #endif /* __GST_RTP_DTMF_SRC_H__ */ From b95b1516e535a3a8b883e29072dcdfb4fb977c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 20 Feb 2009 17:40:57 -0500 Subject: [PATCH 063/138] Fix up documentation blobs SGML --- gst/dtmf/gstdtmfsrc.c | 14 +------------- gst/dtmf/gstdtmfsrc.h | 1 + gst/dtmf/gstrtpdtmfdepay.h | 1 + gst/dtmf/gstrtpdtmfsrc.c | 14 +------------- gst/dtmf/gstrtpdtmfsrc.h | 1 + 5 files changed, 5 insertions(+), 26 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 06e27d4435..1ccad697f7 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -29,25 +29,19 @@ * SECTION:element-dtmfsrc * @short_description: Generates DTMF packets * - * - * - * * 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 @@ -56,7 +50,6 @@ * Purpose * * - * * * * type @@ -101,14 +94,11 @@ * * * - * * - * For example, the following code informs the pipeline (and in turn, the + * 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, @@ -119,9 +109,7 @@ * event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure); * gst_element_send_event (pipeline, event); * - * * - * */ #ifdef HAVE_CONFIG_H diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 73970db155..1d7c5ca0b1 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -71,6 +71,7 @@ typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent; struct _GstDTMFSrc { + /*< private >*/ GstBaseSrc parent; GAsyncQueue *event_queue; GstDTMFSrcEvent *last_event; diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index 1fb8ff7cfb..dfbcc4af07 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -45,6 +45,7 @@ typedef struct _GstRtpDTMFDepayClass GstRtpDTMFDepayClass; struct _GstRtpDTMFDepay { + /*< private >*/ GstBaseRTPDepayload depayload; double sample; guint32 previous_ts; diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index e1d252ba38..fa1841da61 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -27,25 +27,19 @@ * SECTION:element-rtpdtmfsrc * @short_description: Generates RTP DTMF packets * - * - * - * * 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 @@ -54,7 +48,6 @@ * Purpose * * - * * * * type @@ -99,14 +92,11 @@ * * * - * * - * For example, the following code informs the pipeline (and in turn, the + * 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, @@ -117,9 +107,7 @@ * event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure); * gst_element_send_event (pipeline, event); * - * * - * */ #ifdef HAVE_CONFIG_H diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 1b40160f19..b1a483a102 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -69,6 +69,7 @@ typedef struct _GstRTPDTMFSrcEvent GstRTPDTMFSrcEvent; */ struct _GstRTPDTMFSrc { + /*< private >*/ GstBaseSrc basesrc; GAsyncQueue *event_queue; From b7caf7697490452b68a30739e28d0fe4d6692b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 20 Feb 2009 17:41:37 -0500 Subject: [PATCH 064/138] Moved dtmf elements from gst-plugins-farsight to -bad --- gst/dtmf/gstdtmf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c index 4d9d1a5922..d50cf03fc2 100644 --- a/gst/dtmf/gstdtmf.c +++ b/gst/dtmf/gstdtmf.c @@ -26,4 +26,5 @@ plugin_init (GstPlugin * plugin) GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - "dtmf", "DTMF plugins", plugin_init, "0.1", "LGPL", "DTMF", ""); + "dtmf", "DTMF plugins", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) From c0ad75c81033950929c5cc518193748a199ad31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 20 Feb 2009 18:16:02 -0500 Subject: [PATCH 065/138] Document rtpdtmfdepay a bit --- gst/dtmf/gstdtmfsrc.c | 1 + gst/dtmf/gstrtpdtmfdepay.c | 61 ++++++++++++++++++++++++++++++++++++++ gst/dtmf/gstrtpdtmfsrc.c | 1 + 3 files changed, 63 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 1ccad697f7..8c5485b177 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -28,6 +28,7 @@ /** * SECTION:element-dtmfsrc * @short_description: Generates DTMF packets + * @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 diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 3b2097a4a5..237792b382 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -19,6 +19,67 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-rtpdtmfdepay + * @short_description: Transforms RFC 4733/2833 RTP dtmf packets into sound + * @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 + * + * + * + * + * + * 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" diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index fa1841da61..3efa460241 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -26,6 +26,7 @@ /** * SECTION:element-rtpdtmfsrc * @short_description: Generates RTP DTMF packets + * @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 From 68811432dce1f13fc2afeb71462bbc3f57314ec3 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 25 Feb 2009 11:45:05 +0200 Subject: [PATCH 066/138] docs: various doc fixes No short-desc as we have them in the element details. Also keep things (Makefile.am and sections.txt) sorted. Reword ambigous returns. No text after since please. --- gst/dtmf/gstdtmfsrc.c | 1 - gst/dtmf/gstdtmfsrc.h | 13 ++++++------- gst/dtmf/gstrtpdtmfdepay.c | 1 - gst/dtmf/gstrtpdtmfsrc.c | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 8c5485b177..8595adf8ae 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -27,7 +27,6 @@ /** * SECTION:element-dtmfsrc - * @short_description: Generates DTMF packets * @see_also: rtpdtmsrc, rtpdtmfmuxx * * The DTMFSrc element generates DTMF (ITU-T Q.23 Specification) tone packets on request diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index 1d7c5ca0b1..aa5d35a611 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -42,13 +42,6 @@ G_BEGIN_DECLS typedef struct _GstDTMFSrc GstDTMFSrc; typedef struct _GstDTMFSrcClass GstDTMFSrcClass; -/** - * GstDTMFSrc: - * @element: the parent element. - * - * The opaque #GstDTMFSrc data structure. - */ - enum _GstDTMFEventType { DTMF_EVENT_TYPE_START, @@ -69,6 +62,12 @@ struct _GstDTMFSrcEvent typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent; +/** + * GstDTMFSrc: + * @element: the parent element. + * + * The opaque #GstDTMFSrc data structure. + */ struct _GstDTMFSrc { /*< private >*/ diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 237792b382..85e7d1c279 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -21,7 +21,6 @@ */ /** * SECTION:element-rtpdtmfdepay - * @short_description: Transforms RFC 4733/2833 RTP dtmf packets into sound * @see_also: rtpdtmfsrc, rtpdtmfmux * * This element takes RTP DTMF packets and produces sound. It also emits a diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 3efa460241..738be59e3a 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -25,7 +25,6 @@ /** * SECTION:element-rtpdtmfsrc - * @short_description: Generates RTP DTMF packets * @see_also: dtmfsrc, rtpdtmfdepay, rtpdtmfmux * * The RTPDTMFSrc element generates RTP DTMF (RFC 2833) event packets on request From 17ce409de40f974d30be5302a5546778d6768c1b Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 9 Mar 2009 23:43:55 +0200 Subject: [PATCH 067/138] Makefile.am: no static libs for plugins --- gst/dtmf/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index c96a3a4129..3bdabbb438 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -13,4 +13,5 @@ noinst_HEADERS = gstdtmfsrc.h \ libgstdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) -lm libgstdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ +libgstdtmf_la_LIBTOOLFLAGS = --tag=disable-static From 2e27e89d282d0de908a32f3ea5bd953a2f2a13b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 11 Aug 2009 16:23:20 -0400 Subject: [PATCH 068/138] rtpdtmfsrc: Cleanup events on finalize Problem found by Laurent Glayal Fixes bug #591440 --- gst/dtmf/gstrtpdtmfsrc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 738be59e3a..cdaa202a42 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -301,6 +301,16 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_negotiate); } +static void +gst_rtp_dtmf_src_event_free (GstRTPDTMFSrcEvent * event) +{ + if (event) { + g_free (event->payload); + event->payload = NULL; + g_free (event); + } +} + static void gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class) { @@ -315,7 +325,8 @@ gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class) object->interval = DEFAULT_PACKET_INTERVAL; object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; - object->event_queue = g_async_queue_new (); + object->event_queue = + g_async_queue_new_full ((GDestroyNotify) gst_rtp_dtmf_src_event_free); object->payload = NULL; GST_DEBUG_OBJECT (object, "init done"); @@ -997,7 +1008,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) /* Flushing the event queue */ while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) - g_free (event); + gst_rtp_dtmf_src_event_free (event); no_preroll = TRUE; break; @@ -1018,7 +1029,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) /* Flushing the event queue */ while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) - g_free (event); + gst_rtp_dtmf_src_event_free (event); /* Indicate that we don't do PRE_ROLL */ break; From 195be0da01db93759b8d949b5a04450f1360a757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 11 Aug 2009 16:23:20 -0400 Subject: [PATCH 069/138] rtpdtmfsrc: Cleanup events on finalize Problem found by Laurent Glayal Fixes bug #591440 --- gst/dtmf/gstrtpdtmfsrc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index cdaa202a42..b41c0c459c 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -583,7 +583,7 @@ static void gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc * dtmfsrc) { - GstRTPDTMFSrcEvent *event = g_malloc (sizeof (GstRTPDTMFSrcEvent)); + GstRTPDTMFSrcEvent *event = g_new0 (GstRTPDTMFSrcEvent, 1); event->event_type = RTP_DTMF_EVENT_TYPE_STOP; g_async_queue_push (dtmfsrc->event_queue, event); @@ -701,6 +701,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); dtmfsrc->payload = event->payload; + event->payload = NULL; break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: @@ -717,7 +718,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, break; } - g_free (event); + 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) { @@ -755,7 +756,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_OBJECT_UNLOCK (dtmfsrc); break; } - g_free (event); + gst_rtp_dtmf_src_event_free (event); } } } while (dtmfsrc->payload == NULL); @@ -1068,7 +1069,7 @@ gst_rtp_dtmf_src_unlock (GstBaseSrc * src) GST_OBJECT_UNLOCK (dtmfsrc); GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request"); - event = g_malloc (sizeof (GstRTPDTMFSrcEvent)); + event = g_new0 (GstRTPDTMFSrcEvent, 1); event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); From e9f782544e0b97c0d3e5558d95c3d8225a3d4e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 11 Aug 2009 16:39:42 -0400 Subject: [PATCH 070/138] dtmf: Use GSlice for internal event structures --- gst/dtmf/gstdtmfsrc.c | 18 +++++++++--------- gst/dtmf/gstrtpdtmfsrc.c | 16 ++++++++-------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 8595adf8ae..4115395dca 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -482,7 +482,7 @@ gst_dtmf_src_add_start_event (GstDTMFSrc * dtmfsrc, gint event_number, gint event_volume) { - GstDTMFSrcEvent *event = g_malloc (sizeof (GstDTMFSrcEvent)); + 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); @@ -495,7 +495,7 @@ static void gst_dtmf_src_add_stop_event (GstDTMFSrc * dtmfsrc) { - GstDTMFSrcEvent *event = g_malloc (sizeof (GstDTMFSrcEvent)); + GstDTMFSrcEvent *event = g_slice_new0 (GstDTMFSrcEvent); event->event_type = DTMF_EVENT_TYPE_STOP; event->sample = 0; event->event_number = 0; @@ -658,7 +658,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, break; } if (event) - g_free (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); @@ -673,7 +673,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, case DTMF_EVENT_TYPE_STOP: gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); + g_slice_free (GstDTMFSrcEvent, dtmfsrc->last_event); dtmfsrc->last_event = NULL; break; case DTMF_EVENT_TYPE_PAUSE_TASK: @@ -692,7 +692,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, break; } - g_free (event); + g_slice_free (GstDTMFSrcEvent, event); } } } while (dtmfsrc->last_event == NULL); @@ -748,7 +748,7 @@ paused: GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event"); /* Don't forget to release the stream lock */ gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->last_event); + g_slice_free (GstDTMFSrcEvent, dtmfsrc->last_event); dtmfsrc->last_event = NULL; } @@ -772,7 +772,7 @@ gst_dtmf_src_unlock (GstBaseSrc * src) GST_OBJECT_UNLOCK (dtmfsrc); GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request"); - event = g_malloc (sizeof (GstDTMFSrcEvent)); + event = g_slice_new0 (GstDTMFSrcEvent); event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); @@ -875,7 +875,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) event = g_async_queue_try_pop (dtmfsrc->event_queue); while (event != NULL) { - g_free (event); + g_slice_free (GstDTMFSrcEvent, event); event = g_async_queue_try_pop (dtmfsrc->event_queue); } no_preroll = TRUE; @@ -899,7 +899,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) event = g_async_queue_try_pop (dtmfsrc->event_queue); while (event != NULL) { - g_free (event); + g_slice_free (GstDTMFSrcEvent, event); event = g_async_queue_try_pop (dtmfsrc->event_queue); } diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index b41c0c459c..65d0ce8c14 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -305,9 +305,9 @@ static void gst_rtp_dtmf_src_event_free (GstRTPDTMFSrcEvent * event) { if (event) { - g_free (event->payload); - event->payload = NULL; - g_free (event); + if (event->payload) + g_slice_free (GstRTPDTMFPayload, event->payload); + g_slice_free (GstRTPDTMFSrcEvent, event); } } @@ -568,10 +568,10 @@ gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc * dtmfsrc, gint event_number, gint event_volume) { - GstRTPDTMFSrcEvent *event = g_malloc (sizeof (GstRTPDTMFSrcEvent)); + GstRTPDTMFSrcEvent *event = g_slice_new0 (GstRTPDTMFSrcEvent); event->event_type = RTP_DTMF_EVENT_TYPE_START; - event->payload = g_new0 (GstRTPDTMFPayload, 1); + 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); event->payload->duration = dtmfsrc->interval * dtmfsrc->clock_rate / 1000; @@ -583,7 +583,7 @@ static void gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc * dtmfsrc) { - GstRTPDTMFSrcEvent *event = g_new0 (GstRTPDTMFSrcEvent, 1); + GstRTPDTMFSrcEvent *event = g_slice_new0 (GstRTPDTMFSrcEvent); event->event_type = RTP_DTMF_EVENT_TYPE_STOP; g_async_queue_push (dtmfsrc->event_queue, event); @@ -816,7 +816,7 @@ send_last: /* Don't forget to release the stream lock */ gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_free (dtmfsrc->payload); + g_slice_free (GstRTPDTMFPayload, dtmfsrc->payload); dtmfsrc->payload = NULL; dtmfsrc->last_packet = FALSE; @@ -1069,7 +1069,7 @@ gst_rtp_dtmf_src_unlock (GstBaseSrc * src) GST_OBJECT_UNLOCK (dtmfsrc); GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request"); - event = g_new0 (GstRTPDTMFSrcEvent, 1); + event = g_slice_new0 (GstRTPDTMFSrcEvent); event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK; g_async_queue_push (dtmfsrc->event_queue, event); From 757fd42ebb085be9f319ff0e331727137faae338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 11 Aug 2009 16:42:51 -0400 Subject: [PATCH 071/138] dtmfsrc: Empty event queue on finalize --- gst/dtmf/gstdtmfsrc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 4115395dca..7a1f14b29b 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -287,6 +287,12 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) 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, GstDTMFSrcClass * g_class) @@ -297,7 +303,7 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass * g_class) dtmfsrc->interval = DEFAULT_PACKET_INTERVAL; - dtmfsrc->event_queue = g_async_queue_new (); + dtmfsrc->event_queue = g_async_queue_new_full ((GDestroyNotify) event_free); dtmfsrc->last_event = NULL; dtmfsrc->sample_rate = DEFAULT_SAMPLE_RATE; From d1b87e4dda3eb3116e275cae61a28c02208adace Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Sun, 11 Oct 2009 11:35:23 +0200 Subject: [PATCH 072/138] dtmf: fix warnings in macosx snow leopard --- gst/dtmf/gstrtpdtmfdepay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 85e7d1c279..7cdfabfe7e 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -512,7 +512,7 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } GST_DEBUG_OBJECT (depayload, "new previous duration : %d - new duration : %d" - " - diff : %d - clock rate : %d - timestamp : %llu", + " - 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)); @@ -532,7 +532,8 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) GST_BUFFER_OFFSET_END (outbuf) = rtpdtmfdepay->previous_duration * GST_SECOND / depayload->clock_rate; - GST_DEBUG_OBJECT (depayload, "timestamp : %llu - time %" GST_TIME_FORMAT, + GST_DEBUG_OBJECT (depayload, + "timestamp : %" G_GUINT64_FORMAT " - time %" GST_TIME_FORMAT, GST_BUFFER_TIMESTAMP (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); } From af9f789b67dbcc1a34d93fdb2f89e88b60e9bcfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 4 Nov 2009 20:05:17 -0500 Subject: [PATCH 073/138] dtmfsrc: Allow for any samplerate --- gst/dtmf/gstdtmfsrc.c | 67 ++++++++++++------------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 7a1f14b29b..efceb1ecd4 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -218,7 +218,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "width = (int) 16, " "depth = (int) 16, " "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, " "rate = (int) 8000, " "channels = (int) 1") + "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1") ); GST_BOILERPLATE (GstDTMFSrc, gst_dtmf_src, GstBaseSrc, GST_TYPE_BASE_SRC); @@ -804,63 +804,32 @@ gst_dtmf_src_unlock_stop (GstBaseSrc * src) static gboolean gst_dtmf_src_negotiate (GstBaseSrc * basesrc) { - GstCaps *srccaps, *peercaps; GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (basesrc); - gboolean ret = FALSE; + GstCaps *caps; + GstStructure *s; + gboolean ret; - srccaps = gst_caps_new_simple ("audio/x-raw-int", - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, "channels", G_TYPE_INT, 1, NULL); + caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); - peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc)); + if (!caps) + caps = + gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD + (basesrc))); - if (peercaps == NULL) { - /* no peer caps, just add the other properties */ - gst_caps_set_simple (srccaps, - "rate", G_TYPE_INT, dtmfsrc->sample_rate, NULL); - } else { - GstStructure *s; - gint sample_rate; - GstCaps *temp = NULL; + gst_caps_truncate (caps); + s = gst_caps_get_structure (caps, 0); - /* 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); + gst_structure_fixate_field_nearest_int (s, "rate", DEFAULT_SAMPLE_RATE); - 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 */ - gst_caps_truncate (temp); - srccaps = temp; - - /* get first structure */ - s = gst_caps_get_structure (srccaps, 0); - - if (gst_structure_get_int (s, "rate", &sample_rate)) { - dtmfsrc->sample_rate = sample_rate; - GST_LOG_OBJECT (dtmfsrc, "using rate from caps %d", dtmfsrc->sample_rate); - } else { - GST_LOG_OBJECT (dtmfsrc, "using existing rate %d", dtmfsrc->sample_rate); - } - gst_structure_set (s, "rate", G_TYPE_INT, dtmfsrc->sample_rate, NULL); + 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), srccaps); + ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps); - gst_caps_unref (srccaps); + gst_caps_unref (caps); return ret; } From ec62833ee5792b1b02614d79f670f1b4b2b5a7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 4 Nov 2009 22:21:22 -0500 Subject: [PATCH 074/138] dtmfsrc: Use log level for repeated debug messages --- gst/dtmf/gstdtmfsrc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index efceb1ecd4..20cb43a8e8 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -580,7 +580,7 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, gboolean send_silence = FALSE; GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); - GST_DEBUG_OBJECT (dtmfsrc, "Creating buffer for tone %s", + GST_LOG_OBJECT (dtmfsrc, "Creating buffer for tone %s", DTMF_KEYS[event->event_number].event_name); /* create buffer to hold the tone */ @@ -591,11 +591,11 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, } if (send_silence) { - GST_DEBUG_OBJECT (dtmfsrc, "Generating silence"); + GST_LOG_OBJECT (dtmfsrc, "Generating silence"); gst_dtmf_src_generate_silence (buf, dtmfsrc->interval, dtmfsrc->sample_rate); } else { - GST_DEBUG_OBJECT (dtmfsrc, "Generating tone"); + GST_LOG_OBJECT (dtmfsrc, "Generating tone"); gst_dtmf_src_generate_tone (event, DTMF_KEYS[event->event_number], dtmfsrc->interval, buf, dtmfsrc->sample_rate); } @@ -703,7 +703,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, } } while (dtmfsrc->last_event == NULL); - GST_DEBUG_OBJECT (dtmfsrc, "end event check, now wait for the proper time"); + GST_LOG_OBJECT (dtmfsrc, "end event check, now wait for the proper time"); clock = gst_element_get_clock (GST_ELEMENT (basesrc)); @@ -738,11 +738,9 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); - GST_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", - GST_BUFFER_SIZE (buf)); + GST_LOG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf)); *buffer = buf; - GST_DEBUG_OBJECT (dtmfsrc, "returning a buffer"); return GST_FLOW_OK; paused_locked: From f01e6c6f896c06f2cf6f900013eea4f47446c501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 4 Nov 2009 22:21:35 -0500 Subject: [PATCH 075/138] dtmfsrc: Reject empty caps --- gst/dtmf/gstdtmfsrc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 20cb43a8e8..39699d8409 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -814,6 +814,9 @@ gst_dtmf_src_negotiate (GstBaseSrc * basesrc) gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (basesrc))); + if (gst_caps_is_empty (caps)) + return FALSE; + gst_caps_truncate (caps); s = gst_caps_get_structure (caps, 0); From 12837a2611e73a9af235e0f37420269e45b113dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 4 Nov 2009 22:19:58 -0500 Subject: [PATCH 076/138] dtmfdetect: Add DTMF tone detector It looks at raw audio data and emits messages when DTMF is detected. The dtmf detector is the same Goertzel implementation used in FreeSwitch and Asterisk. It is in the public domain. --- gst/dtmf/Makefile.am | 6 +- gst/dtmf/gstdtmf.c | 5 +- gst/dtmf/gstdtmfdetect.c | 308 +++++++++++++++++++++++ gst/dtmf/gstdtmfdetect.h | 73 ++++++ gst/dtmf/tone_detect.c | 517 +++++++++++++++++++++++++++++++++++++++ gst/dtmf/tone_detect.h | 86 +++++++ 6 files changed, 993 insertions(+), 2 deletions(-) create mode 100644 gst/dtmf/gstdtmfdetect.c create mode 100644 gst/dtmf/gstdtmfdetect.h create mode 100644 gst/dtmf/tone_detect.c create mode 100644 gst/dtmf/tone_detect.h diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index 3bdabbb438..cbb351c9dc 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -1,14 +1,18 @@ plugin_LTLIBRARIES = libgstdtmf.la libgstdtmf_la_SOURCES = gstdtmfsrc.c \ + gstdtmfdetect.c \ gstrtpdtmfsrc.c \ gstrtpdtmfdepay.c \ + tone_detect.c \ gstdtmf.c noinst_HEADERS = gstdtmfsrc.h \ + gstdtmfdetect.h \ gstrtpdtmfsrc.h \ gstrtpdtmfdepay.h \ - gstrtpdtmfcommon.h + gstrtpdtmfcommon.h \ + tone_detect.h libgstdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) -lm diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c index d50cf03fc2..9d5854fc1b 100644 --- a/gst/dtmf/gstdtmf.c +++ b/gst/dtmf/gstdtmf.c @@ -3,6 +3,7 @@ #include "config.h" #endif +#include "gstdtmfdetect.h" #include "gstdtmfsrc.h" #include "gstrtpdtmfsrc.h" #include "gstrtpdtmfdepay.h" @@ -11,13 +12,15 @@ static gboolean plugin_init (GstPlugin * plugin) { + if (!gst_dtmf_detect_plugin_init (plugin)) + return FALSE; + 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; diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c new file mode 100644 index 0000000000..5cb7c2cabc --- /dev/null +++ b/gst/dtmf/gstdtmfdetect.c @@ -0,0 +1,308 @@ +/* + * GStreamer - DTMF Detection + * + * Copyright 2009 Nokia Corporation + * Copyright 2009 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * SECTION:element-dtmfdetect + * @short_description: Detects DTMF tones + * + * This element will detect DTMF tones and emit messages + * + * The message is called "dtmf-event" and has the following fields + * + * + * + * + * + * + * + * + * 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-16 + * The event number. + * + * + * method + * G_TYPE_INT + * 2 + * This field will always been 2 (ie sound) from this element. + * + * + * + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdtmfdetect.h" + +#include + +GST_DEBUG_CATEGORY (dtmf_detect_debug); +#define GST_CAT_DEFAULT (dtmf_detect_debug) + +/* elementfactory information */ +static const GstElementDetails gst_dtmf_detect_details = +GST_ELEMENT_DETAILS ("DTMF detector element", + "Detect", + "This element detects DTMF tones", + "Olivier Crete "); + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "width = (int) 16, " + "depth = (int) 16, " + "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " + "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1")); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "width = (int) 16, " + "depth = (int) 16, " + "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " + "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1")); + +/* signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, +}; + +static gboolean gst_dtmf_detect_set_caps (GstBaseTransform * trans, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_dtmf_detect_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); +static gboolean gst_dtmf_detect_event (GstBaseTransform * trans, + GstEvent * event); + +static void +_do_init (GType type) +{ + GST_DEBUG_CATEGORY_INIT (dtmf_detect_debug, "dtmfdetect", 0, "dtmfdetect"); +} + +GST_BOILERPLATE_FULL (GstDtmfDetect, gst_dtmf_detect, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, _do_init); + +static void +gst_dtmf_detect_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details (element_class, &gst_dtmf_detect_details); +} + +static void +gst_dtmf_detect_class_init (GstDtmfDetectClass * klass) +{ + GstBaseTransformClass *gstbasetransform_class; + + gstbasetransform_class = (GstBaseTransformClass *) klass; + + gstbasetransform_class->set_caps = + GST_DEBUG_FUNCPTR (gst_dtmf_detect_set_caps); + gstbasetransform_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_dtmf_detect_transform_ip); + gstbasetransform_class->event = GST_DEBUG_FUNCPTR (gst_dtmf_detect_event); +} + +static void +gst_dtmf_detect_init (GstDtmfDetect * dtmfdetect, GstDtmfDetectClass * klass) +{ + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (dtmfdetect), TRUE); + gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (dtmfdetect), TRUE); +} + +static gboolean +gst_dtmf_detect_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstDtmfDetect *self = GST_DTMF_DETECT (trans); + GstStructure *s = gst_caps_get_structure (incaps, 0); + + if (!gst_structure_get_int (s, "rate", &self->rate)) + return FALSE; + + zap_dtmf_detect_init (&self->dtmf_state); + + return TRUE; +} + + +static GstFlowReturn +gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstDtmfDetect *self = GST_DTMF_DETECT (trans); + int dtmf_count; + char dtmfbuf[MAX_DTMF_DIGITS] = ""; + int i; + + if (GST_BUFFER_IS_DISCONT (buf)) + zap_dtmf_detect_init (&self->dtmf_state); + + + zap_dtmf_detect (&self->dtmf_state, (int16_t *) GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf) / 2, FALSE); + + dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS); + + if (dtmf_count) + GST_DEBUG_OBJECT (self, "Got %d DTMF events: %s", dtmf_count, dtmfbuf); + else + GST_LOG_OBJECT (self, "Got no DTMF events"); + + for (i = 0; i < dtmf_count; i++) { + GstMessage *dtmf_message = NULL; + GstStructure *structure; + gint dtmf_payload_event; + + GST_DEBUG_OBJECT (self, "Got DTMF event %c", dtmfbuf[i]); + + switch (dtmfbuf[i]) { + case '0': + dtmf_payload_event = 0; + break; + case '1': + dtmf_payload_event = 1; + break; + case '2': + dtmf_payload_event = 2; + break; + case '3': + dtmf_payload_event = 3; + break; + case '4': + dtmf_payload_event = 4; + break; + case '5': + dtmf_payload_event = 5; + break; + case '6': + dtmf_payload_event = 6; + break; + case '7': + dtmf_payload_event = 7; + break; + case '8': + dtmf_payload_event = 8; + break; + case '9': + dtmf_payload_event = 9; + break; + case '*': + dtmf_payload_event = 10; + break; + case '#': + dtmf_payload_event = 11; + break; + case 'A': + dtmf_payload_event = 12; + break; + case 'B': + dtmf_payload_event = 13; + break; + case 'C': + dtmf_payload_event = 14; + break; + case 'D': + dtmf_payload_event = 15; + break; + default: + continue; + } + + structure = gst_structure_new ("dtmf-event", + "type", G_TYPE_INT, 1, + "number", G_TYPE_INT, dtmf_payload_event, + "method", G_TYPE_INT, 2, NULL); + dtmf_message = gst_message_new_element (GST_OBJECT (self), structure); + gst_element_post_message (GST_ELEMENT (self), dtmf_message); + } + + return GST_FLOW_OK; +} + + +static gboolean +gst_dtmf_detect_event (GstBaseTransform * trans, GstEvent * event) +{ + GstDtmfDetect *self = GST_DTMF_DETECT (trans); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + zap_dtmf_detect_init (&self->dtmf_state); + break; + default: + break; + } + + return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_TRANSFORM_CLASS, event, + (trans, event), TRUE); +} + + +gboolean +gst_dtmf_detect_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "dtmfdetect", + GST_RANK_MARGINAL, GST_TYPE_DTMF_DETECT); +} diff --git a/gst/dtmf/gstdtmfdetect.h b/gst/dtmf/gstdtmfdetect.h new file mode 100644 index 0000000000..b3bfab94ae --- /dev/null +++ b/gst/dtmf/gstdtmfdetect.h @@ -0,0 +1,73 @@ +/* + * GStreamer - DTMF Detection + * + * Copyright 2009 Nokia Corporation + * Copyright 2009 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GST_DTMF_DETECT_H__ +#define __GST_DTMF_DETECT_H__ + +#include +#include + +#include "tone_detect.h" + +G_BEGIN_DECLS + +/* #define's don't like whitespacey bits */ +#define GST_TYPE_DTMF_DETECT \ + (gst_dtmf_detect_get_type()) +#define GST_DTMF_DETECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_TYPE_DTMF_DETECT,GstDtmfDetect)) +#define GST_DTMF_DETECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_TYPE_DTMF_DETECT,GstDtmfDetectClass)) +#define GST_IS_DTMF_DETECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DTMF_DETECT)) +#define GST_IS_DTMF_DETECT_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DTMF_DETECT)) + +typedef struct _GstDtmfDetect GstDtmfDetect; +typedef struct _GstDtmfDetectClass GstDtmfDetectClass; +typedef struct _GstDtmfDetectPrivate GstDtmfDetectPrivate; + +struct _GstDtmfDetect +{ + GstBaseTransform parent; + + gint rate; + + dtmf_detect_state_t dtmf_state; +}; + +struct _GstDtmfDetectClass +{ + GstBaseTransformClass parent_class; +}; + +GType gst_dtmf_detect_get_type (void); + +gboolean gst_dtmf_detect_plugin_init (GstPlugin *plugin); + +G_END_DECLS + +#endif /* __GST_DTMF_DETECT_H__ */ diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c new file mode 100644 index 0000000000..4785e514fe --- /dev/null +++ b/gst/dtmf/tone_detect.c @@ -0,0 +1,517 @@ +/* + * DTMF Receiver module, part of: + * BSD Telephony Of Mexico "Zapata" Telecom Library, version 1.10 12/9/01 + * + * Part of the "Zapata" Computer Telephony Technology. + * + * See http://www.bsdtelephony.com.mx + * + * + * The technologies, software, hardware, designs, drawings, scheumatics, board + * layouts and/or artwork, concepts, methodologies (including the use of all + * of these, and that which is derived from the use of all of these), all other + * intellectual properties contained herein, and all intellectual property + * rights have been and shall continue to be expressly for the benefit of all + * mankind, and are perpetually placed in the public domain, and may be used, + * copied, and/or modified by anyone, in any manner, for any legal purpose, + * without restriction. + * + * This module written by Stephen Underwood. + */ + +/* + tone_detect.c - General telephony tone detection, and specific + detection of DTMF. + + Copyright (C) 2001 Steve Underwood + + Despite my general liking of the GPL, I place this code in the + public domain for the benefit of all mankind - even the slimy + ones who might try to proprietize my work and use it to my + detriment. +*/ + +#include +#include +#include +#include +#include +#include +#include "tone_detect.h" + +#define FALSE 0 +#define TRUE (!FALSE) + +//#define USE_3DNOW + +/* Basic DTMF specs: + * + * Minimum tone on = 40ms + * Minimum tone off = 50ms + * Maximum digit rate = 10 per second + * Normal twist <= 8dB accepted + * Reverse twist <= 4dB accepted + * S/N >= 15dB will detect OK + * Attenuation <= 26dB will detect OK + * Frequency tolerance +- 1.5% will detect, +-3.5% will reject + */ + +#define SAMPLE_RATE 8000.0 + +#define DTMF_THRESHOLD 8.0e7 +#define FAX_THRESHOLD 8.0e7 +#define FAX_2ND_HARMONIC 2.0 /* 4dB */ +#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ +#define DTMF_REVERSE_TWIST ((isradio) ? 4.0 : 2.5) /* 4dB normal */ +#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ +#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ +#define DTMF_2ND_HARMONIC_ROW ((isradio) ? 1.7 : 2.5) /* 4dB normal */ +#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ + +static tone_detection_descriptor_t dtmf_detect_row[4]; +static tone_detection_descriptor_t dtmf_detect_col[4]; +static tone_detection_descriptor_t dtmf_detect_row_2nd[4]; +static tone_detection_descriptor_t dtmf_detect_col_2nd[4]; +static tone_detection_descriptor_t fax_detect; +static tone_detection_descriptor_t fax_detect_2nd; + +static float dtmf_row[] = +{ + 697.0, 770.0, 852.0, 941.0 +}; +static float dtmf_col[] = +{ + 1209.0, 1336.0, 1477.0, 1633.0 +}; + +static float fax_freq = 1100.0; + +static char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; + +static void goertzel_init(goertzel_state_t *s, + tone_detection_descriptor_t *t) +{ + s->v2 = + s->v3 = 0.0; + s->fac = t->fac; +} +/*- End of function --------------------------------------------------------*/ + +#if defined(USE_3DNOW) +static inline void _dtmf_goertzel_update(goertzel_state_t *s, + float x[], + int samples) +{ + int n; + float v; + int i; + float vv[16]; + + vv[4] = s[0].v2; + vv[5] = s[1].v2; + vv[6] = s[2].v2; + vv[7] = s[3].v2; + vv[8] = s[0].v3; + vv[9] = s[1].v3; + vv[10] = s[2].v3; + vv[11] = s[3].v3; + vv[12] = s[0].fac; + vv[13] = s[1].fac; + vv[14] = s[2].fac; + vv[15] = s[3].fac; + + //v1 = s->v2; + //s->v2 = s->v3; + //s->v3 = s->fac*s->v2 - v1 + x[0]; + + __asm__ __volatile__ ( + " femms;\n" + + " movq 16(%%edx),%%mm2;\n" + " movq 24(%%edx),%%mm3;\n" + " movq 32(%%edx),%%mm4;\n" + " movq 40(%%edx),%%mm5;\n" + " movq 48(%%edx),%%mm6;\n" + " movq 56(%%edx),%%mm7;\n" + + " jmp 1f;\n" + " .align 32;\n" + + " 1: ;\n" + " prefetch (%%eax);\n" + " movq %%mm3,%%mm1;\n" + " movq %%mm2,%%mm0;\n" + " movq %%mm5,%%mm3;\n" + " movq %%mm4,%%mm2;\n" + + " pfmul %%mm7,%%mm5;\n" + " pfmul %%mm6,%%mm4;\n" + " pfsub %%mm1,%%mm5;\n" + " pfsub %%mm0,%%mm4;\n" + + " movq (%%eax),%%mm0;\n" + " movq %%mm0,%%mm1;\n" + " punpckldq %%mm0,%%mm1;\n" + " add $4,%%eax;\n" + " pfadd %%mm1,%%mm5;\n" + " pfadd %%mm1,%%mm4;\n" + + " dec %%ecx;\n" + + " jnz 1b;\n" + + " movq %%mm2,16(%%edx);\n" + " movq %%mm3,24(%%edx);\n" + " movq %%mm4,32(%%edx);\n" + " movq %%mm5,40(%%edx);\n" + + " femms;\n" + : + : "c" (samples), "a" (x), "d" (vv) + : "memory", "eax", "ecx"); + + s[0].v2 = vv[4]; + s[1].v2 = vv[5]; + s[2].v2 = vv[6]; + s[3].v2 = vv[7]; + s[0].v3 = vv[8]; + s[1].v3 = vv[9]; + s[2].v3 = vv[10]; + s[3].v3 = vv[11]; +} +#endif +/*- End of function --------------------------------------------------------*/ + +void zap_goertzel_update(goertzel_state_t *s, + int16_t x[], + int samples) +{ + int i; + float v1; + + for (i = 0; i < samples; i++) + { + v1 = s->v2; + s->v2 = s->v3; + s->v3 = s->fac*s->v2 - v1 + x[i]; + } +} +/*- End of function --------------------------------------------------------*/ + +float zap_goertzel_result (goertzel_state_t *s) +{ + return s->v3*s->v3 + s->v2*s->v2 - s->v2*s->v3*s->fac; +} +/*- End of function --------------------------------------------------------*/ + +void zap_dtmf_detect_init (dtmf_detect_state_t *s) +{ + int i; + float theta; + + s->hit1 = + s->hit2 = 0; + + for (i = 0; i < 4; i++) + { + theta = 2.0*M_PI*(dtmf_row[i]/SAMPLE_RATE); + dtmf_detect_row[i].fac = 2.0*cos(theta); + + theta = 2.0*M_PI*(dtmf_col[i]/SAMPLE_RATE); + dtmf_detect_col[i].fac = 2.0*cos(theta); + + theta = 2.0*M_PI*(dtmf_row[i]*2.0/SAMPLE_RATE); + dtmf_detect_row_2nd[i].fac = 2.0*cos(theta); + + theta = 2.0*M_PI*(dtmf_col[i]*2.0/SAMPLE_RATE); + dtmf_detect_col_2nd[i].fac = 2.0*cos(theta); + + goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + + s->energy = 0.0; + } + + /* Same for the fax dector */ + theta = 2.0*M_PI*(fax_freq/SAMPLE_RATE); + fax_detect.fac = 2.0 * cos(theta); + goertzel_init (&s->fax_tone, &fax_detect); + + /* Same for the fax dector 2nd harmonic */ + theta = 2.0*M_PI*(fax_freq * 2.0/SAMPLE_RATE); + fax_detect_2nd.fac = 2.0 * cos(theta); + goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); + + s->current_sample = 0; + s->detected_digits = 0; + s->lost_digits = 0; + s->digits[0] = '\0'; + s->mhit = 0; +} +/*- End of function --------------------------------------------------------*/ + +int zap_dtmf_detect (dtmf_detect_state_t *s, + int16_t amp[], + int samples, + int isradio) +{ + + float row_energy[4]; + float col_energy[4]; + float fax_energy; + float fax_energy_2nd; + float famp; + float v1; + int i; + int j; + int sample; + int best_row; + int best_col; + int hit; + int limit; + + hit = 0; + for (sample = 0; sample < samples; sample = limit) + { + /* 102 is optimised to meet the DTMF specs. */ + if ((samples - sample) >= (102 - s->current_sample)) + limit = sample + (102 - s->current_sample); + else + limit = samples; +#if defined(USE_3DNOW) + _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); + _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); + _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); + _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); + /* XXX Need to fax detect for 3dnow too XXX */ + #warning "Fax Support Broken" +#else + /* The following unrolled loop takes only 35% (rough estimate) of the + time of a rolled loop on the machine on which it was developed */ + for (j = sample; j < limit; j++) + { + famp = amp[j]; + + s->energy += famp*famp; + + /* With GCC 2.95, the following unrolled code seems to take about 35% + (rough estimate) as long as a neat little 0-3 loop */ + v1 = s->row_out[0].v2; + s->row_out[0].v2 = s->row_out[0].v3; + s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; + + v1 = s->col_out[0].v2; + s->col_out[0].v2 = s->col_out[0].v3; + s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; + + v1 = s->row_out[1].v2; + s->row_out[1].v2 = s->row_out[1].v3; + s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; + + v1 = s->col_out[1].v2; + s->col_out[1].v2 = s->col_out[1].v3; + s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; + + v1 = s->row_out[2].v2; + s->row_out[2].v2 = s->row_out[2].v3; + s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; + + v1 = s->col_out[2].v2; + s->col_out[2].v2 = s->col_out[2].v3; + s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; + + v1 = s->row_out[3].v2; + s->row_out[3].v2 = s->row_out[3].v3; + s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; + + v1 = s->col_out[3].v2; + s->col_out[3].v2 = s->col_out[3].v3; + s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; + + v1 = s->col_out2nd[0].v2; + s->col_out2nd[0].v2 = s->col_out2nd[0].v3; + s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; + + v1 = s->row_out2nd[0].v2; + s->row_out2nd[0].v2 = s->row_out2nd[0].v3; + s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; + + v1 = s->col_out2nd[1].v2; + s->col_out2nd[1].v2 = s->col_out2nd[1].v3; + s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; + + v1 = s->row_out2nd[1].v2; + s->row_out2nd[1].v2 = s->row_out2nd[1].v3; + s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; + + v1 = s->col_out2nd[2].v2; + s->col_out2nd[2].v2 = s->col_out2nd[2].v3; + s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; + + v1 = s->row_out2nd[2].v2; + s->row_out2nd[2].v2 = s->row_out2nd[2].v3; + s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; + + v1 = s->col_out2nd[3].v2; + s->col_out2nd[3].v2 = s->col_out2nd[3].v3; + s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; + + v1 = s->row_out2nd[3].v2; + s->row_out2nd[3].v2 = s->row_out2nd[3].v3; + s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; + + /* Update fax tone */ + v1 = s->fax_tone.v2; + s->fax_tone.v2 = s->fax_tone.v3; + s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; + + v1 = s->fax_tone.v2; + s->fax_tone2nd.v2 = s->fax_tone2nd.v3; + s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; + } +#endif + s->current_sample += (limit - sample); + if (s->current_sample < 102) + continue; + + /* Detect the fax energy, too */ + fax_energy = zap_goertzel_result(&s->fax_tone); + + /* We are at the end of a DTMF detection block */ + /* Find the peak row and the peak column */ + row_energy[0] = zap_goertzel_result (&s->row_out[0]); + col_energy[0] = zap_goertzel_result (&s->col_out[0]); + + for (best_row = best_col = 0, i = 1; i < 4; i++) + { + row_energy[i] = zap_goertzel_result (&s->row_out[i]); + if (row_energy[i] > row_energy[best_row]) + best_row = i; + col_energy[i] = zap_goertzel_result (&s->col_out[i]); + if (col_energy[i] > col_energy[best_col]) + best_col = i; + } + hit = 0; + /* Basic signal level test and the twist test */ + if (row_energy[best_row] >= DTMF_THRESHOLD + && + col_energy[best_col] >= DTMF_THRESHOLD + && + col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST + && + col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) + { + /* Relative peak test */ + for (i = 0; i < 4; i++) + { + if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) + || + (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) + { + break; + } + } + /* ... and second harmonic test */ + if (i >= 4 + && + (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy + && + zap_goertzel_result (&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] + && + zap_goertzel_result (&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) + { + hit = dtmf_positions[(best_row << 2) + best_col]; + /* Look for two successive similar results */ + /* The logic in the next test is: + We need two successive identical clean detects, with + something different preceeding it. This can work with + back to back differing digits. More importantly, it + can work with nasty phones that give a very wobbly start + to a digit. */ + if (hit == s->hit3 && s->hit3 != s->hit2) + { + s->mhit = hit; + s->digit_hits[(best_row << 2) + best_col]++; + s->detected_digits++; + if (s->current_digits < MAX_DTMF_DIGITS) + { + s->digits[s->current_digits++] = hit; + s->digits[s->current_digits] = '\0'; + } + else + { + s->lost_digits++; + } + } + } + } + if (!hit && (fax_energy >= FAX_THRESHOLD) && (fax_energy > s->energy * 21.0)) { + fax_energy_2nd = zap_goertzel_result(&s->fax_tone2nd); + if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) { +#if 0 + printf("Fax energy/Second Harmonic: %f/%f\n", fax_energy, fax_energy_2nd); +#endif + /* XXX Probably need better checking than just this the energy XXX */ + hit = 'f'; + s->fax_hits++; + } /* Don't reset fax hits counter */ + } else { + if (s->fax_hits > 5) { + s->mhit = 'f'; + s->detected_digits++; + if (s->current_digits < MAX_DTMF_DIGITS) + { + s->digits[s->current_digits++] = hit; + s->digits[s->current_digits] = '\0'; + } + else + { + s->lost_digits++; + } + } + s->fax_hits = 0; + } + s->hit1 = s->hit2; + s->hit2 = s->hit3; + s->hit3 = hit; + /* Reinitialise the detector for the next block */ + for (i = 0; i < 4; i++) + { + goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + } + goertzel_init (&s->fax_tone, &fax_detect); + goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); + s->energy = 0.0; + s->current_sample = 0; + } + if ((!s->mhit) || (s->mhit != hit)) + { + s->mhit = 0; + return(0); + } + return (hit); +} +/*- End of function --------------------------------------------------------*/ + +int zap_dtmf_get (dtmf_detect_state_t *s, + char *buf, + int max) +{ + if (max > s->current_digits) + max = s->current_digits; + if (max > 0) + { + memcpy (buf, s->digits, max); + memmove (s->digits, s->digits + max, s->current_digits - max); + s->current_digits -= max; + } + buf[max] = '\0'; + return max; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/gst/dtmf/tone_detect.h b/gst/dtmf/tone_detect.h new file mode 100644 index 0000000000..9b11dbae30 --- /dev/null +++ b/gst/dtmf/tone_detect.h @@ -0,0 +1,86 @@ +/* + * Header file for DTMF Receiver module, part of: + * BSD Telephony Of Mexico "Zapata" Telecom Library, version 1.10 12/9/01 + * + * Part of the "Zapata" Computer Telephony Technology. + * + * See http://www.bsdtelephony.com.mx + * + * + * The technologies, software, hardware, designs, drawings, scheumatics, board + * layouts and/or artwork, concepts, methodologies (including the use of all + * of these, and that which is derived from the use of all of these), all other + * intellectual properties contained herein, and all intellectual property + * rights have been and shall continue to be expressly for the benefit of all + * mankind, and are perpetually placed in the public domain, and may be used, + * copied, and/or modified by anyone, in any manner, for any legal purpose, + * without restriction. + * + * This module written by Stephen Underwood. + */ +/* + tone_detect.h - General telephony tone detection, and specific + detection of DTMF. + + Copyright (C) 2001 Steve Underwood + + Despite my general liking of the GPL, I place this code in the + public domain for the benefit of all mankind - even the slimy + ones who might try to proprietize my work and use it to my + detriment. +*/ + +typedef struct +{ + float v2; + float v3; + float fac; +} goertzel_state_t; + +#define MAX_DTMF_DIGITS 128 + +typedef struct +{ + int hit1; + int hit2; + int hit3; + int hit4; + int mhit; + + goertzel_state_t row_out[4]; + goertzel_state_t col_out[4]; + goertzel_state_t row_out2nd[4]; + goertzel_state_t col_out2nd[4]; + goertzel_state_t fax_tone; + goertzel_state_t fax_tone2nd; + float energy; + + int current_sample; + char digits[MAX_DTMF_DIGITS + 1]; + int current_digits; + int detected_digits; + int lost_digits; + int digit_hits[16]; + int fax_hits; +} dtmf_detect_state_t; + +typedef struct +{ + float fac; +} tone_detection_descriptor_t; + +void zap_goertzel_update(goertzel_state_t *s, + int16_t x[], + int samples); +float zap_goertzel_result (goertzel_state_t *s); + +void zap_dtmf_detect_init (dtmf_detect_state_t *s); +int zap_dtmf_detect (dtmf_detect_state_t *s, + int16_t amp[], + int samples, + int isradio); +int zap_dtmf_get (dtmf_detect_state_t *s, + char *buf, + int max); + +/*- End of file ------------------------------------------------------------*/ From 1f04af784c1d53e71aed05d57e164ea252790fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 19 Nov 2009 20:33:07 -0500 Subject: [PATCH 077/138] dtmf: Update dtmfdetect to make it MSVC friendly https://bugzilla.gnome.org/show_bug.cgi?id=602465 --- gst/dtmf/tone_detect.c | 1 - gst/dtmf/tone_detect.h | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index 4785e514fe..c3b92ba7d4 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -32,7 +32,6 @@ */ #include -#include #include #include #include diff --git a/gst/dtmf/tone_detect.h b/gst/dtmf/tone_detect.h index 9b11dbae30..07c482c55f 100644 --- a/gst/dtmf/tone_detect.h +++ b/gst/dtmf/tone_detect.h @@ -30,6 +30,11 @@ detriment. */ +#ifndef __TONE_DETECT_H__ +#define __TONE_DETECT_H__ + +#include + typedef struct { float v2; @@ -83,4 +88,6 @@ int zap_dtmf_get (dtmf_detect_state_t *s, char *buf, int max); +#endif /* __TONE_DETECT_H__ */ + /*- End of file ------------------------------------------------------------*/ From 5d439f56bb301180416fe63e40204ccdfddd9924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 20 Nov 2009 10:31:47 -0500 Subject: [PATCH 078/138] dtmf: Use _stdint.h from configure https://bugzilla.gnome.org/show_bug.cgi?id=602465 --- gst/dtmf/tone_detect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/tone_detect.h b/gst/dtmf/tone_detect.h index 07c482c55f..909c5ef601 100644 --- a/gst/dtmf/tone_detect.h +++ b/gst/dtmf/tone_detect.h @@ -33,7 +33,7 @@ #ifndef __TONE_DETECT_H__ #define __TONE_DETECT_H__ -#include +#include "_stdint.h" typedef struct { From d40c856ae586227615c03e25c00cbd154db6bbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 22 Nov 2009 19:30:58 +0000 Subject: [PATCH 079/138] Clean up LDFLAGS, LIBS, CFLAGS Fix order, fix variables that don't exist, like GST_LIBS_LIBS, use $(LIBM) instead of -lm, and move _LIBS from LDFLAGS to LIBADD. Spotted by Havard Graff. --- gst/dtmf/Makefile.am | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index cbb351c9dc..049518ea6c 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -14,8 +14,10 @@ noinst_HEADERS = gstdtmfsrc.h \ gstrtpdtmfcommon.h \ tone_detect.h -libgstdtmf_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS) -DEXTERN_BUF -DRTP_SUPPORT -libgstdtmf_la_LIBADD = $(GST_LIBS_LIBS) -lm -libgstdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ +libgstdtmf_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ + -DEXTERN_BUF -DRTP_SUPPORT +libgstdtmf_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ + $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) +libgstdtmf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstdtmf_la_LIBTOOLFLAGS = --tag=disable-static From ecd6632f1858a218aaa7da7e70344c78f20c4230 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 18 Mar 2010 17:30:26 +0100 Subject: [PATCH 080/138] gst_element_class_set_details => gst_element_class_set_details_simple --- gst/dtmf/gstdtmfdetect.c | 13 ++++--------- gst/dtmf/gstdtmfsrc.c | 12 ++++-------- gst/dtmf/gstrtpdtmfdepay.c | 12 ++++-------- gst/dtmf/gstrtpdtmfsrc.c | 11 +++-------- 4 files changed, 15 insertions(+), 33 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 5cb7c2cabc..cf8c058b11 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -84,14 +84,6 @@ GST_DEBUG_CATEGORY (dtmf_detect_debug); #define GST_CAT_DEFAULT (dtmf_detect_debug) -/* elementfactory information */ -static const GstElementDetails gst_dtmf_detect_details = -GST_ELEMENT_DETAILS ("DTMF detector element", - "Detect", - "This element detects DTMF tones", - "Olivier Crete "); - - static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -148,7 +140,10 @@ gst_dtmf_detect_base_init (gpointer klass) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sinktemplate)); - gst_element_class_set_details (element_class, &gst_dtmf_detect_details); + gst_element_class_set_details_simple (element_class, "DTMF detector element", + "Detect", + "This element detects DTMF tones", + "Olivier Crete "); } static void diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 39699d8409..f1244b62be 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -194,13 +194,6 @@ enum DTMF_KEY_EVENT_D = 15, }; -/* elementfactory information */ -static const GstElementDetails gst_dtmf_src_details = -GST_ELEMENT_DETAILS ("DTMF tone generator", - "Source/Audio", - "Generates DTMF tones", - "Youness Alaoui "); - GST_DEBUG_CATEGORY_STATIC (gst_dtmf_src_debug); #define GST_CAT_DEFAULT gst_dtmf_src_debug @@ -253,7 +246,10 @@ gst_dtmf_src_base_init (gpointer g_class) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_dtmf_src_template)); - gst_element_class_set_details (element_class, &gst_dtmf_src_details); + gst_element_class_set_details_simple (element_class, "DTMF tone generator", + "Source/Audio", + "Generates DTMF tones", + "Youness Alaoui "); } static void diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 7cdfabfe7e..9f5ae92789 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -164,13 +164,6 @@ enum DTMF_KEY_EVENT_D = 15, }; -/* elementfactory information */ -static const GstElementDetails gst_rtp_dtmfdepay_details = -GST_ELEMENT_DETAILS ("RTP DTMF packet depayloader", - "Codec/Depayloader/Network", - "Generates DTMF Sound from telephone-event RTP packets", - "Youness Alaoui "); - GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_depay_debug); #define GST_CAT_DEFAULT gst_rtp_dtmf_depay_debug @@ -242,7 +235,10 @@ gst_rtp_dtmf_depay_base_init (gpointer klass) GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug, "rtpdtmfdepay", 0, "rtpdtmfdepay element"); - gst_element_class_set_details (element_class, &gst_rtp_dtmfdepay_details); + gst_element_class_set_details_simple (element_class, + "RTP DTMF packet depayloader", "Codec/Depayloader/Network", + "Generates DTMF Sound from telephone-event RTP packets", + "Youness Alaoui "); } static void diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 65d0ce8c14..0018cb2b9c 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -144,13 +144,6 @@ #define MIN_PACKET_REDUNDANCY 1 #define MAX_PACKET_REDUNDANCY 5 -/* elementfactory information */ -static const GstElementDetails gst_rtp_dtmf_src_details = -GST_ELEMENT_DETAILS ("RTP DTMF packet generator", - "Source/Network", - "Generates RTP DTMF packets", - "Zeeshan Ali "); - GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_src_debug); #define GST_CAT_DEFAULT gst_rtp_dtmf_src_debug @@ -228,7 +221,9 @@ gst_rtp_dtmf_src_base_init (gpointer g_class) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); - gst_element_class_set_details (element_class, &gst_rtp_dtmf_src_details); + gst_element_class_set_details_simple (element_class, + "RTP DTMF packet generator", "Source/Network", + "Generates RTP DTMF packets", "Zeeshan Ali "); } static void From cd564af8732683a074a8d6a51b28364ae621377f Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 21 Mar 2010 21:39:18 +0100 Subject: [PATCH 081/138] Add -Wmissing-declarations -Wmissing-prototypes to configure flags And fix all warnings --- gst/dtmf/gstrtpdtmfdepay.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index dfbcc4af07..172cb8414f 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -60,6 +60,8 @@ struct _GstRtpDTMFDepayClass GstBaseRTPDepayloadClass parent_class; }; +GType gst_rtp_dtmf_depay_get_type (void); + gboolean gst_rtp_dtmf_depay_plugin_init (GstPlugin * plugin); G_END_DECLS From d79780dd629aa471826580c5a421538d9c746925 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 22 Mar 2010 12:02:16 +0100 Subject: [PATCH 082/138] Add -Wredundant-decls flag and fix warnings from it --- gst/dtmf/gstrtpdtmfsrc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 0018cb2b9c..30a9f5c56b 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -185,12 +185,8 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_BOILERPLATE (GstRTPDTMFSrc, gst_rtp_dtmf_src, GstBaseSrc, GST_TYPE_BASE_SRC); - -static void gst_rtp_dtmf_src_base_init (gpointer g_class); -static void gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass); 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, From 316781e0e9860d91a5bba81460c90335f8381857 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 22 Mar 2010 13:16:33 +0100 Subject: [PATCH 083/138] Add -Wwrite-strings and fix its warnings --- gst/dtmf/gstdtmfsrc.c | 2 +- gst/dtmf/gstrtpdtmfdepay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index f1244b62be..8831b39cf7 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -147,7 +147,7 @@ typedef struct st_dtmf_key { - char *event_name; + const char *event_name; int event_encoding; float low_frequency; float high_frequency; diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 9f5ae92789..00ea508e5f 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -117,7 +117,7 @@ typedef struct st_dtmf_key { - char *event_name; + const char *event_name; int event_encoding; float low_frequency; float high_frequency; From f8aa6ab3fee3760a35b46aa2730a6dd625c85c3c Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 25 Mar 2010 22:53:20 +0200 Subject: [PATCH 084/138] dtmfdetect: reformat message docs Use a list like in other element docs as an untweaked docbook table look ugly. --- gst/dtmf/gstdtmfdetect.c | 71 +++++++++++++++------------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index cf8c058b11..cdf717255b 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -26,51 +26,34 @@ * SECTION:element-dtmfdetect * @short_description: Detects DTMF tones * - * This element will detect DTMF tones and emit messages + * This element will detect DTMF tones and emit messages. * - * The message is called "dtmf-event" and has the following fields - * - * - * - * - * - * - * - * - * 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-16 - * The event number. - * - * - * method - * G_TYPE_INT - * 2 - * This field will always been 2 (ie sound) from this element. - * - * - * - * - * + * The message is called "dtmf-event" and has + * the following fields: + * + * + * + * gint type (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 + * specfied by their number. This element can only take events as input. + * Do not confuse with "method" which specified the output. + * + * + * + * + * gint number (0-16): + * The event number. + * + * + * + * + * gint method (2): + * This field will always been 2 (ie sound) from this element. + * + * + * */ #ifdef HAVE_CONFIG_H From 2e2b74df48340374a93f3c8bf75d5982f4759754 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 25 Mar 2010 22:54:49 +0200 Subject: [PATCH 085/138] dtmfdetect: fix classification --- gst/dtmf/gstdtmfdetect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index cdf717255b..78e561563c 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -124,7 +124,7 @@ gst_dtmf_detect_base_init (gpointer klass) gst_static_pad_template_get (&sinktemplate)); gst_element_class_set_details_simple (element_class, "DTMF detector element", - "Detect", + "Filter/Analyzer/Audio", "This element detects DTMF tones", "Olivier Crete "); } From 09b83bc3a38c14db3a6d5ad1a8f5879b7d73fad8 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 25 Mar 2010 22:55:32 +0200 Subject: [PATCH 086/138] dtmfdetect: use glib types --- gst/dtmf/gstdtmfdetect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 78e561563c..a4d0c07e31 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -170,9 +170,9 @@ static GstFlowReturn gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) { GstDtmfDetect *self = GST_DTMF_DETECT (trans); - int dtmf_count; - char dtmfbuf[MAX_DTMF_DIGITS] = ""; - int i; + gint dtmf_count; + gchar dtmfbuf[MAX_DTMF_DIGITS] = ""; + gint i; if (GST_BUFFER_IS_DISCONT (buf)) zap_dtmf_detect_init (&self->dtmf_state); From 763fd13ba973c5798eadc33dd2f299a53e58e713 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 25 Mar 2010 22:58:47 +0200 Subject: [PATCH 087/138] dtmfdetect: if we tell that we handle gap flags, then do so --- gst/dtmf/gstdtmfdetect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index a4d0c07e31..cca196dad1 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -176,7 +176,8 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) if (GST_BUFFER_IS_DISCONT (buf)) zap_dtmf_detect_init (&self->dtmf_state); - + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) + return GST_FLOW_OK; zap_dtmf_detect (&self->dtmf_state, (int16_t *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf) / 2, FALSE); From 032090d9c284a78a7123ab55146b244779b46f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 7 May 2010 18:42:06 -0400 Subject: [PATCH 088/138] dtmf: Remove rtpdtmfmux stream-lock code --- gst/dtmf/gstdtmfsrc.c | 22 ---------------------- gst/dtmf/gstrtpdtmfsrc.c | 22 ---------------------- 2 files changed, 44 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 8831b39cf7..8ed76e0356 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -439,22 +439,6 @@ gst_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, } } -static void -gst_dtmf_src_set_stream_lock (GstDTMFSrc * dtmfsrc, gboolean lock) -{ - GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); - GstEvent *event; - GstStructure *structure; - - structure = gst_structure_new ("stream-lock", - "lock", G_TYPE_BOOLEAN, lock, NULL); - - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - if (!gst_pad_push_event (srcpad, event)) { - GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); - } -} - static void gst_dtmf_prepare_timestamps (GstDTMFSrc * dtmfsrc) { @@ -638,9 +622,6 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, case DTMF_EVENT_TYPE_START: gst_dtmf_prepare_timestamps (dtmfsrc); - /* Don't forget to get exclusive access to the stream */ - gst_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - event->packet_count = 0; dtmfsrc->last_event = event; event = NULL; @@ -673,8 +654,6 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, "Received two consecutive DTMF start events"); break; case DTMF_EVENT_TYPE_STOP: - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_slice_free (GstDTMFSrcEvent, dtmfsrc->last_event); dtmfsrc->last_event = NULL; break; @@ -747,7 +726,6 @@ paused: if (dtmfsrc->last_event) { GST_DEBUG_OBJECT (dtmfsrc, "Stopping current event"); /* Don't forget to release the stream lock */ - gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE); g_slice_free (GstDTMFSrcEvent, dtmfsrc->last_event); dtmfsrc->last_event = NULL; } diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 30a9f5c56b..563585eb55 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -506,22 +506,6 @@ gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, } } -static void -gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc * dtmfsrc, gboolean lock) -{ - GstEvent *event; - GstStructure *structure; - - structure = gst_structure_new ("stream-lock", - "lock", G_TYPE_BOOLEAN, lock, NULL); - - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - if (!gst_pad_push_event (GST_BASE_SRC_PAD (dtmfsrc), event)) { - GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled"); - } - -} - static void gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) { @@ -688,9 +672,6 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; gst_rtp_dtmf_prepare_timestamps (dtmfsrc); - /* Don't forget to get exclusive access to the stream */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE); - dtmfsrc->payload = event->payload; event->payload = NULL; break; @@ -804,9 +785,6 @@ send_last: /* This is the end of the event */ if (dtmfsrc->last_packet == TRUE && dtmfsrc->redundancy_count == 0) { - /* Don't forget to release the stream lock */ - gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE); - g_slice_free (GstRTPDTMFPayload, dtmfsrc->payload); dtmfsrc->payload = NULL; From 2d681fff961f6f6c0a368cab2d78dd35d81d9a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 7 Jun 2010 11:15:26 -0400 Subject: [PATCH 089/138] dtmfdetect: Only works with rate=8000, fix in caps --- gst/dtmf/gstdtmfdetect.c | 8 ++------ gst/dtmf/gstdtmfdetect.h | 2 -- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index cca196dad1..6fa17b5e49 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -74,7 +74,7 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", "width = (int) 16, " "depth = (int) 16, " "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1")); + "signed = (bool) true, rate = (int) 8000, channels = (int) 1")); static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -83,7 +83,7 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", "width = (int) 16, " "depth = (int) 16, " "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1")); + "signed = (bool) true, rate = (int) 8000, channels = (int) 1")); /* signals and args */ enum @@ -155,10 +155,6 @@ gst_dtmf_detect_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) { GstDtmfDetect *self = GST_DTMF_DETECT (trans); - GstStructure *s = gst_caps_get_structure (incaps, 0); - - if (!gst_structure_get_int (s, "rate", &self->rate)) - return FALSE; zap_dtmf_detect_init (&self->dtmf_state); diff --git a/gst/dtmf/gstdtmfdetect.h b/gst/dtmf/gstdtmfdetect.h index b3bfab94ae..01a090792c 100644 --- a/gst/dtmf/gstdtmfdetect.h +++ b/gst/dtmf/gstdtmfdetect.h @@ -54,8 +54,6 @@ struct _GstDtmfDetect { GstBaseTransform parent; - gint rate; - dtmf_detect_state_t dtmf_state; }; From bed1bb3b610be86b779516c3c01d2c9716562e35 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 26 Aug 2010 02:54:55 -0400 Subject: [PATCH 090/138] dtmfsrc: Make the dtmfsrc accept events sent with gst_element_send_event The doc says to use gst_element_send_event on the pipeline, but if we are to call it on the element itself, it's a noop. This should make it handle the event properly before delegating it to basesrc. --- gst/dtmf/gstdtmfsrc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 8ed76e0356..48d359bfe9 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -223,6 +223,7 @@ static void gst_dtmf_src_set_property (GObject * object, guint prop_id, 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, @@ -275,6 +276,7 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) 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); @@ -403,6 +405,17 @@ gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event) return result; } + +static gboolean +gst_dtmf_src_send_event (GstElement * element, GstEvent * event) +{ + + if (gst_dtmf_src_handle_event (GST_BASE_SRC (element), event)) + return TRUE; + + return GST_ELEMENT_CLASS (parent_class)->send_event (element, event); +} + static void gst_dtmf_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) From 594d29b70deb9a651fd99f1e17f51b257fbda31d Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Tue, 19 Oct 2010 13:44:25 +0300 Subject: [PATCH 091/138] dtmfsrc: remove DEBUG_FUNCPTR from gobject vmethods --- gst/dtmf/gstdtmfsrc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 48d359bfe9..9e0e54dfbc 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -265,9 +265,9 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gstelement_class = GST_ELEMENT_CLASS (klass); - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_dtmf_src_finalize); - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_dtmf_src_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_dtmf_src_get_property); + 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", From 7bc9009b37bb1e75377e0bc027f2f2c0dcc2dc4c Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Tue, 19 Oct 2010 13:43:14 +0300 Subject: [PATCH 092/138] various (gst): add missing G_PARAM_STATIC_STRINGS flags Canonicalize property names as needed. --- gst/dtmf/gstdtmfsrc.c | 3 ++- gst/dtmf/gstrtpdtmfdepay.c | 5 +++-- gst/dtmf/gstrtpdtmfsrc.c | 23 ++++++++++++++--------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 9e0e54dfbc..9951c16668 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -272,7 +272,8 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) 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)); + 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); diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 00ea508e5f..858b99af31 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -262,13 +262,14 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) 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)); + 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_READWRITE | G_PARAM_STATIC_STRINGS)); gstbasertpdepayload_class->process = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 563585eb55..22fc59c25e 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -244,41 +244,46 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) 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)); + 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)); + 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_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)); + 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)); + 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)); + 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)); + 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL, g_param_spec_uint ("interval", "Interval between rtp packets", "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL, - MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, G_PARAM_READWRITE)); + MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, + 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)); + DEFAULT_PACKET_REDUNDANCY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_change_state); From 884f716dee31f2dbfc87bfd67120399a02272ed5 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 25 Nov 2010 19:06:27 +0100 Subject: [PATCH 093/138] dtmf: Remove dead assignments --- gst/dtmf/gstrtpdtmfdepay.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 858b99af31..ccf2b02fb0 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -245,11 +245,9 @@ static void gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) { GObjectClass *gobject_class; - GstElementClass *gstelement_class; GstBaseRTPDepayloadClass *gstbasertpdepayload_class; gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; parent_class = g_type_class_peek_parent (klass); From dc54fd9add1c803deb13ff7656ef97bf86c43fd7 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 18:19:47 -0800 Subject: [PATCH 094/138] dtmf: reindent --- gst/dtmf/tone_detect.c | 749 ++++++++++++++++++++--------------------- 1 file changed, 366 insertions(+), 383 deletions(-) diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index c3b92ba7d4..d8f1df16e1 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -60,12 +60,12 @@ #define DTMF_THRESHOLD 8.0e7 #define FAX_THRESHOLD 8.0e7 #define FAX_2ND_HARMONIC 2.0 /* 4dB */ -#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ +#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ #define DTMF_REVERSE_TWIST ((isradio) ? 4.0 : 2.5) /* 4dB normal */ -#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ -#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ +#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ +#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ #define DTMF_2ND_HARMONIC_ROW ((isradio) ? 1.7 : 2.5) /* 4dB normal */ -#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ +#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ static tone_detection_descriptor_t dtmf_detect_row[4]; static tone_detection_descriptor_t dtmf_detect_col[4]; @@ -74,443 +74,426 @@ static tone_detection_descriptor_t dtmf_detect_col_2nd[4]; static tone_detection_descriptor_t fax_detect; static tone_detection_descriptor_t fax_detect_2nd; -static float dtmf_row[] = -{ - 697.0, 770.0, 852.0, 941.0 +static float dtmf_row[] = { + 697.0, 770.0, 852.0, 941.0 }; -static float dtmf_col[] = -{ - 1209.0, 1336.0, 1477.0, 1633.0 + +static float dtmf_col[] = { + 1209.0, 1336.0, 1477.0, 1633.0 }; static float fax_freq = 1100.0; static char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; -static void goertzel_init(goertzel_state_t *s, - tone_detection_descriptor_t *t) +static void +goertzel_init (goertzel_state_t * s, tone_detection_descriptor_t * t) { - s->v2 = - s->v3 = 0.0; - s->fac = t->fac; + s->v2 = s->v3 = 0.0; + s->fac = t->fac; } + /*- End of function --------------------------------------------------------*/ #if defined(USE_3DNOW) -static inline void _dtmf_goertzel_update(goertzel_state_t *s, - float x[], - int samples) +static inline void +_dtmf_goertzel_update (goertzel_state_t * s, float x[], int samples) { - int n; - float v; - int i; - float vv[16]; + int n; + float v; + int i; + float vv[16]; - vv[4] = s[0].v2; - vv[5] = s[1].v2; - vv[6] = s[2].v2; - vv[7] = s[3].v2; - vv[8] = s[0].v3; - vv[9] = s[1].v3; - vv[10] = s[2].v3; - vv[11] = s[3].v3; - vv[12] = s[0].fac; - vv[13] = s[1].fac; - vv[14] = s[2].fac; - vv[15] = s[3].fac; + vv[4] = s[0].v2; + vv[5] = s[1].v2; + vv[6] = s[2].v2; + vv[7] = s[3].v2; + vv[8] = s[0].v3; + vv[9] = s[1].v3; + vv[10] = s[2].v3; + vv[11] = s[3].v3; + vv[12] = s[0].fac; + vv[13] = s[1].fac; + vv[14] = s[2].fac; + vv[15] = s[3].fac; - //v1 = s->v2; - //s->v2 = s->v3; - //s->v3 = s->fac*s->v2 - v1 + x[0]; + //v1 = s->v2; + //s->v2 = s->v3; + //s->v3 = s->fac*s->v2 - v1 + x[0]; - __asm__ __volatile__ ( - " femms;\n" + __asm__ __volatile__ (" femms;\n" + " movq 16(%%edx),%%mm2;\n" + " movq 24(%%edx),%%mm3;\n" + " movq 32(%%edx),%%mm4;\n" + " movq 40(%%edx),%%mm5;\n" + " movq 48(%%edx),%%mm6;\n" + " movq 56(%%edx),%%mm7;\n" + " jmp 1f;\n" + " .align 32;\n" + " 1: ;\n" + " prefetch (%%eax);\n" + " movq %%mm3,%%mm1;\n" + " movq %%mm2,%%mm0;\n" + " movq %%mm5,%%mm3;\n" + " movq %%mm4,%%mm2;\n" + " pfmul %%mm7,%%mm5;\n" + " pfmul %%mm6,%%mm4;\n" + " pfsub %%mm1,%%mm5;\n" + " pfsub %%mm0,%%mm4;\n" + " movq (%%eax),%%mm0;\n" + " movq %%mm0,%%mm1;\n" + " punpckldq %%mm0,%%mm1;\n" + " add $4,%%eax;\n" + " pfadd %%mm1,%%mm5;\n" + " pfadd %%mm1,%%mm4;\n" + " dec %%ecx;\n" + " jnz 1b;\n" + " movq %%mm2,16(%%edx);\n" + " movq %%mm3,24(%%edx);\n" + " movq %%mm4,32(%%edx);\n" + " movq %%mm5,40(%%edx);\n" + " femms;\n"::"c" (samples), "a" (x), "d" (vv) + :"memory", "eax", "ecx"); - " movq 16(%%edx),%%mm2;\n" - " movq 24(%%edx),%%mm3;\n" - " movq 32(%%edx),%%mm4;\n" - " movq 40(%%edx),%%mm5;\n" - " movq 48(%%edx),%%mm6;\n" - " movq 56(%%edx),%%mm7;\n" - - " jmp 1f;\n" - " .align 32;\n" - - " 1: ;\n" - " prefetch (%%eax);\n" - " movq %%mm3,%%mm1;\n" - " movq %%mm2,%%mm0;\n" - " movq %%mm5,%%mm3;\n" - " movq %%mm4,%%mm2;\n" - - " pfmul %%mm7,%%mm5;\n" - " pfmul %%mm6,%%mm4;\n" - " pfsub %%mm1,%%mm5;\n" - " pfsub %%mm0,%%mm4;\n" - - " movq (%%eax),%%mm0;\n" - " movq %%mm0,%%mm1;\n" - " punpckldq %%mm0,%%mm1;\n" - " add $4,%%eax;\n" - " pfadd %%mm1,%%mm5;\n" - " pfadd %%mm1,%%mm4;\n" - - " dec %%ecx;\n" - - " jnz 1b;\n" - - " movq %%mm2,16(%%edx);\n" - " movq %%mm3,24(%%edx);\n" - " movq %%mm4,32(%%edx);\n" - " movq %%mm5,40(%%edx);\n" - - " femms;\n" - : - : "c" (samples), "a" (x), "d" (vv) - : "memory", "eax", "ecx"); - - s[0].v2 = vv[4]; - s[1].v2 = vv[5]; - s[2].v2 = vv[6]; - s[3].v2 = vv[7]; - s[0].v3 = vv[8]; - s[1].v3 = vv[9]; - s[2].v3 = vv[10]; - s[3].v3 = vv[11]; + s[0].v2 = vv[4]; + s[1].v2 = vv[5]; + s[2].v2 = vv[6]; + s[3].v2 = vv[7]; + s[0].v3 = vv[8]; + s[1].v3 = vv[9]; + s[2].v3 = vv[10]; + s[3].v3 = vv[11]; } #endif /*- End of function --------------------------------------------------------*/ -void zap_goertzel_update(goertzel_state_t *s, - int16_t x[], - int samples) +void +zap_goertzel_update (goertzel_state_t * s, int16_t x[], int samples) { - int i; - float v1; - - for (i = 0; i < samples; i++) - { - v1 = s->v2; - s->v2 = s->v3; - s->v3 = s->fac*s->v2 - v1 + x[i]; - } + int i; + float v1; + + for (i = 0; i < samples; i++) { + v1 = s->v2; + s->v2 = s->v3; + s->v3 = s->fac * s->v2 - v1 + x[i]; + } } + /*- End of function --------------------------------------------------------*/ -float zap_goertzel_result (goertzel_state_t *s) +float +zap_goertzel_result (goertzel_state_t * s) { - return s->v3*s->v3 + s->v2*s->v2 - s->v2*s->v3*s->fac; + return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac; } + /*- End of function --------------------------------------------------------*/ -void zap_dtmf_detect_init (dtmf_detect_state_t *s) +void +zap_dtmf_detect_init (dtmf_detect_state_t * s) { - int i; - float theta; + int i; + float theta; - s->hit1 = - s->hit2 = 0; + s->hit1 = s->hit2 = 0; - for (i = 0; i < 4; i++) - { - theta = 2.0*M_PI*(dtmf_row[i]/SAMPLE_RATE); - dtmf_detect_row[i].fac = 2.0*cos(theta); + for (i = 0; i < 4; i++) { + theta = 2.0 * M_PI * (dtmf_row[i] / SAMPLE_RATE); + dtmf_detect_row[i].fac = 2.0 * cos (theta); - theta = 2.0*M_PI*(dtmf_col[i]/SAMPLE_RATE); - dtmf_detect_col[i].fac = 2.0*cos(theta); - - theta = 2.0*M_PI*(dtmf_row[i]*2.0/SAMPLE_RATE); - dtmf_detect_row_2nd[i].fac = 2.0*cos(theta); + theta = 2.0 * M_PI * (dtmf_col[i] / SAMPLE_RATE); + dtmf_detect_col[i].fac = 2.0 * cos (theta); - theta = 2.0*M_PI*(dtmf_col[i]*2.0/SAMPLE_RATE); - dtmf_detect_col_2nd[i].fac = 2.0*cos(theta); - - goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); - - s->energy = 0.0; - } + theta = 2.0 * M_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); + dtmf_detect_row_2nd[i].fac = 2.0 * cos (theta); - /* Same for the fax dector */ - theta = 2.0*M_PI*(fax_freq/SAMPLE_RATE); - fax_detect.fac = 2.0 * cos(theta); - goertzel_init (&s->fax_tone, &fax_detect); + theta = 2.0 * M_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); + dtmf_detect_col_2nd[i].fac = 2.0 * cos (theta); - /* Same for the fax dector 2nd harmonic */ - theta = 2.0*M_PI*(fax_freq * 2.0/SAMPLE_RATE); - fax_detect_2nd.fac = 2.0 * cos(theta); - goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); - - s->current_sample = 0; - s->detected_digits = 0; - s->lost_digits = 0; - s->digits[0] = '\0'; - s->mhit = 0; + goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + + s->energy = 0.0; + } + + /* Same for the fax dector */ + theta = 2.0 * M_PI * (fax_freq / SAMPLE_RATE); + fax_detect.fac = 2.0 * cos (theta); + goertzel_init (&s->fax_tone, &fax_detect); + + /* Same for the fax dector 2nd harmonic */ + theta = 2.0 * M_PI * (fax_freq * 2.0 / SAMPLE_RATE); + fax_detect_2nd.fac = 2.0 * cos (theta); + goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); + + s->current_sample = 0; + s->detected_digits = 0; + s->lost_digits = 0; + s->digits[0] = '\0'; + s->mhit = 0; } + /*- End of function --------------------------------------------------------*/ -int zap_dtmf_detect (dtmf_detect_state_t *s, - int16_t amp[], - int samples, - int isradio) +int +zap_dtmf_detect (dtmf_detect_state_t * s, + int16_t amp[], int samples, int isradio) { - float row_energy[4]; - float col_energy[4]; - float fax_energy; - float fax_energy_2nd; - float famp; - float v1; - int i; - int j; - int sample; - int best_row; - int best_col; - int hit; - int limit; + float row_energy[4]; + float col_energy[4]; + float fax_energy; + float fax_energy_2nd; + float famp; + float v1; + int i; + int j; + int sample; + int best_row; + int best_col; + int hit; + int limit; - hit = 0; - for (sample = 0; sample < samples; sample = limit) - { - /* 102 is optimised to meet the DTMF specs. */ - if ((samples - sample) >= (102 - s->current_sample)) - limit = sample + (102 - s->current_sample); - else - limit = samples; + hit = 0; + for (sample = 0; sample < samples; sample = limit) { + /* 102 is optimised to meet the DTMF specs. */ + if ((samples - sample) >= (102 - s->current_sample)) + limit = sample + (102 - s->current_sample); + else + limit = samples; #if defined(USE_3DNOW) - _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); - _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); - _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); - _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); - /* XXX Need to fax detect for 3dnow too XXX */ - #warning "Fax Support Broken" + _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); + _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); + _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); + _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); + /* XXX Need to fax detect for 3dnow too XXX */ +#warning "Fax Support Broken" #else - /* The following unrolled loop takes only 35% (rough estimate) of the - time of a rolled loop on the machine on which it was developed */ - for (j = sample; j < limit; j++) - { - famp = amp[j]; - - s->energy += famp*famp; - - /* With GCC 2.95, the following unrolled code seems to take about 35% - (rough estimate) as long as a neat little 0-3 loop */ - v1 = s->row_out[0].v2; - s->row_out[0].v2 = s->row_out[0].v3; - s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; - - v1 = s->col_out[0].v2; - s->col_out[0].v2 = s->col_out[0].v3; - s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; - - v1 = s->row_out[1].v2; - s->row_out[1].v2 = s->row_out[1].v3; - s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; - - v1 = s->col_out[1].v2; - s->col_out[1].v2 = s->col_out[1].v3; - s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; - - v1 = s->row_out[2].v2; - s->row_out[2].v2 = s->row_out[2].v3; - s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; - - v1 = s->col_out[2].v2; - s->col_out[2].v2 = s->col_out[2].v3; - s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; - - v1 = s->row_out[3].v2; - s->row_out[3].v2 = s->row_out[3].v3; - s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; + /* The following unrolled loop takes only 35% (rough estimate) of the + time of a rolled loop on the machine on which it was developed */ + for (j = sample; j < limit; j++) { + famp = amp[j]; - v1 = s->col_out[3].v2; - s->col_out[3].v2 = s->col_out[3].v3; - s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; + s->energy += famp * famp; - v1 = s->col_out2nd[0].v2; - s->col_out2nd[0].v2 = s->col_out2nd[0].v3; - s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; - - v1 = s->row_out2nd[0].v2; - s->row_out2nd[0].v2 = s->row_out2nd[0].v3; - s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; - - v1 = s->col_out2nd[1].v2; - s->col_out2nd[1].v2 = s->col_out2nd[1].v3; - s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; - - v1 = s->row_out2nd[1].v2; - s->row_out2nd[1].v2 = s->row_out2nd[1].v3; - s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; - - v1 = s->col_out2nd[2].v2; - s->col_out2nd[2].v2 = s->col_out2nd[2].v3; - s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; - - v1 = s->row_out2nd[2].v2; - s->row_out2nd[2].v2 = s->row_out2nd[2].v3; - s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; - - v1 = s->col_out2nd[3].v2; - s->col_out2nd[3].v2 = s->col_out2nd[3].v3; - s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; - - v1 = s->row_out2nd[3].v2; - s->row_out2nd[3].v2 = s->row_out2nd[3].v3; - s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; + /* With GCC 2.95, the following unrolled code seems to take about 35% + (rough estimate) as long as a neat little 0-3 loop */ + v1 = s->row_out[0].v2; + s->row_out[0].v2 = s->row_out[0].v3; + s->row_out[0].v3 = s->row_out[0].fac * s->row_out[0].v2 - v1 + famp; - /* Update fax tone */ - v1 = s->fax_tone.v2; - s->fax_tone.v2 = s->fax_tone.v3; - s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; + v1 = s->col_out[0].v2; + s->col_out[0].v2 = s->col_out[0].v3; + s->col_out[0].v3 = s->col_out[0].fac * s->col_out[0].v2 - v1 + famp; - v1 = s->fax_tone.v2; - s->fax_tone2nd.v2 = s->fax_tone2nd.v3; - s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; - } + v1 = s->row_out[1].v2; + s->row_out[1].v2 = s->row_out[1].v3; + s->row_out[1].v3 = s->row_out[1].fac * s->row_out[1].v2 - v1 + famp; + + v1 = s->col_out[1].v2; + s->col_out[1].v2 = s->col_out[1].v3; + s->col_out[1].v3 = s->col_out[1].fac * s->col_out[1].v2 - v1 + famp; + + v1 = s->row_out[2].v2; + s->row_out[2].v2 = s->row_out[2].v3; + s->row_out[2].v3 = s->row_out[2].fac * s->row_out[2].v2 - v1 + famp; + + v1 = s->col_out[2].v2; + s->col_out[2].v2 = s->col_out[2].v3; + s->col_out[2].v3 = s->col_out[2].fac * s->col_out[2].v2 - v1 + famp; + + v1 = s->row_out[3].v2; + s->row_out[3].v2 = s->row_out[3].v3; + s->row_out[3].v3 = s->row_out[3].fac * s->row_out[3].v2 - v1 + famp; + + v1 = s->col_out[3].v2; + s->col_out[3].v2 = s->col_out[3].v3; + s->col_out[3].v3 = s->col_out[3].fac * s->col_out[3].v2 - v1 + famp; + + v1 = s->col_out2nd[0].v2; + s->col_out2nd[0].v2 = s->col_out2nd[0].v3; + s->col_out2nd[0].v3 = + s->col_out2nd[0].fac * s->col_out2nd[0].v2 - v1 + famp; + + v1 = s->row_out2nd[0].v2; + s->row_out2nd[0].v2 = s->row_out2nd[0].v3; + s->row_out2nd[0].v3 = + s->row_out2nd[0].fac * s->row_out2nd[0].v2 - v1 + famp; + + v1 = s->col_out2nd[1].v2; + s->col_out2nd[1].v2 = s->col_out2nd[1].v3; + s->col_out2nd[1].v3 = + s->col_out2nd[1].fac * s->col_out2nd[1].v2 - v1 + famp; + + v1 = s->row_out2nd[1].v2; + s->row_out2nd[1].v2 = s->row_out2nd[1].v3; + s->row_out2nd[1].v3 = + s->row_out2nd[1].fac * s->row_out2nd[1].v2 - v1 + famp; + + v1 = s->col_out2nd[2].v2; + s->col_out2nd[2].v2 = s->col_out2nd[2].v3; + s->col_out2nd[2].v3 = + s->col_out2nd[2].fac * s->col_out2nd[2].v2 - v1 + famp; + + v1 = s->row_out2nd[2].v2; + s->row_out2nd[2].v2 = s->row_out2nd[2].v3; + s->row_out2nd[2].v3 = + s->row_out2nd[2].fac * s->row_out2nd[2].v2 - v1 + famp; + + v1 = s->col_out2nd[3].v2; + s->col_out2nd[3].v2 = s->col_out2nd[3].v3; + s->col_out2nd[3].v3 = + s->col_out2nd[3].fac * s->col_out2nd[3].v2 - v1 + famp; + + v1 = s->row_out2nd[3].v2; + s->row_out2nd[3].v2 = s->row_out2nd[3].v3; + s->row_out2nd[3].v3 = + s->row_out2nd[3].fac * s->row_out2nd[3].v2 - v1 + famp; + + /* Update fax tone */ + v1 = s->fax_tone.v2; + s->fax_tone.v2 = s->fax_tone.v3; + s->fax_tone.v3 = s->fax_tone.fac * s->fax_tone.v2 - v1 + famp; + + v1 = s->fax_tone.v2; + s->fax_tone2nd.v2 = s->fax_tone2nd.v3; + s->fax_tone2nd.v3 = s->fax_tone2nd.fac * s->fax_tone2nd.v2 - v1 + famp; + } #endif - s->current_sample += (limit - sample); - if (s->current_sample < 102) - continue; + s->current_sample += (limit - sample); + if (s->current_sample < 102) + continue; - /* Detect the fax energy, too */ - fax_energy = zap_goertzel_result(&s->fax_tone); - - /* We are at the end of a DTMF detection block */ - /* Find the peak row and the peak column */ - row_energy[0] = zap_goertzel_result (&s->row_out[0]); - col_energy[0] = zap_goertzel_result (&s->col_out[0]); + /* Detect the fax energy, too */ + fax_energy = zap_goertzel_result (&s->fax_tone); - for (best_row = best_col = 0, i = 1; i < 4; i++) - { - row_energy[i] = zap_goertzel_result (&s->row_out[i]); - if (row_energy[i] > row_energy[best_row]) - best_row = i; - col_energy[i] = zap_goertzel_result (&s->col_out[i]); - if (col_energy[i] > col_energy[best_col]) - best_col = i; - } - hit = 0; - /* Basic signal level test and the twist test */ - if (row_energy[best_row] >= DTMF_THRESHOLD - && - col_energy[best_col] >= DTMF_THRESHOLD - && - col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST - && - col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) - { - /* Relative peak test */ - for (i = 0; i < 4; i++) - { - if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) - || - (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) - { - break; - } - } - /* ... and second harmonic test */ - if (i >= 4 - && - (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy - && - zap_goertzel_result (&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] - && - zap_goertzel_result (&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) - { - hit = dtmf_positions[(best_row << 2) + best_col]; - /* Look for two successive similar results */ - /* The logic in the next test is: - We need two successive identical clean detects, with - something different preceeding it. This can work with - back to back differing digits. More importantly, it - can work with nasty phones that give a very wobbly start - to a digit. */ - if (hit == s->hit3 && s->hit3 != s->hit2) - { - s->mhit = hit; - s->digit_hits[(best_row << 2) + best_col]++; - s->detected_digits++; - if (s->current_digits < MAX_DTMF_DIGITS) - { - s->digits[s->current_digits++] = hit; - s->digits[s->current_digits] = '\0'; - } - else - { - s->lost_digits++; - } - } - } - } - if (!hit && (fax_energy >= FAX_THRESHOLD) && (fax_energy > s->energy * 21.0)) { - fax_energy_2nd = zap_goertzel_result(&s->fax_tone2nd); - if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) { -#if 0 - printf("Fax energy/Second Harmonic: %f/%f\n", fax_energy, fax_energy_2nd); -#endif - /* XXX Probably need better checking than just this the energy XXX */ - hit = 'f'; - s->fax_hits++; - } /* Don't reset fax hits counter */ - } else { - if (s->fax_hits > 5) { - s->mhit = 'f'; - s->detected_digits++; - if (s->current_digits < MAX_DTMF_DIGITS) - { - s->digits[s->current_digits++] = hit; - s->digits[s->current_digits] = '\0'; - } - else - { - s->lost_digits++; - } - } - s->fax_hits = 0; - } - s->hit1 = s->hit2; - s->hit2 = s->hit3; - s->hit3 = hit; - /* Reinitialise the detector for the next block */ - for (i = 0; i < 4; i++) - { - goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + /* We are at the end of a DTMF detection block */ + /* Find the peak row and the peak column */ + row_energy[0] = zap_goertzel_result (&s->row_out[0]); + col_energy[0] = zap_goertzel_result (&s->col_out[0]); + + for (best_row = best_col = 0, i = 1; i < 4; i++) { + row_energy[i] = zap_goertzel_result (&s->row_out[i]); + if (row_energy[i] > row_energy[best_row]) + best_row = i; + col_energy[i] = zap_goertzel_result (&s->col_out[i]); + if (col_energy[i] > col_energy[best_col]) + best_col = i; + } + hit = 0; + /* Basic signal level test and the twist test */ + if (row_energy[best_row] >= DTMF_THRESHOLD + && + col_energy[best_col] >= DTMF_THRESHOLD + && + col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST + && col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) { + /* Relative peak test */ + for (i = 0; i < 4; i++) { + if ((i != best_col + && col_energy[i] * DTMF_RELATIVE_PEAK_COL > + col_energy[best_col]) + || (i != best_row + && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > + row_energy[best_row])) { + break; } - goertzel_init (&s->fax_tone, &fax_detect); - goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); - s->energy = 0.0; - s->current_sample = 0; + } + /* ... and second harmonic test */ + if (i >= 4 + && + (row_energy[best_row] + col_energy[best_col]) > 42.0 * s->energy + && + zap_goertzel_result (&s->col_out2nd[best_col]) * + DTMF_2ND_HARMONIC_COL < col_energy[best_col] + && zap_goertzel_result (&s->row_out2nd[best_row]) * + DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { + hit = dtmf_positions[(best_row << 2) + best_col]; + /* Look for two successive similar results */ + /* The logic in the next test is: + We need two successive identical clean detects, with + something different preceeding it. This can work with + back to back differing digits. More importantly, it + can work with nasty phones that give a very wobbly start + to a digit. */ + if (hit == s->hit3 && s->hit3 != s->hit2) { + s->mhit = hit; + s->digit_hits[(best_row << 2) + best_col]++; + s->detected_digits++; + if (s->current_digits < MAX_DTMF_DIGITS) { + s->digits[s->current_digits++] = hit; + s->digits[s->current_digits] = '\0'; + } else { + s->lost_digits++; + } + } + } } - if ((!s->mhit) || (s->mhit != hit)) - { - s->mhit = 0; - return(0); + if (!hit && (fax_energy >= FAX_THRESHOLD) + && (fax_energy > s->energy * 21.0)) { + fax_energy_2nd = zap_goertzel_result (&s->fax_tone2nd); + if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) { +#if 0 + printf ("Fax energy/Second Harmonic: %f/%f\n", fax_energy, + fax_energy_2nd); +#endif + /* XXX Probably need better checking than just this the energy XXX */ + hit = 'f'; + s->fax_hits++; + } /* Don't reset fax hits counter */ + } else { + if (s->fax_hits > 5) { + s->mhit = 'f'; + s->detected_digits++; + if (s->current_digits < MAX_DTMF_DIGITS) { + s->digits[s->current_digits++] = hit; + s->digits[s->current_digits] = '\0'; + } else { + s->lost_digits++; + } + } + s->fax_hits = 0; } - return (hit); + s->hit1 = s->hit2; + s->hit2 = s->hit3; + s->hit3 = hit; + /* Reinitialise the detector for the next block */ + for (i = 0; i < 4; i++) { + goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + } + goertzel_init (&s->fax_tone, &fax_detect); + goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); + s->energy = 0.0; + s->current_sample = 0; + } + if ((!s->mhit) || (s->mhit != hit)) { + s->mhit = 0; + return (0); + } + return (hit); } + /*- End of function --------------------------------------------------------*/ -int zap_dtmf_get (dtmf_detect_state_t *s, - char *buf, - int max) +int +zap_dtmf_get (dtmf_detect_state_t * s, char *buf, int max) { - if (max > s->current_digits) - max = s->current_digits; - if (max > 0) - { - memcpy (buf, s->digits, max); - memmove (s->digits, s->digits + max, s->current_digits - max); - s->current_digits -= max; - } - buf[max] = '\0'; - return max; + if (max > s->current_digits) + max = s->current_digits; + if (max > 0) { + memcpy (buf, s->digits, max); + memmove (s->digits, s->digits + max, s->current_digits - max); + s->current_digits -= max; + } + buf[max] = '\0'; + return max; } + /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ From ae9bb7a179b1f76a56b33a5b58ca2fa1b87856e3 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 18:20:47 -0800 Subject: [PATCH 095/138] dtmf: build fixes for MSVC Use gint16 and G_PI. --- gst/dtmf/gstdtmfdetect.c | 2 +- gst/dtmf/tone_detect.c | 12 ++++++------ gst/dtmf/tone_detect.h | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 6fa17b5e49..0bb9242647 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -175,7 +175,7 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) return GST_FLOW_OK; - zap_dtmf_detect (&self->dtmf_state, (int16_t *) GST_BUFFER_DATA (buf), + zap_dtmf_detect (&self->dtmf_state, (gint16 *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf) / 2, FALSE); dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS); diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index d8f1df16e1..8c1b5ad956 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -199,16 +199,16 @@ zap_dtmf_detect_init (dtmf_detect_state_t * s) s->hit1 = s->hit2 = 0; for (i = 0; i < 4; i++) { - theta = 2.0 * M_PI * (dtmf_row[i] / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_row[i] / SAMPLE_RATE); dtmf_detect_row[i].fac = 2.0 * cos (theta); - theta = 2.0 * M_PI * (dtmf_col[i] / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_col[i] / SAMPLE_RATE); dtmf_detect_col[i].fac = 2.0 * cos (theta); - theta = 2.0 * M_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); dtmf_detect_row_2nd[i].fac = 2.0 * cos (theta); - theta = 2.0 * M_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); dtmf_detect_col_2nd[i].fac = 2.0 * cos (theta); goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); @@ -220,12 +220,12 @@ zap_dtmf_detect_init (dtmf_detect_state_t * s) } /* Same for the fax dector */ - theta = 2.0 * M_PI * (fax_freq / SAMPLE_RATE); + theta = 2.0 * G_PI * (fax_freq / SAMPLE_RATE); fax_detect.fac = 2.0 * cos (theta); goertzel_init (&s->fax_tone, &fax_detect); /* Same for the fax dector 2nd harmonic */ - theta = 2.0 * M_PI * (fax_freq * 2.0 / SAMPLE_RATE); + theta = 2.0 * G_PI * (fax_freq * 2.0 / SAMPLE_RATE); fax_detect_2nd.fac = 2.0 * cos (theta); goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); diff --git a/gst/dtmf/tone_detect.h b/gst/dtmf/tone_detect.h index 909c5ef601..ce6dddd2cb 100644 --- a/gst/dtmf/tone_detect.h +++ b/gst/dtmf/tone_detect.h @@ -35,6 +35,8 @@ #include "_stdint.h" +#include + typedef struct { float v2; @@ -75,13 +77,13 @@ typedef struct } tone_detection_descriptor_t; void zap_goertzel_update(goertzel_state_t *s, - int16_t x[], + gint16 x[], int samples); float zap_goertzel_result (goertzel_state_t *s); void zap_dtmf_detect_init (dtmf_detect_state_t *s); int zap_dtmf_detect (dtmf_detect_state_t *s, - int16_t amp[], + gint16 amp[], int samples, int isradio); int zap_dtmf_get (dtmf_detect_state_t *s, From fc96e423db8deadfe61c1f8ddefc7eda78ad2394 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 31 Dec 2010 00:12:53 -0800 Subject: [PATCH 096/138] dtmf: Fix build failure caused by previous commit --- gst/dtmf/tone_detect.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index 8c1b5ad956..73a73ee98b 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -38,8 +38,12 @@ #include #include "tone_detect.h" +#ifndef FALSE #define FALSE 0 +#endif +#ifndef TRUE #define TRUE (!FALSE) +#endif //#define USE_3DNOW From 3c86c6432ae6c649a6a9743517b54fc997a642d4 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 11 Apr 2011 00:36:35 -0400 Subject: [PATCH 097/138] android: make it ready for androgenizer Remove the android/ top dir Fixe the Makefile.am to be androgenized To build gstreamer for android we are now using androgenizer which generates the needed Android.mk files. Androgenizer can be found here: http://git.collabora.co.uk/?p=user/derek/androgenizer.git --- gst/dtmf/Makefile.am | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index 049518ea6c..761575d768 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -21,3 +21,16 @@ libgstdtmf_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ 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' \ + > $@ \ No newline at end of file From 27cafd8d8eac248b160e81fff0fccffc6ab9fe8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 12 Apr 2011 16:42:17 -0400 Subject: [PATCH 098/138] dtmf: Remove leftover MAEMO_BROKEN defines Remove defines to work around bugs in old Maemo releases --- gst/dtmf/gstdtmfsrc.c | 18 ++++-------------- gst/dtmf/gstrtpdtmfsrc.c | 17 +++-------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 9951c16668..f929bae728 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -113,7 +113,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif #include @@ -123,7 +123,7 @@ #include #ifndef M_PI -# define M_PI 3.14159265358979323846 /* pi */ +#define M_PI 3.14159265358979323846 /* pi */ #endif @@ -457,17 +457,11 @@ static void gst_dtmf_prepare_timestamps (GstDTMFSrc * dtmfsrc) { GstClock *clock; - GstClockTime base_time; - - base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { -#ifdef MAEMO_BROKEN - dtmfsrc->timestamp = gst_clock_get_time (clock); -#else - dtmfsrc->timestamp = gst_clock_get_time (clock) - base_time; -#endif + dtmfsrc->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); @@ -696,12 +690,8 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, clock = gst_element_get_clock (GST_ELEMENT (basesrc)); -#ifdef MAEMO_BROKEN - clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp); -#else clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp + gst_element_get_base_time (GST_ELEMENT (dtmfsrc))); -#endif gst_object_unref (clock); GST_OBJECT_LOCK (dtmfsrc); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 22fc59c25e..ec2c6c6c27 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -111,7 +111,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif #include @@ -515,18 +515,12 @@ static void gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) { GstClock *clock; - GstClockTime base_time; - -#ifdef MAEMO_BROKEN - base_time = 0; -#else - base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); -#endif clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); if (clock != NULL) { dtmfsrc->timestamp = gst_clock_get_time (clock) - + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - base_time; + + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) + - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); dtmfsrc->start_timestamp = dtmfsrc->timestamp; gst_object_unref (clock); } else { @@ -742,13 +736,8 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock"); clock = gst_element_get_clock (GST_ELEMENT (basesrc)); - -#ifdef MAEMO_BROKEN - clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp); -#else clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp + gst_element_get_base_time (GST_ELEMENT (dtmfsrc))); -#endif gst_object_unref (clock); GST_OBJECT_LOCK (dtmfsrc); From d68165cff809fd4ef73765c13732304f7dcf401d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 13 Apr 2011 21:58:36 -0400 Subject: [PATCH 099/138] dtmf: Move duplicate #defines into a common include Centralize duplicated constants so they have the same value. Also standardise minimum tone duration to 250ms and minimum inter-tone interval to 100ms. --- gst/dtmf/Makefile.am | 2 +- gst/dtmf/{gstrtpdtmfcommon.h => gstdtmfcommon.h} | 14 ++++++++++++++ gst/dtmf/gstdtmfsrc.c | 11 +---------- gst/dtmf/gstrtpdtmfdepay.c | 13 +------------ gst/dtmf/gstrtpdtmfdepay.h | 2 +- gst/dtmf/gstrtpdtmfsrc.c | 9 --------- gst/dtmf/gstrtpdtmfsrc.h | 2 +- 7 files changed, 19 insertions(+), 34 deletions(-) rename gst/dtmf/{gstrtpdtmfcommon.h => gstdtmfcommon.h} (65%) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index 761575d768..d574323637 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -11,7 +11,7 @@ noinst_HEADERS = gstdtmfsrc.h \ gstdtmfdetect.h \ gstrtpdtmfsrc.h \ gstrtpdtmfdepay.h \ - gstrtpdtmfcommon.h \ + gstdtmfcommon.h \ tone_detect.h libgstdtmf_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ diff --git a/gst/dtmf/gstrtpdtmfcommon.h b/gst/dtmf/gstdtmfcommon.h similarity index 65% rename from gst/dtmf/gstrtpdtmfcommon.h rename to gst/dtmf/gstdtmfcommon.h index c1ab82e0a9..aff881b987 100644 --- a/gst/dtmf/gstrtpdtmfcommon.h +++ b/gst/dtmf/gstdtmfcommon.h @@ -2,6 +2,20 @@ #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 16 +#define MIN_EVENT_STRING "0" +#define MAX_EVENT_STRING "16" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif typedef struct { diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index f929bae728..79525b5729 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -122,10 +122,7 @@ #include -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - +#include "gstdtmfcommon.h" #include "gstdtmfsrc.h" @@ -136,12 +133,6 @@ #define DEFAULT_SAMPLE_RATE 8000 #define SAMPLE_SIZE 16 #define CHANNELS 1 -#define MIN_EVENT 0 -#define MAX_EVENT 16 -#define MIN_VOLUME 0 -#define MAX_VOLUME 36 -#define MIN_INTER_DIGIT_INTERVAL 100 -#define MIN_PULSE_DURATION 250 #define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index ccf2b02fb0..603416dd6f 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -81,7 +81,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif #include @@ -90,23 +90,12 @@ #include #include "gstrtpdtmfdepay.h" -#ifndef M_PI -# define M_PI 3.14159265358979323846 /* pi */ -#endif - - #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_EVENT 0 -#define MAX_EVENT 16 -#define MIN_VOLUME 0 -#define MAX_VOLUME 36 -#define MIN_INTER_DIGIT_INTERVAL 100 -#define MIN_PULSE_DURATION 250 #define MIN_DUTY_CYCLE (MIN_INTER_DIGIT_INTERVAL + MIN_PULSE_DURATION) #define MIN_UNIT_TIME 0 diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index 172cb8414f..65d94549fe 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -27,7 +27,7 @@ #include #include -#include "gstrtpdtmfcommon.h" +#include "gstdtmfcommon.h" G_BEGIN_DECLS #define GST_TYPE_RTP_DTMF_DEPAY \ diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ec2c6c6c27..c7e1c1fb2a 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -130,15 +130,6 @@ #define DEFAULT_TIMESTAMP_OFFSET -1 #define DEFAULT_SEQNUM_OFFSET -1 #define DEFAULT_CLOCK_RATE 8000 -#define MIN_EVENT 0 -#define MAX_EVENT 16 -#define MIN_EVENT_STRING "0" -#define MAX_EVENT_STRING "16" -#define MIN_VOLUME 0 -#define MAX_VOLUME 36 - -#define MIN_INTER_DIGIT_INTERVAL 50 /* ms */ -#define MIN_PULSE_DURATION 70 /* ms */ #define DEFAULT_PACKET_REDUNDANCY 1 #define MIN_PACKET_REDUNDANCY 1 diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index b1a483a102..d04c6ecb7c 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -29,7 +29,7 @@ #include #include -#include "gstrtpdtmfcommon.h" +#include "gstdtmfcommon.h" G_BEGIN_DECLS #define GST_TYPE_RTP_DTMF_SRC (gst_rtp_dtmf_src_get_type()) From 94f75d08af0156515acb21aa020d506aa1f2cf03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 11 Jul 2011 21:30:28 -0400 Subject: [PATCH 100/138] rtpdtmfsrc: Just error out if there is no clock --- gst/dtmf/gstrtpdtmfsrc.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index c7e1c1fb2a..6b2f35031a 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -502,29 +502,27 @@ gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, } } -static void +static gboolean gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) { GstClock *clock; clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - if (clock != NULL) { - dtmfsrc->timestamp = gst_clock_get_time (clock) - + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); - dtmfsrc->start_timestamp = dtmfsrc->timestamp; - 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); - } + if (clock == NULL) + return FALSE; + + dtmfsrc->timestamp = gst_clock_get_time (clock) + + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) + - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); + dtmfsrc->start_timestamp = dtmfsrc->timestamp; + gst_object_unref (clock); 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; } @@ -660,7 +658,8 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, dtmfsrc->last_packet = FALSE; /* Set the redundancy on the first packet */ dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; - gst_rtp_dtmf_prepare_timestamps (dtmfsrc); + if (!gst_rtp_dtmf_prepare_timestamps (dtmfsrc)) + goto no_clock; dtmfsrc->payload = event->payload; event->payload = NULL; @@ -727,6 +726,8 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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); @@ -793,6 +794,12 @@ paused: } else { return GST_FLOW_WRONG_STATE; } + +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; } From e7038fd520f33bb59a44695a1e229eccdae10ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 14 Apr 2011 16:49:39 -0400 Subject: [PATCH 101/138] rtpdtmfsrc: Respect ptime from the caps Respect the ptime from the caps for the DTMF packets --- gst/dtmf/gstrtpdtmfsrc.c | 48 ++++++++++++++++++---------------------- gst/dtmf/gstrtpdtmfsrc.h | 2 +- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 6b2f35031a..a063e775a8 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -122,9 +122,7 @@ #include "gstrtpdtmfsrc.h" #define GST_RTP_DTMF_TYPE_EVENT 1 -#define DEFAULT_PACKET_INTERVAL 50 /* ms */ -#define MIN_PACKET_INTERVAL 10 /* ms */ -#define MAX_PACKET_INTERVAL 50 /* ms */ +#define DEFAULT_PTIME 40 /* ms */ #define DEFAULT_SSRC -1 #define DEFAULT_PT 96 #define DEFAULT_TIMESTAMP_OFFSET -1 @@ -155,7 +153,6 @@ enum PROP_CLOCK_RATE, PROP_TIMESTAMP, PROP_SEQNUM, - PROP_INTERVAL, PROP_REDUNDANCY }; @@ -264,11 +261,6 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) 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_INTERVAL, - g_param_spec_uint ("interval", "Interval between rtp packets", - "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL, - MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, - 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", @@ -309,7 +301,7 @@ gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class) object->ts_offset = DEFAULT_TIMESTAMP_OFFSET; object->pt = DEFAULT_PT; object->clock_rate = DEFAULT_CLOCK_RATE; - object->interval = DEFAULT_PACKET_INTERVAL; + object->ptime = DEFAULT_PTIME; object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY; object->event_queue = @@ -448,9 +440,6 @@ gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id, dtmfsrc->pt = g_value_get_uint (value); dtmfsrc->dirty = TRUE; break; - case PROP_INTERVAL: - dtmfsrc->interval = g_value_get_uint (value); - break; case PROP_REDUNDANCY: dtmfsrc->packet_redundancy = g_value_get_uint (value); break; @@ -490,9 +479,6 @@ gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, case PROP_SEQNUM: g_value_set_uint (value, dtmfsrc->seqnum); break; - case PROP_INTERVAL: - g_value_set_uint (value, dtmfsrc->interval); - break; case PROP_REDUNDANCY: g_value_set_uint (value, dtmfsrc->packet_redundancy); break; @@ -537,7 +523,7 @@ gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc * dtmfsrc, gint event_number, 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); - event->payload->duration = dtmfsrc->interval * dtmfsrc->clock_rate / 1000; + event->payload->duration = dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; g_async_queue_push (dtmfsrc->event_queue, event); } @@ -584,7 +570,7 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) if (dtmfsrc->redundancy_count > 1) GST_BUFFER_DURATION (buf) = 0; else - GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND; + GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND; GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); @@ -593,12 +579,6 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) /* copy payload and convert to network-byte order */ g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload)); - /* Force the packet duration to a certain minumum - * if its the end of the event - */ - if (payload->e && - payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000) - payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000; payload->duration = g_htons (payload->duration); @@ -606,8 +586,7 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) /* duration of DTMF payloadfor the NEXT packet */ /* not updated for redundant packets */ if (dtmfsrc->redundancy_count == 0) - dtmfsrc->payload->duration += - dtmfsrc->interval * dtmfsrc->clock_rate / 1000; + dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; } @@ -920,6 +899,23 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) 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); } diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index d04c6ecb7c..61cda5c119 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -90,7 +90,7 @@ struct _GstRTPDTMFSrc guint pt; guint ssrc; guint current_ssrc; - guint16 interval; + guint16 ptime; guint16 packet_redundancy; guint32 clock_rate; From 340a65b484665c4c032da2b2749d6e6bc42eb29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 14 Apr 2011 17:08:57 -0400 Subject: [PATCH 102/138] rtpdtmfsrc: Start at the last_stop from the start event if there was one The goal is to try to not have a GAP between the audio and the DTMF --- gst/dtmf/gstrtpdtmfsrc.c | 36 +++++++++++++++++++++++++++--------- gst/dtmf/gstrtpdtmfsrc.h | 2 ++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index a063e775a8..8d37f3195b 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -334,6 +334,7 @@ gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc * dtmfsrc, gint event_type; gboolean start; gint method; + GstClockTime last_stop; if (!gst_structure_get_int (event_structure, "type", &event_type) || !gst_structure_get_boolean (event_structure, "start", &start) || @@ -346,6 +347,13 @@ gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc * dtmfsrc, } } + 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; + GST_OBJECT_UNLOCK (dtmfsrc); + if (start) { gint event_number; gint event_volume; @@ -491,17 +499,27 @@ gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, static gboolean gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) { - GstClock *clock; + GstClockTime last_stop; - clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - if (clock == NULL) - return FALSE; + GST_OBJECT_LOCK (dtmfsrc); + last_stop = dtmfsrc->last_stop; + GST_OBJECT_UNLOCK (dtmfsrc); - dtmfsrc->timestamp = gst_clock_get_time (clock) - + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); - dtmfsrc->start_timestamp = dtmfsrc->timestamp; - gst_object_unref (clock); + if (GST_CLOCK_TIME_IS_VALID (last_stop)) { + dtmfsrc->timestamp = last_stop; + dtmfsrc->start_timestamp = last_stop; + } else { + GstClock *clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); + + if (clock == NULL) + return FALSE; + + dtmfsrc->timestamp = gst_clock_get_time (clock) + + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) + - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); + dtmfsrc->start_timestamp = dtmfsrc->timestamp; + gst_object_unref (clock); + } dtmfsrc->rtp_timestamp = dtmfsrc->ts_base + gst_util_uint64_scale_int (gst_segment_to_running_time (&GST_BASE_SRC diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 61cda5c119..9be9df69cb 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -94,6 +94,8 @@ struct _GstRTPDTMFSrc guint16 packet_redundancy; guint32 clock_rate; + GstClockTime last_stop; + gboolean dirty; guint16 redundancy_count; }; From 3a5d14993a8e761059b788a9795cf9907c1deb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 11 Jul 2011 20:46:20 -0400 Subject: [PATCH 103/138] rtpdtmfsrc: Put the inter digit interval at the end, not at the start The reason is to let rtpdtmfmux drop buffers during the inter digit interval, this way, there will be more silence around the DTMF tones so IVFs will have a better chance recognizing them. --- gst/dtmf/gstrtpdtmfsrc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 8d37f3195b..19acc6cae6 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -514,8 +514,7 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) if (clock == NULL) return FALSE; - dtmfsrc->timestamp = gst_clock_get_time (clock) - + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) + dtmfsrc->start_timestamp = gst_clock_get_time (clock) - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); dtmfsrc->start_timestamp = dtmfsrc->timestamp; gst_object_unref (clock); @@ -591,7 +590,6 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND; GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; - dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf); @@ -606,6 +604,18 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) if (dtmfsrc->redundancy_count == 0) dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; + if (dtmfsrc->redundancy_count == 0 && 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; + } + + if (GST_CLOCK_TIME_IS_VALID (dtmfsrc->timestamp)) + dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); } static GstBuffer * From a3de27c68baa571e4011cdc343b382866fd8774c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 11 Jul 2011 20:47:23 -0400 Subject: [PATCH 104/138] rtpdtmfsrc: Make sure rtpdtmfsrc timestamps don't overlap --- gst/dtmf/gstrtpdtmfsrc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 19acc6cae6..90e63fc6e1 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -506,7 +506,6 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) GST_OBJECT_UNLOCK (dtmfsrc); if (GST_CLOCK_TIME_IS_VALID (last_stop)) { - dtmfsrc->timestamp = last_stop; dtmfsrc->start_timestamp = last_stop; } else { GstClock *clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); @@ -516,10 +515,15 @@ gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc) dtmfsrc->start_timestamp = gst_clock_get_time (clock) - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); - dtmfsrc->start_timestamp = dtmfsrc->timestamp; 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), @@ -976,6 +980,7 @@ gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc * dtmfsrc) else dtmfsrc->ts_base = dtmfsrc->ts_offset; + dtmfsrc->timestamp = 0; } static GstStateChangeReturn From 0656a861e3445ee887ce326280f4b8012db7dd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 11 Jul 2011 21:31:07 -0400 Subject: [PATCH 105/138] rtpdtmfsrc: Correctly recognize the end of a buffer --- gst/dtmf/gstrtpdtmfsrc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 90e63fc6e1..89e8c00270 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -605,10 +605,11 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) /* duration of DTMF payloadfor the NEXT packet */ /* not updated for redundant packets */ - if (dtmfsrc->redundancy_count == 0) + if (dtmfsrc->redundancy_count <= 1) dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; - if (dtmfsrc->redundancy_count == 0 && dtmfsrc->last_packet) { + + if (dtmfsrc->redundancy_count <= 1 && dtmfsrc->last_packet) { GstClockTime inter_digit_interval = MIN_INTER_DIGIT_INTERVAL; if (inter_digit_interval % dtmfsrc->ptime != 0) From 126efa5e06d1a90f41736b78e746e982bffb980a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 14 Apr 2011 15:46:08 -0400 Subject: [PATCH 106/138] dtmfsrc: Align DTMF sound buffers with last-stop from event Also make sure the timestamps never go backwards --- gst/dtmf/gstdtmfsrc.c | 48 ++++++++++++++++++++++++++++++++++--------- gst/dtmf/gstdtmfsrc.h | 2 ++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 79525b5729..eb55268d70 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -323,6 +323,7 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, gint event_type; gboolean start; gint method; + GstClockTime last_stop; if (!gst_structure_get_int (event_structure, "type", &event_type) || !gst_structure_get_boolean (event_structure, "start", &start) || @@ -335,6 +336,14 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, } } + + 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; + GST_OBJECT_UNLOCK (dtmfsrc); + if (start) { gint event_number; gint event_volume; @@ -447,19 +456,37 @@ gst_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value, static void gst_dtmf_prepare_timestamps (GstDTMFSrc * dtmfsrc) { - GstClock *clock; + GstClockTime last_stop; + GstClockTime timestamp; - clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc)); - if (clock != NULL) { - dtmfsrc->timestamp = gst_clock_get_time (clock) - - gst_element_get_base_time (GST_ELEMENT (dtmfsrc)); - gst_object_unref (clock); + 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 { - 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); + 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 @@ -823,6 +850,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) g_slice_free (GstDTMFSrcEvent, event); event = g_async_queue_try_pop (dtmfsrc->event_queue); } + dtmfsrc->timestamp = 0; no_preroll = TRUE; break; default: diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index aa5d35a611..cda5840a5f 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -81,6 +81,8 @@ struct _GstDTMFSrc gboolean paused; GstClockID clockid; + GstClockTime last_stop; + gint sample_rate; }; From 9a5a8e49daaee129b14090b05d4e61f7c8c4ee27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 12 Jul 2011 19:09:02 -0400 Subject: [PATCH 107/138] dtmf: Max event type is 15 --- gst/dtmf/gstdtmfcommon.h | 4 ++-- gst/dtmf/gstdtmfsrc.c | 2 +- gst/dtmf/gstrtpdtmfsrc.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gst/dtmf/gstdtmfcommon.h b/gst/dtmf/gstdtmfcommon.h index aff881b987..82617d72fd 100644 --- a/gst/dtmf/gstdtmfcommon.h +++ b/gst/dtmf/gstdtmfcommon.h @@ -9,9 +9,9 @@ #define MAX_VOLUME 36 #define MIN_EVENT 0 -#define MAX_EVENT 16 +#define MAX_EVENT 15 #define MIN_EVENT_STRING "0" -#define MAX_EVENT_STRING "16" +#define MAX_EVENT_STRING "15" #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index eb55268d70..a812e98ef0 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -65,7 +65,7 @@ * * number * G_TYPE_INT - * 0-16 + * 0-15 * The event number. * * diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 89e8c00270..875a020661 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -63,7 +63,7 @@ * * number * G_TYPE_INT - * 0-16 + * 0-15 * The event number. * * From 9e521e2b6d1313f06e41fefa81f4bc87efdc6de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 12 Jul 2011 21:48:37 -0400 Subject: [PATCH 108/138] dtmf: Add more debug --- gst/dtmf/gstdtmfsrc.c | 6 ++++++ gst/dtmf/gstrtpdtmfsrc.c | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index a812e98ef0..7492b151e7 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -611,6 +611,12 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, /* 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); /* Set caps on the buffer before pushing it */ diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 875a020661..8f07cafc4a 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -602,13 +602,6 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) payload->duration = g_htons (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 (dtmfsrc->redundancy_count <= 1 && dtmfsrc->last_packet) { GstClockTime inter_digit_interval = MIN_INTER_DIGIT_INTERVAL; @@ -619,8 +612,20 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) 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); + } static GstBuffer * From 479ab0db68fd6a38139d6b089606f8857c8205e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Sat, 29 Oct 2011 18:24:26 +0200 Subject: [PATCH 109/138] dtmf: Post messages when starting to send/receive DTMF This way, the UI can display the DTMF events as they as being sent. --- gst/dtmf/gstdtmfsrc.c | 41 ++++++++++++++++++++++++++++++++ gst/dtmf/gstrtpdtmfsrc.c | 50 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 7492b151e7..1e76b4baba 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -110,6 +110,12 @@ * 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 @@ -625,6 +631,34 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, return buf; } +static void +gst_dtmf_src_post_message (GstDTMFSrc * dtmfsrc, const gchar * message_name, + GstDTMFSrcEvent * event) +{ + GstStructure *s; + + 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; + } + + 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) @@ -650,6 +684,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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); @@ -657,6 +692,8 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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: /* @@ -684,10 +721,12 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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: /* @@ -853,6 +892,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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); } @@ -878,6 +918,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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); } diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 8f07cafc4a..cd6e12c9a7 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -108,7 +108,13 @@ * 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" @@ -644,6 +650,36 @@ gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc) return buf; } + +static void +gst_dtmf_src_post_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; + } + + gst_element_post_message (GST_ELEMENT (dtmfsrc), + gst_message_new_element (GST_OBJECT (dtmfsrc), s)); +} + + static GstFlowReturn gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer) @@ -668,6 +704,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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: @@ -678,6 +715,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, if (!gst_rtp_dtmf_prepare_timestamps (dtmfsrc)) goto no_clock; + gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event); dtmfsrc->payload = event->payload; event->payload = NULL; break; @@ -711,6 +749,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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: @@ -718,6 +757,7 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, dtmfsrc->last_packet = TRUE; /* Set the redundancy on the last packet */ dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; + gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event); break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: @@ -1004,8 +1044,10 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) gst_rtp_dtmf_src_ready_to_paused (dtmfsrc); /* Flushing the event queue */ - while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) + 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); + } no_preroll = TRUE; break; @@ -1025,8 +1067,10 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PAUSED_TO_READY: /* Flushing the event queue */ - while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) + 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); + } /* Indicate that we don't do PRE_ROLL */ break; From 76b1ac09a328e70681e09f8cf4dddc53497393dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 4 Nov 2011 17:54:04 -0400 Subject: [PATCH 110/138] dtmfsrc: Reject start/stop requests that come out of order --- gst/dtmf/gstdtmfsrc.c | 22 +++++++++++++++------- gst/dtmf/gstdtmfsrc.h | 1 + gst/dtmf/gstrtpdtmfsrc.c | 18 +++++++++++++++--- gst/dtmf/gstrtpdtmfsrc.h | 1 + 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 1e76b4baba..6bc46429d8 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -330,6 +330,9 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, 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) || @@ -342,22 +345,25 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, } } + 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) { - gint event_number; - gint event_volume; - - 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_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume); @@ -896,6 +902,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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; @@ -922,6 +929,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) g_slice_free (GstDTMFSrcEvent, event); event = g_async_queue_try_pop (dtmfsrc->event_queue); } + dtmfsrc->last_event_was_start = FALSE; break; default: diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index cda5840a5f..ce69bf4115 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -74,6 +74,7 @@ struct _GstDTMFSrc GstBaseSrc parent; GAsyncQueue *event_queue; GstDTMFSrcEvent *last_event; + gboolean last_event_was_start; guint16 interval; GstClockTime timestamp; diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index cd6e12c9a7..1689dc46a9 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -341,6 +341,9 @@ gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc * dtmfsrc, 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) || @@ -353,17 +356,24 @@ gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc * dtmfsrc, } } + 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 (start) { - gint event_number; - gint event_volume; + 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; @@ -1048,6 +1058,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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; @@ -1071,6 +1082,7 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) 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; diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 9be9df69cb..5bc0e3ea65 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -93,6 +93,7 @@ struct _GstRTPDTMFSrc guint16 ptime; guint16 packet_redundancy; guint32 clock_rate; + gboolean last_event_was_start; GstClockTime last_stop; From dcadfe662118e82a8d83010e47b9b7e952cfbd02 Mon Sep 17 00:00:00 2001 From: Thijs Vermeir Date: Wed, 9 Nov 2011 11:56:07 +0100 Subject: [PATCH 111/138] dtmf: fix compiler warning for uninitialized values --- gst/dtmf/gstdtmfsrc.c | 7 ++++--- gst/dtmf/gstrtpdtmfsrc.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 6bc46429d8..929147fe07 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -641,7 +641,7 @@ static void gst_dtmf_src_post_message (GstDTMFSrc * dtmfsrc, const gchar * message_name, GstDTMFSrcEvent * event) { - GstStructure *s; + GstStructure *s = NULL; switch (event->event_type) { case DTMF_EVENT_TYPE_START: @@ -661,8 +661,9 @@ gst_dtmf_src_post_message (GstDTMFSrc * dtmfsrc, const gchar * message_name, return; } - gst_element_post_message (GST_ELEMENT (dtmfsrc), - gst_message_new_element (GST_OBJECT (dtmfsrc), s)); + if (s) + gst_element_post_message (GST_ELEMENT (dtmfsrc), + gst_message_new_element (GST_OBJECT (dtmfsrc), s)); } static GstFlowReturn diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 1689dc46a9..ee8703563d 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -665,7 +665,7 @@ static void gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name, GstRTPDTMFSrcEvent * event) { - GstStructure *s; + GstStructure *s = NULL; switch (event->event_type) { case RTP_DTMF_EVENT_TYPE_START: @@ -685,8 +685,9 @@ gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name, return; } - gst_element_post_message (GST_ELEMENT (dtmfsrc), - gst_message_new_element (GST_OBJECT (dtmfsrc), s)); + if (s) + gst_element_post_message (GST_ELEMENT (dtmfsrc), + gst_message_new_element (GST_OBJECT (dtmfsrc), s)); } From cf9dee41c33d9a84861f0155d71718c4ac1ac2de Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 28 Nov 2011 13:08:27 +0000 Subject: [PATCH 112/138] various: fix pad template ref leaks https://bugzilla.gnome.org/show_bug.cgi?id=662664 --- gst/dtmf/gstdtmfdetect.c | 6 ++---- gst/dtmf/gstdtmfsrc.c | 4 ++-- gst/dtmf/gstrtpdtmfdepay.c | 8 ++++---- gst/dtmf/gstrtpdtmfsrc.c | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 0bb9242647..7d76aa067c 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -118,10 +118,8 @@ gst_dtmf_detect_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&srctemplate)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sinktemplate)); + gst_element_class_add_static_pad_template (element_class, &srctemplate); + gst_element_class_add_static_pad_template (element_class, &sinktemplate); gst_element_class_set_details_simple (element_class, "DTMF detector element", "Filter/Analyzer/Audio", diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 929147fe07..e3face8494 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -241,8 +241,8 @@ gst_dtmf_src_base_init (gpointer g_class) GST_DEBUG_CATEGORY_INIT (gst_dtmf_src_debug, "dtmfsrc", 0, "dtmfsrc element"); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_dtmf_src_template)); + gst_element_class_add_static_pad_template (element_class, + &gst_dtmf_src_template); gst_element_class_set_details_simple (element_class, "DTMF tone generator", "Source/Audio", diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 603416dd6f..da1ec2f953 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -216,10 +216,10 @@ gst_rtp_dtmf_depay_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_rtp_dtmf_depay_src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_rtp_dtmf_depay_sink_template)); + gst_element_class_add_static_pad_template (element_class, + &gst_rtp_dtmf_depay_src_template); + gst_element_class_add_static_pad_template (element_class, + &gst_rtp_dtmf_depay_sink_template); GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug, diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ee8703563d..605aca45ea 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -208,8 +208,8 @@ gst_rtp_dtmf_src_base_init (gpointer g_class) GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug, "rtpdtmfsrc", 0, "rtpdtmfsrc element"); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); + gst_element_class_add_static_pad_template (element_class, + &gst_rtp_dtmf_src_template); gst_element_class_set_details_simple (element_class, "RTP DTMF packet generator", "Source/Network", From bc44628831f1ca1f72b89f71bbdfd263a0772328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 25 Jan 2012 11:21:50 +0100 Subject: [PATCH 113/138] dtmf: port to 0.11 --- gst/dtmf/gstdtmfdetect.c | 60 ++++++++++----------- gst/dtmf/gstdtmfsrc.c | 78 +++++++++++++--------------- gst/dtmf/gstrtpdtmfdepay.c | 104 +++++++++++++++++++------------------ gst/dtmf/gstrtpdtmfdepay.h | 6 +-- gst/dtmf/gstrtpdtmfsrc.c | 84 ++++++++++++------------------ 5 files changed, 153 insertions(+), 179 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 0bb9242647..5bc98af17a 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -101,50 +101,42 @@ static gboolean gst_dtmf_detect_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps); static GstFlowReturn gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf); -static gboolean gst_dtmf_detect_event (GstBaseTransform * trans, +static gboolean gst_dtmf_detect_sink_event (GstBaseTransform * trans, GstEvent * event); -static void -_do_init (GType type) -{ - GST_DEBUG_CATEGORY_INIT (dtmf_detect_debug, "dtmfdetect", 0, "dtmfdetect"); -} - -GST_BOILERPLATE_FULL (GstDtmfDetect, gst_dtmf_detect, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM, _do_init); - -static void -gst_dtmf_detect_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&srctemplate)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sinktemplate)); - - gst_element_class_set_details_simple (element_class, "DTMF detector element", - "Filter/Analyzer/Audio", - "This element detects DTMF tones", - "Olivier Crete "); -} +G_DEFINE_TYPE (GstDtmfDetect, gst_dtmf_detect, GST_TYPE_BASE_TRANSFORM); static void gst_dtmf_detect_class_init (GstDtmfDetectClass * klass) { + GstElementClass *gstelement_class; GstBaseTransformClass *gstbasetransform_class; + gstelement_class = GST_ELEMENT_CLASS (klass); gstbasetransform_class = (GstBaseTransformClass *) klass; + GST_DEBUG_CATEGORY_INIT (dtmf_detect_debug, "dtmfdetect", 0, "dtmfdetect"); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_metadata (gstelement_class, "DTMF detector element", + "Filter/Analyzer/Audio", + "This element detects DTMF tones", + "Olivier Crete "); + gstbasetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_dtmf_detect_set_caps); gstbasetransform_class->transform_ip = GST_DEBUG_FUNCPTR (gst_dtmf_detect_transform_ip); - gstbasetransform_class->event = GST_DEBUG_FUNCPTR (gst_dtmf_detect_event); + gstbasetransform_class->sink_event = + GST_DEBUG_FUNCPTR (gst_dtmf_detect_sink_event); } static void -gst_dtmf_detect_init (GstDtmfDetect * dtmfdetect, GstDtmfDetectClass * klass) +gst_dtmf_detect_init (GstDtmfDetect * dtmfdetect) { gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (dtmfdetect), TRUE); gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (dtmfdetect), TRUE); @@ -169,14 +161,17 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) gint dtmf_count; gchar dtmfbuf[MAX_DTMF_DIGITS] = ""; gint i; + gpointer data; + gsize size; if (GST_BUFFER_IS_DISCONT (buf)) zap_dtmf_detect_init (&self->dtmf_state); if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) return GST_FLOW_OK; - zap_dtmf_detect (&self->dtmf_state, (gint16 *) GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf) / 2, FALSE); + data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + + zap_dtmf_detect (&self->dtmf_state, (gint16 *) data, size / 2, FALSE); dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS); @@ -185,6 +180,8 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) else GST_LOG_OBJECT (self, "Got no DTMF events"); + gst_buffer_unmap (buf, data, size); + for (i = 0; i < dtmf_count; i++) { GstMessage *dtmf_message = NULL; GstStructure *structure; @@ -258,7 +255,7 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) static gboolean -gst_dtmf_detect_event (GstBaseTransform * trans, GstEvent * event) +gst_dtmf_detect_sink_event (GstBaseTransform * trans, GstEvent * event) { GstDtmfDetect *self = GST_DTMF_DETECT (trans); @@ -270,8 +267,7 @@ gst_dtmf_detect_event (GstBaseTransform * trans, GstEvent * event) break; } - return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_TRANSFORM_CLASS, event, - (trans, event), TRUE); + return GST_BASE_TRANSFORM_GET_CLASS (trans)->sink_event (trans, event); } diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 929147fe07..80583fbc8f 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -211,7 +211,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1") ); -GST_BOILERPLATE (GstDTMFSrc, gst_dtmf_src, GstBaseSrc, GST_TYPE_BASE_SRC); +G_DEFINE_TYPE (GstDTMFSrc, gst_dtmf_src, GST_TYPE_BASE_SRC); static void gst_dtmf_src_finalize (GObject * object); @@ -234,21 +234,6 @@ 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_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - GST_DEBUG_CATEGORY_INIT (gst_dtmf_src_debug, "dtmfsrc", 0, "dtmfsrc element"); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_dtmf_src_template)); - - gst_element_class_set_details_simple (element_class, "DTMF tone generator", - "Source/Audio", - "Generates DTMF tones", - "Youness Alaoui "); -} static void gst_dtmf_src_class_init (GstDTMFSrcClass * klass) @@ -262,6 +247,17 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * 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_details_simple (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; @@ -291,7 +287,7 @@ event_free (GstDTMFSrcEvent * event) } static void -gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass * g_class) +gst_dtmf_src_init (GstDTMFSrc * dtmfsrc) { /* we operate in time */ gst_base_src_set_format (GST_BASE_SRC (dtmfsrc), GST_FORMAT_TIME); @@ -319,7 +315,7 @@ gst_dtmf_src_finalize (GObject * object) dtmfsrc->event_queue = NULL; } - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_dtmf_src_parent_class)->finalize (object); } static gboolean @@ -426,7 +422,8 @@ gst_dtmf_src_send_event (GstElement * element, GstEvent * event) if (gst_dtmf_src_handle_event (GST_BASE_SRC (element), event)) return TRUE; - return GST_ELEMENT_CLASS (parent_class)->send_event (element, event); + return GST_ELEMENT_CLASS (gst_dtmf_src_parent_class)->send_event + (element, event); } static void @@ -528,24 +525,22 @@ gst_dtmf_src_add_stop_event (GstDTMFSrc * dtmfsrc) g_async_queue_push (dtmfsrc->event_queue, event); } -static void -gst_dtmf_src_generate_silence (GstBuffer * buffer, float duration, - gint sample_rate) +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; - GST_BUFFER_SIZE (buffer) = buf_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc0 (buf_size); - GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); + return gst_buffer_new_wrapped (g_malloc0 (buf_size), buf_size); } -static void +static GstBuffer * gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, - float duration, GstBuffer * buffer, gint sample_rate) + float duration, gint sample_rate) { + GstBuffer *buffer; gint16 *p; gint tone_size; double i = 0; @@ -554,11 +549,10 @@ gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, /* Create a buffer for the tone */ tone_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8; - GST_BUFFER_SIZE (buffer) = tone_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc (tone_size); - GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); - p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); + buffer = gst_buffer_new_allocate (NULL, tone_size, 1); + + p = (gint16 *) gst_buffer_map (buffer, NULL, NULL, GST_MAP_READWRITE); volume_factor = pow (10, (-event->volume) / 20); @@ -586,6 +580,10 @@ gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, (event->sample)++; } + + gst_buffer_unmap (buffer, p, tone_size); + + return buffer; } @@ -596,26 +594,22 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, { GstBuffer *buf = NULL; gboolean send_silence = FALSE; - GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc); GST_LOG_OBJECT (dtmfsrc, "Creating buffer for tone %s", DTMF_KEYS[event->event_number].event_name); - /* create buffer to hold the tone */ - buf = gst_buffer_new (); - if (event->packet_count * dtmfsrc->interval < MIN_INTER_DIGIT_INTERVAL) { send_silence = TRUE; } if (send_silence) { GST_LOG_OBJECT (dtmfsrc, "Generating silence"); - gst_dtmf_src_generate_silence (buf, dtmfsrc->interval, + buf = gst_dtmf_src_generate_silence (dtmfsrc->interval, dtmfsrc->sample_rate); } else { GST_LOG_OBJECT (dtmfsrc, "Generating tone"); - gst_dtmf_src_generate_tone (event, DTMF_KEYS[event->event_number], - dtmfsrc->interval, buf, dtmfsrc->sample_rate); + buf = gst_dtmf_src_generate_tone (event, DTMF_KEYS[event->event_number], + dtmfsrc->interval, dtmfsrc->sample_rate); } event->packet_count++; @@ -631,9 +625,6 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc * dtmfsrc, dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); - /* Set caps on the buffer before pushing it */ - gst_buffer_set_caps (buf, GST_PAD_CAPS (srcpad)); - return buf; } @@ -787,7 +778,8 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); - GST_LOG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf)); + GST_LOG_OBJECT (dtmfsrc, "Created buffer of size %d", + gst_buffer_get_size (buf)); *buffer = buf; return GST_FLOW_OK; @@ -912,7 +904,7 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition) } if ((result = - GST_ELEMENT_CLASS (parent_class)->change_state (element, + GST_ELEMENT_CLASS (gst_dtmf_src_parent_class)->change_state (element, transition)) == GST_STATE_CHANGE_FAILURE) goto failure; diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 603416dd6f..9d470f5f9d 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -199,47 +199,40 @@ GST_STATIC_PAD_TEMPLATE ("sink", "encoding-name = (string) \"TELEPHONE-EVENT\"") ); -GST_BOILERPLATE (GstRtpDTMFDepay, gst_rtp_dtmf_depay, GstBaseRTPDepayload, - GST_TYPE_BASE_RTP_DEPAYLOAD); +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 (GstBaseRTPDepayload * depayload, +static GstBuffer *gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf); -gboolean gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, +gboolean gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps); -static void -gst_rtp_dtmf_depay_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_rtp_dtmf_depay_src_template)); - gst_element_class_add_pad_template (element_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_details_simple (element_class, - "RTP DTMF packet depayloader", "Codec/Depayloader/Network", - "Generates DTMF Sound from telephone-event RTP packets", - "Youness Alaoui "); -} - static void gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) { GObjectClass *gobject_class; - GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + GstElementClass *gstelement_class; + GstRTPBaseDepayloadClass *gstrtpbasedepayload_class; - gobject_class = (GObjectClass *) klass; - gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass); - parent_class = g_type_class_peek_parent (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_details_simple (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); @@ -258,16 +251,15 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) "(0 = no limit)", 0, G_MAXUINT, DEFAULT_MAX_DURATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gstbasertpdepayload_class->process = + gstrtpbasedepayload_class->process = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_process); - gstbasertpdepayload_class->set_caps = + gstrtpbasedepayload_class->set_caps = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_depay_setcaps); } static void -gst_rtp_dtmf_depay_init (GstRtpDTMFDepay * rtpdtmfdepay, - GstRtpDTMFDepayClass * klass) +gst_rtp_dtmf_depay_init (GstRtpDTMFDepay * rtpdtmfdepay) { rtpdtmfdepay->unit_time = DEFAULT_UNIT_TIME; } @@ -315,7 +307,7 @@ gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id, } gboolean -gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) +gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps) { GstCaps *srccaps; GstStructure *structure = gst_caps_get_structure (caps, 0); @@ -330,16 +322,17 @@ gst_rtp_dtmf_depay_setcaps (GstBaseRTPDepayload * filter, GstCaps * caps) "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, clock_rate, NULL); - gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (filter), srccaps); + gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter), srccaps); gst_caps_unref (srccaps); return TRUE; } -static void +static GstBuffer * gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, - GstRTPDTMFPayload payload, GstBuffer * buffer) + GstRTPDTMFPayload payload) { + GstBuffer *buf; gint16 *p; gint tone_size; double i = 0; @@ -347,20 +340,18 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, double volume_factor; DTMF_KEY key = DTMF_KEYS[payload.event]; guint32 clock_rate = 8000 /* default */ ; - GstBaseRTPDepayload *depayload = GST_BASE_RTP_DEPAYLOAD (rtpdtmfdepay); + GstRTPBaseDepayload *depayload = GST_RTP_BASE_DEPAYLOAD (rtpdtmfdepay); gint volume; clock_rate = depayload->clock_rate; /* Create a buffer for the tone */ tone_size = (payload.duration * SAMPLE_SIZE * CHANNELS) / 8; - GST_BUFFER_SIZE (buffer) = tone_size; - GST_BUFFER_MALLOCDATA (buffer) = g_malloc (tone_size); - GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); - GST_BUFFER_DURATION (buffer) = payload.duration * GST_SECOND / clock_rate; + buf = gst_buffer_new_allocate (NULL, tone_size, 1); + GST_BUFFER_DURATION (buf) = payload.duration * GST_SECOND / clock_rate; volume = payload.volume; - p = (gint16 *) GST_BUFFER_MALLOCDATA (buffer); + p = (gint16 *) gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); volume_factor = pow (10, (-volume) / 20); @@ -390,11 +381,15 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, (rtpdtmfdepay->sample)++; } + + gst_buffer_unmap (buf, p, tone_size); + + return buf; } static GstBuffer * -gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstRtpDTMFDepay *rtpdtmfdepay = NULL; @@ -406,14 +401,17 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) gboolean marker; GstStructure *structure = NULL; GstMessage *dtmf_message = NULL; + GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; rtpdtmfdepay = GST_RTP_DTMF_DEPAY (depayload); if (!gst_rtp_buffer_validate (buf)) goto bad_packet; - payload_len = gst_rtp_buffer_get_payload_len (buf); - payload = gst_rtp_buffer_get_payload (buf); + 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; @@ -424,9 +422,9 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) goto bad_packet; - marker = gst_rtp_buffer_get_marker (buf); + marker = gst_rtp_buffer_get_marker (&rtpbuffer); - timestamp = gst_rtp_buffer_get_timestamp (buf); + timestamp = gst_rtp_buffer_get_timestamp (&rtpbuffer); dtmf_payload.duration = g_ntohs (dtmf_payload.duration); @@ -467,7 +465,7 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) rtpdtmfdepay->sample = 0; rtpdtmfdepay->previous_ts = timestamp; rtpdtmfdepay->previous_duration = dtmf_payload.duration; - rtpdtmfdepay->first_gst_ts = GST_BUFFER_TIMESTAMP (buf); + rtpdtmfdepay->first_gst_ts = GST_BUFFER_PTS (buf); structure = gst_structure_new ("dtmf-event", "number", G_TYPE_INT, dtmf_payload.event, @@ -503,11 +501,10 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) /* If late or duplicate packet (like the redundant end packet). Ignore */ if (dtmf_payload.duration > 0) { - outbuf = gst_buffer_new (); - gst_dtmf_src_generate_tone (rtpdtmfdepay, dtmf_payload, outbuf); + outbuf = gst_dtmf_src_generate_tone (rtpdtmfdepay, dtmf_payload); - GST_BUFFER_TIMESTAMP (outbuf) = rtpdtmfdepay->first_gst_ts + + GST_BUFFER_PTS (outbuf) = rtpdtmfdepay->first_gst_ts + (rtpdtmfdepay->previous_duration - dtmf_payload.duration) * GST_SECOND / depayload->clock_rate; GST_BUFFER_OFFSET (outbuf) = @@ -522,12 +519,17 @@ gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } - return outbuf; + 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; } diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index 65d94549fe..f5fe6b9847 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include "gstdtmfcommon.h" @@ -46,7 +46,7 @@ typedef struct _GstRtpDTMFDepayClass GstRtpDTMFDepayClass; struct _GstRtpDTMFDepay { /*< private >*/ - GstBaseRTPDepayload depayload; + GstRTPBaseDepayload depayload; double sample; guint32 previous_ts; guint16 previous_duration; @@ -57,7 +57,7 @@ struct _GstRtpDTMFDepay struct _GstRtpDTMFDepayClass { - GstBaseRTPDepayloadClass parent_class; + GstRTPBaseDepayloadClass parent_class; }; GType gst_rtp_dtmf_depay_get_type (void); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ee8703563d..f97261ef6f 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -176,8 +176,7 @@ GST_STATIC_PAD_TEMPLATE ("src", ); -GST_BOILERPLATE (GstRTPDTMFSrc, gst_rtp_dtmf_src, GstBaseSrc, - GST_TYPE_BASE_SRC); +G_DEFINE_TYPE (GstRTPDTMFSrc, gst_rtp_dtmf_src, GST_TYPE_BASE_SRC); static void gst_rtp_dtmf_src_finalize (GObject * object); @@ -200,22 +199,6 @@ static GstFlowReturn gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, static gboolean gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc); -static void -gst_rtp_dtmf_src_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug, - "rtpdtmfsrc", 0, "rtpdtmfsrc element"); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); - - gst_element_class_set_details_simple (element_class, - "RTP DTMF packet generator", "Source/Network", - "Generates RTP DTMF packets", "Zeeshan Ali "); -} - static void gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) { @@ -227,7 +210,15 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) gstbasesrc_class = GST_BASE_SRC_CLASS (klass); gstelement_class = GST_ELEMENT_CLASS (klass); - parent_class = g_type_class_peek_parent (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_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 = @@ -297,7 +288,7 @@ gst_rtp_dtmf_src_event_free (GstRTPDTMFSrcEvent * event) } static void -gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class) +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); @@ -330,7 +321,7 @@ gst_rtp_dtmf_src_finalize (GObject * object) } - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_rtp_dtmf_src_parent_class)->finalize (object); } static gboolean @@ -577,30 +568,37 @@ gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc * dtmfsrc) static void -gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) +gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc * dtmfsrc, + GstRTPBuffer * rtpbuf) { - gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc); - gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt); + 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 (buf, TRUE); + gst_rtp_buffer_set_marker (rtpbuf, TRUE); } else if (dtmfsrc->last_packet) { dtmfsrc->payload->e = 1; } dtmfsrc->seqnum++; - gst_rtp_buffer_set_seq (buf, dtmfsrc->seqnum); + gst_rtp_buffer_set_seq (rtpbuf, dtmfsrc->seqnum); /* timestamp of RTP header */ - gst_rtp_buffer_set_timestamp (buf, dtmfsrc->rtp_timestamp); + gst_rtp_buffer_set_timestamp (rtpbuf, dtmfsrc->rtp_timestamp); } -static void -gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) +static GstBuffer * +gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc) { + GstBuffer *buf; GstRTPDTMFPayload *payload; + GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; - gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, buf); + 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 ... */ @@ -608,10 +606,9 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) GST_BUFFER_DURATION (buf) = 0; else GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND; - GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp; + GST_BUFFER_PTS (buf) = dtmfsrc->timestamp; - - payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf); + payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (&rtpbuffer); /* copy payload and convert to network-byte order */ g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload)); @@ -642,20 +639,7 @@ gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc * dtmfsrc, GstBuffer * buf) if (GST_CLOCK_TIME_IS_VALID (dtmfsrc->timestamp)) dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); -} - -static GstBuffer * -gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc) -{ - GstBuffer *buf = NULL; - - /* create buffer to hold the payload */ - buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0); - - gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, buf); - - /* Set caps on the buffer before pushing it */ - gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (dtmfsrc))); + gst_rtp_buffer_unmap (&rtpbuffer); return buf; } @@ -884,7 +868,7 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT", NULL); /* the peer caps can override some of the defaults */ - peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc)); + 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, @@ -1068,8 +1052,8 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition) } if ((result = - GST_ELEMENT_CLASS (parent_class)->change_state (element, - transition)) == GST_STATE_CHANGE_FAILURE) + GST_ELEMENT_CLASS (gst_rtp_dtmf_src_parent_class)->change_state + (element, transition)) == GST_STATE_CHANGE_FAILURE) goto failure; switch (transition) { From aa0a531c23630cab7a2a16c749cb5ce473594ff2 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 25 Jan 2012 14:50:50 +0100 Subject: [PATCH 114/138] port to new memory API --- gst/dtmf/gstdtmfdetect.c | 9 ++++----- gst/dtmf/gstdtmfsrc.c | 6 ++++-- gst/dtmf/gstrtpdtmfdepay.c | 6 ++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 5bc98af17a..0370285349 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -161,17 +161,16 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) gint dtmf_count; gchar dtmfbuf[MAX_DTMF_DIGITS] = ""; gint i; - gpointer data; - gsize size; + GstMapInfo map; if (GST_BUFFER_IS_DISCONT (buf)) zap_dtmf_detect_init (&self->dtmf_state); if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) return GST_FLOW_OK; - data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + gst_buffer_map (buf, &map, GST_MAP_READ); - zap_dtmf_detect (&self->dtmf_state, (gint16 *) data, size / 2, FALSE); + zap_dtmf_detect (&self->dtmf_state, (gint16 *) map.data, map.size / 2, FALSE); dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS); @@ -180,7 +179,7 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) else GST_LOG_OBJECT (self, "Got no DTMF events"); - gst_buffer_unmap (buf, data, size); + gst_buffer_unmap (buf, &map); for (i = 0; i < dtmf_count; i++) { GstMessage *dtmf_message = NULL; diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 80583fbc8f..d59fa1c9b8 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -541,6 +541,7 @@ 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; @@ -552,7 +553,8 @@ gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, buffer = gst_buffer_new_allocate (NULL, tone_size, 1); - p = (gint16 *) gst_buffer_map (buffer, NULL, NULL, GST_MAP_READWRITE); + gst_buffer_map (buffer, &map, GST_MAP_READWRITE); + p = (gint16 *) map.data; volume_factor = pow (10, (-event->volume) / 20); @@ -581,7 +583,7 @@ gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, (event->sample)++; } - gst_buffer_unmap (buffer, p, tone_size); + gst_buffer_unmap (buffer, &map); return buffer; } diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 9d470f5f9d..01a1698f20 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -333,6 +333,7 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, GstRTPDTMFPayload payload) { GstBuffer *buf; + GstMapInfo map; gint16 *p; gint tone_size; double i = 0; @@ -351,7 +352,8 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, GST_BUFFER_DURATION (buf) = payload.duration * GST_SECOND / clock_rate; volume = payload.volume; - p = (gint16 *) gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); + gst_buffer_map (buf, &map, GST_MAP_WRITE); + p = (gint16 *) map.data; volume_factor = pow (10, (-volume) / 20); @@ -382,7 +384,7 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, (rtpdtmfdepay->sample)++; } - gst_buffer_unmap (buf, p, tone_size); + gst_buffer_unmap (buf, &map); return buf; } From 00b500ceb12b787648ce9a1eb4f09f2f46f29bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 27 Jan 2012 12:07:43 +0100 Subject: [PATCH 115/138] dtmf: Use new-style caps --- gst/dtmf/gstdtmfdetect.c | 24 +++++++++++++----------- gst/dtmf/gstdtmfsrc.c | 10 +++++----- gst/dtmf/gstrtpdtmfdepay.c | 13 ++++++------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 0370285349..073959ec27 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -64,26 +64,27 @@ #include +#include + GST_DEBUG_CATEGORY (dtmf_detect_debug); #define GST_CAT_DEFAULT (dtmf_detect_debug) static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, rate = (int) 8000, channels = (int) 1")); + GST_STATIC_CAPS ("audio/x-raw, " + "format = (string) \"" GST_AUDIO_NE (S16) "\", " + "rate = (int) 8000, " "channels = (int) 1") + ); + static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, rate = (int) 8000, channels = (int) 1")); + GST_STATIC_CAPS ("audio/x-raw, " + "format = (string) \"" GST_AUDIO_NE (S16) "\", " + "rate = (int) 8000, " "channels = (int) 1") + ); /* signals and args */ enum @@ -266,7 +267,8 @@ gst_dtmf_detect_sink_event (GstBaseTransform * trans, GstEvent * event) break; } - return GST_BASE_TRANSFORM_GET_CLASS (trans)->sink_event (trans, event); + return GST_BASE_TRANSFORM_CLASS (gst_dtmf_detect_parent_class)->sink_event + (trans, event); } diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index d59fa1c9b8..c7b4945ede 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -132,6 +132,8 @@ #include "gstdtmfsrc.h" +#include + #define GST_TONE_DTMF_TYPE_EVENT 1 #define DEFAULT_PACKET_INTERVAL 50 /* ms */ #define MIN_PACKET_INTERVAL 10 /* ms */ @@ -204,11 +206,9 @@ static GstStaticPadTemplate gst_dtmf_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (bool) true, rate = (int) [1, MAX], channels = (int) 1") + GST_STATIC_CAPS ("audio/x-raw, " + "format = (string) \"" GST_AUDIO_NE (S16) "\", " + "rate = " GST_AUDIO_RATE_RANGE ", " "channels = (int) 1") ); G_DEFINE_TYPE (GstDTMFSrc, gst_dtmf_src, GST_TYPE_BASE_SRC); diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 01a1698f20..db4d6fb324 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -84,11 +84,13 @@ #include "config.h" #endif +#include "gstrtpdtmfdepay.h" + #include #include +#include #include -#include "gstrtpdtmfdepay.h" #define DEFAULT_PACKET_INTERVAL 50 /* ms */ #define MIN_PACKET_INTERVAL 10 /* ms */ @@ -180,12 +182,9 @@ 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-int, " - "width = (int) 16, " - "depth = (int) 16, " - "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " - "signed = (boolean) true, " - "rate = (int) [0, MAX], " "channels = (int) 1") + 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 = From aad9a2fc5700f16429db68843e5e4922f4e78bf2 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 8 Feb 2012 16:37:13 +0100 Subject: [PATCH 116/138] GST_FLOW_WRONG_STATE -> GST_FLOW_FLUSHING --- gst/dtmf/gstdtmfsrc.c | 2 +- gst/dtmf/gstrtpdtmfsrc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index c7b4945ede..9e3ea47a10 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -798,7 +798,7 @@ paused: dtmfsrc->last_event = NULL; } - return GST_FLOW_WRONG_STATE; + return GST_FLOW_FLUSHING; } diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index f97261ef6f..6e6140af76 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -844,7 +844,7 @@ paused: dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; goto send_last; } else { - return GST_FLOW_WRONG_STATE; + return GST_FLOW_FLUSHING; } no_clock: From b65fe71cbababb75a6e97beafe09021fd0fffdbf Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Thu, 26 Jan 2012 06:58:46 -0500 Subject: [PATCH 117/138] Fix compiler warnings --- gst/dtmf/gstdtmfsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 9e3ea47a10..e5a8eef585 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -780,7 +780,7 @@ gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event); - GST_LOG_OBJECT (dtmfsrc, "Created buffer of size %d", + GST_LOG_OBJECT (dtmfsrc, "Created buffer of size %" G_GSIZE_FORMAT, gst_buffer_get_size (buf)); *buffer = buf; From 124a33dc957d7338e85ead377496e8608739e475 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Sun, 11 Mar 2012 19:06:59 +0100 Subject: [PATCH 118/138] fix for caps api changes --- gst/dtmf/gstdtmfsrc.c | 12 +++++++----- gst/dtmf/gstrtpdtmfsrc.c | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index e5a8eef585..b3f24ffda1 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -852,14 +852,16 @@ gst_dtmf_src_negotiate (GstBaseSrc * basesrc) caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); if (!caps) - caps = - gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD - (basesrc))); + caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (basesrc)); - if (gst_caps_is_empty (caps)) + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); return FALSE; + } - gst_caps_truncate (caps); + 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); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 6e6140af76..a078a111d7 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -904,7 +904,8 @@ gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc) } /* now fixate, start by taking the first caps */ - gst_caps_truncate (temp); + temp = gst_caps_truncate (temp); + temp = gst_caps_make_writable (temp); srccaps = temp; /* get first structure */ From 04a91237f31a5bf6846a5527f30597a7df492ad1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 15 Mar 2012 13:37:36 +0100 Subject: [PATCH 119/138] update for memory api changes --- gst/dtmf/gstdtmfsrc.c | 3 ++- gst/dtmf/gstrtpdtmfdepay.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index b3f24ffda1..60bc8a5e92 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -547,11 +547,12 @@ gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, double i = 0; double amplitude, f1, f2; double volume_factor; + static GstAllocationParams params = { 0, 0, 0, 1, }; /* Create a buffer for the tone */ tone_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8; - buffer = gst_buffer_new_allocate (NULL, tone_size, 1); + buffer = gst_buffer_new_allocate (NULL, tone_size, ¶ms); gst_buffer_map (buffer, &map, GST_MAP_READWRITE); p = (gint16 *) map.data; diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index db4d6fb324..0dda885013 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -342,12 +342,13 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, guint32 clock_rate = 8000 /* default */ ; GstRTPBaseDepayload *depayload = GST_RTP_BASE_DEPAYLOAD (rtpdtmfdepay); gint volume; + static GstAllocationParams params = { 0, 0, 0, 1, }; 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, 1); + buf = gst_buffer_new_allocate (NULL, tone_size, ¶ms); GST_BUFFER_DURATION (buf) = payload.duration * GST_SECOND / clock_rate; volume = payload.volume; From a2ac7554ee0880ec88ca7a09b86c31da089f5f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 4 Apr 2012 14:41:22 +0200 Subject: [PATCH 120/138] gst: Update versioning --- gst/dtmf/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index d574323637..00b648f34a 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -16,7 +16,7 @@ noinst_HEADERS = gstdtmfsrc.h \ libgstdtmf_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ -DEXTERN_BUF -DRTP_SUPPORT -libgstdtmf_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ +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 From 9c8944ca89e40772cd3b1f2fe933f428c688221c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 5 Apr 2012 18:02:56 +0200 Subject: [PATCH 121/138] gst: Update for GST_PLUGIN_DEFINE() API changes --- gst/dtmf/gstdtmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c index 9d5854fc1b..ddd40580d8 100644 --- a/gst/dtmf/gstdtmf.c +++ b/gst/dtmf/gstdtmf.c @@ -29,5 +29,5 @@ plugin_init (GstPlugin * plugin) GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - "dtmf", "DTMF plugins", + dtmf, "DTMF plugins", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) From 945ed74ebebc9a6da7064aafda5afdc301933676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 8 Jul 2012 00:08:55 +0100 Subject: [PATCH 122/138] dtmfsrc: pass unhandled non-custom events to the base class https://bugzilla.gnome.org/show_bug.cgi?id=666626 --- gst/dtmf/gstdtmfsrc.c | 79 +++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 60bc8a5e92..811cc03f31 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -211,6 +211,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "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); @@ -319,9 +320,11 @@ gst_dtmf_src_finalize (GObject * object) } static gboolean -gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, - const GstStructure * event_structure) +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; @@ -330,6 +333,14 @@ gst_dtmf_src_handle_dtmf_event (GstDTMFSrc * dtmfsrc, 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)) @@ -375,29 +386,6 @@ failure: return FALSE; } -static gboolean -gst_dtmf_src_handle_custom_upstream (GstDTMFSrc * dtmfsrc, GstEvent * event) -{ - gboolean result = FALSE; - 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); - if (structure && gst_structure_has_name (structure, "dtmf-event")) - result = gst_dtmf_src_handle_dtmf_event (dtmfsrc, structure); - -ret: - return result; -} - static gboolean gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event) { @@ -406,9 +394,19 @@ gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event) dtmfsrc = GST_DTMF_SRC (src); - GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad"); - if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) { - result = gst_dtmf_src_handle_custom_upstream (dtmfsrc, event); + 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; @@ -418,12 +416,29 @@ gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event) static gboolean gst_dtmf_src_send_event (GstElement * element, GstEvent * event) { + GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (element); + gboolean ret; - if (gst_dtmf_src_handle_event (GST_BASE_SRC (element), event)) - return TRUE; + GST_LOG_OBJECT (dtmfsrc, "Received an %s event via send_event", + GST_EVENT_TYPE_NAME (event)); - return GST_ELEMENT_CLASS (gst_dtmf_src_parent_class)->send_event - (element, 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 From 3371297afc47ded436011cc1fd725dd942074c14 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 17 Jul 2012 16:39:02 +0200 Subject: [PATCH 123/138] update for RTP buffer api changes --- gst/dtmf/gstrtpdtmfdepay.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 0dda885013..1bea465593 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -407,9 +407,6 @@ gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) rtpdtmfdepay = GST_RTP_DTMF_DEPAY (depayload); - if (!gst_rtp_buffer_validate (buf)) - goto bad_packet; - gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuffer); payload_len = gst_rtp_buffer_get_payload_len (&rtpbuffer); @@ -423,7 +420,6 @@ gst_rtp_dtmf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) if (dtmf_payload.event > MAX_EVENT) goto bad_packet; - marker = gst_rtp_buffer_get_marker (&rtpbuffer); timestamp = gst_rtp_buffer_get_timestamp (&rtpbuffer); From 6586e4238413334d618845ac55e7f0970d547e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 8 Aug 2012 17:40:34 +0200 Subject: [PATCH 124/138] gst: Set alignment at the correct place of GstAllocationParams --- gst/dtmf/gstdtmfsrc.c | 2 +- gst/dtmf/gstrtpdtmfdepay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 811cc03f31..2b3310e6f8 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -562,7 +562,7 @@ gst_dtmf_src_generate_tone (GstDTMFSrcEvent * event, DTMF_KEY key, double i = 0; double amplitude, f1, f2; double volume_factor; - static GstAllocationParams params = { 0, 0, 0, 1, }; + static GstAllocationParams params = { 0, 1, 0, 0, }; /* Create a buffer for the tone */ tone_size = ((duration / 1000) * sample_rate * SAMPLE_SIZE * CHANNELS) / 8; diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 1bea465593..6349485375 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -342,7 +342,7 @@ gst_dtmf_src_generate_tone (GstRtpDTMFDepay * rtpdtmfdepay, guint32 clock_rate = 8000 /* default */ ; GstRTPBaseDepayload *depayload = GST_RTP_BASE_DEPAYLOAD (rtpdtmfdepay); gint volume; - static GstAllocationParams params = { 0, 0, 0, 1, }; + static GstAllocationParams params = { 0, 1, 0, 0, }; clock_rate = depayload->clock_rate; From 0380de3f959f094f0a19fa90697f1b630380c7b4 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 14 Sep 2012 17:08:49 +0200 Subject: [PATCH 125/138] replace gst_element_class_set_details_simple with gst_element_class_set_metadata --- gst/dtmf/gstdtmfsrc.c | 2 +- gst/dtmf/gstrtpdtmfdepay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 2b3310e6f8..18c7ebb6aa 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -253,7 +253,7 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_dtmf_src_template)); - gst_element_class_set_details_simple (gstelement_class, "DTMF tone generator", + gst_element_class_set_metadata (gstelement_class, "DTMF tone generator", "Source/Audio", "Generates DTMF tones", "Youness Alaoui "); diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 6349485375..3650de04c1 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -228,7 +228,7 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug, "rtpdtmfdepay", 0, "rtpdtmfdepay element"); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_metadata (gstelement_class, "RTP DTMF packet depayloader", "Codec/Depayloader/Network", "Generates DTMF Sound from telephone-event RTP packets", "Youness Alaoui "); From 0363c1cebf9b4457124d6d6de464c3825aa07046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Sat, 22 Sep 2012 15:00:27 -0400 Subject: [PATCH 126/138] rtpdtmfdepay: Use 1.0-style caps negotiation and audio/x-raw --- gst/dtmf/gstrtpdtmfdepay.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 3650de04c1..12422ecb2a 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -308,19 +308,23 @@ gst_rtp_dtmf_depay_get_property (GObject * object, guint prop_id, gboolean gst_rtp_dtmf_depay_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps) { - GstCaps *srccaps; + 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; - srccaps = gst_caps_new_simple ("audio/x-raw-int", - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, - "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, clock_rate, NULL); + 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); From 488549bb549cc6d2c4334c79c036651a21fbefa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 17 Oct 2012 17:34:26 +0100 Subject: [PATCH 127/138] Use gst_element_class_set_static_metadata() where possible. Avoids some string copies. Also re-indent some stuff. Also some indent fixes here and there. --- gst/dtmf/gstdtmfdetect.c | 4 ++-- gst/dtmf/gstdtmfsrc.c | 5 ++--- gst/dtmf/gstrtpdtmfdepay.c | 2 +- gst/dtmf/gstrtpdtmfsrc.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 073959ec27..827e68d3cf 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -123,8 +123,8 @@ gst_dtmf_detect_class_init (GstDtmfDetectClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sinktemplate)); - gst_element_class_set_metadata (gstelement_class, "DTMF detector element", - "Filter/Analyzer/Audio", + gst_element_class_set_static_metadata (gstelement_class, + "DTMF detector element", "Filter/Analyzer/Audio", "This element detects DTMF tones", "Olivier Crete "); diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index 18c7ebb6aa..df45223ca9 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -253,9 +253,8 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_dtmf_src_template)); - gst_element_class_set_metadata (gstelement_class, "DTMF tone generator", - "Source/Audio", - "Generates DTMF tones", + gst_element_class_set_static_metadata (gstelement_class, + "DTMF tone generator", "Source/Audio", "Generates DTMF tones", "Youness Alaoui "); diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 12422ecb2a..74df649f22 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -228,7 +228,7 @@ gst_rtp_dtmf_depay_class_init (GstRtpDTMFDepayClass * klass) GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_depay_debug, "rtpdtmfdepay", 0, "rtpdtmfdepay element"); - gst_element_class_set_metadata (gstelement_class, + 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 "); diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index a078a111d7..be71ebd4e3 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -216,7 +216,7 @@ gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_rtp_dtmf_src_template)); - gst_element_class_set_metadata (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "RTP DTMF packet generator", "Source/Network", "Generates RTP DTMF packets", "Zeeshan Ali "); From beb3c9c9be2b251fd57335f37f57329cb8b16149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 3 Nov 2012 20:38:00 +0000 Subject: [PATCH 128/138] Fix FSF address https://bugzilla.gnome.org/show_bug.cgi?id=687520 --- gst/dtmf/gstdtmfdetect.c | 4 ++-- gst/dtmf/gstdtmfdetect.h | 4 ++-- gst/dtmf/gstdtmfsrc.c | 4 ++-- gst/dtmf/gstdtmfsrc.h | 4 ++-- gst/dtmf/gstrtpdtmfdepay.c | 4 ++-- gst/dtmf/gstrtpdtmfdepay.h | 4 ++-- gst/dtmf/gstrtpdtmfsrc.c | 4 ++-- gst/dtmf/gstrtpdtmfsrc.h | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 827e68d3cf..6b53a60a33 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -17,8 +17,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. * */ diff --git a/gst/dtmf/gstdtmfdetect.h b/gst/dtmf/gstdtmfdetect.h index 01a090792c..fa42548df2 100644 --- a/gst/dtmf/gstdtmfdetect.h +++ b/gst/dtmf/gstdtmfdetect.h @@ -17,8 +17,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. * */ diff --git a/gst/dtmf/gstdtmfsrc.c b/gst/dtmf/gstdtmfsrc.c index df45223ca9..a77e3ba8b8 100644 --- a/gst/dtmf/gstdtmfsrc.c +++ b/gst/dtmf/gstdtmfsrc.c @@ -21,8 +21,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** diff --git a/gst/dtmf/gstdtmfsrc.h b/gst/dtmf/gstdtmfsrc.h index ce69bf4115..04440bc185 100644 --- a/gst/dtmf/gstdtmfsrc.h +++ b/gst/dtmf/gstdtmfsrc.h @@ -20,8 +20,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifndef __GST_DTMF_SRC_H__ diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index 74df649f22..dc6053cd44 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -16,8 +16,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** * SECTION:element-rtpdtmfdepay diff --git a/gst/dtmf/gstrtpdtmfdepay.h b/gst/dtmf/gstrtpdtmfdepay.h index f5fe6b9847..c5ed189409 100644 --- a/gst/dtmf/gstrtpdtmfdepay.h +++ b/gst/dtmf/gstrtpdtmfdepay.h @@ -16,8 +16,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifndef __GST_RTP_DTMF_DEPAY_H__ diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index be71ebd4e3..ce9b4eb9c5 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -19,8 +19,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** diff --git a/gst/dtmf/gstrtpdtmfsrc.h b/gst/dtmf/gstrtpdtmfsrc.h index 5bc0e3ea65..3e9256ce58 100644 --- a/gst/dtmf/gstrtpdtmfsrc.h +++ b/gst/dtmf/gstrtpdtmfsrc.h @@ -18,8 +18,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifndef __GST_RTP_DTMF_SRC_H__ From c6dea5d09cca67016f9bc8a09e2ef65945c8f8e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 9 Jan 2013 19:59:16 -0500 Subject: [PATCH 129/138] dtmf/spandsp: Move dtmfdetect to use libspandsp Remove our copy of the tone_detect.c file and use the original from libspandsp. Also move the element to the spandsp plugin. --- gst/dtmf/Makefile.am | 11 +- gst/dtmf/gstdtmf.c | 4 - gst/dtmf/gstdtmfdetect.c | 280 ---------------------- gst/dtmf/gstdtmfdetect.h | 71 ------ gst/dtmf/tone_detect.c | 503 --------------------------------------- gst/dtmf/tone_detect.h | 95 -------- 6 files changed, 3 insertions(+), 961 deletions(-) delete mode 100644 gst/dtmf/gstdtmfdetect.c delete mode 100644 gst/dtmf/gstdtmfdetect.h delete mode 100644 gst/dtmf/tone_detect.c delete mode 100644 gst/dtmf/tone_detect.h diff --git a/gst/dtmf/Makefile.am b/gst/dtmf/Makefile.am index 00b648f34a..56eda1669d 100644 --- a/gst/dtmf/Makefile.am +++ b/gst/dtmf/Makefile.am @@ -1,21 +1,16 @@ plugin_LTLIBRARIES = libgstdtmf.la libgstdtmf_la_SOURCES = gstdtmfsrc.c \ - gstdtmfdetect.c \ gstrtpdtmfsrc.c \ gstrtpdtmfdepay.c \ - tone_detect.c \ gstdtmf.c noinst_HEADERS = gstdtmfsrc.h \ - gstdtmfdetect.h \ gstrtpdtmfsrc.h \ gstrtpdtmfdepay.h \ - gstdtmfcommon.h \ - tone_detect.h + gstdtmfcommon.h -libgstdtmf_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ - -DEXTERN_BUF -DRTP_SUPPORT +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) @@ -33,4 +28,4 @@ Android.mk: Makefile.am $(BUILT_SOURCES) -ldl \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ - > $@ \ No newline at end of file + > $@ diff --git a/gst/dtmf/gstdtmf.c b/gst/dtmf/gstdtmf.c index ddd40580d8..7fd5ee84f1 100644 --- a/gst/dtmf/gstdtmf.c +++ b/gst/dtmf/gstdtmf.c @@ -3,7 +3,6 @@ #include "config.h" #endif -#include "gstdtmfdetect.h" #include "gstdtmfsrc.h" #include "gstrtpdtmfsrc.h" #include "gstrtpdtmfdepay.h" @@ -12,9 +11,6 @@ static gboolean plugin_init (GstPlugin * plugin) { - if (!gst_dtmf_detect_plugin_init (plugin)) - return FALSE; - if (!gst_dtmf_src_plugin_init (plugin)) return FALSE; diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c deleted file mode 100644 index 6b53a60a33..0000000000 --- a/gst/dtmf/gstdtmfdetect.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * GStreamer - DTMF Detection - * - * Copyright 2009 Nokia Corporation - * Copyright 2009 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. - * - */ - -/** - * SECTION:element-dtmfdetect - * @short_description: Detects DTMF tones - * - * This element will detect DTMF tones and emit messages. - * - * The message is called "dtmf-event" and has - * the following fields: - * - * - * - * gint type (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 - * specfied by their number. This element can only take events as input. - * Do not confuse with "method" which specified the output. - * - * - * - * - * gint number (0-16): - * The event number. - * - * - * - * - * gint method (2): - * This field will always been 2 (ie sound) from this element. - * - * - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstdtmfdetect.h" - -#include - -#include - -GST_DEBUG_CATEGORY (dtmf_detect_debug); -#define GST_CAT_DEFAULT (dtmf_detect_debug) - -static GstStaticPadTemplate sinktemplate = 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) 8000, " "channels = (int) 1") - ); - - -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw, " - "format = (string) \"" GST_AUDIO_NE (S16) "\", " - "rate = (int) 8000, " "channels = (int) 1") - ); - -/* signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, -}; - -static gboolean gst_dtmf_detect_set_caps (GstBaseTransform * trans, - GstCaps * incaps, GstCaps * outcaps); -static GstFlowReturn gst_dtmf_detect_transform_ip (GstBaseTransform * trans, - GstBuffer * buf); -static gboolean gst_dtmf_detect_sink_event (GstBaseTransform * trans, - GstEvent * event); - -G_DEFINE_TYPE (GstDtmfDetect, gst_dtmf_detect, GST_TYPE_BASE_TRANSFORM); - -static void -gst_dtmf_detect_class_init (GstDtmfDetectClass * klass) -{ - GstElementClass *gstelement_class; - GstBaseTransformClass *gstbasetransform_class; - - gstelement_class = GST_ELEMENT_CLASS (klass); - gstbasetransform_class = (GstBaseTransformClass *) klass; - - GST_DEBUG_CATEGORY_INIT (dtmf_detect_debug, "dtmfdetect", 0, "dtmfdetect"); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&srctemplate)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sinktemplate)); - - gst_element_class_set_static_metadata (gstelement_class, - "DTMF detector element", "Filter/Analyzer/Audio", - "This element detects DTMF tones", - "Olivier Crete "); - - gstbasetransform_class->set_caps = - GST_DEBUG_FUNCPTR (gst_dtmf_detect_set_caps); - gstbasetransform_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_dtmf_detect_transform_ip); - gstbasetransform_class->sink_event = - GST_DEBUG_FUNCPTR (gst_dtmf_detect_sink_event); -} - -static void -gst_dtmf_detect_init (GstDtmfDetect * dtmfdetect) -{ - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (dtmfdetect), TRUE); - gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (dtmfdetect), TRUE); -} - -static gboolean -gst_dtmf_detect_set_caps (GstBaseTransform * trans, GstCaps * incaps, - GstCaps * outcaps) -{ - GstDtmfDetect *self = GST_DTMF_DETECT (trans); - - zap_dtmf_detect_init (&self->dtmf_state); - - return TRUE; -} - - -static GstFlowReturn -gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) -{ - GstDtmfDetect *self = GST_DTMF_DETECT (trans); - gint dtmf_count; - gchar dtmfbuf[MAX_DTMF_DIGITS] = ""; - gint i; - GstMapInfo map; - - if (GST_BUFFER_IS_DISCONT (buf)) - zap_dtmf_detect_init (&self->dtmf_state); - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) - return GST_FLOW_OK; - - gst_buffer_map (buf, &map, GST_MAP_READ); - - zap_dtmf_detect (&self->dtmf_state, (gint16 *) map.data, map.size / 2, FALSE); - - dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS); - - if (dtmf_count) - GST_DEBUG_OBJECT (self, "Got %d DTMF events: %s", dtmf_count, dtmfbuf); - else - GST_LOG_OBJECT (self, "Got no DTMF events"); - - gst_buffer_unmap (buf, &map); - - for (i = 0; i < dtmf_count; i++) { - GstMessage *dtmf_message = NULL; - GstStructure *structure; - gint dtmf_payload_event; - - GST_DEBUG_OBJECT (self, "Got DTMF event %c", dtmfbuf[i]); - - switch (dtmfbuf[i]) { - case '0': - dtmf_payload_event = 0; - break; - case '1': - dtmf_payload_event = 1; - break; - case '2': - dtmf_payload_event = 2; - break; - case '3': - dtmf_payload_event = 3; - break; - case '4': - dtmf_payload_event = 4; - break; - case '5': - dtmf_payload_event = 5; - break; - case '6': - dtmf_payload_event = 6; - break; - case '7': - dtmf_payload_event = 7; - break; - case '8': - dtmf_payload_event = 8; - break; - case '9': - dtmf_payload_event = 9; - break; - case '*': - dtmf_payload_event = 10; - break; - case '#': - dtmf_payload_event = 11; - break; - case 'A': - dtmf_payload_event = 12; - break; - case 'B': - dtmf_payload_event = 13; - break; - case 'C': - dtmf_payload_event = 14; - break; - case 'D': - dtmf_payload_event = 15; - break; - default: - continue; - } - - structure = gst_structure_new ("dtmf-event", - "type", G_TYPE_INT, 1, - "number", G_TYPE_INT, dtmf_payload_event, - "method", G_TYPE_INT, 2, NULL); - dtmf_message = gst_message_new_element (GST_OBJECT (self), structure); - gst_element_post_message (GST_ELEMENT (self), dtmf_message); - } - - return GST_FLOW_OK; -} - - -static gboolean -gst_dtmf_detect_sink_event (GstBaseTransform * trans, GstEvent * event) -{ - GstDtmfDetect *self = GST_DTMF_DETECT (trans); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - zap_dtmf_detect_init (&self->dtmf_state); - break; - default: - break; - } - - return GST_BASE_TRANSFORM_CLASS (gst_dtmf_detect_parent_class)->sink_event - (trans, event); -} - - -gboolean -gst_dtmf_detect_plugin_init (GstPlugin * plugin) -{ - return gst_element_register (plugin, "dtmfdetect", - GST_RANK_MARGINAL, GST_TYPE_DTMF_DETECT); -} diff --git a/gst/dtmf/gstdtmfdetect.h b/gst/dtmf/gstdtmfdetect.h deleted file mode 100644 index fa42548df2..0000000000 --- a/gst/dtmf/gstdtmfdetect.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * GStreamer - DTMF Detection - * - * Copyright 2009 Nokia Corporation - * Copyright 2009 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. - * - */ - -#ifndef __GST_DTMF_DETECT_H__ -#define __GST_DTMF_DETECT_H__ - -#include -#include - -#include "tone_detect.h" - -G_BEGIN_DECLS - -/* #define's don't like whitespacey bits */ -#define GST_TYPE_DTMF_DETECT \ - (gst_dtmf_detect_get_type()) -#define GST_DTMF_DETECT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - GST_TYPE_DTMF_DETECT,GstDtmfDetect)) -#define GST_DTMF_DETECT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - GST_TYPE_DTMF_DETECT,GstDtmfDetectClass)) -#define GST_IS_DTMF_DETECT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DTMF_DETECT)) -#define GST_IS_DTMF_DETECT_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DTMF_DETECT)) - -typedef struct _GstDtmfDetect GstDtmfDetect; -typedef struct _GstDtmfDetectClass GstDtmfDetectClass; -typedef struct _GstDtmfDetectPrivate GstDtmfDetectPrivate; - -struct _GstDtmfDetect -{ - GstBaseTransform parent; - - dtmf_detect_state_t dtmf_state; -}; - -struct _GstDtmfDetectClass -{ - GstBaseTransformClass parent_class; -}; - -GType gst_dtmf_detect_get_type (void); - -gboolean gst_dtmf_detect_plugin_init (GstPlugin *plugin); - -G_END_DECLS - -#endif /* __GST_DTMF_DETECT_H__ */ diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c deleted file mode 100644 index 73a73ee98b..0000000000 --- a/gst/dtmf/tone_detect.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * DTMF Receiver module, part of: - * BSD Telephony Of Mexico "Zapata" Telecom Library, version 1.10 12/9/01 - * - * Part of the "Zapata" Computer Telephony Technology. - * - * See http://www.bsdtelephony.com.mx - * - * - * The technologies, software, hardware, designs, drawings, scheumatics, board - * layouts and/or artwork, concepts, methodologies (including the use of all - * of these, and that which is derived from the use of all of these), all other - * intellectual properties contained herein, and all intellectual property - * rights have been and shall continue to be expressly for the benefit of all - * mankind, and are perpetually placed in the public domain, and may be used, - * copied, and/or modified by anyone, in any manner, for any legal purpose, - * without restriction. - * - * This module written by Stephen Underwood. - */ - -/* - tone_detect.c - General telephony tone detection, and specific - detection of DTMF. - - Copyright (C) 2001 Steve Underwood - - Despite my general liking of the GPL, I place this code in the - public domain for the benefit of all mankind - even the slimy - ones who might try to proprietize my work and use it to my - detriment. -*/ - -#include -#include -#include -#include -#include -#include "tone_detect.h" - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -//#define USE_3DNOW - -/* Basic DTMF specs: - * - * Minimum tone on = 40ms - * Minimum tone off = 50ms - * Maximum digit rate = 10 per second - * Normal twist <= 8dB accepted - * Reverse twist <= 4dB accepted - * S/N >= 15dB will detect OK - * Attenuation <= 26dB will detect OK - * Frequency tolerance +- 1.5% will detect, +-3.5% will reject - */ - -#define SAMPLE_RATE 8000.0 - -#define DTMF_THRESHOLD 8.0e7 -#define FAX_THRESHOLD 8.0e7 -#define FAX_2ND_HARMONIC 2.0 /* 4dB */ -#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ -#define DTMF_REVERSE_TWIST ((isradio) ? 4.0 : 2.5) /* 4dB normal */ -#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ -#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ -#define DTMF_2ND_HARMONIC_ROW ((isradio) ? 1.7 : 2.5) /* 4dB normal */ -#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ - -static tone_detection_descriptor_t dtmf_detect_row[4]; -static tone_detection_descriptor_t dtmf_detect_col[4]; -static tone_detection_descriptor_t dtmf_detect_row_2nd[4]; -static tone_detection_descriptor_t dtmf_detect_col_2nd[4]; -static tone_detection_descriptor_t fax_detect; -static tone_detection_descriptor_t fax_detect_2nd; - -static float dtmf_row[] = { - 697.0, 770.0, 852.0, 941.0 -}; - -static float dtmf_col[] = { - 1209.0, 1336.0, 1477.0, 1633.0 -}; - -static float fax_freq = 1100.0; - -static char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; - -static void -goertzel_init (goertzel_state_t * s, tone_detection_descriptor_t * t) -{ - s->v2 = s->v3 = 0.0; - s->fac = t->fac; -} - -/*- End of function --------------------------------------------------------*/ - -#if defined(USE_3DNOW) -static inline void -_dtmf_goertzel_update (goertzel_state_t * s, float x[], int samples) -{ - int n; - float v; - int i; - float vv[16]; - - vv[4] = s[0].v2; - vv[5] = s[1].v2; - vv[6] = s[2].v2; - vv[7] = s[3].v2; - vv[8] = s[0].v3; - vv[9] = s[1].v3; - vv[10] = s[2].v3; - vv[11] = s[3].v3; - vv[12] = s[0].fac; - vv[13] = s[1].fac; - vv[14] = s[2].fac; - vv[15] = s[3].fac; - - //v1 = s->v2; - //s->v2 = s->v3; - //s->v3 = s->fac*s->v2 - v1 + x[0]; - - __asm__ __volatile__ (" femms;\n" - " movq 16(%%edx),%%mm2;\n" - " movq 24(%%edx),%%mm3;\n" - " movq 32(%%edx),%%mm4;\n" - " movq 40(%%edx),%%mm5;\n" - " movq 48(%%edx),%%mm6;\n" - " movq 56(%%edx),%%mm7;\n" - " jmp 1f;\n" - " .align 32;\n" - " 1: ;\n" - " prefetch (%%eax);\n" - " movq %%mm3,%%mm1;\n" - " movq %%mm2,%%mm0;\n" - " movq %%mm5,%%mm3;\n" - " movq %%mm4,%%mm2;\n" - " pfmul %%mm7,%%mm5;\n" - " pfmul %%mm6,%%mm4;\n" - " pfsub %%mm1,%%mm5;\n" - " pfsub %%mm0,%%mm4;\n" - " movq (%%eax),%%mm0;\n" - " movq %%mm0,%%mm1;\n" - " punpckldq %%mm0,%%mm1;\n" - " add $4,%%eax;\n" - " pfadd %%mm1,%%mm5;\n" - " pfadd %%mm1,%%mm4;\n" - " dec %%ecx;\n" - " jnz 1b;\n" - " movq %%mm2,16(%%edx);\n" - " movq %%mm3,24(%%edx);\n" - " movq %%mm4,32(%%edx);\n" - " movq %%mm5,40(%%edx);\n" - " femms;\n"::"c" (samples), "a" (x), "d" (vv) - :"memory", "eax", "ecx"); - - s[0].v2 = vv[4]; - s[1].v2 = vv[5]; - s[2].v2 = vv[6]; - s[3].v2 = vv[7]; - s[0].v3 = vv[8]; - s[1].v3 = vv[9]; - s[2].v3 = vv[10]; - s[3].v3 = vv[11]; -} -#endif -/*- End of function --------------------------------------------------------*/ - -void -zap_goertzel_update (goertzel_state_t * s, int16_t x[], int samples) -{ - int i; - float v1; - - for (i = 0; i < samples; i++) { - v1 = s->v2; - s->v2 = s->v3; - s->v3 = s->fac * s->v2 - v1 + x[i]; - } -} - -/*- End of function --------------------------------------------------------*/ - -float -zap_goertzel_result (goertzel_state_t * s) -{ - return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac; -} - -/*- End of function --------------------------------------------------------*/ - -void -zap_dtmf_detect_init (dtmf_detect_state_t * s) -{ - int i; - float theta; - - s->hit1 = s->hit2 = 0; - - for (i = 0; i < 4; i++) { - theta = 2.0 * G_PI * (dtmf_row[i] / SAMPLE_RATE); - dtmf_detect_row[i].fac = 2.0 * cos (theta); - - theta = 2.0 * G_PI * (dtmf_col[i] / SAMPLE_RATE); - dtmf_detect_col[i].fac = 2.0 * cos (theta); - - theta = 2.0 * G_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); - dtmf_detect_row_2nd[i].fac = 2.0 * cos (theta); - - theta = 2.0 * G_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); - dtmf_detect_col_2nd[i].fac = 2.0 * cos (theta); - - goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); - - s->energy = 0.0; - } - - /* Same for the fax dector */ - theta = 2.0 * G_PI * (fax_freq / SAMPLE_RATE); - fax_detect.fac = 2.0 * cos (theta); - goertzel_init (&s->fax_tone, &fax_detect); - - /* Same for the fax dector 2nd harmonic */ - theta = 2.0 * G_PI * (fax_freq * 2.0 / SAMPLE_RATE); - fax_detect_2nd.fac = 2.0 * cos (theta); - goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); - - s->current_sample = 0; - s->detected_digits = 0; - s->lost_digits = 0; - s->digits[0] = '\0'; - s->mhit = 0; -} - -/*- End of function --------------------------------------------------------*/ - -int -zap_dtmf_detect (dtmf_detect_state_t * s, - int16_t amp[], int samples, int isradio) -{ - - float row_energy[4]; - float col_energy[4]; - float fax_energy; - float fax_energy_2nd; - float famp; - float v1; - int i; - int j; - int sample; - int best_row; - int best_col; - int hit; - int limit; - - hit = 0; - for (sample = 0; sample < samples; sample = limit) { - /* 102 is optimised to meet the DTMF specs. */ - if ((samples - sample) >= (102 - s->current_sample)) - limit = sample + (102 - s->current_sample); - else - limit = samples; -#if defined(USE_3DNOW) - _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); - _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); - _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); - _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); - /* XXX Need to fax detect for 3dnow too XXX */ -#warning "Fax Support Broken" -#else - /* The following unrolled loop takes only 35% (rough estimate) of the - time of a rolled loop on the machine on which it was developed */ - for (j = sample; j < limit; j++) { - famp = amp[j]; - - s->energy += famp * famp; - - /* With GCC 2.95, the following unrolled code seems to take about 35% - (rough estimate) as long as a neat little 0-3 loop */ - v1 = s->row_out[0].v2; - s->row_out[0].v2 = s->row_out[0].v3; - s->row_out[0].v3 = s->row_out[0].fac * s->row_out[0].v2 - v1 + famp; - - v1 = s->col_out[0].v2; - s->col_out[0].v2 = s->col_out[0].v3; - s->col_out[0].v3 = s->col_out[0].fac * s->col_out[0].v2 - v1 + famp; - - v1 = s->row_out[1].v2; - s->row_out[1].v2 = s->row_out[1].v3; - s->row_out[1].v3 = s->row_out[1].fac * s->row_out[1].v2 - v1 + famp; - - v1 = s->col_out[1].v2; - s->col_out[1].v2 = s->col_out[1].v3; - s->col_out[1].v3 = s->col_out[1].fac * s->col_out[1].v2 - v1 + famp; - - v1 = s->row_out[2].v2; - s->row_out[2].v2 = s->row_out[2].v3; - s->row_out[2].v3 = s->row_out[2].fac * s->row_out[2].v2 - v1 + famp; - - v1 = s->col_out[2].v2; - s->col_out[2].v2 = s->col_out[2].v3; - s->col_out[2].v3 = s->col_out[2].fac * s->col_out[2].v2 - v1 + famp; - - v1 = s->row_out[3].v2; - s->row_out[3].v2 = s->row_out[3].v3; - s->row_out[3].v3 = s->row_out[3].fac * s->row_out[3].v2 - v1 + famp; - - v1 = s->col_out[3].v2; - s->col_out[3].v2 = s->col_out[3].v3; - s->col_out[3].v3 = s->col_out[3].fac * s->col_out[3].v2 - v1 + famp; - - v1 = s->col_out2nd[0].v2; - s->col_out2nd[0].v2 = s->col_out2nd[0].v3; - s->col_out2nd[0].v3 = - s->col_out2nd[0].fac * s->col_out2nd[0].v2 - v1 + famp; - - v1 = s->row_out2nd[0].v2; - s->row_out2nd[0].v2 = s->row_out2nd[0].v3; - s->row_out2nd[0].v3 = - s->row_out2nd[0].fac * s->row_out2nd[0].v2 - v1 + famp; - - v1 = s->col_out2nd[1].v2; - s->col_out2nd[1].v2 = s->col_out2nd[1].v3; - s->col_out2nd[1].v3 = - s->col_out2nd[1].fac * s->col_out2nd[1].v2 - v1 + famp; - - v1 = s->row_out2nd[1].v2; - s->row_out2nd[1].v2 = s->row_out2nd[1].v3; - s->row_out2nd[1].v3 = - s->row_out2nd[1].fac * s->row_out2nd[1].v2 - v1 + famp; - - v1 = s->col_out2nd[2].v2; - s->col_out2nd[2].v2 = s->col_out2nd[2].v3; - s->col_out2nd[2].v3 = - s->col_out2nd[2].fac * s->col_out2nd[2].v2 - v1 + famp; - - v1 = s->row_out2nd[2].v2; - s->row_out2nd[2].v2 = s->row_out2nd[2].v3; - s->row_out2nd[2].v3 = - s->row_out2nd[2].fac * s->row_out2nd[2].v2 - v1 + famp; - - v1 = s->col_out2nd[3].v2; - s->col_out2nd[3].v2 = s->col_out2nd[3].v3; - s->col_out2nd[3].v3 = - s->col_out2nd[3].fac * s->col_out2nd[3].v2 - v1 + famp; - - v1 = s->row_out2nd[3].v2; - s->row_out2nd[3].v2 = s->row_out2nd[3].v3; - s->row_out2nd[3].v3 = - s->row_out2nd[3].fac * s->row_out2nd[3].v2 - v1 + famp; - - /* Update fax tone */ - v1 = s->fax_tone.v2; - s->fax_tone.v2 = s->fax_tone.v3; - s->fax_tone.v3 = s->fax_tone.fac * s->fax_tone.v2 - v1 + famp; - - v1 = s->fax_tone.v2; - s->fax_tone2nd.v2 = s->fax_tone2nd.v3; - s->fax_tone2nd.v3 = s->fax_tone2nd.fac * s->fax_tone2nd.v2 - v1 + famp; - } -#endif - s->current_sample += (limit - sample); - if (s->current_sample < 102) - continue; - - /* Detect the fax energy, too */ - fax_energy = zap_goertzel_result (&s->fax_tone); - - /* We are at the end of a DTMF detection block */ - /* Find the peak row and the peak column */ - row_energy[0] = zap_goertzel_result (&s->row_out[0]); - col_energy[0] = zap_goertzel_result (&s->col_out[0]); - - for (best_row = best_col = 0, i = 1; i < 4; i++) { - row_energy[i] = zap_goertzel_result (&s->row_out[i]); - if (row_energy[i] > row_energy[best_row]) - best_row = i; - col_energy[i] = zap_goertzel_result (&s->col_out[i]); - if (col_energy[i] > col_energy[best_col]) - best_col = i; - } - hit = 0; - /* Basic signal level test and the twist test */ - if (row_energy[best_row] >= DTMF_THRESHOLD - && - col_energy[best_col] >= DTMF_THRESHOLD - && - col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST - && col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) { - /* Relative peak test */ - for (i = 0; i < 4; i++) { - if ((i != best_col - && col_energy[i] * DTMF_RELATIVE_PEAK_COL > - col_energy[best_col]) - || (i != best_row - && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > - row_energy[best_row])) { - break; - } - } - /* ... and second harmonic test */ - if (i >= 4 - && - (row_energy[best_row] + col_energy[best_col]) > 42.0 * s->energy - && - zap_goertzel_result (&s->col_out2nd[best_col]) * - DTMF_2ND_HARMONIC_COL < col_energy[best_col] - && zap_goertzel_result (&s->row_out2nd[best_row]) * - DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { - hit = dtmf_positions[(best_row << 2) + best_col]; - /* Look for two successive similar results */ - /* The logic in the next test is: - We need two successive identical clean detects, with - something different preceeding it. This can work with - back to back differing digits. More importantly, it - can work with nasty phones that give a very wobbly start - to a digit. */ - if (hit == s->hit3 && s->hit3 != s->hit2) { - s->mhit = hit; - s->digit_hits[(best_row << 2) + best_col]++; - s->detected_digits++; - if (s->current_digits < MAX_DTMF_DIGITS) { - s->digits[s->current_digits++] = hit; - s->digits[s->current_digits] = '\0'; - } else { - s->lost_digits++; - } - } - } - } - if (!hit && (fax_energy >= FAX_THRESHOLD) - && (fax_energy > s->energy * 21.0)) { - fax_energy_2nd = zap_goertzel_result (&s->fax_tone2nd); - if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) { -#if 0 - printf ("Fax energy/Second Harmonic: %f/%f\n", fax_energy, - fax_energy_2nd); -#endif - /* XXX Probably need better checking than just this the energy XXX */ - hit = 'f'; - s->fax_hits++; - } /* Don't reset fax hits counter */ - } else { - if (s->fax_hits > 5) { - s->mhit = 'f'; - s->detected_digits++; - if (s->current_digits < MAX_DTMF_DIGITS) { - s->digits[s->current_digits++] = hit; - s->digits[s->current_digits] = '\0'; - } else { - s->lost_digits++; - } - } - s->fax_hits = 0; - } - s->hit1 = s->hit2; - s->hit2 = s->hit3; - s->hit3 = hit; - /* Reinitialise the detector for the next block */ - for (i = 0; i < 4; i++) { - goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); - } - goertzel_init (&s->fax_tone, &fax_detect); - goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); - s->energy = 0.0; - s->current_sample = 0; - } - if ((!s->mhit) || (s->mhit != hit)) { - s->mhit = 0; - return (0); - } - return (hit); -} - -/*- End of function --------------------------------------------------------*/ - -int -zap_dtmf_get (dtmf_detect_state_t * s, char *buf, int max) -{ - if (max > s->current_digits) - max = s->current_digits; - if (max > 0) { - memcpy (buf, s->digits, max); - memmove (s->digits, s->digits + max, s->current_digits - max); - s->current_digits -= max; - } - buf[max] = '\0'; - return max; -} - -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ diff --git a/gst/dtmf/tone_detect.h b/gst/dtmf/tone_detect.h deleted file mode 100644 index ce6dddd2cb..0000000000 --- a/gst/dtmf/tone_detect.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Header file for DTMF Receiver module, part of: - * BSD Telephony Of Mexico "Zapata" Telecom Library, version 1.10 12/9/01 - * - * Part of the "Zapata" Computer Telephony Technology. - * - * See http://www.bsdtelephony.com.mx - * - * - * The technologies, software, hardware, designs, drawings, scheumatics, board - * layouts and/or artwork, concepts, methodologies (including the use of all - * of these, and that which is derived from the use of all of these), all other - * intellectual properties contained herein, and all intellectual property - * rights have been and shall continue to be expressly for the benefit of all - * mankind, and are perpetually placed in the public domain, and may be used, - * copied, and/or modified by anyone, in any manner, for any legal purpose, - * without restriction. - * - * This module written by Stephen Underwood. - */ -/* - tone_detect.h - General telephony tone detection, and specific - detection of DTMF. - - Copyright (C) 2001 Steve Underwood - - Despite my general liking of the GPL, I place this code in the - public domain for the benefit of all mankind - even the slimy - ones who might try to proprietize my work and use it to my - detriment. -*/ - -#ifndef __TONE_DETECT_H__ -#define __TONE_DETECT_H__ - -#include "_stdint.h" - -#include - -typedef struct -{ - float v2; - float v3; - float fac; -} goertzel_state_t; - -#define MAX_DTMF_DIGITS 128 - -typedef struct -{ - int hit1; - int hit2; - int hit3; - int hit4; - int mhit; - - goertzel_state_t row_out[4]; - goertzel_state_t col_out[4]; - goertzel_state_t row_out2nd[4]; - goertzel_state_t col_out2nd[4]; - goertzel_state_t fax_tone; - goertzel_state_t fax_tone2nd; - float energy; - - int current_sample; - char digits[MAX_DTMF_DIGITS + 1]; - int current_digits; - int detected_digits; - int lost_digits; - int digit_hits[16]; - int fax_hits; -} dtmf_detect_state_t; - -typedef struct -{ - float fac; -} tone_detection_descriptor_t; - -void zap_goertzel_update(goertzel_state_t *s, - gint16 x[], - int samples); -float zap_goertzel_result (goertzel_state_t *s); - -void zap_dtmf_detect_init (dtmf_detect_state_t *s); -int zap_dtmf_detect (dtmf_detect_state_t *s, - gint16 amp[], - int samples, - int isradio); -int zap_dtmf_get (dtmf_detect_state_t *s, - char *buf, - int max); - -#endif /* __TONE_DETECT_H__ */ - -/*- End of file ------------------------------------------------------------*/ From 90497aa3cdcc9b4988f425282c9168cf5a7cf51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 25 Jan 2013 20:37:09 -0500 Subject: [PATCH 130/138] rtpdtmfsrc: remove "ssrc" from caps ssrc is uint and we don't have a uint range type --- gst/dtmf/gstrtpdtmfsrc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ce9b4eb9c5..5c166e7d32 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -170,7 +170,6 @@ GST_STATIC_PAD_TEMPLATE ("src", "media = (string) \"audio\", " "payload = (int) [ 96, 127 ], " "clock-rate = (int) [ 0, MAX ], " - "ssrc = (int) [ 0, MAX ], " "encoding-name = (string) \"TELEPHONE-EVENT\"") /* "events = (string) \"0-15\" */ ); From 0d316b4f43c56d68ba40b9afd3299372d2d12e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 25 Jan 2013 20:37:53 -0500 Subject: [PATCH 131/138] rtpdtmfsrc: Only set the duration when starting to send The duration depends on the clock rate, which could change due to renegotiation --- gst/dtmf/gstrtpdtmfsrc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 5c166e7d32..ccba67f644 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -550,7 +550,6 @@ gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc * dtmfsrc, gint event_number, 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); - event->payload->duration = dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; g_async_queue_push (dtmfsrc->event_queue, event); } @@ -711,6 +710,8 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event); dtmfsrc->payload = event->payload; + dtmfsrc->payload->duration = + dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; event->payload = NULL; break; From 92f9a9d9ff557a886f463fa0a1f7923955ad6fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 25 Jan 2013 20:39:33 -0500 Subject: [PATCH 132/138] rtpdtmfsrc: Post the messages after the clock wait This way, the messages will be closer in time to when the packets are sent out --- gst/dtmf/gstrtpdtmfsrc.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index ccba67f644..834ec480e4 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -642,12 +642,11 @@ gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc) return buf; } - -static void -gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name, - GstRTPDTMFSrcEvent * event) +static GstMessage * +gst_dtmf_src_prepare_message (GstRTPDTMFSrc * dtmfsrc, + const gchar * message_name, GstRTPDTMFSrcEvent * event) { - GstStructure *s = NULL; + GstStructure *s; switch (event->event_type) { case RTP_DTMF_EVENT_TYPE_START: @@ -664,12 +663,21 @@ gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name, "start", G_TYPE_BOOLEAN, FALSE, NULL); break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: - return; + return NULL; } - if (s) - gst_element_post_message (GST_ELEMENT (dtmfsrc), - gst_message_new_element (GST_OBJECT (dtmfsrc), s)); + 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); } @@ -682,6 +690,8 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, GstClock *clock; GstClockID *clockid; GstClockReturn clockret; + GstMessage *message; + GQueue messages = G_QUEUE_INIT; dtmfsrc = GST_RTP_DTMF_SRC (basesrc); @@ -708,7 +718,9 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, if (!gst_rtp_dtmf_prepare_timestamps (dtmfsrc)) goto no_clock; - gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event); + 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; @@ -752,7 +764,9 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, dtmfsrc->last_packet = TRUE; /* Set the redundancy on the last packet */ dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy; - gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event); + g_queue_push_tail (&messages, + gst_dtmf_src_prepare_message (dtmfsrc, "dtmf-event-processed", + event)); break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: @@ -801,6 +815,9 @@ gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset, 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; } From 6105510a7a9ab4116a687bf874b4df0ee9e2400a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 24 Jan 2013 21:00:08 -0500 Subject: [PATCH 133/138] tests: Add test for rtpdtmfdepay and rtpdtmfsrc --- tests/check/elements/dtmf.c | 477 ++++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 tests/check/elements/dtmf.c diff --git a/tests/check/elements/dtmf.c b/tests/check/elements/dtmf.c new file mode 100644 index 0000000000..aeaf1b8dd0 --- /dev/null +++ b/tests/check/elements/dtmf.c @@ -0,0 +1,477 @@ +/* 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); + } + + 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 *rtpdtmfsrc; +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); +} + +static void +setup_rtpdtmfsrc (void) +{ + testclock = gst_test_clock_new (); + bus = gst_bus_new (); + + rtpdtmfsrc = gst_check_setup_element ("rtpdtmfsrc"); + sink = gst_check_setup_sink_pad (rtpdtmfsrc, &rtp_dtmf_sink_template); + gst_element_set_bus (rtpdtmfsrc, bus); + fail_unless (gst_element_set_clock (rtpdtmfsrc, testclock)); + + gst_pad_set_active (sink, TRUE); + fail_unless (gst_element_set_state (rtpdtmfsrc, GST_STATE_PLAYING) == + GST_STATE_CHANGE_SUCCESS); +} + +static void +teardown_rtpdtmfsrc (void) +{ + gst_object_unref (testclock); + gst_pad_set_active (sink, FALSE); + gst_element_set_bus (rtpdtmfsrc, NULL); + gst_object_unref (bus); + gst_check_teardown_sink_pad (rtpdtmfsrc); + gst_check_teardown_element (rtpdtmfsrc); +} + +GST_START_TEST (test_rtpdtmfsrc_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, 1, "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, 1, "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, 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, s)) == FALSE); + + /* Missing type */ + s = gst_structure_new ("dtmf-event", + "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, 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, 1, "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 (rtpdtmfsrc, 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)))); + 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 (rtpdtmfsrc, 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_rtpdtmfsrc); + tcase_add_test (tc, test_rtpdtmfsrc_invalid_events); + tcase_add_test (tc, test_rtpdtmfsrc_min_duration); + suite_add_tcase (s, tc); + + return s; +} + + +GST_CHECK_MAIN (dtmf); From db5c3f404840f0980bbddef9d22b92359af255de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 25 Jan 2013 21:06:05 -0500 Subject: [PATCH 134/138] rtpdtmfdepay: Fix missing work in doc --- gst/dtmf/gstrtpdtmfdepay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dtmf/gstrtpdtmfdepay.c b/gst/dtmf/gstrtpdtmfdepay.c index dc6053cd44..d66f24a24d 100644 --- a/gst/dtmf/gstrtpdtmfdepay.c +++ b/gst/dtmf/gstrtpdtmfdepay.c @@ -43,7 +43,7 @@ * * * - * + * type * G_TYPE_INT * 0-1 * Which of the two methods From 47fccbe6357d3240485d7bdfb13787762bee19d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 26 Jan 2013 22:58:29 +0000 Subject: [PATCH 135/138] rtpdtmfsrc: fix compiler warning gstrtpdtmfsrc.c: In function 'gst_dtmf_src_prepare_message.isra.1': gstrtpdtmfsrc.c:669:3: error: 's' may be used uninitialized in this function --- gst/dtmf/gstrtpdtmfsrc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/dtmf/gstrtpdtmfsrc.c b/gst/dtmf/gstrtpdtmfsrc.c index 834ec480e4..2a0b4a3bb4 100644 --- a/gst/dtmf/gstrtpdtmfsrc.c +++ b/gst/dtmf/gstrtpdtmfsrc.c @@ -664,6 +664,8 @@ gst_dtmf_src_prepare_message (GstRTPDTMFSrc * dtmfsrc, break; case RTP_DTMF_EVENT_TYPE_PAUSE_TASK: return NULL; + default: + return NULL; } return gst_message_new_element (GST_OBJECT (dtmfsrc), s); From 0233eb9f79a643addbbdb43d4cb8114c3bb27205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 27 Feb 2013 16:15:27 -0500 Subject: [PATCH 136/138] tests: Fix ref leak in dtmf test --- tests/check/elements/dtmf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/check/elements/dtmf.c b/tests/check/elements/dtmf.c index aeaf1b8dd0..6330a3d99b 100644 --- a/tests/check/elements/dtmf.c +++ b/tests/check/elements/dtmf.c @@ -119,6 +119,7 @@ check_buffers_duration (GstClockTime expected_duration) fail_unless (GST_BUFFER_DURATION_IS_VALID (buf)); duration += GST_BUFFER_DURATION (buf); + gst_buffer_unref (buf); } fail_unless (duration == expected_duration); From ab2a342f426cbae1f5d9d4c04a2f0040f1fa0968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 27 Feb 2013 18:56:50 -0500 Subject: [PATCH 137/138] tests: Add tests for dtmfsrc --- tests/check/elements/dtmf.c | 150 +++++++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 20 deletions(-) diff --git a/tests/check/elements/dtmf.c b/tests/check/elements/dtmf.c index 6330a3d99b..46b681ed50 100644 --- a/tests/check/elements/dtmf.c +++ b/tests/check/elements/dtmf.c @@ -239,7 +239,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", "maxptime = (uint) 20, encoding-name = (string) \"TELEPHONE-EVENT\"") ); -GstElement *rtpdtmfsrc; +GstElement *dtmfsrc; GstPad *sink; GstClock *testclock; GstBus *bus; @@ -302,61 +302,64 @@ check_rtp_buffer (GstClockTime ts, GstClockTime duration, gboolean start, gst_buffer_unref (buffer); } +gint method; + static void setup_rtpdtmfsrc (void) { testclock = gst_test_clock_new (); bus = gst_bus_new (); - rtpdtmfsrc = gst_check_setup_element ("rtpdtmfsrc"); - sink = gst_check_setup_sink_pad (rtpdtmfsrc, &rtp_dtmf_sink_template); - gst_element_set_bus (rtpdtmfsrc, bus); - fail_unless (gst_element_set_clock (rtpdtmfsrc, testclock)); + 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 (rtpdtmfsrc, GST_STATE_PLAYING) == + fail_unless (gst_element_set_state (dtmfsrc, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); } static void -teardown_rtpdtmfsrc (void) +teardown_dtmfsrc (void) { gst_object_unref (testclock); gst_pad_set_active (sink, FALSE); - gst_element_set_bus (rtpdtmfsrc, NULL); + gst_element_set_bus (dtmfsrc, NULL); gst_object_unref (bus); - gst_check_teardown_sink_pad (rtpdtmfsrc); - gst_check_teardown_element (rtpdtmfsrc); + gst_check_teardown_sink_pad (dtmfsrc); + gst_check_teardown_element (dtmfsrc); } -GST_START_TEST (test_rtpdtmfsrc_invalid_events) +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, 1, "volume", G_TYPE_INT, 8, NULL); + "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, 1, "start", G_TYPE_BOOLEAN, TRUE, NULL); + "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, 1, + "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, 1, + "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); @@ -364,12 +367,12 @@ GST_START_TEST (test_rtpdtmfsrc_invalid_events) /* Stop before start */ 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, + "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 (rtpdtmfsrc, GST_STATE_NULL); + gst_element_set_state (dtmfsrc, GST_STATE_NULL); } GST_END_TEST; @@ -390,6 +393,7 @@ GST_START_TEST (test_rtpdtmfsrc_min_duration) 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)); @@ -448,7 +452,107 @@ GST_START_TEST (test_rtpdtmfsrc_min_duration) gst_caps_unref (caps); gst_caps_unref (expected_caps); - gst_element_set_state (rtpdtmfsrc, GST_STATE_NULL); + 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); } @@ -466,11 +570,17 @@ dtmf_suite (void) suite_add_tcase (s, tc); tc = tcase_create ("rtpdtmfsrc"); - tcase_add_checked_fixture (tc, setup_rtpdtmfsrc, teardown_rtpdtmfsrc); - tcase_add_test (tc, test_rtpdtmfsrc_invalid_events); + 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; } From fba30e3384c277a07c5ec514ed061468332379c0 Mon Sep 17 00:00:00 2001 From: Jonas Holmberg Date: Thu, 28 Feb 2013 13:25:06 +0100 Subject: [PATCH 138/138] tests: use relative include for out-of-tree builds in dtmf test --- tests/check/elements/dtmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/check/elements/dtmf.c b/tests/check/elements/dtmf.c index 46b681ed50..454a3209ed 100644 --- a/tests/check/elements/dtmf.c +++ b/tests/check/elements/dtmf.c @@ -33,7 +33,7 @@ /* Include this from the plugin to get the defines */ -#include "gst/dtmf/gstdtmfcommon.h" +#include "../../gst/dtmf/gstdtmfcommon.h" #define END_BIT (1<<7)