--- rtp_back.c	2007-09-03 01:18:12.858434896 -0400
+++ rtp.c	2007-09-03 01:18:08.250135464 -0400
@@ -42,6 +42,7 @@
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
+#include <math.h> 
 
 #include "asterisk/rtp.h"
 #include "asterisk/frame.h"
@@ -224,10 +225,36 @@
 	unsigned int reported_jitter;	/*!< The contents of their last jitter entry in the RR */
 	unsigned int reported_lost;	/*!< Reported lost packets in their RR */
 	char quality[AST_MAX_USER_FIELD];
+	char quality_total[AST_MAX_USER_FIELD];
+
+	double reported_maxjitter;
+	double reported_minjitter;
+	double reported_normdev_jitter;
+	double reported_stdev_jitter;
+	unsigned int reported_jitter_count;
+
+	double reported_maxlost;
+	double reported_minlost;
+	double reported_normdev_lost;
+	double reported_stdev_lost;
+
+	double rxlost;
+	double maxrxlost;
+	double minrxlost;
+	double normdev_rxlost;
+	double stdev_rxlost;
+	unsigned int rxlost_count;
+
 	double maxrxjitter;
 	double minrxjitter;
+	double normdev_rxjitter;
+	double stdev_rxjitter;
+	unsigned int rxjitter_count;
 	double maxrtt;
 	double minrtt;
+	double normdevrtt;
+	double stdevrtt;
+	unsigned int rtt_count;
 	int sendfur;
 };
 
@@ -839,7 +866,12 @@
 	unsigned int lsw;
 	unsigned int comp;
 	struct ast_frame *f = &ast_null_frame;
-	
+	double reported_jitter;
+	double reported_normdev_jitter_current;
+	double normdevrtt_current;
+	double reported_lost;
+	double reported_normdev_lost_current;
+
 	if (!rtp || !rtp->rtcp)
 		return &ast_null_frame;
 
@@ -934,14 +966,21 @@
 				}
 				rtt = rtt / 1000.;
 				rttsec = rtt / 1000.;
+				rtp->rtcp->rtt = rttsec;
+
 
 				if (comp - dlsr >= lsr) {
 					rtp->rtcp->accumulated_transit += rttsec;
-					rtp->rtcp->rtt = rttsec;
+					if(rtp->rtcp->rtt_count==0) rtp->rtcp->minrtt=rttsec;
 					if (rtp->rtcp->maxrtt<rttsec)
 						rtp->rtcp->maxrtt = rttsec;
 					if (rtp->rtcp->minrtt>rttsec)
 						rtp->rtcp->minrtt = rttsec;
+					normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
+					rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
+					rtp->rtcp->normdevrtt = normdevrtt_current;
+					rtp->rtcp->rtt_count++;
+			
 				} else if (rtcp_debug_test_addr(&sin)) {
 					ast_verbose("Internal RTCP NTP clock skew detected: "
 							   "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
@@ -953,7 +992,29 @@
 			}
 
 			rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
+			reported_jitter = (double) rtp->rtcp->reported_jitter;
+			if(rtp->rtcp->reported_jitter_count==0) rtp->rtcp->reported_minjitter=reported_jitter;
+			if(reported_jitter < rtp->rtcp->reported_minjitter) 
+				rtp->rtcp->reported_minjitter=reported_jitter;
+			if(reported_jitter > rtp->rtcp->reported_maxjitter) 
+				rtp->rtcp->reported_maxjitter=reported_jitter;
+			reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
+			rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
+			rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
+
 			rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
+			reported_lost = (double) rtp->rtcp->reported_lost;
+			//using same counter as for jitter
+			if(rtp->rtcp->reported_jitter_count==0) rtp->rtcp->reported_minlost=reported_lost;
+			if(reported_lost < rtp->rtcp->reported_minlost) 
+				rtp->rtcp->reported_minlost=reported_lost;
+			if(reported_lost > rtp->rtcp->reported_maxlost) 
+				rtp->rtcp->reported_maxlost=reported_lost;
+			reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
+			rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
+			rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
+			rtp->rtcp->reported_jitter_count++;
+
 			if (rtcp_debug_test_addr(&sin)) {
 				ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
 				ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
@@ -1004,7 +1065,7 @@
 	double d;
 	double dtv;
 	double prog;
-	
+	double normdev_rxjitter_current;
 	if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
 		gettimeofday(&rtp->rxcore, NULL);
 		rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
@@ -1040,8 +1101,30 @@
 	rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
 	if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
 		rtp->rtcp->maxrxjitter = rtp->rxjitter;
+	if(rtp->rtcp->rxjitter_count == 1)rtp->rtcp->minrxjitter = rtp->rxjitter;
 	if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
 		rtp->rtcp->minrxjitter = rtp->rxjitter;
+		
+	normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
+	rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
+
+	rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
+	rtp->rtcp->rxjitter_count++;
+}
+
+/*! \brief Calculate normal deviation */
+double normdev_compute(double normdev,double sample,unsigned int sample_count)
+{
+	return (normdev*sample_count+sample)/(sample_count+1);
+}
+
+double stddev_compute(double stddev,double sample,double normdev,double normdev_curent,unsigned int sample_count)
+{
+	//for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
+//	return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
+	//we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
+	//optimized formula
+	return  (sample_count*stddev + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1);
 }
 
 /*! \brief Perform a Packet2Packet RTP write */
@@ -2047,6 +2130,33 @@
 	rtp->rxseqno = 0;
 }
 
+
+
+char *ast_rtp_get_quality_total(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
+{
+	/*
+	*ssrc          our ssrc
+	*themssrc      their ssrc
+	*lp            lost packets
+	*rxjitter      our calculated jitter(rx)
+	*rxcount       no. received packets
+	*txjitter      reported jitter of the other end
+	*txcount       transmitted packets
+	*rlp           remote lost packets
+	*rtt           round trip time
+	*/
+
+	snprintf(rtp->rtcp->quality_total, sizeof(rtp->rtcp->quality_total), "minrxjitter=%f;maxrxjitter=%f;avgrxjitter=%f;stdevrxjitter=%f;minrxlost=%f;maxrxlost=%f;avgrxlostr=%f;stdevrxlost=%f;reported_minjitter=%f;reported_maxjitter=%f;reported_avgjitter=%f;reported_stdevjitter=%f;reported_minlost=%f;reported_maxlost=%f;reported_avglost=%f;reported_stdevlost=%f;minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
+		rtp->rtcp->minrxjitter,rtp->rtcp->maxrxjitter,rtp->rtcp->normdev_rxjitter,sqrt(rtp->rtcp->stdev_rxjitter),
+		rtp->rtcp->minrxlost,rtp->rtcp->maxrxlost,rtp->rtcp->normdev_rxlost,sqrt(rtp->rtcp->stdev_rxlost),
+		rtp->rtcp->reported_minjitter,rtp->rtcp->reported_maxjitter,rtp->rtcp->reported_normdev_jitter,sqrt(rtp->rtcp->reported_stdev_jitter),
+		rtp->rtcp->reported_minlost,rtp->rtcp->reported_maxlost,rtp->rtcp->reported_normdev_lost,sqrt(rtp->rtcp->reported_stdev_lost),
+		rtp->rtcp->minrtt,rtp->rtcp->maxrtt,rtp->rtcp->normdevrtt,sqrt(rtp->rtcp->stdevrtt)
+		);
+	ast_verbose("AUDIORTPQOSTOTAL=%s\n",rtp->rtcp->quality_total);
+	return rtp->rtcp->quality_total;
+}
+
 char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
 {
 	/*
@@ -2073,7 +2183,6 @@
 		qual->rtt = rtp->rtcp->rtt;
 	}
 	snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt);
-	
 	return rtp->rtcp->quality;
 }
 
@@ -2325,6 +2434,7 @@
 	int fraction;
 	struct timeval dlsr;
 	char bdata[512];
+	double rxlost_current;
 
 	/* Commented condition is always not NULL if rtp->rtcp is not NULL */
 	if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
@@ -2359,6 +2469,24 @@
 	received_interval = rtp->rxcount - rtp->rtcp->received_prior;
 	rtp->rtcp->received_prior = rtp->rxcount;
 	lost_interval = expected_interval - received_interval;
+
+
+	if(lost_interval<=0)
+		rtp->rtcp->rxlost = 0;
+	else
+		rtp->rtcp->rxlost = rtp->rtcp->rxlost;
+	if(rtp->rtcp->rxlost_count == 0) 
+		rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
+	if(lost_interval < rtp->rtcp->minrxlost)
+		rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
+	if(lost_interval > rtp->rtcp->maxrxlost)
+		rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
+
+	rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
+	rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
+	rtp->rtcp->normdev_rxlost = rxlost_current;
+	rtp->rtcp->rxlost_count++;
+
 	if (expected_interval == 0 || lost_interval <= 0)
 		fraction = 0;
 	else
