Changeset 390 for pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
- Timestamp:
- Apr 6, 2006 7:29:03 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
r389 r390 44 44 * Get NTP time. 45 45 */ 46 static void rtcp_get_ntp_time(const pjmedia_rtcp_session *s ,46 static void rtcp_get_ntp_time(const pjmedia_rtcp_session *sess, 47 47 struct pjmedia_rtcp_ntp_rec *ntp) 48 48 { … … 57 57 58 58 /* Calculate second fractions */ 59 ts.u64 %= s ->ts_freq.u64;60 ts.u64 = (ts.u64 << 32) / s ->ts_freq.u64;59 ts.u64 %= sess->ts_freq.u64; 60 ts.u64 = (ts.u64 << 32) / sess->ts_freq.u64; 61 61 62 62 /* Fill up the low 32bit part */ … … 65 65 66 66 67 PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *s ,67 PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess, 68 68 unsigned clock_rate, 69 unsigned samples_per_frame, 69 70 pj_uint32_t ssrc) 70 71 { 71 pjmedia_rtcp_pkt *rtcp_pkt = &s ->rtcp_pkt;72 pjmedia_rtcp_pkt *rtcp_pkt = &sess->rtcp_pkt; 72 73 73 74 pj_memset(rtcp_pkt, 0, sizeof(pjmedia_rtcp_pkt)); 74 75 75 76 /* Set clock rate */ 76 s->clock_rate = clock_rate; 77 sess->clock_rate = clock_rate; 78 sess->pkt_size = samples_per_frame; 77 79 78 80 /* Init time */ 79 s ->rx_lsr = 0;80 s ->rx_lsr_time.u64 = 0;81 sess->rx_lsr = 0; 82 sess->rx_lsr_time.u64 = 0; 81 83 82 84 /* Init common RTCP header */ … … 90 92 91 93 /* Get timestamp frequency */ 92 pj_get_timestamp_freq(&s ->ts_freq);94 pj_get_timestamp_freq(&sess->ts_freq); 93 95 94 96 /* RR will be initialized on receipt of the first RTP packet. */ … … 96 98 97 99 98 PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *sess ion)100 PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *sess) 99 101 { 100 102 /* Nothing to do. */ 101 PJ_UNUSED_ARG(session); 102 } 103 104 static void rtcp_init_seq(pjmedia_rtcp_session *s, pj_uint16_t seq) 105 { 106 s->received = 0; 107 s->exp_prior = 0; 108 s->rx_prior = 0; 109 s->transit = 0; 110 s->jitter = 0; 111 112 pjmedia_rtp_seq_restart(&s->seq_ctrl, seq); 113 } 114 115 PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *s, 116 pj_uint16_t seq, 117 pj_uint32_t rtp_ts) 103 PJ_UNUSED_ARG(sess); 104 } 105 106 static void rtcp_init_seq(pjmedia_rtcp_session *sess) 107 { 108 sess->received = 0; 109 sess->exp_prior = 0; 110 sess->rx_prior = 0; 111 sess->transit = 0; 112 sess->jitter = 0; 113 } 114 115 PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *sess, 116 unsigned seq, 117 unsigned rtp_ts, 118 unsigned payload) 118 119 { 119 120 pj_timestamp ts; 120 121 pj_uint32_t arrival; 121 122 pj_int32_t transit; 122 int status; 123 124 /* Update sequence numbers (received, lost, etc). */ 125 status = pjmedia_rtp_seq_update(&s->seq_ctrl, seq); 126 if (status == PJMEDIA_RTP_ESESSRESTART) { 127 rtcp_init_seq(s, seq); 128 status = 0; 129 } 130 131 if (status != 0) 123 pjmedia_rtp_status seq_st; 124 unsigned last_seq; 125 126 sess->stat.rx.pkt++; 127 sess->stat.rx.bytes += payload; 128 129 /* Update sequence numbers. */ 130 last_seq = sess->seq_ctrl.max_seq; 131 pjmedia_rtp_seq_update(&sess->seq_ctrl, (pj_uint16_t)seq, &seq_st); 132 if (seq_st.status.flag.restart) { 133 rtcp_init_seq(sess); 134 } 135 136 if (seq_st.status.flag.dup) 137 sess->stat.rx.dup++; 138 if (seq_st.status.flag.outorder) 139 sess->stat.rx.reorder++; 140 141 if (seq_st.status.flag.bad) { 142 sess->stat.rx.discard++; 132 143 return; 133 134 ++s->received; 144 } 145 146 147 /* Only mark "good" packets */ 148 ++sess->received; 149 135 150 136 151 /* … … 140 155 /* Get arrival time and convert timestamp to samples */ 141 156 pj_get_timestamp(&ts); 142 ts.u64 = ts.u64 * s ->clock_rate /s->ts_freq.u64;157 ts.u64 = ts.u64 * sess->clock_rate / sess->ts_freq.u64; 143 158 arrival = ts.u32.lo; 144 159 145 160 transit = arrival - rtp_ts; 146 161 147 if (s->transit == 0) { 148 s->transit = transit; 162 /* Ignore the first N packets as they normally have bad jitter 163 * due to other threads working to establish the call 164 */ 165 if (sess->transit == 0 || sess->received < 25 ) { 166 sess->transit = transit; 167 sess->stat.rx.jitter.min = 2000; 149 168 } else { 150 169 pj_int32_t d; 151 152 d = transit - s->transit; 153 s->transit = transit; 170 pj_uint32_t jitter; 171 172 d = transit - sess->transit; 173 sess->transit = transit; 154 174 if (d < 0) 155 175 d = -d; 156 176 157 s->jitter += d - ((s->jitter + 8) >> 4); 158 } 159 } 160 161 PJ_DEF(void) pjmedia_rtcp_tx_rtp(pjmedia_rtcp_session *s, 162 pj_uint16_t bytes_payload_size) 163 { 164 pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; 165 166 /* Update number of packets */ 167 rtcp_pkt->sr.sender_pcount = 168 pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_pcount) + 1); 169 170 /* Update number of bytes */ 171 rtcp_pkt->sr.sender_bcount = 172 pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_bcount) + bytes_payload_size ); 173 } 174 175 176 PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *session, 177 sess->jitter += d - ((sess->jitter + 8) >> 4); 178 179 /* Get jitter in usec */ 180 if (d < 4294) 181 jitter = d * 1000000 / sess->clock_rate; 182 else { 183 jitter = d * 1000 / sess->clock_rate; 184 jitter *= 1000; 185 } 186 187 /* Update jitter stat */ 188 if (jitter < sess->stat.rx.jitter.min) 189 sess->stat.rx.jitter.min = jitter; 190 if (jitter > sess->stat.rx.jitter.max) 191 sess->stat.rx.jitter.max = jitter; 192 sess->stat.rx.jitter.last = jitter; 193 } 194 } 195 196 PJ_DEF(void) pjmedia_rtcp_tx_rtp(pjmedia_rtcp_session *sess, 197 unsigned bytes_payload_size) 198 { 199 /* Update statistics */ 200 sess->stat.tx.pkt++; 201 sess->stat.tx.bytes += bytes_payload_size; 202 } 203 204 205 PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess, 177 206 const void *pkt, 178 207 pj_size_t size) … … 184 213 185 214 /* Save LSR from NTP timestamp of RTCP packet */ 186 sess ion->rx_lsr = ((pj_ntohl(rtcp->sr.ntp_sec) & 0x0000FFFF) << 16) |187 215 sess->rx_lsr = ((pj_ntohl(rtcp->sr.ntp_sec) & 0x0000FFFF) << 16) | 216 ((pj_ntohl(rtcp->sr.ntp_frac) >> 16) & 0xFFFF); 188 217 189 218 /* Calculate SR arrival time for DLSR */ 190 pj_get_timestamp(&sess ion->rx_lsr_time);219 pj_get_timestamp(&sess->rx_lsr_time); 191 220 192 221 TRACE_((THIS_FILE, "Rx RTCP SR: ntp-ts=%p, time=%p", 193 sess ion->rx_lsr,194 (pj_uint32_t)(sess ion->rx_lsr_time.u64*65536/session->ts_freq.u64)));222 sess->rx_lsr, 223 (pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64))); 195 224 196 225 /* Calculate RTT if it has RR */ 197 226 if (size >= sizeof(pjmedia_rtcp_pkt)) { 198 227 228 pj_uint32_t last_loss, jitter_samp, jitter; 229 230 last_loss = sess->stat.tx.loss; 231 232 /* Get packet loss */ 233 sess->stat.tx.loss = (rtcp->rr.total_lost_2 << 16) + 234 (rtcp->rr.total_lost_1 << 8) + 235 rtcp->rr.total_lost_0; 236 237 /* We can't calculate the exact loss period for TX, so just give the 238 * best estimation. 239 */ 240 if (sess->stat.tx.loss > last_loss) { 241 unsigned period; 242 243 /* Loss period in msec */ 244 period = (sess->stat.tx.loss - last_loss) * sess->pkt_size * 245 1000 / sess->clock_rate; 246 247 /* Loss period in usec */ 248 period *= 1000; 249 250 if (sess->stat.tx.update_cnt==0||sess->stat.tx.loss_period.min==0) 251 sess->stat.tx.loss_period.min = period; 252 if (period < sess->stat.tx.loss_period.min) 253 sess->stat.tx.loss_period.min = period; 254 if (period > sess->stat.tx.loss_period.max) 255 sess->stat.tx.loss_period.max = period; 256 257 sess->stat.tx.loss_period.avg = 258 (sess->stat.tx.loss_period.avg*sess->stat.tx.update_cnt+period) 259 / (sess->stat.tx.update_cnt + 1); 260 sess->stat.tx.loss_period.last = period; 261 } 262 263 /* Get jitter value in usec */ 264 jitter_samp = pj_ntohl(rtcp->rr.jitter); 265 /* Calculate jitter in usec, avoiding overflows */ 266 if (jitter_samp <= 4294) 267 jitter = jitter_samp * 1000000 / sess->clock_rate; 268 else { 269 jitter = jitter_samp * 1000 / sess->clock_rate; 270 jitter *= 1000; 271 } 272 273 /* Update jitter statistics */ 274 if (sess->stat.tx.update_cnt == 0) 275 sess->stat.tx.jitter.min = jitter; 276 if (jitter < sess->stat.tx.jitter.min && jitter) 277 sess->stat.tx.jitter.min = jitter; 278 if (jitter > sess->stat.tx.jitter.max) 279 sess->stat.tx.jitter.max = jitter; 280 sess->stat.tx.jitter.avg = 281 (sess->stat.tx.jitter.avg * sess->stat.tx.update_cnt + jitter) / 282 (sess->stat.tx.update_cnt + 1); 283 sess->stat.tx.jitter.last = jitter; 284 285 199 286 /* Can only calculate if LSR and DLSR is present in RR */ 200 287 if (rtcp->rr.lsr && rtcp->rr.dlsr) { … … 212 299 213 300 /* Get current time, and convert to 1/65536 resolution */ 214 rtcp_get_ntp_time(sess ion, &ntp);301 rtcp_get_ntp_time(sess, &ntp); 215 302 now = ((ntp.hi & 0xFFFF) << 16) + 216 303 (ntp.lo >> 16); … … 221 308 /* Convert end to end delay to usec (keeping the calculation in 222 309 * 64bit space):: 223 * sess ion->ee_delay = (eedelay * 1000) / 65536;310 * sess->ee_delay = (eedelay * 1000) / 65536; 224 311 */ 225 312 eedelay = (eedelay * 1000000) >> 16; … … 234 321 */ 235 322 if (now-dlsr >= lsr) { 236 session->rtt_us = (pj_uint32_t)eedelay; 323 unsigned rtt = (pj_uint32_t)eedelay; 324 325 if (sess->stat.rtt_update_cnt == 0) 326 sess->stat.rtt.min = rtt; 327 328 if (rtt < sess->stat.rtt.min && rtt) 329 sess->stat.rtt.min = rtt; 330 if (rtt > sess->stat.rtt.max) 331 sess->stat.rtt.max = rtt; 332 333 sess->stat.rtt.avg = 334 (sess->stat.rtt.avg * sess->stat.rtt_update_cnt + rtt) / 335 (sess->stat.rtt_update_cnt + 1); 336 337 sess->stat.rtt.last = rtt; 338 sess->stat.rtt_update_cnt++; 339 237 340 } else { 238 PJ_LOG(3, (THIS_FILE, "Internal NTP clock skew detected")); 341 PJ_LOG(3, (THIS_FILE, "Internal NTP clock skew detected: " 342 "lsr=%p, now=%p, dlsr=%p (%d:%03dms)", 343 lsr, now, dlsr, dlsr/65536, 344 (dlsr%65536)*1000/65536)); 239 345 } 240 346 } 241 } 242 } 243 244 245 static void rtcp_build_rtcp(pjmedia_rtcp_session *s, 246 pj_uint32_t receiver_ssrc) 247 { 248 pj_uint32_t expected; 249 pj_uint32_t u32; 250 pj_uint32_t expected_interval, received_interval, lost_interval; 251 pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; 347 348 pj_gettimeofday(&sess->stat.tx.update); 349 sess->stat.tx.update_cnt++; 350 } 351 } 352 353 354 PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess, 355 pjmedia_rtcp_pkt **ret_p_pkt, 356 int *len) 357 { 358 pj_uint32_t expected, expected_interval, received_interval, lost_interval; 359 pj_uint32_t jitter_samp, jitter; 360 pjmedia_rtcp_pkt *rtcp_pkt = &sess->rtcp_pkt; 361 pjmedia_rtcp_ntp_rec ntp; 362 363 /* Packet count */ 364 rtcp_pkt->sr.sender_pcount = pj_htonl(sess->stat.tx.pkt); 365 366 /* Octets count */ 367 rtcp_pkt->sr.sender_bcount = pj_htonl(sess->stat.tx.bytes); 252 368 253 369 /* SSRC and last_seq */ 254 rtcp_pkt->rr.ssrc = pj_htonl( receiver_ssrc);255 rtcp_pkt->rr.last_seq = (s ->seq_ctrl.cycles & 0xFFFF0000L);256 rtcp_pkt->rr.last_seq += s ->seq_ctrl.max_seq;370 rtcp_pkt->rr.ssrc = pj_htonl(sess->peer_ssrc); 371 rtcp_pkt->rr.last_seq = (sess->seq_ctrl.cycles & 0xFFFF0000L); 372 rtcp_pkt->rr.last_seq += sess->seq_ctrl.max_seq; 257 373 rtcp_pkt->rr.last_seq = pj_htonl(rtcp_pkt->rr.last_seq); 258 374 375 259 376 /* Jitter */ 260 rtcp_pkt->rr.jitter = pj_htonl(s->jitter >> 4); 377 jitter_samp = (sess->jitter >> 4); 378 rtcp_pkt->rr.jitter = pj_htonl(jitter_samp); 379 380 /* Calculate jitter in usec, avoiding overflows */ 381 if (jitter_samp <= 4294) 382 jitter = jitter_samp * 1000000 / sess->clock_rate; 383 else { 384 jitter = jitter_samp * 1000 / sess->clock_rate; 385 jitter *= 1000; 386 } 387 388 /* Update jitter statistics */ 389 sess->stat.rx.jitter.avg = 390 (sess->stat.rx.jitter.avg * sess->stat.rx.update_cnt + jitter) / 391 (sess->stat.rx.update_cnt + 1); 261 392 262 393 /* Total lost. */ 263 expected = pj_ntohl(rtcp_pkt->rr.last_seq) - s->seq_ctrl.base_seq; 264 if (expected >= s->received) 265 u32 = expected - s->received; 266 else 267 u32 = 0; 268 rtcp_pkt->rr.total_lost_2 = (u32 >> 16) & 0x00FF; 269 rtcp_pkt->rr.total_lost_1 = (u32 >> 8) & 0x00FF; 270 rtcp_pkt->rr.total_lost_0 = u32 & 0x00FF; 394 expected = pj_ntohl(rtcp_pkt->rr.last_seq) - sess->seq_ctrl.base_seq; 395 if (expected >= sess->received) 396 sess->stat.rx.loss = expected - sess->received; 397 rtcp_pkt->rr.total_lost_2 = (sess->stat.rx.loss >> 16) & 0xFF; 398 rtcp_pkt->rr.total_lost_1 = (sess->stat.rx.loss >> 8) & 0xFF; 399 rtcp_pkt->rr.total_lost_0 = (sess->stat.rx.loss & 0xFF); 271 400 272 401 /* Fraction lost calculation */ 273 expected_interval = expected - s ->exp_prior;274 s ->exp_prior = expected;275 276 received_interval = s ->received -s->rx_prior;277 s ->rx_prior =s->received;402 expected_interval = expected - sess->exp_prior; 403 sess->exp_prior = expected; 404 405 received_interval = sess->received - sess->rx_prior; 406 sess->rx_prior = sess->received; 278 407 279 408 lost_interval = expected_interval - received_interval; … … 284 413 rtcp_pkt->rr.fract_lost = (lost_interval << 8) / expected_interval; 285 414 } 286 }287 288 PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *session,289 pjmedia_rtcp_pkt **ret_p_pkt,290 int *len)291 {292 pjmedia_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt;293 pjmedia_rtcp_ntp_rec ntp;294 295 rtcp_build_rtcp(session, session->peer_ssrc);296 415 297 416 /* Get current NTP time. */ 298 rtcp_get_ntp_time(sess ion, &ntp);417 rtcp_get_ntp_time(sess, &ntp); 299 418 300 419 /* Fill in NTP timestamp in SR. */ … … 302 421 rtcp_pkt->sr.ntp_frac = pj_htonl(ntp.lo); 303 422 304 if (sess ion->rx_lsr_time.u64 == 0 || session->rx_lsr == 0) {423 if (sess->rx_lsr_time.u64 == 0 || sess->rx_lsr == 0) { 305 424 rtcp_pkt->rr.lsr = 0; 306 425 rtcp_pkt->rr.dlsr = 0; 307 426 } else { 308 427 pj_timestamp ts; 309 pj_uint32_t lsr = sess ion->rx_lsr;310 pj_uint64_t lsr_time = sess ion->rx_lsr_time.u64;428 pj_uint32_t lsr = sess->rx_lsr; 429 pj_uint64_t lsr_time = sess->rx_lsr_time.u64; 311 430 pj_uint32_t dlsr; 312 431 313 432 /* Convert LSR time to 1/65536 seconds resolution */ 314 lsr_time = (lsr_time << 16) / sess ion->ts_freq.u64;433 lsr_time = (lsr_time << 16) / sess->ts_freq.u64; 315 434 316 435 /* Fill in LSR. … … 325 444 326 445 /* Convert interval to 1/65536 seconds value */ 327 ts.u64 = (ts.u64 << 16) / sess ion->ts_freq.u64;446 ts.u64 = (ts.u64 << 16) / sess->ts_freq.u64; 328 447 329 448 /* Get DLSR */ … … 341 460 } 342 461 462 /* Update counter */ 463 pj_gettimeofday(&sess->stat.rx.update); 464 sess->stat.rx.update_cnt++; 465 343 466 344 467 /* Return pointer. */
Note: See TracChangeset
for help on using the changeset viewer.