Skip to content

Commit b4816a2

Browse files
author
Michael Ketchel
committed
backport missing changes
1 parent f4ad5fb commit b4816a2

3 files changed

Lines changed: 57 additions & 6 deletions

File tree

modules/rgrtcpsummary/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
project(rtcpsummary)
1+
project(rgrtcpsummary)
22

33
list(APPEND MODULES_DETECTED ${PROJECT_NAME})
44
set(MODULES_DETECTED ${MODULES_DETECTED} PARENT_SCOPE)
55

6-
set(SRCS rtcpsummary.c)
6+
set(SRCS rgrtcpsummary.c)
77

88
if(STATIC)
99
add_library(${PROJECT_NAME} OBJECT ${SRCS})

modules/rgrtcpsummary/rgrtcpsummary.c

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,56 @@
11
/**
2-
* @file rtcpsummary.c RTCP summary module
3-
* Output RTCP stats at the end of a call if there are any
2+
* @file rgrtcpsummary.c RG Nets RTCP summary module
3+
* Output RTCP stats and MOS score at the end of a call if there are any
44
*
5-
* Copyright (C) 2010 - 2018 Alfred E. Heggestad
5+
* Copyright (C) 2025 Michael D. Ketchel
66
*/
77
#include <re.h>
88
#include <baresip.h>
99

1010

11+
// Clamp value between min and max
12+
double clamp(double value, double min, double max) {
13+
if (value < min) return min;
14+
if (value > max) return max;
15+
return value;
16+
}
17+
18+
// Calculate MOS using ITU-T E-model approximation
19+
double calculate_mos(double rtt_ms, double tx_jitter_ms, double rx_jitter_ms, double packet_loss_percent) {
20+
// Step 1: Calculate mouth-to-ear delay (ms)
21+
double delay = rtt_ms + tx_jitter_ms + rx_jitter_ms;
22+
23+
// Step 2: Calculate delay impairment
24+
double delay_impairment = 0.024 * delay;
25+
if (delay > 177.3) {
26+
delay_impairment += 0.11 * (delay - 177.3);
27+
}
28+
29+
// Step 3: Calculate loss impairment (simplified)
30+
double loss_impairment = 2.5 * packet_loss_percent;
31+
32+
// Step 4: Calculate R-factor
33+
double R = 94.2 - delay_impairment - loss_impairment;
34+
R = clamp(R, 0.0, 100.0);
35+
36+
// Step 5: Calculate MOS from R-factor
37+
double MOS = 1.0 + 0.035 * R + (R * (R - 60.0) * (100.0 - R) * 7.0e-6);
38+
MOS = clamp(MOS, 1.0, 5.0);
39+
40+
return MOS;
41+
}
42+
43+
1144
static void print_rtcp_summary_line(const struct call *call,
1245
const struct stream *s)
1346
{
1447
const struct rtcp_stats *rtcp;
1548
rtcp = stream_rtcp_stats(s);
1649

1750
if (rtcp && (rtcp->tx.sent || rtcp->rx.sent)) {
51+
52+
53+
1854
info("\n");
1955
/*
2056
* Add a stats line to make it easier to parse result
@@ -32,6 +68,7 @@ static void print_rtcp_summary_line(const struct call *call,
3268
"JI=%.1f,%.1f;"/* Jitter RX, TX in ms */
3369
"DL=%.1f;" /* RTT in ms */
3470
"IP=%J,%J;" /* Local, Remote IPs */
71+
"MOS=%.2f;" /* MOS score */
3572
"\n"
3673
,
3774
call_setup_duration(call) * 1000,
@@ -46,7 +83,15 @@ static void print_rtcp_summary_line(const struct call *call,
4683
1.0 * rtcp->tx.jit/1000,
4784
1.0 * rtcp->rtt/1000,
4885
sdp_media_laddr(stream_sdpmedia(s)),
49-
sdp_media_raddr(stream_sdpmedia(s)));
86+
sdp_media_raddr(stream_sdpmedia(s)),
87+
calculate_mos(
88+
1.0 * rtcp->rtt/1000,
89+
1.0 * rtcp->tx.jit/1000,
90+
1.0 * rtcp->rx.jit/1000,
91+
// A naive handling of packet loss here. There is likely a better way.
92+
(1.0*(rtcp->rx.lost + rtcp->tx.lost) / (rtcp->rx.sent + rtcp->tx.sent))
93+
)
94+
);
5095
}
5196
else {
5297
/*

src/stream.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ static void print_rtp_stats(const struct stream *s)
5151
1.0*s->rtcp_stats.tx.jit/1000,
5252
1.0*s->rtcp_stats.rx.jit/1000);
5353
}
54+
info(
55+
"rtt: %7f\n"
56+
,
57+
1.0*s->rtcp_stats.rtt/1000
58+
);
59+
5460
}
5561

5662

0 commit comments

Comments
 (0)