aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-03-08 11:08:37 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2013-07-29 12:34:13 +0200
commitedf41a2c2f4d498833fcd92731f87a20955e5366 (patch)
tree8db4f32a077dcea87006d80cd38d5ff77c65205c /openbsc/src
parent23ce6df082713157e9d3296251218ea51e5feafa (diff)
Fixed delay problems, if RTP stream jitters too much
The RTP stream is generated or forwarded by OpenBSC to nanoBTS. Due to switching of streams (hold/retrieve call), packet loss or even stalling of sender's process, the time stamp must be corrected. If outdated packets are received, they get dropped.
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/libtrau/rtp_proxy.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index fdcd5254f..58aadfc3c 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -242,6 +242,20 @@ static void tv_difference(struct timeval *diff, const struct timeval *from,
diff->tv_sec = to->tv_sec - from->tv_sec;
}
+/* add sec,usec to tv */
+static void tv_add(struct timeval *tv, int sec, int usec)
+{
+
+ if (usec < 0)
+ usec += 1000000;
+ tv->tv_sec += sec;
+ tv->tv_usec += usec;
+ if (tv->tv_usec >= 1000000) {
+ tv->tv_sec++;
+ tv->tv_usec -= 1000000;
+ }
+}
+
/*! \brief encode and send a rtp frame
* \param[in] rs RTP socket through which we shall send
* \param[in] frame GSM RTP frame to be sent
@@ -265,6 +279,7 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
rs->transmit.ssrc = rand();
rs->transmit.sequence = random();
rs->transmit.timestamp = random();
+ gettimeofday(&rs->transmit.last_tv, NULL);
}
switch (frame->msg_type) {
@@ -303,18 +318,27 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
gettimeofday(&tv, NULL);
tv_difference(&tv_diff, &rs->transmit.last_tv, &tv);
- rs->transmit.last_tv = tv;
+ tv_add(&rs->transmit.last_tv, 0, 20000);
usec_diff = tv_diff.tv_sec * 1000000 + tv_diff.tv_usec;
- frame_diff = (usec_diff / 20000);
+ frame_diff = ((usec_diff + 10000) / 20000); /* round */
- if (abs(frame_diff) > 1) {
+ if (abs(frame_diff - 1) > 1) {
long int frame_diff_excess = frame_diff - 1;
-
+ long int sample_diff_excess = frame_diff_excess * duration;
+
+ /* correct last_tv */
+ tv_add(&rs->transmit.last_tv, sample_diff_excess / 8000,
+ (sample_diff_excess % 8000) * 125);
+ /* drop frame, if time stamp is in the past */
+ if (frame_diff_excess < 0)
+ return 0;
LOGP(DLMUX, LOGL_NOTICE,
- "Correcting frame difference of %ld frames\n", frame_diff_excess);
+ "Correcting timestamp difference of %ld frames "
+ "(to %s)\n", frame_diff_excess,
+ (rs->rx_action == RTP_RECV_L4) ? "app" : "BTS");
rs->transmit.sequence += frame_diff_excess;
- rs->transmit.timestamp += frame_diff_excess * duration;
+ rs->transmit.timestamp += sample_diff_excess;
}
}