From c8352843dbe81afaf8e6daffaeb76d0138806162 Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Mon, 8 Apr 2013 12:56:23 +0300 Subject: [PATCH] Fix timestamps in RTP Multicast Bug: https://issues.asterisk.org/jira/browse/ASTERISK-19883 --- res/res_rtp_multicast.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 40 insertions(+), 2 deletions(-) diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c index d5b1c14..2b5cbbc 100644 --- a/res/res_rtp_multicast.c +++ b/res/res_rtp_multicast.c @@ -90,6 +90,8 @@ struct multicast_rtp { unsigned int ssrc; /*! Sequence number, used when creating/sending the RTP packet */ uint16_t seqno; + unsigned int lastts; + struct timeval txcore; }; /* Forward Declarations */ @@ -140,6 +142,30 @@ static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_con return 0; } +static int rtp_get_rate(format_t format) +{ + return (format == AST_FORMAT_G722) ? 8000 : ast_format_rate(format); +} + +static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery) +{ + struct timeval t; + long ms; + + if (ast_tvzero(rtp->txcore)) { + rtp->txcore = ast_tvnow(); + rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; + } + + t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); + if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) { + ms = 0; + } + rtp->txcore = t; + + return (unsigned int) ms; +} + /*! \brief Helper function which populates a control packet with useful information and sends it */ static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command) { @@ -209,12 +235,15 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra struct ast_frame *f = frame; struct ast_sockaddr remote_address; int hdrlen = 12, res = 0, codec; + int rate; unsigned char *rtpheader; + unsigned int ms = calc_txstamp(multicast, &frame->delivery); /* We only accept audio, nothing else */ if (frame->frametype != AST_FRAME_VOICE) { return 0; } + rate = rtp_get_rate(frame->subclass.codec) / 1000; /* Grab the actual payload number for when we create the RTP packet */ if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) { @@ -226,11 +255,20 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra f = ast_frdup(frame); } + /* Calucate last TS */ + multicast->lastts = multicast->lastts + ms * rate; + /* Construct an RTP header for our packet */ rtpheader = (unsigned char *)(f->data.ptr - hdrlen); put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno))); - put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8)); - put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc)); + put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts)); + + if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) { + put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8)); + } + else { + put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc)); + } /* Increment sequence number and wrap to 0 if it overflows 16 bits. */ multicast->seqno = 0xFFFF & (multicast->seqno + 1); -- 1.7.4.1