[asterisk-commits] oej: branch group/pinefool-poor-mans-plc-1.4 r383908 - in /team/group/pinefoo...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 26 07:33:35 CDT 2013


Author: oej
Date: Tue Mar 26 07:33:30 2013
New Revision: 383908

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383908
Log:
Various updates to handle weird situations.

Again, thanks to Martin at VoipMonitor.org for a brainstorm session.

Modified:
    team/group/pinefool-poor-mans-plc-1.4/README.pinefool-poor-mans-plc
    team/group/pinefool-poor-mans-plc-1.4/channels/chan_sip.c
    team/group/pinefool-poor-mans-plc-1.4/configs/rtp.conf.sample
    team/group/pinefool-poor-mans-plc-1.4/main/rtp.c

Modified: team/group/pinefool-poor-mans-plc-1.4/README.pinefool-poor-mans-plc
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefool-poor-mans-plc-1.4/README.pinefool-poor-mans-plc?view=diff&rev=383908&r1=383907&r2=383908
==============================================================================
--- team/group/pinefool-poor-mans-plc-1.4/README.pinefool-poor-mans-plc (original)
+++ team/group/pinefool-poor-mans-plc-1.4/README.pinefool-poor-mans-plc Tue Mar 26 07:33:30 2013
@@ -83,6 +83,7 @@
 - http://en.wikipedia.org/wiki/Packet_loss_concealment
 - http://research.microsoft.com/pubs/73282/network-survey-1998.pdf
 - http://ivms.stanford.edu/~liang/research/sigproc2/
+- http://www.ietf.org/rfc/rfc3550.txt - The RTP RFC
 
 And finally a description of the current PLC in Asterisk
 - https://wiki.asterisk.org/wiki/display/AST/Packet+Loss+Concealment+%28PLC%29

Modified: team/group/pinefool-poor-mans-plc-1.4/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefool-poor-mans-plc-1.4/channels/chan_sip.c?view=diff&rev=383908&r1=383907&r2=383908
==============================================================================
--- team/group/pinefool-poor-mans-plc-1.4/channels/chan_sip.c (original)
+++ team/group/pinefool-poor-mans-plc-1.4/channels/chan_sip.c Tue Mar 26 07:33:30 2013
@@ -4901,7 +4901,9 @@
 			free(p);
 			return NULL;
 		}
-		ast_rtp_set_plc(p->rtp, ast_test_flag(&p->flags[1], SIP_DTMF) == SIP_PAGE2_POORMANSPLC);
+		if (ast_test_flag(&p->flags[1], SIP_PAGE2_POORMANSPLC)) {
+			ast_rtp_set_plc(p->rtp, TRUE);
+		}
 		ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
 		ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
 		ast_rtp_settos(p->rtp, global_tos_audio);
@@ -10767,6 +10769,9 @@
 		if (p->rtp) {
 			ast_rtp_codec_setpref(p->rtp, &p->prefs);
 			p->autoframing = user->autoframing;
+			if (ast_test_flag(&p->flags[1], SIP_PAGE2_POORMANSPLC)) {
+				ast_rtp_set_plc(p->rtp, TRUE);
+			}
 		}
 		/* replace callerid if rpid found, and not restricted */
 		if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
@@ -10786,6 +10791,9 @@
 				ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
 			ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
 			ast_copy_flags(&p->flags[1], &user->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+			if (ast_test_flag(&p->flags[1], SIP_PAGE2_POORMANSPLC)) {
+				ast_rtp_set_plc(p->rtp, TRUE);
+			}
 			/* Copy SIP extensions profile from INVITE */
 			if (p->sipoptions)
 				user->sipoptions = p->sipoptions;
@@ -10867,6 +10875,9 @@
 			if (p->rtp) {
 				ast_rtp_codec_setpref(p->rtp, &peer->prefs);
 				p->autoframing = peer->autoframing;
+				if (ast_test_flag(&p->flags[1], SIP_PAGE2_POORMANSPLC)) {
+					ast_rtp_set_plc(p->rtp, TRUE);
+				}
 			}
 			if (debug)
 				ast_verbose("Found peer '%s'\n", peer->name);
@@ -10912,6 +10923,10 @@
 					ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
 				ast_string_field_set(p, peername, peer->name);
 				ast_string_field_set(p, authname, peer->name);
+
+				if (p->rtp && ast_test_flag(&p->flags[1], SIP_PAGE2_POORMANSPLC)) {
+					ast_rtp_set_plc(p->rtp, TRUE);
+				}
 
 				if (sipmethod == SIP_INVITE) {
 					/* destroy old channel vars and copy new channel vars */

Modified: team/group/pinefool-poor-mans-plc-1.4/configs/rtp.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefool-poor-mans-plc-1.4/configs/rtp.conf.sample?view=diff&rev=383908&r1=383907&r2=383908
==============================================================================
--- team/group/pinefool-poor-mans-plc-1.4/configs/rtp.conf.sample (original)
+++ team/group/pinefool-poor-mans-plc-1.4/configs/rtp.conf.sample Tue Mar 26 07:33:30 2013
@@ -27,3 +27,12 @@
 ; be a gap in the outbound sequence numbers as well, which in most cases will help
 ; both codecs and jitter buffers/PLC functions in the receiving end - a phone or a gateway.
 donthidepacketloss = no
+
+; If a channel driver turns on Poor Man's PLC the RTP channel will replace lost packets
+; with a copy of a previous packet. The "plcmax" setting defines the maximum number of
+; packets inserted in one operation. If the seqno indicates 200 lost packets, it doesn't
+; make much sense to inject all of them. (default 10)
+; For many codecs, the size of the packet is 20 ms (see packetization settings)
+; so 10 packets is 0.2 secs of noise. 50 packets is a second and will sound really bad.
+;plcmax = 42
+

Modified: team/group/pinefool-poor-mans-plc-1.4/main/rtp.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pinefool-poor-mans-plc-1.4/main/rtp.c?view=diff&rev=383908&r1=383907&r2=383908
==============================================================================
--- team/group/pinefool-poor-mans-plc-1.4/main/rtp.c (original)
+++ team/group/pinefool-poor-mans-plc-1.4/main/rtp.c Tue Mar 26 07:33:30 2013
@@ -77,8 +77,11 @@
 
 static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
 
-static int poormansplc;			/*!< Are we using poor man's packet loss concealment? */
+
 static int donthidepacketloss;		/*!< Do not hide packet loss on outbound RTP - default off */
+static int plcmax;			/*!< Maximum number of PLC injections in the stream in one operation */
+#define DEFAULT_PLCMAX	10
+
 static int rtpstart;			/*!< First port for RTP sessions (set in rtp.conf) */
 static int rtpend;			/*!< Last port for RTP sessions (set in rtp.conf) */
 static int rtpdebug;			/*!< Are we debugging? */
@@ -580,6 +583,9 @@
 {
 	if (state) {
 		ast_set_flag(rtp, FLAG_POORMANSPLC);
+		if (option_debug > 2) {
+			ast_log(LOG_DEBUG, "*** Enabling PLC for this call\n");
+		}
 	} else {
 		ast_clear_flag(rtp, FLAG_POORMANSPLC);
 	}
@@ -1356,30 +1362,64 @@
 		rtp->cycles += RTP_SEQ_MOD;
 
 	if (rtp->rxcount > 1) {
-		if (ast_test_flag(rtp, FLAG_POORMANSPLC) && seqno < rtp->lastrxseqno)  {
-			/* This is a latecome we've already replaced. A jitter buffer would have handled this
-			   properly, but in many cases we can't afford a jitterbuffer and will have to live
-			   with the face that the poor man's PLC already has replaced this frame and we can't
-			   insert it AGAIN, because that would cause negative skew.
-			   Henry, just ignore this late visitor. Thank you.
-			*/
-			return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
-		}
+		int MAX_MISORDER = 100;
+		int not_jitter = 0;
+
+		/* RTP sequence numbers are consecutive. Have we lost a packet? */
 		lostpackets = (int) seqno - (int) rtp->lastrxseqno - 1;
-		/* RTP sequence numbers are consecutive. Have we lost a packet? */
-		if (lostpackets && option_debug > 2) {
-			ast_log(LOG_DEBUG, "**** Packet loss detected - # %d. Current Seqno %-6.6u\n", lostpackets, seqno);
-		}
-		if (ast_test_flag(rtp, FLAG_POORMANSPLC)  && rtp->plcbuf != NULL) {
-			int i;
-			rtp->lastrxseqno++;
-			/* Fix the seqno in the frame */
-			rtp->plcbuf->seqno = rtp->lastrxseqno;
-			/* OEJ:: Fix timestamp */
-			;rtp->lastrxts = timestamp;
-			for (i = 0; i < lostpackets; i++) {
-				AST_LIST_INSERT_TAIL(&frames, ast_frdup(rtp->plcbuf), frame_list);
-				ast_log(LOG_DEBUG, "**** Inserting buffer frame %d. \n", i + 1);
+		if (lostpackets > MAX_MISORDER) {
+			/* We have a new seqno sequence and will just have to live with it */
+			lostpackets = 0;
+		}
+		if (seqno < rtp->lastrxseqno && (rtp->lastrxseqno - seqno) > MAX_MISORDER) {
+			/* We have a new seqno that is much lower than the previous one. */
+			/* The difference is bigger than normal jitter, so assume a new 
+			   seqno series */
+			lostpackets = 0;
+			not_jitter = 1;
+		}
+
+		if (!mark) {
+			/* If we have a marker bit set, the SSRC and the SEQNO have changed and
+			   we can't compare with the previous one. Just go ahead and wait for
+			   the next packet 
+			 */
+			if (ast_test_flag(rtp, FLAG_POORMANSPLC) && seqno < rtp->lastrxseqno && not_jitter == 0)  {
+				/* This is a latecomer that we've already replaced. A jitter buffer would have handled this
+			   	properly, but in many cases we can't afford a jitterbuffer and will have to live
+			   	with the face that the poor man's PLC already has replaced this frame and we can't
+			   	insert it AGAIN, because that would cause negative skew.
+			   	Henry, just ignore this late visitor. Thank you.
+				*/
+				if (rtp_debug_test_addr(&sin)) {
+					ast_verbose("Ignoring RTP from       %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u) - jitter?\n",
+						ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
+				}
+				return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
+			}
+		} 
+
+		if (lostpackets) {
+			if(option_debug > 2) {
+				ast_log(LOG_DEBUG, "**** Packet loss detected - # %d. Current Seqno %-6.6u\n", lostpackets, seqno);
+			}
+			if (ast_test_flag(rtp, FLAG_POORMANSPLC)  && rtp->plcbuf != NULL) {
+				int i;
+				for (i = 0; i < lostpackets && i < plcmax; i++) {
+					rtp->lastrxseqno++;
+					/* Fix the seqno in the frame */
+					rtp->plcbuf->seqno = rtp->lastrxseqno;
+					rtp->plcbuf->ts += rtp->plcbuf->len;
+
+					AST_LIST_INSERT_TAIL(&frames, ast_frdup(rtp->plcbuf), frame_list);
+					if (option_debug > 2) {
+						ast_log(LOG_DEBUG, "**** Inserting buffer frame %d. \n", i + 1);
+					}
+				}
+			} else {
+				if (ast_test_flag(rtp, FLAG_POORMANSPLC)  &&  option_debug > 2 && rtp->plcbuf == NULL) {
+					ast_log(LOG_DEBUG, " *** Not copying frame from PLCbuf, since it's empty \n");
+				}
 			}
 		}
 	}
@@ -1498,6 +1538,10 @@
 			ast_frame_free(rtp->plcbuf, 0);
 		}
 		rtp->plcbuf = ast_frdup(&rtp->f);
+	} else {
+		if (option_debug > 1 && lostpackets) {
+			ast_log(LOG_DEBUG, " *** Not copying frame into plcbuf PLC=%s\n", ast_test_flag(rtp, FLAG_POORMANSPLC) ? "On" : "Off");
+		}
 	}
 
 	AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
@@ -2064,11 +2108,9 @@
 	rtp->us.sin_family = AF_INET;
 	rtp->ssrc = ast_random();
 	rtp->seqno = ast_random() & 0xffff;
+	rtp->lastrxseqno = 0;
 	ast_set_flag(rtp, FLAG_HAS_DTMF);
 	rtp->plcbuf = NULL;
-	if (poormansplc) {
-		ast_set_flag(rtp, FLAG_POORMANSPLC);
-	}
 
 	return;
 }
@@ -2861,11 +2903,13 @@
 	if (donthidepacketloss && rtp->prev_frame_seqno > 0 && f->seqno && f->seqno != (rtp->prev_frame_seqno + 1)) {
 		/* We have incoming packet loss and need to signal that outbound. */
 		unsigned int loss = f->seqno - rtp->prev_frame_seqno - 1;
-		if (option_debug > 2) {
-			ast_log(LOG_DEBUG, "**** Incoming packet loss, letting it through: %u packets\n", loss);
-		}
-		/* Jump ahead, let the packet loss go straight through */
-		rtp->seqno += loss;
+		if (f->seqno > rtp->prev_frame_seqno) {
+			if (option_debug > 2) {
+				ast_log(LOG_DEBUG, "**** Incoming packet loss, letting it through: %u packets\n", loss);
+			}
+			/* Jump ahead, let the packet loss go straight through */
+			rtp->seqno += loss;
+		}
 	}
 
 	ms = calc_txstamp(rtp, &f->delivery);
@@ -4035,8 +4079,8 @@
 	struct ast_config *cfg;
 	const char *s;
 
-	poormansplc = 0;
 	donthidepacketloss = 0;
+	plcmax = DEFAULT_PLCMAX;
 	rtpstart = 5000;
 	rtpend = 31000;
 	dtmftimeout = DEFAULT_DTMF_TIMEOUT;
@@ -4076,10 +4120,16 @@
 				ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
 #endif
 		}
+		if ((s = ast_variable_retrieve(cfg, "general", "plcmax"))) {
+			plcmax = atoi(s);
+			if (option_debug > 1) {
+				ast_log(LOG_DEBUG, "PLCmax: Maximum number of injected RTP packets in one operation  %d\n", plcmax);
+			}
+		}
 		if ((s = ast_variable_retrieve(cfg, "general", "donthidepacketloss"))) {
 			donthidepacketloss = ast_true(s);
 			if (option_debug > 1) {
-				ast_log(LOG_DEBUG, "*** Hiding packet loss on outbound RTP stream?  %s\n", donthidepacketloss ? "on" : "off" );
+				ast_log(LOG_DEBUG, "Hiding packet loss on outbound RTP stream?  %s\n", donthidepacketloss ? "on" : "off" );
 			}
 		}
 		if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {




More information about the asterisk-commits mailing list