f9f7c2c79db5a7cc85a7d702bcb9d9a37b805f6a
[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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, 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   stats->nacks_dropped = 0;
35   stats->nacks_sent = 0;
36   stats->nacks_received = 0;
37 }
38
39 /**
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
46  *
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
49  * defaults.
50  */
51 void
52 rtp_stats_set_bandwidths (RTPSessionStats * stats, guint rtp_bw,
53     gdouble rtcp_bw, guint rs, guint rr)
54 {
55   GST_DEBUG ("recalc bandwidths: RTP %u, RTCP %f, RS %u, RR %u", rtp_bw,
56       rtcp_bw, rs, rr);
57
58   /* when given, sender and receive bandwidth add up to the total
59    * rtcp bandwidth */
60   if (rs != -1 && rr != -1)
61     rtcp_bw = rs + rr;
62
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) {
65     if (rtp_bw > 0.0)
66       rtcp_bw = rtp_bw * rtcp_bw;
67     else
68       rtcp_bw = -1.0;
69   }
70
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;
80   }
81
82   stats->bandwidth = rtp_bw;
83   stats->rtcp_bandwidth = rtcp_bw;
84
85   /* now figure out the fractions */
86   if (rs == -1) {
87     /* rs unknown */
88     if (rr == -1) {
89       /* both not given, use defaults */
90       rs = stats->rtcp_bandwidth * RTP_STATS_SENDER_FRACTION;
91       rr = stats->rtcp_bandwidth * RTP_STATS_RECEIVER_FRACTION;
92     } else {
93       /* rr known, calculate rs */
94       if (stats->rtcp_bandwidth > rr)
95         rs = stats->rtcp_bandwidth - rr;
96       else
97         rs = 0;
98     }
99   } else if (rr == -1) {
100     /* rs known, calculate rr */
101     if (stats->rtcp_bandwidth > rs)
102       rr = stats->rtcp_bandwidth - rs;
103     else
104       rr = 0;
105   }
106
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;
110   } else {
111     /* no RTCP bandwidth, set dummy values */
112     stats->sender_fraction = 0.0;
113     stats->receiver_fraction = 0.0;
114   }
115   GST_DEBUG ("bandwidths: RTP %u, RTCP %u, RS %f, RR %f", stats->bandwidth,
116       stats->rtcp_bandwidth, stats->sender_fraction, stats->receiver_fraction);
117 }
118
119 /**
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
126  *
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.
129  *
130  * Returns: the RTCP interval.
131  */
132 GstClockTime
133 rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean we_send,
134     GstRTPProfile profile, gboolean ptp, gboolean first)
135 {
136   gdouble members, senders, n;
137   gdouble avg_rtcp_size, rtcp_bw;
138   gdouble interval;
139   gdouble rtcp_min_time;
140
141   if (profile == GST_RTP_PROFILE_AVPF || profile == GST_RTP_PROFILE_SAVPF) {
142     /* RFC 4585 3.4d), 3.5.1 */
143
144     if (first && !ptp)
145       rtcp_min_time = 1.0;
146     else
147       rtcp_min_time = 0.0;
148   } else {
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.
154      */
155     rtcp_min_time = stats->min_interval;
156     if (first)
157       rtcp_min_time /= 2.0;
158   }
159
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.
163    */
164   n = members = stats->active_sources;
165   senders = (gdouble) stats->sender_sources;
166   rtcp_bw = stats->rtcp_bandwidth;
167
168   if (senders <= members * stats->sender_fraction) {
169     if (we_send) {
170       rtcp_bw *= stats->sender_fraction;
171       n = senders;
172     } else {
173       rtcp_bw *= stats->receiver_fraction;
174       n -= senders;
175     }
176   }
177
178   /* no bandwidth for RTCP, return NONE to signal that we don't want to send
179    * RTCP packets */
180   if (rtcp_bw <= 0.0001)
181     return GST_CLOCK_TIME_NONE;
182
183   avg_rtcp_size = 8.0 * stats->avg_rtcp_packet_size;
184   /*
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.
192    */
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;
197
198   return interval * GST_SECOND;
199 }
200
201 /**
202  * rtp_stats_add_rtcp_jitter:
203  * @stats: an #RTPSessionStats struct
204  * @interval: an RTCP interval
205  *
206  * Apply a random jitter to the @interval. @interval is typically obtained with
207  * rtp_stats_calculate_rtcp_interval().
208  *
209  * Returns: the new RTCP interval.
210  */
211 GstClockTime
212 rtp_stats_add_rtcp_jitter (RTPSessionStats * stats, GstClockTime interval)
213 {
214   gdouble temp;
215
216   /* see RFC 3550 p 30
217    * To compensate for "unconditional reconsideration" converging to a
218    * value below the intended average.
219    */
220 #define COMPENSATION  (2.71828 - 1.5);
221
222   temp = (interval * g_random_double_range (0.5, 1.5)) / COMPENSATION;
223
224   return (GstClockTime) temp;
225 }
226
227
228 /**
229  * rtp_stats_calculate_bye_interval:
230  * @stats: an #RTPSessionStats struct
231  *
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.
234  *
235  * Returns: the BYE interval.
236  */
237 GstClockTime
238 rtp_stats_calculate_bye_interval (RTPSessionStats * stats)
239 {
240   gdouble members;
241   gdouble avg_rtcp_size, rtcp_bw;
242   gdouble interval;
243   gdouble rtcp_min_time;
244
245   /* no interval when we have less than 50 members */
246   if (stats->active_sources < 50)
247     return 0;
248
249   rtcp_min_time = (stats->min_interval) / 2.0;
250
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.
254    */
255   members = stats->bye_members;
256   rtcp_bw = stats->rtcp_bandwidth * stats->receiver_fraction;
257
258   /* no bandwidth for RTCP, return NONE to signal that we don't want to send
259    * RTCP packets */
260   if (rtcp_bw <= 0.0001)
261     return GST_CLOCK_TIME_NONE;
262
263   avg_rtcp_size = 8.0 * stats->avg_rtcp_packet_size;
264   /*
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.
272    */
273   interval = avg_rtcp_size * members / rtcp_bw;
274   if (interval < rtcp_min_time)
275     interval = rtcp_min_time;
276
277   return interval * GST_SECOND;
278 }
279
280 /**
281  * rtp_stats_get_packets_lost:
282  * @stats: an #RTPSourceStats struct
283  *
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.
288  *
289  * Returns: total RTP packets lost.
290  */
291 gint64
292 rtp_stats_get_packets_lost (const RTPSourceStats * stats)
293 {
294   gint64 lost;
295   guint64 extended_max, expected;
296
297   extended_max = stats->cycles + stats->max_seq;
298   expected = extended_max - stats->base_seq + 1;
299   lost = expected - stats->packets_received;
300
301   return lost;
302 }
303
304 void
305 rtp_stats_set_min_interval (RTPSessionStats * stats, gdouble min_interval)
306 {
307   stats->min_interval = min_interval;
308 }
309
310 gboolean
311 __g_socket_address_equal (GSocketAddress * a, GSocketAddress * b)
312 {
313   GInetSocketAddress *ia, *ib;
314   GInetAddress *iaa, *iab;
315
316   ia = G_INET_SOCKET_ADDRESS (a);
317   ib = G_INET_SOCKET_ADDRESS (b);
318
319   if (g_inet_socket_address_get_port (ia) !=
320       g_inet_socket_address_get_port (ib))
321     return FALSE;
322
323   iaa = g_inet_socket_address_get_address (ia);
324   iab = g_inet_socket_address_get_address (ib);
325
326   return g_inet_address_equal (iaa, iab);
327 }
328
329 gchar *
330 __g_socket_address_to_string (GSocketAddress * addr)
331 {
332   GInetSocketAddress *ia;
333   gchar *ret, *tmp;
334
335   ia = G_INET_SOCKET_ADDRESS (addr);
336
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));
339   g_free (tmp);
340
341   return ret;
342 }