aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2013-05-21 00:28:13 +0200
committerPablo Neira Ayuso <pablo@gnumonks.org>2013-05-21 00:48:13 +0200
commit56c4681d8374328b7e50a755e09471bfb52e6b4a (patch)
tree93e6adc7f20d1485b87c3a4f530e582e44d22e8d /src
parenta9ab95c2c4efae10119212dcc18b046afe9601f4 (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.
Diffstat (limited to 'src')
-rw-r--r--src/osmux.c51
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);