summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-09-20 11:30:59 +0000
committerBenny Prijono <bennylp@teluu.com>2007-09-20 11:30:59 +0000
commit6c3a7b9adc1a3cb3bf7d00b6ab270d729e5c0085 (patch)
treea47c031776f580c0157fddad0682f5ec30146829
parent3592de54d190cbeae2ec12aacbadd437b7264e5f (diff)
Ticket #377: Support for sending RTCP RR
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1444 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia/rtcp.h26
-rw-r--r--pjmedia/src/pjmedia/rtcp.c127
-rw-r--r--pjmedia/src/pjmedia/stream.c2
-rw-r--r--pjsip-apps/src/samples/siprtp.c2
4 files changed, 95 insertions, 62 deletions
diff --git a/pjmedia/include/pjmedia/rtcp.h b/pjmedia/include/pjmedia/rtcp.h
index b680d0ea..4c02e8b2 100644
--- a/pjmedia/include/pjmedia/rtcp.h
+++ b/pjmedia/include/pjmedia/rtcp.h
@@ -58,7 +58,6 @@ PJ_BEGIN_DECL
*/
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. */
pj_uint32_t rtp_ts; /**< RTP timestamp. */
@@ -117,6 +116,7 @@ struct pjmedia_rtcp_common
unsigned pt:8; /**< payload type */
#endif
unsigned length:16; /**< packet length */
+ pj_uint32_t ssrc; /**< SSRC identification */
};
/**
@@ -129,17 +129,21 @@ typedef struct pjmedia_rtcp_common pjmedia_rtcp_common;
* Incoming RTCP packet may have different format, and must be parsed
* 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 */
-};
+} pjmedia_rtcp_sr_pkt;
/**
- * @see pjmedia_rtcp_pkt
+ * This structure declares RTCP RR (Receiver Report) packet.
*/
-typedef struct pjmedia_rtcp_pkt pjmedia_rtcp_pkt;
+typedef struct pjmedia_rtcp_rr_pkt
+{
+ pjmedia_rtcp_common common; /**< Common header. */
+ pjmedia_rtcp_rr rr; /**< variable-length list */
+} pjmedia_rtcp_rr_pkt;
#pragma pack()
@@ -250,7 +254,8 @@ typedef struct pjmedia_rtcp_stat pjmedia_rtcp_stat;
struct pjmedia_rtcp_session
{
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. */
unsigned rtp_last_ts;/**< Last timestamp in RX RTP pkt. */
@@ -363,19 +368,20 @@ PJ_DECL(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *session,
/**
- * 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.
*
* @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);
/**
diff --git a/pjmedia/src/pjmedia/rtcp.c b/pjmedia/src/pjmedia/rtcp.c
index 0c48b3f6..f2f2e28d 100644
--- a/pjmedia/src/pjmedia/rtcp.c
+++ b/pjmedia/src/pjmedia/rtcp.c
@@ -130,7 +130,7 @@ PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess,
unsigned samples_per_frame,
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;
/* Memset everything */
@@ -146,15 +146,19 @@ PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess,
sess->clock_rate = clock_rate;
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);
sess->tv_base = now;
@@ -340,7 +344,7 @@ PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess,
/* 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))) {
+ if (common->count > 0 && size >= (sizeof(pjmedia_rtcp_sr_pkt))) {
rr = (pjmedia_rtcp_rr*)(((char*)pkt) + (sizeof(pjmedia_rtcp_common)
+ sizeof(pjmedia_rtcp_sr)));
}
@@ -529,33 +533,73 @@ end_rtt_calc:
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!
if (expected >= sess->received)
@@ -564,9 +608,9 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
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;
- 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 */
expected_interval = expected - sess->exp_prior;
@@ -578,26 +622,14 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
lost_interval = expected_interval - received_interval;
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;
+ 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)));
-
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;
pj_uint32_t lsr = sess->rx_lsr;
@@ -610,7 +642,7 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
/* Fill in LSR.
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.
DLSR is Delay since Last SR, in 1/65536 seconds.
@@ -622,7 +654,7 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
/* 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"
"(%ds:%03dms)",
@@ -637,11 +669,6 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
/* Update counter */
pj_gettimeofday(&sess->stat.rx.update);
sess->stat.rx.update_cnt++;
-
-
- /* Return pointer. */
- *ret_p_pkt = rtcp_pkt;
- *len = sizeof(pjmedia_rtcp_pkt);
}
diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c
index 4b0ca144..23127632 100644
--- a/pjmedia/src/pjmedia/stream.c
+++ b/pjmedia/src/pjmedia/stream.c
@@ -439,7 +439,7 @@ static void check_tx_rtcp(pjmedia_stream *stream, pj_uint32_t timestamp)
} else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
- pjmedia_rtcp_pkt *rtcp_pkt;
+ void *rtcp_pkt;
int len;
pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len);
diff --git a/pjsip-apps/src/samples/siprtp.c b/pjsip-apps/src/samples/siprtp.c
index 1e9ee06f..1ca46188 100644
--- a/pjsip-apps/src/samples/siprtp.c
+++ b/pjsip-apps/src/samples/siprtp.c
@@ -1342,7 +1342,7 @@ static int media_thread(void *arg)
/*
* Time to send RTCP packet.
*/
- pjmedia_rtcp_pkt *rtcp_pkt;
+ void *rtcp_pkt;
int rtcp_len;
pj_ssize_t size;
pj_status_t status;