[asterisk-commits] file: branch file/rtp_engine r129565 - /team/file/rtp_engine/res/
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list