From edf41a2c2f4d498833fcd92731f87a20955e5366 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 8 Mar 2012 11:08:37 +0100 Subject: 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. --- openbsc/src/libtrau/rtp_proxy.c | 36 ++++++++++++++++++++++++++++++------ 1 file 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; } } -- cgit v1.2.3