aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2009-12-20 13:16:14 +0100
committerHarald Welte <laforge@netfilter.org>2009-12-20 13:36:42 +0100
commit392736d38bf9dae29800bde630c9ceee8a3914f3 (patch)
tree3c1626eb5a825579b395627f51cad3c8745e9331
parent31981a0051682c59fc5bcebfa1ac4e3086103b25 (diff)
RTP Proxy: Fix RTP sequence number and timestamp in case of dropped frames
During handover, we will not send RTP frames for quite some time. However, the way the rtp_send code is structured, it will increment the timestamp with a fixed amount every time we send a frame, independent how much wallclock time has actually passed. This code is a hack to update the sequence number and timestamp in case it seems to be wrong. It makes handover much more reliable.
-rw-r--r--openbsc/include/openbsc/rtp_proxy.h1
-rw-r--r--openbsc/src/rtp_proxy.c35
2 files changed, 36 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/rtp_proxy.h b/openbsc/include/openbsc/rtp_proxy.h
index a3e45964..d128e4f2 100644
--- a/openbsc/include/openbsc/rtp_proxy.h
+++ b/openbsc/include/openbsc/rtp_proxy.h
@@ -70,6 +70,7 @@ struct rtp_socket {
u_int16_t sequence;
u_int32_t timestamp;
u_int32_t ssrc;
+ struct timeval last_tv;
} transmit;
};
diff --git a/openbsc/src/rtp_proxy.c b/openbsc/src/rtp_proxy.c
index 55134975..02938125 100644
--- a/openbsc/src/rtp_proxy.c
+++ b/openbsc/src/rtp_proxy.c
@@ -176,6 +176,21 @@ static int rtp_decode(struct msgb *msg, u_int32_t callref, struct msgb **data)
return 0;
}
+/* "to - from" */
+static void tv_difference(struct timeval *diff, const struct timeval *from,
+ const struct timeval *__to)
+{
+ struct timeval _to = *__to, *to = &_to;
+
+ if (to->tv_usec < from->tv_usec) {
+ to->tv_sec -= 1;
+ to->tv_usec += 1000000;
+ }
+
+ diff->tv_usec = to->tv_usec - from->tv_usec;
+ diff->tv_sec = to->tv_sec - from->tv_sec;
+}
+
/* encode and send a rtp frame */
int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
{
@@ -211,6 +226,26 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
return -EINVAL;
}
+ {
+ struct timeval tv, tv_diff;
+ long int usec_diff, frame_diff;
+
+ gettimeofday(&tv, NULL);
+ tv_difference(&tv_diff, &rs->transmit.last_tv, &tv);
+ rs->transmit.last_tv = tv;
+
+ usec_diff = tv_diff.tv_sec * 1000000 + tv_diff.tv_usec;
+ frame_diff = (usec_diff / 20000);
+
+ if (abs(frame_diff) > 1) {
+ long int frame_diff_excess = frame_diff - 1;
+
+ DEBUGP(DMUX, "Correcting frame difference of %ld frames\n", frame_diff_excess);
+ rs->transmit.sequence += frame_diff_excess;
+ rs->transmit.timestamp += frame_diff_excess * duration;
+ }
+ }
+
msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM-FULL");
if (!msg)
return -ENOMEM;