Changeset 383


Ignore:
Timestamp:
Apr 5, 2006 12:53:42 PM (18 years ago)
Author:
bennylp
Message:

Added RTCP end to end delay calculation

Location:
pjproject/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/rtcp.h

    r382 r383  
    117117{ 
    118118    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   */ 
    121121}; 
    122122 
     
    147147 
    148148/** 
    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. 
    150151 */ 
    151152struct pjmedia_rtcp_session 
     
    155156    pjmedia_rtp_seq_session seq_ctrl;   /**< RTCP sequence number control.  */ 
    156157 
    157     unsigned        clock_rate;     /**< Clock rate.                        */ 
    158     pj_uint32_t     received;       /**< # pkts received                    */ 
    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.     */ 
    169170}; 
    170171 
     
    220221 
    221222/** 
    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 */ 
     231PJ_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  
    226243 *                  RTCP packet. 
    227  * @param len       [output] Upon return, it will indicate the size of  
     244 * @param len       Upon return, it will indicate the size of  
    228245 *                  the RTCP packet. 
    229246 */ 
    230247PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session,  
    231248                                       pjmedia_rtcp_pkt **rtcp_pkt,  
    232                                        int *len ); 
     249                                       int *len); 
    233250 
    234251 
  • pjproject/trunk/pjmedia/src/pjmedia/rtcp.c

    r381 r383  
    1919#include <pjmedia/rtcp.h> 
    2020#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> 
    2425 
    2526 
     
    2829 
    2930 
    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 
    3134 
    3235 
     
    3437 * Get NTP time. 
    3538 */ 
    36 static void rtcp_get_ntp_time(struct pjmedia_rtcp_ntp_rec *ntp) 
     39static void rtcp_get_ntp_time(const pjmedia_rtcp_session *s,  
     40                              struct pjmedia_rtcp_ntp_rec *ntp) 
    3741{ 
    3842    pj_time_val tv; 
     43    pj_timestamp ts; 
    3944 
    4045    pj_gettimeofday(&tv); 
    41      
     46    pj_get_timestamp(&ts); 
     47     
     48    /* Fill up the high 32bit part */ 
    4249    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; 
    4657} 
    4758 
     
    6071    /* Init time */ 
    6172    s->rtcp_lsr.hi = s->rtcp_lsr.lo = 0; 
    62     s->rtcp_lsr_time = 0; 
     73    s->rtcp_lsr_time.u64 = 0; 
    6374     
    6475    /* Init common RTCP header */ 
     
    7283     
    7384    /* Get timestamp frequency */ 
    74 #if USE_TIMESTAMP 
    7585    pj_get_timestamp_freq(&s->ts_freq); 
    76 #endif 
    7786 
    7887    /* RR will be initialized on receipt of the first RTP packet. */ 
    7988} 
     89 
    8090 
    8191PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *session) 
     
    8898{ 
    8999    s->received = 0; 
    90     s->expected_prior = 0; 
    91     s->received_prior = 0; 
     100    s->exp_prior = 0; 
     101    s->rx_prior = 0; 
    92102    s->transit = 0; 
    93103    s->jitter = 0; 
     
    100110                                 pj_uint32_t rtp_ts) 
    101111{    
     112    pj_timestamp ts; 
    102113    pj_uint32_t arrival; 
    103114    pj_int32_t transit; 
     
    117128 
    118129    /* 
    119      * Calculate jitter (s->jitter is in timer tick unit) 
     130     * Calculate jitter (see RFC 3550 section A.8) 
    120131     */ 
    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; 
    143137 
    144138    transit = arrival - rtp_ts; 
     
    147141        s->transit = transit; 
    148142    } else { 
    149         pj_int32_t d, jitter = s->jitter; 
     143        pj_int32_t d; 
    150144         
    151145        d = transit - s->transit; 
     
    154148            d = -d; 
    155149         
    156         jitter += d - ((jitter + 8) >> 4); 
    157         s->jitter = jitter; 
     150        s->jitter += d - ((s->jitter + 8) >> 4); 
    158151    } 
    159152} 
     
    163156{ 
    164157    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 
     169PJ_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 
    168217 
    169218static void rtcp_build_rtcp(pjmedia_rtcp_session *s,  
     
    185234     
    186235    /* 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; 
    188237    u32 = expected - s->received; 
    189     if (u32 == 1) u32 = 0; 
    190238    rtcp_pkt->rr.total_lost_2 = (u32 >> 16) & 0x00FF; 
    191239    rtcp_pkt->rr.total_lost_1 = (u32 >> 8) & 0x00FF; 
     
    193241 
    194242    /* Fraction lost calculation */ 
    195     expected_interval = expected - s->expected_prior; 
    196     s->expected_prior = expected; 
    197      
    198     received_interval = s->received - s->received_prior; 
    199     s->received_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; 
    200248     
    201249    lost_interval = expected_interval - received_interval; 
     
    214262    pjmedia_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt; 
    215263    pjmedia_rtcp_ntp_rec ntp; 
    216     pj_time_val now; 
    217264     
    218265    rtcp_build_rtcp(session, session->peer_ssrc); 
    219266     
    220267    /* Get current NTP time. */ 
    221     rtcp_get_ntp_time(&ntp); 
     268    rtcp_get_ntp_time(session, &ntp); 
    222269     
    223270    /* Fill in NTP timestamp in SR. */ 
     
    225272    rtcp_pkt->sr.ntp_frac = pj_htonl(ntp.lo); 
    226273     
    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) { 
    228275        rtcp_pkt->rr.lsr = 0; 
    229276        rtcp_pkt->rr.dlsr = 0; 
    230277    } else { 
    231         unsigned msec_elapsed; 
     278        pj_timestamp ts; 
    232279         
    233280        /* Fill in LSR. 
     
    241288           DLSR is Delay since Last SR, in 1/65536 seconds. 
    242289         */ 
    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 
    248300    /* Return pointer. */ 
    249301    *ret_p_pkt = rtcp_pkt; 
     
    251303} 
    252304 
     305  
  • pjproject/trunk/pjsip-apps/src/samples/siprtp.c

    r382 r383  
    11141114                    pj_memcpy(&strm->rem_rtcp, packet, size); 
    11151115                    status = PJ_SUCCESS; 
     1116 
     1117                    /* Report receipt of RTCP to RTCP session */ 
     1118                    pjmedia_rtcp_rx_rtcp(&strm->rtcp, packet, size); 
    11161119                } 
    11171120            } 
     
    15251528           ); 
    15261529 
     1530    printf("              End to end delay: %u ms\n", audio->rtcp.ee_delay); 
     1531 
    15271532} 
    15281533 
Note: See TracChangeset for help on using the changeset viewer.