[asterisk-commits] oej: branch oej/rana-dtmf-duration-1.8 r364162 - /team/oej/rana-dtmf-duration...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Apr 27 04:32:34 CDT 2012


Author: oej
Date: Fri Apr 27 04:32:29 2012
New Revision: 364162

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=364162
Log:
Now we're up to the standard of the 1.6.0 version of the patch.

All that is required is to activate the DTMF queue

Modified:
    team/oej/rana-dtmf-duration-1.8/res/res_rtp_asterisk.c

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=364162&r1=364161&r2=364162
==============================================================================
--- 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 Fri Apr 27 04:32:29 2012
@@ -161,21 +161,25 @@
 	unsigned int dtmf_timeout;      /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
 	unsigned int dtmfsamples;
 	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 */
+	char send_dtmf_frame;	/*!< Number of samples in a frame with the current packetization */
+	AST_LIST_HEAD_NOLOCK(, ast_frame) dtmfqueue;	/*!< Queue for DTMF that we receive while occupied with transmitting an outbound DTMF */
+	struct timeval dtmfmute;
+
 	int send_payload;
 	int send_duration;
+	int send_endflag:1;		/*!< We have received END marker but are in waiting mode */
 	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;
 	double drxcore;                 /*!< The double representation of the first received packet */
 	struct timeval lastrx;          /*!< timeval when we last received a packet */
-	struct timeval dtmfmute;
 	struct ast_smoother *smoother;
 	int *ioid;
 	unsigned short seqno;		/*!< Sequence number, RFC 3550, page 13. */
@@ -595,6 +599,7 @@
 static int ast_rtp_destroy(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	struct ast_frame *f;
 
 	/* Destroy the smoother that was smoothing out audio if present */
 	if (rtp->smoother) {
@@ -623,6 +628,11 @@
 		ast_free(rtp->red);
 	}
 
+	/* Empty the DTMF queue */
+	while ((f = AST_LIST_REMOVE_HEAD(&rtp->dtmfqueue, frame_list))) {
+		ast_frfree(f);
+	}
+
 	/* Finally destroy ourselves */
 	ast_free(rtp);
 
@@ -655,6 +665,16 @@
 	/* If we have no remote address information bail out now */
 	if (ast_sockaddr_isnull(&remote_address)) {
 		return -1;
+	}
+
+	/* If we're sending DTMF already, we will ignore this but raise sending_dtmf with one
+	   to mark that we're busy and can't be disturbed. When we receive an END packet, we will
+	   act on that - either start playing with some delay or stack it up in a dtmfqueue.
+	*/
+	if (rtp->sending_dtmf) {
+		ast_debug(3, "Received DTMF begin while we're playing out DTMF. Ignoring \n");
+		rtp->sending_dtmf = DTMF_SEND_INPROGRESS_WITH_QUEUE;	/* Tell the world that there's an ignored DTMF */
+/* OEJ Fix ??? */
 	}
 
 	/* Convert given digit into what we want to transmit */
@@ -700,14 +720,17 @@
 				    payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
 		}
 		rtp->seqno++;
-		rtp->send_duration += 160;
+		rtp->send_duration += 160;	/* OEJ - check what's going on here. */
+		
 		rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
 	}
 
-	/* Record that we are in the process of sending a digit and information needed to continue doing so */
-	rtp->sending_digit = 1;
+	/* Since we received a begin, we can safely store the digit and disable any compensation */
+	rtp->sending_dtmf = DTMF_SEND_INIT;
 	rtp->send_digit = digit;
 	rtp->send_payload = payload;
+
+	ast_log(LOG_DEBUG, "DEBUG DTMF BEGIN - Digit %d send-digit %d\n", digit, rtp->send_digit);
 
 	return 0;
 }
@@ -744,6 +767,19 @@
 	return 0;
 }
 
+/*! \brief Send continuation frame for DTMF 
+
+This is called when we get a frame in ast_rtp_read. To keep the timing, because there may be delays through Asterisk
+feature handling and other code, we need to clock the outbound DTMF with the frame size we have on the stream.
+We should not cut short and send a begin then in the next packet an END with a duration that exceeds the
+framesize (in most cases for audio 20 ms) and number of frames. That will seriously cause issues in gateways
+or phones down the path.
+
+An effect of this is that we may get a new DTMF frame while we're transmitting the previous one. For this case,
+we have implemented an DTMF queue that will queue up the dtmf and play out. The alternative would be to skip
+these, which is no good, or cut them short and cause issues with timing for other devices, while we solve our
+own situation. That's generally considered bad behaviour amongst SIP devices.
+*/
 static int ast_rtp_dtmf_cont(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
@@ -759,6 +795,20 @@
 		return -1;
 	}
 
+	ast_debug(4, "---- Send duration %d Received duration %d Endflag %d Send-digit %d\n", rtp->send_duration, rtp->received_duration, rtp->send_endflag, rtp->send_digit);
+
+	/*! \todo XXX This code assumes 160 samples, which is for 20 ms of 8000 samples
+		we need to calculate this based on the current sample rate and the rtp 
+		stream packetization. Please help me figure this out :-)
+	 */
+	if (rtp->received_duration == 0 || rtp->send_duration + 160 <= rtp->received_duration) {
+		rtp->send_duration += 160;
+	} else if (rtp->send_endflag) {
+		ast_log(LOG_DEBUG, "---- Send duration %d Received duration %d - sending END packet\n", rtp->send_duration, rtp->received_duration);
+		/* We are done, ready to send end flag */
+		rtp->send_endflag = 0;
+		return ast_rtp_dtmf_end_with_duration(instance, 0, rtp->received_duration);
+	}
 	/* Actually create the packet we will be sending */
 	rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
 	rtpheader[1] = htonl(rtp->lastdigitts);
@@ -782,7 +832,7 @@
 
 	/* And now we increment some values for the next time we swing by */
 	rtp->seqno++;
-	rtp->send_duration += 160;
+	rtp->send_duration += 160;	/* Again assuming 20 ms packetization and 8000 samples */
 
 	return 0;
 }
@@ -795,12 +845,25 @@
 	char data[256];
 	unsigned int *rtpheader = (unsigned int*)data;
 	unsigned int measured_samples;
+	unsigned int dursamples;
 
 	ast_rtp_instance_get_remote_address(instance, &remote_address);
 
 	/* Make sure we know where the remote side is so we can send them the packet we construct */
 	if (ast_sockaddr_isnull(&remote_address)) {
 		return -1;
+	}
+	dursamples =  duration * (8000 / 1000);     /* How do we get the sample rate for the primary media in this call? */
+
+	ast_debug(1, "---- Send duration %d Received duration %d Duration %d Endflag %d Digit %d      Send-digit %d\n", rtp->send_duration, rtp->received_duration, duration, rtp->send_endflag, digit, rtp     ->send_digit);
+
+	if (!rtp->send_endflag && rtp->send_duration + 160 < rtp->received_duration) {
+		/* We still have to send DTMF continuation, because otherwise we will end prematurely. Set end flag to indicate
+		   that we will have to end ourselves when we're done with the actual duration
+		 */
+		ast_log(LOG_DEBUG, "---- Send duration %d Received duration %d - Avoiding sending END packet\n", rtp->send_duration, rtp->received_duration);
+		rtp->send_endflag = 1;
+		return ast_rtp_dtmf_cont(instance);
 	}
 
 	/* Convert the given digit to the one we are going to send */
@@ -851,7 +914,7 @@
 
 	/* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
 	rtp->lastts += rtp->send_duration;
-	rtp->sending_digit = 0;
+	rtp->sending_dtmf = DTMF_NOT_SENDING;
 	rtp->send_digit = 0;
 
 	return 0;
@@ -1201,7 +1264,7 @@
 		frame->samples /= 2;
 	}
 
-	if (rtp->sending_digit) {
+	if (rtp->sending_dtmf) {
 		return 0;
 	}
 
@@ -2171,7 +2234,7 @@
 	}
 
 	/* If we are currently sending DTMF to the remote party send a continuation packet */
-	if (rtp->sending_digit) {
+	if (rtp->sending_dtmf) {
 		ast_rtp_dtmf_cont(instance);
 	}
 




More information about the asterisk-commits mailing list