[asterisk-commits] file: branch file/rtp_engine r129683 - in /team/file/rtp_engine: include/aste...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jul 10 14:02:39 CDT 2008


Author: file
Date: Thu Jul 10 14:02:39 2008
New Revision: 129683

URL: http://svn.digium.com/view/asterisk?view=rev&rev=129683
Log:
Bring RTCP sending back.

Modified:
    team/file/rtp_engine/include/asterisk/rtp_engine.h
    team/file/rtp_engine/main/rtp_engine.c
    team/file/rtp_engine/res/res_rtp_asterisk.c

Modified: team/file/rtp_engine/include/asterisk/rtp_engine.h
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/include/asterisk/rtp_engine.h?view=diff&rev=129683&r1=129682&r2=129683
==============================================================================
--- team/file/rtp_engine/include/asterisk/rtp_engine.h (original)
+++ team/file/rtp_engine/include/asterisk/rtp_engine.h Thu Jul 10 14:02:39 2008
@@ -86,6 +86,7 @@
 	void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value); /*!< Callback for when an RTP property is set */
 	void (*payload_set)(struct ast_rtp_instance *instance, int payload, int AstFormat, int format); /*!< Callback for when a payload is set */
 	void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);      /*!< Callback for setting codec packetization preferences */
+	void (*remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);         /*!< Callback for when the remote address is set on an RTP instance */
 	int (*get_stats)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats);      /*!< Callback for retrieving statistics about the session */
 	int (*qos)(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);              /*!< Callback for setting QoS parameters on the RTP session */
 	int (*fd)(struct ast_rtp_instance *instance, int rtcp);                                         /*!< Callback for retrieving a file descriptor for RTP or RTCP */

Modified: team/file/rtp_engine/main/rtp_engine.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/main/rtp_engine.c?view=diff&rev=129683&r1=129682&r2=129683
==============================================================================
--- team/file/rtp_engine/main/rtp_engine.c (original)
+++ team/file/rtp_engine/main/rtp_engine.c Thu Jul 10 14:02:39 2008
@@ -266,6 +266,10 @@
 {
 	memcpy(&instance->remote_address, address, sizeof(instance->remote_address));
 
+	if (instance->engine->remote_address_set) {
+		instance->engine->remote_address_set(instance, address);
+	}
+
 	return 0;
 }
 

Modified: team/file/rtp_engine/res/res_rtp_asterisk.c
URL: http://svn.digium.com/view/asterisk/team/file/rtp_engine/res/res_rtp_asterisk.c?view=diff&rev=129683&r1=129682&r2=129683
==============================================================================
--- team/file/rtp_engine/res/res_rtp_asterisk.c (original)
+++ team/file/rtp_engine/res/res_rtp_asterisk.c Thu Jul 10 14:02:39 2008
@@ -234,6 +234,7 @@
 static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
 static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
 static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp);
+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
 
 /* RTP Engine Declaration */
 static struct ast_rtp_engine asterisk_rtp_engine = {
@@ -247,6 +248,7 @@
 	.read = ast_rtp_read,
 	.prop_set = ast_rtp_prop_set,
 	.fd = ast_rtp_fd,
+	.remote_address_set = ast_rtp_remote_address_set,
 };
 
 static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
@@ -279,6 +281,15 @@
 	}
 	
 	return 1;
+}
+
+static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
+{
+        unsigned int interval;
+        /*! \todo XXX Do a more reasonable calculation on this one
+         * Look in RFC 3550 Section A.7 for an example*/
+        interval = rtcpinterval;
+        return interval;
 }
 
 /*! \brief Calculate normal deviation */
@@ -604,6 +615,264 @@
 	rtp->txcore = t;
 	
 	return (unsigned int) ms;
+}
+
+static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
+{
+        unsigned int sec, usec, frac;
+        sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
+        usec = tv.tv_usec;
+        frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
+        *msw = sec;
+        *lsw = frac;
+}
+
+/*! \brief Send RTCP recipient's report */
+static int ast_rtcp_write_rr(const void *data)
+{
+        struct ast_rtp *rtp = (struct ast_rtp *)data;
+        int res;
+        int len = 32;
+        unsigned int lost;
+        unsigned int extended;
+        unsigned int expected;
+        unsigned int expected_interval;
+        unsigned int received_interval;
+        int lost_interval;
+        struct timeval now;
+        unsigned int *rtcpheader;
+        char bdata[1024];
+        struct timeval dlsr;
+        int fraction;
+
+        double rxlost_current;
+
+        if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
+                return 0;
+
+        if (!rtp->rtcp->them.sin_addr.s_addr) {
+                ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
+                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+                return 0;
+        }
+
+        extended = rtp->cycles + rtp->lastrxseqno;
+        expected = extended - rtp->seedrxseqno + 1;
+        lost = expected - rtp->rxcount;
+        expected_interval = expected - rtp->rtcp->expected_prior;
+        rtp->rtcp->expected_prior = expected;
+        received_interval = rtp->rxcount - rtp->rtcp->received_prior;
+        rtp->rtcp->received_prior = rtp->rxcount;
+        lost_interval = expected_interval - received_interval;
+
+        if (lost_interval <= 0)
+                rtp->rtcp->rxlost = 0;
+        else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
+        if (rtp->rtcp->rxlost_count == 0)
+                rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
+        if (lost_interval < rtp->rtcp->minrxlost)
+                rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
+        if (lost_interval > rtp->rtcp->maxrxlost)
+                rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
+
+        rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
+        rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
+        rtp->rtcp->normdev_rxlost = rxlost_current;
+        rtp->rtcp->rxlost_count++;
+
+        if (expected_interval == 0 || lost_interval <= 0)
+                fraction = 0;
+        else
+                fraction = (lost_interval << 8) / expected_interval;
+        gettimeofday(&now, NULL);
+        timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
+        rtcpheader = (unsigned int *)bdata;
+        rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
+        rtcpheader[1] = htonl(rtp->ssrc);
+        rtcpheader[2] = htonl(rtp->themssrc);
+        rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
+        rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
+        rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
+        rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
+        rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
+
+        /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
+	  it can change mid call, and SDES can't) */
+        rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
+        rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
+        rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
+        len += 12;
+
+        res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+
+        if (res < 0) {
+                ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
+                /* Remove the scheduler */
+                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+                return 0;
+        }
+
+        rtp->rtcp->rr_count++;
+        if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+                ast_verbose("\n* Sending RTCP RR to %s:%d\n"
+                        "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
+                        "  IA jitter: %.4f\n"
+                        "  Their last SR: %u\n"
+			    "  DLSR: %4.4f (sec)\n\n",
+			    ast_inet_ntoa(rtp->rtcp->them.sin_addr),
+			    ntohs(rtp->rtcp->them.sin_port),
+			    rtp->ssrc, rtp->themssrc, fraction, lost,
+			    rtp->rxjitter,
+			    rtp->rtcp->themrxlsr,
+			    (double)(ntohl(rtcpheader[7])/65536.0));
+        }
+
+        return res;
+}
+
+/*! \brief Send RTCP sender's report */
+static int ast_rtcp_write_sr(const void *data)
+{
+        struct ast_rtp *rtp = (struct ast_rtp *)data;
+        int res;
+        int len = 0;
+        struct timeval now;
+        unsigned int now_lsw;
+        unsigned int now_msw;
+        unsigned int *rtcpheader;
+        unsigned int lost;
+        unsigned int extended;
+        unsigned int expected;
+        unsigned int expected_interval;
+        unsigned int received_interval;
+        int lost_interval;
+        int fraction;
+        struct timeval dlsr;
+        char bdata[512];
+
+        /* Commented condition is always not NULL if rtp->rtcp is not NULL */
+        if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
+                return 0;
+
+        if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
+                ast_verbose("RTCP SR transmission error, rtcp halted\n");
+                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+                return 0;
+        }
+
+        gettimeofday(&now, NULL);
+        timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
+        rtcpheader = (unsigned int *)bdata;
+        rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
+        rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
+        rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
+        rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
+        rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
+        rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
+        len += 28;
+
+        extended = rtp->cycles + rtp->lastrxseqno;
+        expected = extended - rtp->seedrxseqno + 1;
+        if (rtp->rxcount > expected)
+                expected += rtp->rxcount - expected;
+        lost = expected - rtp->rxcount;
+        expected_interval = expected - rtp->rtcp->expected_prior;
+        rtp->rtcp->expected_prior = expected;
+        received_interval = rtp->rxcount - rtp->rtcp->received_prior;
+        rtp->rtcp->received_prior = rtp->rxcount;
+        lost_interval = expected_interval - received_interval;
+        if (expected_interval == 0 || lost_interval <= 0)
+                fraction = 0;
+        else
+                fraction = (lost_interval << 8) / expected_interval;
+        timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
+        rtcpheader[7] = htonl(rtp->themssrc);
+        rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
+        rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
+        rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
+        rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
+        rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
+        len += 24;
+
+        rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
+
+        /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
+        /* it can change mid call, and SDES can't) */
+        rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
+        rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
+        rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
+        len += 12;
+
+        res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+        if (res < 0) {
+                ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
+                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+                return 0;
+        }
+
+        /* FIXME Don't need to get a new one */
+        gettimeofday(&rtp->rtcp->txlsr, NULL);
+        rtp->rtcp->sr_count++;
+
+        rtp->rtcp->lastsrtxcount = rtp->txcount;
+
+        if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+                ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
+                ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
+                ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
+                ast_verbose("  Sent packets: %u\n", rtp->txcount);
+                ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
+                ast_verbose("  Report block:\n");
+                ast_verbose("  Fraction lost: %u\n", fraction);
+                ast_verbose("  Cumulative loss: %u\n", lost);
+                ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
+                ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
+                ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
+        }
+        manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s:%d\r\n"
+                                            "OurSSRC: %u\r\n"
+                                            "SentNTP: %u.%010u\r\n"
+                                            "SentRTP: %u\r\n"
+                                            "SentPackets: %u\r\n"
+                                            "SentOctets: %u\r\n"
+                                            "ReportBlock:\r\n"
+                                            "FractionLost: %u\r\n"
+                                            "CumulativeLoss: %u\r\n"
+                                            "IAJitter: %.4f\r\n"
+                                            "TheirLastSR: %u\r\n"
+		      "DLSR: %4.4f (sec)\r\n",
+		      ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
+		      rtp->ssrc,
+		      (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
+		      rtp->lastts,
+		      rtp->txcount,
+		      rtp->txoctetcount,
+		      fraction,
+		      lost,
+		      rtp->rxjitter,
+		      rtp->rtcp->themrxlsr,
+		      (double)(ntohl(rtcpheader[12])/65536.0));
+        return res;
+}
+
+/*! \brief Write and RTCP packet to the far end
+ * \note Decide if we are going to send an SR (with Reception Block) or RR
+ * RR is sent if we have not sent any rtp packets in the previous interval */
+static int ast_rtcp_write(const void *data)
+{
+        struct ast_rtp *rtp = (struct ast_rtp *)data;
+        int res;
+
+        if (!rtp || !rtp->rtcp)
+                return 0;
+
+        if (rtp->txcount > rtp->rtcp->lastsrtxcount)
+                res = ast_rtcp_write_sr(data);
+        else
+                res = ast_rtcp_write_rr(data);
+
+        return res;
 }
 
 static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
@@ -695,7 +964,9 @@
 			rtp->txcount++;
 			rtp->txoctetcount += (res - hdrlen);
 
-			if (rtp->rtcp) {
+			if (rtp->rtcp && rtp->rtcp->schedid < 1) {
+				ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
+				rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
 			}
 		}
 
@@ -1070,16 +1341,6 @@
         rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
 
 	return &rtp->f;
-}
-
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
-{
-        unsigned int sec, usec, frac;
-        sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
-        usec = tv.tv_usec;
-        frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
-        *msw = sec;
-        *lsw = frac;
 }
 
 static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
@@ -1402,6 +1663,8 @@
                     (instance->remote_address.sin_port != sin.sin_port)) {
                         instance->remote_address = sin;
                         if (rtp->rtcp) {
+				memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
+				rtp->rtcp->them.sin_port = htons(ntohs(sin.sin_port)+1);
                         }
                         rtp->rxseqno = 0;
                         ast_set_flag(rtp, FLAG_NAT_ACTIVE);
@@ -1460,6 +1723,14 @@
 	if (rtp->rxcount == 1) {
 		rtp->seedrxseqno = seqno;
 	}
+
+        /* Do not schedule RR if RTCP isn't run */
+        if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
+                /* Schedule transmission of Receiver Report */
+                rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
+        }
+        if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
+                rtp->cycles += RTP_SEQ_MOD;
 
 	prev_seqno = rtp->lastrxseqno;
 	rtp->lastrxseqno = seqno;
@@ -1590,6 +1861,25 @@
 	return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
 }
 
+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
+{
+	struct ast_rtp *rtp = instance->data;
+
+	if (rtp->rtcp) {
+		ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
+		memcpy(&rtp->rtcp->them, sin, sizeof(rtp->rtcp->them));
+		rtp->rtcp->them.sin_port = htons(ntohs(sin->sin_port) + 1);
+	}
+
+	rtp->rxseqno = 0;
+
+	if (strictrtp) {
+		rtp->strict_rtp_state = STRICT_RTP_LEARN;
+	}
+
+	return;
+}
+
 static char *rtp_do_debug_ip(struct ast_cli_args *a)
 {
 	struct hostent *hp;




More information about the asterisk-commits mailing list