Ignore:
Timestamp:
May 2, 2006 5:47:51 PM (18 years ago)
Author:
bennylp
Message:

Fixed several bugs in RTCP and tested the compatibility. Fixed bugs: total lost byte order, RTCP RR parsing, normalizing large RTT, RX pkt lost online update.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/rtcp.c

    r411 r427  
    5151{ 
    5252/* Seconds between 1900-01-01 to 1970-01-01 */ 
    53 #define NTP_DIFF    ((70 * 365 + 17) * 86400UL) 
     53#define JAN_1970  (2208988800UL) 
    5454    pj_timestamp ts; 
    5555    pj_status_t status; 
     
    5959    /* Fill up the high 32bit part */ 
    6060    ntp->hi = (pj_uint32_t)((ts.u64 - sess->ts_base.u64) / sess->ts_freq.u64) 
    61               + sess->tv_base.sec + NTP_DIFF; 
     61              + sess->tv_base.sec + JAN_1970; 
    6262 
    6363    /* Calculate seconds fractions */ 
     
    9595        pj_gettimeofday(&elapsed); 
    9696 
    97         ts_time.sec = ntp->hi - sess->tv_base.sec - NTP_DIFF; 
     97        ts_time.sec = ntp->hi - sess->tv_base.sec - JAN_1970; 
    9898        ts_time.msec = (long)(ntp->lo * 1000.0 / 0xFFFFFFFF); 
    9999 
     
    114114 
    115115 
    116             ntp->hi = elapsed.sec + sess->tv_base.sec + NTP_DIFF; 
     116            ntp->hi = elapsed.sec + sess->tv_base.sec + JAN_1970; 
    117117            ntp->lo = (elapsed.msec * 65536 / 1000) << 16; 
    118118        } 
     
    217217    } 
    218218 
     219    /* Only mark "good" packets */ 
     220    ++sess->received; 
     221 
    219222    /* Calculate loss periods. */ 
    220223    if (seq_st.diff > 1) { 
     
    224227        period = count * sess->pkt_size * 1000 / sess->clock_rate; 
    225228        period *= 1000; 
     229 
     230        /* Update packet lost.  
     231         * The packet lost number will also be updated when we're sending 
     232         * outbound RTCP RR. 
     233         */ 
     234        sess->stat.rx.loss += (seq_st.diff - 1); 
    226235 
    227236        /* Update loss period stat */ 
     
    241250 
    242251 
    243     /* Only mark "good" packets */ 
    244     ++sess->received; 
    245  
    246  
    247252    /* 
    248253     * Calculate jitter only when sequence is good (see RFC 3550 section A.8) 
     
    304309                                   pj_size_t size) 
    305310{ 
    306     const struct pjmedia_rtcp_pkt *rtcp = pkt; 
     311    const pjmedia_rtcp_common *common = pkt; 
     312    const pjmedia_rtcp_rr *rr = NULL; 
     313    const pjmedia_rtcp_sr *sr = NULL; 
    307314    pj_uint32_t last_loss, jitter_samp, jitter; 
    308315 
    309     /* Must at least contain SR */ 
    310     pj_assert(size >= sizeof(pjmedia_rtcp_common)+sizeof(pjmedia_rtcp_sr)); 
    311  
    312     /* Save LSR from NTP timestamp of RTCP packet */ 
    313     sess->rx_lsr = ((pj_ntohl(rtcp->sr.ntp_sec) & 0x0000FFFF) << 16) |  
    314                    ((pj_ntohl(rtcp->sr.ntp_frac) >> 16) & 0xFFFF); 
    315  
    316     /* Calculate SR arrival time for DLSR */ 
    317     pj_get_timestamp(&sess->rx_lsr_time); 
    318  
    319     TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p",  
    320             sess->rx_lsr, 
    321             (pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64))); 
    322  
    323     /* Nothing more to do if this is an SR only RTCP packet */ 
    324     if (size < sizeof(pjmedia_rtcp_pkt)) 
     316    /* Parse RTCP */ 
     317    if (common->pt == RTCP_SR) { 
     318        sr = (pjmedia_rtcp_sr*) (((char*)pkt) + sizeof(pjmedia_rtcp_common)); 
     319        if (common->count > 0 && size >= (sizeof(pjmedia_rtcp_pkt))) { 
     320            rr = (pjmedia_rtcp_rr*)(((char*)pkt) + (sizeof(pjmedia_rtcp_common) 
     321                                    + sizeof(pjmedia_rtcp_sr))); 
     322        } 
     323    } else if (common->pt == RTCP_RR && common->count > 0) 
     324        rr = (pjmedia_rtcp_rr*)(((char*)pkt) +sizeof(pjmedia_rtcp_common) +4); 
     325 
     326 
     327    if (sr) { 
     328        /* Save LSR from NTP timestamp of RTCP packet */ 
     329        sess->rx_lsr = ((pj_ntohl(sr->ntp_sec) & 0x0000FFFF) << 16) |  
     330                       ((pj_ntohl(sr->ntp_frac) >> 16) & 0xFFFF); 
     331 
     332        /* Calculate SR arrival time for DLSR */ 
     333        pj_get_timestamp(&sess->rx_lsr_time); 
     334 
     335        TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p",  
     336                sess->rx_lsr, 
     337                (pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64))); 
     338    } 
     339 
     340 
     341    /* Nothing more to do if there's no RR packet */ 
     342    if (rr == NULL) 
    325343        return; 
    326          
     344 
    327345 
    328346    last_loss = sess->stat.tx.loss; 
    329347 
    330348    /* Get packet loss */ 
    331     sess->stat.tx.loss = (rtcp->rr.total_lost_2 << 16) + 
    332                          (rtcp->rr.total_lost_1 << 8) + 
    333                           rtcp->rr.total_lost_0; 
     349    sess->stat.tx.loss = (rr->total_lost_2 << 16) + 
     350                         (rr->total_lost_1 << 8) + 
     351                          rr->total_lost_0; 
     352 
     353    TRACE_((sess->name, "Rx RTCP RR: total_lost_2=%x, 1=%x, 0=%x, lost=%d",  
     354            (int)rr->total_lost_2, 
     355            (int)rr->total_lost_1, 
     356            (int)rr->total_lost_0, 
     357            sess->stat.tx.loss)); 
    334358     
    335359    /* We can't calculate the exact loss period for TX, so just give the 
     
    360384 
    361385    /* Get jitter value in usec */ 
    362     jitter_samp = pj_ntohl(rtcp->rr.jitter); 
     386    jitter_samp = pj_ntohl(rr->jitter); 
    363387    /* Calculate jitter in usec, avoiding overflows */ 
    364388    if (jitter_samp <= 4294) 
     
    383407 
    384408    /* Can only calculate if LSR and DLSR is present in RR */ 
    385     if (rtcp->rr.lsr && rtcp->rr.dlsr) { 
     409    if (rr->lsr && rr->dlsr) { 
    386410        pj_uint32_t lsr, now, dlsr; 
    387411        pj_uint64_t eedelay; 
     
    391415         * resolution  
    392416         */ 
    393         lsr = pj_ntohl(rtcp->rr.lsr); 
     417        lsr = pj_ntohl(rr->lsr); 
    394418 
    395419        /* DLSR is delay since LSR, also in 1/65536 resolution */ 
    396         dlsr = pj_ntohl(rtcp->rr.dlsr); 
     420        dlsr = pj_ntohl(rr->dlsr); 
    397421 
    398422        /* Get current time, and convert to 1/65536 resolution */ 
     
    425449            unsigned rtt = (pj_uint32_t)eedelay; 
    426450             
    427             TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt)); 
    428  
    429             if (rtt >= 1000000) { 
    430                 pjmedia_rtcp_ntp_rec ntp2; 
    431                 pj_thread_sleep(50); 
    432                 pjmedia_rtcp_get_ntp_time(sess, &ntp2); 
    433                 ntp2.lo = ntp2.lo; 
     451            /* Check that eedelay value really makes sense.  
     452             * We allow up to 30 seconds RTT! 
     453             */ 
     454            if (eedelay > 30 * 1000 * 1000UL) { 
     455 
     456                TRACE_((sess->name, "RTT not making any sense, ignored..")); 
     457                goto end_rtt_calc; 
    434458            } 
    435459 
    436460            if (sess->stat.rtt_update_cnt == 0) 
    437461                sess->stat.rtt.min = rtt; 
     462 
     463            /* "Normalize" rtt value that is exceptionally high. 
     464             * For such values, "normalize" the rtt to be three times 
     465             * the average value. 
     466             */ 
     467            if (rtt > (sess->stat.rtt.avg*3) && sess->stat.rtt_update_cnt!=0) { 
     468                unsigned orig_rtt = rtt; 
     469                rtt = sess->stat.rtt.avg*3; 
     470                PJ_LOG(5,(sess->name,  
     471                          "RTT value %d usec is normalized to %d usec", 
     472                          orig_rtt, rtt)); 
     473            } 
     474         
     475            TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt)); 
    438476 
    439477            if (rtt < sess->stat.rtt.min && rtt) 
     
    458496        } 
    459497    } 
     498 
     499end_rtt_calc: 
    460500 
    461501    pj_gettimeofday(&sess->stat.tx.update); 
     
    508548    if (expected >= sess->received) 
    509549        sess->stat.rx.loss = expected - sess->received; 
     550    else 
     551        sess->stat.rx.loss = 0; 
     552 
    510553    rtcp_pkt->rr.total_lost_2 = (sess->stat.rx.loss >> 16) & 0xFF; 
    511554    rtcp_pkt->rr.total_lost_1 = (sess->stat.rx.loss >> 8) & 0xFF; 
Note: See TracChangeset for help on using the changeset viewer.