From 102399153cc12f988c4e1039caab8cd159dd1019 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 4 Apr 2006 19:43:24 +0000 Subject: Changed RTCP timing to use high resolution timestamp git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@381 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/rtcp.h | 6 +++- pjmedia/src/pjmedia/rtcp.c | 40 +++++++++++++++++++---- pjmedia/src/pjmedia/stream.c | 2 +- pjsip-apps/src/samples/siprtp.c | 71 +++++++++++++++++++++++++---------------- 4 files changed, 83 insertions(+), 36 deletions(-) diff --git a/pjmedia/include/pjmedia/rtcp.h b/pjmedia/include/pjmedia/rtcp.h index f39c7800..ccd32a20 100644 --- a/pjmedia/include/pjmedia/rtcp.h +++ b/pjmedia/include/pjmedia/rtcp.h @@ -27,6 +27,7 @@ #include #include + PJ_BEGIN_DECL @@ -148,12 +149,14 @@ struct pjmedia_rtcp_session pjmedia_rtp_seq_session seq_ctrl; /**< RTCP sequence number control. */ + unsigned clock_rate; /**< Clock rate. */ pj_uint32_t received; /**< # pkts received */ pj_uint32_t expected_prior; /**< # pkts expected at last interval */ pj_uint32_t received_prior; /**< # pkts received at last interval */ pj_int32_t transit; /**< Relative trans time for prev pkt */ pj_uint32_t jitter; /**< Estimated jitter */ - + pj_timestamp ts_freq; /**< System timestamp frequency. */ + pjmedia_rtcp_ntp_rec rtcp_lsr; /**< NTP ts in last SR received */ unsigned rtcp_lsr_time; /**< Time when last SR is received.*/ pj_uint32_t peer_ssrc; /**< Peer SSRC */ @@ -173,6 +176,7 @@ typedef struct pjmedia_rtcp_session pjmedia_rtcp_session; * @param ssrc The SSRC used in to identify the session. */ PJ_DECL(void) pjmedia_rtcp_init( pjmedia_rtcp_session *session, + unsigned clock_rate, pj_uint32_t ssrc ); diff --git a/pjmedia/src/pjmedia/rtcp.c b/pjmedia/src/pjmedia/rtcp.c index 7bd5a7d8..3ce2783e 100644 --- a/pjmedia/src/pjmedia/rtcp.c +++ b/pjmedia/src/pjmedia/rtcp.c @@ -27,6 +27,8 @@ #define RTCP_RR 201 +#define USE_TIMESTAMP PJ_HAS_HIGH_RES_TIMER + /* * Get NTP time. @@ -45,12 +47,16 @@ static void rtcp_get_ntp_time(struct pjmedia_rtcp_ntp_rec *ntp) PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *s, + unsigned clock_rate, pj_uint32_t ssrc) { pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; pj_memset(rtcp_pkt, 0, sizeof(pjmedia_rtcp_pkt)); + /* Set clock rate */ + s->clock_rate = clock_rate; + /* Init time */ s->rtcp_lsr.hi = s->rtcp_lsr.lo = 0; s->rtcp_lsr_time = 0; @@ -64,6 +70,11 @@ PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *s, /* Init SR */ rtcp_pkt->sr.ssrc = pj_htonl(ssrc); + /* Get timestamp frequency */ +#if USE_TIMESTAMP + pj_get_timestamp_freq(&s->ts_freq); +#endif + /* RR will be initialized on receipt of the first RTP packet. */ } @@ -90,8 +101,6 @@ PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *s, { pj_uint32_t arrival; pj_int32_t transit; - unsigned long timer_tick; - pj_time_val tv; int status; /* Update sequence numbers (received, lost, etc). */ @@ -106,15 +115,32 @@ PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *s, ++s->received; - pj_gettimeofday(&tv); - timer_tick = tv.sec * 1000 + tv.msec; - /* * Calculate jitter (s->jitter is in timer tick unit) */ - PJ_TODO(SUPPORT_JITTER_CALCULATION_FOR_NON_8KHZ_SAMPLE_RATE) +#if USE_TIMESTAMP + { + pj_timestamp ts; + + pj_get_timestamp(&ts); + + /* Convert timestamp to samples */ + ts.u64 = ts.u64 * s->clock_rate / s->ts_freq.u64; + arrival = (pj_uint32_t)ts.u64; + } +#else + { + pj_time_val tv; + unsigned long timer_tick; + + pj_gettimeofday(&tv); + timer_tick = tv.sec * 1000 + tv.msec; + + /* Convert timer tick to samples */ + arrival = timer_tick * s->clock_rate / 1000; + } +#endif - arrival = timer_tick << 3; // 8 samples per ms. transit = arrival - rtp_ts; if (s->transit == 0) { diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index 95d9a7c9..6f0d4881 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -738,7 +738,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, /* Init RTCP session: */ - pjmedia_rtcp_init(&stream->rtcp, info->ssrc); + pjmedia_rtcp_init(&stream->rtcp, info->fmt.sample_rate, info->ssrc); /* Create jitter buffer: */ diff --git a/pjsip-apps/src/samples/siprtp.c b/pjsip-apps/src/samples/siprtp.c index 9cdb3a8f..ab59dd2a 100644 --- a/pjsip-apps/src/samples/siprtp.c +++ b/pjsip-apps/src/samples/siprtp.c @@ -29,6 +29,11 @@ #include + +#if PJ_HAS_HIGH_RES_TIMER==0 +# error "High resolution timer is needed for this sample" +#endif + #define THIS_FILE "siprtp.c" #define MAX_CALLS 1024 #define RTP_START_PORT 44100 @@ -988,35 +993,46 @@ static pj_status_t create_sdp( pj_pool_t *pool, */ static int media_thread(void *arg) { + enum { RTCP_INTERVAL = 5 }; struct media_stream *strm = arg; char packet[1500]; - pj_time_val next_rtp, next_rtcp; + unsigned msec_interval; + pj_timestamp freq, next_rtp, next_rtcp; - pj_gettimeofday(&next_rtp); - next_rtp.msec += strm->samples_per_frame * 1000 / strm->clock_rate; - pj_time_val_normalize(&next_rtp); + msec_interval = strm->samples_per_frame * 1000 / strm->clock_rate; + pj_get_timestamp_freq(&freq); + + pj_get_timestamp(&next_rtp); + next_rtp.u64 += (freq.u64 * msec_interval / 1000); next_rtcp = next_rtp; - next_rtcp.sec += 5; + next_rtcp.u64 += (freq.u64 * RTCP_INTERVAL); while (!strm->thread_quit_flag) { pj_fd_set_t set; - pj_time_val now, lesser, timeout; + pj_timestamp now, lesser; + pj_time_val timeout; int rc; /* Determine how long to sleep */ - if (PJ_TIME_VAL_LT(next_rtp, next_rtcp)) + if (next_rtp.u64 < next_rtcp.u64) lesser = next_rtp; else lesser = next_rtcp; - pj_gettimeofday(&now); - if (PJ_TIME_VAL_LTE(lesser, now)) + pj_get_timestamp(&now); + if (lesser.u64 <= now.u64) { timeout.sec = timeout.msec = 0; - else { - timeout = lesser; - PJ_TIME_VAL_SUB(timeout, now); + //printf("immediate "); fflush(stdout); + } else { + pj_uint64_t tick_delay; + tick_delay = lesser.u64 - now.u64; + timeout.sec = 0; + timeout.msec = (pj_uint32_t)(tick_delay * 1000 / freq.u64); + pj_time_val_normalize(&timeout); + + //printf("%d:%03d ", timeout.sec, timeout.msec); fflush(stdout); } PJ_FD_ZERO(&set); @@ -1025,7 +1041,7 @@ static int media_thread(void *arg) rc = pj_sock_select(FD_SETSIZE, &set, NULL, NULL, &timeout); - if (PJ_FD_ISSET(strm->rtp_sock, &set)) { + if (rc > 0 && PJ_FD_ISSET(strm->rtp_sock, &set)) { /* * Process incoming RTP packet. @@ -1074,7 +1090,9 @@ static int media_thread(void *arg) pjmedia_rtcp_rx_rtp(&strm->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); - } else if (PJ_FD_ISSET(strm->rtcp_sock, &set)) { + } + + if (rc > 0 && PJ_FD_ISSET(strm->rtcp_sock, &set)) { /* * Process incoming RTCP @@ -1114,9 +1132,9 @@ static int media_thread(void *arg) } - pj_gettimeofday(&now); + pj_get_timestamp(&now); - if (PJ_TIME_VAL_LTE(next_rtp, now)) { + if (next_rtp.u64 <= now.u64) { /* * Time to send RTP packet. */ @@ -1154,8 +1172,7 @@ static int media_thread(void *arg) pjmedia_rtcp_tx_rtp( &strm->rtcp, (pj_uint16_t)strm->bytes_per_frame); /* Schedule next send */ - next_rtp.msec += strm->samples_per_frame * 1000 / strm->clock_rate; - pj_time_val_normalize(&next_rtp); + next_rtp.u64 += (msec_interval * freq.u64 / 1000); /* Update stats */ strm->tx_stat.pkt++; @@ -1163,7 +1180,7 @@ static int media_thread(void *arg) } - if (PJ_TIME_VAL_LTE(next_rtcp, now)) { + if (next_rtcp.u64 <= now.u64) { /* * Time to send RTCP packet. */ @@ -1208,7 +1225,7 @@ static int media_thread(void *arg) strm->rx_stat.rtcp_cnt++; } - next_rtcp.sec += 5; + next_rtcp.u64 += (freq.u64 * RTCP_INTERVAL); } } @@ -1281,7 +1298,7 @@ static void call_on_media_update( pjsip_inv_session *inv, pjmedia_rtp_session_init(&audio->out_sess, audio->si.tx_pt, pj_rand()); pjmedia_rtp_session_init(&audio->in_sess, audio->si.fmt.pt, 0); - pjmedia_rtcp_init(&audio->rtcp, 0); + pjmedia_rtcp_init(&audio->rtcp, audio->clock_rate, 0); /* Clear media statistics */ @@ -1779,6 +1796,12 @@ int main(int argc, char *argv[]) return 1; } + /* Start worker threads */ + for (i=0; i