summaryrefslogtreecommitdiffstats
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
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.
-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;
}
}