[PATCH 8/9] Fixed (nanoBTS) delay problems, if RTP stream jitters too much

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

Andreas Eversberg jolly at eversberg.eu
Wed Jan 22 09:05:57 UTC 2014


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.
---
 openbsc/src/libtrau/rtp_proxy.c | 80 ++++++++++++++++++++++++++++++-----------
 1 file changed, 59 insertions(+), 21 deletions(-)

diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index ed7479d..3e6c462 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -236,6 +236,12 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data, in
 	return 0;
 }
 
+#define USEC_1S 1000000
+#define USEC_10MS 10000
+#define USEC_20MS 20000
+#define SAMPLES_1S 8000
+#define USEC_SAMPLE 125
+
 /* "to - from" */
 static void tv_difference(struct timeval *diff, const struct timeval *from,
 			  const struct timeval *__to)
@@ -244,13 +250,60 @@ static void tv_difference(struct timeval *diff, const struct timeval *from,
 
 	if (to->tv_usec < from->tv_usec) {
 		to->tv_sec -= 1;
-		to->tv_usec += 1000000;
+		to->tv_usec += USEC_1S;
 	}
 
 	diff->tv_usec = to->tv_usec - from->tv_usec;
 	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 += USEC_1S;
+	tv->tv_sec += sec;
+	tv->tv_usec += usec;
+	if (tv->tv_usec >= USEC_1S) {
+		tv->tv_sec++;
+		tv->tv_usec -= USEC_1S;
+	}
+}
+
+static int correct_timestamp(struct rtp_socket *rs, int duration)
+{
+	struct timeval tv, tv_diff;
+	long int usec_diff, frame_diff;
+
+	gettimeofday(&tv, NULL);
+	tv_difference(&tv_diff, &rs->transmit.last_tv, &tv);
+	tv_add(&rs->transmit.last_tv, 0, USEC_20MS);
+
+	usec_diff = tv_diff.tv_sec * USEC_1S + tv_diff.tv_usec;
+	frame_diff = ((usec_diff + (USEC_10MS)) / USEC_20MS); /* round */
+
+	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 / SAMPLES_1S,
+			(sample_diff_excess % SAMPLES_1S) * USEC_SAMPLE);
+		/* drop frame, if time stamp is in the past */
+		if (frame_diff_excess < 0)
+			return -1;
+		LOGP(DLMUX, LOGL_NOTICE,
+			"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 += sample_diff_excess;
+	}
+
+	return 0;
+}
+
 /*! \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 +318,7 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
 	int duration; /* in samples */
 	int amr = 0;
 	uint8_t dynamic_pt = 0;
+	int rc;
 
 	if (rs->rx_action == RTP_RECV_L4)
 		dynamic_pt = rs->receive.payload_type;
@@ -275,6 +329,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) {
@@ -313,26 +368,9 @@ 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;
-
-			LOGP(DLMUX, LOGL_NOTICE,
-				"Correcting frame difference of %ld frames\n", frame_diff_excess);
-			rs->transmit.sequence += frame_diff_excess;
-			rs->transmit.timestamp += frame_diff_excess * duration;
-		}
-	}
+	rc = correct_timestamp(rs, duration);
+	if (rc)
+		return 0;
 
 	if (frame->msg_type == GSM_BAD_FRAME)
 		return 0;
-- 
1.8.1.5





More information about the OpenBSC mailing list