aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-03-08 11:08:37 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2017-12-01 03:37:42 +0100
commite5c7567607b4fb455206faddcae390053b73e220 (patch)
tree3da01328bad02f458596cdfa037c1a49542a6501
parent966eff030472aebe60e8300de0e4c05f3bc1112e (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--src/libtrau/rtp_proxy.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/src/libtrau/rtp_proxy.c b/src/libtrau/rtp_proxy.c
index fdcd5254f..58aadfc3c 100644
--- a/src/libtrau/rtp_proxy.c
+++ b/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;
}
}