2 * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 * rtp_stats_init_defaults:
24 * @stats: an #RTPSessionStats struct
26 * Initialize @stats with its default values.
29 rtp_stats_init_defaults (RTPSessionStats * stats)
31 rtp_stats_set_bandwidths (stats, -1, -1, -1, -1);
32 stats->min_interval = RTP_STATS_MIN_INTERVAL;
33 stats->bye_timeout = RTP_STATS_BYE_TIMEOUT;
34 stats->nacks_dropped = 0;
35 stats->nacks_sent = 0;
36 stats->nacks_received = 0;
40 * rtp_stats_set_bandwidths:
41 * @stats: an #RTPSessionStats struct
42 * @rtp_bw: RTP bandwidth
43 * @rtcp_bw: RTCP bandwidth
44 * @rs: sender RTCP bandwidth
45 * @rr: receiver RTCP bandwidth
47 * Configure the bandwidth parameters in the stats. When an input variable is
48 * set to -1, it will be calculated from the other input variables and from the
52 rtp_stats_set_bandwidths (RTPSessionStats * stats, guint rtp_bw,
53 gdouble rtcp_bw, guint rs, guint rr)
55 GST_DEBUG ("recalc bandwidths: RTP %u, RTCP %f, RS %u, RR %u", rtp_bw,
58 /* when given, sender and receive bandwidth add up to the total
60 if (rs != -1 && rr != -1)
63 /* If rtcp_bw is between 0 and 1, it is a fraction of rtp_bw */
64 if (rtcp_bw > 0.0 && rtcp_bw < 1.0) {
66 rtcp_bw = rtp_bw * rtcp_bw;
71 /* RTCP is 5% of the RTP bandwidth */
72 if (rtp_bw == -1 && rtcp_bw > 1.0)
73 rtp_bw = rtcp_bw * 20;
74 else if (rtp_bw != -1 && rtcp_bw < 0.0)
75 rtcp_bw = rtp_bw / 20;
76 else if (rtp_bw == -1 && rtcp_bw < 0.0) {
77 /* nothing given, take defaults */
78 rtp_bw = RTP_STATS_BANDWIDTH;
79 rtcp_bw = rtp_bw * RTP_STATS_RTCP_FRACTION;
82 stats->bandwidth = rtp_bw;
83 stats->rtcp_bandwidth = rtcp_bw;
85 /* now figure out the fractions */
89 /* both not given, use defaults */
90 rs = stats->rtcp_bandwidth * RTP_STATS_SENDER_FRACTION;
91 rr = stats->rtcp_bandwidth * RTP_STATS_RECEIVER_FRACTION;
93 /* rr known, calculate rs */
94 if (stats->rtcp_bandwidth > rr)
95 rs = stats->rtcp_bandwidth - rr;
99 } else if (rr == -1) {
100 /* rs known, calculate rr */
101 if (stats->rtcp_bandwidth > rs)
102 rr = stats->rtcp_bandwidth - rs;
107 if (stats->rtcp_bandwidth > 0) {
108 stats->sender_fraction = ((gdouble) rs) / ((gdouble) stats->rtcp_bandwidth);
109 stats->receiver_fraction = 1.0 - stats->sender_fraction;
111 /* no RTCP bandwidth, set dummy values */
112 stats->sender_fraction = 0.0;
113 stats->receiver_fraction = 0.0;
115 GST_DEBUG ("bandwidths: RTP %u, RTCP %u, RS %f, RR %f", stats->bandwidth,
116 stats->rtcp_bandwidth, stats->sender_fraction, stats->receiver_fraction);
120 * rtp_stats_calculate_rtcp_interval:
121 * @stats: an #RTPSessionStats struct
122 * @sender: if we are a sender
123 * @profile: RTP profile of this session
124 * @ptp: if this session is a point-to-point session
125 * @first: if this is the first time
127 * Calculate the RTCP interval. The result of this function is the amount of
128 * time to wait (in nanoseconds) before sending a new RTCP message.
130 * Returns: the RTCP interval.
133 rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean we_send,
134 GstRTPProfile profile, gboolean ptp, gboolean first)
136 gdouble members, senders, n;
137 gdouble avg_rtcp_size, rtcp_bw;
139 gdouble rtcp_min_time;
141 if (profile == GST_RTP_PROFILE_AVPF || profile == GST_RTP_PROFILE_SAVPF) {
142 /* RFC 4585 3.4d), 3.5.1 */
149 /* Very first call at application start-up uses half the min
150 * delay for quicker notification while still allowing some time
151 * before reporting for randomization and to learn about other
152 * sources so the report interval will converge to the correct
153 * interval more quickly.
155 rtcp_min_time = stats->min_interval;
157 rtcp_min_time /= 2.0;
160 /* Dedicate a fraction of the RTCP bandwidth to senders unless
161 * the number of senders is large enough that their share is
162 * more than that fraction.
164 n = members = stats->active_sources;
165 senders = (gdouble) stats->sender_sources;
166 rtcp_bw = stats->rtcp_bandwidth;
168 if (senders <= members * stats->sender_fraction) {
170 rtcp_bw *= stats->sender_fraction;
173 rtcp_bw *= stats->receiver_fraction;
178 /* no bandwidth for RTCP, return NONE to signal that we don't want to send
180 if (rtcp_bw <= 0.0001)
181 return GST_CLOCK_TIME_NONE;
183 avg_rtcp_size = 8.0 * stats->avg_rtcp_packet_size;
185 * The effective number of sites times the average packet size is
186 * the total number of octets sent when each site sends a report.
187 * Dividing this by the effective bandwidth gives the time
188 * interval over which those packets must be sent in order to
189 * meet the bandwidth target, with a minimum enforced. In that
190 * time interval we send one report so this time is also our
191 * average time between reports.
193 GST_DEBUG ("avg size %f, n %f, rtcp_bw %f", avg_rtcp_size, n, rtcp_bw);
194 interval = avg_rtcp_size * n / rtcp_bw;
195 if (interval < rtcp_min_time)
196 interval = rtcp_min_time;
198 return interval * GST_SECOND;
202 * rtp_stats_add_rtcp_jitter:
203 * @stats: an #RTPSessionStats struct
204 * @interval: an RTCP interval
206 * Apply a random jitter to the @interval. @interval is typically obtained with
207 * rtp_stats_calculate_rtcp_interval().
209 * Returns: the new RTCP interval.
212 rtp_stats_add_rtcp_jitter (RTPSessionStats * stats, GstClockTime interval)
217 * To compensate for "unconditional reconsideration" converging to a
218 * value below the intended average.
220 #define COMPENSATION (2.71828 - 1.5);
222 temp = (interval * g_random_double_range (0.5, 1.5)) / COMPENSATION;
224 return (GstClockTime) temp;
229 * rtp_stats_calculate_bye_interval:
230 * @stats: an #RTPSessionStats struct
232 * Calculate the BYE interval. The result of this function is the amount of
233 * time to wait (in nanoseconds) before sending a BYE message.
235 * Returns: the BYE interval.
238 rtp_stats_calculate_bye_interval (RTPSessionStats * stats)
241 gdouble avg_rtcp_size, rtcp_bw;
243 gdouble rtcp_min_time;
245 /* no interval when we have less than 50 members */
246 if (stats->active_sources < 50)
249 rtcp_min_time = (stats->min_interval) / 2.0;
251 /* Dedicate a fraction of the RTCP bandwidth to senders unless
252 * the number of senders is large enough that their share is
253 * more than that fraction.
255 members = stats->bye_members;
256 rtcp_bw = stats->rtcp_bandwidth * stats->receiver_fraction;
258 /* no bandwidth for RTCP, return NONE to signal that we don't want to send
260 if (rtcp_bw <= 0.0001)
261 return GST_CLOCK_TIME_NONE;
263 avg_rtcp_size = 8.0 * stats->avg_rtcp_packet_size;
265 * The effective number of sites times the average packet size is
266 * the total number of octets sent when each site sends a report.
267 * Dividing this by the effective bandwidth gives the time
268 * interval over which those packets must be sent in order to
269 * meet the bandwidth target, with a minimum enforced. In that
270 * time interval we send one report so this time is also our
271 * average time between reports.
273 interval = avg_rtcp_size * members / rtcp_bw;
274 if (interval < rtcp_min_time)
275 interval = rtcp_min_time;
277 return interval * GST_SECOND;
281 * rtp_stats_get_packets_lost:
282 * @stats: an #RTPSourceStats struct
284 * Calculate the total number of RTP packets lost since beginning of
285 * reception. Packets that arrive late are not considered lost, and
286 * duplicates are not taken into account. Hence, the loss may be negative
287 * if there are duplicates.
289 * Returns: total RTP packets lost.
292 rtp_stats_get_packets_lost (const RTPSourceStats * stats)
295 guint64 extended_max, expected;
297 extended_max = stats->cycles + stats->max_seq;
298 expected = extended_max - stats->base_seq + 1;
299 lost = expected - stats->packets_received;
305 rtp_stats_set_min_interval (RTPSessionStats * stats, gdouble min_interval)
307 stats->min_interval = min_interval;
311 __g_socket_address_equal (GSocketAddress * a, GSocketAddress * b)
313 GInetSocketAddress *ia, *ib;
314 GInetAddress *iaa, *iab;
316 ia = G_INET_SOCKET_ADDRESS (a);
317 ib = G_INET_SOCKET_ADDRESS (b);
319 if (g_inet_socket_address_get_port (ia) !=
320 g_inet_socket_address_get_port (ib))
323 iaa = g_inet_socket_address_get_address (ia);
324 iab = g_inet_socket_address_get_address (ib);
326 return g_inet_address_equal (iaa, iab);
330 __g_socket_address_to_string (GSocketAddress * addr)
332 GInetSocketAddress *ia;
335 ia = G_INET_SOCKET_ADDRESS (addr);
337 tmp = g_inet_address_to_string (g_inet_socket_address_get_address (ia));
338 ret = g_strdup_printf ("%s:%u", tmp, g_inet_socket_address_get_port (ia));