diff options
author | Pablo Neira Ayuso <pablo@gnumonks.org> | 2013-05-21 00:28:13 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@gnumonks.org> | 2013-05-21 00:48:13 +0200 |
commit | 56c4681d8374328b7e50a755e09471bfb52e6b4a (patch) | |
tree | 93e6adc7f20d1485b87c3a4f530e582e44d22e8d | |
parent | a9ab95c2c4efae10119212dcc18b046afe9601f4 (diff) |
osmux: replay last RTP packet seen under packet loss scenario
If osmux notices a gap between two RTP packets, fill it with
the last RTP packet seen. Without this patch, 10% of packet loss
is enough to get garbage, with it we get glitches in the conversation
with 30%, and pretty much broken conversation with 40% of it.
-rw-r--r-- | src/osmux.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/osmux.c b/src/osmux.c index c8e8557..33ab7ad 100644 --- a/src/osmux.c +++ b/src/osmux.c @@ -305,6 +305,54 @@ static int osmux_rtp_amr_payload_len(struct msgb *msg, struct rtp_hdr *rtph) return amr_len - sizeof(struct amr_hdr); } +static void osmux_replay_lost_packets(struct batch_list_node *node, + struct rtp_hdr *cur_rtph) +{ + uint16_t diff; + struct msgb *last; + struct rtp_hdr *rtph; + int i; + + /* Have we see any RTP packet in this batch before? */ + if (llist_empty(&node->list)) + return; + + /* Get last RTP packet seen in this batch */ + last = llist_entry(node->list.prev, struct msgb, list); + rtph = osmo_rtp_get_hdr(last); + if (rtph == NULL) + return; + + diff = ntohs(cur_rtph->sequence) - ntohs(rtph->sequence); + + /* If diff between last RTP packet seen and this one is > 1, + * then we lost several RTP packets, let's replay them. + */ + for (i=1; i<diff; i++) { + struct msgb *clone; + + /* Clone last RTP packet seen */ + clone = msgb_alloc(last->data_len, "RTP clone"); + if (!clone) + continue; + + memcpy(clone->data, last->data, last->len); + msgb_put(clone, last->len); + + rtph = osmo_rtp_get_hdr(clone); + if (rtph == NULL) + return; + + /* Adjust sequence number and timestamp */ + rtph->sequence = htons(ntohs(rtph->sequence) + i); + rtph->timestamp = htonl(ntohl(rtph->timestamp) + + DELTA_RTP_TIMESTAMP); + + LOGP(DLMIB, LOGL_ERROR, "adding cloned RTP\n"); + llist_add_tail(&clone->list, &node->list); + } +} + static int osmux_batch_add(struct osmux_batch *batch, struct msgb *msg, int ccid) { @@ -352,6 +400,9 @@ osmux_batch_add(struct osmux_batch *batch, struct msgb *msg, int ccid) return 0; } } + /* Handle RTP packet loss scenario */ + osmux_replay_lost_packets(node, rtph); + } else { /* This is the first message with that ssrc we've seen */ node = talloc_zero(osmux_ctx, struct batch_list_node); |