Index: /pjproject/trunk/pjmedia/include/pjmedia/rtcp.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/rtcp.h	(revision 426)
+++ /pjproject/trunk/pjmedia/include/pjmedia/rtcp.h	(revision 427)
@@ -71,7 +71,7 @@
 #else
     pj_uint32_t	    fract_lost:8;   /**< Fraction lost.			*/
-    pj_uint32_t	    total_lost_0:8; /**< Total lost, bit 0-7.		*/
+    pj_uint32_t	    total_lost_2:8; /**< Total lost, bit 0-7.		*/
     pj_uint32_t	    total_lost_1:8; /**< Total lost, bit 8-15.		*/
-    pj_uint32_t	    total_lost_2:8; /**< Total lost, bit 16-23.		*/
+    pj_uint32_t	    total_lost_0:8; /**< Total lost, bit 16-23.		*/
 #endif	
     pj_uint32_t	    last_seq;	    /**< Last sequence number.		*/
@@ -112,5 +112,7 @@
 
 /**
- * RTCP packet.
+ * This structure declares default RTCP packet (SR) that is sent by pjmedia.
+ * Incoming RTCP packet may have different format, and must be parsed
+ * manually by application.
  */
 struct pjmedia_rtcp_pkt
Index: /pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 426)
+++ /pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 427)
@@ -51,5 +51,5 @@
 {
 /* Seconds between 1900-01-01 to 1970-01-01 */
-#define NTP_DIFF    ((70 * 365 + 17) * 86400UL)
+#define JAN_1970  (2208988800UL)
     pj_timestamp ts;
     pj_status_t status;
@@ -59,5 +59,5 @@
     /* Fill up the high 32bit part */
     ntp->hi = (pj_uint32_t)((ts.u64 - sess->ts_base.u64) / sess->ts_freq.u64)
-	      + sess->tv_base.sec + NTP_DIFF;
+	      + sess->tv_base.sec + JAN_1970;
 
     /* Calculate seconds fractions */
@@ -95,5 +95,5 @@
 	pj_gettimeofday(&elapsed);
 
-	ts_time.sec = ntp->hi - sess->tv_base.sec - NTP_DIFF;
+	ts_time.sec = ntp->hi - sess->tv_base.sec - JAN_1970;
 	ts_time.msec = (long)(ntp->lo * 1000.0 / 0xFFFFFFFF);
 
@@ -114,5 +114,5 @@
 
 
-	    ntp->hi = elapsed.sec + sess->tv_base.sec + NTP_DIFF;
+	    ntp->hi = elapsed.sec + sess->tv_base.sec + JAN_1970;
 	    ntp->lo = (elapsed.msec * 65536 / 1000) << 16;
 	}
@@ -217,4 +217,7 @@
     }
 
+    /* Only mark "good" packets */
+    ++sess->received;
+
     /* Calculate loss periods. */
     if (seq_st.diff > 1) {
@@ -224,4 +227,10 @@
 	period = count * sess->pkt_size * 1000 / sess->clock_rate;
 	period *= 1000;
+
+	/* Update packet lost. 
+	 * The packet lost number will also be updated when we're sending
+	 * outbound RTCP RR.
+	 */
+	sess->stat.rx.loss += (seq_st.diff - 1);
 
 	/* Update loss period stat */
@@ -241,8 +250,4 @@
 
 
-    /* Only mark "good" packets */
-    ++sess->received;
-
-
     /*
      * Calculate jitter only when sequence is good (see RFC 3550 section A.8)
@@ -304,32 +309,51 @@
 				   pj_size_t size)
 {
-    const struct pjmedia_rtcp_pkt *rtcp = pkt;
+    const pjmedia_rtcp_common *common = pkt;
+    const pjmedia_rtcp_rr *rr = NULL;
+    const pjmedia_rtcp_sr *sr = NULL;
     pj_uint32_t last_loss, jitter_samp, jitter;
 
-    /* Must at least contain SR */
-    pj_assert(size >= sizeof(pjmedia_rtcp_common)+sizeof(pjmedia_rtcp_sr));
-
-    /* Save LSR from NTP timestamp of RTCP packet */
-    sess->rx_lsr = ((pj_ntohl(rtcp->sr.ntp_sec) & 0x0000FFFF) << 16) | 
-		   ((pj_ntohl(rtcp->sr.ntp_frac) >> 16) & 0xFFFF);
-
-    /* Calculate SR arrival time for DLSR */
-    pj_get_timestamp(&sess->rx_lsr_time);
-
-    TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p", 
-	    sess->rx_lsr,
-	    (pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64)));
-
-    /* Nothing more to do if this is an SR only RTCP packet */
-    if (size < sizeof(pjmedia_rtcp_pkt))
+    /* Parse RTCP */
+    if (common->pt == RTCP_SR) {
+	sr = (pjmedia_rtcp_sr*) (((char*)pkt) + sizeof(pjmedia_rtcp_common));
+	if (common->count > 0 && size >= (sizeof(pjmedia_rtcp_pkt))) {
+	    rr = (pjmedia_rtcp_rr*)(((char*)pkt) + (sizeof(pjmedia_rtcp_common)
+				    + sizeof(pjmedia_rtcp_sr)));
+	}
+    } else if (common->pt == RTCP_RR && common->count > 0)
+	rr = (pjmedia_rtcp_rr*)(((char*)pkt) +sizeof(pjmedia_rtcp_common) +4);
+
+
+    if (sr) {
+	/* Save LSR from NTP timestamp of RTCP packet */
+	sess->rx_lsr = ((pj_ntohl(sr->ntp_sec) & 0x0000FFFF) << 16) | 
+		       ((pj_ntohl(sr->ntp_frac) >> 16) & 0xFFFF);
+
+	/* Calculate SR arrival time for DLSR */
+	pj_get_timestamp(&sess->rx_lsr_time);
+
+	TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p", 
+		sess->rx_lsr,
+		(pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64)));
+    }
+
+
+    /* Nothing more to do if there's no RR packet */
+    if (rr == NULL)
 	return;
-	
+
 
     last_loss = sess->stat.tx.loss;
 
     /* Get packet loss */
-    sess->stat.tx.loss = (rtcp->rr.total_lost_2 << 16) +
-			 (rtcp->rr.total_lost_1 << 8) +
-			  rtcp->rr.total_lost_0;
+    sess->stat.tx.loss = (rr->total_lost_2 << 16) +
+			 (rr->total_lost_1 << 8) +
+			  rr->total_lost_0;
+
+    TRACE_((sess->name, "Rx RTCP RR: total_lost_2=%x, 1=%x, 0=%x, lost=%d", 
+	    (int)rr->total_lost_2,
+	    (int)rr->total_lost_1,
+	    (int)rr->total_lost_0,
+	    sess->stat.tx.loss));
     
     /* We can't calculate the exact loss period for TX, so just give the
@@ -360,5 +384,5 @@
 
     /* Get jitter value in usec */
-    jitter_samp = pj_ntohl(rtcp->rr.jitter);
+    jitter_samp = pj_ntohl(rr->jitter);
     /* Calculate jitter in usec, avoiding overflows */
     if (jitter_samp <= 4294)
@@ -383,5 +407,5 @@
 
     /* Can only calculate if LSR and DLSR is present in RR */
-    if (rtcp->rr.lsr && rtcp->rr.dlsr) {
+    if (rr->lsr && rr->dlsr) {
 	pj_uint32_t lsr, now, dlsr;
 	pj_uint64_t eedelay;
@@ -391,8 +415,8 @@
 	 * resolution 
 	 */
-	lsr = pj_ntohl(rtcp->rr.lsr);
+	lsr = pj_ntohl(rr->lsr);
 
 	/* DLSR is delay since LSR, also in 1/65536 resolution */
-	dlsr = pj_ntohl(rtcp->rr.dlsr);
+	dlsr = pj_ntohl(rr->dlsr);
 
 	/* Get current time, and convert to 1/65536 resolution */
@@ -425,15 +449,29 @@
 	    unsigned rtt = (pj_uint32_t)eedelay;
 	    
-	    TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt));
-
-	    if (rtt >= 1000000) {
-		pjmedia_rtcp_ntp_rec ntp2;
-		pj_thread_sleep(50);
-		pjmedia_rtcp_get_ntp_time(sess, &ntp2);
-		ntp2.lo = ntp2.lo;
+	    /* Check that eedelay value really makes sense. 
+	     * We allow up to 30 seconds RTT!
+	     */
+	    if (eedelay > 30 * 1000 * 1000UL) {
+
+		TRACE_((sess->name, "RTT not making any sense, ignored.."));
+		goto end_rtt_calc;
 	    }
 
 	    if (sess->stat.rtt_update_cnt == 0)
 		sess->stat.rtt.min = rtt;
+
+	    /* "Normalize" rtt value that is exceptionally high.
+	     * For such values, "normalize" the rtt to be three times
+	     * the average value.
+	     */
+	    if (rtt > (sess->stat.rtt.avg*3) && sess->stat.rtt_update_cnt!=0) {
+		unsigned orig_rtt = rtt;
+		rtt = sess->stat.rtt.avg*3;
+		PJ_LOG(5,(sess->name, 
+			  "RTT value %d usec is normalized to %d usec",
+			  orig_rtt, rtt));
+	    }
+	
+	    TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt));
 
 	    if (rtt < sess->stat.rtt.min && rtt)
@@ -458,4 +496,6 @@
 	}
     }
+
+end_rtt_calc:
 
     pj_gettimeofday(&sess->stat.tx.update);
@@ -508,4 +548,7 @@
     if (expected >= sess->received)
 	sess->stat.rx.loss = expected - sess->received;
+    else
+	sess->stat.rx.loss = 0;
+
     rtcp_pkt->rr.total_lost_2 = (sess->stat.rx.loss >> 16) & 0xFF;
     rtcp_pkt->rr.total_lost_1 = (sess->stat.rx.loss >> 8) & 0xFF;
