diff options
author | Benny Prijono <bennylp@teluu.com> | 2007-09-20 11:30:59 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2007-09-20 11:30:59 +0000 |
commit | 6c3a7b9adc1a3cb3bf7d00b6ab270d729e5c0085 (patch) | |
tree | a47c031776f580c0157fddad0682f5ec30146829 /pjmedia | |
parent | 3592de54d190cbeae2ec12aacbadd437b7264e5f (diff) |
Ticket #377: Support for sending RTCP RR
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1444 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/include/pjmedia/rtcp.h | 26 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/rtcp.c | 127 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/stream.c | 2 |
3 files changed, 94 insertions, 61 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); |