Index: pjproject/trunk/pjmedia/include/pjmedia/rtcp.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/rtcp.h	(revision 1443)
+++ pjproject/trunk/pjmedia/include/pjmedia/rtcp.h	(revision 1444)
@@ -59,5 +59,4 @@
 struct pjmedia_rtcp_sr
 {
-    pj_uint32_t	    ssrc;	    /**< SSRC identification.		*/
     pj_uint32_t	    ntp_sec;	    /**< NTP time, seconds part.	*/
     pj_uint32_t	    ntp_frac;	    /**< NTP time, fractions part.	*/
@@ -118,4 +117,5 @@
 #endif
     unsigned	    length:16;	/**< packet length          */
+    pj_uint32_t	    ssrc;	/**< SSRC identification    */
 };
 
@@ -130,15 +130,19 @@
  * manually by application.
  */
-struct pjmedia_rtcp_pkt
+typedef struct pjmedia_rtcp_sr_pkt
 {
     pjmedia_rtcp_common  common;	/**< Common header.	    */
     pjmedia_rtcp_sr	 sr;		/**< Sender report.	    */
     pjmedia_rtcp_rr	 rr;		/**< variable-length list   */
-};
-
-/**
- * @see pjmedia_rtcp_pkt
- */
-typedef struct pjmedia_rtcp_pkt pjmedia_rtcp_pkt;
+} pjmedia_rtcp_sr_pkt;
+
+/**
+ * This structure declares RTCP RR (Receiver Report) packet.
+ */
+typedef struct pjmedia_rtcp_rr_pkt
+{
+    pjmedia_rtcp_common  common;	/**< Common header.	    */
+    pjmedia_rtcp_rr	 rr;		/**< variable-length list   */
+} pjmedia_rtcp_rr_pkt;
 
 
@@ -251,5 +255,6 @@
 {
     char		   *name;	/**< Name identification.	    */
-    pjmedia_rtcp_pkt	    rtcp_pkt;	/**< Cached RTCP packet.	    */
+    pjmedia_rtcp_sr_pkt	    rtcp_sr_pkt;/**< Cached RTCP packet.	    */
+    pjmedia_rtcp_rr_pkt	    rtcp_rr_pkt;/**< Cached RTCP RR packet.	    */
     
     pjmedia_rtp_seq_session seq_ctrl;	/**< RTCP sequence number control.  */
@@ -364,5 +369,7 @@
 
 /**
- * Build a RTCP SR+RR packet to be transmitted to remote RTP peer.
+ * Build a RTCP packet to be transmitted to remote RTP peer. This will
+ * create RTCP Sender Report (SR) or Receiver Report (RR) depending on
+ * whether the endpoint has been transmitting RTP since the last interval.
  * Note that this function will reset the interval counters (such as
  * the ones to calculate fraction lost) in the session.
@@ -370,11 +377,10 @@
  * @param session   The RTCP session.
  * @param rtcp_pkt  Upon return, it will contain pointer to the 
- *		    RTCP packet.
+ *		    RTCP packet, which can be RTCP SR or RR.
  * @param len	    Upon return, it will indicate the size of 
  *		    the RTCP packet.
  */
 PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session, 
-				       pjmedia_rtcp_pkt **rtcp_pkt, 
-				       int *len);
+				       void **rtcp_pkt, int *len);
 
 
Index: pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 1443)
+++ pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 1444)
@@ -131,5 +131,5 @@
 			       pj_uint32_t ssrc)
 {
-    pjmedia_rtcp_pkt *rtcp_pkt = &sess->rtcp_pkt;
+    pjmedia_rtcp_sr_pkt *sr_pkt = &sess->rtcp_sr_pkt;
     pj_time_val now;
     
@@ -147,13 +147,17 @@
     sess->pkt_size = samples_per_frame;
 
-    /* Init common RTCP header */
-    rtcp_pkt->common.version = 2;
-    rtcp_pkt->common.count = 1;
-    rtcp_pkt->common.pt = RTCP_SR;
-    rtcp_pkt->common.length = pj_htons(12);
-    
-    /* Init SR */
-    rtcp_pkt->sr.ssrc = pj_htonl(ssrc);
-    
+    /* Init common RTCP SR header */
+    sr_pkt->common.version = 2;
+    sr_pkt->common.count = 1;
+    sr_pkt->common.pt = RTCP_SR;
+    sr_pkt->common.length = pj_htons(12);
+    sr_pkt->common.ssrc = pj_htonl(ssrc);
+    
+    /* Copy to RTCP RR header */
+    pj_memcpy(&sess->rtcp_rr_pkt.common, &sr_pkt->common, 
+	      sizeof(pjmedia_rtcp_common));
+    sess->rtcp_rr_pkt.common.pt = RTCP_RR;
+    sess->rtcp_rr_pkt.common.length = pj_htons(7);
+
     /* Get time and timestamp base and frequency */
     pj_gettimeofday(&now);
@@ -341,5 +345,5 @@
     if (common->pt == RTCP_SR) {
 	sr = (pjmedia_rtcp_sr*) (((char*)pkt) + sizeof(pjmedia_rtcp_common));
-	if (common->count > 0 && size >= (sizeof(pjmedia_rtcp_pkt))) {
+	if (common->count > 0 && size >= (sizeof(pjmedia_rtcp_sr_pkt))) {
 	    rr = (pjmedia_rtcp_rr*)(((char*)pkt) + (sizeof(pjmedia_rtcp_common)
 				    + sizeof(pjmedia_rtcp_sr)));
@@ -530,31 +534,71 @@
 
 PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess, 
-				     pjmedia_rtcp_pkt **ret_p_pkt, 
-				     int *len)
+				     void **ret_p_pkt, int *len)
 {
     pj_uint32_t expected, expected_interval, received_interval, lost_interval;
-    pjmedia_rtcp_pkt *rtcp_pkt = &sess->rtcp_pkt;
+    pjmedia_rtcp_common *common;
+    pjmedia_rtcp_sr *sr;
+    pjmedia_rtcp_rr *rr;
     pj_timestamp ts_now;
     pjmedia_rtcp_ntp_rec ntp;
-    
-    /* Packet count */
-    rtcp_pkt->sr.sender_pcount = pj_htonl(sess->stat.tx.pkt);
-
-    /* Octets count */
-    rtcp_pkt->sr.sender_bcount = pj_htonl(sess->stat.tx.bytes);
+
+    /* Get current NTP time. */
+    pj_get_timestamp(&ts_now);
+    pjmedia_rtcp_get_ntp_time(sess, &ntp);
+
+
+    /* See if we have transmitted RTP packets since last time we
+     * sent RTCP SR.
+     */
+    if (sess->stat.tx.pkt != pj_ntohl(sess->rtcp_sr_pkt.sr.sender_pcount)) {
+
+	/* So we should send RTCP SR */
+	*ret_p_pkt = (void*) &sess->rtcp_sr_pkt;
+	*len = sizeof(pjmedia_rtcp_sr_pkt);
+	common = &sess->rtcp_sr_pkt.common;
+	rr = &sess->rtcp_sr_pkt.rr;
+	sr = &sess->rtcp_sr_pkt.sr;
+
+	/* Update packet count */
+	sr->sender_pcount = pj_htonl(sess->stat.tx.pkt);
+
+	/* Update octets count */
+	sr->sender_bcount = pj_htonl(sess->stat.tx.bytes);
+
+	/* Fill in NTP timestamp in SR. */
+	sr->ntp_sec = pj_htonl(ntp.hi);
+	sr->ntp_frac = pj_htonl(ntp.lo);
+
+	TRACE_((sess->name, "TX RTCP SR: ntp_ts=%p", 
+			   ((ntp.hi & 0xFFFF) << 16) + ((ntp.lo & 0xFFFF0000) 
+				>> 16)));
+
+
+    } else {
+	/* We should send RTCP RR then */
+	*ret_p_pkt = (void*) &sess->rtcp_rr_pkt;
+	*len = sizeof(pjmedia_rtcp_rr_pkt);
+	common = &sess->rtcp_rr_pkt.common;
+	rr = &sess->rtcp_rr_pkt.rr;
+	sr = NULL;
+    }
     
     /* SSRC and last_seq */
-    rtcp_pkt->rr.ssrc = pj_htonl(sess->peer_ssrc);
-    rtcp_pkt->rr.last_seq = (sess->seq_ctrl.cycles & 0xFFFF0000L);
-    rtcp_pkt->rr.last_seq += sess->seq_ctrl.max_seq;
-    rtcp_pkt->rr.last_seq = pj_htonl(rtcp_pkt->rr.last_seq);
+    rr->ssrc = pj_htonl(sess->peer_ssrc);
+    rr->last_seq = (sess->seq_ctrl.cycles & 0xFFFF0000L);
+    /* Since this is an "+=" operation, make sure we update last_seq on
+     * both RR and SR.
+     */
+    sess->rtcp_sr_pkt.rr.last_seq += sess->seq_ctrl.max_seq;
+    sess->rtcp_rr_pkt.rr.last_seq += sess->seq_ctrl.max_seq;
+    rr->last_seq = pj_htonl(rr->last_seq);
 
 
     /* Jitter */
-    rtcp_pkt->rr.jitter = pj_htonl(sess->jitter >> 4);
+    rr->jitter = pj_htonl(sess->jitter >> 4);
     
     
     /* Total lost. */
-    expected = pj_ntohl(rtcp_pkt->rr.last_seq) - sess->seq_ctrl.base_seq;
+    expected = pj_ntohl(rr->last_seq) - sess->seq_ctrl.base_seq;
 
     /* This is bug: total lost already calculated on each incoming RTP!
@@ -565,7 +609,7 @@
     */
 
-    rtcp_pkt->rr.total_lost_2 = (sess->stat.rx.loss >> 16) & 0xFF;
-    rtcp_pkt->rr.total_lost_1 = (sess->stat.rx.loss >> 8) & 0xFF;
-    rtcp_pkt->rr.total_lost_0 = (sess->stat.rx.loss & 0xFF);
+    rr->total_lost_2 = (sess->stat.rx.loss >> 16) & 0xFF;
+    rr->total_lost_1 = (sess->stat.rx.loss >> 8) & 0xFF;
+    rr->total_lost_0 = (sess->stat.rx.loss & 0xFF);
 
     /* Fraction lost calculation */
@@ -579,24 +623,12 @@
     
     if (expected_interval==0 || lost_interval == 0) {
-	rtcp_pkt->rr.fract_lost = 0;
+	rr->fract_lost = 0;
     } else {
-	rtcp_pkt->rr.fract_lost = (lost_interval << 8) / expected_interval;
-    }
-    
-    /* Get current NTP time. */
-    pj_get_timestamp(&ts_now);
-    pjmedia_rtcp_get_ntp_time(sess, &ntp);
-    
-    /* Fill in NTP timestamp in SR. */
-    rtcp_pkt->sr.ntp_sec = pj_htonl(ntp.hi);
-    rtcp_pkt->sr.ntp_frac = pj_htonl(ntp.lo);
-
-    TRACE_((sess->name, "TX RTCP SR: ntp_ts=%p", 
-		       ((ntp.hi & 0xFFFF) << 16) + ((ntp.lo & 0xFFFF0000) 
-			    >> 16)));
-
+	rr->fract_lost = (lost_interval << 8) / expected_interval;
+    }
+    
     if (sess->rx_lsr_time.u64 == 0 || sess->rx_lsr == 0) {
-	rtcp_pkt->rr.lsr = 0;
-	rtcp_pkt->rr.dlsr = 0;
+	rr->lsr = 0;
+	rr->dlsr = 0;
     } else {
 	pj_timestamp ts;
@@ -611,5 +643,5 @@
 	   LSR is the middle 32bit of the last SR NTP time received.
 	 */
-	rtcp_pkt->rr.lsr = pj_htonl(lsr);
+	rr->lsr = pj_htonl(lsr);
 	
 	/* Fill in DLSR.
@@ -623,5 +655,5 @@
 	/* Get DLSR */
 	dlsr = (pj_uint32_t)(ts.u64 - lsr_time);
-	rtcp_pkt->rr.dlsr = pj_htonl(dlsr);
+	rr->dlsr = pj_htonl(dlsr);
 
 	TRACE_((sess->name,"Tx RTCP RR: lsr=%p, lsr_time=%p, now=%p, dlsr=%p"
@@ -638,9 +670,4 @@
     pj_gettimeofday(&sess->stat.rx.update);
     sess->stat.rx.update_cnt++;
-
-
-    /* Return pointer. */
-    *ret_p_pkt = rtcp_pkt;
-    *len = sizeof(pjmedia_rtcp_pkt);
 }
 
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 1443)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 1444)
@@ -440,5 +440,5 @@
     } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
 	
-	pjmedia_rtcp_pkt *rtcp_pkt;
+	void *rtcp_pkt;
 	int len;
 
Index: pjproject/trunk/pjsip-apps/src/samples/siprtp.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/siprtp.c	(revision 1443)
+++ pjproject/trunk/pjsip-apps/src/samples/siprtp.c	(revision 1444)
@@ -1343,5 +1343,5 @@
 	     * Time to send RTCP packet.
 	     */
-	    pjmedia_rtcp_pkt *rtcp_pkt;
+	    void *rtcp_pkt;
 	    int rtcp_len;
 	    pj_ssize_t size;
