aboutsummaryrefslogtreecommitdiffstats
path: root/main/rtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/rtp.c')
-rw-r--r--main/rtp.c427
1 files changed, 401 insertions, 26 deletions
diff --git a/main/rtp.c b/main/rtp.c
index e11243358..9afd0b940 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -33,8 +33,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
+#include <math.h>
#include "asterisk/rtp.h"
+#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
@@ -229,6 +231,7 @@ int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
*
*/
struct ast_rtcp {
+ int rtcp_info;
int s; /*!< Socket */
struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
@@ -248,10 +251,38 @@ struct ast_rtcp {
unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
unsigned int reported_lost; /*!< Reported lost packets in their RR */
char quality[AST_MAX_USER_FIELD];
+ char quality_jitter[AST_MAX_USER_FIELD];
+ char quality_loss[AST_MAX_USER_FIELD];
+ char quality_rtt[AST_MAX_USER_FIELD];
+
+ double reported_maxjitter;
+ double reported_minjitter;
+ double reported_normdev_jitter;
+ double reported_stdev_jitter;
+ unsigned int reported_jitter_count;
+
+ double reported_maxlost;
+ double reported_minlost;
+ double reported_normdev_lost;
+ double reported_stdev_lost;
+
+ double rxlost;
+ double maxrxlost;
+ double minrxlost;
+ double normdev_rxlost;
+ double stdev_rxlost;
+ unsigned int rxlost_count;
+
double maxrxjitter;
double minrxjitter;
+ double normdev_rxjitter;
+ double stdev_rxjitter;
+ unsigned int rxjitter_count;
double maxrtt;
double minrtt;
+ double normdevrtt;
+ double stdevrtt;
+ unsigned int rtt_count;
int sendfur;
};
@@ -805,6 +836,35 @@ static void rtp_bridge_unlock(struct ast_rtp *rtp)
return;
}
+/*! \brief Calculate normal deviation */
+static double normdev_compute(double normdev, double sample, unsigned int sample_count)
+{
+ normdev = normdev * sample_count + sample;
+ sample_count++;
+
+ return normdev / sample_count;
+}
+
+static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
+{
+/*
+ for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
+ return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
+ we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
+ optimized formula
+*/
+#define SQUARE(x) ((x) * (x))
+
+ stddev = sample_count * stddev;
+ sample_count++;
+
+ return stddev +
+ ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
+ ( SQUARE(sample - normdev_curent) / sample_count );
+
+#undef SQUARE
+}
+
static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
{
if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
@@ -1086,6 +1146,12 @@ struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
unsigned int comp;
struct ast_frame *f = &ast_null_frame;
+ double reported_jitter;
+ double reported_normdev_jitter_current;
+ double normdevrtt_current;
+ double reported_lost;
+ double reported_normdev_lost_current;
+
if (!rtp || !rtp->rtcp)
return &ast_null_frame;
@@ -1179,14 +1245,27 @@ struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
}
rtt = rtt / 1000.;
rttsec = rtt / 1000.;
+ rtp->rtcp->rtt = rttsec;
if (comp - dlsr >= lsr) {
rtp->rtcp->accumulated_transit += rttsec;
- rtp->rtcp->rtt = 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), "
@@ -1198,7 +1277,45 @@ struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
}
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);
@@ -1210,6 +1327,7 @@ struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
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"
@@ -1286,7 +1404,7 @@ struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
}
position += (length + 1);
}
-
+ rtp->rtcp->rtcp_info = 1;
return f;
}
@@ -1299,6 +1417,7 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
double dtv;
double prog;
+ double normdev_rxjitter_current;
if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
gettimeofday(&rtp->rxcore, NULL);
rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
@@ -1334,8 +1453,16 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
rtp->rtcp->maxrxjitter = rtp->rxjitter;
+ if (rtp->rtcp->rxjitter_count == 1)
+ rtp->rtcp->minrxjitter = rtp->rxjitter;
if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
rtp->rtcp->minrxjitter = rtp->rxjitter;
+
+ normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
+ rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
+
+ rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
+ rtp->rtcp->rxjitter_count++;
}
/*! \brief Perform a Packet2Packet RTP write */
@@ -1557,7 +1684,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
/* 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 */
+ 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;
@@ -1688,7 +1815,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
rtp->f.ts = timestamp / 8;
rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 );
- } else if(rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
+ } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
/* Video -- samples is # of samples vs. 90000 */
if (!rtp->lastividtimestamp)
rtp->lastividtimestamp = timestamp;
@@ -2497,7 +2624,89 @@ void ast_rtp_reset(struct ast_rtp *rtp)
rtp->rxseqno = 0;
}
-char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
+static double __ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, int *found)
+{
+ *found = 1;
+
+ if (!strcasecmp(qos, "remote_maxjitter"))
+ return rtp->rtcp->reported_maxjitter * 1000.0;
+ if (!strcasecmp(qos, "remote_minjitter"))
+ return rtp->rtcp->reported_minjitter * 1000.0;
+ if (!strcasecmp(qos, "remote_normdevjitter"))
+ return rtp->rtcp->reported_normdev_jitter * 1000.0;
+ if (!strcasecmp(qos, "remote_stdevjitter"))
+ return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
+
+ if (!strcasecmp(qos, "local_maxjitter"))
+ return rtp->rtcp->maxrxjitter * 1000.0;
+ if (!strcasecmp(qos, "local_minjitter"))
+ return rtp->rtcp->minrxjitter * 1000.0;
+ if (!strcasecmp(qos, "local_normdevjitter"))
+ return rtp->rtcp->normdev_rxjitter * 1000.0;
+ if (!strcasecmp(qos, "local_stdevjitter"))
+ return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
+
+ if (!strcasecmp(qos, "maxrtt"))
+ return rtp->rtcp->maxrtt * 1000.0;
+ if (!strcasecmp(qos, "minrtt"))
+ return rtp->rtcp->minrtt * 1000.0;
+ if (!strcasecmp(qos, "normdevrtt"))
+ return rtp->rtcp->normdevrtt * 1000.0;
+ if (!strcasecmp(qos, "stdevrtt"))
+ return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
+
+ *found = 0;
+
+ return 0.0;
+}
+
+int ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
+{
+ double value;
+ int found;
+
+ value = __ast_rtp_get_qos(rtp, qos, &found);
+
+ if (!found)
+ return -1;
+
+ snprintf(buf, buflen, "%.0lf", value);
+
+ return 0;
+}
+
+void ast_rtp_set_vars(struct ast_channel *chan, struct ast_rtp *rtp) {
+ char *audioqos;
+ char *audioqos_jitter;
+ char *audioqos_loss;
+ char *audioqos_rtt;
+ struct ast_channel *bridge;
+
+ if (!rtp || !chan)
+ return;
+
+ bridge = ast_bridged_channel(chan);
+
+ audioqos = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
+ audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
+ audioqos_loss = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
+ audioqos_rtt = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
+
+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
+
+ if (!bridge)
+ return;
+
+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
+}
+
+static char *__ast_rtp_get_quality_jitter(struct ast_rtp *rtp)
{
/*
*ssrc our ssrc
@@ -2510,21 +2719,129 @@ char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
*rlp remote lost packets
*rtt round trip time
*/
+#define RTCP_JITTER_FORMAT1 \
+ "minrxjitter=%f;" \
+ "maxrxjitter=%f;" \
+ "avgrxjitter=%f;" \
+ "stdevrxjitter=%f;" \
+ "reported_minjitter=%f;" \
+ "reported_maxjitter=%f;" \
+ "reported_avgjitter=%f;" \
+ "reported_stdevjitter=%f;"
+
+#define RTCP_JITTER_FORMAT2 \
+ "rxjitter=%f;"
+
+ if (rtp->rtcp && rtp->rtcp->rtcp_info) {
+ snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1,
+ rtp->rtcp->minrxjitter,
+ rtp->rtcp->maxrxjitter,
+ rtp->rtcp->normdev_rxjitter,
+ sqrt(rtp->rtcp->stdev_rxjitter),
+ rtp->rtcp->reported_minjitter,
+ rtp->rtcp->reported_maxjitter,
+ rtp->rtcp->reported_normdev_jitter,
+ sqrt(rtp->rtcp->reported_stdev_jitter)
+ );
+ } else {
+ snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2,
+ rtp->rxjitter
+ );
+ }
- if (qual && rtp) {
- qual->local_ssrc = rtp->ssrc;
- qual->local_jitter = rtp->rxjitter;
- qual->local_count = rtp->rxcount;
- qual->remote_ssrc = rtp->themssrc;
- qual->remote_count = rtp->txcount;
- if (rtp->rtcp) {
- qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
- qual->remote_lostpackets = rtp->rtcp->reported_lost;
- qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
- qual->rtt = rtp->rtcp->rtt;
- }
+ return rtp->rtcp->quality_jitter;
+
+#undef RTCP_JITTER_FORMAT1
+#undef RTCP_JITTER_FORMAT2
+}
+
+static char *__ast_rtp_get_quality_loss(struct ast_rtp *rtp)
+{
+ unsigned int lost;
+ unsigned int extended;
+ unsigned int expected;
+ int fraction;
+
+#define RTCP_LOSS_FORMAT1 \
+ "minrxlost=%f;" \
+ "maxrxlost=%f;" \
+ "avgrxlostr=%f;" \
+ "stdevrxlost=%f;" \
+ "reported_minlost=%f;" \
+ "reported_maxlost=%f;" \
+ "reported_avglost=%f;" \
+ "reported_stdevlost=%f;"
+
+#define RTCP_LOSS_FORMAT2 \
+ "lost=%d;" \
+ "expected=%d;"
+
+ if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) {
+ snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1,
+ rtp->rtcp->minrxlost,
+ rtp->rtcp->maxrxlost,
+ rtp->rtcp->normdev_rxlost,
+ sqrt(rtp->rtcp->stdev_rxlost),
+ rtp->rtcp->reported_minlost,
+ rtp->rtcp->reported_maxlost,
+ rtp->rtcp->reported_normdev_lost,
+ sqrt(rtp->rtcp->reported_stdev_lost)
+ );
+ } else {
+ extended = rtp->cycles + rtp->lastrxseqno;
+ expected = extended - rtp->seedrxseqno + 1;
+ if (rtp->rxcount > expected)
+ expected += rtp->rxcount - expected;
+ lost = expected - rtp->rxcount;
+
+ if (!expected || lost <= 0)
+ fraction = 0;
+ else
+ fraction = (lost << 8) / expected;
+
+ snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2,
+ lost,
+ expected
+ );
}
- if (rtp->rtcp) {
+
+ return rtp->rtcp->quality_loss;
+
+#undef RTCP_LOSS_FORMAT1
+#undef RTCP_LOSS_FORMAT2
+}
+
+static char *__ast_rtp_get_quality_rtt(struct ast_rtp *rtp)
+{
+ if (rtp->rtcp && rtp->rtcp->rtcp_info) {
+ snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
+ rtp->rtcp->minrtt,
+ rtp->rtcp->maxrtt,
+ rtp->rtcp->normdevrtt,
+ sqrt(rtp->rtcp->stdevrtt)
+ );
+ } else {
+ snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
+ }
+
+ return rtp->rtcp->quality_rtt;
+}
+
+static char *__ast_rtp_get_quality(struct ast_rtp *rtp)
+{
+ /*
+ *ssrc our ssrc
+ *themssrc their ssrc
+ *lp lost packets
+ *rxjitter our calculated jitter(rx)
+ *rxcount no. received packets
+ *txjitter reported jitter of the other end
+ *txcount transmitted packets
+ *rlp remote lost packets
+ *rtt round trip time
+ */
+
+ if (rtp->rtcp && rtp->rtcp->rtcp_info) {
snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
"ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
rtp->ssrc,
@@ -2535,10 +2852,50 @@ char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
(double)rtp->rtcp->reported_jitter / 65536.0,
rtp->txcount,
rtp->rtcp->reported_lost,
- rtp->rtcp->rtt);
- return rtp->rtcp->quality;
- } else
- return "<Unknown> - RTP/RTCP has already been destroyed";
+ rtp->rtcp->rtt
+ );
+ } else {
+ snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
+ rtp->ssrc,
+ rtp->themssrc,
+ rtp->rxjitter,
+ rtp->rxcount,
+ rtp->txcount
+ );
+ }
+
+ return rtp->rtcp->quality;
+}
+
+char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
+{
+ if (qual && rtp) {
+ qual->local_ssrc = rtp->ssrc;
+ qual->local_jitter = rtp->rxjitter;
+ qual->local_count = rtp->rxcount;
+ qual->remote_ssrc = rtp->themssrc;
+ qual->remote_count = rtp->txcount;
+
+ if (rtp->rtcp) {
+ qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
+ qual->remote_lostpackets = rtp->rtcp->reported_lost;
+ qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
+ qual->rtt = rtp->rtcp->rtt;
+ }
+ }
+
+ switch (qtype) {
+ case RTPQOS_SUMMARY:
+ return __ast_rtp_get_quality(rtp);
+ case RTPQOS_JITTER:
+ return __ast_rtp_get_quality_jitter(rtp);
+ case RTPQOS_LOSS:
+ return __ast_rtp_get_quality_loss(rtp);
+ case RTPQOS_RTT:
+ return __ast_rtp_get_quality_rtt(rtp);
+ }
+
+ return NULL;
}
void ast_rtp_destroy(struct ast_rtp *rtp)
@@ -2944,6 +3301,8 @@ static int ast_rtcp_write_rr(const void *data)
struct timeval dlsr;
int fraction;
+ double rxlost_current;
+
if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
return 0;
@@ -2961,6 +3320,22 @@ static int ast_rtcp_write_rr(const void *data)
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
@@ -3223,7 +3598,7 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
return 0;
/* If there is no data length, return immediately */
- if(!_f->datalen && !rtp->red)
+ if (!_f->datalen && !rtp->red)
return 0;
/* Make sure we have enough space for RTP header */
@@ -3903,8 +4278,8 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
* we can still do packet-to-packet bridging, because passing through the
* core will handle DTMF mode translation.
*/
- if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
- (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
+ if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
+ (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
ast_channel_unlock(c0);
ast_channel_unlock(c1);
@@ -4456,7 +4831,7 @@ int rtp_red_init(struct ast_rtp *rtp, int ti, int *red_data_pt, int num_gen)
*/
void red_buffer_t140(struct ast_rtp *rtp, struct ast_frame *f)
{
- if( f->datalen > -1 ) {
+ if (f->datalen > -1) {
struct rtp_red *red = rtp->red;
memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen);
red->t140.datalen += f->datalen;