[Asterisk-cvs] asterisk/channels chan_iax2.c,1.156,1.157

markster at lists.digium.com markster at lists.digium.com
Tue Jun 22 14:04:44 CDT 2004


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv21284/channels

Modified Files:
	chan_iax2.c 
Log Message:
Merge Steven Davie's IAX2 jitter buffer enhancements


Index: chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.156
retrieving revision 1.157
diff -u -d -r1.156 -r1.157
--- chan_iax2.c	22 Jun 2004 17:42:13 -0000	1.156
+++ chan_iax2.c	22 Jun 2004 17:50:39 -0000	1.157
@@ -318,6 +318,8 @@
 #define DEFAULT_TRUNKDATA	640 * 10		/* 40ms, uncompressed linear * 10 channels */
 #define MAX_TRUNKDATA		640 * 200		/* 40ms, uncompressed linear * 200 channels */
 
+#define MAX_TIMESTAMP_SKEW	640
+
 /* If we have more than this much excess real jitter buffer, srhink it. */
 static int max_jitter_buffer = MAX_JITTER_BUFFER;
 
@@ -1113,17 +1115,8 @@
 	  the IAX thread with the iaxsl lock held. */
 	struct iax_frame *fr = data;
 	fr->retrans = -1;
-	if (iaxs[fr->callno] && !iaxs[fr->callno]->alreadygone) {
-		if (fr->af.frametype == AST_FRAME_IAX && 
-		    fr->af.subclass == IAX_COMMAND_LAGRQ) {
-			/* send a lag response to a lag request that has
-			 * gone through our jitter buffer */
-				fr->af.subclass = IAX_COMMAND_LAGRP;
-				iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0);
-		} else {
-			iax2_queue_frame(fr->callno, &fr->af);
-		}
-	}
+	if (iaxs[fr->callno] && !iaxs[fr->callno]->alreadygone)
+		iax2_queue_frame(fr->callno, &fr->af);
 	/* Free our iax frame */
 	iax2_frame_free(fr);
 	/* And don't run again */
@@ -1606,9 +1599,11 @@
 	int ms,x;
 	int drops[MEMORY_SIZE];
 	int min, max=0, maxone=0,y,z, match;
+
 	/* ms is a measure of the "lateness" of the packet relative to the first
-	   packet we received, which always has a lateness of 1.  Called by
-	   IAX thread, with iaxsl lock held. */
+	   packet we received.  Understand that "ms" can easily be -ve if lag improves
+	   since call start.
+	   Called by IAX thread, with iaxsl lock held. */
 	ms = calc_rxstamp(iaxs[fr->callno]) - fr->ts;
 
 	if (ms > 32767) {
@@ -1626,6 +1621,7 @@
 		fr->ts -= 65536;
 	}
 
+	/* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
 	fr->af.delivery.tv_sec = iaxs[fr->callno]->rxcore.tv_sec;
 	fr->af.delivery.tv_usec = iaxs[fr->callno]->rxcore.tv_usec;
 	fr->af.delivery.tv_sec += fr->ts / 1000;
@@ -1635,7 +1631,6 @@
 		fr->af.delivery.tv_sec += 1;
 	}
 
-	
 	/* Rotate our history queue of "lateness".  Don't worry about those initial
 	   zeros because the first entry will always be zero */
 	if (updatehistory) {
@@ -1708,10 +1703,16 @@
 	if (max > iaxs[fr->callno]->jitterbuffer)
 		iaxs[fr->callno]->jitterbuffer = max 
 			/* + ((float)iaxs[fr->callno]->jitter) * 0.1 */;
-		
+
+	/* If the caller just wanted us to update, return now */
+	if (!reallydeliver)
+		return 0;
 
 	if (option_debug)
-		ast_log(LOG_DEBUG, "min = %d, max = %d, jb = %d, lateness = %d\n", min, max, iaxs[fr->callno]->jitterbuffer, ms);
+		/* Log jitter stats for possible offline analysis */
+		ast_log(LOG_DEBUG, "Jitter: call=%d ts=%d: min=%d max=%d jb=%d; lateness=%d; jitter=%d historic=%d\n",
+					fr->callno, fr->ts, min, max, iaxs[fr->callno]->jitterbuffer, ms,
+					iaxs[fr->callno]->jitter, iaxs[fr->callno]->historicjitter);
 	
 	/* Subtract the lateness from our jitter buffer to know how long to wait
 	   before sending our packet.  */
@@ -1720,25 +1721,21 @@
 	if (!use_jitterbuffer)
 		ms = 0;
 
-	/* If the caller just wanted us to update, return now */
-	if (!reallydeliver)
-		return 0;
-		
 	if (ms < 1) {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Calculated ms is %d\n", ms);
 		/* Don't deliver it more than 4 ms late */
 		if ((ms > -4) || (fr->af.frametype != AST_FRAME_VOICE)) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "schedule_delivery: Delivering immediately (Calculated ms is %d)\n", ms);
 			__do_deliver(fr);
 		} else {
 			if (option_debug)
-				ast_log(LOG_DEBUG, "Dropping voice packet since %d ms is, too old\n", ms);
+				ast_log(LOG_DEBUG, "schedule_delivery: Dropping voice packet since %d ms is too old\n", ms);
 			/* Free our iax frame */
 			iax2_frame_free(fr);
 		}
 	} else {
 		if (option_debug)
-			ast_log(LOG_DEBUG, "Scheduling delivery in %d ms\n", ms);
+			ast_log(LOG_DEBUG, "schedule_delivery: Scheduling delivery in %d ms\n", ms);
 		fr->retrans = ast_sched_add(sched, ms, do_deliver, fr);
 	}
 	return 0;
@@ -2588,7 +2585,7 @@
 	ms = (tv->tv_sec - tpeer->txtrunktime.tv_sec) * 1000 + (tv->tv_usec - tpeer->txtrunktime.tv_usec) / 1000;
 	/* Predict from last value */
 	pred = tpeer->lastsent + sampms;
-	if (abs(ms - pred) < 640)
+	if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
 		ms = pred;
 	
 	/* We never send the same timestamp twice, so fudge a little if we must */
@@ -2621,6 +2618,13 @@
 	int voice = 0;
 	int genuine = 0;
 	struct timeval *delivery = NULL;
+
+	/* What sort of frame do we have?: voice is self-explanatory
+	   "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
+	   non-genuine frames are CONTROL frames [ringing etc], DTMF
+	   The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
+	   the others need a timestamp slaved to the voice frames so that they go in sequence
+	*/
 	if (f) {
 		if (f->frametype == AST_FRAME_VOICE) {
 			voice = 1;
@@ -2637,6 +2641,7 @@
 	/* If the timestamp is specified, just send it as is */
 	if (ts)
 		return ts;
+	/* If we have a time that the frame arrived, always use it to make our timestamp */
 	if (delivery && (delivery->tv_sec || delivery->tv_usec)) {
 		ms = (delivery->tv_sec - p->offset.tv_sec) * 1000 + (delivery->tv_usec - p->offset.tv_usec) / 1000;
 	} else {
@@ -2646,19 +2651,24 @@
 			ms = 0;
 		if (voice) {
 			/* On a voice frame, use predicted values if appropriate */
-			if (abs(ms - p->nextpred) <= 640) {
-				if (!p->nextpred)
-					p->nextpred = f->samples / 8;
+			if (abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
+				if (!p->nextpred) {
+					p->nextpred = ms; /*f->samples / 8;*/
+					if (p->nextpred <= p->lastsent)
+						p->nextpred = p->lastsent + 3;
+				}
 				ms = p->nextpred;
 			} else
 				p->nextpred = ms;
 		} else {
-			/* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinkign) if appropriate unless
+			/* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
 			   it's a genuine frame */
 			if (genuine) {
+				/* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
 				if (ms <= p->lastsent)
 					ms = p->lastsent + 3;
-			} else if (abs(ms - p->lastsent) <= 640) {
+			} else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
+				/* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
 				ms = p->lastsent + 3;
 			}
 		}
@@ -4955,10 +4965,8 @@
 			/* Handle the IAX pseudo frame itself */
 			if (option_debug)
 				ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass);
-			/* Go through the motions of delivering the packet without actually doing so,
-			   unless this is a lag request since it will be done for real */
-			if (f.subclass != IAX_COMMAND_LAGRQ)
-				schedule_delivery(&fr, 0, updatehistory);
+			/* Go through the motions of delivering the packet without actually doing so */
+			schedule_delivery(&fr, 0, updatehistory);
 			switch(f.subclass) {
 			case IAX_COMMAND_ACK:
 				/* Do nothing */
@@ -5248,15 +5256,18 @@
 					f.samples = 0;
 					iax_frame_wrap(&fr, &f);
 					if(f.subclass == IAX_COMMAND_LAGRQ) {
-						/* A little strange -- We have to actually go through the motions of
-						delivering the packet.  In the very last step, it will be properly
-						handled by do_deliver */
-					    schedule_delivery(iaxfrdup2(&fr), 1, updatehistory);
+					    /* Received a LAGRQ - echo back a LAGRP */
+					    fr.af.subclass = IAX_COMMAND_LAGRP;
+					    iax2_send(iaxs[fr.callno], &fr.af, fr.ts, -1, 0, 0, 0);
 					} else {
+					    /* Received LAGRP in response to our LAGRQ */
 					    unsigned int ts;
 					    /* This is a reply we've been given, actually measure the difference */
 					    ts = calc_timestamp(iaxs[fr.callno], 0, &fr.af);
 					    iaxs[fr.callno]->lag = ts - fr.ts;
+					    if (option_debug)
+						ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n",
+								inet_ntoa(iaxs[fr.callno]->addr.sin_addr), iaxs[fr.callno]->lag);
 					}
 #ifdef BRIDGE_OPTIMIZATION
 				}




More information about the svn-commits mailing list