Index: rtp.c
===================================================================
--- rtp.c	(revision 12841)
+++ rtp.c	(working copy)
@@ -97,6 +97,8 @@
 	unsigned int lastovidtimestamp;
 	unsigned int lasteventseqn;
 	unsigned int lasteventendseqn;
+	char lasteventresp;
+	unsigned int lasteventtimestamp;
 	int lasttxformat;
 	int lastrxformat;
 	int dtmfcount;
@@ -258,14 +260,17 @@
  * \param data
  * \param len
  * \param seqno
+ * \param timestamp
+ * \param mark
  * \returns
  */
-static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno)
+static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int mark)
 {
 	unsigned int event;
 	unsigned int event_end;
 	unsigned int duration;
 	char resp = 0;
+	char dtmfdetect = 0;
 	struct ast_frame *f = NULL;
 	event = ntohl(*((unsigned int *)(data)));
 	event >>= 24;
@@ -287,23 +292,44 @@
 	} else if (event < 17) {	/* Event 16: Hook flash */
 		resp = 'X';	
 	}
-	if (rtp->resp && (rtp->resp != resp)) {
-		f = send_dtmf(rtp);
-	} else if(event_end & 0x80) {
-		if (rtp->resp) {
-			if(rtp->lasteventendseqn != seqno) {
-				f = send_dtmf(rtp);
-				rtp->lasteventendseqn = seqno;
-			}
-			rtp->resp = 0;
+
+
+	/* Currently only fixed length dtmfs supported.
+	   So our goal is to detect dtmf once and ignore furhter updates on it, just not to report the same dtmf multiple times.
+	   The easiest way to do it is to check marker bit on dtmf event, which indicates for new dtmf.
+	   Actually marker bit can be missed (not all implemantation support this), or even this packet can be lost, so for robustness
+	   further checking should be apllied as well
+	*/
+
+	/* dtmf detection */
+	if (mark) {
+		/* Good enough.
+		   Some implemantations set marker on every dtmf event, even on updates, which is surely wrong.
+		   So timestamp should be checked against it, just not to report multiple dtmfs, instead of one	*/
+		if (rtp->lasteventtimestamp != timestamp) {
+			dtmfdetect = 1;
 		}
-		resp = 0;
-		duration = 0;
-	} else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) {
+	} else if (rtp->lasteventresp != resp) {
+		/* Marker bit is missed or lost, but we actaully have different event here */
+		dtmfdetect = 1;
+	} else if (rtp->lasteventtimestamp != timestamp && !(event_end & 0x80) && 
+		rtp->lasteventtimestamp + duration + 320 < timestamp) {
+		/* The most complex case.
+		Marker bit is still missed or lost, but we have the same dtmf, which is not the update on the previous one.
+		So should be reported as separate dtmf */
+		printf("dtmf detect: 3, timestamp_diff=%d, duration=%d\n",timestamp-rtp->lasteventtimestamp,duration);
+		dtmfdetect = 1;
+	} else {
+		/* Nothing to do, as this is update on already reported dtmf */
+	}
+
+	if (dtmfdetect) {
+		rtp->lasteventresp = resp;
+		rtp->lasteventtimestamp = timestamp;
+		rtp->resp = resp;
 		f = send_dtmf(rtp);
 	}
-	if (!(event_end & 0x80))
-		rtp->resp = resp;
+
 	rtp->dtmfcount = dtmftimeout;
 	rtp->dtmfduration = duration;
 	return f;
@@ -533,11 +559,7 @@
 				duration &= 0xFFFF;
 				ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
 			}
-			if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
-				f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
-				rtp->lasteventseqn = seqno;
-			} else
-				f = NULL;
+			f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, mark);
 			if (f)
 				return f;
 			else
@@ -1063,6 +1085,8 @@
 	rtp->lastovidtimestamp = 0;
 	rtp->lasteventseqn = 0;
 	rtp->lasteventendseqn = 0;
+	rtp->lasteventresp = 0;
+	rtp->lasteventtimestamp = 0;
 	rtp->lasttxformat = 0;
 	rtp->lastrxformat = 0;
 	rtp->dtmfcount = 0;
