From a468f02d2aeabcf7e31d9e4cf576ab3474e8a1f7 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 27 Apr 2007 15:09:12 +0000 Subject: gst/rtpmanager/gstrtpsession.c: Move reconsideration code to the rtpsession object. Original commit message from CVS: * gst/rtpmanager/gstrtpsession.c: (rtcp_thread), (gst_rtp_session_send_rtcp), (gst_rtp_session_reconsider): Move reconsideration code to the rtpsession object. Simplify timout handling and add reconsideration. * gst/rtpmanager/rtpsession.c: (rtp_session_class_init), (rtp_session_init), (rtp_session_finalize), (on_bye_ssrc), (on_bye_timeout), (on_timeout), (rtp_session_set_callbacks), (obtain_source), (rtp_session_create_source), (update_arrival_stats), (rtp_session_process_rtp), (rtp_session_process_sr), (rtp_session_process_rr), (rtp_session_process_bye), (rtp_session_process_rtcp), (calculate_rtcp_interval), (rtp_session_send_bye), (rtp_session_next_timeout), (session_start_rtcp), (session_report_blocks), (session_cleanup), (session_sdes), (session_bye), (is_rtcp_time), (rtp_session_on_timeout): * gst/rtpmanager/rtpsession.h: Handle timeout of inactive sources and senders. Implement BYE scheduling. * gst/rtpmanager/rtpsource.c: (calculate_jitter), (rtp_source_process_sr), (rtp_source_get_last_sr), (rtp_source_get_last_rb): * gst/rtpmanager/rtpsource.h: Add members to check for timeouts. * gst/rtpmanager/rtpstats.c: (rtp_stats_init_defaults), (rtp_stats_calculate_rtcp_interval), (rtp_stats_add_rtcp_jitter), (rtp_stats_calculate_bye_interval): * gst/rtpmanager/rtpstats.h: Use RFC algorithm for calculating the reporting interval. --- gst/rtpmanager/rtpstats.c | 134 +++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 36 deletions(-) (limited to 'gst/rtpmanager/rtpstats.c') diff --git a/gst/rtpmanager/rtpstats.c b/gst/rtpmanager/rtpstats.c index 456ed15f..1e18f45e 100644 --- a/gst/rtpmanager/rtpstats.c +++ b/gst/rtpmanager/rtpstats.c @@ -33,63 +33,77 @@ rtp_stats_init_defaults (RTPSessionStats * stats) stats->receiver_fraction = RTP_STATS_RECEIVER_FRACTION; stats->rtcp_bandwidth = RTP_STATS_RTCP_BANDWIDTH; stats->min_interval = RTP_STATS_MIN_INTERVAL; + stats->bye_timeout = RTP_STATS_BYE_TIMEOUT; } /** * rtp_stats_calculate_rtcp_interval: * @stats: an #RTPSessionStats struct + * @sender: if we are a sender + * @first: if this is the first time * * Calculate the RTCP interval. The result of this function is the amount of - * time to wait (in seconds) before sender a new RTCP message. + * time to wait (in nanoseconds) before sending a new RTCP message. * * Returns: the RTCP interval. */ -gdouble -rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean sender) +GstClockTime +rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean we_send, + gboolean first) { - gdouble active, senders, receivers, sfraction; - gboolean avg_rtcp; + gdouble members, senders, n; + gdouble avg_rtcp_size, rtcp_bw; gdouble interval; + gdouble rtcp_min_time; - active = stats->active_sources; - /* Try to avoid division by zero */ - if (stats->active_sources == 0) - active += 1.0; - senders = (gdouble) stats->sender_sources; - receivers = (gdouble) (active - senders); - avg_rtcp = (gdouble) stats->avg_rtcp_packet_size; - - sfraction = senders / active; + /* Very first call at application start-up uses half the min + * delay for quicker notification while still allowing some time + * before reporting for randomization and to learn about other + * sources so the report interval will converge to the correct + * interval more quickly. + */ + rtcp_min_time = stats->min_interval; + if (first) + rtcp_min_time /= 2.0; - GST_DEBUG ("senders: %f, receivers %f, avg_rtcp %f, sfraction %f", - senders, receivers, avg_rtcp, sfraction); + /* Dedicate a fraction of the RTCP bandwidth to senders unless + * the number of senders is large enough that their share is + * more than that fraction. + */ + n = members = stats->active_sources; + senders = (gdouble) stats->sender_sources; + rtcp_bw = stats->rtcp_bandwidth; - if (senders > 0 && sfraction <= stats->sender_fraction) { - if (sender) { - interval = - (avg_rtcp * senders) / (stats->sender_fraction * - stats->rtcp_bandwidth); + if (senders <= members * RTP_STATS_SENDER_FRACTION) { + if (we_send) { + rtcp_bw *= RTP_STATS_SENDER_FRACTION; + n = senders; } else { - interval = - (avg_rtcp * receivers) / ((1.0 - - stats->sender_fraction) * stats->rtcp_bandwidth); + rtcp_bw *= RTP_STATS_RECEIVER_FRACTION; + n -= senders; } - } else { - interval = (avg_rtcp * active) / stats->rtcp_bandwidth; } - if (interval < stats->min_interval) - interval = stats->min_interval; - - if (!stats->sent_rtcp) - interval /= 2.0; + avg_rtcp_size = stats->avg_rtcp_packet_size / 16.0; + /* + * The effective number of sites times the average packet size is + * the total number of octets sent when each site sends a report. + * Dividing this by the effective bandwidth gives the time + * interval over which those packets must be sent in order to + * meet the bandwidth target, with a minimum enforced. In that + * time interval we send one report so this time is also our + * average time between reports. + */ + interval = avg_rtcp_size * n / rtcp_bw; + if (interval < rtcp_min_time) + interval = rtcp_min_time; - return interval; + return interval * GST_SECOND; } /** - * rtp_stats_calculate_rtcp_interval: + * rtp_stats_add_rtcp_jitter: * @stats: an #RTPSessionStats struct * @interval: an RTCP interval * @@ -98,14 +112,62 @@ rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean sender) * * Returns: the new RTCP interval. */ -gdouble -rtp_stats_add_rtcp_jitter (RTPSessionStats * stats, gdouble interval) +GstClockTime +rtp_stats_add_rtcp_jitter (RTPSessionStats * stats, GstClockTime interval) { + gdouble temp; + /* see RFC 3550 p 30 * To compensate for "unconditional reconsideration" converging to a * value below the intended average. */ #define COMPENSATION (2.71828 - 1.5); - return (interval * g_random_double_range (0.5, 1.5)) / COMPENSATION; + temp = (interval * g_random_double_range (0.5, 1.5)) / COMPENSATION; + + return (GstClockTime) temp; +} + + +/** + * rtp_stats_calculate_bye_interval: + * @stats: an #RTPSessionStats struct + * + * Calculate the BYE interval. The result of this function is the amount of + * time to wait (in nanoseconds) before sending a BYE message. + * + * Returns: the BYE interval. + */ +GstClockTime +rtp_stats_calculate_bye_interval (RTPSessionStats * stats) +{ + gdouble members; + gdouble avg_rtcp_size, rtcp_bw; + gdouble interval; + gdouble rtcp_min_time; + + rtcp_min_time = (stats->min_interval) / 2.0; + + /* Dedicate a fraction of the RTCP bandwidth to senders unless + * the number of senders is large enough that their share is + * more than that fraction. + */ + members = stats->bye_members; + rtcp_bw = stats->rtcp_bandwidth * RTP_STATS_RECEIVER_FRACTION; + + avg_rtcp_size = stats->avg_rtcp_packet_size / 16.0; + /* + * The effective number of sites times the average packet size is + * the total number of octets sent when each site sends a report. + * Dividing this by the effective bandwidth gives the time + * interval over which those packets must be sent in order to + * meet the bandwidth target, with a minimum enforced. In that + * time interval we send one report so this time is also our + * average time between reports. + */ + interval = avg_rtcp_size * members / rtcp_bw; + if (interval < rtcp_min_time) + interval = rtcp_min_time; + + return interval * GST_SECOND; } -- cgit v1.2.1