[asterisk-commits] oej: branch oej/rana-dtmf-duration-1.8 r363327 - in /team/oej/rana-dtmf-durat...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Apr 24 09:19:31 CDT 2012


Author: oej
Date: Tue Apr 24 09:19:25 2012
New Revision: 363327

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=363327
Log:
It compiles, which is a good start

Added:
    team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration   (with props)
Modified:
    team/oej/rana-dtmf-duration-1.8/apps/app_senddtmf.c
    team/oej/rana-dtmf-duration-1.8/channels/chan_iax2.c
    team/oej/rana-dtmf-duration-1.8/channels/chan_local.c
    team/oej/rana-dtmf-duration-1.8/channels/chan_mgcp.c
    team/oej/rana-dtmf-duration-1.8/channels/chan_sip.c
    team/oej/rana-dtmf-duration-1.8/funcs/func_frame_trace.c
    team/oej/rana-dtmf-duration-1.8/include/asterisk/channel.h
    team/oej/rana-dtmf-duration-1.8/include/asterisk/frame.h
    team/oej/rana-dtmf-duration-1.8/include/asterisk/rtp_engine.h
    team/oej/rana-dtmf-duration-1.8/main/channel.c
    team/oej/rana-dtmf-duration-1.8/main/features.c
    team/oej/rana-dtmf-duration-1.8/main/frame.c
    team/oej/rana-dtmf-duration-1.8/main/rtp_engine.c
    team/oej/rana-dtmf-duration-1.8/res/res_rtp_asterisk.c

Added: team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration?view=auto&rev=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration (added)
+++ team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration Tue Apr 24 09:19:25 2012
@@ -1,0 +1,43 @@
+EDVINA AB
+Olle E. Johansson
+
+
+This branch is trying to focus on DTMF in the RTP channel. Asterisk 1.4 and later
+doesn't send the proper DTMF duration on the outbound call leg. If we receive
+a DTMF with a duration of 480 samples, we might end up sending 1440 samples out.
+
+Another issue is the delayed transmission when using the core bridge with features
+enabled. If you send a three second DTMF inbound, the outbound begins after the inbound
+ends, so you get a six second interruption to the call.
+
+A third issue is that if we get a new DTMF while we're still transmitting the old,
+we immediately jump to the new one without finishing the old DTMF tone. 
+
+Fixes
+=====
+
+In order to handle this a lot of bugs was fixed. We also added a new control
+frame to update the outbound channel with the latest duration from the inbound,
+in order to try to prevent the outbound channel to run ahead of the inbound.
+If the outbound channel gets these frames, it will stop adding to the outbound
+DTMF, but retransmit previous message instead.
+
+The outbound channel sends a packet for every incoming RTP packet. As usual,
+the inbound and outbond channels are not synchronized at all. So the outbound
+always clocks dtmf in 160 samples /20 ms, something which will break wideband
+codecs. (another fix required for that).
+
+With this code, the outbound channel sends outbound DTMF for the duration of
+the inbound dtmf tone, a bit adjusted to match 160 samples per outbound
+transmission. We do not break outbound DTMF when we receive inbound
+DTMF end, we continue until we have reached the duration of the DTMF that
+we received on the inbound channel.
+
+By adding a ast_feature_check function to main/features.c we now check 
+the DTMF on the incoming DTMF_BEGIN. If it's not a feature code it's 
+immediately forwarded to the outbound channel. If it's a feature code,
+it's dropped and the feature channel waits for DTMF_END (like now).
+This dramatically changes DTMF behaviour in a PBX bridged call.
+
+
+This work was sponsored by IPvision AS, Denmark

Propchange: team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/oej/rana-dtmf-duration-1.8/README.rana-dtmf-rtp-duration
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/oej/rana-dtmf-duration-1.8/apps/app_senddtmf.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/apps/app_senddtmf.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/apps/app_senddtmf.c (original)
+++ team/oej/rana-dtmf-duration-1.8/apps/app_senddtmf.c Tue Apr 24 09:19:25 2012
@@ -78,6 +78,9 @@
 			<parameter name="Digit" required="true">
 				<para>The DTMF digit to play.</para>
 			</parameter>
+			<parameter name="Duration" required="false">
+				<para>The duration in ms for the digit to play.</para>
+			</parameter>
 		</syntax>
 		<description>
 			<para>Plays a dtmf digit on the specified channel.</para>
@@ -134,7 +137,9 @@
 {
 	const char *channel = astman_get_header(m, "Channel");
 	const char *digit = astman_get_header(m, "Digit");
+	const char *duration = astman_get_header(m, "Duration");
 	struct ast_channel *chan;
+	int dtmfduration = 0;
 
 	if (!(chan = ast_channel_get_by_name(channel))) {
 		astman_send_error(s, m, "Channel not found");
@@ -146,8 +151,11 @@
 		chan = ast_channel_unref(chan);
 		return 0;
 	}
+	if (!ast_strlen_zero(duration)) {
+		dtmfduration = atoi(duration);
+	}
 
-	ast_senddigit(chan, *digit, 0);
+	ast_senddigit(chan, *digit, dtmfduration);
 
 	chan = ast_channel_unref(chan);
 

Modified: team/oej/rana-dtmf-duration-1.8/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/channels/chan_iax2.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/channels/chan_iax2.c (original)
+++ team/oej/rana-dtmf-duration-1.8/channels/chan_iax2.c Tue Apr 24 09:19:25 2012
@@ -1170,6 +1170,7 @@
 static int iax2_call(struct ast_channel *c, char *dest, int timeout);
 static int iax2_devicestate(void *data);
 static int iax2_digit_begin(struct ast_channel *c, char digit);
+static int iax2_digit_continue(struct ast_channel *c, char digit, unsigned int duration);
 static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration);
 static int iax2_do_register(struct iax2_registry *reg);
 static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
@@ -1221,6 +1222,7 @@
 	.requester = iax2_request,
 	.devicestate = iax2_devicestate,
 	.send_digit_begin = iax2_digit_begin,
+	.send_digit_continue = iax2_digit_continue,
 	.send_digit_end = iax2_digit_end,
 	.send_text = iax2_sendtext,
 	.send_image = iax2_sendimage,
@@ -4285,6 +4287,11 @@
 static int iax2_digit_begin(struct ast_channel *c, char digit)
 {
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
+}
+
+static int iax2_digit_continue(struct ast_channel *c, char digit, unsigned int duration)
+{
+	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_CONTINUE, digit, 0, NULL, 0, -1);
 }
 
 static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration)

Modified: team/oej/rana-dtmf-duration-1.8/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/channels/chan_local.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/channels/chan_local.c (original)
+++ team/oej/rana-dtmf-duration-1.8/channels/chan_local.c Tue Apr 24 09:19:25 2012
@@ -94,6 +94,7 @@
 
 static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
 static int local_digit_begin(struct ast_channel *ast, char digit);
+static int local_digit_continue(struct ast_channel *ast, char digit, unsigned int duration);
 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int local_call(struct ast_channel *ast, char *dest, int timeout);
 static int local_hangup(struct ast_channel *ast);
@@ -116,6 +117,7 @@
 	.capabilities = -1,
 	.requester = local_request,
 	.send_digit_begin = local_digit_begin,
+	.send_digit_continue = local_digit_continue,
 	.send_digit_end = local_digit_end,
 	.call = local_call,
 	.hangup = local_hangup,
@@ -734,6 +736,29 @@
 	return res;
 }
 
+static int local_digit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+	struct local_pvt *p = ast->tech_pvt;
+	int res = -1;
+	struct ast_frame f = { AST_FRAME_DTMF_CONTINUE, };
+	int isoutbound;
+
+	if (!p) {
+		return -1;
+	}
+
+	ao2_ref(p, 1); /* ref for local_queue_frame */
+	ao2_lock(p);
+	isoutbound = IS_OUTBOUND(ast, p);
+	f.subclass.integer = digit;
+	f.len = duration;
+	res = local_queue_frame(p, isoutbound, &f, ast, 0);
+	ao2_unlock(p);
+	ao2_ref(p, -1);
+
+	return res;
+}
+
 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct local_pvt *p = ast->tech_pvt;

Modified: team/oej/rana-dtmf-duration-1.8/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/channels/chan_mgcp.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/channels/chan_mgcp.c (original)
+++ team/oej/rana-dtmf-duration-1.8/channels/chan_mgcp.c Tue Apr 24 09:19:25 2012
@@ -450,6 +450,7 @@
 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
+static int mgcp_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration);
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int mgcp_devicestate(void *data);
 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone);
@@ -475,6 +476,7 @@
 	.indicate = mgcp_indicate,
 	.fixup = mgcp_fixup,
 	.send_digit_begin = mgcp_senddigit_begin,
+	.send_digit_continue = mgcp_senddigit_continue,
 	.send_digit_end = mgcp_senddigit_end,
 	.bridge = ast_rtp_instance_bridge,
 	.func_channel_read = acf_channel_read,
@@ -1317,6 +1319,21 @@
 	return res;
 }
 
+static int mgcp_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+	struct mgcp_subchannel *sub = ast->tech_pvt;
+	struct mgcp_endpoint *p = sub->parent;
+
+	ast_mutex_lock(&sub->lock);
+
+	if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+		ast_debug(4, "DTMF continue using RFC2833\n");
+		ast_rtp_senddigit_continue(sub->rtp, digit, duration);
+	}
+	ast_mutex_unlock(&sub->lock);
+
+	return 0;
+}
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct mgcp_subchannel *sub = ast->tech_pvt;

Modified: team/oej/rana-dtmf-duration-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/channels/chan_sip.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/channels/chan_sip.c (original)
+++ team/oej/rana-dtmf-duration-1.8/channels/chan_sip.c Tue Apr 24 09:19:25 2012
@@ -1224,6 +1224,7 @@
 static int sip_transfer(struct ast_channel *ast, const char *dest);
 static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int sip_senddigit_begin(struct ast_channel *ast, char digit);
+static int sip_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration);
 static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int sip_setoption(struct ast_channel *chan, int option, void *data, int datalen);
 static int sip_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
@@ -1612,6 +1613,7 @@
 	.transfer = sip_transfer,		/* called with chan locked */
 	.fixup = sip_fixup,			/* called with chan locked */
 	.send_digit_begin = sip_senddigit_begin,	/* called with chan unlocked */
+	.send_digit_continue = sip_senddigit_continue,	/* called with chan unlocked */
 	.send_digit_end = sip_senddigit_end,
 	.bridge = ast_rtp_instance_bridge,			/* XXX chan unlocked ? */
 	.early_bridge = ast_rtp_instance_early_bridge,
@@ -6652,6 +6654,27 @@
 	return res;
 }
 
+/*! \brief Update DTMF character on SIP channel
+	within one call, we're able to transmit in many methods simultaneously */
+static int sip_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+	struct sip_pvt *p = ast->tech_pvt;
+	int res = 0;
+
+	ast_log(LOG_DEBUG, " DTMF CONTINUE HERE!!! \n");
+
+	sip_pvt_lock(p);
+	switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
+	case SIP_DTMF_RFC2833:
+		if (p->rtp) {
+			ast_rtp_senddigit_continue(p->rtp, digit, duration);
+		}
+		break;
+	}
+	sip_pvt_unlock(p);
+
+	return res;
+}
 /*! \brief Send DTMF character on SIP channel
 	within one call, we're able to transmit in many methods simultaneously */
 static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)

Modified: team/oej/rana-dtmf-duration-1.8/funcs/func_frame_trace.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/funcs/func_frame_trace.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/funcs/func_frame_trace.c (original)
+++ team/oej/rana-dtmf-duration-1.8/funcs/func_frame_trace.c Tue Apr 24 09:19:25 2012
@@ -54,6 +54,7 @@
 				<para>Below are the different types of frames that can be filtered.</para>
 				<enumlist>
 					<enum name = "DTMF_BEGIN" />
+					<enum name = "DTMF_CONTINUE" />
 					<enum name = "DTMF_END" />
 					<enum name = "VOICE" />
 					<enum name = "VIDEO" />
@@ -83,6 +84,7 @@
 	const char *str;
 } frametype2str[] = {
 	{ AST_FRAME_DTMF_BEGIN,   "DTMF_BEGIN" },
+	{ AST_FRAME_DTMF_CONTINUE,   "DTMF_CONTINUE" },
 	{ AST_FRAME_DTMF_END,   "DTMF_END" },
 	{ AST_FRAME_VOICE,   "VOICE" },
 	{ AST_FRAME_VIDEO,   "VIDEO" },
@@ -353,6 +355,10 @@
 		ast_verbose("FrameType: DTMF BEGIN\n");
 		ast_verbose("Digit: %d\n", frame->subclass.integer);
 		break;
+	case AST_FRAME_DTMF_CONTINUE:
+		ast_verbose("FrameType: DTMF CONTINUE\n");
+		ast_verbose("Digit: %d\n", frame->subclass.integer);
+		break;
 	}
 
 	ast_verbose("Src: %s\n", ast_strlen_zero(frame->src) ? "NOT PRESENT" : frame->src);

Modified: team/oej/rana-dtmf-duration-1.8/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/include/asterisk/channel.h?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/include/asterisk/channel.h (original)
+++ team/oej/rana-dtmf-duration-1.8/include/asterisk/channel.h Tue Apr 24 09:19:25 2012
@@ -526,6 +526,13 @@
 	 * \note The channel is not locked when this function gets called.
 	 */
 	int (* const send_digit_begin)(struct ast_channel *chan, char digit);
+
+	/*! 
+	 * \brief Continue sending a literal DTMF digit 
+	 *
+	 * \note The channel is not locked when this function gets called. 
+	 */
+	int (* const send_digit_continue)(struct ast_channel *chan, char digit, unsigned int duration);
 
 	/*!
 	 * \brief Stop sending a literal DTMF digit
@@ -1851,6 +1858,15 @@
  */
 int ast_senddigit_begin(struct ast_channel *chan, char digit);
 
+/*! \brief Continue to send a DTMF digit to a channel
+ * used on RTP bridges mainly (to get the duration correct)
+ * Send a DTMF digit to a channel.
+ * \param chan channel to act upon
+ * \param digit the DTMF digit to send, encoded in ASCII
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_senddigit_continue(struct ast_channel *chan, char digit, unsigned int duration);
+
 /*!
  * \brief Send a DTMF digit to a channel.
  * \param chan channel to act upon

Modified: team/oej/rana-dtmf-duration-1.8/include/asterisk/frame.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/include/asterisk/frame.h?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/include/asterisk/frame.h (original)
+++ team/oej/rana-dtmf-duration-1.8/include/asterisk/frame.h Tue Apr 24 09:19:25 2012
@@ -124,6 +124,8 @@
 	AST_FRAME_MODEM,	
 	/*! DTMF begin event, subclass is the digit */
 	AST_FRAME_DTMF_BEGIN,
+	/*! DTMF continue event, subclass is the digit */
+	AST_FRAME_DTMF_CONTINUE,
 };
 #define AST_FRAME_DTMF AST_FRAME_DTMF_END
 

Modified: team/oej/rana-dtmf-duration-1.8/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/include/asterisk/rtp_engine.h?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/include/asterisk/rtp_engine.h (original)
+++ team/oej/rana-dtmf-duration-1.8/include/asterisk/rtp_engine.h Tue Apr 24 09:19:25 2012
@@ -322,6 +322,8 @@
 	void (*stop)(struct ast_rtp_instance *instance);
 	/*! Callback for starting RFC2833 DTMF transmission */
 	int (*dtmf_begin)(struct ast_rtp_instance *instance, char digit);
+	/*! Callback for continuing RFC2833 DTMF transmission */
+	int (*dtmf_continue)(struct ast_rtp_instance *instance, char digit, unsigned int duration);
 	/*! Callback for stopping RFC2833 DTMF transmission */
 	int (*dtmf_end)(struct ast_rtp_instance *instance, char digit);
 	int (*dtmf_end_with_duration)(struct ast_rtp_instance *instance, char digit, unsigned int duration);
@@ -1190,6 +1192,28 @@
 int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit);
 
 /*!
+ * \brief Continue sending a DTMF digit
+ *
+ * \param instance The RTP instance to send the DTMF on
+ * \param digit What DTMF digit to send
+ * \param duration Current duration of the DTMF
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * Example usage:
+ *
+ * \code
+ * ast_rtp_instance_dtmf_continue(instance, '1', 142857);
+ * \endcode
+ *
+ * This starts continues the DTMF '1' on the RTP instance pointed to by instance.
+ *
+ * \since 11
+ */
+int ast_rtp_instance_dtmf_continue(struct ast_rtp_instance *instance, char digit, unsigned int duration);
+
+/*!
  * \brief Stop sending a DTMF digit
  *
  * \param instance The RTP instance to stop the DTMF on

Modified: team/oej/rana-dtmf-duration-1.8/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/main/channel.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/main/channel.c (original)
+++ team/oej/rana-dtmf-duration-1.8/main/channel.c Tue Apr 24 09:19:25 2012
@@ -1790,6 +1790,7 @@
 		return 1;
 
 	case AST_FRAME_DTMF_END:
+	case AST_FRAME_DTMF_CONTINUE:
 	case AST_FRAME_DTMF_BEGIN:
 	case AST_FRAME_VOICE:
 	case AST_FRAME_VIDEO:
@@ -2992,6 +2993,7 @@
 				case AST_FRAME_VIDEO:
 				case AST_FRAME_TEXT:
 				case AST_FRAME_DTMF_BEGIN:
+				case AST_FRAME_DTMF_CONTINUE:
 				case AST_FRAME_DTMF_END:
 				case AST_FRAME_IMAGE:
 				case AST_FRAME_HTML:
@@ -3562,6 +3564,7 @@
 
 			switch (f->frametype) {
 			case AST_FRAME_DTMF_BEGIN:
+			case AST_FRAME_DTMF_CONTINUE:
 				break;
 			case AST_FRAME_DTMF_END:
 				res = f->subclass.integer;
@@ -3872,7 +3875,7 @@
 			 * there are cases where we want to leave DTMF frames on the queue until
 			 * some later time. */
 
-			if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
+			if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_CONTINUE || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
 				continue;
 			}
 
@@ -4077,6 +4080,13 @@
 						ast_frfree(old_frame);
 				}
 			}
+			break;
+		case AST_FRAME_DTMF_CONTINUE:
+			/* No manager event at this point
+				send_dtmf_event(chan, "Received", f->subclass, "Yes", "No");
+			*/
+			ast_log(LOG_DTMF, "DTMF continue '%c' received on %s\n", f->subclass.integer, chan->name);
+			ast_debug(4, "DTMF continue '%c' received on %s\n", f->subclass.integer, chan->name);
 			break;
 		case AST_FRAME_DTMF_BEGIN:
 			send_dtmf_event(chan, "Received", f->subclass.integer, "Yes", "No");
@@ -4629,6 +4639,18 @@
 	return 0;
 }
 
+int ast_senddigit_continue(struct ast_channel *chan, char digit, unsigned int duration)
+{
+	int res = -1;
+
+	ast_debug(4, "--- Continue frame passed on to tech for %s\n", chan->name);
+	if (chan->tech->send_digit_continue) {
+		res = chan->tech->send_digit_continue(chan, digit, duration);
+	}
+
+	return 0;
+}
+
 int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
 {
 	int res = -1;
@@ -4866,6 +4888,22 @@
 		ast_clear_flag(chan, AST_FLAG_BLOCKING);
 		ast_channel_unlock(chan);
 		res = ast_senddigit_begin(chan, fr->subclass.integer);
+		ast_channel_lock(chan);
+		CHECK_BLOCKING(chan);
+		break;
+	case AST_FRAME_DTMF_CONTINUE:
+		if (chan->audiohooks) {
+			struct ast_frame *old_frame = fr;
+			fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
+			if (old_frame != fr)
+				f = fr;
+		}
+		ast_log(LOG_DEBUG, "---Continue FRAME received, forwarding to channel %s\n", chan->name);
+		// Skip manager for continue events (at least for now)
+		//send_dtmf_event(chan, "Sent", fr->subclass, "Yes", "No");
+		ast_clear_flag(chan, AST_FLAG_BLOCKING);
+		ast_channel_unlock(chan);
+		res = ast_senddigit_continue(chan, fr->subclass.integer, fr->len);
 		ast_channel_lock(chan);
 		CHECK_BLOCKING(chan);
 		break;
@@ -7139,6 +7177,7 @@
 		}
 		if ((f->frametype == AST_FRAME_VOICE) ||
 		    (f->frametype == AST_FRAME_DTMF_BEGIN) ||
+		    (f->frametype == AST_FRAME_DTMF_CONTINUE) ||
 		    (f->frametype == AST_FRAME_DTMF) ||
 		    (f->frametype == AST_FRAME_VIDEO) ||
 		    (f->frametype == AST_FRAME_IMAGE) ||
@@ -7154,7 +7193,7 @@
 				*fo = f;
 				*rc = who;
 				ast_debug(1, "Got DTMF %s on channel (%s)\n", 
-					f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",
+					f->frametype == AST_FRAME_DTMF_END ? "end" : (AST_FRAME_DTMF_CONTINUE ? "cont" : "begin"),	
 					who->name);
 
 				break;

Modified: team/oej/rana-dtmf-duration-1.8/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/main/features.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/main/features.c (original)
+++ team/oej/rana-dtmf-duration-1.8/main/features.c Tue Apr 24 09:19:25 2012
@@ -4055,11 +4055,11 @@
 					   digits to come in for features. */
 					ast_debug(1, "Timed out for feature!\n");
 					if (!ast_strlen_zero(peer_featurecode)) {
-						ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
+						ast_dtmf_stream(chan, peer, peer_featurecode, 0, f->len);
 						memset(peer_featurecode, 0, sizeof(peer_featurecode));
 					}
 					if (!ast_strlen_zero(chan_featurecode)) {
-						ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
+						ast_dtmf_stream(peer, chan, chan_featurecode, 0, f->len);
 						memset(chan_featurecode, 0, sizeof(chan_featurecode));
 					}
 					if (f)

Modified: team/oej/rana-dtmf-duration-1.8/main/frame.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/main/frame.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/main/frame.c (original)
+++ team/oej/rana-dtmf-duration-1.8/main/frame.c Tue Apr 24 09:19:25 2012
@@ -801,6 +801,11 @@
 		subclass[0] = f->subclass.integer;
 		subclass[1] = '\0';
 		break;
+	case AST_FRAME_DTMF_CONTINUE:
+		strcpy(ftype, "DTMF Continue");
+		subclass[0] = f->subclass.integer;
+		subclass[1] = '\0';
+		break;
 	case AST_FRAME_DTMF_END:
 		strcpy(ftype, "DTMF End");
 		subclass[0] = f->subclass.integer;

Modified: team/oej/rana-dtmf-duration-1.8/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/main/rtp_engine.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/main/rtp_engine.c (original)
+++ team/oej/rana-dtmf-duration-1.8/main/rtp_engine.c Tue Apr 24 09:19:25 2012
@@ -732,6 +732,11 @@
 int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
 {
 	return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
+}
+
+int ast_rtp_instance_dtmf_continue(struct ast_rtp_instance *instance, char digit, unsigned int duration)
+{
+	return instance->engine->dtmf_continue ? instance->engine->dtmf_continue(instance, digit, duration) : -1;
 }
 
 int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)

Modified: team/oej/rana-dtmf-duration-1.8/res/res_rtp_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/rana-dtmf-duration-1.8/res/res_rtp_asterisk.c?view=diff&rev=363327&r1=363326&r2=363327
==============================================================================
--- team/oej/rana-dtmf-duration-1.8/res/res_rtp_asterisk.c (original)
+++ team/oej/rana-dtmf-duration-1.8/res/res_rtp_asterisk.c Tue Apr 24 09:19:25 2012
@@ -105,6 +105,14 @@
 	STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
 	STRICT_RTP_LEARN,    /*! Accept next packet as source */
 	STRICT_RTP_CLOSED,   /*! Drop all RTP packets not coming from source that was learned */
+};
+
+/*! \brief States for an outbound RTP stream that handles DTMF in RFC 2833 mode */
+enum dtmf_send_states {
+	DTMF_NOT_SENDING = 0,	/*! Not sending DTMF this very moment */
+	DTMF_SEND_INIT,		/*! Initializing */
+	DTMF_SEND_INPROGRESS,	/*! Playing DTMF */
+	DTMF_SEND_INPROGRESS_WITH_QUEUE	/*! Playing and having a queue to continue with */
 };
 
 #define FLAG_3389_WARNING               (1 << 0)
@@ -155,10 +163,13 @@
 	enum ast_rtp_dtmf_mode dtmfmode;/*!< The current DTMF mode of the RTP stream */
 	/* DTMF Transmission Variables */
 	unsigned int lastdigitts;
+	enum dtmf_send_states sending_dtmf;     /*!< - are we sending dtmf */
 	char sending_digit;	/*!< boolean - are we sending digits */
 	char send_digit;	/*!< digit we are sending */
 	int send_payload;
 	int send_duration;
+	unsigned int received_duration; /*!< Received duration (according to control frames) */
+	int send_endflag;               /*!< We have received END marker but are in waiting mode */
 	unsigned int flags;
 	struct timeval rxcore;
 	struct timeval txcore;
@@ -271,6 +282,7 @@
 static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
 static int ast_rtp_destroy(struct ast_rtp_instance *instance);
 static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
+static int ast_rtp_dtmf_continue(struct ast_rtp_instance *instance, char digit, unsigned int duration);
 static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
 static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration);
 static int ast_rtp_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
@@ -299,6 +311,7 @@
 	.new = ast_rtp_new,
 	.destroy = ast_rtp_destroy,
 	.dtmf_begin = ast_rtp_dtmf_begin,
+	.dtmf_continue = ast_rtp_dtmf_continue,
 	.dtmf_end = ast_rtp_dtmf_end,
 	.dtmf_end_with_duration = ast_rtp_dtmf_end_with_duration,
 	.dtmf_mode_set = ast_rtp_dtmf_mode_set,
@@ -699,7 +712,39 @@
 	return 0;
 }
 
-static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
+/*! \brief Get notification of duration updates */
+static int ast_rtp_dtmf_continue(struct ast_rtp_instance *instance, char digit, unsigned int duration)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	ast_debug(4, "DTMF CONTINUE - Duration %d Digit %d Send-digit %d\n", duration, digit, rtp->send_digit);
+
+	/* If we missed the BEGIN, we will have to turn on the flag */
+	if (!rtp->sending_dtmf) {
+		rtp->sending_dtmf = DTMF_SEND_INPROGRESS;
+	}
+
+	/* Duration is in ms. Calculate the duration in timestamps */
+	if (duration > 0) {
+		/* We have an incoming duration from the incoming channel. This needs
+		   to be matched with our outbound pacing. The inbound can be paced
+		   in either 50 ms or whatever packetization that is used on that channel,
+		   so we can't assume 20 ms (160 units in 8000 hz audio).
+		*/
+		int dursamples = duration * rtp_get_rate(rtp->f.subclass.codec) / 1000;
+
+		/* How do we get the sample rate for the primary media in this call? */
+
+		ast_debug(4, "DTMF CONTINUE : %d ms %d samples\n", duration, dursamples);
+		rtp->received_duration = dursamples;
+	} else {
+		ast_debug(4, "DTMF CONTINUE : Missing duration!!!!!!!\n");
+		
+	}
+	return 0;
+}
+
+static int ast_rtp_dtmf_cont(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 	struct ast_sockaddr remote_address = { {0,} };
@@ -1552,7 +1597,7 @@
 		resp = 'X';
 	} else {
 		/* Not a supported event */
-		ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
+		ast_debug(4, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
 		return;
 	}
 
@@ -1598,6 +1643,7 @@
 				f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
 				f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
 				rtp->resp = 0;
+				ast_debug(4, "--GOT DTMF END message. Duration samples %d (%ld ms)\n", rtp->dtmf_duration, f->len);
 				rtp->dtmf_duration = rtp->dtmf_timeout = 0;
 				AST_LIST_INSERT_TAIL(frames, f, frame_list);
 			}
@@ -1616,6 +1662,10 @@
 			if (rtp->resp) {
 				/* Digit continues */
 				rtp->dtmf_duration = new_duration;
+				f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_CONTINUE, 0));
+				f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
+				AST_LIST_INSERT_TAIL(frames, f, frame_list);
+				ast_debug(4, "Queued frame AST_FRAME_DTMF_CONTINUE, Samples %d Ms %d\n", rtp->dtmf_duration, (int)f->len);
 			} else {
 				/* New digit began */
 				rtp->resp = resp;
@@ -1804,8 +1854,10 @@
 		length &= 0xffff;
 
 		if ((i + length) > packetwords) {
-			if (option_debug || rtpdebug)
+			if (rtpdebug || option_debug) {
+				/* Because of rtpdebug, this can't be ast_debug() */
 				ast_log(LOG_DEBUG, "RTCP Read too short\n");
+			}
 			return &ast_null_frame;
 		}
 
@@ -2120,7 +2172,7 @@
 
 	/* If we are currently sending DTMF to the remote party send a continuation packet */
 	if (rtp->sending_digit) {
-		ast_rtp_dtmf_continuation(instance);
+		ast_rtp_dtmf_cont(instance);
 	}
 
 	/* Actually read in the data from the socket */




More information about the asterisk-commits mailing list