diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2012-03-08 11:08:37 +0100 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2017-12-01 03:37:42 +0100 |
commit | e5c7567607b4fb455206faddcae390053b73e220 (patch) | |
tree | 3da01328bad02f458596cdfa037c1a49542a6501 | |
parent | 966eff030472aebe60e8300de0e4c05f3bc1112e (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.c | 36 |
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; } } |