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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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;
37 * rtp_stats_set_bandwidths:
38 * @stats: an #RTPSessionStats struct
39 * @rtp_bw: RTP bandwidth
40 * @rtcp_bw: RTCP bandwidth
41 * @rs: sender RTCP bandwidth
42 * @rr: receiver RTCP bandwidth
44 * Configure the bandwidth parameters in the stats. When an input variable is
45 * set to -1, it will be calculated from the other input variables and from the
49 rtp_stats_set_bandwidths (RTPSessionStats * stats, guint rtp_bw,
50 gdouble rtcp_bw, guint rs, guint rr)
52 GST_DEBUG ("recalc bandwidths: RTP %u, RTCP %f, RS %u, RR %u", rtp_bw,
55 /* when given, sender and receive bandwidth add up to the total
57 if (rs != -1 && rr != -1)
60 /* If rtcp_bw is between 0 and 1, it is a fraction of rtp_bw */
61 if (rtcp_bw > 0.0 && rtcp_bw < 1.0) {
63 rtcp_bw = rtp_bw * rtcp_bw;
68 /* RTCP is 5% of the RTP bandwidth */
69 if (rtp_bw == -1 && rtcp_bw > 1.0)
70 rtp_bw = rtcp_bw * 20;
71 else if (rtp_bw != -1 && rtcp_bw < 0.0)
72 rtcp_bw = rtp_bw / 20;
73 else if (rtp_bw == -1 && rtcp_bw < 0.0) {
74 /* nothing given, take defaults */
75 rtp_bw = RTP_STATS_BANDWIDTH;
76 rtcp_bw = rtp_bw * RTP_STATS_RTCP_FRACTION;
79 stats->bandwidth = rtp_bw;
80 stats->rtcp_bandwidth = rtcp_bw;
82 /* now figure out the fractions */
86 /* both not given, use defaults */
87 rs = stats->rtcp_bandwidth * RTP_STATS_SENDER_FRACTION;
88 rr = stats->rtcp_bandwidth * RTP_STATS_RECEIVER_FRACTION;
90 /* rr known, calculate rs */
91 if (stats->rtcp_bandwidth > rr)
92 rs = stats->rtcp_bandwidth - rr;
96 } else if (rr == -1) {
97 /* rs known, calculate rr */
98 if (stats->rtcp_bandwidth > rs)
99 rr = stats->rtcp_bandwidth - rs;
104 if (stats->rtcp_bandwidth > 0) {
105 stats->sender_fraction = ((gdouble) rs) / ((gdouble) stats->rtcp_bandwidth);
106 stats->receiver_fraction = 1.0 - stats->sender_fraction;
108 /* no RTCP bandwidth, set dummy values */
109 stats->sender_fraction = 0.0;
110 stats->receiver_fraction = 0.0;
112 GST_DEBUG ("bandwidths: RTP %u, RTCP %u, RS %f, RR %f", stats->bandwidth,
113 stats->rtcp_bandwidth, stats->sender_fraction, stats->receiver_fraction);
117 * rtp_stats_calculate_rtcp_interval:
118 * @stats: an #RTPSessionStats struct
119 * @sender: if we are a sender
120 * @first: if this is the first time
122 * Calculate the RTCP interval. The result of this function is the amount of
123 * time to wait (in nanoseconds) before sending a new RTCP message.
125 * Returns: the RTCP interval.
128 rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean we_send,
131 gdouble members, senders, n;
132 gdouble avg_rtcp_size, rtcp_bw;
134 gdouble rtcp_min_time;
136 /* Very first call at application start-up uses half the min
137 * delay for quicker notification while still allowing some time
138 * before reporting for randomization and to learn about other
139 * sources so the report interval will converge to the correct
140 * interval more quickly.
142 rtcp_min_time = stats->min_interval;
144 rtcp_min_time /= 2.0;
146 /* Dedicate a fraction of the RTCP bandwidth to senders unless
147 * the number of senders is large enough that their share is
148 * more than that fraction.
150 n = members = stats->active_sources;
151 senders = (gdouble) stats->sender_sources;
152 rtcp_bw = stats->rtcp_bandwidth;
154 if (senders <= members * stats->sender_fraction) {
156 rtcp_bw *= stats->sender_fraction;
159 rtcp_bw *= stats->receiver_fraction;
164 /* no bandwidth for RTCP, return NONE to signal that we don't want to send
166 if (rtcp_bw <= 0.00001)
167 return GST_CLOCK_TIME_NONE;
169 avg_rtcp_size = stats->avg_rtcp_packet_size;
171 * The effective number of sites times the average packet size is
172 * the total number of octets sent when each site sends a report.
173 * Dividing this by the effective bandwidth gives the time
174 * interval over which those packets must be sent in order to
175 * meet the bandwidth target, with a minimum enforced. In that
176 * time interval we send one report so this time is also our
177 * average time between reports.
179 GST_DEBUG ("avg size %f, n %f, rtcp_bw %f", avg_rtcp_size, n, rtcp_bw);
180 interval = avg_rtcp_size * n / rtcp_bw;
181 if (interval < rtcp_min_time)
182 interval = rtcp_min_time;
184 return interval * GST_SECOND;
188 * rtp_stats_add_rtcp_jitter:
189 * @stats: an #RTPSessionStats struct
190 * @interval: an RTCP interval
192 * Apply a random jitter to the @interval. @interval is typically obtained with
193 * rtp_stats_calculate_rtcp_interval().
195 * Returns: the new RTCP interval.
198 rtp_stats_add_rtcp_jitter (RTPSessionStats * stats, GstClockTime interval)
203 * To compensate for "unconditional reconsideration" converging to a
204 * value below the intended average.
206 #define COMPENSATION (2.71828 - 1.5);
208 temp = (interval * g_random_double_range (0.5, 1.5)) / COMPENSATION;
210 return (GstClockTime) temp;
215 * rtp_stats_calculate_bye_interval:
216 * @stats: an #RTPSessionStats struct
218 * Calculate the BYE interval. The result of this function is the amount of
219 * time to wait (in nanoseconds) before sending a BYE message.
221 * Returns: the BYE interval.
224 rtp_stats_calculate_bye_interval (RTPSessionStats * stats)
227 gdouble avg_rtcp_size, rtcp_bw;
229 gdouble rtcp_min_time;
231 /* no interval when we have less than 50 members */
232 if (stats->active_sources < 50)
235 rtcp_min_time = (stats->min_interval) / 2.0;
237 /* Dedicate a fraction of the RTCP bandwidth to senders unless
238 * the number of senders is large enough that their share is
239 * more than that fraction.
241 members = stats->bye_members;
242 rtcp_bw = stats->rtcp_bandwidth * stats->receiver_fraction;
244 /* no bandwidth for RTCP, return NONE to signal that we don't want to send
246 if (rtcp_bw <= 0.0001)
247 return GST_CLOCK_TIME_NONE;
249 avg_rtcp_size = stats->avg_rtcp_packet_size;
251 * The effective number of sites times the average packet size is
252 * the total number of octets sent when each site sends a report.
253 * Dividing this by the effective bandwidth gives the time
254 * interval over which those packets must be sent in order to
255 * meet the bandwidth target, with a minimum enforced. In that
256 * time interval we send one report so this time is also our
257 * average time between reports.
259 interval = avg_rtcp_size * members / rtcp_bw;
260 if (interval < rtcp_min_time)
261 interval = rtcp_min_time;
263 return interval * GST_SECOND;
267 * rtp_stats_get_packets_lost:
268 * @stats: an #RTPSourceStats struct
270 * Calculate the total number of RTP packets lost since beginning of
271 * reception. Packets that arrive late are not considered lost, and
272 * duplicates are not taken into account. Hence, the loss may be negative
273 * if there are duplicates.
275 * Returns: total RTP packets lost.
278 rtp_stats_get_packets_lost (const RTPSourceStats * stats)
281 guint64 extended_max, expected;
283 extended_max = stats->cycles + stats->max_seq;
284 expected = extended_max - stats->base_seq + 1;
285 lost = expected - stats->packets_received;
291 rtp_stats_set_min_interval (RTPSessionStats * stats, gdouble min_interval)
293 stats->min_interval = min_interval;
297 __g_socket_address_equal (GSocketAddress * a, GSocketAddress * b)
299 GInetSocketAddress *ia, *ib;
300 GInetAddress *iaa, *iab;
302 ia = G_INET_SOCKET_ADDRESS (a);
303 ib = G_INET_SOCKET_ADDRESS (b);
305 if (g_inet_socket_address_get_port (ia) !=
306 g_inet_socket_address_get_port (ib))
309 iaa = g_inet_socket_address_get_address (ia);
310 iab = g_inet_socket_address_get_address (ib);
312 return g_inet_address_equal (iaa, iab);
316 __g_socket_address_to_string (GSocketAddress * addr)
318 GInetSocketAddress *ia;
321 ia = G_INET_SOCKET_ADDRESS (addr);
323 tmp = g_inet_address_to_string (g_inet_socket_address_get_address (ia));
324 ret = g_strdup_printf ("%s:%u", tmp, g_inet_socket_address_get_port (ia));