]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Calculate the timestamp for outbound RTP if we don't have timing information
authorMatthew Jordan <mjordan@digium.com>
Sun, 14 Apr 2013 02:58:57 +0000 (02:58 +0000)
committerMatthew Jordan <mjordan@digium.com>
Sun, 14 Apr 2013 02:58:57 +0000 (02:58 +0000)
This patch calculates the timestamp for outbound RTP when we don't have timing
information. This uses the same approach in res_rtp_asterisk. Thanks to both
Pietro and Tzafrir for providing patches.

(closes issue ASTERISK-19883)
Reported by: Giacomo Trovato
Tested by: Pietro Bertera, Tzafrir Cohen
patches:
  rtp-timestamp-1.8.patch uploaded by tzafrir (License 5035)
  rtp-timestamp.patch uploaded by pbertera (License 5943)

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@385636 65c4cc65-6c06-0410-ace0-fbb531ad65f3

res/res_rtp_multicast.c

index d5b1c143d70cd980e3c04a46c700be899b40eae7..2b5cbbc82aaaac3e84d4e6ec24841a696d05fd5b 100644 (file)
@@ -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);