summaryrefslogtreecommitdiff
path: root/res/res_rtp_multicast.c
diff options
context:
space:
mode:
authorSean Bright <sean.bright@gmail.com>2017-06-06 11:04:44 -0400
committerSean Bright <sean.bright@gmail.com>2017-06-06 10:55:04 -0500
commitb3ca24d216120d6f6fa1440c73331bb85592ddf1 (patch)
tree99560ab3840a575b74815e998bf4ff92f1d5b41a /res/res_rtp_multicast.c
parent452e6315bb8be7578937de279aa1d906662faa20 (diff)
res_rtp_multicast: Use consistent timestamps when possible
When a frame destined for a MulticastRTP channel does not have timing information (such as when an 'originate' is done), we generate the RTP timestamps ourselves without regard to the number of samples we are about to send. Instead, use the same method as res_rtp_asterisk and 'predict' a timestamp given the number of samples. If the difference between the timestamp that we generate and the one we predict is within a specific threshold, use the predicted timestamp so that we end up with timestamps that are consistent with the number of samples we are actually sending. Change-Id: I2bf0db3541b1573043330421cbb114ff0f22ec1f
Diffstat (limited to 'res/res_rtp_multicast.c')
-rw-r--r--res/res_rtp_multicast.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 14176da41..72c53211b 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -99,6 +99,8 @@ struct multicast_rtp {
struct ast_smoother *smoother;
};
+#define MAX_TIMESTAMP_SKEW 640
+
enum {
OPT_CODEC = (1 << 0),
OPT_LOOP = (1 << 1),
@@ -415,21 +417,36 @@ static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *fr
unsigned char *rtpheader;
struct ast_sockaddr remote_address = { {0,} };
int rate = rtp_get_rate(frame->subclass.format) / 1000;
- int hdrlen = 12;
-
- /* Calculate last TS */
- multicast->lastts = multicast->lastts + ms * rate;
+ int hdrlen = 12, mark = 0;
- /* Construct an RTP header for our packet */
- rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
- put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
+ if (ast_format_cmp(frame->subclass.format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
+ frame->samples /= 2;
+ }
if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
- put_unaligned_uint32(rtpheader + 4, htonl(frame->ts * 8));
+ multicast->lastts = frame->ts * rate;
} else {
- put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
+ /* Try to predict what our timestamp should be */
+ int pred = multicast->lastts + frame->samples;
+
+ /* Calculate last TS */
+ multicast->lastts = multicast->lastts + ms * rate;
+ if (ast_tvzero(frame->delivery)) {
+ int delta = abs((int) multicast->lastts - pred);
+ if (delta < MAX_TIMESTAMP_SKEW) {
+ multicast->lastts = pred;
+ } else {
+ ast_debug(3, "Difference is %d, ms is %u\n", delta, ms);
+ mark = 1;
+ }
+ }
}
+ /* Construct an RTP header for our packet */
+ rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
+
+ put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno) | (mark << 23)));
+ put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
/* Increment sequence number and wrap to 0 if it overflows 16 bits. */