[svn-commits] file: branch file/rtp_engine r129565 - /team/file/rtp_engine/res/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jul 10 10:45:03 CDT 2008


Author: file
Date: Thu Jul 10 10:45:03 2008
New Revision: 129565

URL: http://svn.digium.com/view/asterisk?view=rev&rev=129565
Log:
Bring back reception of RTCP.

Modified:
    team/file/rtp_engine/res/res_rtp_asterisk.c

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=129565&r1=129564&r2=129565
==============================================================================
--- team/file/rtp_engine/res/res_rtp_asterisk.c (original)
+++ team/file/rtp_engine/res/res_rtp_asterisk.c Thu Jul 10 10:45:03 2008
@@ -1072,6 +1072,277 @@
 	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)
+{
+	struct ast_rtp *rtp = instance->data;
+	struct sockaddr_in sin;
+	socklen_t len = sizeof(sin);
+	unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
+	unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
+	int res, packetwords, position = 0;
+	struct ast_frame *f = &ast_null_frame;
+
+	/* Read in RTCP data from the socket */
+	if ((res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0) {
+		ast_assert(errno != EBADF);
+		if (errno != EAGAIN) {
+			ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
+			return NULL;
+		}
+		return &ast_null_frame;
+	}
+
+	packetwords = res / 4;
+
+	if (instance->properties[AST_RTP_PROPERTY_NAT]) {
+		/* Send to whoever sent to us */
+                if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
+                    (rtp->rtcp->them.sin_port != sin.sin_port)) {
+                        memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
+                        if (option_debug || rtpdebug)
+                                ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                }
+	}
+
+	ast_debug(1, "Got RTCP report of %d bytes\n", res);
+
+	while (position < packetwords) {
+		int i, pt, rc;
+		unsigned int length, dlsr, lsr, msw, lsw, comp;
+		struct timeval now;
+		double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
+		uint64_t rtt = 0;
+
+                i = position;
+                length = ntohl(rtcpheader[i]);
+                pt = (length & 0xff0000) >> 16;
+                rc = (length & 0x1f000000) >> 24;
+                length &= 0xffff;
+
+                if ((i + length) > packetwords) {
+                        if (option_debug || rtpdebug)
+                                ast_log(LOG_DEBUG, "RTCP Read too short\n");
+                        return &ast_null_frame;
+                }
+
+                if (rtcp_debug_test_addr(&sin)) {
+                        ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+                        ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
+                        ast_verbose("Reception reports: %d\n", rc);
+                        ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
+                }
+
+                i += 2; /* Advance past header and ssrc */
+
+                switch (pt) {
+                case RTCP_PT_SR:
+                        gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
+                        rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
+                        rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
+                        rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
+
+                        if (rtcp_debug_test_addr(&sin)) {
+                                ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
+                                ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
+                                ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
+                        }
+                        i += 5;
+                        if (rc < 1)
+                                break;
+                        /* Intentional fall through */
+                case RTCP_PT_RR:
+                        /* Don't handle multiple reception reports (rc > 1) yet */
+                        /* Calculate RTT per RFC */
+                        gettimeofday(&now, NULL);
+                        timeval2ntp(now, &msw, &lsw);
+                        if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
+                                comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
+                                lsr = ntohl(rtcpheader[i + 4]);
+                                dlsr = ntohl(rtcpheader[i + 5]);
+                                rtt = comp - lsr - dlsr;
+
+                                /* Convert end to end delay to usec (keeping the calculation in 64bit space)
+                                   sess->ee_delay = (eedelay * 1000) / 65536; */
+                                if (rtt < 4294) {
+					rtt = (rtt * 1000000) >> 16;
+                                } else {
+					rtt = (rtt * 1000) >> 16;
+					rtt *= 1000;
+                                }
+                                rtt = rtt / 1000.;
+                                rttsec = rtt / 1000.;
+                                rtp->rtcp->rtt = rttsec;
+
+                                if (comp - dlsr >= lsr) {
+                                        rtp->rtcp->accumulated_transit += rttsec;
+
+                                        if (rtp->rtcp->rtt_count == 0)
+                                                rtp->rtcp->minrtt = rttsec;
+
+                                        if (rtp->rtcp->maxrtt<rttsec)
+                                                rtp->rtcp->maxrtt = rttsec;
+                                        if (rtp->rtcp->minrtt>rttsec)
+                                                rtp->rtcp->minrtt = rttsec;
+
+                                        normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
+
+                                        rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
+
+                                        rtp->rtcp->normdevrtt = normdevrtt_current;
+
+                                        rtp->rtcp->rtt_count++;
+                                } else if (rtcp_debug_test_addr(&sin)) {
+                                        ast_verbose("Internal RTCP NTP clock skew detected: "
+                                                           "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
+						    "diff=%d\n",
+						    lsr, comp, dlsr, dlsr / 65536,
+						    (dlsr % 65536) * 1000 / 65536,
+						    dlsr - (comp - lsr));
+                                }
+                        }
+
+                        rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
+                        reported_jitter = (double) rtp->rtcp->reported_jitter;
+
+                        if (rtp->rtcp->reported_jitter_count == 0)
+                                rtp->rtcp->reported_minjitter = reported_jitter;
+
+                        if (reported_jitter < rtp->rtcp->reported_minjitter)
+                                rtp->rtcp->reported_minjitter = reported_jitter;
+
+                        if (reported_jitter > rtp->rtcp->reported_maxjitter)
+                                rtp->rtcp->reported_maxjitter = reported_jitter;
+
+                        reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
+
+                        rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
+
+                        rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
+
+                        rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
+
+                        reported_lost = (double) rtp->rtcp->reported_lost;
+
+                        /* using same counter as for jitter */
+                        if (rtp->rtcp->reported_jitter_count == 0)
+                                rtp->rtcp->reported_minlost = reported_lost;
+
+                        if (reported_lost < rtp->rtcp->reported_minlost)
+                                rtp->rtcp->reported_minlost = reported_lost;
+
+                        if (reported_lost > rtp->rtcp->reported_maxlost)
+                                rtp->rtcp->reported_maxlost = reported_lost;
+                        reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
+
+                        rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
+
+                        rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
+
+                        rtp->rtcp->reported_jitter_count++;
+
+                        if (rtcp_debug_test_addr(&sin)) {
+                                ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
+                                ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
+                                ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
+                                ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
+                                ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
+                                ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
+                                ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
+                                if (rtt)
+                                        ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
+                        }
+                        if (rtt) {
+                                manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
+                                                                    "PT: %d(%s)\r\n"
+                                                                    "ReceptionReports: %d\r\n"
+                                                                    "SenderSSRC: %u\r\n"
+                                                                    "FractionLost: %ld\r\n"
+                                                                    "PacketsLost: %d\r\n"
+                                                                    "HighestSequence: %ld\r\n"
+                                                                    "SequenceNumberCycles: %ld\r\n"
+                                                                    "IAJitter: %u\r\n"
+                                                                    "LastSR: %lu.%010lu\r\n"
+                                                                    "DLSR: %4.4f(sec)\r\n"
+					      "RTT: %llu(sec)\r\n",
+					      ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+					      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
+					      rc,
+					      rtcpheader[i + 1],
+					      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
+					      rtp->rtcp->reported_lost,
+					      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
+					      (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
+					      rtp->rtcp->reported_jitter,
+					      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
+					      ntohl(rtcpheader[i + 5])/65536.0,
+					      (unsigned long long)rtt);
+                        } else {
+                                manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
+                                                                    "PT: %d(%s)\r\n"
+                                                                    "ReceptionReports: %d\r\n"
+                                                                    "SenderSSRC: %u\r\n"
+                                                                    "FractionLost: %ld\r\n"
+                                                                    "PacketsLost: %d\r\n"
+                                                                    "HighestSequence: %ld\r\n"
+                                                                    "SequenceNumberCycles: %ld\r\n"
+                                                                    "IAJitter: %u\r\n"
+                                                                    "LastSR: %lu.%010lu\r\n"
+					      "DLSR: %4.4f(sec)\r\n",
+					      ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+					      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
+					      rc,
+					      rtcpheader[i + 1],
+					      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
+					      rtp->rtcp->reported_lost,
+					      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
+					      (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
+					      rtp->rtcp->reported_jitter,
+					      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
+					      ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
+					      ntohl(rtcpheader[i + 5])/65536.0);
+                        }
+                        break;
+                case RTCP_PT_FUR:
+                        if (rtcp_debug_test_addr(&sin))
+                                ast_verbose("Received an RTCP Fast Update Request\n");
+                        rtp->f.frametype = AST_FRAME_CONTROL;
+                        rtp->f.subclass = AST_CONTROL_VIDUPDATE;
+                        rtp->f.datalen = 0;
+                        rtp->f.samples = 0;
+                        rtp->f.mallocd = 0;
+                        rtp->f.src = "RTP";
+                        f = &rtp->f;
+                        break;
+                case RTCP_PT_SDES:
+                        if (rtcp_debug_test_addr(&sin))
+                                ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                        break;
+                case RTCP_PT_BYE:
+                        if (rtcp_debug_test_addr(&sin))
+                                ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                        break;
+                default:
+                        ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                        break;
+                }
+                position += (length + 1);
+	}
+
+	rtp->rtcp->rtcp_info = 1;
+
+	return f;
+}
+
 static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
 {
 	struct ast_rtp *rtp = instance->data;
@@ -1084,6 +1355,7 @@
 	/* If this is actually RTCP let's hop on over and handle it */
 	if (rtcp) {
 		if (rtp->rtcp) {
+			return ast_rtcp_read(instance);
 		}
 		return &ast_null_frame;
 	}
@@ -1279,6 +1551,33 @@
 			ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
 			return;
 		}
+		if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
+			return;
+		}
+		if ((rtp->rtcp->s = create_new_socket("RTCP")) < 0) {
+			ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
+			ast_free(rtp->rtcp);
+			rtp->rtcp = NULL;
+			return;
+		}
+
+		/* Grab the IP address and port we are going to use */
+		memcpy(&rtp->rtcp->us, &instance->local_address, sizeof(rtp->rtcp->us));
+		rtp->rtcp->us.sin_port = htons(ntohs(instance->remote_address.sin_port) + 1);
+
+		/* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
+		if (bind(rtp->rtcp->s, (struct sockaddr*)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) {
+			ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
+			close(rtp->rtcp->s);
+			ast_free(rtp->rtcp);
+			rtp->rtcp = NULL;
+			return;
+		}
+
+		ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
+		rtp->rtcp->schedid = -1;
+
+		return;
 	}
 
 	return;




More information about the svn-commits mailing list