summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-04-04 19:43:24 +0000
committerBenny Prijono <bennylp@teluu.com>2006-04-04 19:43:24 +0000
commit102399153cc12f988c4e1039caab8cd159dd1019 (patch)
treec1744cfabe9ed1cd33428ffaf90b65b298fea456
parent95b4193bb46c59b412d752c3315a4d0273109f34 (diff)
Changed RTCP timing to use high resolution timestamp
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@381 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia/rtcp.h6
-rw-r--r--pjmedia/src/pjmedia/rtcp.c40
-rw-r--r--pjmedia/src/pjmedia/stream.c2
-rw-r--r--pjsip-apps/src/samples/siprtp.c71
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 <pjmedia/types.h>
#include <pjmedia/rtp.h>
+
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 <stdlib.h>
+
+#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<app.thread_count; ++i) {
+ pj_thread_create( app.pool, "app", &worker_thread, NULL,
+ 0, 0, &app.thread[i]);
+ }
+
/* If URL is specified, then make call immediately */
if (app.uri_to_call.slen) {
unsigned i;
@@ -1800,12 +1823,6 @@ int main(int argc, char *argv[])
app.max_calls));
}
- /* Start worker threads */
- for (i=0; i<app.thread_count; ++i) {
- pj_thread_create( app.pool, "app", &worker_thread, NULL,
- 0, 0, &app.thread[i]);
- }
-
/* Start user interface loop */
console_main();