aboutsummaryrefslogtreecommitdiffstats
path: root/main/rtp.c
diff options
context:
space:
mode:
authorbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2008-06-05 16:24:19 +0000
committerbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2008-06-05 16:24:19 +0000
commit68dea9b6d66ac8281286c8fd85d3ef4b1ed3a823 (patch)
treed1e5ce5e2319e18edd672e98cdfaae3e096a1e2e /main/rtp.c
parente387c61e4f71e932c9a81269c34c93b4ff92f0fb (diff)
This patch adds more detailed statistics for RTP channels, and provides an API call to access it, including maximums, minimums, standard deviatinos,
and normal deviations. Currently this is implemented for chan_sip, but could be added to the func_channel_read callbacks for the CHANNEL function for any channel that uses RTP. (closes issue #10590) Reported by: gasparz Patches: chan_sip_c.diff uploaded by gasparz (license 219) rtp_c.diff uploaded by gasparz (license 219) rtp_h.diff uploaded by gasparz (license 219) audioqos-trunk.diff uploaded by snuffy (license 35) rtpqos-trunk-r119891.diff uploaded by sergee (license 138) Tested by: jsmith, gasparz, snuffy, marsosa, chappell, sergee git-svn-id: http://svn.digium.com/svn/asterisk/trunk@120635 f38db490-d61c-443f-a65b-d21fe96a405b
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;