summaryrefslogtreecommitdiff
path: root/res/res_rtp_multicast.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-04-14 03:01:33 +0000
committerMatthew Jordan <mjordan@digium.com>2013-04-14 03:01:33 +0000
commit2dd40e970737913363f4298242b83cf4c2d8b8a2 (patch)
tree1c762d3c14d93760fd8373f80bc9fa6dadbbf960 /res/res_rtp_multicast.c
parent51117442149cbe9b0f7e25487f22a970bffda682 (diff)
Calculate the timestamp for outbound RTP if we don't have timing information
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) ........ Merged revisions 385636 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 385637 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@385638 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_rtp_multicast.c')
-rw-r--r--res/res_rtp_multicast.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 3f3c3773b..2b6678d11 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 ast_sched
return 0;
}
+static int rtp_get_rate(struct ast_format *format)
+{
+ return (format->id == 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)
{
@@ -210,6 +236,8 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
struct ast_sockaddr remote_address;
int hdrlen = 12, res = 0, codec;
unsigned char *rtpheader;
+ unsigned int ms = calc_txstamp(multicast, &frame->delivery);
+ int rate = rtp_get_rate(&frame->subclass.format) / 1000;
/* We only accept audio, nothing else */
if (frame->frametype != AST_FRAME_VOICE) {
@@ -225,12 +253,21 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
if (frame->offset < hdrlen) {
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);