Peter Stuge wrote:
+       if (usec < 0)
>+           usec += USEC_1S;
Doesn't this also need to do sec--; ?


>+   tv->tv_sec += sec;
>+   tv->tv_usec += usec;
>+   if (tv->tv_usec >= USEC_1S) {
>+           tv->tv_sec++;
>+           tv->tv_usec -= USEC_1S;
>+   }
>+}
Consider changing the second if() to while(), so that the function
works correctly also when adding several seconds using only the usec
parameter.
dear peter,

thanx for looking at the patch. i fixed the missing "sec--" and added while loops. see attachment.

best regards,

andreas

>From 01bc8de69ebd68111122290f0109eecba53ec306 Mon Sep 17 00:00:00 2001
From: Andreas Eversberg <[email protected]>
Date: Thu, 8 Mar 2012 11:08:37 +0100
Subject: [PATCH 8/9] Fixed (nanoBTS) 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.
---
 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

Reply via email to