- Timestamp:
- Apr 9, 2006 10:42:51 AM (19 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/rtcp.h
r390 r397 230 230 pj_int32_t transit; /**< Rel transit time for prev pkt */ 231 231 pj_uint32_t jitter; /**< Scaled jitter */ 232 pj_time_val tv_base; /**< Base time, in seconds. */ 233 pj_timestamp ts_base; /**< Base system timestamp. */ 232 234 pj_timestamp ts_freq; /**< System timestamp frequency. */ 233 235 … … 260 262 261 263 /** 264 * Utility function to retrieve current NTP timestamp. 265 * 266 * @param sess RTCP session. 267 * @param ntp NTP record. 268 * 269 * @return PJ_SUCCESS on success. 270 */ 271 PJ_DEF(pj_status_t) pjmedia_rtcp_get_ntp_time(const pjmedia_rtcp_session *sess, 272 pjmedia_rtcp_ntp_rec *ntp); 273 274 275 /** 262 276 * Deinitialize RTCP session. 263 277 * -
pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
r394 r397 35 35 #endif 36 36 37 38 37 39 #if 0 38 40 # define TRACE_(x) PJ_LOG(3,x) … … 41 43 #endif 42 44 45 43 46 /* 44 47 * Get NTP time. 45 48 */ 46 static void rtcp_get_ntp_time(const pjmedia_rtcp_session *sess, 47 struct pjmedia_rtcp_ntp_rec *ntp) 48 { 49 pj_time_val tv; 49 PJ_DEF(pj_status_t) pjmedia_rtcp_get_ntp_time(const pjmedia_rtcp_session *sess, 50 pjmedia_rtcp_ntp_rec *ntp) 51 { 52 /* Seconds between 1900-01-01 to 1970-01-01 */ 53 #define NTP_DIFF ((70 * 365 + 17) * 86400UL) 50 54 pj_timestamp ts; 51 52 pj_gettimeofday(&tv); 53 pj_get_timestamp(&ts);54 55 pj_status_t status; 56 57 status = pj_get_timestamp(&ts); 58 55 59 /* Fill up the high 32bit part */ 56 ntp->hi = tv.sec; 57 58 /* Calculate second fractions */ 60 ntp->hi = (pj_uint32_t)((ts.u64 - sess->ts_base.u64) / sess->ts_freq.u64) 61 + sess->tv_base.sec + NTP_DIFF; 62 63 /* Calculate seconds fractions */ 59 64 ts.u64 %= sess->ts_freq.u64; 65 pj_assert(ts.u64 < sess->ts_freq.u64); 60 66 ts.u64 = (ts.u64 << 32) / sess->ts_freq.u64; 61 67 62 68 /* Fill up the low 32bit part */ 63 69 ntp->lo = ts.u32.lo; 70 71 72 #if (defined(PJ_WIN32) && PJ_WIN32!=0) || \ 73 (defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0) 74 75 /* On Win32, since we use QueryPerformanceCounter() as the backend 76 * timestamp API, we need to protect against this bug: 77 * Performance counter value may unexpectedly leap forward 78 * http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q274323 79 */ 80 { 81 /* 82 * Compare elapsed time reported by timestamp with actual elapsed 83 * time. If the difference is too excessive, then we use system 84 * time instead. 85 */ 86 87 /* MIN_DIFF needs to be large enough so that "normal" diff caused 88 * by system activity or context switch doesn't trigger the time 89 * correction. 90 */ 91 enum { MIN_DIFF = 400 }; 92 93 pj_time_val ts_time, elapsed, diff; 94 95 pj_gettimeofday(&elapsed); 96 97 ts_time.sec = ntp->hi - sess->tv_base.sec - NTP_DIFF; 98 ts_time.msec = (long)(ntp->lo * 1000.0 / 0xFFFFFFFF); 99 100 PJ_TIME_VAL_SUB(elapsed, sess->tv_base); 101 102 if (PJ_TIME_VAL_LT(ts_time, elapsed)) { 103 diff = elapsed; 104 PJ_TIME_VAL_SUB(diff, ts_time); 105 } else { 106 diff = ts_time; 107 PJ_TIME_VAL_SUB(diff, elapsed); 108 } 109 110 if (PJ_TIME_VAL_MSEC(diff) >= MIN_DIFF) { 111 112 TRACE_((THIS_FILE, "NTP timestamp corrected by %d ms", 113 PJ_TIME_VAL_MSEC(diff))); 114 115 116 ntp->hi = elapsed.sec + sess->tv_base.sec + NTP_DIFF; 117 ntp->lo = (elapsed.msec * 65536 / 1000) << 16; 118 } 119 120 } 121 #endif 122 123 return status; 64 124 } 65 125 … … 91 151 rtcp_pkt->sr.ssrc = pj_htonl(ssrc); 92 152 93 /* Get timestamp frequency */ 153 /* Get time and timestamp base and frequency */ 154 pj_gettimeofday(&sess->tv_base); 155 pj_get_timestamp(&sess->ts_base); 94 156 pj_get_timestamp_freq(&sess->ts_freq); 95 157 … … 208 270 { 209 271 const struct pjmedia_rtcp_pkt *rtcp = pkt; 272 pj_uint32_t last_loss, jitter_samp, jitter; 210 273 211 274 /* Must at least contain SR */ … … 219 282 pj_get_timestamp(&sess->rx_lsr_time); 220 283 221 TRACE_((THIS_FILE, "Rx RTCP SR: ntp -ts=%p, time=%p",284 TRACE_((THIS_FILE, "Rx RTCP SR: ntp_ts=%p", 222 285 sess->rx_lsr, 223 286 (pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64))); 224 287 225 /* Calculate RTT if it has RR */ 226 if (size >= sizeof(pjmedia_rtcp_pkt)) { 288 /* Nothing more to do if this is an SR only RTCP packet */ 289 if (size < sizeof(pjmedia_rtcp_pkt)) 290 return; 227 291 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; 292 293 last_loss = sess->stat.tx.loss; 294 295 /* Get packet loss */ 296 sess->stat.tx.loss = (rtcp->rr.total_lost_2 << 16) + 297 (rtcp->rr.total_lost_1 << 8) + 298 rtcp->rr.total_lost_0; 299 300 /* We can't calculate the exact loss period for TX, so just give the 301 * best estimation. 302 */ 303 if (sess->stat.tx.loss > last_loss) { 304 unsigned period; 305 306 /* Loss period in msec */ 307 period = (sess->stat.tx.loss - last_loss) * sess->pkt_size * 308 1000 / sess->clock_rate; 309 310 /* Loss period in usec */ 311 period *= 1000; 312 313 if (sess->stat.tx.update_cnt==0||sess->stat.tx.loss_period.min==0) 314 sess->stat.tx.loss_period.min = period; 315 if (period < sess->stat.tx.loss_period.min) 316 sess->stat.tx.loss_period.min = period; 317 if (period > sess->stat.tx.loss_period.max) 318 sess->stat.tx.loss_period.max = period; 319 320 sess->stat.tx.loss_period.avg = 321 (sess->stat.tx.loss_period.avg*sess->stat.tx.update_cnt+period) 322 / (sess->stat.tx.update_cnt + 1); 323 sess->stat.tx.loss_period.last = period; 324 } 325 326 /* Get jitter value in usec */ 327 jitter_samp = pj_ntohl(rtcp->rr.jitter); 328 /* Calculate jitter in usec, avoiding overflows */ 329 if (jitter_samp <= 4294) 330 jitter = jitter_samp * 1000000 / sess->clock_rate; 331 else { 332 jitter = jitter_samp * 1000 / sess->clock_rate; 333 jitter *= 1000; 334 } 335 336 /* Update jitter statistics */ 337 if (sess->stat.tx.update_cnt == 0) 338 sess->stat.tx.jitter.min = jitter; 339 if (jitter < sess->stat.tx.jitter.min && jitter) 340 sess->stat.tx.jitter.min = jitter; 341 if (jitter > sess->stat.tx.jitter.max) 342 sess->stat.tx.jitter.max = jitter; 343 sess->stat.tx.jitter.avg = 344 (sess->stat.tx.jitter.avg * sess->stat.tx.update_cnt + jitter) / 345 (sess->stat.tx.update_cnt + 1); 346 sess->stat.tx.jitter.last = jitter; 347 348 349 /* Can only calculate if LSR and DLSR is present in RR */ 350 if (rtcp->rr.lsr && rtcp->rr.dlsr) { 351 pj_uint32_t lsr, now, dlsr; 352 pj_uint64_t eedelay; 353 pjmedia_rtcp_ntp_rec ntp; 354 355 /* LSR is the middle 32bit of NTP. It has 1/65536 second 356 * resolution 357 */ 358 lsr = pj_ntohl(rtcp->rr.lsr); 359 360 /* DLSR is delay since LSR, also in 1/65536 resolution */ 361 dlsr = pj_ntohl(rtcp->rr.dlsr); 362 363 /* Get current time, and convert to 1/65536 resolution */ 364 pjmedia_rtcp_get_ntp_time(sess, &ntp); 365 now = ((ntp.hi & 0xFFFF) << 16) + (ntp.lo >> 16); 366 367 /* End-to-end delay is (now-lsr-dlsr) */ 368 eedelay = now - lsr - dlsr; 369 370 /* Convert end to end delay to usec (keeping the calculation in 371 * 64bit space):: 372 * sess->ee_delay = (eedelay * 1000) / 65536; 373 */ 374 if (eedelay < 4294) { 375 eedelay = (eedelay * 1000000) >> 16; 376 } else { 377 eedelay = (eedelay * 1000) >> 16; 378 eedelay *= 1000; 379 } 380 381 TRACE_((THIS_FILE, "Rx RTCP RR: lsr=%p, dlsr=%p (%d:%03dms), " 382 "now=%p, rtt=%p", 383 lsr, dlsr, dlsr/65536, (dlsr%65536)*1000/65536, 384 now, (pj_uint32_t)eedelay)); 236 385 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; 386 /* Only save calculation if "now" is greater than lsr, or 387 * otherwise rtt will be invalid 388 */ 389 if (now-dlsr >= lsr) { 390 unsigned rtt = (pj_uint32_t)eedelay; 391 392 TRACE_((THIS_FILE, "RTT is set to %d usec", rtt)); 393 394 if (rtt >= 1000000) { 395 pjmedia_rtcp_ntp_rec ntp2; 396 pj_thread_sleep(50); 397 pjmedia_rtcp_get_ntp_time(sess, &ntp2); 398 ntp2.lo = ntp2.lo; 399 } 400 401 if (sess->stat.rtt_update_cnt == 0) 402 sess->stat.rtt.min = rtt; 403 404 if (rtt < sess->stat.rtt.min && rtt) 405 sess->stat.rtt.min = rtt; 406 if (rtt > sess->stat.rtt.max) 407 sess->stat.rtt.max = rtt; 408 409 sess->stat.rtt.avg = 410 (sess->stat.rtt.avg * sess->stat.rtt_update_cnt + rtt) / 411 (sess->stat.rtt_update_cnt + 1); 412 413 sess->stat.rtt.last = rtt; 414 sess->stat.rtt_update_cnt++; 415 416 } else { 417 PJ_LOG(5, (THIS_FILE, "Internal NTP clock skew detected: " 418 "lsr=%p, now=%p, dlsr=%p (%d:%03dms), " 419 "diff=%d", 420 lsr, now, dlsr, dlsr/65536, 421 (dlsr%65536)*1000/65536, 422 dlsr-(now-lsr))); 261 423 } 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 286 /* Can only calculate if LSR and DLSR is present in RR */ 287 if (rtcp->rr.lsr && rtcp->rr.dlsr) { 288 pj_uint32_t lsr, now, dlsr; 289 pj_uint64_t eedelay; 290 pjmedia_rtcp_ntp_rec ntp; 291 292 /* LSR is the middle 32bit of NTP. It has 1/65536 second 293 * resolution 294 */ 295 lsr = pj_ntohl(rtcp->rr.lsr); 296 297 /* DLSR is delay since LSR, also in 1/65536 resolution */ 298 dlsr = pj_ntohl(rtcp->rr.dlsr); 299 300 /* Get current time, and convert to 1/65536 resolution */ 301 rtcp_get_ntp_time(sess, &ntp); 302 now = ((ntp.hi & 0xFFFF) << 16) + 303 (ntp.lo >> 16); 304 305 /* End-to-end delay is (now-lsr-dlsr) */ 306 eedelay = now - lsr - dlsr; 307 308 /* Convert end to end delay to usec (keeping the calculation in 309 * 64bit space):: 310 * sess->ee_delay = (eedelay * 1000) / 65536; 311 */ 312 eedelay = (eedelay * 1000000) >> 16; 313 314 TRACE_((THIS_FILE, "Rx RTCP RR: lsr=%p, dlsr=%p (%d:%03dms), " 315 "now=%p, rtt=%p", 316 lsr, dlsr, dlsr/65536, (dlsr%65536)*1000/65536, 317 now, (pj_uint32_t)eedelay)); 318 319 /* Only save calculation if "now" is greater than lsr, or 320 * otherwise rtt will be invalid 321 */ 322 if (now-dlsr >= lsr) { 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 340 } else { 341 PJ_LOG(3, (THIS_FILE, "Internal NTP clock skew detected: " 342 "lsr=%p, now=%p, dlsr=%p (%d:%03dms), " 343 "diff=%d", 344 lsr, now, dlsr, dlsr/65536, 345 (dlsr%65536)*1000/65536, 346 dlsr-(now-lsr))); 347 } 348 } 349 350 pj_gettimeofday(&sess->stat.tx.update); 351 sess->stat.tx.update_cnt++; 352 } 424 } 425 426 pj_gettimeofday(&sess->stat.tx.update); 427 sess->stat.tx.update_cnt++; 353 428 } 354 429 … … 361 436 pj_uint32_t jitter_samp, jitter; 362 437 pjmedia_rtcp_pkt *rtcp_pkt = &sess->rtcp_pkt; 438 pj_timestamp ts_now; 363 439 pjmedia_rtcp_ntp_rec ntp; 364 440 … … 417 493 418 494 /* Get current NTP time. */ 419 rtcp_get_ntp_time(sess, &ntp); 495 pj_get_timestamp(&ts_now); 496 pjmedia_rtcp_get_ntp_time(sess, &ntp); 420 497 421 498 /* Fill in NTP timestamp in SR. */ 422 499 rtcp_pkt->sr.ntp_sec = pj_htonl(ntp.hi); 423 500 rtcp_pkt->sr.ntp_frac = pj_htonl(ntp.lo); 424 501 502 TRACE_((THIS_FILE, "TX RTCP SR: ntp_ts=%p", 503 ((ntp.hi & 0xFFFF) << 16) + ((ntp.lo & 0xFFFF0000) 504 >> 16))); 505 425 506 if (sess->rx_lsr_time.u64 == 0 || sess->rx_lsr == 0) { 426 507 rtcp_pkt->rr.lsr = 0; … … 443 524 DLSR is Delay since Last SR, in 1/65536 seconds. 444 525 */ 445 pj_get_timestamp(&ts);526 ts.u64 = ts_now.u64; 446 527 447 528 /* Convert interval to 1/65536 seconds value */ -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r394 r397 31 31 #include <pj/os.h> 32 32 #include <pj/pool.h> 33 #include <pj/rand.h> 33 34 #include <pj/sock_select.h> 34 35 #include <pj/string.h> /* memcpy() */
Note: See TracChangeset
for help on using the changeset viewer.