Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gst-plugins-good.git] / gst / rtpmanager / rtpstats.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include "rtpstats.h"
21
22 /**
23  * rtp_stats_init_defaults:
24  * @stats: an #RTPSessionStats struct
25  *
26  * Initialize @stats with its default values.
27  */
28 void
29 rtp_stats_init_defaults (RTPSessionStats * stats)
30 {
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 }
35
36 /**
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
43  *
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
46  * defaults.
47  */
48 void
49 rtp_stats_set_bandwidths (RTPSessionStats * stats, guint rtp_bw,
50     gdouble rtcp_bw, guint rs, guint rr)
51 {
52   GST_DEBUG ("recalc bandwidths: RTP %u, RTCP %f, RS %u, RR %u", rtp_bw,
53       rtcp_bw, rs, rr);
54
55   /* when given, sender and receive bandwidth add up to the total
56    * rtcp bandwidth */
57   if (rs != -1 && rr != -1)
58     rtcp_bw = rs + rr;
59
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) {
62     if (rtp_bw > 0.0)
63       rtcp_bw = rtp_bw * rtcp_bw;
64     else
65       rtcp_bw = -1.0;
66   }
67
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;
77   }
78
79   stats->bandwidth = rtp_bw;
80   stats->rtcp_bandwidth = rtcp_bw;
81
82   /* now figure out the fractions */
83   if (rs == -1) {
84     /* rs unknown */
85     if (rr == -1) {
86       /* both not given, use defaults */
87       rs = stats->rtcp_bandwidth * RTP_STATS_SENDER_FRACTION;
88       rr = stats->rtcp_bandwidth * RTP_STATS_RECEIVER_FRACTION;
89     } else {
90       /* rr known, calculate rs */
91       if (stats->rtcp_bandwidth > rr)
92         rs = stats->rtcp_bandwidth - rr;
93       else
94         rs = 0;
95     }
96   } else if (rr == -1) {
97     /* rs known, calculate rr */
98     if (stats->rtcp_bandwidth > rs)
99       rr = stats->rtcp_bandwidth - rs;
100     else
101       rr = 0;
102   }
103
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;
107   } else {
108     /* no RTCP bandwidth, set dummy values */
109     stats->sender_fraction = 0.0;
110     stats->receiver_fraction = 0.0;
111   }
112   GST_DEBUG ("bandwidths: RTP %u, RTCP %u, RS %f, RR %f", stats->bandwidth,
113       stats->rtcp_bandwidth, stats->sender_fraction, stats->receiver_fraction);
114 }
115
116 /**
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
121  *
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.
124  *
125  * Returns: the RTCP interval.
126  */
127 GstClockTime
128 rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean we_send,
129     gboolean first)
130 {
131   gdouble members, senders, n;
132   gdouble avg_rtcp_size, rtcp_bw;
133   gdouble interval;
134   gdouble rtcp_min_time;
135
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.
141    */
142   rtcp_min_time = stats->min_interval;
143   if (first)
144     rtcp_min_time /= 2.0;
145
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.
149    */
150   n = members = stats->active_sources;
151   senders = (gdouble) stats->sender_sources;
152   rtcp_bw = stats->rtcp_bandwidth;
153
154   if (senders <= members * stats->sender_fraction) {
155     if (we_send) {
156       rtcp_bw *= stats->sender_fraction;
157       n = senders;
158     } else {
159       rtcp_bw *= stats->receiver_fraction;
160       n -= senders;
161     }
162   }
163
164   /* no bandwidth for RTCP, return NONE to signal that we don't want to send
165    * RTCP packets */
166   if (rtcp_bw <= 0.00001)
167     return GST_CLOCK_TIME_NONE;
168
169   avg_rtcp_size = stats->avg_rtcp_packet_size;
170   /*
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.
178    */
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;
183
184   return interval * GST_SECOND;
185 }
186
187 /**
188  * rtp_stats_add_rtcp_jitter:
189  * @stats: an #RTPSessionStats struct
190  * @interval: an RTCP interval
191  *
192  * Apply a random jitter to the @interval. @interval is typically obtained with
193  * rtp_stats_calculate_rtcp_interval().
194  *
195  * Returns: the new RTCP interval.
196  */
197 GstClockTime
198 rtp_stats_add_rtcp_jitter (RTPSessionStats * stats, GstClockTime interval)
199 {
200   gdouble temp;
201
202   /* see RFC 3550 p 30
203    * To compensate for "unconditional reconsideration" converging to a
204    * value below the intended average.
205    */
206 #define COMPENSATION  (2.71828 - 1.5);
207
208   temp = (interval * g_random_double_range (0.5, 1.5)) / COMPENSATION;
209
210   return (GstClockTime) temp;
211 }
212
213
214 /**
215  * rtp_stats_calculate_bye_interval:
216  * @stats: an #RTPSessionStats struct
217  *
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.
220  *
221  * Returns: the BYE interval.
222  */
223 GstClockTime
224 rtp_stats_calculate_bye_interval (RTPSessionStats * stats)
225 {
226   gdouble members;
227   gdouble avg_rtcp_size, rtcp_bw;
228   gdouble interval;
229   gdouble rtcp_min_time;
230
231   /* no interval when we have less than 50 members */
232   if (stats->active_sources < 50)
233     return 0;
234
235   rtcp_min_time = (stats->min_interval) / 2.0;
236
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.
240    */
241   members = stats->bye_members;
242   rtcp_bw = stats->rtcp_bandwidth * stats->receiver_fraction;
243
244   /* no bandwidth for RTCP, return NONE to signal that we don't want to send
245    * RTCP packets */
246   if (rtcp_bw <= 0.0001)
247     return GST_CLOCK_TIME_NONE;
248
249   avg_rtcp_size = stats->avg_rtcp_packet_size;
250   /*
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.
258    */
259   interval = avg_rtcp_size * members / rtcp_bw;
260   if (interval < rtcp_min_time)
261     interval = rtcp_min_time;
262
263   return interval * GST_SECOND;
264 }
265
266 /**
267  * rtp_stats_get_packets_lost:
268  * @stats: an #RTPSourceStats struct
269  *
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.
274  *
275  * Returns: total RTP packets lost.
276  */
277 gint64
278 rtp_stats_get_packets_lost (const RTPSourceStats * stats)
279 {
280   gint64 lost;
281   guint64 extended_max, expected;
282
283   extended_max = stats->cycles + stats->max_seq;
284   expected = extended_max - stats->base_seq + 1;
285   lost = expected - stats->packets_received;
286
287   return lost;
288 }
289
290 void
291 rtp_stats_set_min_interval (RTPSessionStats * stats, gdouble min_interval)
292 {
293   stats->min_interval = min_interval;
294 }
295
296 gboolean
297 __g_socket_address_equal (GSocketAddress * a, GSocketAddress * b)
298 {
299   GInetSocketAddress *ia, *ib;
300   GInetAddress *iaa, *iab;
301
302   ia = G_INET_SOCKET_ADDRESS (a);
303   ib = G_INET_SOCKET_ADDRESS (b);
304
305   if (g_inet_socket_address_get_port (ia) !=
306       g_inet_socket_address_get_port (ib))
307     return FALSE;
308
309   iaa = g_inet_socket_address_get_address (ia);
310   iab = g_inet_socket_address_get_address (ib);
311
312   return g_inet_address_equal (iaa, iab);
313 }
314
315 gchar *
316 __g_socket_address_to_string (GSocketAddress * addr)
317 {
318   GInetSocketAddress *ia;
319   gchar *ret, *tmp;
320
321   ia = G_INET_SOCKET_ADDRESS (addr);
322
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));
325   g_free (tmp);
326
327   return ret;
328 }