[asterisk-commits] branch kpfleming/vldtmf r9141 - in /team/kpfleming/vldtmf: ./ channels/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Feb 3 16:14:24 MST 2006


Author: kpfleming
Date: Fri Feb  3 17:14:23 2006
New Revision: 9141

URL: http://svn.digium.com/view/asterisk?rev=9141&view=rev
Log:
more cleanups
enable sending of variable length DTMF

Modified:
    team/kpfleming/vldtmf/channels/chan_vpb.c
    team/kpfleming/vldtmf/rtp.c

Modified: team/kpfleming/vldtmf/channels/chan_vpb.c
URL: http://svn.digium.com/view/asterisk/team/kpfleming/vldtmf/channels/chan_vpb.c?rev=9141&r1=9140&r2=9141&view=diff
==============================================================================
--- team/kpfleming/vldtmf/channels/chan_vpb.c (original)
+++ team/kpfleming/vldtmf/channels/chan_vpb.c Fri Feb  3 17:14:23 2006
@@ -356,7 +356,6 @@
 	devicestate: NULL,
 	send_digit: vpb_digit,
 	send_digit_begin: NULL,
-	send_digit_end: NULL,
 	call: vpb_call,
 	hangup: vpb_hangup,
 	answer: vpb_answer,
@@ -385,7 +384,6 @@
 	devicestate: NULL,
 	send_digit: vpb_digit,
 	send_digit_begin: NULL,
-	send_digit_end: NULL,
 	call: vpb_call,
 	hangup: vpb_hangup,
 	answer: vpb_answer,

Modified: team/kpfleming/vldtmf/rtp.c
URL: http://svn.digium.com/view/asterisk/team/kpfleming/vldtmf/rtp.c?rev=9141&r1=9140&r2=9141&view=diff
==============================================================================
--- team/kpfleming/vldtmf/rtp.c (original)
+++ team/kpfleming/vldtmf/rtp.c Fri Feb  3 17:14:23 2006
@@ -91,12 +91,13 @@
 /*! \brief RTP session description */
 struct ast_rtp {
 	int s;
-	char resp;
+	char inprocess_dtmf_receive;
+	char inprocess_dtmf_send;
 	struct ast_frame f;
 	unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
 	unsigned int ssrc;		/*!< Synchronization source, RFC 3550, page 10. */
-	unsigned int lastts;
-	unsigned int lastdigitts;
+	unsigned int next_send_ts;
+	unsigned int next_send_digit_ts;
 	unsigned int lastrxts;
 	unsigned int lastividtimestamp;
 	unsigned int lastovidtimestamp;
@@ -196,8 +197,24 @@
 #endif
 };
 
+struct cisco_dtmf_event {
+	/* Always keep in network byte order */
+#if __BYTE_ORDER == __BIG_ENDIAN
+	uint32_t padding:27;
+	uint32_t event:5;
+#else
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	uint32_t padding:27;
+	uint32_t event:5;
+#else
+#error Byte order not defined
+#endif
+#endif
+};
+
 struct rfc3389_event {
-	char level;
+	unsigned char level;
+	unsigned char spectral_data[22];
 };
 
 int ast_rtp_fd(struct ast_rtp *rtp)
@@ -270,24 +287,24 @@
 	if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
-		rtp->resp = 0;
+		rtp->inprocess_dtmf_receive = 0;
 		rtp->dtmfduration = 0;
 		return &ast_null_frame;
 	}
 	if (option_debug)
-		ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
-	if (rtp->resp == 'X') {
+		ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->inprocess_dtmf_receive, rtp->inprocess_dtmf_receive, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
+	if (rtp->inprocess_dtmf_receive == 'X') {
 		rtp->f.frametype = AST_FRAME_CONTROL;
 		rtp->f.subclass = AST_CONTROL_FLASH;
 	} else {
 		rtp->f.frametype = AST_FRAME_DTMF;
-		rtp->f.subclass = rtp->resp;
+		rtp->f.subclass = rtp->inprocess_dtmf_receive;
 	}
 	rtp->f.datalen = 0;
 	rtp->f.samples = 0;
 	rtp->f.mallocd = 0;
 	rtp->f.src = "RTP";
-	rtp->resp = 0;
+	rtp->inprocess_dtmf_receive = 0;
 	rtp->dtmfduration = 0;
 	return &rtp->f;
 	
@@ -299,31 +316,29 @@
 		return 0;
 	if (rtpdebugaddr.sin_addr.s_addr) {
 		if (((ntohs(rtpdebugaddr.sin_port) != 0)
-			&& (rtpdebugaddr.sin_port != addr->sin_port))
-			|| (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
+		     && (rtpdebugaddr.sin_port != addr->sin_port))
+		    || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
 		return 0;
 	}
 	return 1;
 }
 
-static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
-{
-	unsigned int event;
-	char resp = 0;
+static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, struct rtp_header *header, struct cisco_dtmf_event *event)
+{
+	char digit = 0;
 	struct ast_frame *f = NULL;
 
-	event = ntohl(*((unsigned int *)(data)));
-	event &= 0x001F;
 	if (option_debug > 2 || rtpdebug)
-		ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
-
-	resp = code_to_digit(event);
-
-	if (rtp->resp && (rtp->resp != resp))
+		ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x\n", event->event);
+
+	digit = code_to_digit(event->event);
+
+	if (rtp->inprocess_dtmf_receive && (rtp->inprocess_dtmf_receive != digit))
 		f = send_dtmf(rtp);
 
-	rtp->resp = resp;
+	rtp->inprocess_dtmf_receive = digit;
 	rtp->dtmfcount = dtmftimeout;
+
 	return f;
 }
 
@@ -339,32 +354,32 @@
  */
 static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, struct rtp_header *header, struct rfc2833_event *event)
 {
-	char resp = 0;
+	char digit = 0;
 	struct ast_frame *f = NULL;
 
 	if (rtpdebug || option_debug > 2)
 		ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x\n", event->event);
 
-	resp = code_to_digit(event->event);
-
-	if (rtp->resp && (rtp->resp != resp)) {
+	digit = code_to_digit(event->event);
+
+	if (rtp->inprocess_dtmf_receive && (rtp->inprocess_dtmf_receive != digit)) {
 		f = send_dtmf(rtp);
 	} else if (event->end) {
-		if (rtp->resp) {
+		if (rtp->inprocess_dtmf_receive) {
 			if (rtp->lasteventendseqn != header->sequence) {
 				f = send_dtmf(rtp);
 				rtp->lasteventendseqn = header->sequence;
 			}
-			rtp->resp = 0;
-		}
-		resp = 0;
+			rtp->inprocess_dtmf_receive = 0;
+		}
+		digit = 0;
 		event->duration = 0;
-	} else if (rtp->resp && rtp->dtmfduration && (event->duration < rtp->dtmfduration)) {
+	} else if (rtp->inprocess_dtmf_receive && rtp->dtmfduration && (event->duration < rtp->dtmfduration)) {
 		f = send_dtmf(rtp);
 	}
 
 	if (!event->end)
-		rtp->resp = resp;
+		rtp->inprocess_dtmf_receive = digit;
 
 	rtp->dtmfcount = dtmftimeout;
 	rtp->dtmfduration = event->duration;
@@ -388,12 +403,12 @@
 	   guaranteed to have it every 20ms or anything */
 
 	if (rtpdebug)
-		ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
+		ast_log(LOG_DEBUG, "- RFC3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
 
 	if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
 		char iabuf[INET_ADDRSTRLEN];
 
-		ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
+		ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC3389). Please turn off on client if possible. Client IP: %s\n",
 			ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
 		ast_set_flag(rtp, FLAG_3389_WARNING);
 	}
@@ -402,7 +417,7 @@
 		rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
 		rtp->f.datalen = len - 1;
 		rtp->f.offset = AST_FRIENDLY_OFFSET;
-		memcpy(rtp->f.data, ((unsigned char *) event) + 1, len - 1);
+		memcpy(rtp->f.data, event->spectral_data, len - 1);
 	} else {
 		rtp->f.data = NULL;
 		rtp->f.offset = 0;
@@ -595,22 +610,26 @@
 					    header->timestamp, res, header->marker,
 					    event->event, event->end, ntohs(event->duration));
 			}
-			if (rtp->lasteventseqn <= header->sequence || rtp->resp == 0 ||
+			if (rtp->lasteventseqn <= header->sequence || rtp->inprocess_dtmf_receive == 0 ||
 			    (rtp->lasteventseqn >= 65530 && header->sequence <= 6)) {
 				f = process_rfc2833(rtp, header, (struct rfc2833_event *) buffer);
 				rtp->lasteventseqn = header->sequence;
 			}
 			break;
 		case AST_RTP_CISCO_DTMF:
+			if (res < sizeof(struct cisco_dtmf_event)) {
+				ast_log(LOG_WARNING, "Cisco DTMF event too short\n");
+				return &ast_null_frame;
+			}
 			/* It's really special -- process it the Cisco way */
-			if (rtp->lasteventseqn <= header->sequence || rtp->resp == 0 ||
+			if (rtp->lasteventseqn <= header->sequence || rtp->inprocess_dtmf_receive == 0 ||
 			    (rtp->lasteventseqn >= 65530 && header->sequence <= 6)) {
-				f = process_cisco_dtmf(rtp, buffer, res);
+				f = process_cisco_dtmf(rtp, header, (struct cisco_dtmf_event *) buffer);
 				rtp->lasteventseqn = header->sequence;
 			}
 			break;
 		case AST_RTP_CN:
-			if (res < sizeof(struct rfc3389_event)) {
+			if (res < 1) {
 				ast_log(LOG_WARNING, "RFC3389 event too short\n");
 				return &ast_null_frame;
 			}
@@ -643,7 +662,7 @@
 	rtp->lastrxts = header->timestamp;
 
 	/* Send any pending DTMF */
-	if (rtp->resp && !rtp->dtmfcount) {
+	if (rtp->inprocess_dtmf_receive && !rtp->dtmfcount) {
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Sending pending DTMF\n");
 		return send_dtmf(rtp);
@@ -741,6 +760,7 @@
 void ast_rtp_pt_clear(struct ast_rtp* rtp) 
 {
 	int i;
+
 	if (!rtp)
 		return;
 
@@ -772,6 +792,7 @@
 static void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src)
 {
 	int i;
+
 	/* Copy payload types from source to destination */
 	for (i=0; i < MAX_RTP_PT; ++i) {
 		dest->current_RTP_PT[i].isAstFormat = 
@@ -804,6 +825,7 @@
 	struct ast_rtp *destp, *srcp;		/* Audio RTP Channels */
 	struct ast_rtp *vdestp, *vsrcp;		/* Video RTP channels */
 	struct ast_rtp_protocol *destpr, *srcpr;
+
 	/* Lock channels */
 	ast_mutex_lock(&dest->lock);
 	while(ast_mutex_trylock(&src->lock)) {
@@ -959,16 +981,16 @@
 	return -1;
 }
 
-char* ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code) 
+char *ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code) 
 {
 
 	int i;
 
 	for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
-	if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
-      		return mimeTypes[i].subtype;
-		}
-	}
+		if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat)
+			return mimeTypes[i].subtype;
+	}
+
 	return "";
 }
 
@@ -992,6 +1014,7 @@
 	for (format = 1; format < AST_RTP_MAX; format <<= 1) {
 		if (capability & format) {
 			const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
+
 			snprintf(end, size, "%s|", name);
 			len = strlen(end);
 			end += len;
@@ -1011,6 +1034,7 @@
 {
 	int s;
 	long flags;
+
 	s = socket(AF_INET, SOCK_DGRAM, 0);
 	if (s > -1) {
 		flags = fcntl(s, F_GETFL);
@@ -1020,6 +1044,7 @@
 			setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
 #endif
 	}
+
 	return s;
 }
 
@@ -1031,6 +1056,7 @@
 static struct ast_rtcp *ast_rtcp_new(void)
 {
 	struct ast_rtcp *rtcp;
+
 	rtcp = malloc(sizeof(struct ast_rtcp));
 	if (!rtcp)
 		return NULL;
@@ -1042,6 +1068,7 @@
 		ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
 		return NULL;
 	}
+
 	return rtcp;
 }
 
@@ -1051,6 +1078,7 @@
 	int x;
 	int first;
 	int startplace;
+
 	rtp = malloc(sizeof(struct ast_rtp));
 	if (!rtp)
 		return NULL;
@@ -1129,6 +1157,7 @@
 		rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
 	}
 	ast_rtp_pt_default(rtp);
+
 	return rtp;
 }
 
@@ -1137,6 +1166,7 @@
 	struct in_addr ia;
 
 	memset(&ia, 0, sizeof(ia));
+
 	return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
 }
 
@@ -1146,6 +1176,7 @@
 
 	if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
 		ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
+
 	return res;
 }
 
@@ -1186,8 +1217,8 @@
 	memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
 	memset(&rtp->txcore, 0, sizeof(rtp->txcore));
 	memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
-	rtp->lastts = 0;
-	rtp->lastdigitts = 0;
+	rtp->next_send_ts = 0;
+	rtp->next_send_digit_ts = 0;
 	rtp->lastrxts = 0;
 	rtp->lastividtimestamp = 0;
 	rtp->lastovidtimestamp = 0;
@@ -1219,6 +1250,7 @@
 {
 	struct timeval t;
 	long ms;
+
 	if (ast_tvzero(rtp->txcore)) {
 		rtp->txcore = ast_tvnow();
 		/* Round to 20ms for nice, pretty timestamps */
@@ -1231,26 +1263,61 @@
 		ms = 0;
 	/* Use what we just got for next time */
 	rtp->txcore = t;
+
 	return (unsigned int) ms;
 }
 
-void static prep_header(struct rtp_header *header, struct ast_rtp *rtp, int payload)
+void static prep_header(struct rtp_header *header, struct ast_rtp *rtp, unsigned int payload, unsigned int timestamp)
 {
 	header->payload = ast_rtp_lookup_code(rtp, 0, payload);
 	header->sequence = htons(rtp->seqno);
 	header->version = 2;
-	header->timestamp = htonl(rtp->lastdigitts);
+	header->timestamp = timestamp;
 	header->ssrc = htonl(rtp->ssrc);
 }
 
 int ast_rtp_send_digit_begin(struct ast_rtp *rtp, char digit)
 {
+	unsigned char packet[sizeof(struct rtp_header) + sizeof(struct rfc2833_event)];
+	struct rtp_header *header = (struct rtp_header *) &packet[0];
+	struct rfc2833_event *event = (struct rfc2833_event *) &packet[sizeof(struct rtp_header)];
+	int res;
+	char code;
+	char iabuf[INET_ADDRSTRLEN];
+
 	/* If we have no peer, return immediately */	
-	if (!rtp->them.sin_addr.s_addr)
+	if (!(rtp->them.sin_addr.s_addr && rtp->them.sin_port))
 		return 0;
 
-	if ((digit = digit_to_code(digit)) == -1)
+	if ((code = digit_to_code(digit)) == -1)
 		return -1;
+
+	memset(packet, 0, sizeof(packet));
+
+	prep_header(header, rtp, AST_RTP_DTMF, rtp->next_send_digit_ts);
+	header->marker = 1;
+
+	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+	rtp->inprocess_dtmf_send = code;
+	
+	event->event = code;
+	event->volume = 0xa;
+
+	res = sendto(rtp->s, packet, sizeof(packet), 0,
+		     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+	if (res < 0) 
+		ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+			ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
+			ntohs(rtp->them.sin_port), strerror(errno));
+	if (rtp_debug_test_addr(&rtp->them))
+		ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %lu)\n",
+			    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
+			    ntohs(rtp->them.sin_port), header->payload,
+			    rtp->seqno, rtp->next_send_digit_ts, sizeof(*event));
+
+	rtp->seqno++;
+
+	return 0;
 }
 
 int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
@@ -1260,61 +1327,94 @@
 	struct rfc2833_event *event = (struct rfc2833_event *) &packet[sizeof(struct rtp_header)];
 	int res;
 	int x;
+	char code;
 	char iabuf[INET_ADDRSTRLEN];
 
 	/* If we have no peer, return immediately */	
 	if (!rtp->them.sin_addr.s_addr)
 		return 0;
 
-	if ((digit = digit_to_code(digit)) == -1)
+	if ((code = digit_to_code(digit)) == -1)
 		return -1;
 
 	memset(packet, 0, sizeof(packet));
 
-	prep_header(header, rtp, AST_RTP_DTMF);
-	header->marker = 1;
-
-	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+	prep_header(header, rtp, AST_RTP_DTMF, rtp->next_send_digit_ts);
+	event->event = code;
+	event->volume = 0xa;
+
+	/* if a digit is in-process, send only the 'end'
+	   indication; otherwise, send the whole thing */
+	if (rtp->inprocess_dtmf_send == code) {
+		event->end = 1;
+		/*** TODO: need to set duration and increment next_send_digit_ts***/
+		/* these packets are intentional duplicates; the seqno is _NOT_
+		   incremented as they are sent
+		*/
+		for (x = 0; x < 2; x++) {
+			if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
+				res = sendto(rtp->s, packet, sizeof(packet), 0,
+					     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+				if (res < 0) 
+					ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+						ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
+						ntohs(rtp->them.sin_port), strerror(errno));
+				if (rtp_debug_test_addr(&rtp->them))
+					ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %lu)\n",
+						    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
+						    ntohs(rtp->them.sin_port), header->payload,
+						    rtp->seqno, rtp->next_send_digit_ts, sizeof(*event));
+			}
+		}
+	} else {
+		header->marker = 1;
+
+		rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
 	
-	event->event = digit;
-	event->volume = 0xa;
-
-	for (x = 0; x < 6; x++) {
-		if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-			res = sendto(rtp->s, packet, sizeof(packet), 0,
-				     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
-			if (res < 0) 
-				ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-					ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
-					ntohs(rtp->them.sin_port), strerror(errno));
-			if (rtp_debug_test_addr(&rtp->them))
-				ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %lu)\n",
-					    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
-					    ntohs(rtp->them.sin_port), header->payload,
-					    rtp->seqno, rtp->lastdigitts, sizeof(*event));
-		}
-		/* Sequence number of last two end packets does not get incremented */
-		if (x < 3)
-			rtp->seqno++;
-		/* Clear marker bit and set seqno */
-		header->marker = 0;
-		header->sequence = htons(rtp->seqno);
-		/* For the last three packets, set the duration and the end bit */
-		if (x == 2) {
-			event->duration = htons(800);
-			event->end = 1;
-		}
-	}
-	/* Increment the digit timestamp by 120ms, to ensure that digits
-	   sent sequentially with no intervening non-digit packets do not
-	   get sent with the same timestamp, and that sequential digits
-	   have some 'dead air' in between them
-	*/
-	rtp->lastdigitts += 960;
+		for (x = 0; x < 6; x++) {
+			if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
+				res = sendto(rtp->s, packet, sizeof(packet), 0,
+					     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+				if (res < 0) 
+					ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+						ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
+						ntohs(rtp->them.sin_port), strerror(errno));
+				if (rtp_debug_test_addr(&rtp->them))
+					ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %lu)\n",
+						    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
+						    ntohs(rtp->them.sin_port), header->payload,
+						    rtp->seqno, rtp->next_send_digit_ts, sizeof(*event));
+			}
+			switch (x) {
+			case 0:
+				header->marker = 0;
+				/* fallthrough */
+			case 1:
+				rtp->seqno++;
+				header->sequence = htons(rtp->seqno);
+				break;
+			case 2:
+				rtp->seqno++;
+				header->sequence = htons(rtp->seqno);
+				event->duration = htons(800);
+				event->end = 1;
+				break;
+			}
+		}
+		/* Increment the digit timestamp by 120ms, to ensure that digits
+		   sent sequentially with no intervening non-digit packets do not
+		   get sent with the same timestamp, and that sequential digits
+		   have some 'dead air' in between them
+		*/
+		rtp->next_send_digit_ts += 960;
+	}
+
 	/* Increment the sequence number to reflect the last packet
 	   that was sent
 	*/
 	rtp->seqno++;
+
+	rtp->inprocess_dtmf_send = 0;
 
 	return 0;
 }
@@ -1335,7 +1435,7 @@
 
 	memset(packet, 0, sizeof(packet));
 
-	prep_header(header, rtp, AST_RTP_CN);
+	prep_header(header, rtp, AST_RTP_CN, rtp->next_send_ts);
 
 	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
 
@@ -1352,7 +1452,7 @@
 			ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %lu)\n",
 				    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
 				    ntohs(rtp->them.sin_port), header->payload,
-				    rtp->seqno, rtp->lastts, sizeof(*event));
+				    rtp->seqno, rtp->next_send_ts, sizeof(*event));
 	}
 
 	rtp->seqno++;
@@ -1372,18 +1472,18 @@
 	ms = calc_txstamp(rtp, &f->delivery);
 	/* Default prediction */
 	if (f->subclass < AST_FORMAT_MAX_AUDIO) {
-		pred = rtp->lastts + f->samples;
+		pred = rtp->next_send_ts + f->samples;
 
 		/* Re-calculate last TS */
-		rtp->lastts = rtp->lastts + ms * 8;
+		rtp->next_send_ts = rtp->next_send_ts + ms * 8;
 		if (ast_tvzero(f->delivery)) {
 			/* If this isn't an absolute delivery time, Check if it is close to our prediction, 
 			   and if so, go with our prediction */
-			if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
-				rtp->lastts = pred;
+			if (abs(rtp->next_send_ts - pred) < MAX_TIMESTAMP_SKEW)
+				rtp->next_send_ts = pred;
 			else {
 				if (option_debug > 2)
-					ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
+					ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->next_send_ts - pred), ms);
 				mark = 1;
 			}
 		}
@@ -1391,27 +1491,27 @@
 		mark = f->subclass & 0x1;
 		pred = rtp->lastovidtimestamp + f->samples;
 		/* Re-calculate last TS */
-		rtp->lastts = rtp->lastts + ms * 90;
+		rtp->next_send_ts = rtp->next_send_ts + ms * 90;
 		/* If it's close to our prediction, go for it */
 		if (ast_tvzero(f->delivery)) {
-			if (abs(rtp->lastts - pred) < 7200) {
-				rtp->lastts = pred;
+			if (abs(rtp->next_send_ts - pred) < 7200) {
+				rtp->next_send_ts = pred;
 				rtp->lastovidtimestamp += f->samples;
 			} else {
 				if (option_debug > 2)
-					ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
-				rtp->lastovidtimestamp = rtp->lastts;
+					ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->next_send_ts - pred), ms, ms * 90, rtp->next_send_ts, pred, f->samples);
+				rtp->lastovidtimestamp = rtp->next_send_ts;
 			}
 		}
 	}
 	/* If the timestamp for non-digit packets has moved beyond the timestamp
 	   for digits, update the digit timestamp.
 	*/
-	if (rtp->lastts > rtp->lastdigitts)
-		rtp->lastdigitts = rtp->lastts;
+	if (rtp->next_send_ts > rtp->next_send_digit_ts)
+		rtp->next_send_digit_ts = rtp->next_send_ts;
 
 	header = (struct rtp_header *) (f->data - sizeof(*header));
-	prep_header(header, rtp, codec);
+	prep_header(header, rtp, codec, rtp->next_send_ts);
 	header->marker = mark;
 
 	if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
@@ -1435,7 +1535,7 @@
 		if (rtp_debug_test_addr(&rtp->them))
 			ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n",
 				    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
-				    ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts, res);
+				    ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->next_send_ts, res);
 	}
 
 	rtp->seqno++;
@@ -1631,7 +1731,6 @@
 	struct sockaddr_in t0, t1;
 	struct sockaddr_in vt0, vt1;
 	char iabuf[INET_ADDRSTRLEN];
-	
 	void *pvt0, *pvt1;
 	int codec0,codec1, oldcodec0, oldcodec1;
 	
@@ -1856,6 +1955,7 @@
 		cs[1] = cs[2];
 		
 	}
+
 	return AST_BRIDGE_FAILED;
 }
 



More information about the asterisk-commits mailing list