Changeset 383
- Timestamp:
- Apr 5, 2006 12:53:42 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/rtcp.h
r382 r383 117 117 { 118 118 pjmedia_rtcp_common common; /**< Common header. */ 119 pjmedia_rtcp_sr sr; /**< Sender report. */120 pjmedia_rtcp_rr rr; /**< variable-length list */119 pjmedia_rtcp_sr sr; /**< Sender report. */ 120 pjmedia_rtcp_rr rr; /**< variable-length list */ 121 121 }; 122 122 … … 147 147 148 148 /** 149 * RTCP session. 149 * RTCP session is used to monitor the RTP session of one endpoint. There 150 * should only be one RTCP session for a bidirectional RTP streams. 150 151 */ 151 152 struct pjmedia_rtcp_session … … 155 156 pjmedia_rtp_seq_session seq_ctrl; /**< RTCP sequence number control. */ 156 157 157 unsigned clock_rate; /**< Clock rate.*/158 pj_uint32_t received; /**< # pktsreceived */159 pj_uint32_t expected_prior; /**< # pkts expected at last interval*/160 pj_uint32_t received_prior; /**< # pkts received at last interval*/161 pj_int32_t transit; /**< Relative trans time for prev pkt*/162 pj_uint32_t jitter; /**< Estimated jitter */163 pj_timestamp ts_freq; /**< System timestamp frequency.*/164 165 pjmedia_rtcp_ntp_rec rtcp_lsr; /**< NTP ts in last SR received */166 unsigned rtcp_lsr_time; /**< Time when last SR is received.*/167 pj_uint32_t peer_ssrc; /**< Peer SSRC */168 158 unsigned clock_rate; /**< Clock rate of the stream */ 159 pj_uint32_t received; /**< # pkt received */ 160 pj_uint32_t exp_prior; /**< # pkt expected at last interval*/ 161 pj_uint32_t rx_prior; /**< # pkt received at last interval*/ 162 pj_int32_t transit; /**< Rel transit time for prev pkt */ 163 pj_uint32_t jitter; /**< Scaled jitter */ 164 pj_timestamp ts_freq; /**< System timestamp frequency. */ 165 166 pjmedia_rtcp_ntp_rec rtcp_lsr; /**< NTP ts in last SR received */ 167 pj_timestamp rtcp_lsr_time;/**< Time when last SR is received*/ 168 pj_uint32_t peer_ssrc; /**< Peer SSRC */ 169 unsigned ee_delay; /**< End-to-end delay, in msec. */ 169 170 }; 170 171 … … 220 221 221 222 /** 222 * Build a RTCP SR/RR packet to be transmitted to remote RTP peer. 223 * @param session The session. 224 * 225 * @param rtcp_pkt [output] Upon return, it will contain pointer to the 223 * Call this function when an RTCP packet is received from remote peer. 224 * This RTCP packet received from remote is used to calculate the end-to- 225 * end delay of the network. 226 * 227 * @param session RTCP session. 228 * @param rtcp_pkt The received RTCP packet. 229 * @param size Size of the incoming packet. 230 */ 231 PJ_DECL(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *session, 232 const void *rtcp_pkt, 233 pj_size_t size); 234 235 236 /** 237 * Build a RTCP SR+RR packet to be transmitted to remote RTP peer. 238 * Note that this function will reset the interval counters (such as 239 * the ones to calculate fraction lost) in the session. 240 * 241 * @param session The RTCP session. 242 * @param rtcp_pkt Upon return, it will contain pointer to the 226 243 * RTCP packet. 227 * @param len [output]Upon return, it will indicate the size of244 * @param len Upon return, it will indicate the size of 228 245 * the RTCP packet. 229 246 */ 230 247 PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session, 231 248 pjmedia_rtcp_pkt **rtcp_pkt, 232 int *len 249 int *len); 233 250 234 251 -
pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
r381 r383 19 19 #include <pjmedia/rtcp.h> 20 20 #include <pjmedia/errno.h> 21 #include <pj/os.h> /* pj_gettimeofday */ 22 #include <pj/sock.h> /* pj_htonx, pj_ntohx */ 23 #include <pj/string.h> /* pj_memset */ 21 #include <pj/assert.h> 22 #include <pj/os.h> 23 #include <pj/sock.h> 24 #include <pj/string.h> 24 25 25 26 … … 28 29 29 30 30 #define USE_TIMESTAMP PJ_HAS_HIGH_RES_TIMER 31 #if PJ_HAS_HIGH_RES_TIMER==0 32 # error "High resolution timer needs to be enabled" 33 #endif 31 34 32 35 … … 34 37 * Get NTP time. 35 38 */ 36 static void rtcp_get_ntp_time(struct pjmedia_rtcp_ntp_rec *ntp) 39 static void rtcp_get_ntp_time(const pjmedia_rtcp_session *s, 40 struct pjmedia_rtcp_ntp_rec *ntp) 37 41 { 38 42 pj_time_val tv; 43 pj_timestamp ts; 39 44 40 45 pj_gettimeofday(&tv); 41 46 pj_get_timestamp(&ts); 47 48 /* Fill up the high 32bit part */ 42 49 ntp->hi = tv.sec; 43 tv.msec = tv.msec % 1000; 44 ntp->lo = tv.msec * 0xFFFF / 1000; 45 ntp->lo <<= 16; 50 51 /* Calculate second fractions */ 52 ts.u64 %= s->ts_freq.u64; 53 ts.u64 = (ts.u64 << 32) / s->ts_freq.u64; 54 55 /* Fill up the low 32bit part */ 56 ntp->lo = ts.u32.lo; 46 57 } 47 58 … … 60 71 /* Init time */ 61 72 s->rtcp_lsr.hi = s->rtcp_lsr.lo = 0; 62 s->rtcp_lsr_time = 0;73 s->rtcp_lsr_time.u64 = 0; 63 74 64 75 /* Init common RTCP header */ … … 72 83 73 84 /* Get timestamp frequency */ 74 #if USE_TIMESTAMP75 85 pj_get_timestamp_freq(&s->ts_freq); 76 #endif77 86 78 87 /* RR will be initialized on receipt of the first RTP packet. */ 79 88 } 89 80 90 81 91 PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *session) … … 88 98 { 89 99 s->received = 0; 90 s->exp ected_prior = 0;91 s->r eceived_prior = 0;100 s->exp_prior = 0; 101 s->rx_prior = 0; 92 102 s->transit = 0; 93 103 s->jitter = 0; … … 100 110 pj_uint32_t rtp_ts) 101 111 { 112 pj_timestamp ts; 102 113 pj_uint32_t arrival; 103 114 pj_int32_t transit; … … 117 128 118 129 /* 119 * Calculate jitter (s ->jitter is in timer tick unit)130 * Calculate jitter (see RFC 3550 section A.8) 120 131 */ 121 #if USE_TIMESTAMP 122 { 123 pj_timestamp ts; 124 125 pj_get_timestamp(&ts); 126 127 /* Convert timestamp to samples */ 128 ts.u64 = ts.u64 * s->clock_rate / s->ts_freq.u64; 129 arrival = (pj_uint32_t)ts.u64; 130 } 131 #else 132 { 133 pj_time_val tv; 134 unsigned long timer_tick; 135 136 pj_gettimeofday(&tv); 137 timer_tick = tv.sec * 1000 + tv.msec; 138 139 /* Convert timer tick to samples */ 140 arrival = timer_tick * s->clock_rate / 1000; 141 } 142 #endif 132 133 /* Get arrival time and convert timestamp to samples */ 134 pj_get_timestamp(&ts); 135 ts.u64 = ts.u64 * s->clock_rate / s->ts_freq.u64; 136 arrival = ts.u32.lo; 143 137 144 138 transit = arrival - rtp_ts; … … 147 141 s->transit = transit; 148 142 } else { 149 pj_int32_t d , jitter = s->jitter;143 pj_int32_t d; 150 144 151 145 d = transit - s->transit; … … 154 148 d = -d; 155 149 156 jitter += d - ((jitter + 8) >> 4); 157 s->jitter = jitter; 150 s->jitter += d - ((s->jitter + 8) >> 4); 158 151 } 159 152 } … … 163 156 { 164 157 pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; 165 rtcp_pkt->sr.sender_pcount = pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_pcount) + 1); 166 rtcp_pkt->sr.sender_bcount = pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_bcount) + bytes_payload_size ); 167 } 158 159 /* Update number of packets */ 160 rtcp_pkt->sr.sender_pcount = 161 pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_pcount) + 1); 162 163 /* Update number of bytes */ 164 rtcp_pkt->sr.sender_bcount = 165 pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_bcount) + bytes_payload_size ); 166 } 167 168 169 PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *session, 170 const void *pkt, 171 pj_size_t size) 172 { 173 const struct pjmedia_rtcp_pkt *rtcp = pkt; 174 175 /* Must at least contain SR */ 176 pj_assert(size >= sizeof(pjmedia_rtcp_common)+sizeof(pjmedia_rtcp_sr)); 177 178 /* Save NTP timestamp */ 179 session->rtcp_lsr.hi = pj_ntohl(rtcp->sr.ntp_sec); 180 session->rtcp_lsr.lo = pj_ntohl(rtcp->sr.ntp_frac); 181 182 /* Calculate SR arrival time for DLSR */ 183 pj_get_timestamp(&session->rtcp_lsr_time); 184 185 /* Calculate ee_delay if it has RR */ 186 if (size >= sizeof(pjmedia_rtcp_pkt)) { 187 188 /* Can only calculate if LSR and DLSR is present in RR */ 189 if (rtcp->rr.lsr && rtcp->rr.dlsr) { 190 pj_uint32_t lsr, now, dlsr, eedelay; 191 pjmedia_rtcp_ntp_rec ntp; 192 193 /* LSR is the middle 32bit of NTP. It has 1/65536 second 194 * resolution 195 */ 196 lsr = pj_ntohl(rtcp->rr.lsr); 197 198 /* DLSR is delay since LSR, also in 1/65536 resolution */ 199 dlsr = pj_ntohl(rtcp->rr.dlsr); 200 201 /* Get current time, and convert to 1/65536 resolution */ 202 rtcp_get_ntp_time(session, &ntp); 203 now = ((ntp.hi & 0xFFFF) << 16) + 204 (ntp.lo >> 16); 205 206 /* End-to-end delay is (now-lsr-dlsr) */ 207 eedelay = now - lsr - dlsr; 208 209 /* Convert end to end delay to msec: 210 * session->ee_delay = (eedelay * 1000) / 65536; 211 */ 212 session->ee_delay = (eedelay * 1000) >> 16; 213 } 214 } 215 } 216 168 217 169 218 static void rtcp_build_rtcp(pjmedia_rtcp_session *s, … … 185 234 186 235 /* Total lost. */ 187 expected = pj_ntohl(rtcp_pkt->rr.last_seq) - s->seq_ctrl.base_seq + 1;236 expected = pj_ntohl(rtcp_pkt->rr.last_seq) - s->seq_ctrl.base_seq; 188 237 u32 = expected - s->received; 189 if (u32 == 1) u32 = 0;190 238 rtcp_pkt->rr.total_lost_2 = (u32 >> 16) & 0x00FF; 191 239 rtcp_pkt->rr.total_lost_1 = (u32 >> 8) & 0x00FF; … … 193 241 194 242 /* Fraction lost calculation */ 195 expected_interval = expected - s->exp ected_prior;196 s->exp ected_prior = expected;197 198 received_interval = s->received - s->r eceived_prior;199 s->r eceived_prior = s->received;243 expected_interval = expected - s->exp_prior; 244 s->exp_prior = expected; 245 246 received_interval = s->received - s->rx_prior; 247 s->rx_prior = s->received; 200 248 201 249 lost_interval = expected_interval - received_interval; … … 214 262 pjmedia_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt; 215 263 pjmedia_rtcp_ntp_rec ntp; 216 pj_time_val now;217 264 218 265 rtcp_build_rtcp(session, session->peer_ssrc); 219 266 220 267 /* Get current NTP time. */ 221 rtcp_get_ntp_time( &ntp);268 rtcp_get_ntp_time(session, &ntp); 222 269 223 270 /* Fill in NTP timestamp in SR. */ … … 225 272 rtcp_pkt->sr.ntp_frac = pj_htonl(ntp.lo); 226 273 227 if (session->rtcp_lsr_time == 0 || session->rtcp_lsr.lo == 0) {274 if (session->rtcp_lsr_time.u64 == 0 || session->rtcp_lsr.lo == 0) { 228 275 rtcp_pkt->rr.lsr = 0; 229 276 rtcp_pkt->rr.dlsr = 0; 230 277 } else { 231 unsigned msec_elapsed;278 pj_timestamp ts; 232 279 233 280 /* Fill in LSR. … … 241 288 DLSR is Delay since Last SR, in 1/65536 seconds. 242 289 */ 243 pj_gettimeofday(&now); 244 msec_elapsed = (now.msec - session->rtcp_lsr_time); 245 rtcp_pkt->rr.dlsr = pj_htonl((msec_elapsed * 65536) / 1000); 246 } 247 290 pj_get_timestamp(&ts); 291 292 /* Convert interval to 1/65536 seconds value */ 293 ts.u64 = ((ts.u64 - session->rtcp_lsr_time.u64) << 16) / 294 session->ts_freq.u64; 295 296 rtcp_pkt->rr.dlsr = pj_htonl( (pj_uint32_t)ts.u64 ); 297 } 298 299 248 300 /* Return pointer. */ 249 301 *ret_p_pkt = rtcp_pkt; … … 251 303 } 252 304 305 -
pjproject/trunk/pjsip-apps/src/samples/siprtp.c
r382 r383 1114 1114 pj_memcpy(&strm->rem_rtcp, packet, size); 1115 1115 status = PJ_SUCCESS; 1116 1117 /* Report receipt of RTCP to RTCP session */ 1118 pjmedia_rtcp_rx_rtcp(&strm->rtcp, packet, size); 1116 1119 } 1117 1120 } … … 1525 1528 ); 1526 1529 1530 printf(" End to end delay: %u ms\n", audio->rtcp.ee_delay); 1531 1527 1532 } 1528 1533
Note: See TracChangeset
for help on using the changeset viewer.